skir-codemirror-plugin 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +126 -0
  2. package/dist/codemirror/create_editor_state.d.ts +20 -0
  3. package/dist/codemirror/create_editor_state.d.ts.map +1 -0
  4. package/dist/codemirror/create_editor_state.js +252 -0
  5. package/dist/codemirror/create_editor_state.js.map +1 -0
  6. package/dist/codemirror/enter_key_handler.d.ts +8 -0
  7. package/dist/codemirror/enter_key_handler.d.ts.map +1 -0
  8. package/dist/codemirror/enter_key_handler.js +181 -0
  9. package/dist/codemirror/enter_key_handler.js.map +1 -0
  10. package/dist/codemirror/json_completion.d.ts +4 -0
  11. package/dist/codemirror/json_completion.d.ts.map +1 -0
  12. package/dist/codemirror/json_completion.js +150 -0
  13. package/dist/codemirror/json_completion.js.map +1 -0
  14. package/dist/codemirror/json_linter.d.ts +4 -0
  15. package/dist/codemirror/json_linter.d.ts.map +1 -0
  16. package/dist/codemirror/json_linter.js +277 -0
  17. package/dist/codemirror/json_linter.js.map +1 -0
  18. package/dist/codemirror/json_state.d.ts +16 -0
  19. package/dist/codemirror/json_state.d.ts.map +1 -0
  20. package/dist/codemirror/json_state.js +124 -0
  21. package/dist/codemirror/json_state.js.map +1 -0
  22. package/dist/codemirror/status_bar.d.ts +3 -0
  23. package/dist/codemirror/status_bar.d.ts.map +1 -0
  24. package/dist/codemirror/status_bar.js +123 -0
  25. package/dist/codemirror/status_bar.js.map +1 -0
  26. package/dist/index.d.ts +4 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +2 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/json/json_parser.d.ts +3 -0
  31. package/dist/json/json_parser.d.ts.map +1 -0
  32. package/dist/json/json_parser.js +414 -0
  33. package/dist/json/json_parser.js.map +1 -0
  34. package/dist/json/json_parser.test.d.ts +2 -0
  35. package/dist/json/json_parser.test.d.ts.map +1 -0
  36. package/dist/json/json_parser.test.js +337 -0
  37. package/dist/json/json_parser.test.js.map +1 -0
  38. package/dist/json/schema_validator.d.ts +3 -0
  39. package/dist/json/schema_validator.d.ts.map +1 -0
  40. package/dist/json/schema_validator.js +525 -0
  41. package/dist/json/schema_validator.js.map +1 -0
  42. package/dist/json/schema_validator.test.d.ts +2 -0
  43. package/dist/json/schema_validator.test.d.ts.map +1 -0
  44. package/dist/json/schema_validator.test.js +212 -0
  45. package/dist/json/schema_validator.test.js.map +1 -0
  46. package/dist/json/to_json.d.ts +6 -0
  47. package/dist/json/to_json.d.ts.map +1 -0
  48. package/dist/json/to_json.js +61 -0
  49. package/dist/json/to_json.js.map +1 -0
  50. package/dist/json/to_json.test.d.ts +2 -0
  51. package/dist/json/to_json.test.d.ts.map +1 -0
  52. package/dist/json/to_json.test.js +128 -0
  53. package/dist/json/to_json.test.js.map +1 -0
  54. package/dist/json/types.d.ts +170 -0
  55. package/dist/json/types.d.ts.map +1 -0
  56. package/dist/json/types.js +2 -0
  57. package/dist/json/types.js.map +1 -0
  58. package/package.json +85 -0
  59. package/src/codemirror/create_editor_state.ts +278 -0
  60. package/src/codemirror/enter_key_handler.ts +232 -0
  61. package/src/codemirror/json_completion.ts +182 -0
  62. package/src/codemirror/json_linter.ts +358 -0
  63. package/src/codemirror/json_state.ts +170 -0
  64. package/src/codemirror/status_bar.ts +137 -0
  65. package/src/index.ts +6 -0
  66. package/src/json/json_parser.test.ts +360 -0
  67. package/src/json/json_parser.ts +461 -0
  68. package/src/json/schema_validator.test.ts +230 -0
  69. package/src/json/schema_validator.ts +558 -0
  70. package/src/json/to_json.test.ts +150 -0
  71. package/src/json/to_json.ts +70 -0
  72. package/src/json/types.ts +254 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json_state.js","sourceRoot":"","sources":["../../src/codemirror/json_state.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Extension,\n StateEffect,\n StateField,\n Transaction,\n} from \"@codemirror/state\";\nimport { EditorView, ViewPlugin, ViewUpdate } from \"@codemirror/view\";\nimport { parseJsonValue } from \"../json/json_parser\";\nimport { validateSchema } from \"../json/schema_validator\";\nimport type {\n JsonParseResult,\n TypeDefinition,\n ValidationResult,\n} from \"../json/types\";\n\nexport interface JsonState {\n readonly parseResult: JsonParseResult;\n readonly validationResult?: ValidationResult;\n readonly source: string;\n}\n\nconst updateJsonState = StateEffect.define<JsonState>();\n\nexport const jsonStateField = StateField.define<JsonState | null>({\n create(): JsonState | null {\n return null;\n },\n update(value, tr): JsonState | null {\n for (const effect of tr.effects) {\n if (effect.is(updateJsonState)) {\n return effect.value;\n }\n }\n return value;\n },\n});\n\n/**\n * Ensures the JSON state is up-to-date with the current document.\n * If the state is stale or missing, triggers an immediate parse and returns the updated state.\n */\nexport function ensureJsonState(\n view: EditorView,\n schema: TypeDefinition,\n): JsonState {\n const currentState = view.state.field(jsonStateField, false);\n const source = view.state.doc.toString();\n\n // If the source hasn't changed, return the current state\n if (currentState && currentState.source === source) {\n return currentState;\n }\n\n // Parse and validate immediately\n const parseResult = parseJsonValue(source);\n let validationResult: ValidationResult | undefined;\n if (parseResult.value) {\n validationResult = validateSchema(parseResult.value, schema);\n }\n\n const newState: JsonState = { parseResult, validationResult, source };\n\n // Update the state if it's different\n if (!currentState || currentState !== newState) {\n view.dispatch({\n effects: updateJsonState.of(newState),\n });\n }\n\n return newState;\n}\n\nexport function debouncedJsonParser(schema: TypeDefinition): Extension[] {\n return [\n jsonStateField,\n ViewPlugin.fromClass(\n class {\n timeout: number | null = null;\n view: EditorView;\n\n constructor(view: EditorView) {\n this.view = view;\n this.scheduleUpdate();\n }\n\n update(update: ViewUpdate): void {\n if (update.docChanged) {\n const isUndo = update.transactions.some(\n (tr) =>\n tr.annotation(Transaction.userEvent) === \"undo\" ||\n tr.annotation(Transaction.userEvent) === \"redo\",\n );\n this.scheduleUpdate(isUndo ? \"from-undo\" : undefined);\n }\n }\n\n scheduleUpdate(fromUndo?: \"from-undo\"): void {\n if (this.timeout !== null) {\n clearTimeout(this.timeout);\n }\n this.timeout = window.setTimeout(() => {\n this.parseJson(fromUndo);\n this.timeout = null;\n }, 200);\n }\n\n parseJson(fromUndo: \"from-undo\" | undefined): void {\n const source = this.view.state.doc.toString();\n const parseResult = parseJsonValue(source);\n\n let validationResult: ValidationResult | undefined;\n if (parseResult.value) {\n validationResult = validateSchema(parseResult.value, schema);\n }\n\n const cursorInsideEdit = (): boolean => {\n const cursorPos = this.view.state.selection.main.head;\n return parseResult.edits.some(\n (edit) =>\n edit.segment.start <= cursorPos &&\n cursorPos <= edit.segment.end,\n );\n };\n\n // Apply edits if all these conditions are satisfied:\n // - no error\n // - the cursor is not inside any of the edited segments, to avoid\n // disrupting the user while they're typing\n // - the update is not triggered by an undo operation\n if (\n !fromUndo &&\n parseResult.edits.length &&\n parseResult.errors.length <= 0 &&\n !cursorInsideEdit()\n ) {\n const changes = parseResult.edits.map((edit) => ({\n from: edit.segment.start,\n to: edit.segment.end,\n insert: edit.replacement,\n }));\n\n this.view.dispatch({\n changes,\n effects: updateJsonState.of({\n parseResult,\n validationResult,\n source,\n }),\n scrollIntoView: true,\n });\n } else {\n this.view.dispatch({\n effects: updateJsonState.of({\n parseResult,\n validationResult,\n source,\n }),\n });\n }\n }\n\n destroy(): void {\n if (this.timeout !== null) {\n clearTimeout(this.timeout);\n }\n }\n },\n ),\n ];\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { showPanel } from "@codemirror/view";
2
+ export declare function statusBar(): ReturnType<typeof showPanel.of>;
3
+ //# sourceMappingURL=status_bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status_bar.d.ts","sourceRoot":"","sources":["../../src/codemirror/status_bar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAyChE,wBAAgB,SAAS,IAAI,UAAU,CAAC,OAAO,SAAS,CAAC,EAAE,CAAC,CAE3D"}
@@ -0,0 +1,123 @@
1
+ import { showPanel } from "@codemirror/view";
2
+ import { jsonStateField } from "./json_state";
3
+ function createStatusBarPanel(view) {
4
+ const dom = document.createElement("div");
5
+ dom.className = "cm-status-bar";
6
+ function updateCursor() {
7
+ const pos = view.state.selection.main.head;
8
+ const jsonState = view.state.field(jsonStateField, false);
9
+ const validationResult = jsonState?.validationResult;
10
+ const rootTypeHint = validationResult?.rootTypeHint;
11
+ const nodes = [];
12
+ if (rootTypeHint) {
13
+ const typeHint = findTypeHint(pos, rootTypeHint);
14
+ if (typeHint) {
15
+ const { pathToTypeHint } = validationResult;
16
+ const builder = new NavigatorNodesBuilder(pathToTypeHint, view);
17
+ builder.appendNodesForPath(typeHint.valueContext.path);
18
+ nodes.push(...builder.nodes);
19
+ nodes.reverse();
20
+ }
21
+ }
22
+ dom.replaceChildren(...nodes);
23
+ }
24
+ updateCursor();
25
+ return {
26
+ dom,
27
+ update(update) {
28
+ if (update.selectionSet) {
29
+ updateCursor();
30
+ }
31
+ },
32
+ top: false,
33
+ };
34
+ }
35
+ export function statusBar() {
36
+ return showPanel.of(createStatusBarPanel);
37
+ }
38
+ function findTypeHint(pos, root) {
39
+ // Check if pos is within the root's segment
40
+ const segment = root.valueContext.value.segment;
41
+ if (pos < segment.start || pos > segment.end) {
42
+ return undefined;
43
+ }
44
+ // Binary search through childHints to find a child containing pos
45
+ let left = 0;
46
+ let right = root.childHints.length - 1;
47
+ let foundChild;
48
+ while (left <= right) {
49
+ const mid = Math.floor((left + right) / 2);
50
+ const child = root.childHints[mid];
51
+ const childSegment = child.valueContext.value.segment;
52
+ if (pos < childSegment.start) {
53
+ right = mid - 1;
54
+ }
55
+ else if (pos > childSegment.end) {
56
+ left = mid + 1;
57
+ }
58
+ else {
59
+ // pos is within this child's segment
60
+ foundChild = child;
61
+ break;
62
+ }
63
+ }
64
+ // If we found a child containing pos, recursively search deeper
65
+ if (foundChild) {
66
+ const deeperHint = findTypeHint(pos, foundChild);
67
+ return deeperHint !== undefined ? deeperHint : foundChild;
68
+ }
69
+ // No child contains pos, so root is the deepest match
70
+ return root;
71
+ }
72
+ class NavigatorNodesBuilder {
73
+ constructor(pathToTypeHint, view) {
74
+ this.pathToTypeHint = pathToTypeHint;
75
+ this.view = view;
76
+ this.nodes = [];
77
+ }
78
+ appendNodesForPath(path) {
79
+ const typeHint = this.pathToTypeHint.get(path);
80
+ const pos = typeHint.valueContext.value.segment.start;
81
+ const link = document.createElement("a");
82
+ link.className = "cm-status-bar-link";
83
+ link.addEventListener("click", (e) => {
84
+ e.preventDefault();
85
+ this.view.dispatch({
86
+ selection: { anchor: pos, head: pos },
87
+ scrollIntoView: true,
88
+ });
89
+ this.view.focus();
90
+ });
91
+ switch (path.kind) {
92
+ case "root": {
93
+ link.append("root");
94
+ this.nodes.push(link);
95
+ break;
96
+ }
97
+ case "array-item": {
98
+ this.appendNodesForPath(path.arrayPath);
99
+ if (path.key != null) {
100
+ link.append(`[${path.index}|${path.key}]`);
101
+ }
102
+ else {
103
+ link.append(`[${path.index}]`);
104
+ }
105
+ this.nodes.push(link);
106
+ break;
107
+ }
108
+ case "field-value": {
109
+ this.appendNodesForPath(path.structPath);
110
+ link.append(`.${path.fieldName}`);
111
+ this.nodes.push(link);
112
+ break;
113
+ }
114
+ case "variant-value": {
115
+ this.appendNodesForPath(path.enumPath);
116
+ link.append(`.value("${path.variantName}")`);
117
+ this.nodes.push(link);
118
+ break;
119
+ }
120
+ }
121
+ }
122
+ }
123
+ //# sourceMappingURL=status_bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status_bar.js","sourceRoot":"","sources":["../../src/codemirror/status_bar.ts"],"names":[],"mappings":"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","sourcesContent":["import { EditorView, Panel, showPanel } from \"@codemirror/view\";\nimport { Path, TypeHint } from \"../json/types\";\nimport { jsonStateField } from \"./json_state\";\n\nfunction createStatusBarPanel(view: EditorView): Panel {\n const dom = document.createElement(\"div\");\n dom.className = \"cm-status-bar\";\n\n function updateCursor(): void {\n const pos = view.state.selection.main.head;\n\n const jsonState = view.state.field(jsonStateField, false);\n const validationResult = jsonState?.validationResult;\n const rootTypeHint = validationResult?.rootTypeHint;\n const nodes: Node[] = [];\n if (rootTypeHint) {\n const typeHint = findTypeHint(pos, rootTypeHint);\n if (typeHint) {\n const { pathToTypeHint } = validationResult;\n const builder = new NavigatorNodesBuilder(pathToTypeHint, view);\n builder.appendNodesForPath(typeHint.valueContext.path);\n nodes.push(...builder.nodes);\n nodes.reverse();\n }\n }\n dom.replaceChildren(...nodes);\n }\n\n updateCursor();\n\n return {\n dom,\n update(update): void {\n if (update.selectionSet) {\n updateCursor();\n }\n },\n top: false,\n };\n}\n\nexport function statusBar(): ReturnType<typeof showPanel.of> {\n return showPanel.of(createStatusBarPanel);\n}\n\nfunction findTypeHint(pos: number, root: TypeHint): TypeHint | undefined {\n // Check if pos is within the root's segment\n const segment = root.valueContext.value.segment;\n if (pos < segment.start || pos > segment.end) {\n return undefined;\n }\n\n // Binary search through childHints to find a child containing pos\n let left = 0;\n let right = root.childHints.length - 1;\n let foundChild: TypeHint | undefined;\n\n while (left <= right) {\n const mid = Math.floor((left + right) / 2);\n const child = root.childHints[mid];\n const childSegment = child.valueContext.value.segment;\n\n if (pos < childSegment.start) {\n right = mid - 1;\n } else if (pos > childSegment.end) {\n left = mid + 1;\n } else {\n // pos is within this child's segment\n foundChild = child;\n break;\n }\n }\n\n // If we found a child containing pos, recursively search deeper\n if (foundChild) {\n const deeperHint = findTypeHint(pos, foundChild);\n return deeperHint !== undefined ? deeperHint : foundChild;\n }\n\n // No child contains pos, so root is the deepest match\n return root;\n}\n\nclass NavigatorNodesBuilder {\n readonly nodes: Node[] = [];\n\n constructor(\n private readonly pathToTypeHint: ReadonlyMap<Path, TypeHint>,\n private readonly view: EditorView,\n ) {}\n\n appendNodesForPath(path: Path): void {\n const typeHint = this.pathToTypeHint.get(path)!;\n const pos = typeHint.valueContext.value.segment.start;\n const link = document.createElement(\"a\");\n link.className = \"cm-status-bar-link\";\n\n link.addEventListener(\"click\", (e) => {\n e.preventDefault();\n this.view.dispatch({\n selection: { anchor: pos, head: pos },\n scrollIntoView: true,\n });\n this.view.focus();\n });\n\n switch (path.kind) {\n case \"root\": {\n link.append(\"root\");\n this.nodes.push(link);\n break;\n }\n case \"array-item\": {\n this.appendNodesForPath(path.arrayPath);\n if (path.key != null) {\n link.append(`[${path.index}|${path.key}]`);\n } else {\n link.append(`[${path.index}]`);\n }\n this.nodes.push(link);\n break;\n }\n case \"field-value\": {\n this.appendNodesForPath(path.structPath);\n link.append(`.${path.fieldName}`);\n this.nodes.push(link);\n break;\n }\n case \"variant-value\": {\n this.appendNodesForPath(path.enumPath);\n link.append(`.value(\"${path.variantName}\")`);\n this.nodes.push(link);\n break;\n }\n }\n }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export { createEditorState } from "./codemirror/create_editor_state";
2
+ export type { CreateEditorStateParams, CustomTheme, } from "./codemirror/create_editor_state";
3
+ export type { Json } from "./json/types";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,YAAY,EACV,uBAAuB,EACvB,WAAW,GACZ,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { createEditorState } from "./codemirror/create_editor_state";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC","sourcesContent":["export { createEditorState } from \"./codemirror/create_editor_state\";\nexport type {\n CreateEditorStateParams,\n CustomTheme,\n} from \"./codemirror/create_editor_state\";\nexport type { Json } from \"./json/types\";\n"]}
@@ -0,0 +1,3 @@
1
+ import type { JsonParseResult } from "./types";
2
+ export declare function parseJsonValue(input: string): JsonParseResult;
3
+ //# sourceMappingURL=json_parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json_parser.d.ts","sourceRoot":"","sources":["../../src/json/json_parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAOV,eAAe,EAGhB,MAAM,SAAS,CAAC;AAEjB,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAkB7D"}
@@ -0,0 +1,414 @@
1
+ export function parseJsonValue(input) {
2
+ const tokens = tokenize(input);
3
+ if (tokens.kind === "error") {
4
+ return {
5
+ value: undefined,
6
+ errors: [tokens],
7
+ edits: [],
8
+ };
9
+ }
10
+ const parser = new JsonParser(tokens.tokens, input);
11
+ const parseResult = parser.parseValueOrSkip();
12
+ parser.expectEnd();
13
+ return {
14
+ value: parseResult,
15
+ errors: parser.errors,
16
+ edits: parser.edits,
17
+ };
18
+ }
19
+ function tokenize(input) {
20
+ const tokens = [];
21
+ let pos = 0;
22
+ const whitespaceRegex = /[ \t\r\n]*/y;
23
+ const tokenRegex = /([[\]{}:,]|(-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)|false|true|null|("(((?=\\)\\(["\\/ bfnrt]|u[0-9a-fA-F]{4}))|[^"\\\0-\x1F\x7F]+)*")|$)/y;
24
+ while (true) {
25
+ whitespaceRegex.lastIndex = pos;
26
+ whitespaceRegex.exec(input);
27
+ pos = whitespaceRegex.lastIndex;
28
+ tokenRegex.lastIndex = pos;
29
+ const tokenMatch = tokenRegex.exec(input);
30
+ if (tokenMatch) {
31
+ const tokenText = tokenMatch[0];
32
+ const segment = {
33
+ start: pos,
34
+ end: pos + tokenText.length,
35
+ };
36
+ const token = { segment, jsonCode: tokenText };
37
+ pos = tokenRegex.lastIndex;
38
+ tokens.push(token);
39
+ if (tokenText === "") {
40
+ return {
41
+ kind: "tokens",
42
+ tokens: tokens,
43
+ };
44
+ }
45
+ }
46
+ else {
47
+ // Find the next word boundary using unicode support
48
+ const wordBoundaryRegex = /\w*/uy;
49
+ wordBoundaryRegex.lastIndex = pos + 1;
50
+ wordBoundaryRegex.exec(input);
51
+ const end = wordBoundaryRegex.lastIndex || pos + 1;
52
+ return {
53
+ kind: "error",
54
+ message: "not a token",
55
+ segment: { start: pos, end: end },
56
+ };
57
+ }
58
+ }
59
+ }
60
+ class JsonParser {
61
+ constructor(tokens, input) {
62
+ this.tokens = tokens;
63
+ this.input = input;
64
+ this.tokenIndex = 0;
65
+ this.errors = [];
66
+ this.edits = [];
67
+ this.indent = "";
68
+ }
69
+ parseValueOrSkip() {
70
+ const token = this.peekToken();
71
+ const firstChar = token.jsonCode ? token.jsonCode[0] : "";
72
+ switch (firstChar) {
73
+ case "[":
74
+ return this.parseArray();
75
+ case "{":
76
+ return this.parseObject();
77
+ case "n":
78
+ this.nextToken();
79
+ return {
80
+ kind: "literal",
81
+ firstToken: token.segment,
82
+ segment: token.segment,
83
+ jsonCode: "null",
84
+ type: "null",
85
+ };
86
+ case "f":
87
+ this.nextToken();
88
+ return {
89
+ kind: "literal",
90
+ firstToken: token.segment,
91
+ segment: token.segment,
92
+ jsonCode: "false",
93
+ type: "boolean",
94
+ };
95
+ case "t":
96
+ this.nextToken();
97
+ return {
98
+ kind: "literal",
99
+ firstToken: token.segment,
100
+ segment: token.segment,
101
+ jsonCode: "true",
102
+ type: "boolean",
103
+ };
104
+ case '"':
105
+ this.nextToken();
106
+ return {
107
+ kind: "literal",
108
+ firstToken: token.segment,
109
+ segment: token.segment,
110
+ jsonCode: token.jsonCode,
111
+ type: "string",
112
+ };
113
+ case "0":
114
+ case "1":
115
+ case "2":
116
+ case "3":
117
+ case "4":
118
+ case "5":
119
+ case "6":
120
+ case "7":
121
+ case "8":
122
+ case "9":
123
+ case "-":
124
+ this.nextToken();
125
+ return {
126
+ kind: "literal",
127
+ firstToken: token.segment,
128
+ segment: token.segment,
129
+ jsonCode: token.jsonCode,
130
+ type: "number",
131
+ };
132
+ }
133
+ this.errors.push({
134
+ kind: "error",
135
+ message: "expected: value",
136
+ segment: this.peekToken().segment,
137
+ });
138
+ this.skip();
139
+ return undefined;
140
+ }
141
+ parseArray() {
142
+ const leftBracket = this.nextToken();
143
+ const values = [];
144
+ while (true) {
145
+ if (this.peekToken().jsonCode === "]") {
146
+ const rightBracket = this.nextToken();
147
+ return {
148
+ kind: "array",
149
+ firstToken: leftBracket.segment,
150
+ segment: {
151
+ start: leftBracket.segment.start,
152
+ end: rightBracket.segment.end,
153
+ },
154
+ values,
155
+ };
156
+ }
157
+ if (this.peekToken().jsonCode === "}") {
158
+ this.errors.push({
159
+ kind: "error",
160
+ message: "expected: ']'",
161
+ segment: this.peekToken().segment,
162
+ });
163
+ const wrongBracket = this.nextToken();
164
+ return {
165
+ kind: "array",
166
+ firstToken: leftBracket.segment,
167
+ segment: {
168
+ start: leftBracket.segment.start,
169
+ end: wrongBracket.segment.end,
170
+ },
171
+ values,
172
+ };
173
+ }
174
+ if (this.peekToken().jsonCode === "") {
175
+ // End of file
176
+ this.expectSymbolOrSkip("]");
177
+ return {
178
+ kind: "array",
179
+ firstToken: leftBracket.segment,
180
+ segment: {
181
+ start: leftBracket.segment.start,
182
+ end: this.peekToken().segment.start,
183
+ },
184
+ values,
185
+ };
186
+ }
187
+ const value = this.parseValueOrSkip();
188
+ if (value) {
189
+ values.push(value);
190
+ }
191
+ if (this.peekToken().jsonCode === ",") {
192
+ const commaToken = this.nextToken();
193
+ // Check if this is a trailing comma
194
+ if (this.peekToken().jsonCode === "]") {
195
+ // Trailing comma - add edit to remove it
196
+ this.edits.push({
197
+ segment: commaToken.segment,
198
+ replacement: "",
199
+ });
200
+ }
201
+ }
202
+ }
203
+ }
204
+ parseObject() {
205
+ const leftBracket = this.nextToken();
206
+ const keyValues = {};
207
+ const allKeys = [];
208
+ while (true) {
209
+ if (this.peekToken().jsonCode === "}") {
210
+ const rightBracket = this.nextToken();
211
+ return {
212
+ kind: "object",
213
+ firstToken: leftBracket.segment,
214
+ segment: {
215
+ start: leftBracket.segment.start,
216
+ end: rightBracket.segment.end,
217
+ },
218
+ keyValues,
219
+ allKeys,
220
+ };
221
+ }
222
+ if (this.peekToken().jsonCode === "]") {
223
+ this.errors.push({
224
+ kind: "error",
225
+ message: "expected: ']'",
226
+ segment: this.peekToken().segment,
227
+ });
228
+ const wrongBracket = this.nextToken();
229
+ return {
230
+ kind: "object",
231
+ firstToken: leftBracket.segment,
232
+ segment: {
233
+ start: leftBracket.segment.start,
234
+ end: wrongBracket.segment.end,
235
+ },
236
+ keyValues,
237
+ allKeys,
238
+ };
239
+ }
240
+ if (this.peekToken().jsonCode === "") {
241
+ // End of file
242
+ this.expectSymbolOrSkip("}");
243
+ return {
244
+ kind: "object",
245
+ firstToken: leftBracket.segment,
246
+ segment: {
247
+ start: leftBracket.segment.start,
248
+ end: this.peekToken().segment.start,
249
+ },
250
+ keyValues,
251
+ allKeys,
252
+ };
253
+ }
254
+ const keyToken = this.peekToken();
255
+ if (!keyToken.jsonCode.startsWith('"')) {
256
+ this.errors.push({
257
+ kind: "error",
258
+ message: "expected: string",
259
+ segment: keyToken.segment,
260
+ });
261
+ this.skip();
262
+ // Consume comma if we're stuck at one to avoid infinite loop
263
+ if (this.peekToken().jsonCode === ",") {
264
+ this.nextToken();
265
+ }
266
+ continue;
267
+ }
268
+ const key = JSON.parse(keyToken.jsonCode);
269
+ allKeys.push({
270
+ key: key,
271
+ keySegment: keyToken.segment,
272
+ });
273
+ this.nextToken();
274
+ if (!this.expectSymbolOrSkip(":")) {
275
+ continue;
276
+ }
277
+ if (keyValues[key]) {
278
+ this.errors.push({
279
+ kind: "error",
280
+ message: "duplicate key",
281
+ segment: keyToken.segment,
282
+ });
283
+ }
284
+ const value = this.parseValueOrSkip();
285
+ if (value) {
286
+ keyValues[key] = {
287
+ keySegment: keyToken.segment,
288
+ key: key,
289
+ value: value,
290
+ };
291
+ }
292
+ if (this.peekToken().jsonCode === ",") {
293
+ const commaToken = this.nextToken();
294
+ // Check if this is a trailing comma
295
+ if (this.peekToken().jsonCode === "}") {
296
+ // Trailing comma - add edit to remove it
297
+ this.edits.push({
298
+ segment: commaToken.segment,
299
+ replacement: "",
300
+ });
301
+ }
302
+ }
303
+ }
304
+ }
305
+ expectEnd() {
306
+ const token = this.nextToken();
307
+ if (token.jsonCode) {
308
+ this.errors.push({
309
+ kind: "error",
310
+ message: "expected: end",
311
+ segment: this.peekToken().segment,
312
+ });
313
+ }
314
+ }
315
+ nextToken() {
316
+ const result = this.tokens[this.tokenIndex];
317
+ // Check the whitespace separator before the current token.
318
+ {
319
+ const previous = this.tokenIndex <= 0 ? undefined : this.tokens[this.tokenIndex - 1];
320
+ const separatorSegment = {
321
+ start: previous ? previous.segment.end : 0,
322
+ end: result.segment.start,
323
+ };
324
+ const actualSeparator = this.input.substring(separatorSegment.start, separatorSegment.end);
325
+ const expectedSeparator = this.inferWhitespaceSeparator(previous?.jsonCode ?? "", result.jsonCode);
326
+ if (actualSeparator !== expectedSeparator.text) {
327
+ this.edits.push({
328
+ segment: separatorSegment,
329
+ replacement: expectedSeparator.text,
330
+ });
331
+ }
332
+ this.indent = expectedSeparator.newIndent ?? this.indent;
333
+ }
334
+ ++this.tokenIndex;
335
+ return result;
336
+ }
337
+ inferWhitespaceSeparator(a, b) {
338
+ const { indent } = this;
339
+ if (a === ":") {
340
+ return {
341
+ text: " ",
342
+ };
343
+ }
344
+ else if (a === "," && b !== "]" && b !== "}") {
345
+ return {
346
+ text: `\n${indent}`,
347
+ };
348
+ }
349
+ else if (/[0-9"}\]el]$/.test(a) && /^[0-9"{[tfn-]/.test(b)) {
350
+ // a is the end of a JSON value and B is the start of a JSON value
351
+ return {
352
+ text: `,\n${indent}`,
353
+ };
354
+ }
355
+ else if ((a === "[" && b !== "]") || (a === "{" && b !== "}")) {
356
+ const newIndent = indent + INDENT_UNIT;
357
+ return {
358
+ text: `\n${newIndent}`,
359
+ newIndent: newIndent,
360
+ };
361
+ }
362
+ else if ((a !== "[" && b === "]") || (a !== "{" && b === "}")) {
363
+ const newIndent = indent.replace(INDENT_UNIT, "");
364
+ return {
365
+ text: `\n${newIndent}`,
366
+ newIndent: newIndent,
367
+ };
368
+ }
369
+ else {
370
+ return {
371
+ text: "",
372
+ };
373
+ }
374
+ }
375
+ peekToken() {
376
+ return this.tokens[this.tokenIndex];
377
+ }
378
+ expectSymbolOrSkip(symbol) {
379
+ if (this.peekToken().jsonCode !== symbol) {
380
+ this.errors.push({
381
+ kind: "error",
382
+ message: `expected: '${symbol}'`,
383
+ segment: this.peekToken().segment,
384
+ });
385
+ this.skip();
386
+ return false;
387
+ }
388
+ this.nextToken();
389
+ return true;
390
+ }
391
+ skip() {
392
+ while (true) {
393
+ const tokenJson = this.peekToken().jsonCode;
394
+ if (tokenJson === "" ||
395
+ tokenJson === "," ||
396
+ tokenJson === "]" ||
397
+ tokenJson === "}" ||
398
+ tokenJson.startsWith('"')) {
399
+ return;
400
+ }
401
+ else if (tokenJson === "[") {
402
+ this.parseArray();
403
+ }
404
+ else if (tokenJson === "{") {
405
+ this.parseObject();
406
+ }
407
+ else {
408
+ this.nextToken();
409
+ }
410
+ }
411
+ }
412
+ }
413
+ const INDENT_UNIT = " ";
414
+ //# sourceMappingURL=json_parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json_parser.js","sourceRoot":"","sources":["../../src/json/json_parser.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n JsonArray,\n JsonEdit,\n JsonError,\n JsonKey,\n JsonKeyValue,\n JsonObject,\n JsonParseResult,\n JsonValue,\n Segment,\n} from \"./types\";\n\nexport function parseJsonValue(input: string): JsonParseResult {\n const tokens = tokenize(input);\n if (tokens.kind === \"error\") {\n return {\n value: undefined,\n errors: [tokens],\n edits: [],\n };\n }\n const parser = new JsonParser(tokens.tokens, input);\n const parseResult = parser.parseValueOrSkip();\n parser.expectEnd();\n\n return {\n value: parseResult,\n errors: parser.errors,\n edits: parser.edits,\n };\n}\n\ninterface JsonToken {\n segment: Segment;\n jsonCode: string;\n}\n\ninterface JsonTokens {\n kind: \"tokens\";\n tokens: JsonToken[];\n}\n\nfunction tokenize(input: string): JsonTokens | JsonError {\n const tokens: JsonToken[] = [];\n let pos = 0;\n\n const whitespaceRegex = /[ \\t\\r\\n]*/y;\n const tokenRegex =\n /([[\\]{}:,]|(-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)|false|true|null|(\"(((?=\\\\)\\\\([\"\\\\/ bfnrt]|u[0-9a-fA-F]{4}))|[^\"\\\\\\0-\\x1F\\x7F]+)*\")|$)/y;\n\n while (true) {\n whitespaceRegex.lastIndex = pos;\n whitespaceRegex.exec(input);\n pos = whitespaceRegex.lastIndex;\n\n tokenRegex.lastIndex = pos;\n const tokenMatch = tokenRegex.exec(input);\n if (tokenMatch) {\n const tokenText = tokenMatch[0];\n const segment: Segment = {\n start: pos,\n end: pos + tokenText.length,\n };\n const token: JsonToken = { segment, jsonCode: tokenText };\n pos = tokenRegex.lastIndex;\n tokens.push(token);\n if (tokenText === \"\") {\n return {\n kind: \"tokens\",\n tokens: tokens,\n };\n }\n } else {\n // Find the next word boundary using unicode support\n const wordBoundaryRegex = /\\w*/uy;\n wordBoundaryRegex.lastIndex = pos + 1;\n wordBoundaryRegex.exec(input);\n const end = wordBoundaryRegex.lastIndex || pos + 1;\n return {\n kind: \"error\",\n message: \"not a token\",\n segment: { start: pos, end: end },\n };\n }\n }\n}\n\nclass JsonParser {\n constructor(private tokens: JsonToken[], private readonly input: string) {}\n private tokenIndex = 0;\n errors: JsonError[] = [];\n edits: JsonEdit[] = [];\n private indent = \"\";\n\n parseValueOrSkip(): JsonValue | undefined {\n const token = this.peekToken();\n const firstChar = token.jsonCode ? token.jsonCode[0] : \"\";\n\n switch (firstChar) {\n case \"[\":\n return this.parseArray();\n case \"{\":\n return this.parseObject();\n case \"n\":\n this.nextToken();\n return {\n kind: \"literal\",\n firstToken: token.segment,\n segment: token.segment,\n jsonCode: \"null\",\n type: \"null\",\n };\n case \"f\":\n this.nextToken();\n return {\n kind: \"literal\",\n firstToken: token.segment,\n segment: token.segment,\n jsonCode: \"false\",\n type: \"boolean\",\n };\n case \"t\":\n this.nextToken();\n return {\n kind: \"literal\",\n firstToken: token.segment,\n segment: token.segment,\n jsonCode: \"true\",\n type: \"boolean\",\n };\n case '\"':\n this.nextToken();\n return {\n kind: \"literal\",\n firstToken: token.segment,\n segment: token.segment,\n jsonCode: token.jsonCode,\n type: \"string\",\n };\n case \"0\":\n case \"1\":\n case \"2\":\n case \"3\":\n case \"4\":\n case \"5\":\n case \"6\":\n case \"7\":\n case \"8\":\n case \"9\":\n case \"-\":\n this.nextToken();\n return {\n kind: \"literal\",\n firstToken: token.segment,\n segment: token.segment,\n jsonCode: token.jsonCode,\n type: \"number\",\n };\n }\n\n this.errors.push({\n kind: \"error\",\n message: \"expected: value\",\n segment: this.peekToken().segment,\n });\n this.skip();\n return undefined;\n }\n\n private parseArray(): JsonArray {\n const leftBracket = this.nextToken();\n const values: JsonValue[] = [];\n while (true) {\n if (this.peekToken().jsonCode === \"]\") {\n const rightBracket = this.nextToken();\n return {\n kind: \"array\",\n firstToken: leftBracket.segment,\n segment: {\n start: leftBracket.segment.start,\n end: rightBracket.segment.end,\n },\n values,\n };\n }\n if (this.peekToken().jsonCode === \"}\") {\n this.errors.push({\n kind: \"error\",\n message: \"expected: ']'\",\n segment: this.peekToken().segment,\n });\n const wrongBracket = this.nextToken();\n return {\n kind: \"array\",\n firstToken: leftBracket.segment,\n segment: {\n start: leftBracket.segment.start,\n end: wrongBracket.segment.end,\n },\n values,\n };\n }\n if (this.peekToken().jsonCode === \"\") {\n // End of file\n this.expectSymbolOrSkip(\"]\");\n return {\n kind: \"array\",\n firstToken: leftBracket.segment,\n segment: {\n start: leftBracket.segment.start,\n end: this.peekToken().segment.start,\n },\n values,\n };\n }\n const value = this.parseValueOrSkip();\n if (value) {\n values.push(value);\n }\n if (this.peekToken().jsonCode === \",\") {\n const commaToken = this.nextToken();\n // Check if this is a trailing comma\n if (this.peekToken().jsonCode === \"]\") {\n // Trailing comma - add edit to remove it\n this.edits.push({\n segment: commaToken.segment,\n replacement: \"\",\n });\n }\n }\n }\n }\n\n private parseObject(): JsonObject {\n const leftBracket = this.nextToken();\n const keyValues: { [key: string]: JsonKeyValue } = {};\n const allKeys: JsonKey[] = [];\n while (true) {\n if (this.peekToken().jsonCode === \"}\") {\n const rightBracket = this.nextToken();\n return {\n kind: \"object\",\n firstToken: leftBracket.segment,\n segment: {\n start: leftBracket.segment.start,\n end: rightBracket.segment.end,\n },\n keyValues,\n allKeys,\n };\n }\n if (this.peekToken().jsonCode === \"]\") {\n this.errors.push({\n kind: \"error\",\n message: \"expected: ']'\",\n segment: this.peekToken().segment,\n });\n const wrongBracket = this.nextToken();\n return {\n kind: \"object\",\n firstToken: leftBracket.segment,\n segment: {\n start: leftBracket.segment.start,\n end: wrongBracket.segment.end,\n },\n keyValues,\n allKeys,\n };\n }\n if (this.peekToken().jsonCode === \"\") {\n // End of file\n this.expectSymbolOrSkip(\"}\");\n return {\n kind: \"object\",\n firstToken: leftBracket.segment,\n segment: {\n start: leftBracket.segment.start,\n end: this.peekToken().segment.start,\n },\n keyValues,\n allKeys,\n };\n }\n const keyToken = this.peekToken();\n if (!keyToken.jsonCode.startsWith('\"')) {\n this.errors.push({\n kind: \"error\",\n message: \"expected: string\",\n segment: keyToken.segment,\n });\n this.skip();\n // Consume comma if we're stuck at one to avoid infinite loop\n if (this.peekToken().jsonCode === \",\") {\n this.nextToken();\n }\n continue;\n }\n const key = JSON.parse(keyToken.jsonCode) as string;\n allKeys.push({\n key: key,\n keySegment: keyToken.segment,\n });\n this.nextToken();\n if (!this.expectSymbolOrSkip(\":\")) {\n continue;\n }\n if (keyValues[key]) {\n this.errors.push({\n kind: \"error\",\n message: \"duplicate key\",\n segment: keyToken.segment,\n });\n }\n const value = this.parseValueOrSkip();\n if (value) {\n keyValues[key] = {\n keySegment: keyToken.segment,\n key: key,\n value: value,\n };\n }\n if (this.peekToken().jsonCode === \",\") {\n const commaToken = this.nextToken();\n // Check if this is a trailing comma\n if (this.peekToken().jsonCode === \"}\") {\n // Trailing comma - add edit to remove it\n this.edits.push({\n segment: commaToken.segment,\n replacement: \"\",\n });\n }\n }\n }\n }\n\n expectEnd(): void {\n const token = this.nextToken();\n if (token.jsonCode) {\n this.errors.push({\n kind: \"error\",\n message: \"expected: end\",\n segment: this.peekToken().segment,\n });\n }\n }\n\n private nextToken(): JsonToken {\n const result = this.tokens[this.tokenIndex];\n\n // Check the whitespace separator before the current token.\n {\n const previous =\n this.tokenIndex <= 0 ? undefined : this.tokens[this.tokenIndex - 1];\n const separatorSegment: Segment = {\n start: previous ? previous.segment.end : 0,\n end: result.segment.start,\n };\n const actualSeparator = this.input.substring(\n separatorSegment.start,\n separatorSegment.end,\n );\n const expectedSeparator = this.inferWhitespaceSeparator(\n previous?.jsonCode ?? \"\",\n result.jsonCode,\n );\n\n if (actualSeparator !== expectedSeparator.text) {\n this.edits.push({\n segment: separatorSegment,\n replacement: expectedSeparator.text,\n });\n }\n this.indent = expectedSeparator.newIndent ?? this.indent;\n }\n\n ++this.tokenIndex;\n return result;\n }\n\n private inferWhitespaceSeparator(a: string, b: string): WhitespaceSeparator {\n const { indent } = this;\n if (a === \":\") {\n return {\n text: \" \",\n };\n } else if (a === \",\" && b !== \"]\" && b !== \"}\") {\n return {\n text: `\\n${indent}`,\n };\n } else if (/[0-9\"}\\]el]$/.test(a) && /^[0-9\"{[tfn-]/.test(b)) {\n // a is the end of a JSON value and B is the start of a JSON value\n return {\n text: `,\\n${indent}`,\n };\n } else if ((a === \"[\" && b !== \"]\") || (a === \"{\" && b !== \"}\")) {\n const newIndent = indent + INDENT_UNIT;\n return {\n text: `\\n${newIndent}`,\n newIndent: newIndent,\n };\n } else if ((a !== \"[\" && b === \"]\") || (a !== \"{\" && b === \"}\")) {\n const newIndent = indent.replace(INDENT_UNIT, \"\");\n return {\n text: `\\n${newIndent}`,\n newIndent: newIndent,\n };\n } else {\n return {\n text: \"\",\n };\n }\n }\n\n private peekToken(): JsonToken {\n return this.tokens[this.tokenIndex];\n }\n\n private expectSymbolOrSkip(symbol: string): boolean {\n if (this.peekToken().jsonCode !== symbol) {\n this.errors.push({\n kind: \"error\",\n message: `expected: '${symbol}'`,\n segment: this.peekToken().segment,\n });\n this.skip();\n return false;\n }\n this.nextToken();\n return true;\n }\n\n private skip(): void {\n while (true) {\n const tokenJson = this.peekToken().jsonCode;\n if (\n tokenJson === \"\" ||\n tokenJson === \",\" ||\n tokenJson === \"]\" ||\n tokenJson === \"}\" ||\n tokenJson.startsWith('\"')\n ) {\n return;\n } else if (tokenJson === \"[\") {\n this.parseArray();\n } else if (tokenJson === \"{\") {\n this.parseObject();\n } else {\n this.nextToken();\n }\n }\n }\n}\n\n/// Text to insert between two consecutive tokens.\ninterface WhitespaceSeparator {\n /// Matches /(,?)(\\n?)( )*/\n text: string;\n newIndent?: string;\n}\n\nconst INDENT_UNIT = \" \";\n"]}