diff --git a/examples/demo/package.json b/examples/demo/package.json
index 1f24a9e..d0faffa 100644
--- a/examples/demo/package.json
+++ b/examples/demo/package.json
@@ -8,6 +8,7 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4",
+ "@schemastore/schema-catalog": "^0.0.5",
"css-loader": "^6.2.0",
"css-minimizer-webpack-plugin": "^3.0.2",
"html-webpack-plugin": "^5.3.2",
diff --git a/examples/demo/src/index.css b/examples/demo/src/index.css
index b9a8879..5670402 100644
--- a/examples/demo/src/index.css
+++ b/examples/demo/src/index.css
@@ -59,6 +59,14 @@ nav {
margin: 1.5rem;
}
+#schema-selection {
+ background-color: var(--editor-background);
+ border: none;
+ border-bottom: 1px solid var(--shadow-color);
+ color: var(--foreground-color);
+ width: 100%;
+}
+
#breadcrumbs {
border-bottom: 1px solid var(--shadow-color);
color: var(--foreground-color);
diff --git a/examples/demo/src/index.ejs b/examples/demo/src/index.ejs
index b0c847f..ae4d37e 100644
--- a/examples/demo/src/index.ejs
+++ b/examples/demo/src/index.ejs
@@ -24,6 +24,11 @@
+
+
+
diff --git a/examples/demo/src/index.ts b/examples/demo/src/index.ts
index 888c0a8..3f3ab27 100644
--- a/examples/demo/src/index.ts
+++ b/examples/demo/src/index.ts
@@ -1,5 +1,6 @@
import './index.css';
+import { JSONSchemaForSchemaStoreOrgCatalogFiles } from '@schemastore/schema-catalog';
import { CancellationToken } from 'monaco-editor/esm/vs/base/common/cancellation';
import { getDocumentSymbols } from 'monaco-editor/esm/vs/editor/contrib/documentSymbols/documentSymbols';
import {
@@ -8,13 +9,16 @@ import {
languages,
Position,
Range,
+ Uri,
} from 'monaco-editor/esm/vs/editor/editor.api';
-import { setDiagnosticsOptions } from 'monaco-yaml';
+import { SchemasSettings, setDiagnosticsOptions } from 'monaco-yaml';
// NOTE: This will give you all editor featues. If you would prefer to limit to only the editor
// features you want to use, import them each individually. See this example: (https://github.com/microsoft/monaco-editor-samples/blob/main/browser-esm-webpack-small/index.js#L1-L91)
import 'monaco-editor';
+import defaultSchemaUri from './schema.json';
+
declare global {
interface Window {
MonacoEnvironment: Environment;
@@ -34,63 +38,18 @@ window.MonacoEnvironment = {
},
};
+const defaultSchema: SchemasSettings = {
+ uri: defaultSchemaUri,
+ fileMatch: ['monaco-yaml.yaml'],
+};
+
setDiagnosticsOptions({
validate: true,
enableSchemaRequest: true,
format: true,
hover: true,
completion: true,
- schemas: [
- {
- // Id of the first schema
- uri: 'https://example.com/example-schema.json',
- // Associate with our model
- fileMatch: ['*'],
- schema: {
- // Id of the first schema
- id: 'https://example.com/example-schema.json',
- type: 'object',
- properties: {
- property: {
- description: 'I have a description',
- },
- titledProperty: {
- title: 'I have a title',
- description: 'I also have a description',
- },
- markdown: {
- markdownDescription: 'Even **markdown** _descriptions_ `are` ~~not~~ supported!',
- },
- enum: {
- description: 'Pick your starter',
- enum: ['Bulbasaur', 'Squirtle', 'Charmander', 'Pikachu'],
- },
- number: {
- description: 'Numbers work!',
- minimum: 42,
- maximum: 1337,
- },
- boolean: {
- description: 'Are boolean supported?',
- type: 'boolean',
- },
- string: {
- type: 'string',
- },
- reference: {
- description: 'JSON schemas can be referenced, even recursively',
- $ref: 'https://example.com/example-schema.json',
- },
- array: {
- description: 'It also works in arrays',
- items: {
- $ref: 'https://example.com/example-schema.json',
- },
- },
- },
- },
- },
- ],
+ schemas: [defaultSchema],
});
const value = `
@@ -152,11 +111,50 @@ formatting: Formatting is supported too! Under the hood this is powered by
const ed = editor.create(document.getElementById('editor'), {
automaticLayout: true,
- value,
- language: 'yaml',
+ model: editor.createModel(value, 'yaml', Uri.parse('monaco-yaml.yaml')),
theme: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'vs-dark' : 'vs-light',
});
+const select = document.getElementById('schema-selection') as HTMLSelectElement;
+
+fetch('https://www.schemastore.org/api/json/catalog.json').then(async (response) => {
+ if (!response.ok) {
+ return;
+ }
+ const catalog: JSONSchemaForSchemaStoreOrgCatalogFiles = await response.json();
+ const schemas = [defaultSchema];
+ catalog.schemas.sort((a, b) => a.name.localeCompare(b.name));
+ for (const { fileMatch, name, url } of catalog.schemas) {
+ const match =
+ typeof name === 'string' && fileMatch?.find((filename) => /\.ya?ml$/i.test(filename));
+ if (!match) {
+ continue;
+ }
+ const option = document.createElement('option');
+ option.value = match;
+
+ option.textContent = name;
+ select.append(option);
+ schemas.push({
+ fileMatch: [match],
+ uri: url,
+ });
+ }
+
+ setDiagnosticsOptions({
+ validate: true,
+ enableSchemaRequest: true,
+ format: true,
+ hover: true,
+ completion: true,
+ schemas,
+ });
+});
+
+select.addEventListener('change', () => {
+ ed.setModel(editor.createModel(ed.getValue(), 'yaml', Uri.parse(select.value)));
+});
+
function* iterateSymbols(
symbols: languages.DocumentSymbol[],
position: Position,
diff --git a/examples/demo/src/schema.json b/examples/demo/src/schema.json
new file mode 100644
index 0000000..38adcdc
--- /dev/null
+++ b/examples/demo/src/schema.json
@@ -0,0 +1,41 @@
+{
+ "type": "object",
+ "properties": {
+ "property": {
+ "description": "I have a description"
+ },
+ "titledProperty": {
+ "title": "I have a title",
+ "description": "I also have a description"
+ },
+ "markdown": {
+ "markdownDescription": "Even **markdown** _descriptions_ `are` ~~not~~ supported!"
+ },
+ "enum": {
+ "description": "Pick your starter",
+ "enum": ["Bulbasaur", "Squirtle", "Charmander", "Pikachu"]
+ },
+ "number": {
+ "description": "Numbers work!",
+ "minimum": 42,
+ "maximum": 1337
+ },
+ "boolean": {
+ "description": "Are boolean supported?",
+ "type": "boolean"
+ },
+ "string": {
+ "type": "string"
+ },
+ "reference": {
+ "description": "JSON schemas can be referenced, even recursively",
+ "$ref": "#"
+ },
+ "array": {
+ "description": "It also works in arrays",
+ "items": {
+ "$ref": "#"
+ }
+ }
+ }
+}
diff --git a/examples/demo/src/types.d.ts b/examples/demo/src/types.d.ts
new file mode 100644
index 0000000..ade23fa
--- /dev/null
+++ b/examples/demo/src/types.d.ts
@@ -0,0 +1,4 @@
+declare module '*.json' {
+ declare const uri;
+ export default uri;
+}
diff --git a/examples/demo/webpack.config.js b/examples/demo/webpack.config.js
index 2aa5c97..bb9816f 100644
--- a/examples/demo/webpack.config.js
+++ b/examples/demo/webpack.config.js
@@ -22,7 +22,11 @@ module.exports = {
{
// Monaco editor uses .ttf icons.
test: /\.(svg|ttf)$/,
- type: 'asset',
+ type: 'asset/resource',
+ },
+ {
+ test: /schema\.json$/,
+ type: 'asset/resource',
},
{
test: /\.ts$/,
diff --git a/index.d.ts b/index.d.ts
index 9f922ed..c40f0e0 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -1,6 +1,29 @@
import { JSONSchema4, JSONSchema6, JSONSchema7 } from 'json-schema';
import { IEvent, languages } from 'monaco-editor/esm/vs/editor/editor.api';
+export interface SchemasSettings {
+ /**
+ * A `Uri` file match which will trigger the schema validation. This may be a glob or an exact
+ * path.
+ *
+ * @example '.gitlab-ci.yml'
+ * @example 'file://**\/.github/actions/*.yaml'
+ */
+ fileMatch: string[];
+
+ /**
+ * The JSON schema which will be used for validation. If not specified, it will be downloaded from
+ * `uri`.
+ */
+ schema?: JSONSchema4 | JSONSchema6 | JSONSchema7;
+
+ /**
+ * The source URI of the JSON schema. The JSON schema will be downloaded from here if no schema
+ * was supplied. It will also be displayed as the source in hover tooltips.
+ */
+ uri: string;
+}
+
declare module 'monaco-editor/esm/vs/editor/editor.api' {
namespace languages.yaml {
export interface DiagnosticsOptions {
@@ -23,21 +46,7 @@ declare module 'monaco-editor/esm/vs/editor/editor.api' {
/**
* A list of known schemas and/or associations of schemas to file names.
*/
- readonly schemas?: {
- /**
- * The URI of the schema, which is also the identifier of the schema.
- */
- readonly uri: string;
- /**
- * A list of file names that are associated to the schema. The '*' wildcard can be used.
- * For example '*.schema.json', 'package.json'
- */
- readonly fileMatch?: string[];
- /**
- * The schema for the given URI.
- */
- readonly schema?: JSONSchema4 | JSONSchema6 | JSONSchema7;
- }[];
+ readonly schemas?: SchemasSettings[];
/**
* If set, the schema service would load schema content on-demand with 'fetch' if available
diff --git a/package-lock.json b/package-lock.json
index a92d4c9..ceb1a75 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -42,6 +42,7 @@
"version": "1.0.0",
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4",
+ "@schemastore/schema-catalog": "^0.0.5",
"css-loader": "^6.2.0",
"css-minimizer-webpack-plugin": "^3.0.2",
"html-webpack-plugin": "^5.3.2",
@@ -690,6 +691,11 @@
"node": ">= 8"
}
},
+ "node_modules/@schemastore/schema-catalog": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/@schemastore/schema-catalog/-/schema-catalog-0.0.5.tgz",
+ "integrity": "sha512-5+Xo5tNdgdQ6Q2otY3XSs1WZR8J1cYHAmGDDHbCk0C3Qx/ycD6r2Fpzz0X9UFjm/hsbZDBd9fh/xLqdIKzREew=="
+ },
"node_modules/@trysound/sax": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.1.1.tgz",
@@ -11590,6 +11596,11 @@
"fastq": "^1.6.0"
}
},
+ "@schemastore/schema-catalog": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/@schemastore/schema-catalog/-/schema-catalog-0.0.5.tgz",
+ "integrity": "sha512-5+Xo5tNdgdQ6Q2otY3XSs1WZR8J1cYHAmGDDHbCk0C3Qx/ycD6r2Fpzz0X9UFjm/hsbZDBd9fh/xLqdIKzREew=="
+ },
"@trysound/sax": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.1.1.tgz",
@@ -13368,6 +13379,7 @@
"version": "file:examples/demo",
"requires": {
"@fortawesome/fontawesome-free": "^5.15.4",
+ "@schemastore/schema-catalog": "*",
"css-loader": "^6.2.0",
"css-minimizer-webpack-plugin": "^3.0.2",
"html-webpack-plugin": "^5.3.2",
@@ -16139,7 +16151,7 @@
"monaco-editor": "^0.27.0",
"path-browserify": "^1.0.1",
"prettier": "2.0.5",
- "type-fest": "*",
+ "type-fest": "^2.1.0",
"typescript": "^4.3.5",
"vscode-languageserver-textdocument": "^1.0.1",
"vscode-languageserver-types": "^3.16.0",
@@ -16649,6 +16661,11 @@
"fastq": "^1.6.0"
}
},
+ "@schemastore/schema-catalog": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/@schemastore/schema-catalog/-/schema-catalog-0.0.5.tgz",
+ "integrity": "sha512-5+Xo5tNdgdQ6Q2otY3XSs1WZR8J1cYHAmGDDHbCk0C3Qx/ycD6r2Fpzz0X9UFjm/hsbZDBd9fh/xLqdIKzREew=="
+ },
"@trysound/sax": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.1.1.tgz",
@@ -18427,6 +18444,7 @@
"version": "file:examples/demo",
"requires": {
"@fortawesome/fontawesome-free": "^5.15.4",
+ "@schemastore/schema-catalog": "*",
"css-loader": "^6.2.0",
"css-minimizer-webpack-plugin": "^3.0.2",
"html-webpack-plugin": "^5.3.2",