diff --git a/global.css b/global.css
index 7b7188b..6448ec2 100644
--- a/global.css
+++ b/global.css
@@ -11,8 +11,6 @@
body {
font-family: 'Open Sans', 'Helvetica', sans-serif;
- max-width: 800px;
- margin: 0 auto;
padding: 5px;
}
diff --git a/markdown-panel/index.html b/markdown-panel/index.html
new file mode 100644
index 0000000..a4f6119
--- /dev/null
+++ b/markdown-panel/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+ Markdown Panel
+
+
+
+
+
+
+
+
diff --git a/markdown-panel/markdown-panel.ts b/markdown-panel/markdown-panel.ts
new file mode 100644
index 0000000..8fbf7e7
--- /dev/null
+++ b/markdown-panel/markdown-panel.ts
@@ -0,0 +1,75 @@
+import { LitElement, html, css } from 'lit-element'
+import { customElement, state } from 'lit/decorators.js'
+import { unsafeHTML } from 'lit/directives/unsafe-html.js'
+import { marked } from 'marked'
+
+@customElement('markdown-panel')
+export class MarkdownPanel extends LitElement {
+ @state({ type: String })
+ mode: string = 'view'
+
+ @state({ type: String })
+ markdown = ''
+
+ static styles = css`
+ p {
+ margin-top: 0;
+ margin-bottom: 16px;
+ }
+
+ textarea {
+ width: 100%;
+ height: 50vh;
+ }
+
+ button {
+ padding: 10px 20px;
+ }
+
+ h1,
+ h2,
+ h3,
+ h4 {
+ font-family: 'Raleway', sans-serif;
+ margin-top: 0;
+ }
+ `
+
+ constructor() {
+ super()
+ grist.ready({
+ onEditOptions: () => {
+ this.mode = 'edit'
+ },
+ })
+ grist.onOptions((options, interaction) => {
+ if (options.markdown) {
+ this.markdown = options.markdown
+ } else {
+ this.mode = 'edit'
+ }
+ })
+ }
+
+ saveText() {
+ const textarea = this.shadowRoot!.querySelector('textarea')!
+ grist.setOption('markdown', textarea.value)
+ this.markdown = textarea.value
+ this.mode = 'view'
+ }
+
+ protected render() {
+ const rendered_markdown = unsafeHTML(marked(this.markdown) as string)
+ if (this.mode === 'edit') {
+ return html`
+
+
+
+
+
+ `
+ } else {
+ return html`${rendered_markdown}
`
+ }
+ }
+}
diff --git a/package-lock.json b/package-lock.json
index 19be164..2ec545e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,8 @@
"version": "0.0.4",
"dependencies": {
"@vitejs/plugin-vue": "^5.0.4",
+ "lit": "^3.1.3",
+ "marked": "^12.0.2",
"moment": "^2.30.1",
"qrcode": "^1.5.3",
"vue": "^3.4.27"
@@ -380,6 +382,19 @@
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
+ "node_modules/@lit-labs/ssr-dom-shim": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz",
+ "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g=="
+ },
+ "node_modules/@lit/reactive-element": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
+ "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0"
+ }
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
@@ -584,6 +599,11 @@
"optional": true,
"peer": true
},
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
+ },
"node_modules/@vitejs/plugin-vue": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
@@ -851,6 +871,34 @@
"node": ">=8"
}
},
+ "node_modules/lit": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.3.tgz",
+ "integrity": "sha512-l4slfspEsnCcHVRTvaP7YnkTZEZggNFywLEIhQaGhYDczG+tu/vlgm/KaWIEjIp+ZyV20r2JnZctMb8LeLCG7Q==",
+ "dependencies": {
+ "@lit/reactive-element": "^2.0.4",
+ "lit-element": "^4.0.4",
+ "lit-html": "^3.1.2"
+ }
+ },
+ "node_modules/lit-element": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.5.tgz",
+ "integrity": "sha512-iTWskWZEtn9SyEf4aBG6rKT8GABZMrTWop1+jopsEOgEcugcXJGKuX5bEbkq9qfzY+XB4MAgCaSPwnNpdsNQ3Q==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0",
+ "@lit/reactive-element": "^2.0.4",
+ "lit-html": "^3.1.2"
+ }
+ },
+ "node_modules/lit-html": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.3.tgz",
+ "integrity": "sha512-FwIbqDD8O/8lM4vUZ4KvQZjPPNx7V1VhT7vmRB8RBAO0AU6wuTVdoXiu2CivVjEGdugvcbPNBLtPE1y0ifplHA==",
+ "dependencies": {
+ "@types/trusted-types": "^2.0.2"
+ }
+ },
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -870,6 +918,17 @@
"@jridgewell/sourcemap-codec": "^1.4.15"
}
},
+ "node_modules/marked": {
+ "version": "12.0.2",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz",
+ "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/moment": {
"version": "2.30.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
diff --git a/package.json b/package.json
index 469531b..1faf4d5 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,8 @@
},
"dependencies": {
"@vitejs/plugin-vue": "^5.0.4",
+ "lit": "^3.1.3",
+ "marked": "^12.0.2",
"moment": "^2.30.1",
"qrcode": "^1.5.3",
"vue": "^3.4.27"
diff --git a/tent-sheet/tent-sheet.css b/tent-sheet/tent-sheet.css
index a9d33aa..a669548 100644
--- a/tent-sheet/tent-sheet.css
+++ b/tent-sheet/tent-sheet.css
@@ -4,6 +4,8 @@ html {
}
body {
+ max-width: 800px;
+ margin: 0 auto;
border: 1px solid #999;
border-radius: 5px;
padding-top: 0px;
diff --git a/tsconfig.json b/tsconfig.json
index a42c85c..deac7ab 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,10 +1,9 @@
{
"compilerOptions": {
- "target": "ES2020",
+ "target": "ES2022",
"types": ["vite/client", "node"],
- "useDefineForClassFields": true,
"module": "esnext",
- "lib": ["ES2020", "DOM", "DOM.Iterable", "WebWorker"],
+ "lib": ["ES2022", "DOM", "DOM.Iterable", "WebWorker"],
"skipLibCheck": true,
/* Bundler mode */
@@ -18,7 +17,10 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
- "noFallthroughCasesInSwitch": true
+ "noFallthroughCasesInSwitch": true,
+
+ "experimentalDecorators": true,
+ "useDefineForClassFields": false,
},
"ts-node": {
"esm": true
diff --git a/vite.config.ts b/vite.config.ts
index 2dd964b..94f02e9 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -7,6 +7,7 @@ export default defineConfig({
input: {
'index': resolve(__dirname, 'index.html'),
'tent-sheet': resolve(__dirname, 'tent-sheet/index.html'),
+ 'markdown-panel': resolve(__dirname, 'markdown-panel/index.html'),
},
},
},