Skip to content

Commit 24d166c

Browse files
committed
Add a runMode method that provides syntax highlighting for static html content.
1 parent 3737b4a commit 24d166c

File tree

6 files changed

+105
-30
lines changed

6 files changed

+105
-30
lines changed

package-lock.json

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@openwebwork/pg-codemirror-editor",
3-
"version": "0.0.1-beta.25",
3+
"version": "0.0.1-beta.26",
44
"description": "PG CodeMirror Editor",
55
"author": "The WeBWorK Project",
66
"license": "MIT",
@@ -41,6 +41,7 @@
4141
"codemirror": "^6.0.1",
4242
"codemirror-lang-mt": "^0.0.2-beta.3",
4343
"codemirror-lang-perl": "^0.1.5-beta.4",
44+
"style-mod": "^4.1.2",
4445
"thememirror": "^2.0.1"
4546
},
4647
"devDependencies": {

public/static-view.html

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!doctype html>
2+
<html lang="en-US">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>PG CodeMirror Static View Playground</title>
7+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
8+
<link href="style.css" rel="stylesheet">
9+
<script src="pg-codemirror-editor.js" defer></script>
10+
<script src="static-view.js" defer></script>
11+
</head>
12+
13+
<body>
14+
<div class="container my-3">
15+
<h1>PG CodeMirror Static View Playground</h1>
16+
<div class="input-group mb-3">
17+
<button class="btn btn-primary" id="load-file" type="button">Load File</button>
18+
<input type="file" name="problem-file" class="form-control">
19+
</div>
20+
<input type="hidden" name="view-source">
21+
<div><pre class="pg-codemirror-view m-0 h-100 p-3 border border-secondary overflow-scroll"></pre></div>
22+
</div>
23+
</body>
24+
</html>

public/static-view.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* global PGCodeMirrorEditor */
2+
3+
const codeMirrorElt = document.querySelector('.pg-codemirror-view');
4+
5+
if (codeMirrorElt instanceof HTMLElement) {
6+
const sourceInput = document.getElementsByName('view-source')[0];
7+
PGCodeMirrorEditor.runMode(sourceInput.value, codeMirrorElt);
8+
9+
document.getElementById('load-file')?.addEventListener('click', () => {
10+
const file = document.getElementsByName('problem-file')[0]?.files?.[0];
11+
if (file) {
12+
const reader = new FileReader();
13+
reader.readAsText(file);
14+
reader.addEventListener('load', () => {
15+
sourceInput.value = reader.result;
16+
PGCodeMirrorEditor.runMode(sourceInput.value, codeMirrorElt);
17+
});
18+
}
19+
});
20+
}

src/light-theme.ts

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
import { tags as t } from '@lezer/highlight';
22
import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
33

4-
export const lightTheme = syntaxHighlighting(
5-
HighlightStyle.define([
6-
{ tag: t.meta, color: '#404740' },
7-
{ tag: t.link, textDecoration: 'underline' },
8-
{ tag: t.heading, textDecoration: 'underline', fontWeight: 'bold' },
9-
{ tag: t.emphasis, fontStyle: 'italic' },
10-
{ tag: t.strong, fontWeight: 'bold' },
11-
{ tag: t.strikethrough, textDecoration: 'line-through' },
12-
{ tag: t.keyword, color: '#708' },
13-
{ tag: [t.atom, t.bool, t.url, t.contentSeparator, t.labelName], color: '#219' },
14-
{ tag: [t.literal, t.inserted], color: '#164' },
15-
{ tag: [t.string, t.deleted], color: '#a11' },
16-
{ tag: [t.regexp, t.escape, t.special(t.string)], color: '#e40' },
17-
{ tag: t.definition(t.variableName), color: '#00f' },
18-
{ tag: t.variableName, color: '#30a' },
19-
{ tag: t.local(t.variableName), color: '#30a' },
20-
{ tag: [t.typeName, t.namespace], color: '#085' },
21-
{ tag: t.className, color: '#167' },
22-
{ tag: [t.special(t.variableName), t.macroName], color: '#256' },
23-
{ tag: t.definition(t.propertyName), color: '#00c' },
24-
{ tag: [t.processingInstruction, t.inserted], color: '#05a' },
25-
{ tag: t.comment, color: '#940' },
26-
{ tag: t.invalid, color: '#f00' }
27-
]),
28-
{ fallback: true }
29-
);
4+
export const lightHighlightStyle = HighlightStyle.define([
5+
{ tag: t.meta, color: '#404740' },
6+
{ tag: t.link, textDecoration: 'underline' },
7+
{ tag: t.heading, textDecoration: 'underline', fontWeight: 'bold' },
8+
{ tag: t.emphasis, fontStyle: 'italic' },
9+
{ tag: t.strong, fontWeight: 'bold' },
10+
{ tag: t.strikethrough, textDecoration: 'line-through' },
11+
{ tag: t.keyword, color: '#708' },
12+
{ tag: [t.atom, t.bool, t.url, t.contentSeparator, t.labelName], color: '#219' },
13+
{ tag: [t.literal, t.inserted], color: '#164' },
14+
{ tag: [t.string, t.deleted], color: '#a11' },
15+
{ tag: [t.regexp, t.escape, t.special(t.string)], color: '#e40' },
16+
{ tag: t.definition(t.variableName), color: '#00f' },
17+
{ tag: t.variableName, color: '#30a' },
18+
{ tag: t.local(t.variableName), color: '#30a' },
19+
{ tag: [t.typeName, t.namespace], color: '#085' },
20+
{ tag: t.className, color: '#167' },
21+
{ tag: [t.special(t.variableName), t.macroName], color: '#256' },
22+
{ tag: t.definition(t.propertyName), color: '#00c' },
23+
{ tag: [t.processingInstruction, t.inserted], color: '#05a' },
24+
{ tag: t.comment, color: '#940' },
25+
{ tag: t.invalid, color: '#f00' }
26+
]);
27+
28+
export const lightTheme = syntaxHighlighting(lightHighlightStyle, { fallback: true });

src/pg-codemirror-editor.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ import { bracketMatching, foldGutter, foldKeymap, indentOnInput, indentUnit, syn
2828
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
2929
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
3030
import type { SyntaxNode } from '@lezer/common';
31-
import { lightTheme } from 'src/light-theme';
31+
import { highlightCode } from '@lezer/highlight';
32+
import { StyleModule } from 'style-mod';
33+
import { lightHighlightStyle, lightTheme } from 'src/light-theme';
3234
import 'src/pg-codemirror-editor.scss';
3335

3436
export interface InitializationOptions {
@@ -385,3 +387,31 @@ export class View {
385387
});
386388
}
387389
}
390+
391+
export const runMode = async (source: string, container: HTMLElement) => {
392+
const pgLanguage = (await import(/* webpackChunkName: 'pg' */ '@openwebwork/codemirror-lang-pg')).pgLanguage;
393+
394+
if (lightHighlightStyle.module) StyleModule.mount(document, lightHighlightStyle.module);
395+
396+
while (container.firstChild) container.firstChild.remove();
397+
398+
highlightCode(
399+
source,
400+
pgLanguage.parser.parse(source),
401+
lightHighlightStyle,
402+
(text: string, classes: string) => {
403+
let node: Text | HTMLElement = document.createTextNode(text);
404+
if (classes) {
405+
const span = document.createElement('span');
406+
span.appendChild(node);
407+
span.className = classes;
408+
container.appendChild(span);
409+
node = span;
410+
}
411+
container.appendChild(node);
412+
},
413+
() => {
414+
container.appendChild(document.createTextNode('\n'));
415+
}
416+
);
417+
};

0 commit comments

Comments
 (0)