Skip to content

Commit 7942e6e

Browse files
committed
Add JSON-LD keyword syntax highlighting.
1 parent 2bde7c7 commit 7942e6e

File tree

2 files changed

+122
-2
lines changed

2 files changed

+122
-2
lines changed

playground/next/editor.bundle.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39516,6 +39516,64 @@ ${O$2.repeat(r.depth)}}`:r.close="}";break}case f$4.TAG:e+=String(i),e+=a(f$4.PO
3951639516
autocomplete: completeJSONLDTerms
3951739517
});
3951839518

39519+
// Create a decoration that applies a CSS class for JSON‑LD property names
39520+
const jsonLdPropertyDecoration = Decoration.mark({ class: 'cm-jsonld-property' });
39521+
39522+
const jsonLdKeywords = new Set(
39523+
[].concat(...Object.values(jsonLdAtTerms)).map((term) => term.label));
39524+
39525+
/**
39526+
* A view plugin that scans the document for PropertyName nodes and, if their
39527+
* content (without quotes) is a JSON‑LD keyword, adds a decoration to style it.
39528+
*/
39529+
const jsonLdKeywordHighlighter = ViewPlugin.fromClass(class {
39530+
constructor(view) {
39531+
this.decorations = this.buildDecorations(view);
39532+
}
39533+
39534+
update(update) {
39535+
if (update.docChanged || update.viewportChanged) {
39536+
this.decorations = this.buildDecorations(update.view);
39537+
}
39538+
}
39539+
39540+
buildDecorations(view) {
39541+
let builder = new RangeSetBuilder();
39542+
let tree = syntaxTree(view.state);
39543+
// Only inspect nodes in the current viewport
39544+
tree.iterate({
39545+
from: view.viewport.from,
39546+
to: view.viewport.to,
39547+
enter: (node) => {
39548+
// Look for property names (as defined by lang-json)
39549+
if (node.name === "PropertyName" || node.name === "String") {
39550+
let token = view.state.doc.sliceString(node.from, node.to);
39551+
// Remove the surrounding quotes, if any
39552+
if (token.startsWith('"') && token.endsWith('"')) {
39553+
token = token.slice(1, -1);
39554+
}
39555+
if (jsonLdKeywords.has(token)) {
39556+
builder.add(node.from, node.to, jsonLdPropertyDecoration);
39557+
}
39558+
}
39559+
}
39560+
});
39561+
return builder.finish();
39562+
}
39563+
39564+
destroy() {}
39565+
}, {
39566+
decorations: v => v.decorations
39567+
});
39568+
39569+
// A base theme for our decoration
39570+
const jsonLdHighlightTheme = EditorView.baseTheme({
39571+
'.cm-jsonld-property': {
39572+
color: '#333',
39573+
fontWeight: 'bold'
39574+
}
39575+
});
39576+
3951939577
function initEditor(id, content, varName) {
3952039578
return new EditorView({
3952139579
parent: document.getElementById(id),
@@ -39524,6 +39582,8 @@ ${O$2.repeat(r.depth)}}`:r.close="}";break}case f$4.TAG:e+=String(i),e+=a(f$4.PO
3952439582
basicSetup,
3952539583
keymap.of([indentWithTab]),
3952639584
jsonLanguage,
39585+
jsonLdKeywordHighlighter,
39586+
jsonLdHighlightTheme,
3952739587
linter(jsonParseLinter()),
3952839588
jsonLdCompletions,
3952939589
editorListener.call(this, varName)

playground/next/editor.mjs

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
import {EditorView, basicSetup} from 'codemirror';
44
import {createApp} from "petite-vue";
5-
import {Compartment, EditorState} from '@codemirror/state'
5+
import {Compartment, EditorState, RangeSetBuilder} from '@codemirror/state'
66
import {indentWithTab} from '@codemirror/commands';
77
import {json, jsonLanguage, jsonParseLinter} from "@codemirror/lang-json";
88
import {syntaxTree, StreamLanguage} from '@codemirror/language';
99
import {ntriples} from '@codemirror/legacy-modes/mode/ntriples';
10-
import {keymap} from '@codemirror/view';
10+
import {Decoration, keymap, ViewPlugin} from '@codemirror/view';
1111
import {linter} from '@codemirror/lint';
1212
import YAML from 'yaml';
1313
import {yaml} from '@codemirror/lang-yaml';
@@ -190,6 +190,64 @@ const jsonLdCompletions = jsonLanguage.data.of({
190190
autocomplete: completeJSONLDTerms
191191
});
192192

193+
// Create a decoration that applies a CSS class for JSON‑LD property names
194+
const jsonLdPropertyDecoration = Decoration.mark({ class: 'cm-jsonld-property' });
195+
196+
const jsonLdKeywords = new Set(
197+
[].concat(...Object.values(jsonLdAtTerms)).map((term) => term.label));
198+
199+
/**
200+
* A view plugin that scans the document for PropertyName nodes and, if their
201+
* content (without quotes) is a JSON‑LD keyword, adds a decoration to style it.
202+
*/
203+
const jsonLdKeywordHighlighter = ViewPlugin.fromClass(class {
204+
constructor(view) {
205+
this.decorations = this.buildDecorations(view);
206+
}
207+
208+
update(update) {
209+
if (update.docChanged || update.viewportChanged) {
210+
this.decorations = this.buildDecorations(update.view);
211+
}
212+
}
213+
214+
buildDecorations(view) {
215+
let builder = new RangeSetBuilder();
216+
let tree = syntaxTree(view.state);
217+
// Only inspect nodes in the current viewport
218+
tree.iterate({
219+
from: view.viewport.from,
220+
to: view.viewport.to,
221+
enter: (node) => {
222+
// Look for property names (as defined by lang-json)
223+
if (node.name === "PropertyName" || node.name === "String") {
224+
let token = view.state.doc.sliceString(node.from, node.to);
225+
// Remove the surrounding quotes, if any
226+
if (token.startsWith('"') && token.endsWith('"')) {
227+
token = token.slice(1, -1);
228+
}
229+
if (jsonLdKeywords.has(token)) {
230+
builder.add(node.from, node.to, jsonLdPropertyDecoration);
231+
}
232+
}
233+
}
234+
});
235+
return builder.finish();
236+
}
237+
238+
destroy() {}
239+
}, {
240+
decorations: v => v.decorations
241+
});
242+
243+
// A base theme for our decoration
244+
const jsonLdHighlightTheme = EditorView.baseTheme({
245+
'.cm-jsonld-property': {
246+
color: '#333',
247+
fontWeight: 'bold'
248+
}
249+
});
250+
193251
function initEditor(id, content, varName) {
194252
return new EditorView({
195253
parent: document.getElementById(id),
@@ -198,6 +256,8 @@ function initEditor(id, content, varName) {
198256
basicSetup,
199257
keymap.of([indentWithTab]),
200258
jsonLanguage,
259+
jsonLdKeywordHighlighter,
260+
jsonLdHighlightTheme,
201261
linter(jsonParseLinter()),
202262
jsonLdCompletions,
203263
editorListener.call(this, varName)

0 commit comments

Comments
 (0)