9
0
mirror of https://github.com/donlon/cloudflare-error-page.git synced 2025-12-27 10:49:16 +00:00

editor/web: support syntax highlighting on save as dialog

This commit is contained in:
Anthony Donlon
2025-12-23 01:28:17 +08:00
parent fb52f6d523
commit 8be87415fe
5 changed files with 36 additions and 14 deletions

View File

@@ -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
</button>
</div>
<textarea id="saveAsDialogCode" class="form-control save-as-dialog__code" spellcheck="false"
readonly></textarea>
<pre id="saveAsDialogCode" class="border px-2 py-1 save-as-dialog__code"></pre>
</div>
</div>
</div>

View File

@@ -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"
}
}

View File

@@ -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);

View File

@@ -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();

View File

@@ -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"