Skip to content

Commit 694df74

Browse files
authored
improve bundling, demo and hover rendering (#87)
- finish the reorg @imolorhe started - consistent file names, move features to features directory - switch to `nodeResolution: bundler` for esm, get rid of .js imports but still something newer than `Node`. keep `nodeResolution: Node` for cjs - fix some issues with hover rendering, add hover rendering of `$ref` pointers! (see image) - demo improvements - persist the edited values, use shema cache, remember the chosen schema, and change the headers based on the chosen schema (going to improve this further) ![image](https://github.com/acao/codemirror-json-schema/assets/1368727/1f134415-17f4-4de5-8291-cac9a40b1426)
1 parent 5a22761 commit 694df74

40 files changed

+1693
-356
lines changed

README.md

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ Codemirror 6 extensions that provide full [JSON Schema](https://json-schema.org/
88

99
## Features
1010

11-
This is now a full-featured library for both json4 (aka json) and json5 using extensions, so they should compatible with any frontend framework and/or integration library
11+
This is now a full-featured library for json schema for `json`, `json5` and `yaml` as cm6 extensions!
1212

13-
- ✅ validation messages
14-
- ✅ autocompletion with insert text
13+
-lint validation messages from json schema
14+
- ✅ autocompletion with insert text from json schema
1515
- ✅ hover tooltips
1616
- ✅ dynamic, per-editor-instance schemas using codemirror `StateField` and linting refresh
17+
- ✅ markdown rendering for `schema.description` and custom `formatHover` and `formatError` configuration
1718

1819
## Resources
1920

@@ -29,6 +30,7 @@ Based on whether you want to support json4, json5 or both, you will need to inst
2930

3031
### Breaking Changes:
3132

33+
- 0.7.0 - this version introduces markdown rendering in place of returning html strings, so any usage of `formatHover` and/or `formatError` configuration will be passed to `markdown-it` which doesn't handle html by default.
3234
- 0.5.0 - this breaking change only impacts those following the "custom usage" approach, it _does not_ effect users using the high level, "bundled" `jsonSchema()` or `json5Schema()` modes. See the custom usages below to learn how to use the new `stateExtensions` and `handleRefresh` exports.
3335

3436
### json4
@@ -281,11 +283,3 @@ const state = EditorState.create({
281283
`monaco-json` and `monaco-yaml` both provide json schema features for json, cson and yaml, and we want the nascent codemirror 6 to have them as well!
282284
283285
Also, json5 is slowly growing in usage, and it needs full language support for the browser!
284-
285-
## Our Goals
286-
287-
- working GeoJSON spec linter & completion
288-
- working variables json mode for `cm6-graphql`, ala `monaco-graphql`
289-
- json5 support for `graphiql` as a plugin!
290-
- perhaps use @lezer to make a json5 language service for monaco-editor + json5?
291-
- json5 + json4 json schema features for all!

dev/index.html

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,21 +103,30 @@ <h1><code>codemirror-json-schema</code> demo</h1>
103103
>
104104
docker-compose.yml
105105
</option>
106+
<option value="github-workflow.json">github workflow</option>
107+
106108
<option value="github-action.json">github action</option>
107109
<option value="eslintrc.json">eslintrc.json</option>
110+
<option value="chart.json">helm chart</option>
108111
</select>
109112
</div>
110113
<div class="grid-row">
111114
<div>
112-
<h2><code>package.json</code> demo</h2>
113-
<div id="editor"></div>
115+
<h2>
116+
<code><span>package</span>.json</code> demo
117+
</h2>
118+
<div id="editor-json"></div>
114119
</div>
115120
<div>
116-
<h2><code>package.json5</code> demo</h2>
121+
<h2>
122+
<code><span>package</span>.json5</code> demo
123+
</h2>
117124
<div id="editor-json5"></div>
118125
</div>
119126
<div>
120-
<h2><code>package.yaml</code> demo</h2>
127+
<h2>
128+
<code><span>package</span>.yaml</code> demo
129+
</h2>
121130
<div id="editor-yaml"></div>
122131
</div>
123132
</div>

dev/index.ts

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
drawSelection,
77
keymap,
88
highlightActiveLineGutter,
9+
ViewUpdate,
910
} from "@codemirror/view";
1011
// import { basicSetup } from "@codemirror/basic-setup";
1112
import { lintGutter } from "@codemirror/lint";
@@ -41,6 +42,7 @@ import { json5Schema } from "../src/json5";
4142
import { yamlSchema } from "../src/yaml";
4243

4344
const schema = packageJsonSchema as JSONSchema7;
45+
const ls = localStorage;
4446

4547
/**
4648
* none of these are required for json4 or 5
@@ -74,26 +76,44 @@ const commonExtensions = [
7476
syntaxHighlighting(oneDarkHighlightStyle),
7577
];
7678

79+
const persistEditorStateOnChange = (key: string) => {
80+
return EditorView.updateListener.of(
81+
debounce((v: ViewUpdate) => {
82+
if (v.docChanged) {
83+
ls.setItem(key, v.state.doc.toString());
84+
}
85+
}, 300)
86+
);
87+
};
88+
7789
/**
7890
* json4!
7991
*/
8092

8193
const state = EditorState.create({
82-
doc: jsonText,
83-
extensions: [commonExtensions, jsonSchema(schema)],
94+
doc: ls.getItem("json4") ?? jsonText,
95+
extensions: [
96+
commonExtensions,
97+
jsonSchema(schema),
98+
persistEditorStateOnChange("json4"),
99+
],
84100
});
85101

86102
const editor1 = new EditorView({
87103
state,
88-
parent: document.querySelector("#editor")!,
104+
parent: document.querySelector("#editor-json")!,
89105
});
90106

91107
/**
92108
* json5!
93109
*/
94110
const json5State = EditorState.create({
95-
doc: json5Text,
96-
extensions: [commonExtensions, json5Schema(schema)],
111+
doc: ls.getItem("json5") ?? json5Text,
112+
extensions: [
113+
commonExtensions,
114+
json5Schema(schema),
115+
persistEditorStateOnChange("json5"),
116+
],
97117
});
98118

99119
const editor2 = new EditorView({
@@ -105,8 +125,12 @@ const editor2 = new EditorView({
105125
* yaml!
106126
*/
107127
const yamlState = EditorState.create({
108-
doc: yamlText,
109-
extensions: [commonExtensions, yamlSchema(schema)],
128+
doc: ls.getItem("yaml") ?? yamlText,
129+
extensions: [
130+
commonExtensions,
131+
yamlSchema(schema),
132+
persistEditorStateOnChange("yaml"),
133+
],
110134
});
111135

112136
const editor3 = new EditorView({
@@ -120,21 +144,56 @@ const handleSchemaChange = (newSchema: JSONSchema7) => {
120144
updateSchema(editor3, newSchema);
121145
};
122146

123-
// new EditorState.fi(editor1, editor2);
124-
// Hot Module Replacement
125-
// if (module.hot) {
126-
// module.hot.accept();
127-
// }
147+
const schemaCache = new Map<string, JSONSchema7>([["package.json", schema]]);
148+
149+
const getSchema = async (val: string) => {
150+
const cachedSchema = schemaCache.get(val);
151+
if (cachedSchema) {
152+
handleSchemaChange(cachedSchema);
153+
return;
154+
}
155+
156+
const data = await (
157+
await fetch(`https://json.schemastore.org/${val}`)
158+
).json();
159+
schemaCache.set(val, data);
160+
handleSchemaChange(data);
161+
};
128162

129163
const schemaSelect = document.getElementById("schema-selection");
164+
const schemaValue = localStorage.getItem("selectedSchema")!;
165+
166+
const setFileName = (value) => {
167+
document.querySelectorAll("h2 code span").forEach((el) => {
168+
el.textContent = value;
169+
});
170+
};
171+
172+
(async () => {
173+
if (schemaValue) {
174+
schemaSelect!.value = schemaValue;
175+
await getSchema(schemaValue);
176+
document.querySelectorAll("h2 code span").forEach((el) => {
177+
el.textContent = schemaValue.split(".")[0];
178+
});
179+
setFileName(schemaValue.split(".")[0]);
180+
}
181+
})();
130182

131183
schemaSelect!.onchange = async (e) => {
132184
const val = e.target!.value!;
133185
if (!val) {
134186
return;
135187
}
136-
const data = await (
137-
await fetch(`https://json.schemastore.org/${val}`)
138-
).json();
139-
handleSchemaChange(data);
188+
ls.setItem("selectedSchema", val);
189+
await getSchema(val);
190+
setFileName(val.split(".")[0]);
140191
};
192+
193+
function debounce(fn: Function, ms: number) {
194+
let timeout: number;
195+
return function (this: any, ...args: any[]) {
196+
clearTimeout(timeout);
197+
timeout = window.setTimeout(() => fn.apply(this, args), ms);
198+
};
199+
}

package.json

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,19 @@
5858
"homepage": "https://codemirror-json-schema.netlify.app/",
5959
"dependencies": {
6060
"@changesets/changelog-github": "^0.4.8",
61-
"@codemirror/lang-yaml": "^6.0.0",
6261
"@sagold/json-pointer": "^5.1.1",
62+
"@shikijs/markdown-it": "^1.1.7",
6363
"@types/json-schema": "^7.0.12",
6464
"@types/node": "^20.4.2",
6565
"json-schema": "^0.4.0",
6666
"json-schema-library": "^9.1.2",
6767
"markdown-it": "^14.0.0",
68+
"vite-tsconfig-paths": "^4.3.1",
6869
"yaml": "^2.3.4"
6970
},
7071
"optionalDependencies": {
7172
"@codemirror/lang-json": "^6.0.1",
73+
"@codemirror/lang-yaml": "^6.0.0",
7274
"codemirror-json5": "^1.0.3",
7375
"json5": "^2.2.3"
7476
},
@@ -85,10 +87,10 @@
8587
"@codemirror/basic-setup": "^0.20.0",
8688
"@codemirror/commands": "^6.2.4",
8789
"@codemirror/language": "^6.8.0",
88-
"@codemirror/lint": "^6.4.0",
89-
"@codemirror/state": "^6.2.1",
90+
"@codemirror/lint": "^6.5.0",
91+
"@codemirror/state": "^6.0.0",
9092
"@codemirror/theme-one-dark": "^6.1.2",
91-
"@codemirror/view": "^6.14.1",
93+
"@codemirror/view": "^6.0.0",
9294
"@evilmartians/lefthook": "^1.4.6",
9395
"@lezer/common": "^1.0.3",
9496
"@types/markdown-it": "^13.0.7",
@@ -100,16 +102,16 @@
100102
"typedoc": "^0.24.8",
101103
"typedoc-plugin-markdown": "^3.15.3",
102104
"typescript": "^5.1.6",
103-
"vite": "^4.5.0",
105+
"vite": "^5.2.12",
104106
"vitest": "0.34.6",
105107
"vitest-dom": "^0.1.0"
106108
},
107109
"scripts": {
108110
"dev": "vite ./dev --port 3000",
109-
"build": "pnpm tsc && tsc --module commonjs --target es2017 --outDir cjs && vite build ./dev --outDir ../public --emptyOutDir",
111+
"build": "pnpm tsc && tsc --module commonjs --outDir cjs && vite build ./dev --outDir ../public --emptyOutDir",
110112
"test": "vitest --dom",
111113
"test:coverage": "vitest run --dom --coverage ",
112-
"tsc": "tsc && pnpm replace:env",
114+
"tsc": "NODE_OPTIONS=--experimental-specifier-resolution=node tsc && pnpm replace:env",
113115
"version-packages": "changeset version && pnpm typedoc && pnpm prettier:write CHANGELOG.md && git add package.json pnpm-lock.yaml CHANGELOG.md",
114116
"release": "pnpm build && changeset publish",
115117
"typedoc": "typedoc --out docs src/index.ts src/json5.ts && pnpm prettier:write docs/**/*",

0 commit comments

Comments
 (0)