Skip to content

Commit a73c517

Browse files
committed
improve docs, cleanup, add changeset
1 parent 5128c0e commit a73c517

File tree

9 files changed

+148
-42
lines changed

9 files changed

+148
-42
lines changed

.changeset/strange-chicken-smell.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
"codemirror-json-schema": minor
3+
---
4+
5+
**breaking change**: only impacts those following the "custom usage" approach, it _does not_ effect users using the high level, "bundled" `jsonSchema()` or `json5Schema()` modes.
6+
7+
Previously, we ask you to pass schema to each of the linter, completion and hover extensions.
8+
9+
Now, we ask you to use these new exports to instantiate your schema like this, with `stateExtensions(schema)` as a new extension, and the only one that you pass schema to, like so:
10+
11+
```ts
12+
import type { JSONSchema7 } from "json-schema";
13+
import { json, jsonLanguage, jsonParseLinter } from "@codemirror/lang-json";
14+
import { hoverTooltip } from "@codemirror/view";
15+
import { linter } from "@codemirror/lint";
16+
17+
import {
18+
jsonCompletion,
19+
handleRefresh,
20+
jsonSchemaLinter,
21+
jsonSchemaHover,
22+
stateExtensions,
23+
} from "codemirror-json-schema";
24+
25+
import schema from "./myschema.json";
26+
27+
// ...
28+
extensions: [
29+
json(),
30+
linter(jsonParseLinter()),
31+
linter(jsonSchemaLinter(), {
32+
needsRefresh: handleRefresh,
33+
}),
34+
jsonLanguage.data.of({
35+
autocomplete: jsonCompletion(),
36+
}),
37+
hoverTooltip(jsonSchemaHover()),
38+
// this is where we pass the schema!
39+
// very important!!!!
40+
stateExtensions(schema),
41+
];
42+
```

README.md

Lines changed: 97 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,29 @@ 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, but the APIs may still have breakages.
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
1212

13-
So far mostly tested with standard json4 schema specs. See
13+
- ✅ validation messages
14+
- ✅ autocompletion with insert text
15+
- ✅ hover tooltips
16+
- ✅ dynamic, per-editor-instance schemas using codemirror `StateField` and linting refresh
1417

15-
### json4
18+
## Resources
1619

17-
- ✅ validates json
18-
- ✅ autocompletion
19-
- ✅ hover tooltips from schema
20-
21-
### json5
22-
23-
- ✅ validates json5
24-
- ✅ autocompletion
25-
- ✅ hover tooltips
20+
- [Changelog](./CHANGELOG.md)
21+
- [Comprehensive example](https://github.com/acao/cm6-json-schema/blob/main/dev/index.ts)
22+
- [API Docs](./docs/)
2623

2724
## Usage
2825

2926
To give you as much flexibility as possible, everything codemirror related is a peer or optional dependency
3027

3128
Based on whether you want to support json4, json5 or both, you will need to install the relevant language mode for our library to use.
3229

30+
### Breaking Changes:
31+
32+
- 0.5.0 - this breaking change _does not_ effect users using `jsonSchema()` or `json5Schema()` modes, but those using the "custom path".
33+
3334
### json4
3435

3536
with `auto-install-peers true` or similar:
@@ -76,8 +77,15 @@ This approach allows you to configure the json mode and parse linter, as well as
7677
import { EditorState } from "@codemirror/state";
7778
import { linter } from "@codemirror/lint";
7879
import { hoverTooltip } from "@codemirror/view";
79-
import { json, jsonLanguage, jsonParseLinter } from "@codemirror/lang-json";
80-
import { jsonCompletion jsonSchemaLinter, jsonSchemaHover } from "codemirror-json-schema";
80+
import { json, jsonParseLinter, jsonLanguage } from "@codemirror/lang-json";
81+
82+
import {
83+
jsonSchemaLinter,
84+
jsonSchemaHover,
85+
jsonCompletion,
86+
stateExtensions,
87+
handleRefresh
88+
} from "codemirror-json-schema";
8189

8290
const schema = {
8391
type: "object",
@@ -96,11 +104,14 @@ const state = EditorState.create({
96104
// default is 750ms
97105
delay: 300
98106
}),
99-
linter(jsonSchemaLinter(schema)),
107+
linter(jsonSchemaLinter(), {
108+
needsRefresh: handleRefresh,
109+
}),
100110
jsonLanguage.data.of({
101-
autocomplete: jsonCompletion(schema),
111+
autocomplete: jsonCompletion(),
102112
}),
103-
hoverTooltip(jsonSchemaHover(schema)),
113+
hoverTooltip(jsonSchemaHover()),
114+
stateExtensions(schema)
104115
];
105116
})
106117
```
@@ -159,6 +170,7 @@ import {
159170
json5SchemaHover,
160171
json5Completion,
161172
} from "codemirror-json-schema/json5";
173+
import { stateExtensions, handleRefresh } from "codemirror-json-schema";
162174

163175
const schema = {
164176
type: "object",
@@ -180,30 +192,89 @@ const json5State = EditorState.create({
180192
// the default linting delay is 750ms
181193
delay: 300,
182194
}),
183-
linter(json5SchemaLinter(schema)),
184-
hoverTooltip(json5SchemaHover(schema)),
195+
linter(
196+
json5SchemaLinter({
197+
needsRefresh: handleRefresh,
198+
})
199+
),
200+
hoverTooltip(json5SchemaHover()),
185201
json5Language.data.of({
186-
autocomplete: json5Completion(schema),
202+
autocomplete: json5Completion(),
187203
}),
204+
stateExtensions(schema),
188205
],
189206
});
190207
```
191208

192-
### Complete demo
209+
### Dynamic Schema
210+
211+
If you want to, you can provide schema dynamically, in several ways.
212+
This works the same for either json or json5, using the underlying codemirror 6 StateFields, via the `updateSchema` method export.
213+
214+
In this example
215+
216+
- the initial schema state is empty
217+
- schema is loaded dynamically based on user input
218+
- the linting refresh will be handled automatically, because it's built into our bundled `jsonSchema()` and `json5Schema()` modes
219+
220+
```ts
221+
import { EditorState } from "@codemirror/state";
222+
import { EditorView } from "@codemirror/view";
223+
224+
import { json5Schema } from "codemirror-json-schema/json5";
225+
226+
import { updateSchema } from "codemirror-json-schema";
227+
228+
const json5State = EditorState.create({
229+
doc: `{
230+
example: true,
231+
// json5 is awesome!
232+
}`,
233+
// note: you can still provide initial
234+
// schema when creating state
235+
extensions: [json5Schema()],
236+
});
193237

194-
You can start with the [deployed example](https://github.com/acao/cm6-json-schema/blob/main/dev/index.ts) to see a more comprehensive setup.
238+
const editor = new EditorView({ state: json5State });
239+
240+
const schemaSelect = document.getElementById("schema-selection");
241+
242+
schemaSelect!.onchange = async (e) => {
243+
const val = e.target!.value!;
244+
if (!val) {
245+
return;
246+
}
247+
// parse the remote schema spec to json
248+
const data = await (
249+
await fetch(`https://json.schemastore.org/${val}`)
250+
).json();
251+
// this will update the schema state field, in an editor specific way
252+
updateSchema(editor, data);
253+
};
254+
```
255+
256+
if you are using the "custom path" with this approach, you will need to configure linting refresh as well:
195257

196-
### API Docs
258+
```ts
259+
import { linter } from "@codemirror/lint";
260+
import { json5SchemaLinter } from "codemirror-json-schema/json5";
261+
import { handleRefresh } from "codemirror-json-schema";
197262

198-
For more information, see the [API Docs](./docs/)
263+
const state = EditorState.create({
264+
// ...
265+
extensions: [
266+
linter(json5SchemaLinter(), {
267+
needsRefresh: handleRefresh,
268+
})
269+
];
270+
}
271+
```
199272
200273
## Current Constraints:
201274
202-
- it only works with one json schema instance at a time, and doesn't yet fetch remote schemas. schema service coming soon!
203275
- currently only tested with standard schemas using json4 spec. results may vary
204276
- doesn't place cursor inside known insert text yet
205277
- currently you can only override the texts and rendering of a hover. we plan to add the same for validation errors and autocomplete
206-
- json5 properties on autocompletion selection will insert surrounding double quotes, but we plan to make it insert without delimiters
207278
208279
## Inspiration
209280

dev/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,12 @@ const editor2 = new EditorView({
9898
state: json5State,
9999
parent: document.querySelector("#editor-json5")!,
100100
});
101-
const handleSchema = (newSchema: JSONSchema7) => {
101+
102+
const handleSchemaChange = (newSchema: JSONSchema7) => {
102103
updateSchema(editor1, newSchema);
103104
updateSchema(editor2, newSchema);
104105
};
105106

106-
handleSchema(schema);
107107
// new EditorState.fi(editor1, editor2);
108108
// Hot Module Replacement
109109
// if (module.hot) {
@@ -120,5 +120,5 @@ schemaSelect!.onchange = async (e) => {
120120
const data = await (
121121
await fetch(`https://json.schemastore.org/${val}`)
122122
).json();
123-
handleSchema(data);
123+
handleSchemaChange(data);
124124
};

src/bundled.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { linter } from "@codemirror/lint";
1212
* Full featured cm6 extension for json, including `@codemirror/lang-json`
1313
* @group Bundled Codemirror Extensions
1414
*/
15-
export function jsonSchema(schema: JSONSchema7) {
15+
export function jsonSchema(schema?: JSONSchema7) {
1616
return [
1717
json(),
1818
linter(jsonParseLinter()),
@@ -23,6 +23,6 @@ export function jsonSchema(schema: JSONSchema7) {
2323
autocomplete: jsonCompletion(),
2424
}),
2525
hoverTooltip(jsonSchemaHover()),
26-
stateExtensions(),
26+
stateExtensions(schema),
2727
];
2828
}

src/json-completion.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import { jsonPointerForPosition } from "./utils/jsonPointers.js";
2222
import { TOKENS } from "./constants.js";
2323
import { getJSONSchema } from "./state.js";
2424
import getSchema from "./utils/schema-lib/getSchema.js";
25-
import { EditorState } from "@codemirror/state";
2625

2726
function json5PropertyInsertSnippet(rawWord: string, value: string) {
2827
if (rawWord.startsWith('"')) {

src/json-validation.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ export type JSONValidationOptions = {
3030
type JSONValidationSettings = RequiredPick<JSONValidationOptions, "jsonParser">;
3131

3232
export const handleRefresh = (vu: ViewUpdate) => {
33-
console.log("handleRefresh");
3433
return (
3534
vu.startState.field(schemaStateField) !== vu.state.field(schemaStateField)
3635
);

src/json5-bundled.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@ import { handleRefresh } from "./json-validation.js";
1313
* Full featured cm6 extension for json5, including `codemirror-json5`
1414
* @group Bundled Codemirror Extensions
1515
*/
16-
export function json5Schema(schema: JSONSchema7) {
16+
export function json5Schema(schema?: JSONSchema7) {
1717
return [
1818
json5(),
1919
linter(json5ParseLinter()),
2020
linter(json5SchemaLinter(), {
2121
needsRefresh: handleRefresh,
2222
}),
2323
json5Language.data.of({
24-
autocomplete: json5Completion(schema),
24+
autocomplete: json5Completion(),
2525
}),
26-
hoverTooltip(json5SchemaHover(schema)),
26+
hoverTooltip(json5SchemaHover()),
2727
stateExtensions(schema),
2828
];
2929
}

src/json5-hover.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ export type JSON5HoverOptions = Exclude<HoverOptions, "mode">;
1010
* Instantiates a JSONHover instance with the JSON5 mode
1111
* @group Codemirror Extensions
1212
*/
13-
export function json5SchemaHover(
14-
schema: JSONSchema7,
15-
options?: JSON5HoverOptions
16-
) {
13+
export function json5SchemaHover(options?: JSON5HoverOptions) {
1714
const hover = new JSONHover({
1815
...options,
1916
parser: json5.parse,

src/json5-validation.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { EditorView } from "@codemirror/view";
2-
import { linter } from "@codemirror/lint";
32
import {
43
JSONValidation,
5-
handleRefresh,
64
type JSONValidationOptions,
75
} from "./json-validation.js";
86
import { parseJSON5DocumentState } from "./utils/parseJSON5Document.js";

0 commit comments

Comments
 (0)