diff --git a/editor/web/index.html b/editor/web/index.html index a9e5a8e..93415a1 100644 --- a/editor/web/index.html +++ b/editor/web/index.html @@ -170,8 +170,10 @@ width: 100%; height: 100%; min-height: 700px !important; + max-height: 1200px !important; font-family: monospace; font-size: 0.8em !important; + overflow: auto; } .save-as-dialog__buttons { @@ -545,8 +547,7 @@ Save - +
diff --git a/editor/web/package.json b/editor/web/package.json index ccf0d43..93baba5 100644 --- a/editor/web/package.json +++ b/editor/web/package.json @@ -14,6 +14,7 @@ "@types/ejs": "^3.1.5", "@types/html-minifier-terser": "^7.0.2", "@types/node": "^24.10.2", + "@types/prismjs": "^1.26.5", "html-minifier-terser": "^7.2.0", "prettier": "3.7.4", "typescript": "^5.9.3", @@ -23,6 +24,7 @@ "dependencies": { "bootstrap": "^5.3.8", "cloudflare-error-page": "../../javascript", - "ejs": "^3.1.10" + "ejs": "^3.1.10", + "prismjs": "^1.30.0" } } diff --git a/editor/web/src/codegen/index.ts b/editor/web/src/codegen/index.ts index 0b0447f..b871936 100644 --- a/editor/web/src/codegen/index.ts +++ b/editor/web/src/codegen/index.ts @@ -6,14 +6,17 @@ import pythonTemplate from './python.ejs?raw'; interface CodeGen { name: string; + language: string; generate(params: any): string; } class EjsCodeGen implements CodeGen { name: string; + language: string; private template: ejs.TemplateFunction; - constructor(name: string, templateContent: any) { + constructor(name: string, language: string, templateContent: any) { this.name = name; + this.language = language; this.template = ejs.compile(templateContent); } generate(params: any): string { @@ -21,6 +24,6 @@ class EjsCodeGen implements CodeGen { } } -export const jsCodeGen = new EjsCodeGen('NodeJS Example', jsTemplate); -export const jsonCodeGen = new EjsCodeGen('JSON', jsonTemplate); -export const pythonCodeGen = new EjsCodeGen('Python Example', pythonTemplate); +export const jsCodeGen = new EjsCodeGen('NodeJS Example', 'javascript', jsTemplate); +export const jsonCodeGen = new EjsCodeGen('JSON', 'json', jsonTemplate); +export const pythonCodeGen = new EjsCodeGen('Python Example', 'python', pythonTemplate); diff --git a/editor/web/src/index.js b/editor/web/src/index.js index 5948194..450e33c 100644 --- a/editor/web/src/index.js +++ b/editor/web/src/index.js @@ -5,11 +5,16 @@ - inputs call render() on change - "Open in new tab" opens the rendered HTML in a new window using a blob URL */ -import { render as render_cf_error_page } from 'cloudflare-error-page'; import 'bootstrap/js/src/modal.js'; import Popover from 'bootstrap/js/src/popover.js'; +import Prism from 'prismjs'; +import 'prismjs/components/prism-json.js'; +import 'prismjs/components/prism-python.js'; +import { render as render_cf_error_page } from 'cloudflare-error-page'; + import 'bootstrap/dist/css/bootstrap.min.css'; +import 'prismjs/themes/prism.css'; import { jsCodeGen, jsonCodeGen, pythonCodeGen } from './codegen'; @@ -426,16 +431,20 @@ function updateSaveAsDialog(e) { } const params = { ...lastCfg }; delete params.time; + let language; if (codegen) { saveAsContent = codegen.generate(params); + language = codegen.language; } else if (saveAsType == 'static') { render(); // rerender the page saveAsContent = lastRenderedHtml; + language = 'html'; } else { throw new Error('unexpected saveAsType=' + saveAsType); } - $('saveAsDialogCode').value = saveAsContent; - $('saveAsDialogCode').scrollTop = 0; + const html = Prism.highlight(saveAsContent, Prism.languages[language], language); + + $('saveAsDialogCode').innerHTML = html; document.querySelectorAll('#saveAsDialogTypes button').forEach((element) => { const isCurrent = element.dataset.type == saveAsType; @@ -456,10 +465,7 @@ document.querySelectorAll('#saveAsDialogTypes button').forEach((element) => { const saveAsDialogCopyPopover = new Popover($('saveAsDialogCopyBtn')); $('saveAsDialogCopyBtn').addEventListener('click', (e) => { - const field = $('saveAsDialogCode'); - field.select(); - // field.setSelectionRange(0, field.value.length); - navigator.clipboard.writeText(field.value).then(() => { + navigator.clipboard.writeText(saveAsContent).then(() => { saveAsDialogCopyPopover.show(); setTimeout(() => { saveAsDialogCopyPopover.hide(); diff --git a/editor/web/yarn.lock b/editor/web/yarn.lock index bf45c62..61afdd9 100644 --- a/editor/web/yarn.lock +++ b/editor/web/yarn.lock @@ -310,6 +310,11 @@ dependencies: undici-types "~7.16.0" +"@types/prismjs@^1.26.5": + version "1.26.5" + resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.5.tgz#72499abbb4c4ec9982446509d2f14fb8483869d6" + integrity sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ== + acorn@^8.15.0: version "8.15.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" @@ -618,6 +623,11 @@ prettier@3.7.4: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.7.4.tgz#d2f8335d4b1cec47e1c8098645411b0c9dff9c0f" integrity sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA== +prismjs@^1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.30.0.tgz#d9709969d9d4e16403f6f348c63553b19f0975a9" + integrity sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw== + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"