mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 00:58:32 +02:00
Support comments in JSON body (#419)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,7 @@ export interface EditorProps {
|
||||
hideGutter?: boolean;
|
||||
id?: string;
|
||||
language?: EditorLanguage | 'pairs' | 'url' | 'timeline' | null;
|
||||
lintExtension?: Extension;
|
||||
graphQLSchema?: GraphQLSchema | null;
|
||||
onBlur?: () => void;
|
||||
onChange?: (value: string) => void;
|
||||
@@ -124,6 +125,7 @@ function EditorInner({
|
||||
hideGutter,
|
||||
graphQLSchema,
|
||||
language,
|
||||
lintExtension,
|
||||
onBlur,
|
||||
onChange,
|
||||
onFocus,
|
||||
@@ -332,6 +334,7 @@ function EditorInner({
|
||||
const ext = getLanguageExtension({
|
||||
useTemplating,
|
||||
language,
|
||||
lintExtension,
|
||||
hideGutter,
|
||||
environmentVariables,
|
||||
autocomplete,
|
||||
@@ -344,6 +347,7 @@ function EditorInner({
|
||||
view.dispatch({ effects: languageCompartment.reconfigure(ext) });
|
||||
}, [
|
||||
language,
|
||||
lintExtension,
|
||||
autocomplete,
|
||||
environmentVariables,
|
||||
onClickFunction,
|
||||
@@ -371,6 +375,7 @@ function EditorInner({
|
||||
const langExt = getLanguageExtension({
|
||||
useTemplating,
|
||||
language,
|
||||
lintExtension,
|
||||
completionOptions,
|
||||
autocomplete,
|
||||
environmentVariables,
|
||||
|
||||
@@ -8,7 +8,6 @@ import { history, historyKeymap } from '@codemirror/commands';
|
||||
import { go } from '@codemirror/lang-go';
|
||||
import { java } from '@codemirror/lang-java';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { json } from '@codemirror/lang-json';
|
||||
import { markdown } from '@codemirror/lang-markdown';
|
||||
import { php } from '@codemirror/lang-php';
|
||||
import { python } from '@codemirror/lang-python';
|
||||
@@ -34,7 +33,6 @@ import { ruby } from '@codemirror/legacy-modes/mode/ruby';
|
||||
import { shell } from '@codemirror/legacy-modes/mode/shell';
|
||||
import { swift } from '@codemirror/legacy-modes/mode/swift';
|
||||
import { linter, lintGutter, lintKeymap } from '@codemirror/lint';
|
||||
|
||||
import { search, searchKeymap } from '@codemirror/search';
|
||||
import type { Extension } from '@codemirror/state';
|
||||
import { EditorState } from '@codemirror/state';
|
||||
@@ -50,6 +48,7 @@ import {
|
||||
rectangularSelection,
|
||||
} from '@codemirror/view';
|
||||
import { tags as t } from '@lezer/highlight';
|
||||
import { jsonc, jsoncLanguage } from '@shopify/lang-jsonc';
|
||||
import { graphql } from 'cm6-graphql';
|
||||
import type { GraphQLSchema } from 'graphql';
|
||||
import { activeRequestIdAtom } from '../../../hooks/useActiveRequestId';
|
||||
@@ -61,13 +60,13 @@ import { showGraphQLDocExplorerAtom } from '../../graphql/graphqlAtoms';
|
||||
import type { EditorProps } from './Editor';
|
||||
import { jsonParseLinter } from './json-lint';
|
||||
import { pairs } from './pairs/extension';
|
||||
import { searchMatchCount } from './searchMatchCount';
|
||||
import { text } from './text/extension';
|
||||
import { timeline } from './timeline/extension';
|
||||
import type { TwigCompletionOption } from './twig/completion';
|
||||
import { twig } from './twig/extension';
|
||||
import { pathParametersPlugin } from './twig/pathParameters';
|
||||
import { url } from './url/extension';
|
||||
import { searchMatchCount } from './searchMatchCount';
|
||||
|
||||
export const syntaxHighlightStyle = HighlightStyle.define([
|
||||
{
|
||||
@@ -107,7 +106,7 @@ const syntaxExtensions: Record<
|
||||
null | (() => LanguageSupport)
|
||||
> = {
|
||||
graphql: null,
|
||||
json: json,
|
||||
json: jsonc,
|
||||
javascript: javascript,
|
||||
// HTML as XML because HTML is oddly slow
|
||||
html: xml,
|
||||
@@ -140,6 +139,7 @@ const closeBracketsFor: (keyof typeof syntaxExtensions)[] = ['json', 'javascript
|
||||
export function getLanguageExtension({
|
||||
useTemplating,
|
||||
language = 'text',
|
||||
lintExtension,
|
||||
environmentVariables,
|
||||
autocomplete,
|
||||
hideGutter,
|
||||
@@ -156,7 +156,7 @@ export function getLanguageExtension({
|
||||
onClickPathParameter: (name: string) => void;
|
||||
completionOptions: TwigCompletionOption[];
|
||||
graphQLSchema: GraphQLSchema | null;
|
||||
} & Pick<EditorProps, 'language' | 'autocomplete' | 'hideGutter'>) {
|
||||
} & Pick<EditorProps, 'language' | 'autocomplete' | 'hideGutter' | 'lintExtension'>) {
|
||||
const extraExtensions: Extension[] = [];
|
||||
|
||||
if (language === 'url') {
|
||||
@@ -193,7 +193,12 @@ export function getLanguageExtension({
|
||||
}
|
||||
|
||||
if (language === 'json') {
|
||||
extraExtensions.push(linter(jsonParseLinter()));
|
||||
extraExtensions.push(lintExtension ?? linter(jsonParseLinter()));
|
||||
extraExtensions.push(
|
||||
jsoncLanguage.data.of({
|
||||
commentTokens: { line: '//', block: { open: '/*', close: '*/' } },
|
||||
}),
|
||||
);
|
||||
if (!hideGutter) {
|
||||
extraExtensions.push(lintGutter());
|
||||
}
|
||||
|
||||
@@ -4,14 +4,22 @@ import { parse as jsonLintParse } from '@prantlf/jsonlint';
|
||||
|
||||
const TEMPLATE_SYNTAX_REGEX = /\$\{\[[\s\S]*?]}/g;
|
||||
|
||||
export function jsonParseLinter() {
|
||||
interface JsonLintOptions {
|
||||
allowComments?: boolean;
|
||||
allowTrailingCommas?: boolean;
|
||||
}
|
||||
|
||||
export function jsonParseLinter(options?: JsonLintOptions) {
|
||||
return (view: EditorView): Diagnostic[] => {
|
||||
try {
|
||||
const doc = view.state.doc.toString();
|
||||
// We need lint to not break on stuff like {"foo:" ${[ ... ]}} so we'll replace all template
|
||||
// syntax with repeating `1` characters, so it's valid JSON and the position is still correct.
|
||||
const escapedDoc = doc.replace(TEMPLATE_SYNTAX_REGEX, (m) => '1'.repeat(m.length));
|
||||
jsonLintParse(escapedDoc);
|
||||
jsonLintParse(escapedDoc, {
|
||||
mode: (options?.allowComments ?? true) ? 'cjson' : 'json',
|
||||
ignoreTrailingCommas: options?.allowTrailingCommas ?? false,
|
||||
});
|
||||
// biome-ignore lint/suspicious/noExplicitAny: none
|
||||
} catch (err: any) {
|
||||
if (!('location' in err)) {
|
||||
|
||||
Reference in New Issue
Block a user