You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
64 lines
1.8 KiB
64 lines
1.8 KiB
import { parser } from '@lezer/json'; |
|
import { LRLanguage, indentNodeProp, continuedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language'; |
|
|
|
/** |
|
Calls |
|
[`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) |
|
on the document and, if that throws an error, reports it as a |
|
single diagnostic. |
|
*/ |
|
const jsonParseLinter = () => (view) => { |
|
try { |
|
JSON.parse(view.state.doc.toString()); |
|
} |
|
catch (e) { |
|
if (!(e instanceof SyntaxError)) |
|
throw e; |
|
const pos = getErrorPosition(e, view.state.doc); |
|
return [{ |
|
from: pos, |
|
message: e.message, |
|
severity: 'error', |
|
to: pos |
|
}]; |
|
} |
|
return []; |
|
}; |
|
function getErrorPosition(error, doc) { |
|
let m; |
|
if (m = error.message.match(/at position (\d+)/)) |
|
return Math.min(+m[1], doc.length); |
|
if (m = error.message.match(/at line (\d+) column (\d+)/)) |
|
return Math.min(doc.line(+m[1]).from + (+m[2]) - 1, doc.length); |
|
return 0; |
|
} |
|
|
|
/** |
|
A language provider that provides JSON parsing. |
|
*/ |
|
const jsonLanguage = /*@__PURE__*/LRLanguage.define({ |
|
name: "json", |
|
parser: /*@__PURE__*/parser.configure({ |
|
props: [ |
|
/*@__PURE__*/indentNodeProp.add({ |
|
Object: /*@__PURE__*/continuedIndent({ except: /^\s*\}/ }), |
|
Array: /*@__PURE__*/continuedIndent({ except: /^\s*\]/ }) |
|
}), |
|
/*@__PURE__*/foldNodeProp.add({ |
|
"Object Array": foldInside |
|
}) |
|
] |
|
}), |
|
languageData: { |
|
closeBrackets: { brackets: ["[", "{", '"'] }, |
|
indentOnInput: /^\s*[\}\]]$/ |
|
} |
|
}); |
|
/** |
|
JSON language support. |
|
*/ |
|
function json() { |
|
return new LanguageSupport(jsonLanguage); |
|
} |
|
|
|
export { json, jsonLanguage, jsonParseLinter };
|
|
|