From 7d47a8dc327b2532081d6a02c43188456c864a38 Mon Sep 17 00:00:00 2001 From: "Charles-P. Clermont" Date: Fri, 6 Dec 2024 09:26:58 -0500 Subject: [PATCH] Add AST support of JSONC (for theme check, language features, etc.) - Rip out `json-to-ast` - Inline the `json-to-ast` types in `theme-check-common/src/jsonc` - Make a little `jsonc-parser#Node` -> `json-to-ast#ASTNode` adapter Fixes #654 --- .changeset/witty-chairs-kneel.md | 5 + ThirdPartyNotices.txt | 25 ++++ packages/theme-check-common/package.json | 2 - .../src/checks/liquid-free-settings/index.ts | 9 +- .../src/checks/matching-translations/index.ts | 2 +- .../schema-presets-block-order/index.ts | 12 +- .../checks/valid-block-target/block-utils.ts | 11 +- .../src/checks/valid-block-target/index.ts | 2 +- .../checks/valid-html-translation/index.ts | 5 +- .../src/checks/valid-local-blocks/index.ts | 10 +- .../valid-local-blocks/valid-block-utils.ts | 3 +- .../src/checks/valid-schema-name/index.ts | 3 +- .../src/jsonc/parse.spec.ts | 118 +++++++++++++++++ .../theme-check-common/src/jsonc/parse.ts | 121 ++++++++++++++++++ .../theme-check-common/src/jsonc/types.ts | 47 +++++++ .../theme-check-common/src/to-source-code.ts | 8 +- packages/theme-check-common/src/types.ts | 34 +++-- yarn.lock | 18 --- 18 files changed, 373 insertions(+), 62 deletions(-) create mode 100644 .changeset/witty-chairs-kneel.md create mode 100644 packages/theme-check-common/src/jsonc/parse.spec.ts create mode 100644 packages/theme-check-common/src/jsonc/parse.ts create mode 100644 packages/theme-check-common/src/jsonc/types.ts diff --git a/.changeset/witty-chairs-kneel.md b/.changeset/witty-chairs-kneel.md new file mode 100644 index 000000000..7eeeb9e82 --- /dev/null +++ b/.changeset/witty-chairs-kneel.md @@ -0,0 +1,5 @@ +--- +'@shopify/theme-check-common': minor +--- + +[Internal] Add JSONC support to the AST parser diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index dcaf7f380..d9f09bb75 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -7,6 +7,7 @@ The theme-language-server project incorporates third party material from the pro 3. @lezer/json (https://github.com/lezer-parser/json) 4. @codemirror/lang-json (https://github.com/codemirror/lang-json) 5. monaco-editor (https://github.com/microsoft/monaco-editor) +6. json-to-ast (https://github.com/vtrushin/json-to-ast) %% vscode-languageserver-node NOTICES, INFORMATION, AND LICENSE BEGIN HERE ========================================= @@ -133,3 +134,27 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF monaco-editor NOTICES, INFORMATION, AND LICENSE + +%% json-to-ast NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright (C) 2016 by Vlad Trushin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +========================================= +END OF json-to-ast NOTICES, INFORMATION, AND LICENSE diff --git a/packages/theme-check-common/package.json b/packages/theme-check-common/package.json index 4d5bd30ee..15e018bbc 100644 --- a/packages/theme-check-common/package.json +++ b/packages/theme-check-common/package.json @@ -28,7 +28,6 @@ "dependencies": { "@shopify/liquid-html-parser": "2.1.2", "cross-fetch": "^4.0.0", - "json-to-ast": "^2.1.0", "jsonc-parser": "^3.2.0", "line-column": "^1.0.2", "lodash-es": "^4.17.21", @@ -37,7 +36,6 @@ "vscode-uri": "^3.0.7" }, "devDependencies": { - "@types/json-to-ast": "^2.1.2", "@types/line-column": "^1.0.0", "@types/lodash-es": "^4.17.12" } diff --git a/packages/theme-check-common/src/checks/liquid-free-settings/index.ts b/packages/theme-check-common/src/checks/liquid-free-settings/index.ts index cce9030b6..916cafa22 100644 --- a/packages/theme-check-common/src/checks/liquid-free-settings/index.ts +++ b/packages/theme-check-common/src/checks/liquid-free-settings/index.ts @@ -1,7 +1,12 @@ -import { JSONNode, LiquidCheckDefinition, Severity, SourceCodeType } from '../../types'; import { toJSONAST } from '../../to-source-code'; +import { + JSONNode, + LiquidCheckDefinition, + LiteralNode, + Severity, + SourceCodeType, +} from '../../types'; import { visit } from '../../visitor'; -import { LiteralNode } from 'json-to-ast'; export const LiquidFreeSettings: LiquidCheckDefinition = { meta: { diff --git a/packages/theme-check-common/src/checks/matching-translations/index.ts b/packages/theme-check-common/src/checks/matching-translations/index.ts index b7678da2f..b43054fe1 100644 --- a/packages/theme-check-common/src/checks/matching-translations/index.ts +++ b/packages/theme-check-common/src/checks/matching-translations/index.ts @@ -1,10 +1,10 @@ -import { PropertyNode } from 'json-to-ast'; import { JSONCheckDefinition, JSONNode, JSONSourceCode, Severity, SourceCodeType, + PropertyNode, } from '../../types'; const PLURALIZATION_KEYS = new Set(['zero', 'one', 'two', 'few', 'many', 'other']); diff --git a/packages/theme-check-common/src/checks/schema-presets-block-order/index.ts b/packages/theme-check-common/src/checks/schema-presets-block-order/index.ts index c1d25bff1..d082e1bfe 100644 --- a/packages/theme-check-common/src/checks/schema-presets-block-order/index.ts +++ b/packages/theme-check-common/src/checks/schema-presets-block-order/index.ts @@ -1,11 +1,15 @@ -import { ArrayNode } from 'json-to-ast'; import { getLocEnd, getLocStart, nodeAtPath } from '../../json'; import { basename } from '../../path'; import { isBlock, isSection } from '../../to-schema'; -import { JSONNode, LiquidCheckDefinition, Severity, SourceCodeType } from '../../types'; +import { + ArrayNode, + Context, + JSONNode, + LiquidCheckDefinition, + Severity, + SourceCodeType, +} from '../../types'; import { Preset } from '../../types/schemas/preset'; -import { ThemeBlock } from '../../types/schemas/theme-block'; -import { Context } from '../../types'; export const SchemaPresetsBlockOrder: LiquidCheckDefinition = { meta: { diff --git a/packages/theme-check-common/src/checks/valid-block-target/block-utils.ts b/packages/theme-check-common/src/checks/valid-block-target/block-utils.ts index 55e8e6887..8826aa41f 100644 --- a/packages/theme-check-common/src/checks/valid-block-target/block-utils.ts +++ b/packages/theme-check-common/src/checks/valid-block-target/block-utils.ts @@ -1,5 +1,12 @@ -import { JSONNode, Preset, Section, SourceCodeType, Theme, ThemeBlock } from '../../types'; -import { LiteralNode } from 'json-to-ast'; +import { + JSONNode, + LiteralNode, + Preset, + Section, + SourceCodeType, + Theme, + ThemeBlock, +} from '../../types'; import { getLocEnd, getLocStart, nodeAtPath } from '../../json'; import { Context } from '../../types'; import { doesFileExist } from '../../utils/file-utils'; diff --git a/packages/theme-check-common/src/checks/valid-block-target/index.ts b/packages/theme-check-common/src/checks/valid-block-target/index.ts index 144ae2aae..5f3aeb15e 100644 --- a/packages/theme-check-common/src/checks/valid-block-target/index.ts +++ b/packages/theme-check-common/src/checks/valid-block-target/index.ts @@ -5,8 +5,8 @@ import { Preset, Section, ThemeBlock, + LiteralNode, } from '../../types'; -import { LiteralNode } from 'json-to-ast'; import { nodeAtPath } from '../../json'; import { getSchema } from '../../to-schema'; import { diff --git a/packages/theme-check-common/src/checks/valid-html-translation/index.ts b/packages/theme-check-common/src/checks/valid-html-translation/index.ts index b3919d1af..622af32b2 100644 --- a/packages/theme-check-common/src/checks/valid-html-translation/index.ts +++ b/packages/theme-check-common/src/checks/valid-html-translation/index.ts @@ -1,6 +1,5 @@ -import { SourceCodeType, JSONCheckDefinition, Severity, Problem, JSONNode } from '../../types'; +import { SourceCodeType, JSONCheckDefinition, Severity, Problem, LiteralNode } from '../../types'; import { toLiquidHtmlAST } from '@shopify/liquid-html-parser'; -import { Location, LiteralNode } from 'json-to-ast'; export const ValidHTMLTranslation: JSONCheckDefinition = { meta: { @@ -31,7 +30,7 @@ export const ValidHTMLTranslation: JSONCheckDefinition = { try { toLiquidHtmlAST(node.value); } catch (error) { - const loc = node.loc as Location; + const loc = node.loc; const problem: Problem = { message: `${error}.`, diff --git a/packages/theme-check-common/src/checks/valid-local-blocks/index.ts b/packages/theme-check-common/src/checks/valid-local-blocks/index.ts index 5f15764b4..b2ef48123 100644 --- a/packages/theme-check-common/src/checks/valid-local-blocks/index.ts +++ b/packages/theme-check-common/src/checks/valid-local-blocks/index.ts @@ -1,5 +1,11 @@ -import { LiquidCheckDefinition, Preset, Severity, SourceCodeType, Section } from '../../types'; -import { LiteralNode } from 'json-to-ast'; +import { + LiquidCheckDefinition, + Preset, + Severity, + SourceCodeType, + Section, + LiteralNode, +} from '../../types'; import { nodeAtPath } from '../../json'; import { getSchema } from '../../to-schema'; import { isBlock, isSection } from '../../to-schema'; diff --git a/packages/theme-check-common/src/checks/valid-local-blocks/valid-block-utils.ts b/packages/theme-check-common/src/checks/valid-local-blocks/valid-block-utils.ts index c4b7a3e8e..30407332e 100644 --- a/packages/theme-check-common/src/checks/valid-local-blocks/valid-block-utils.ts +++ b/packages/theme-check-common/src/checks/valid-local-blocks/valid-block-utils.ts @@ -1,6 +1,5 @@ -import { LiteralNode } from 'json-to-ast'; import { getLocEnd, getLocStart } from '../../json'; -import { Preset, ThemeBlock, Section, Context, SourceCodeType } from '../../types'; +import { Preset, ThemeBlock, Section, Context, SourceCodeType, LiteralNode } from '../../types'; type BlockNodeWithPath = { node: Section.Block | ThemeBlock.Block | Preset.Block; diff --git a/packages/theme-check-common/src/checks/valid-schema-name/index.ts b/packages/theme-check-common/src/checks/valid-schema-name/index.ts index ea19565aa..714cd43ec 100644 --- a/packages/theme-check-common/src/checks/valid-schema-name/index.ts +++ b/packages/theme-check-common/src/checks/valid-schema-name/index.ts @@ -1,7 +1,6 @@ -import { LiteralNode } from 'json-to-ast'; import { getLocEnd, getLocStart, nodeAtPath } from '../../json'; import { getSchema } from '../../to-schema'; -import { LiquidCheckDefinition, Severity, SourceCodeType } from '../../types'; +import { LiquidCheckDefinition, LiteralNode, Severity, SourceCodeType } from '../../types'; import { deepGet } from '../../utils'; const MAX_SCHEMA_NAME_LENGTH = 25; diff --git a/packages/theme-check-common/src/jsonc/parse.spec.ts b/packages/theme-check-common/src/jsonc/parse.spec.ts new file mode 100644 index 000000000..df3b62a98 --- /dev/null +++ b/packages/theme-check-common/src/jsonc/parse.spec.ts @@ -0,0 +1,118 @@ +import { describe, expect, it } from 'vitest'; +import { toJSONNode, location } from './parse'; + +describe('module: toJSONNode', () => { + it('should parse basic key-value pairs', () => { + // 0123456789012345 + const ast = toJSONNode(`{"key": "value"}`); + expect(ast).toEqual({ + type: 'Object', + loc: location(0, 16), + children: [ + { + type: 'Property', + loc: location(1, 15), + key: { + type: 'Identifier', + value: 'key', + raw: '"key"', + loc: location(1, 6), + }, + value: { + type: 'Literal', + value: 'value', + raw: '"value"', + loc: location(8, 15), + }, + }, + ], + }); + }); + + it('should parse basic array of literals', () => { + // 0123456789012345678901234 + const ast = toJSONNode(`["one", true, null, 10]`); + expect(ast).toEqual({ + type: 'Array', + loc: location(0, 23), + children: [ + { + type: 'Literal', + value: 'one', + raw: '"one"', + loc: location(1, 6), + }, + { + type: 'Literal', + value: true, + raw: 'true', + loc: location(8, 12), + }, + { + type: 'Literal', + value: null, + raw: 'null', + loc: location(14, 18), + }, + { + type: 'Literal', + value: 10, + raw: '10', + loc: location(20, 22), + }, + ], + }); + }); + + it('should not break on block comments', () => { + // 01234567890123456789012 + const ast = toJSONNode(`/** block comment */10`); + expect(ast).toEqual({ + type: 'Literal', + value: 10, + raw: '10', + loc: location(20, 22), + }); + }); + + it('should not break on line comments', () => { + const source = `// line comment +10`; + const ast = toJSONNode(source); + expect(ast).toEqual({ + type: 'Literal', + value: 10, + raw: '10', + loc: location(source.indexOf('10'), source.indexOf('10') + 2), + }); + }); + + it('should not break on trailing commas', () => { + const source = `{ + "key": "value", + }`; + const ast = toJSONNode(source); + expect(ast).toEqual({ + type: 'Object', + loc: location(0, source.length), + children: [ + { + type: 'Property', + loc: location(source.indexOf('"key"'), source.indexOf('"value"') + '"value"'.length), + key: { + type: 'Identifier', + value: 'key', + raw: '"key"', + loc: expect.anything(), + }, + value: { + type: 'Literal', + value: 'value', + raw: '"value"', + loc: expect.anything(), + }, + }, + ], + }); + }); +}); diff --git a/packages/theme-check-common/src/jsonc/parse.ts b/packages/theme-check-common/src/jsonc/parse.ts new file mode 100644 index 000000000..3df559905 --- /dev/null +++ b/packages/theme-check-common/src/jsonc/parse.ts @@ -0,0 +1,121 @@ +import { assertNever } from '../utils'; +import { + ArrayNode, + IdentifierNode, + JSONNode as JSONToASTNode, + LiteralNode, + ObjectNode, + PropertyNode, + ValueNode, +} from './types'; +import { Node as JSONCParserNode, ParseError, parseTree } from 'jsonc-parser'; + +export class JSONCParseErrors extends Error { + public errors: ParseError[]; + + constructor(message: string, errors: ParseError[]) { + super(message); + this.errors = errors; + } +} + +/** + * At some point, we started supporting JSONC. Theme Check 2 was built on top of + * `json-to-ast` which does not support comments. + * + * This little adapter here will take a tree we get from `jsonc-parser` and + * convert it to the shape of `json-to-ast`. + * + * The `json-to-ast` types feel much better to use than the ones from `jsonc-parser` + * and we don't need to rewrite all our downstream code. + */ +export function toJSONNode(source: string): JSONToASTNode { + const errors: ParseError[] = []; + const tree = parseTree(source, errors, { + allowTrailingComma: true, + disallowComments: false, + }); + + if (errors.length || tree === undefined) { + throw new JSONCParseErrors('Failed to parse JSONC', errors); + } + + return jsoncToJsonAst(tree); +} + +function jsoncToJsonAst(node: JSONCParserNode): JSONToASTNode { + switch (node.type) { + case 'object': { + return objectToObjectNode(node); + } + + case 'property': { + return propertyToPropertyNode(node); + } + + case 'array': { + return arrayToArrayNode(node); + } + + case 'boolean': + case 'null': + case 'number': + case 'string': { + return valueToLiteralNode(node); + } + + default: { + assertNever(node.type); + } + } +} + +function objectToObjectNode(node: JSONCParserNode): ObjectNode { + return { + type: 'Object', + children: (node.children ?? []).map(jsoncToJsonAst) as PropertyNode[], + loc: location(node.offset, node.offset + node.length), + }; +} + +function arrayToArrayNode(node: JSONCParserNode): ArrayNode { + return { + type: 'Array', + children: node.children!.map(jsoncToJsonAst) as ValueNode[], + loc: location(node.offset, node.offset + node.length), + }; +} + +function propertyToPropertyNode(node: JSONCParserNode): PropertyNode { + return { + type: 'Property', + key: identifierToIdentifierNode(node.children![0]), + value: jsoncToJsonAst(node.children![1]) as ValueNode, + loc: location(node.offset, node.offset + node.length), + }; +} + +function identifierToIdentifierNode(node: JSONCParserNode): IdentifierNode { + return { + type: 'Identifier', + value: node.value, + raw: JSON.stringify(node.value), + loc: location(node.offset, node.offset + node.length), + }; +} + +function valueToLiteralNode(node: JSONCParserNode): LiteralNode { + return { + type: 'Literal', + value: node.value, + raw: JSON.stringify(node.value), + loc: location(node.offset, node.offset + node.length), + }; +} + +export const location = (start: number, end: number) => ({ + start: position(start), + end: position(end), +}); + +const position = (offset: number) => ({ offset }); diff --git a/packages/theme-check-common/src/jsonc/types.ts b/packages/theme-check-common/src/jsonc/types.ts new file mode 100644 index 000000000..fdf71865a --- /dev/null +++ b/packages/theme-check-common/src/jsonc/types.ts @@ -0,0 +1,47 @@ +// These are the from `@types/json-to-ast` +export type JSONNodeTypes = 'Object' | 'Array' | 'Property' | 'Identifier' | 'Literal'; +export type JSONNode = ArrayNode | IdentifierNode | LiteralNode | ObjectNode | PropertyNode; +export type ValueNode = ObjectNode | ArrayNode | LiteralNode; + +export interface Position { + offset: number; +} + +export interface Location { + start: Position; + end: Position; +} + +export interface ASTNode { + type: string; + // Modified from @types/json-to-ast make this not-optional + loc: Location; +} + +export interface ObjectNode extends ASTNode { + type: 'Object'; + children: PropertyNode[]; +} + +export interface PropertyNode extends ASTNode { + type: 'Property'; + key: IdentifierNode; + value: ValueNode; +} + +export interface IdentifierNode extends ASTNode { + type: 'Identifier'; + value: string; + raw: string; +} + +export interface ArrayNode extends ASTNode { + type: 'Array'; + children: ValueNode[]; +} + +export interface LiteralNode extends ASTNode { + type: 'Literal'; + value: string | number | boolean | null; + raw: string; +} diff --git a/packages/theme-check-common/src/to-source-code.ts b/packages/theme-check-common/src/to-source-code.ts index 9aa655bd4..11bf36c60 100644 --- a/packages/theme-check-common/src/to-source-code.ts +++ b/packages/theme-check-common/src/to-source-code.ts @@ -1,8 +1,8 @@ import { toLiquidHtmlAST } from '@shopify/liquid-html-parser'; -import toJSON from 'json-to-ast'; +import { toJSONNode } from './jsonc/parse'; import * as path from './path'; -import { JSONSourceCode, LiquidSourceCode, SourceCodeType } from './types'; +import { JSONNode, JSONSourceCode, LiquidSourceCode, SourceCodeType } from './types'; import { asError } from './utils/error'; export function toLiquidHTMLAST(source: string) { @@ -13,9 +13,9 @@ export function toLiquidHTMLAST(source: string) { } } -export function toJSONAST(source: string) { +export function toJSONAST(source: string): JSONNode | Error { try { - return toJSON(source); + return toJSONNode(source); } catch (error) { return asError(error); } diff --git a/packages/theme-check-common/src/types.ts b/packages/theme-check-common/src/types.ts index fe7e97f1f..41d12b200 100644 --- a/packages/theme-check-common/src/types.ts +++ b/packages/theme-check-common/src/types.ts @@ -1,23 +1,24 @@ -import { NodeTypes as LiquidHtmlNodeTypes, LiquidHtmlNode } from '@shopify/liquid-html-parser'; +import { LiquidHtmlNode, NodeTypes as LiquidHtmlNodeTypes } from '@shopify/liquid-html-parser'; -import { - ArrayNode, - IdentifierNode, - LiteralNode, - ObjectNode, - PropertyNode, - ASTNode, -} from 'json-to-ast'; import { Schema, Settings } from './types/schema-prop-factory'; -import { StringCorrector, JSONCorrector } from './fixes'; import { AbstractFileSystem, UriString } from './AbstractFileSystem'; +import { JSONCorrector, StringCorrector } from './fixes'; -import { ThemeDocset, JsonValidationSet } from './types/theme-liquid-docs'; -import { AppBlockSchema, ThemeBlockSchema, SectionSchema } from './types/theme-schemas'; +import { + ArrayNode, + ASTNode, + JSONNode, + JSONNodeTypes, + ObjectNode, + PropertyNode, +} from './jsonc/types'; +import { JsonValidationSet, ThemeDocset } from './types/theme-liquid-docs'; +import { AppBlockSchema, SectionSchema, ThemeBlockSchema } from './types/theme-schemas'; -export * from './types/theme-liquid-docs'; +export * from './jsonc/types'; export * from './types/schema-prop-factory'; +export * from './types/theme-liquid-docs'; export * from './types/theme-schemas'; export const isObjectNode = (node?: ASTNode): node is ObjectNode => node?.type === 'Object'; @@ -55,8 +56,7 @@ export type LiquidCheckDefinition = CheckDefinition< >; export type LiquidCheck = Check; -export { LiquidHtmlNodeTypes }; -export { LiquidHtmlNode }; +export { LiquidHtmlNode, LiquidHtmlNodeTypes }; export type JSONSourceCode = SourceCode; export type JSONCheckDefinition = CheckDefinition< @@ -65,10 +65,6 @@ export type JSONCheckDefinition = CheckDefinition< >; export type JSONCheck = Check; -export type JSONNodeTypes = 'Object' | 'Property' | 'Identifier' | 'Array' | 'Literal'; - -export type JSONNode = ArrayNode | IdentifierNode | LiteralNode | ObjectNode | PropertyNode; - // AST[SourceCodeType.LiquidHtml] maps to LiquidHtmlNode export type AST = { [T in SourceCodeType]: { diff --git a/yarn.lock b/yarn.lock index e9ec72a98..ede475eb7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -886,11 +886,6 @@ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz" integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== -"@types/json-to-ast@^2.1.2": - version "2.1.2" - resolved "https://registry.npmjs.org/@types/json-to-ast/-/json-to-ast-2.1.2.tgz" - integrity sha512-GEjR5l9wZGS74KhL1a1tZuyRJqdLB7LGgOXzWspJx9xxC/iyCFTwwKv71Lz8fzZyGuVW8FjASQGoYFi6XZJWLQ== - "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" @@ -2058,11 +2053,6 @@ co@^4.6.0: resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== -code-error-fragment@0.0.230: - version "0.0.230" - resolved "https://registry.npmjs.org/code-error-fragment/-/code-error-fragment-0.0.230.tgz" - integrity sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw== - codemirror@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.1.tgz#62b91142d45904547ee3e0e0e4c1a79158035a29" @@ -4129,14 +4119,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-to-ast@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/json-to-ast/-/json-to-ast-2.1.0.tgz" - integrity sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ== - dependencies: - code-error-fragment "0.0.230" - grapheme-splitter "^1.0.4" - json5@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz"