diff --git a/.gitignore b/.gitignore index 2e095e84..6504043b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,4 @@ /public/ -/hugo/resources/ -/hugo/static/css/ -hugo/static/libs -hugo/static/showcase/ -hugo/static/libs/ -hugo/static/playground/ node_modules/ .DS_Store .hugo_build.lock diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..abee2eef --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible Node.js debug attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome", + "url": "http://localhost:1313", + "webRoot": "${workspaceFolder}" + } + ] +} diff --git a/README.md b/README.md index bd1fb42d..764e68e8 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This repository contains the assets required to build the Langium website and do Our setup uses TailwindCSS to build the styles which are then copied into the Hugo installation, from which our website is finally built. -Please look into the sub folders [hugo/](hugo/README.md) and [tailwind/](tailwind/README.md). +Please look into the sub folders [core/](core/README.md) [hugo/](hugo/README.md) and [tailwind/](tailwind/README.md). You can find the `showcase/` folder [here](hugo/content/showcase). diff --git a/core/.gitignore b/core/.gitignore new file mode 100644 index 00000000..b6291f30 --- /dev/null +++ b/core/.gitignore @@ -0,0 +1,2 @@ +bundle/ +dist/ diff --git a/core/README.md b/core/README.md new file mode 100644 index 00000000..4a6fed62 --- /dev/null +++ b/core/README.md @@ -0,0 +1,5 @@ +# core/ + +We utilize [monaco-editor-wrapper](https://www.npmjs.com/package/monaco-editor-wrapper) and [@typefox/monaco-editor-react](https://www.npmjs.com/package/@typefox/monaco-editor-react) to make the monaco-editor intgration a smoother experience. + +This package provides utility `createUserConfig` that provides a fully specified user configuration to be used by either of the two packages. The other purpose is to bundle the code, so it can be integrated with hugo and remove the burden dealing with complex javascript in the hugo build process. diff --git a/core/package.json b/core/package.json new file mode 100644 index 00000000..bcc0ab3a --- /dev/null +++ b/core/package.json @@ -0,0 +1,67 @@ +{ + "name": "langium-website-core", + "version": "1.0.0", + "type": "module", + "description": "Bundling complex sources for hugo", + "author": "TypeFox", + "license": "MIT", + "private": true, + "main": "./dist/index.js", + "module": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./bundle": { + "types": "./dist/index.d.ts", + "default": "./bundle/monaco-editor-wrapper-bundle/index.js" + } + }, + "typesVersions": { + "*": { + ".": [ + "dist/index" + ], + "bundle": [ + "dist/index" + ] + } + }, + "files": [ + "dist", + "bundle", + "src", + "LICENSE", + "README.md" + ], + "scripts": { + "clean": "shx rm -rf ./bundle ./dist", + "compile": "tsc", + "build:bundle": "vite --config vite.bundle.ts build", + "build": "npm run clean && npm run compile && npm run build:bundle" + }, + "devDependencies": { + "@types/react": "~18.2.28", + "@types/react-dom": "~18.2.13", + "@types/vscode": "~1.83.0", + "typescript": "~5.2.2", + "vite": "~4.4.11" + }, + "dependencies": { + "@codingame/monaco-vscode-keybindings-service-override": "~1.83.2", + "@typefox/monaco-editor-react": "2.3.0", + "monaco-editor": "~0.44.0", + "monaco-editor-workers": "~0.44.0", + "monaco-editor-wrapper": "~3.3.0", + "monaco-languageclient": "~6.6.0", + "react": "~18.2.0", + "react-dom": "~18.2.0", + "vscode": "npm:@codingame/monaco-vscode-api@>=1.83.2 <1.84.0", + "vscode-languageserver": "~8.0.2" + }, + "volta": { + "node": "18.18.1", + "npm": "9.9.0" + } +} diff --git a/core/src/index.ts b/core/src/index.ts new file mode 100644 index 00000000..151921cf --- /dev/null +++ b/core/src/index.ts @@ -0,0 +1,17 @@ +import * as monaco from "monaco-editor"; +import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-service-override'; +import type { MonacoEditorProps } from "@typefox/monaco-editor-react"; +import { MonacoEditorReactComp } from "@typefox/monaco-editor-react"; +import { addMonacoStyles } from 'monaco-editor-wrapper/styles'; + +export * from "monaco-editor-wrapper"; +export type * from "monaco-editor-wrapper"; +export * from "./monaco-editor-wrapper-utils.js"; + +export { + monaco, + MonacoEditorProps, + MonacoEditorReactComp, + addMonacoStyles, + getKeybindingsServiceOverride +} diff --git a/core/src/monaco-editor-wrapper-utils.ts b/core/src/monaco-editor-wrapper-utils.ts new file mode 100644 index 00000000..fd739bff --- /dev/null +++ b/core/src/monaco-editor-wrapper-utils.ts @@ -0,0 +1,176 @@ +import { languages } from "monaco-editor"; +import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-service-override'; +import { EditorAppConfigClassic, EditorAppConfigExtended, LanguageClientConfig, UserConfig } from "monaco-editor-wrapper"; + +export type WorkerUrl = string; + +/** + * Generalized configuration used with 'getMonacoEditorReactConfig' to generate a working configuration for monaco-editor-react + */ +export interface MonacoReactConfig { + code: string, + languageId: string, + worker: WorkerUrl | Worker, + readonly?: boolean // whether to make the editor readonly or not (by default is false) +} + +/** + * Extended config, specifically for textmate usage + */ +export interface MonacoExtendedReactConfig extends MonacoReactConfig { + textmateGrammar: any; +} + +/** + * Editor config, specifically for monarch grammar usage + */ +export interface MonacoEditorReactConfig extends MonacoReactConfig { + monarchGrammar?: languages.IMonarchLanguage; +} + +/** + * Helper to identify a Extended config, for use with TextMate + */ +function isMonacoExtendedReactConfig(config: unknown): config is MonacoExtendedReactConfig { + return (config as MonacoExtendedReactConfig).textmateGrammar !== undefined; +} + + +/** + * Default language configuration, common to most Langium DSLs + */ +export const defaultLanguageConfig = { + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ], + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ] +}; + +/** + * Generates a UserConfig for a given Langium example, which is then passed to the monaco-editor-react component + * + * @param config A Extended or classic editor config to generate a UserConfig from + * @returns A completed UserConfig + */ +export function createUserConfig(config: MonacoExtendedReactConfig | MonacoEditorReactConfig): UserConfig { + // setup urls for config & grammar + const id = config.languageId; + + // check whether to use extended config (Textmate) or the classic editor config (Monarch) + let editorAppConfig: EditorAppConfigClassic | EditorAppConfigExtended; + const useExtendedConfig = isMonacoExtendedReactConfig(config); + if (useExtendedConfig) { + // setup extension contents + const languageConfigUrl = `/${id}-configuration.json`; + const languageGrammarUrl = `/${id}-grammar.json`; + const extensionContents = new Map(); + extensionContents.set(languageConfigUrl, JSON.stringify(defaultLanguageConfig)); + extensionContents.set(languageGrammarUrl, JSON.stringify(config.textmateGrammar)); + + editorAppConfig = { + $type: 'extended', + languageId: id, + code: config.code, + useDiffEditor: false, + extensions: [{ + config: { + name: id, + publisher: 'TypeFox', + version: '1.0.0', + engines: { + vscode: '*' + }, + contributes: { + languages: [{ + id: id, + extensions: [ `.${id}` ], + configuration: languageConfigUrl + }], + grammars: [{ + language: id, + scopeName: `source.${id}`, + path: languageGrammarUrl + }] + } + }, + filesOrContents: extensionContents, + }], + userConfiguration: { + json: JSON.stringify({ + 'workbench.colorTheme': 'Default Dark Modern', + 'editor.semanticHighlighting.enabled': true, + 'editor.lightbulb.enabled': true, + 'editor.guides.bracketPairsHorizontal': 'active' + }) + } + }; + } else { + editorAppConfig = { + $type: 'classic', + languageId: id, + code: config.code, + useDiffEditor: false, + languageExtensionConfig: { id }, + languageDef: config.monarchGrammar, + editorOptions: { + 'semanticHighlighting.enabled': true, + readOnly: config.readonly, + theme: 'vs-dark' + } + }; + } + + let languageClientConfig: LanguageClientConfig; + if (typeof config.worker === 'string') { + languageClientConfig = { + options: { + $type: 'WorkerConfig', + url: new URL(config.worker, window.location.href), + type: 'module', + name: `${id}-language-server-worker`, + } + }; + } else { + languageClientConfig = { + options: { + $type: 'WorkerDirect', + worker: config.worker + } + }; + } + + // generate user config for langium based language + const userConfig: UserConfig = { + wrapperConfig: { + serviceConfig: { + // only use keyboard service in addition to the default services from monaco-editor-wrapper + userServices: { + ...getKeybindingsServiceOverride() + }, + debugLogging: true + }, + editorAppConfig + }, + languageClientConfig + } + return userConfig; +} diff --git a/core/tsconfig.json b/core/tsconfig.json new file mode 100644 index 00000000..501bcbcb --- /dev/null +++ b/core/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "noImplicitAny": true, + "target": "ES2022", + "module": "Node16", + "moduleResolution": "Node16", + "rootDir": "src", + "outDir": "dist", + "declaration": true, + "declarationDir": "dist" + }, + "include": [ + "src/**/*.ts", + ] +} \ No newline at end of file diff --git a/hugo/vite.bundle-monaco-editor-react.ts b/core/vite.bundle.ts similarity index 51% rename from hugo/vite.bundle-monaco-editor-react.ts rename to core/vite.bundle.ts index e9043e81..24a35854 100644 --- a/hugo/vite.bundle-monaco-editor-react.ts +++ b/core/vite.bundle.ts @@ -4,21 +4,21 @@ import { defineConfig } from 'vite'; const config = defineConfig({ build: { lib: { - entry: resolve(__dirname, './assets/scripts/monaco-editor-react.ts'), - name: 'monaco-editor-react', - fileName: () => 'monaco-editor-react.js', + entry: resolve(__dirname, './src/index.ts'), + name: 'monaco-editor-wrapper-bundle', + fileName: () => 'index.js', formats: ['es'] }, - outDir: resolve(__dirname, 'static/libs/monaco-editor-react'), - assetsDir: resolve(__dirname, 'static/libs/monaco-editor-react/assets'), - emptyOutDir: false, + outDir: resolve(__dirname, 'bundle/monaco-editor-wrapper-bundle'), + assetsDir: resolve(__dirname, 'bundle/monaco-editor-wrapper-bundle/assets'), + emptyOutDir: true, cssCodeSplit: false, commonjsOptions: { strictRequires: true }, rollupOptions: { output: { - name: 'monaco-editor-react', + name: 'monaco-editor-wrapper-bundle', exports: 'named', sourcemap: false, assetFileNames: (assetInfo) => { @@ -28,11 +28,8 @@ const config = defineConfig({ } }, resolve: { - alias: { - path: 'path-browserify' - } - }, - assetsInclude: ['**/*.wasm'] + dedupe: ['monaco-editor', 'vscode'] + } }); -export default config; \ No newline at end of file +export default config; diff --git a/hugo/.gitignore b/hugo/.gitignore new file mode 100644 index 00000000..b9d7b3f1 --- /dev/null +++ b/hugo/.gitignore @@ -0,0 +1,5 @@ +resources/ +static/css/ +static/showcase/ +static/libs/ +static/playground/ diff --git a/hugo/assets/scripts/arithmetics/arithmetics-tools.tsx b/hugo/assets/scripts/arithmetics/arithmetics-tools.tsx index 25941728..651b1777 100644 --- a/hugo/assets/scripts/arithmetics/arithmetics-tools.tsx +++ b/hugo/assets/scripts/arithmetics/arithmetics-tools.tsx @@ -1,4 +1,4 @@ -import { monaco } from "monaco-editor-wrapper/."; +import { monaco } from "langium-website-core/bundle"; import { Pos } from "../langium-utils/langium-ast"; export interface Evaluation { diff --git a/hugo/assets/scripts/arithmetics/arithmetics.tsx b/hugo/assets/scripts/arithmetics/arithmetics.tsx index 89f87589..662172ab 100644 --- a/hugo/assets/scripts/arithmetics/arithmetics.tsx +++ b/hugo/assets/scripts/arithmetics/arithmetics.tsx @@ -1,11 +1,11 @@ -import { MonacoEditorReactComp } from "./static/libs/monaco-editor-react/monaco-editor-react.js"; +import { addMonacoStyles, createUserConfig, MonacoEditorReactComp, UserConfig } from "langium-website-core/bundle"; import { buildWorkerDefinition } from "monaco-editor-workers"; import React from "react"; import { createRoot } from "react-dom/client"; import { Diagnostic, DocumentChangeResponse } from "../langium-utils/langium-ast"; import { Evaluation, examples, syntaxHighlighting } from "./arithmetics-tools"; -import { UserConfig } from "monaco-editor-wrapper"; -import { createUserConfig } from "../utils"; + +addMonacoStyles('monaco-styles-helper'); buildWorkerDefinition( "../../libs/monaco-editor-workers/workers", @@ -175,7 +175,7 @@ class App extends React.Component<{}, AppState> {
Preview
-
+
{ this.monacoEditor.current?.getEditorWrapper()?.getEditor()?.revealLineInCenter(line); this.monacoEditor.current?.getEditorWrapper()?.getEditor()?.setPosition({ lineNumber: line, column: 1 }); diff --git a/hugo/assets/scripts/domainmodel/d3tree.tsx b/hugo/assets/scripts/domainmodel/d3tree.tsx index ade317a3..bbc7e442 100644 --- a/hugo/assets/scripts/domainmodel/d3tree.tsx +++ b/hugo/assets/scripts/domainmodel/d3tree.tsx @@ -22,22 +22,22 @@ export default function D3Tree({ data }: TreeProps) { useEffect(() => { if (!svgRef.current) return; - // get the size of the tree - const getChildSize = (child: TreeNode): number => { + // get the leaf nodes of the tree + const getLeafNodes = (child: TreeNode): number => { if (!child.children) return 1; - let amount = child.children.length; - - // fastest way to iterate over an array - const length = child.children.length; - for (let i = 0; i < length; i++) { - amount += getChildSize(child.children[i]); - } - return amount; + if(child.children.length === 0) return 1; + return child.children.map(getLeafNodes).reduce((a, b) => a + b); }; - const size = getChildSize(data); - const height = size * 20; - const width = size * 18; + // get the longest path in the tree + const getLongestPath = (child: TreeNode): number => { + if (!child.children) return 1; + if(child.children.length === 0) return 1; + return 1 + Math.max(...child.children.map(getLongestPath)); + }; + + const height = getLeafNodes(data) * 60; + const width = getLongestPath(data) * 120; const svg = d3.select(svgRef.current); svg.selectAll('*').remove(); @@ -51,10 +51,10 @@ export default function D3Tree({ data }: TreeProps) { g.attr('transform', event.transform); }); - svg.call(zoom, d3.zoomIdentity.translate(50, 50)); - // zoom to show the whole tree - svg.call(zoom.transform, d3.zoomIdentity.translate(width / size * 3, height / size * 2).scale(3 / (0.1 * size))); + svg.call(zoom.transform, d3.zoomIdentity.translate(width / 20, height / 30).scale(0.5)); + + svg.call(zoom, d3.zoomIdentity.translate(50, 50)); // draw the links g.selectAll('.link') diff --git a/hugo/assets/scripts/domainmodel/domainmodel-tools.ts b/hugo/assets/scripts/domainmodel/domainmodel-tools.ts index 30052e19..c174eb44 100644 --- a/hugo/assets/scripts/domainmodel/domainmodel-tools.ts +++ b/hugo/assets/scripts/domainmodel/domainmodel-tools.ts @@ -3,17 +3,8 @@ import { AstNode } from "../langium-utils/langium-ast"; import { TreeNode } from "./d3tree"; -export function getTreeNode(ast: AstNode): TreeNode { +export function getMainTreeNode(ast: AstNode): TreeNode { const astNode = getDomainModelAst(ast as DomainModelAstNode); - - // create a TreeNode from all PackageDeclarations in the ast - const packageDeclarations = astNode.packageDeclarations.map(p => { - return { - ...p, - children: p.elements - } as TreeNode; - }); - // create a TreeNode a DataType const getDataTypeTreeNode = (d: DataType): TreeNode => { return { @@ -22,6 +13,24 @@ export function getTreeNode(ast: AstNode): TreeNode { } } + // create a TreeNode from a PackageDeclaration + const getPackageDeclarationTreeNode = (p: PackageDeclaration): TreeNode => { + return { + ...p, + children: p.elements.map(e => getTreeNode(e)) + } + } + + // create a TreeNode from any DomainModelElement + const getTreeNode = (e: DomainModelElement): TreeNode => { + switch(e.$type) { + case 'DataType': return getDataTypeTreeNode(e as DataType); + case 'Entity': return getEntityTreeNode(e as Entity); + case 'PackageDeclaration': return getPackageDeclarationTreeNode(e as PackageDeclaration); + default: return e as TreeNode; + } + } + // create a TreeNode from an Entity const getEntityTreeNode = (entity: Entity): TreeNode => { @@ -58,16 +67,28 @@ export function getTreeNode(ast: AstNode): TreeNode { // create a TreeNode from all Entities in the ast const entities = astNode.entities.flatMap(e => getEntityTreeNode(e)); - // create a TreeNode from all DataTypes in the ast const datatypes = astNode.dataTypes.map(d => getDataTypeTreeNode(d)); - - // combine them all to a single TreeNode - const children: TreeNode[] = [ - {name: 'DataTypes', $type: 'DataType', children: datatypes}, - {name: 'Entities', $type: 'Entity', children: entities}, - {name: 'Packages', $type: 'PackageDeclaration', children: packageDeclarations}, - ]; + // create a TreeNode from all PackageDeclarations in the ast + const packageDeclarations = astNode.packageDeclarations.map(p => getPackageDeclarationTreeNode(p)); + + const children: TreeNode[] = []; + + // if datatypes exist, add them to the children + if(datatypes.length > 0) { + children.push({ name: 'DataTypes', $type: 'DataType', children: datatypes }); + } + + // if entities exist, add them to the children + if(entities.length > 0) { + children.push({name: 'Entities', $type: 'Entity', children: entities}); + } + + // if packageDeclarations exist, add them to the children + if(packageDeclarations.length > 0) { + children.push({name: 'Packages', $type: 'PackageDeclaration', children: packageDeclarations}); + } + // return the root TreeNode return { @@ -103,7 +124,7 @@ export interface DomainModelAstNode extends AstNode, DomainModelElement { export interface PackageDeclaration extends DomainModelElement { $type: 'PackageDeclaration'; - elements: DataType[]; + elements: DomainModelElementType[]; } export interface Entity extends DomainModelElement { diff --git a/hugo/assets/scripts/domainmodel/domainmodel.tsx b/hugo/assets/scripts/domainmodel/domainmodel.tsx index 02fc14f5..c07a4ab4 100644 --- a/hugo/assets/scripts/domainmodel/domainmodel.tsx +++ b/hugo/assets/scripts/domainmodel/domainmodel.tsx @@ -1,13 +1,14 @@ -import { MonacoEditorReactComp } from "@typefox/monaco-editor-react/bundle"; +import { addMonacoStyles, createUserConfig, MonacoEditorReactComp, UserConfig } from "langium-website-core/bundle"; import { buildWorkerDefinition } from "monaco-editor-workers"; import React from "react"; import { createRoot } from "react-dom/client"; import { Diagnostic, DocumentChangeResponse, LangiumAST } from "../langium-utils/langium-ast"; -import { DomainModelAstNode, example, getTreeNode, syntaxHighlighting } from "./domainmodel-tools"; -import { UserConfig } from "monaco-editor-wrapper"; -import { createUserConfig } from "../utils"; +import { DomainModelAstNode, example, getMainTreeNode, syntaxHighlighting } from "./domainmodel-tools"; + import D3Tree from "./d3tree"; - + +addMonacoStyles('monaco-styles-helper'); + buildWorkerDefinition( "../../libs/monaco-editor-workers/workers", new URL("", window.location.href).href, @@ -85,7 +86,7 @@ class App extends React.Component<{}, AppState> { // if there are no errors, render the tree if (this.state.diagnostics == null || this.state.diagnostics.filter((i) => i.severity === 1).length == 0) { return ( - + ); } diff --git a/hugo/assets/scripts/lox/lox-tools.ts b/hugo/assets/scripts/lox/lox-tools.ts new file mode 100644 index 00000000..80cbc5b0 --- /dev/null +++ b/hugo/assets/scripts/lox/lox-tools.ts @@ -0,0 +1,72 @@ +export interface LoxMessage { + type: LoxMessageType; + content: unknown; +}; + +export type LoxMessageType = "notification" | "output" | "error"; + + +export const exampleCode = `fun factorial(n: number): number { + if (n <= 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} + +fun binomial(n: number, k: number): number { + return factorial(n) / (factorial(k) * factorial(n - k)); +} + +fun pow(x: number, n: number): number { + var result = 1; + for (var i = 0; i < n; i = i + 1) { + result = result * x; + } + return result; +} + +fun mod(x: number, y: number): number { + return x - y * (x / y); +} + +fun floor(x: number): number { + return x - mod(x, 1); +} + +print("factorial(5) = " + factorial(5)); +print("binomial(5, 2) = " + binomial(5, 2)); +print("pow(2, 10) = " + pow(2, 10)); +print("mod(10, 3) = " + mod(10, 3)); +print("floor(3.14) = " + floor(3.14)); +`; + +export const syntaxHighlighting = { + keywords: [ + 'and', 'boolean', 'class', 'else', 'false', 'for', 'fun', 'if', 'nil', 'number', 'or', 'print', 'return', 'string', 'super', 'this', 'true', 'var', 'void', 'while' + ], + operators: [ + '-', ',', ';', ':', '!', '!=', '.', '*', '/', '+', '<', '<=', '=', '==', '=>', '>', '>=' + ], + symbols: /-|,|;|:|!|!=|\.|\(|\)|\{|\}|\*|\+|<|<=|=|==|=>|>|>=/, + + tokenizer: { + initial: [ + { regex: /[_a-zA-Z][\w_]*/, action: { cases: { '@keywords': { "token": "keyword" }, '@default': { "token": "ID" } } } }, + { regex: /[0-9]+(\.[0-9]+)?/, action: { "token": "number" } }, + { regex: /"[^"]*"/, action: { "token": "string" } }, + { include: '@whitespace' }, + { regex: /@symbols/, action: { cases: { '@operators': { "token": "operator" }, '@default': { "token": "" } } } }, + ], + whitespace: [ + { regex: /\s+/, action: { "token": "white" } }, + { regex: /\/\*/, action: { "token": "comment", "next": "@comment" } }, + { regex: /\/\/[^\n\r]*/, action: { "token": "comment" } }, + ], + comment: [ + { regex: /[^\/\*]+/, action: { "token": "comment" } }, + { regex: /\*\//, action: { "token": "comment", "next": "@pop" } }, + { regex: /[\/\*]/, action: { "token": "comment" } }, + ], + } +}; diff --git a/hugo/assets/scripts/lox/lox.tsx b/hugo/assets/scripts/lox/lox.tsx new file mode 100644 index 00000000..fe057d79 --- /dev/null +++ b/hugo/assets/scripts/lox/lox.tsx @@ -0,0 +1,170 @@ +import { + MonacoEditorReactComp, +} from "@typefox/monaco-editor-react/bundle"; +import { buildWorkerDefinition } from "monaco-editor-workers"; +import React, { createRef, useRef } from "react"; +import { createRoot } from "react-dom/client"; +import { Diagnostic, DocumentChangeResponse } from "../langium-utils/langium-ast"; +import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from "lz-string"; +import { LoxMessage, exampleCode, syntaxHighlighting } from "./lox-tools"; +import { UserConfig } from "monaco-editor-wrapper"; +import { createUserConfig } from "../utils"; +import { LoxPreview } from "./preview"; + +buildWorkerDefinition( + "../../libs/monaco-editor-workers/workers", + new URL("", window.location.href).href, + false +); +let userConfig: UserConfig; + + + +class App extends React.Component<{}, {}> { + monacoEditor: React.RefObject; + preview: React.RefObject; + copyHint: React.RefObject; + shareButton: React.RefObject; + constructor(props) { + super(props); + + // bind 'this' ref for callbacks to maintain parent context + this.onMonacoLoad = this.onMonacoLoad.bind(this); + this.onDocumentChange = this.onDocumentChange.bind(this); + this.copyLink = this.copyLink.bind(this); + this.monacoEditor = React.createRef(); + this.preview = React.createRef(); + this.copyHint = React.createRef(); + this.shareButton = React.createRef(); + } + + /** + * Callback that is invoked when Monaco is finished loading up. + * Can be used to safely register notification listeners, retrieve data, and the like + * + * @throws Error on inability to ref the Monaco component or to get the language client + */ + onMonacoLoad() { + // verify we can get a ref to the editor + if (!this.monacoEditor.current) { + throw new Error("Unable to get a reference to the Monaco Editor"); + } + + // verify we can get a ref to the language client + const lc = this.monacoEditor.current + ?.getEditorWrapper() + ?.getLanguageClient(); + if (!lc) { + throw new Error("Could not get handle to Language Client on mount"); + } + this.monacoEditor.current.getEditorWrapper()?.getEditor()?.focus(); + // register to receive DocumentChange notifications + lc.onNotification("browser/DocumentChange", this.onDocumentChange); + } + + /** + * Callback invoked when the document processed by the LS changes + * Invoked on startup as well + * @param resp Response data + */ + onDocumentChange(resp: DocumentChangeResponse) { + // decode the received Asts + const message = JSON.parse(resp.content) as LoxMessage; + switch (message.type) { + case "notification": + switch (message.content) { + case "startInterpreter": + this.preview.current?.clear(); + break; + } + break; + case "error": + this.preview.current?.error(message.content as string); + break; + case "output": + this.preview.current?.println(message.content as string); + break; + } + this.preview.current?.setDiagnostics(resp.diagnostics); + } + + + async copyLink() { + const code = this.monacoEditor.current?.getEditorWrapper()?.getEditor()?.getValue()!; + const url = new URL("/showcase/lox", window.origin); + url.searchParams.append("code", compressToEncodedURIComponent(code)); + + this.copyHint.current!.style.display = "block"; + this.shareButton.current!.src = '/assets/checkmark.svg'; + setTimeout(() => { + this.shareButton.current!.src = '/assets/share.svg'; + this.copyHint.current!.style.display = 'none'; + }, 1000); + + navigator.clipboard.writeText(window.location.href); + + await navigator.clipboard.writeText(url.toString()); + } + + componentDidMount() { + this.shareButton.current!.addEventListener('click', this.copyLink); + } + + render() { + const style = { + height: "100%", + width: "100%", + }; + const url = new URL(window.location.toString()); + let code = url.searchParams.get("code"); + if (code) { + code = decompressFromEncodedURIComponent(code); + } + + return ( +
+
+
+ Editor +
+
Link was copied!
+ +
+
+
+ +
+
+
+
+ Output +
+
+ +
+
+
+ ); + } +} + +export async function share(code: string): Promise { + const url = new URL("/showcase/lox", window.origin); + url.searchParams.append("code", compressToEncodedURIComponent(code)); + await navigator.clipboard.writeText(url.toString()); +} + +userConfig = createUserConfig({ + languageId: 'lox', + code: exampleCode, + htmlElement: document.getElementById('root')!, + worker: '/showcase/libs/worker/loxServerWorker.js', + monarchGrammar: syntaxHighlighting +}); +const root = createRoot(document.getElementById("root") as HTMLElement); +root.render(); diff --git a/hugo/assets/scripts/lox/preview.tsx b/hugo/assets/scripts/lox/preview.tsx new file mode 100644 index 00000000..53df3817 --- /dev/null +++ b/hugo/assets/scripts/lox/preview.tsx @@ -0,0 +1,91 @@ +import { createRef } from "react"; +import { Diagnostic } from "../langium-utils/langium-ast"; +import React from "react"; + +interface PreviewProps { + diagnostics?: Diagnostic[]; +} + +interface PreviewState { + diagnostics?: Diagnostic[]; + messages: TerminalMessage[]; +} + +interface TerminalMessage { + type: "notification" | "error" | "output"; + content: string | string[]; +} + +export class LoxPreview extends React.Component { + terminalContainer: React.RefObject; + constructor(props: PreviewProps) { + super(props); + this.state = { + diagnostics: props.diagnostics, + messages: [], + }; + + this.terminalContainer = createRef(); + } + + println(text: string) { + this.setState((state) => ({ + messages: [...state.messages, { type: "output", content: text }], + })); + } + + error(text: string) { + this.setState((state) => ({ + messages: [...state.messages, { type: "error", content: text }], + })); + } + + clear() { + this.setState({ messages: [] }); + } + + setDiagnostics(diagnostics: Diagnostic[]) { + this.setState({ diagnostics: diagnostics }); + + } + + render() { + // if the code doesn't contain any errors and the diagnostics aren't warnings + if (this.state.diagnostics == null || this.state.diagnostics.filter((i) => i.severity === 1).length == 0) { + + // auto scroll to bottom + const terminal = this.terminalContainer.current; + const newLine = terminal?.lastElementChild; + if (newLine && terminal) { + const rect = newLine.getBoundingClientRect(); + if (rect.bottom <= terminal.getBoundingClientRect().bottom) { + newLine.scrollIntoView(); + } + } + + return ( +
+
+ {this.state.messages.map((message, index) => +

{message.type == "error" ? "An error occurred: " : ""} {message.content}

+ )} +
+
+ ); + } + + // Show the exception + return ( +
+
+ {this.state.diagnostics.filter((i) => i.severity === 1).map((diagnostic, index) => +
+ {`Line ${diagnostic.range.start.line}-${diagnostic.range.end.line}: ${diagnostic.message}`} +

Source: {diagnostic.source} | Code: {diagnostic.code}

+
+ )} +
+
+ ); + } +} diff --git a/hugo/assets/scripts/minilogo/minilogo-tools.ts b/hugo/assets/scripts/minilogo/minilogo-tools.ts index 9978a0e5..deee44bc 100644 --- a/hugo/assets/scripts/minilogo/minilogo-tools.ts +++ b/hugo/assets/scripts/minilogo/minilogo-tools.ts @@ -1,4 +1,4 @@ -import { monaco } from "monaco-editor-wrapper/."; +import { monaco } from "langium-website-core/bundle"; export interface Command { name: 'penUp' | 'penDown' | 'move' | 'color'; diff --git a/hugo/assets/scripts/minilogo/minilogo.tsx b/hugo/assets/scripts/minilogo/minilogo.tsx index 25bcdde6..3f39c923 100644 --- a/hugo/assets/scripts/minilogo/minilogo.tsx +++ b/hugo/assets/scripts/minilogo/minilogo.tsx @@ -1,12 +1,12 @@ -import { MonacoEditorReactComp } from "@typefox/monaco-editor-react/bundle"; +import { addMonacoStyles, createUserConfig, MonacoEditorReactComp, UserConfig } from "langium-website-core/bundle"; import { buildWorkerDefinition } from "monaco-editor-workers"; import React, { createRef } from "react"; import { createRoot } from "react-dom/client"; import { Diagnostic, DocumentChangeResponse, LangiumAST } from "../langium-utils/langium-ast"; import { ColorArgs, Command, MoveArgs, examples, syntaxHighlighting } from "./minilogo-tools"; import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from "lz-string"; -import { UserConfig } from "monaco-editor-wrapper"; -import { createUserConfig } from "../utils"; + +addMonacoStyles('monaco-styles-helper'); buildWorkerDefinition( "../../libs/monaco-editor-workers/workers", diff --git a/hugo/assets/scripts/monaco-editor-react.ts b/hugo/assets/scripts/monaco-editor-react.ts deleted file mode 100644 index a92213a9..00000000 --- a/hugo/assets/scripts/monaco-editor-react.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "@typefox/monaco-editor-react"; -import 'vscode/default-extensions/theme-defaults'; diff --git a/hugo/assets/scripts/sql/constants.ts b/hugo/assets/scripts/sql/constants.ts index 92ea8528..5d237a09 100644 --- a/hugo/assets/scripts/sql/constants.ts +++ b/hugo/assets/scripts/sql/constants.ts @@ -1,4 +1,4 @@ -import { monaco } from "@typefox/monaco-editor-react/."; +import { monaco } from "langium-website-core/bundle"; export const syntaxHighlighting: monaco.languages.IMonarchLanguage = { tokenizer: { diff --git a/hugo/assets/scripts/sql/ui.tsx b/hugo/assets/scripts/sql/ui.tsx index b2d339c0..4e352182 100644 --- a/hugo/assets/scripts/sql/ui.tsx +++ b/hugo/assets/scripts/sql/ui.tsx @@ -1,4 +1,4 @@ -import { MonacoEditorReactComp } from "./static/libs/monaco-editor-react/monaco-editor-react.js"; +import { addMonacoStyles, createUserConfig, MonacoEditorReactComp, UserConfig } from "langium-website-core/bundle"; import { buildWorkerDefinition } from "monaco-editor-workers"; import React from "react"; import { createRoot } from "react-dom/client"; @@ -9,8 +9,8 @@ import { defaultText, syntaxHighlighting, } from "./constants"; -import { UserConfig } from "monaco-editor-wrapper"; -import { createUserConfig } from '../utils'; + +addMonacoStyles('monaco-styles-helper'); buildWorkerDefinition( "../../libs/monaco-editor-workers/workers", diff --git a/hugo/assets/scripts/statemachine/statemachine.tsx b/hugo/assets/scripts/statemachine/statemachine.tsx index a3b1f6b0..e57476f0 100644 --- a/hugo/assets/scripts/statemachine/statemachine.tsx +++ b/hugo/assets/scripts/statemachine/statemachine.tsx @@ -1,13 +1,13 @@ -import { MonacoEditorReactComp } from "./static/libs/monaco-editor-react/monaco-editor-react.js"; +import { addMonacoStyles, createUserConfig, MonacoEditorReactComp, UserConfig } from "langium-website-core/bundle"; import { buildWorkerDefinition } from "monaco-editor-workers"; import React from "react"; import { createRoot } from "react-dom/client"; import { Diagnostic, DocumentChangeResponse, LangiumAST } from "../langium-utils/langium-ast"; import { defaultText, StateMachineAstNode, StateMachineState, StateMachineTools } from "./statemachine-tools"; -import { UserConfig } from "monaco-editor-wrapper"; -import { createUserConfig } from '../utils'; import statemachineGrammar from 'langium-statemachine-dsl/syntaxes/statemachine.tmLanguage.json'; +addMonacoStyles('monaco-styles-helper'); + buildWorkerDefinition( "../../libs/monaco-editor-workers/workers", new URL("", window.location.href).href, @@ -278,7 +278,7 @@ class StateMachineComponent extends React.Component<{
Preview
-
+
diff --git a/hugo/assets/scripts/utils.ts b/hugo/assets/scripts/utils.ts deleted file mode 100644 index 442b764b..00000000 --- a/hugo/assets/scripts/utils.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { UserConfig } from "monaco-editor-wrapper"; -import { monaco } from "monaco-editor-wrapper/."; - -export type WorkerUrl = string; - -/** - * Generalized configuration used with 'getMonacoEditorReactConfig' to generate a working configuration for monaco-editor-react - */ -export interface MonacoReactConfig { - code: string, - htmlElement: HTMLElement, - languageId: string, - worker: WorkerUrl | Worker, - readonly?: boolean // whether to make the editor readonly or not (by default is false) -} - -/** - * VSCode API config, specifically for textmate usage - */ -export interface MonacoVSCodeReactConfig extends MonacoReactConfig { - textmateGrammar: any; -} - -/** - * Editor config, specifically for monarch grammar usage - */ -export interface MonacoEditorReactConfig extends MonacoReactConfig { - monarchGrammar?: monaco.languages.IMonarchLanguage; -} - -/** - * Helper to identify a VSCode API config, for use with TextMate - */ -function isMonacoVSCodeReactConfig(config: unknown): config is MonacoVSCodeReactConfig { - return (config as MonacoVSCodeReactConfig).textmateGrammar !== undefined; -} - -/** - * Helper to identify an editor config (classic), for use with Monarch - */ -function isMonacoEditorReactConfig(config: unknown): config is MonacoEditorReactConfig { - return (config as MonacoEditorReactConfig).monarchGrammar !== undefined; -} - -/** - * Default language configuration, common to most Langium DSLs - */ -export const defaultLanguageConfig = { - "comments": { - "lineComment": "//", - "blockComment": ["/*", "*/"] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ] -}; - -/** - * Generates a UserConfig for a given Langium example, which is then passed to the monaco-editor-react component - * - * @param config A VSCode API or classic editor config to generate a UserConfig from - * @returns A completed UserConfig - */ -export function createUserConfig(config: MonacoVSCodeReactConfig | MonacoEditorReactConfig): UserConfig { - // setup extension contents - const extensionContents = new Map(); - - // setup urls for config & grammar - const id = config.languageId; - const languageConfigUrl = `/${id}-configuration.json`; - const languageGrammarUrl = `/${id}-grammar.json`; - - // set extension contents - extensionContents.set(languageConfigUrl, JSON.stringify(defaultLanguageConfig)); - - // check whether to use the VSCode API config (TM), or the classic editor config (Monarch) - const useVscodeConfig = isMonacoVSCodeReactConfig(config); - - if (isMonacoVSCodeReactConfig(config)) { - extensionContents.set(languageGrammarUrl, JSON.stringify(config.textmateGrammar)); - } - - // generate langium config - return { - htmlElement: config.htmlElement, - wrapperConfig: { - // have to disable this for Monarch - // generally true otherwise (toggles using monacoVscodeApiConfig / monacoEditorConfig) - useVscodeConfig, - - serviceConfig: { - // the theme service & textmate services are dependent, they need to both be enabled or disabled together - // this explicitly disables the Monarch capabilities - // both are tied to whether we are using the VSCode config as well - enableThemeService: useVscodeConfig, - enableTextmateService: useVscodeConfig, - - enableModelService: true, - configureEditorOrViewsServiceConfig: { - enableViewsService: false, - useDefaultOpenEditorFunction: true - }, - configureConfigurationServiceConfig: { - defaultWorkspaceUri: '/tmp/' - }, - enableKeybindingsService: true, - enableLanguagesService: true, - debugLogging: false - }, - // VSCode config (for TextMate grammars) - monacoVscodeApiConfig: { - extension: { - name: id, - publisher: 'TypeFox', - version: '1.0.0', - engines: { - vscode: '*' - }, - contributes: { - languages: [{ - id, - extensions: [], - aliases: [ - id - ], - configuration: `.${languageConfigUrl}` - }], - grammars: isMonacoVSCodeReactConfig(config) ? [{ - language: id, - scopeName: `source.${id}`, - path: `.${languageGrammarUrl}` - }] : undefined, - keybindings: [{ - key: 'ctrl+p', - command: 'editor.action.quickCommand', - when: 'editorTextFocus' - }, { - key: 'ctrl+shift+c', - command: 'editor.action.commentLine', - when: 'editorTextFocus' - }] - } - }, - extensionFilesOrContents: extensionContents, - userConfiguration: { - json: `{ - "workbench.colorTheme": "Default Dark Modern", - "editor.fontSize": 14, - "editor.lightbulb.enabled": true, - "editor.lineHeight": 20, - "editor.guides.bracketPairsHorizontal": "active", - "editor.lightbulb.enabled": true -}` - } - }, - // Editor config (classic) (for Monarch) - monacoEditorConfig: { - languageExtensionConfig: { - id - }, - languageDef: isMonacoEditorReactConfig(config) ? config.monarchGrammar : undefined - } - }, - editorConfig: { - languageId: id, - code: config.code, - useDiffEditor: false, - automaticLayout: true, - theme: 'vs-dark', - editorOptions: { - readOnly: config.readonly - } - }, - languageClientConfig: { - enabled: true, - useWebSocket: false, - // build a worker config from a worker URL string, or just copy in the entire worker - workerConfigOptions: typeof config.worker === 'string' ? { - url: new URL(config.worker, window.location.href), - type: 'module', - name: `${id}-language-server-worker`, - } : config.worker - } - }; -} diff --git a/hugo/content/docs/getting-started.md b/hugo/content/docs/getting-started.md index 16ee9ede..dd77574d 100644 --- a/hugo/content/docs/getting-started.md +++ b/hugo/content/docs/getting-started.md @@ -75,7 +75,7 @@ Here's the grammar that parses the previous text snippet: grammar HelloWorld hidden terminal WS: /\s+/; -terminal ID: /[_a-zA-Z][\w_]*/; +terminal ID: /[_a-zA-Z][\w]*/; entry Model: (persons+=Person | greetings+=Greeting)*; diff --git a/hugo/content/playground/_index.html b/hugo/content/playground/_index.html index 8764727d..d005d41b 100644 --- a/hugo/content/playground/_index.html +++ b/hugo/content/playground/_index.html @@ -10,14 +10,14 @@ noMain: true playground: true --- - - - -``` +```ts +let running = false; +let timeout: number | null = null; -{{< /tab >}} -{{< tab "CSS" >}} -We need to update our **styles.css** file as well to allow a side-by-side view of Monaco and our canvas. You can replace your previous CSS content with these new contents to achieve that effect. - -```css -html,body { - background: rgb(33,33,33); - font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; - color: white; - /* for monaco */ - margin: 0; - padding: 0; - width: 100%; - height: 100%; -} -h1 { - text-align: center; -} -#minilogo-canvas { - display: block; - margin: 8px auto; - text-align: center; -} -#page-wrapper { - display: flex; - max-width: 2000px; - margin: 4px auto; - padding: 4px; - min-height: 80vh; - justify-content: center; -} -#page-wrapper .half { - display: flex; - width: 40vw; -} -.build { - display: block; - margin: 8px auto; - width: 300px; - height: 30px; - background: none; - border: 2px #fff solid; - color: #fff; - transition: 0.3s; - font-size: 1.2rem; - border-radius: 4px; -} -.build:hover { - border-color: #6cf; - color: #6cf; - cursor: pointer; -} -.build:active { - color: #fff; - border-color: #fff; -} -footer { - text-align: center; - color: #444; - font-size: 1.2rem; - margin-bottom: 16px; -} -@media(max-width: 1000px) { - #page-wrapper { - display: block; - } - #page-wrapper .half { - display: block; - width: auto; +function onDocumentChange(resp: any) { + // block until we're finished with a given run + if (running) { + return; } - #minilogo-canvas { - margin-top: 32px; + + // clear previous timeouts + if (timeout) { + clearTimeout(timeout); } - #page-wrapper { - min-height: auto; - } -} -/* for monaco */ -.wrapper { - display: flex; - flex-direction: column; - height: 100%; - width: 100%; -} + timeout = window.setTimeout(async () => { + running = true; + let commands = JSON.parse(resp.content).$commands; + await updateMiniLogoCanvas(commands); + running = false; -#monaco-editor-root { - flex-grow: 1; + }, 200); // delay of 200ms is arbitrary, choose what makes the most sense in your use case } ``` -{{< /tab >}} -{{< /tabs >}} +And now we have a nice delay where repeated updates are discarded, until we have about 200ms without a subsequent update. That allows us to take the commands we're working with, and start doing something with them. The semaphore will prevent following updates from overriding the current run, allowing it to finish before starting a new execution. -At this point, running `npm run build:web && npm run serve` should show Monaco on the left, an empty space on the right (this is the canvas), along with an "Update Canvas" button at the bottom. If you see this, then you can trust that the layout was updated correctly. +You may have also noticed we added `updateMiniLogoCanvas` as the action to perform with our commands. This will be implemented in the next step, where we interpret our drawing commands. -We'll also want to go into **setup.js** file, and add a small modification to the end. This change will create a global function on the window, giving us a callback that lets us execute our command to parse and generate data from the current program in Monaco. It's important that this goes into the same file as your Monaco setup code, as it directly interacts with the Monaco editor language client instance. +That's it for listening for notifications! Now that we have our commands extracted, we'll can actually perform a series of drawing actions on an HTML5 canvas. -```js -// modify your previous import to bring in the appropriate monaco-vscode-api version -import { vscode } from './monaco-editor-wrapper/index.js'; +## Interpreting Draw Commands (Drawing) -... - -const generateAndDisplay = (async () => { - console.info('generating & running current code...'); - const value = client.getEditor()?.getValue()!; - // parse & generate commands for drawing an image - // execute custom LSP command, and receive the response - const minilogoCmds = await vscode.commands.executeCommand('parseAndGenerate', value); - updateMiniLogoCanvas(minilogoCmds); -}); +If you've gotten to this point then you're on the final stretch! The last part we need to implement is the actual logic that takes our drawing commands and updates the canvas. This logic will be the content of the `updateMiniLogoCanvas` function, and we'll walk through each step here. -// Updates the mini-logo canvas -window.generateAndDisplay = generateAndDisplay; +First, let's get a handle on our canvas, as well as the associated 2D context. -// Takes generated MiniLogo commands, and draws on an HTML5 canvas -function updateMiniLogoCanvas(cmds) { - // print the commands out, so we can verify what we have received. - // TODO, will change in th next section... - alert(JSON.stringify(cmds)); +```ts +const canvas : HTMLCanvasElement | null = document.getElementById('minilogo-canvas') as HTMLCanvasElement | null; +if (!canvas) { + throw new Error('Unable to find canvas element!'); } -``` - -Running the build & serve workflow again, you should be able to now click "Update Canvas" and view an alert containing your generated commands corresponding with the current MiniLogo program in Monaco. Feel free to use the **examples/langium.logo** or **examples/test.logo** to try this out. - -## Interpreting Draw Commands -If you've gotten to this point then you're on the final stretch! The last part we need to implement is the actual logic that takes our drawing commands and updates the canvas. This logic will replace the existing contents of the `updateMiniLogoCanvas` function, and we'll walk through each step here. - -First, let's get a handle on our canvas, as well as the associated 2D context. - -```js -const canvas = document.getElementById('minilogo-canvas'); const context = canvas.getContext('2d'); +if (!context) { + throw new Error('Unable to get canvas context!'); +} ``` We'll also want to clean up the context, in case we already drew something there before. This will be relevant when we're updating the canvas multiple times with a new program. -```js +```ts context.clearRect(0, 0, canvas.width, canvas.height); ``` Next, we want to setup a background grid to display. It's not essential for drawing, but it looks nicer than an empty canvas. -```js +```ts context.beginPath(); context.strokeStyle = '#333'; for (let x = 0; x <= canvas.width; x+=(canvas.width / 10)) { @@ -405,38 +186,40 @@ context.stroke(); After drawing a grid, let's reset the stroke to a white color. -```js +```ts context.strokeStyle = 'white'; ``` Let's also setup some initial drawing state. This will be used to keep track of the pen state, and where we are on the canvas. -```js +```ts // maintain some state about our drawing context let drawing = false; let posX = 0; let posY = 0; ``` -And let's begin evaluating each of our commands. To do this, we'll setup an interval that repeatedly shifts the top element from our list of commands, evaluates it, and repeats. Once we're out of commands to evaluate, we'll clear the interval. Feel free to adjust the delay (or remove it entirely) in your version. - -```js -// use the command list to execute each command with a small delay -const id = setInterval(() => { - if (cmds.length > 0) { - // evaluate the next command in the current env/context - evalCmd(cmds.shift(), context); - } else { - // finish existing draw - if (drawing) { - context.stroke(); +And let's begin evaluating each of our commands. To do this, we'll setup an interval that repeatedly shifts the top element from our list of commands, evaluates it, and repeats. Once we're out of commands to evaluate, we'll clear the interval. The whole invocation will be wrapped in a promise, to make it easy to await later on. Feel free to adjust the delay (or remove it entirely) in your version. + +```ts +const doneDrawingPromise = new Promise((resolve) => { + // use the command list to execute each command with a small delay + const id = setInterval(() => { + if (cmds.length > 0) { + dispatchCommand(cmds.shift() as MiniLogoCommand, context); + } else { + // finish existing draw + if (drawing) { + context.stroke(); + } + clearInterval(id); + resolve(''); } - clearInterval(id); - } -}, 1); + }, 1); +}); ``` -The evaluate command itself only needs to handle 4 cases: +`dispatchCommand` itself only needs to handle 4 cases: - penUp - penDown @@ -447,11 +230,11 @@ Knowing this, and the details about what properties each command type can have, *Be sure to add this function inside the `updateMiniLogoCanvas` function, otherwise it will not have access to the necessary state!* -```js -// evaluate a single command in the current context -function evalCmd(cmd, context) { - if (cmd.cmd) { - switch (cmd.cmd) { +```ts +// dispatches a single command in the current context +function dispatchCommand(cmd: MiniLogoCommand, context: CanvasRenderingContext2D) { + if (cmd.name) { + switch (cmd.name) { // pen is lifted off the canvas case 'penUp': drawing = false; @@ -468,8 +251,8 @@ function evalCmd(cmd, context) { // move across the canvas // will draw only if the pen is 'down' case 'move': - const x = cmd.x; - const y = cmd.y; + const x = cmd.args.x; + const y = cmd.args.y; posX += x; posY += y; if (!drawing) { @@ -483,44 +266,37 @@ function evalCmd(cmd, context) { // set the color of the stroke case 'color': - if (cmd.color) { + if ((cmd.args as { color: string }).color) { // literal color or hex - context.strokeStyle = cmd.color; + context.strokeStyle = (cmd.args as { color: string }).color; } else { // literal r,g,b components - context.strokeStyle = `rgb(${cmd.r},${cmd.g},${cmd.b})`; + const args = cmd.args as { r: number, g: number, b: number }; + context.strokeStyle = `rgb(${args.r},${args.g},${args.b})`; } break; + // fallback in case we missed an instruction + default: + throw new Error('Unrecognized command received: ' + JSON.stringify(cmd)); + } } } ``` -Lastly, we want to view the page with some output on the canvas when our editor is finished starting, rather than an empty half of the screen to start. We can address this by setting the `generateAndDisplay` function to be called once the editor is finished loading. We can place this anywhere after our `startingPromise` has been created. +Now that we can interpret commands into drawing instructions, we're effectively done with setting up the last part of MiniLogo. Since we're listening to document updates, we don't need to do anything other than to just start it up and start with an example program. -*If you don't recall, this promise was returned by the previous call to `client.start({...})` in our last tutorial on Langium + Monaco. If you haven't read that, it would be good to double check it out now*. - -```js -startingPromise.then(() => { - generateAndDisplay(); -}); -``` - -That's it, we're all done writing up our JS file. We should now be able to run the following (assuming the generator script is also executed by `build:web`), and get our results in `localhost:3000`. +That's it, we're all done writing up our TS file. We should now be able to run the following (assuming the generator script is also executed by `build:web`), and get our results in `localhost:3000`. ```bash npm run build:web npm run serve ``` -If all went well, you should see a white diamond sketched out on the canvas when the page loads. If not, double check that you set the `code` value correctly in your `client.start({...})` configuration. To be specific, it's under `editorConfig.code`. If you didn't, you can still add it to the underlying editor directly, assuming you have access to the client wrapper: +If all went well, you should see a white diamond sketched out on the canvas when the page loads. If not, double check that you receive & use the `code` value correctly in your `createUserConfig` function. You can also add the program yourself from here: -```js -// where client is an instance of MonacoEditorLanguageClientWrapper -// retrieve the underlying editor, and set it's value -// this is implicitly the 'main' code -client.getEditor()?.setValue(` +```minilogo def test() { move(100, 0) pen(down) @@ -532,8 +308,6 @@ def test() { } color(white) test() - -`); ``` Once you have something drawing on the screen, you're all set, congratulations! You've just successfully written your own Langium-based language, deployed it in the web, and hooked up generation to boot. In fact, you've done *quite* a lot if you've gone through all of these tutorials so far. @@ -545,13 +319,13 @@ Once you have something drawing on the screen, you're all set, congratulations! - configuring code bundling - building an extension - setting up Langium + Monaco in the web -- adding a custom LSP command & handler -- using an LSP command to drive generation & draw images +- adding a document build phase listener +- listening for notifications in the client, and using the results And the concepts that we've gone over from the beginning to now are not just for MiniLogo of course, they can be easily generalized to work for your own language as well. As you've been going through these tutorials, we hope that you've been thinking about how you could have done things *differently* too. Whether a simple improvement, or another approach, we believe it's this creative kind of thinking that takes an idea of a language and really allows it to grow into something great. -One easy point to make is how the example code shown in these tutorials is designed to designed to be easy to demonstrate. However, it can improved with better error checking, better logic, generator optimizations, etc. +One easy note is how the example code shown in these tutorials was designed to be easy to demonstrate. It could definitely be improved with better error checking, better logic, generator optimizations, etc; something to keep in mind. -It is also easy to imagine how one could extend their generator to produce their own functionality, besides drawing. It's even possible to imagine that you might have multiple generator targets, as there is no requirement to have a single generator output form like we've done in these tutorials. You could add as many different outputs forms as you need for each specific target, and even share some functionality between generators. +It's also easy to imagine how one could extend their generator to produce their own functionality besides drawing. For example, imagine that you might have multiple generator targets, as there is no requirement to have a single generator output form like we've done in these tutorials. You could add as many different output forms as you need for each specific target, and even share some functionality between generators. We hope that these tutorials have given you a practical demonstration of how to construct a language in Langium, and facilitated further exploration into more advanced topics & customizations. If you're interested about learning more about Langium, you can continue through our other tutorials, reach out to us via discussions on Github, or continue working on your Langium-based language. diff --git a/hugo/content/tutorials/langium_and_monaco.md b/hugo/content/tutorials/langium_and_monaco.md index 171d71bb..48111921 100644 --- a/hugo/content/tutorials/langium_and_monaco.md +++ b/hugo/content/tutorials/langium_and_monaco.md @@ -5,43 +5,35 @@ weight: 6 {{< toc format=html >}} -*Updated on Aug. 2nd, 2023 for usage with monaco-editor-wrapper 2.1.1 & above.* +*Updated on Oct. 4th, 2023 for usage with monaco-editor-wrapper 3.1.0 & above, as well as Langium 2.0.2* In this tutorial we'll be talking about running Langium in the web with the Monaco editor. If you're not familiar with Monaco, it's the editor that powers VS Code. We're quite fond of it at TypeFox, so we've taken the time to write up this tutorial to explain how to integrate Langium in the web with Monaco, no backend required. -As a disclaimer, just because we are using Monaco in this tutorial does not mean that you cannot use another code editor of your choice. For example, you can use Code Mirror with Langium as well. Generally, if an editor has LSP support, it is very likely you can integrate it quite easily with Langium, since it's LSP compatible. +Although we're using Monaco in this tutorial, that does not mean that you cannot use another code editor of your choice. For example, you can use Code Mirror with Langium as well. Generally, if an editor has LSP support, it is very likely you can integrate it easily with Langium, since it's LSP compatible. -Without further ado, let's jump into getting your web-based Langium experience setup. +Without further ado, let's jump into getting your web-based Langium experience setup! -## Getting your Language Setup for the Web - -To begin, you're going to need a Langium-based language to work with. We have already written [MiniLogo](https://github.com/langium/langium-minilogo) in Langium as an example for deploying a language in the web. However, if you've been following along with these tutorials, you should be ready to move your own language into a web-based context. - -Per usual, we'll be using MiniLogo as the motivating example here. +## Technologies You'll Need -Once you have a language picked, you're going to want to add a script to your **package.json** to build a web worker for your language. The bundle this script produces will contain the language server for your language. +- [Langium](https://www.npmjs.com/package/langium) 2.0.2 or greater +- [Monaco Editor Wrapper](https://www.npmjs.com/package/monaco-editor-wrapper) 3.1.0 or greater +- [ESBuild](https://www.npmjs.com/package/esbuild) 0.18.20 or greater -```json -{ - ... - "build:worker": "esbuild --minify ./out/language/main.js --bundle --format=iife --outfile=./public/minilogo-server-worker.js" -} -``` - -Now, assuming `esbuild` is installed, if we try to invoke this it *won't succeed as expected*. Instead we'll get a warning back about some dependencies that couldn't be resolved. For example: +## Getting your Language Setup for the Web -> Could not resolve "fs" +To begin, you're going to need a Langium-based language to work with. We have already written [MiniLogo](https://github.com/langium/langium-minilogo) in Langium as an example for deploying a language in the web. However, if you've been following along with these tutorials so far, you should be ready to move your own language into a web-based context. -This makes sense since we're bundling for the web, and we can't depend on packages that rely on the usual environment with a filesystem. So, we need to update our language to make it compatible in a web-based context. +Per usual, we'll be using MiniLogo as the motivating example here. ## Factoring out File System Dependencies -First off, let's create a new entry point for our language server in **src/language/main-browser.ts**. This will mirror the regular entry point that we use to build already, but will allow us to target a web-based context instead. In this file, we'll have the following contents: +In order to build for the browser, we need to create a bundle that is free of any browser-incompatible modules. To do this, let's create a new entry point for our language server in **src/language-server/main-browser.ts**. This will mirror the regular entry point that we use to build already, but will target a browser-based context instead. We'll start with the following content: ```ts import { startLanguageServer, EmptyFileSystem } from 'langium'; -import { BrowserMessageReader, BrowserMessageWriter, createConnection } from 'vscode-languageserver/browser'; -import { createHelloWorldServices } from './hello-world-module'; +import { BrowserMessageReader, BrowserMessageWriter, createConnection } from 'vscode-languageserver/browser.js'; +// your services & module name may differ based on your language's name +import { createMiniLogoServices } from './minilogo-module.js'; declare const self: DedicatedWorkerGlobalScope; @@ -52,68 +44,117 @@ const messageWriter = new BrowserMessageWriter(self); const connection = createConnection(messageReader, messageWriter); // Inject the shared services and language-specific services -const { shared } = createHelloWorldServices({ connection, ...EmptyFileSystem }); +const { shared, MiniLogo } = createMiniLogoServices({connection, ...EmptyFileSystem }); // Start the language server with the shared services startLanguageServer(shared); ``` -Again, this is based on code that was originally produced by the yeoman generator, thus the **hello world** references. +Again, this is based on code that was originally produced by the yeoman generator, so it should look familiar. -Most of this is similar to what's in the **main.ts** file. The exceptions are the message readers & writers, and the notion of an `EmptyFileSystem` for the browser. There is a virtual file system API that we could utilize on most modern browsers, but for this tutorial we'll assume we aren't using any file system. Instead we'll have a single source 'file' located in our Monaco editor in memory. +Most of this is in line with what's contained in the **main.ts** file. The exceptions being the message readers & writers, and the notion of an `EmptyFileSystem` for the browser. There is a virtual file system API that we could utilize on most modern browsers, but for this tutorial we'll assume we aren't using any file system. Instead we'll have a single source 'file' located in memory. -We'll also need to include a library to resolve the missing `DedicatedWorkerGlobalScope`, which is normally not accessible until we update our **tsconfig.json** in our project root. We need to supplement the libs entry with `DOM` and `webworker`. From the yeoman generator example, the `lib` entry usually has just `["ESNext"]`. +We'll also need to include a library to resolve the missing `DedicatedWorkerGlobalScope`, which is normally not accessible until we update our **tsconfig.json** in our project root. We need to supplement the libs entry with `DOM` and `WebWorker`. From the yeoman generator example, the `lib` entry usually has just `["ESNext"]`. ```json { "compilerOptions": { ... - "lib": ["ESNext","DOM","webworker"] + "lib": ["ESNext", "DOM", "WebWorker"] } } ``` -Going back to the script we wrote before in our **package.json**, we're now ready to change **main.js** to **main-browser.js**: +Now that we have a new entry point for the browser, we need to add a script to our **package.json** to build a web worker for this language. The bundle this script produces will contain the language server for your language. The following script example is specific to MiniLogo, but should capture the general approach quite nicely: ```json { ... - "build:worker": "esbuild --minify ./out/language/main-browser.js --bundle --format=iife --outfile=./public/minilogo-server-worker.js" + "build:worker": "esbuild --minify ./out/language-server/main-browser.js --bundle --format=iife --outfile=./public/minilogo-server-worker.js", } ``` -Running `npm run build:worker` again, we should see the bundle is successfully generated without issue. If you're still having problems building the worker, double check that you're not coupled to `fs` or other file system dependent libraries in a related file. +Assuming `esbuild` is installed, and we've properly factored out any modules that are not suitable for a browser-based context, we should be good to go! + +Running `npm run build:worker` we should see the bundle is successfully generated without issue. If you're still having problems building the worker, double check that you're not coupled to `fs` or other file system dependent modules in a related file. Note that although our generator is still connected to using the file system, it's not relevant for the worker bundle to function. ## Setting up Monaco -Now we're going to setup Monaco, but not with Langium yet, as we want to be sure it's working first. +Now we're going to setup Monaco, but not with Langium yet, as we want to be sure it's working first before connecting the two. -For convenience, we're going to use two helper libraries from npm that wrap around some of Monaco's core functionality. +For convenience, we're going to use the Monaco Editor Wrapper (MER) to wrap around some of Monaco's core functionality, along with the Monaco Editor Workers package to assist. These packages are both maintained by TypeFox, and are designed to make it easier to use Monaco in a web-based context. We'll be using the following versions of these packages: -- [monaco-editor-wrapper](https://www.npmjs.com/package/monaco-editor-wrapper) -- [monaco-editor-workers](https://www.npmjs.com/package/monaco-editor-workers) +- [Monaco Editor Wrapper](https://www.npmjs.com/package/monaco-editor-wrapper) version **3.1.0** +- [monaco-editor-workers](https://www.npmjs.com/package/monaco-editor-workers) version **0.39.0** -Both these packages should be installed as dependencies for your language. In particular, this guide will assume that you're using version **2.1.1** or later of the monaco-editor-wrapper package, and version **0.39.0** of the monaco-editor-workers package. +Both these packages should be installed as dependencies for your language. In particular, this guide will assume that you're using version **3.1.0** or later of the monaco-editor-wrapper package, and version **0.39.0** of the monaco-editor-workers package. -Additionally, we'll want to add `express` as a development dependency (don't forget to also add `@types/express` too), since we'll be using that to run a local web server to test our standalone webpage. +Additionally, we'll want a way to serve this bundled language server. The choice of how you want to go about this is ultimately up to you. Previously we've recommended `express` as a development dependency (don't forget to also add `@types/express` too), as a powerful & lightweight NodeJS server framework. However, we'll be going with the built-in NodeJS support for standing up a web-server; however again the choice is yours here. -We'll also want to add some more scripts to our package.json to copy over the necessary files from the monaco-editor-wrapper & monaco-editor-worker into the **public** folder. We'll be referencing these library assets to setup the webpage for Langium and Monaco. +We'll also want to add some more scripts to our package.json to copy over the necessary files from the monaco-editor-wrapper & monaco-editor-worker into the **public** folder. We'll be referencing these library assets to setup the webpage for Langium + Monaco. ```json { ... - "prepare:public": "shx mkdir -p ./public && shx cp -fr ./src/static/* ./public/", - "copy:monaco-editor-wrapper": "shx cp -fr ./node_modules/monaco-editor-wrapper/bundle ./public/monaco-editor-wrapper", - "copy:monaco-workers": "shx cp -fr ./node_modules/monaco-editor-workers/dist/ ./public/monaco-editor-workers", - "build:web": "npm run build && npm run prepare:public && npm run build:worker && npm run copy:monaco-editor-wrapper && npm run copy:monaco-workers" + "prepare:public": "node scripts/prepare-public.mjs", + "build:web": "npm run build && npm run prepare:public && npm run build:worker && node scripts/copy-monaco-assets.mjs", } ``` -The last script is there to provide a convenient way to invoke all the intermediate build steps in sequence. However you'll want to wait before running the `build:web` script, as we still need to add our **static** assets to make that work. +Both scripts reference *mjs* files that need to be added as well into the scripts folder: + +**scripts/prepare-public.mjs** + +```js +import * as esbuild from 'esbuild' +import shell from 'shelljs' + +// setup & copy over css & html to public +shell.mkdir('-p', './public'); +shell.cp('-fr', './src/static/*.css', './public/'); +shell.cp('-fr', './src/static/*.html', './public'); + +// bundle minilogo.ts, and also copy to public +await esbuild.build({ + entryPoints: ['./src/static/minilogo.ts'], + minify: true, + sourcemap: true, + bundle: true, + outfile: './public/minilogo.js', +}); +``` + +**scripts/copy-monaco-assets.mjs** + +```js +import shell from 'shelljs' + +// copy workers to public +shell.mkdir('-p', './public/monaco-editor-workers/workers'); +shell.cp( + '-fr', + './node_modules/monaco-editor-workers/dist/index.js', + './public/monaco-editor-workers/index.js' +); +shell.cp( + '-fr', + './node_modules/monaco-editor-workers/dist/workers/editorWorker-es.js', + './public/monaco-editor-workers/workers/editorWorker-es.js' +); +shell.cp( + '-fr', + './node_modules/monaco-editor-workers/dist/workers/editorWorker-iife.js', + './public/monaco-editor-workers/workers/editorWorker-iife.js' +); +``` + +This saves us from writing these extra details into our package json, and focusing on the overall goal each step. -If you went with another editor you would want to make sure that the assets required for that editor will also be copied into **public** folder as part of your output. +The last script, `build:web` is there to provide a convenient way to invoke all the intermediate build steps in sequence. However you'll want to wait before running the `build:web` script, as we still need to add our **static** assets to make that work; which will come in the next step. + +As a quick note, if you went with another editor you would want to make sure that the assets required for that editor will also be copied into **public** folder as part of your output. ## Setting up a Static Page @@ -128,15 +169,30 @@ Here's the raw contents of the HTML content stored in **src/static/index.html**. - MiniLogo in Langium

MiniLogo in Langium

-
- -
+ + +
+ +
+
+
+
+
+ +
+ +
+
+ + +
+
+

@@ -144,7 +200,7 @@ Here's the raw contents of the HTML content stored in **src/static/index.html**. Langium
- + ``` @@ -157,9 +213,10 @@ html,body { font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; color: white; /* for monaco */ - margin: 8px auto; - width: 80%; - height: 80%; + margin: 0; + padding: 0; + width: 100%; + height: 100%; } h1 { text-align: center; @@ -169,6 +226,39 @@ h1 { margin: 8px auto; text-align: center; } +#page-wrapper { + display: flex; + max-width: 2000px; + margin: 4px auto; + padding: 4px; + min-height: 75vh; + justify-content: center; +} +#page-wrapper .half { + display: flex; + width: 40vw; +} +.build { + display: block; + margin: 8px auto; + width: 300px; + height: 30px; + background: none; + border: 2px #fff solid; + color: #fff; + transition: 0.3s; + font-size: 1.2rem; + border-radius: 4px; +} +.build:hover { + border-color: #6cf; + color: #6cf; + cursor: pointer; +} +.build:active { + color: #fff; + border-color: #fff; +} footer { text-align: center; color: #444; @@ -176,10 +266,21 @@ footer { margin-bottom: 16px; } @media(max-width: 1000px) { + #page-wrapper { + display: block; + } + #page-wrapper .half { + display: block; + width: auto; + } #minilogo-canvas { margin-top: 32px; } + #page-wrapper { + min-height: auto; + } } + /* for monaco */ .wrapper { display: flex; @@ -187,76 +288,85 @@ footer { height: 100%; width: 100%; } + #monaco-editor-root { flex-grow: 1; } + +#status-msg { + color: red; +} ``` -Finally, there's the actual Javascript setting up our Monaco instance (stored in **src/static/setup.js**), and for setting up Langium as well. This is the most complex part of setting up Langium + Monaco in the web, so we'll walk through the file in parts. +Finally, there's the actual Javascript setting up our Monaco instance (stored in **src/static/minilogo.ts**), and for setting up Langium as well. This is the most complex part of setting up Langium + Monaco in the web, so we'll walk through the file in parts. + +(*Update on Oct. 4th, 2023: Previously we wrote this as **src/static/setup.js**. This new file can be considered the same, but reworked into TypeScript & updated for the new versions of Langium & the MER.*) First, we need to import and setup the worker, as well as some language client wrapper configuration. -```js -import { MonacoEditorLanguageClientWrapper } from './monaco-editor-wrapper/index.js'; -import { buildWorkerDefinition } from "./monaco-editor-workers/index.js"; +```ts +import { MonacoEditorLanguageClientWrapper, UserConfig } from "monaco-editor-wrapper/bundle"; +import { buildWorkerDefinition } from "monaco-editor-workers"; +import { addMonacoStyles } from 'monaco-editor-wrapper/styles'; -buildWorkerDefinition('./monaco-editor-workers/workers', new URL('', window.location.href).href, false); +/** + * Setup Monaco's own workers and also incorporate the necessary styles for the monaco-editor + */ +function setup() { + buildWorkerDefinition( + './monaco-editor-workers/workers', + new URL('', window.location.href).href, + false + ); + addMonacoStyles('monaco-editor-styles'); +} ``` -Then, we'll want to instantiate our language client wrapper. In previous versions of the `monaco-editor-wrapper` package (before 2.0.0), configuration was performed by manually setting properties on the `MonacoEditorLanguageClientWrapper` instance. However, as of 2.1.1 (at the time of writing this), the constructor for `MonacoEditorLanguageClientWrapper` now takes a configuration object as its first argument. This configuration object allows us to set the same properties as before, but with more fine-grained control over all the properties that are set. - -The configuration itself can be quite large, so we're going to walk through the parts that will be used to build up this configuration first, and then joining the actual configuration object together afterwards. +Then, we'll want to instantiate our language client wrapper. In previous versions of the `monaco-editor-wrapper` package (before 2.0.0), configuration was performed by manually setting properties on the `MonacoEditorLanguageClientWrapper` instance. However, as of 3.1.0 (at the time of writing this), the constructor for `MonacoEditorLanguageClientWrapper` now takes a configuration object as its first argument. This configuration object allows us to set the same properties as before, but with more fine-grained control over all the properties that are set. -To start, let's mark our current language id as `minilogo`. This should match the id of the language that will be recognized by our language server. +We're going to walk through the parts that will be used to build up this configuration first, and then joining the actual configuration object together afterwards. -```js -const languageId = 'minilogo'; -``` +To start, let's keep in mind that our current language id will be `minilogo`. This should match the id of the language that will be recognized by our language server. Then, we'll want to add some static syntax highlighting. To do this we have a couple choices, using a TextMate or a [Monarch grammar](https://microsoft.github.io/monaco-editor/monarch.html). Both will provide us with the ability to parse our language, and apply styling to our tokens. However we have to choose one, we cannot use both simultaneously. This is related to how Monaco itself is configured with regards to whether we're using the VSCode API config, or the classic editor config. This makes sense to a degree, as we can only prepare the editor one way or the other. For MiniLogo, our monarch grammar will look like so: -```js -const monarchGrammar = { - // recognized keywords - keywords: [ - 'color','def','down','for','move','pen','to','up' - ], - // recognized operators - operators: [ - '-',',','*','/','+','=' - ], - // pattern for symbols we want to highlight - symbols: /-|,|\(|\)|\{|\}|\*|\/|\+|=/, - - // tokenizer itself, starts at the first 'state' (entry), which happens to be 'initial' - tokenizer: { - // initial tokenizer state - initial: [ - { regex: /#(\d|[a-fA-F])+/, action: {"token":"string"} }, - { regex: /[_a-zA-Z][\w_]*/, action: { cases: { '@keywords': {"token":"keyword"}, '@default': {"token":"string"} }} }, - { regex: /-?[0-9]+/, action: {"token":"number"} }, - // inject the rules for the 'whitespace' state here, effectively inlined - { include: '@whitespace' }, - { regex: /@symbols/, action: { cases: { '@operators': {"token":"operator"}, '@default': {"token":""} }} }, - ], - // state for parsing whitespace - whitespace: [ - { regex: /\s+/, action: {"token":"white"} }, - // for this rule, if we match, push up the next state as 'comment', advancing to the set of rules below - { regex: /\/\*/, action: {"token":"comment","next":"@comment"} }, - { regex: /\/\/[^\n\r]*/, action: {"token":"comment"} }, +```ts +/** + * Returns a Monarch grammar definition for MiniLogo + */ +function getMonarchGrammar() { + return { + keywords: [ + 'color','def','down','for','move','pen','to','up' ], - // state for parsing a comment - comment: [ - { regex: /[^\/\*]+/, action: {"token":"comment"} }, - // done with this comment, pop the current state & roll back to the previous one - { regex: /\*\//, action: {"token":"comment","next":"@pop"} }, - { regex: /[\/\*]/, action: {"token":"comment"} }, + operators: [ + '-',',','*','/','+','=' ], - } -}; + symbols: /-|,|\(|\)|\{|\}|\*|\/|\+|=/, + + tokenizer: { + initial: [ + { regex: /#(\d|[a-fA-F]){3,6}/, action: {"token":"string"} }, + { regex: /[_a-zA-Z][\w_]*/, action: { cases: { '@keywords': {"token":"keyword"}, '@default': {"token":"string"} }} }, + { regex: /(?:(?:-?[0-9]+)?\.[0-9]+)|-?[0-9]+/, action: {"token":"number"} }, + { include: '@whitespace' }, + { regex: /@symbols/, action: { cases: { '@operators': {"token":"operator"}, '@default': {"token":""} }} }, + ], + whitespace: [ + { regex: /\s+/, action: {"token":"white"} }, + { regex: /\/\*/, action: {"token":"comment","next":"@comment"} }, + { regex: /\/\/[^\n\r]*/, action: {"token":"comment"} }, + ], + comment: [ + { regex: /[^\/\*]+/, action: {"token":"comment"} }, + { regex: /\*\//, action: {"token":"comment","next":"@pop"} }, + { regex: /[\/\*]/, action: {"token":"comment"} }, + ], + } + }; +} ``` We can produce this Monarch grammar by updating our **langium-config.json** to produce a Monarch file as output. Note that although we're talking about MiniLogo here, we based this example off of the hello-world example produced by the yeoman generator. As such, we still have hello world names here and there, and for this tutorial we'll just use the same name again as for the TextMate grammar. @@ -264,138 +374,219 @@ We can produce this Monarch grammar by updating our **langium-config.json** to p ```json ... "textMate": { - "out": "syntaxes/hello-world.tmLanguage.json" + "out": "syntaxes/minilogo.tmLanguage.json" }, "monarch": { - "out": "syntaxes/hello-world.monarch.ts" + "out": "syntaxes/minilogo.monarch.ts" } ``` -To generate this file, run `npm run langium:generate`. You can then copy over the definition of the grammar from **syntaxes/hello-world.monarch.ts** (or whatever other name you have given this file) into the `setMonarchTokensProvider` function to setup that highlighting. Keep in mind that this generated monarch grammar is *very* simple. If you want more complex highlighting, we recommend writing your own custom monarch grammar, and storing it somewhere else to prevent it from being overridden. If you're interested, you can find more details about the [Monarch grammar highlighting language here](https://microsoft.github.io/monaco-editor/monarch.html). +To generate this file, run `npm run langium:generate`. You can then copy over the definition of the grammar from **syntaxes/hello-world.monarch.ts** (or whatever other name you have given this file). Keep in mind that this generated monarch grammar is *very* simple. If you want more complex highlighting, we recommend writing your own custom monarch grammar, and storing it somewhere else to prevent it from being overridden. If you're interested, you can find more details about the [Monarch grammar highlighting language here](https://microsoft.github.io/monaco-editor/monarch.html). Then, we want to setup the code that shows up by default. The following is a fixed MiniLogo program that should display a white diamond in the top left corner of the screen. -```js -const code = ` -def test() { - move(100, 0) - pen(down) - move(100, 100) - move(-100, 100) - move(-100, -100) - move(100, -100) - pen(up) +```ts +/** + * Retrieves the program code to display, either a default or from local storage + */ +function getMainCode() { + let mainCode = ` + def test() { + move(100, 0) + pen(down) + move(100, 100) + move(-100, 100) + move(-100, -100) + move(100, -100) + pen(up) + } + color(white) + test() + + `; + + // optionally: use local storage to save the code + // and seek to restore any previous code from our last session + if (window.localStorage) { + const storedCode = window.localStorage.getItem('mainCode'); + if (storedCode !== null) { + mainCode = storedCode; + } + } + + return mainCode; } -color(white) -test() -`; ``` -We'll want to setup the editor config as well. This will include configurations to setup the theme, languageId, main code, and some layout. +Since we're planning to use a language server with Monaco, we'll need to setup a language client config too. To do this we'll also need to generate a worker using our language server worker file, but that's fairly straightforward to setup here. Keep in mind that you'll need to have access to the bundle produced from your **main-browser.ts** from before. Here the built result is copied over as **public/minilogo-server-worker.js**. -```js -const editorConfig = { - languageId, - code, - useDiffEditor: false, - automaticLayout: true, - theme: 'vs-dark' -}; +```ts +/** + * Creates & returns a fresh worker using the MiniLogo language server + */ +function getWorker() { + const workerURL = new URL('minilogo-server-worker.js', window.location.href); + return new Worker(workerURL.href, { + type: 'module', + name: 'MiniLogoLS' + }); +} ``` -Since we're planning to use a language server with Monaco, we'll need to setup a language client config too. To do this we'll also need to generate a worker using our language server worker file, but that's fairly straightforward to setup here. +By creating the worker in advance, we give ourselves the ability to directly interact with the worker/LS independent of the wrapper itself, and to even pre-configure it before use. This can be hugely beneficial, especially if we expect to customize our LS on the fly. -```js -// configure the worker -const workerURL = new URL('./minilogo-server-worker.js', import.meta.url); -const lsWorker = new Worker(workerURL.href, { - type: 'classic', - name: 'minilogo-language-server-worker' -}); +Lastly, let's setup the user config, which will be used to startup the wrapper. -// setup the language client config with the worker -const languageClientConfig = { - enabled: true, - useWebSocket: false, - // can pass configuration data, or a pre-configured worker as well - // the later works better for us in this case - workerConfigOptions: lsWorker -}; -``` +```ts +type WorkerUrl = string; -We can also pass more explicit config options to `workerConfigOptions` if we don't want to create the worker ourselves. For example: +/** + * Classic configuration for the monaco editor (for use with a Monarch grammar) + */ +interface ClassicConfig { + code: string, + htmlElement: HTMLElement, + languageId: string, + worker: WorkerUrl | Worker, + monarchGrammar: any; +} -```js -{ - url: new URL('./minilogo-server-worker.js', import.meta.url), - type: 'classic', - name: 'minilogo-language-server-worker' +/** + * Generates a valid UserConfig for a given Langium example + * + * @param config An extended or classic editor config to generate a UserConfig from + * @returns A completed UserConfig + */ +function createUserConfig(config: ClassicConfig): UserConfig { + // setup urls for config & grammar + const id = config.languageId; + + // generate langium config + return { + htmlElement: config.htmlElement, + wrapperConfig: { + editorAppConfig: { + $type: 'classic', + languageId: id, + useDiffEditor: false, + code: config.code, + theme: 'vs-dark', + languageDef: config.monarchGrammar + }, + serviceConfig: { + enableModelService: true, + configureConfigurationService: { + defaultWorkspaceUri: '/tmp/' + }, + enableKeybindingsService: true, + enableLanguagesService: true, + debugLogging: false + } + }, + languageClientConfig: { + options: { + $type: 'WorkerDirect', + worker: config.worker as Worker, + name: `${id}-language-server-worker` + } + } + }; } ``` -Either case works, but by creating the worker in advance, we give ourselves the ability to directly interact with the worker/LS independent of the wrapper itself, and to even pre-configure it before use. This can hugely beneficial, especially if we expect to customize our LS on the fly. +This particular UserConfig will be for configuring a classic editor, rather than a VSCode extension-based editor. This is because we're using a Monarch grammar, which is not supported by the extension configuration. However, if we wanted to use a TextMate grammar, we could use the extension based configuration instead. -Lastly, let's put together the service config for our wrapper. Like the name suggests, this indicates what services should be enabled. It also influences whether we use the VSCode API config (with TextMate grammars) or the classic editor config (with Monarch grammars). - -```js -const serviceConfig = { - // the theme service & textmate services are dependent, they need to both be enabled or disabled together - // this explicitly disables the Monarch capabilities - // both are tied to whether we are using the VSCode config as well - enableThemeService: false, - enableTextmateService: false, - - enableModelService: true, - configureEditorOrViewsServiceConfig: { - enableViewsService: false, - useDefaultOpenEditorFunction: true - }, - configureConfigurationServiceConfig: { - defaultWorkspaceUri: '/tmp/' - }, - enableKeybindingsService: true, - enableLanguagesService: true, - // if you want debugging facilities, keep this on - debugLogging: true -}; +```json +editorAppConfig: { + $type: 'vscodeApi', + languageId: id, + useDiffEditor: false, + code: config.code, + ... +} ``` -Now, getting back to building our configuration. We have built all the parts we needed to make this work, so let's put them all together and start the wrapper. +You would just need to fill in the rest of the details for associating a TextMate grammar & such. [Here's an example from the monaco-components repo](https://github.com/TypeFox/monaco-components/blob/4f301445eca943b9775166704304637cf5e8bd00/packages/examples/src/langium/config/wrapperLangiumVscode.ts#L37). -```js -// create a client wrapper -const client = new MonacoEditorLanguageClientWrapper(); -// start the editor -// keep a reference to a promise for when the editor is finished starting, we'll use this to setup the canvas on load -const startingPromise = client.start({ - htmlElement: document.getElementById("monaco-editor-root"), - wrapperConfig: { - // setting this to false disables using the VSCode config, and instead favors - // the monaco editor config (classic editor) - useVscodeConfig: false, - serviceConfig, - // Editor config (classic) (for Monarch) - monacoEditorConfig: { - languageExtensionConfig: { id: languageId }, - languageDef: monarchGrammar - } - }, - editorConfig, - languageClientConfig -}); +Regardless of how the user config is setup, we can now invoke that helper function with a handful of configuration details, and have a working UserConfig to pass to the wrapper. + +```ts +// create a wrapper instance +const wrapper = new MonacoEditorLanguageClientWrapper(); + +// start up with a user config +await wrapper.start(createUserConfig({ + htmlElement: document.getElementById("monaco-editor-root")!, + languageId: 'minilogo', + code: getMainCode(), + worker: getWorker(), + monarchGrammar: getMonarchGrammar() +})); ``` That's it! Now if everything was configured correctly, we should have a valid wrapper that will display the code we want in our browser. -*Note the `startingPromise` that's returned from `startEditor`. We're not using this yet, but it will be important for our setup in the next tutorial.* +## Serving via NodeJS + +Now that we have our files all setup, and our build process prepared, we can put together a mini server application to make viewing our public assets easy. We'll do this by adding **src/web/app.ts** to our project, and giving it the following contents: + +```ts +/** + * Simple server app for serving generated examples locally + * Based on: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Node_server_without_framework + */ +import * as fs from "node:fs"; +import * as http from "node:http"; +import * as path from "node:path"; + +const port = 3000; -## Serving via Express +const MIME_TYPES: Record = { + default: "application/octet-stream", + html: "text/html; charset=UTF-8", + js: "application/javascript", + css: "text/css", +}; + +const STATIC_PATH = path.join(process.cwd(), "./public"); + +const toBool = [() => true, () => false]; + +const prepareFile = async (url: string) => { + const paths = [STATIC_PATH, url]; + if (url.endsWith("/")) { + paths.push("index.html"); + } + const filePath = path.join(...paths); + const pathTraversal = !filePath.startsWith(STATIC_PATH); + const exists = await fs.promises.access(filePath).then(...toBool); + const found = !pathTraversal && exists; + // there's no 404, just redirect to index.html in all other cases + const streamPath = found ? filePath : STATIC_PATH + "/index.html"; + const ext = path.extname(streamPath).substring(1).toLowerCase(); + const stream = fs.createReadStream(streamPath); + return { found, ext, stream }; +}; + +http + .createServer(async (req, res) => { + const file = await prepareFile(req.url!); + const statusCode = file.found ? 200 : 404; + const mimeType: string = MIME_TYPES[file.ext] || MIME_TYPES.default; + res.writeHead(statusCode, { "Content-Type": mimeType }); + file.stream.pipe(res); + console.log(`${req.method} ${req.url} ${statusCode}`); + }) + .listen(port); + +console.log(`Server for MiniLogo assets listening on http://localhost:${port}`); +``` -Now that we have our files all setup, and our build process prepared, we can put together a mini express application to make viewing our public assets easy. We'll do this by adding **src/web/app.ts** to our project, and giving it the following contents: +If you would like to compact this, and don't mind adding additional deps to your project, you can include `express` and `@types/express` to your project, and use the following code instead: ```ts /** - * Simple app for serving generated examples + * Simple express app for serving generated examples */ import express from 'express'; @@ -407,7 +598,7 @@ console.log(`Server for MiniLogo assets listening on http://localhost:${port}`); }); ``` -And to invoke express, we need to add one more script to our package.json. +And to invoke the server, we need to add one more script to our package.json. ```json { @@ -423,6 +614,6 @@ npm run build:web npm run serve ``` -You should be greeted with a page that contains a working Monaco instance and a small MiniLogo program in the editor. This editor has the highlighting we would expect, and also is fully connected to the language server for our language. This means we have full LSP support for operations that we would expect to have in a desktop editor. +You should be greeted with a page that contains a working Monaco instance and a small MiniLogo program in the editor. This editor has the highlighting we would expect, and also is fully connected to the language server for our language. This means we have full LSP support for operations that we would expect to have in a native IDE, such as VSCode. And that's it, we have successfully implemented Langium + Monaco in the web for our language. It's not doing much at this time besides presenting us with an editor, but in the next tutorial we'll talk about [using the same setup to add generation in the web](/tutorials/generation_in_the_web). Since our generation has already been configured natively in prior tutorials, we can use what we've written to quickly implement a web application that translates MiniLogo programs into drawing instructions for an HTML5 canvas. diff --git a/hugo/layouts/langium/list.html b/hugo/layouts/langium/list.html index 1958f237..ffea3f3b 100644 --- a/hugo/layouts/langium/list.html +++ b/hugo/layouts/langium/list.html @@ -6,7 +6,11 @@
-

{{.Title}}

+

{{.Title}} + {{if .Params.beta}} +
Beta
+ {{ end }} +

{{.Params.description}}

diff --git a/hugo/layouts/langium/showcase-page.html b/hugo/layouts/langium/showcase-page.html index 9fcffc30..eaea9c97 100644 --- a/hugo/layouts/langium/showcase-page.html +++ b/hugo/layouts/langium/showcase-page.html @@ -15,7 +15,6 @@ width: 100%; } -
diff --git a/hugo/package.json b/hugo/package.json index e8860849..029ee04c 100644 --- a/hugo/package.json +++ b/hugo/package.json @@ -7,37 +7,33 @@ "scripts": { "clean:static": "shx rm -rf ./static/showcase ./static/playground ./static/libs", "copy:libs:prepare": "shx mkdir -p ./static/libs/monaco-editor-workers/workers", - "copy:monaco-editor-wrapper": "npm run copy:libs:prepare && shx cp -fr ../node_modules/monaco-editor-wrapper/bundle ./static/libs/monaco-editor-wrapper", "copy:monaco-workers": "npm run copy:libs:prepare && shx cp -f ../node_modules/monaco-editor-workers/dist/index.* ./static/libs/monaco-editor-workers && shx cp -f ../node_modules/monaco-editor-workers/dist/workers/editorWorker-iife.js ./static/libs/monaco-editor-workers/workers", "build:worker/statemachine": "esbuild ../node_modules/langium-statemachine-dsl/out/language-server/main-browser.js --bundle --format=iife --outfile=./static/showcase/libs/worker/statemachineServerWorker.js", - "vite:build:worker/statemachine": "vite --config vite.showcase-worker.ts build", - "build:worker/monaco-editor-react": "vite --config vite.bundle-monaco-editor-react.ts build", "build:worker/arithmetics": "esbuild ../node_modules/langium-arithmetics-dsl/out/language-server/main-browser.js --bundle --format=iife --outfile=./static/showcase/libs/worker/arithmeticsServerWorker.js", "build:worker/domainmodel": "esbuild ../node_modules/langium-domainmodel-dsl/out/language-server/main-browser.js --bundle --format=iife --outfile=./static/showcase/libs/worker/domainmodelServerWorker.js", + "build:worker/lox": "esbuild ../node_modules/langium-lox/out/language-server/main-browser.js --bundle --format=iife --outfile=./static/showcase/libs/worker/loxServerWorker.js", "build:worker/playground-langium": "esbuild ./content/playground/langium-worker.ts --bundle --format=iife --outfile=./static/playground/libs/worker/langiumServerWorker.js", "build:worker/playground-user": "esbuild ./content/playground/user-worker.ts --bundle --format=iife --outfile=./static/playground/libs/worker/userServerWorker.js", "build:worker/playground-common": "esbuild ./content/playground/common.ts --bundle --format=esm --outfile=./static/playground/libs/worker/common.js", "build:worker/sql": "esbuild ./assets/scripts/sql/language-server.ts --bundle --format=iife --outfile=./static/showcase/libs/worker/sqlServerWorker.js", "build:worker/minilogo": "esbuild ../node_modules/langium-minilogo/out/language-server/main-browser.js --bundle --format=iife --outfile=./static/showcase/libs/worker/minilogoServerWorker.js", - "build:static": "npm run clean:static && npm run build:worker/monaco-editor-react && npm run build:worker/statemachine && npm run build:worker/domainmodel && npm run build:worker/sql && npm run build:worker/minilogo && npm run build:worker/arithmetics && npm run build:worker/playground-common && npm run build:worker/playground-langium && npm run build:worker/playground-user && npm run copy:monaco-editor-wrapper && npm run copy:monaco-workers", - "build": "npm run build:static && cross-env NODE_ENV=production hugo --config ./config.toml -b / -d ../public --gc --minify ", + "build:static": "npm run clean:static && npm run build:worker/statemachine && npm run build:worker/lox && npm run build:worker/domainmodel && npm run build:worker/sql && npm run build:worker/minilogo && npm run build:worker/arithmetics && npm run build:worker/playground-common && npm run build:worker/playground-langium && npm run build:worker/playground-user && npm run copy:monaco-workers", "build": "npm run build:static && cross-env NODE_ENV=production hugo --config ./config.toml -b / -d ../public --gc --minify ", "watch": "npm run build:static && cross-env NODE_ENV=development hugo server --config ./config.toml -D -b localhost:1313 -d ../public --appendPort=false", "watch:gitpod": "npm run build:static && cross-env NODE_ENV=development hugo server --config ./config.toml -D -b `gp url 1313` -d ../public --appendPort=false" }, "devDependencies": { - "@rollup/plugin-inject": "^5.0.2", + "@rollup/plugin-inject": "~5.0.4", "@types/lz-string": "^1.3.34", "@types/mustache": "^4.2.1", - "@types/react": "^18.0.25", - "@types/react-dom": "^18.0.9", - "esbuild": "^0.15.7" + "@types/react": "~18.2.28", + "@types/react-dom": "~18.2.13", + "esbuild": "~0.19.4" }, "dependencies": { "@babel/cli": "~7.19.3", "@babel/core": "~7.20.5", "@babel/preset-react": "~7.18.6", "@babel/preset-typescript": "~7.18.6", - "@typefox/monaco-editor-react": "1.1.1", "@types/d3": "^7.4.0", "clsx": "^1.2.1", "d3": "^7.8.5", @@ -48,16 +44,15 @@ "langium-minilogo": "^1.2.0", "langium-sql": "^0.2.3", "langium-statemachine-dsl": "~1.2.0", + "langium-website-core": "~1.0.0", "lz-string": "^1.4.4", - "monaco-editor-workers": "0.39.0", - "path-browserify": "~1.0.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "vite": "~4.3.9", - "vscode-languageserver": "8.0.2" + "monaco-editor-workers": "~0.44.0", + "react": "~18.2.0", + "react-dom": "~18.2.0", + "vscode-languageserver": "~8.0.2" }, "volta": { - "node": "18.16.0", - "npm": "9.6.6" + "node": "18.18.1", + "npm": "9.9.0" } } diff --git a/hugo/static/assets/Langium_Lox.svg b/hugo/static/assets/Langium_Lox.svg new file mode 100644 index 00000000..c3f1c1dc --- /dev/null +++ b/hugo/static/assets/Langium_Lox.svg @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hugo/static/custom.css b/hugo/static/custom.css index 751cda8b..2d0b36c4 100644 --- a/hugo/static/custom.css +++ b/hugo/static/custom.css @@ -210,6 +210,10 @@ h4 { font-size: 1.125rem; } +.gdoc-markdown pre code { + overflow-x: scroll; +} + .gdoc_heart { margin-left: 5px; } diff --git a/hugo/vite.showcase-worker.ts b/hugo/vite.showcase-worker.ts index c729542f..b95a9efe 100644 --- a/hugo/vite.showcase-worker.ts +++ b/hugo/vite.showcase-worker.ts @@ -7,7 +7,7 @@ const config = defineConfig({ entry: resolve(__dirname, '../node_modules/langium-statemachine-dsl/out/language-server/main-browser.js'), name: 'statemachineServerWorker', fileName: () => 'statemachineServerWorker.js', - formats: ['iife'] + formats: ['iife'] }, outDir: resolve(__dirname, 'static/showcase/libs/worker/'), emptyOutDir: false, diff --git a/package-lock.json b/package-lock.json index 757aa4f5..155d8ee0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,15 +7,65 @@ "name": "langium-website-project", "license": "MIT", "workspaces": [ + "core", "hugo", "tailwind" ], "devDependencies": { - "concurrently": "~7.6.0", + "concurrently": "~8.2.1", "cross-env": "~7.0.3", "shx": "~0.3.4" } }, + "core": { + "name": "langium-website-core", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@codingame/monaco-vscode-keybindings-service-override": "~1.83.2", + "@typefox/monaco-editor-react": "2.3.0", + "monaco-editor": "~0.44.0", + "monaco-editor-workers": "~0.44.0", + "monaco-editor-wrapper": "~3.3.0", + "monaco-languageclient": "~6.6.0", + "react": "~18.2.0", + "react-dom": "~18.2.0", + "vscode": "npm:@codingame/monaco-vscode-api@>=1.83.2 <1.84.0", + "vscode-languageserver": "~8.0.2" + }, + "devDependencies": { + "@types/react": "~18.2.28", + "@types/react-dom": "~18.2.13", + "@types/vscode": "~1.83.0", + "typescript": "~5.2.2", + "vite": "~4.4.11" + } + }, + "foundation": { + "name": "langium-website-foundation", + "version": "1.0.0", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@codingame/monaco-vscode-keybindings-service-override": "~1.83.2", + "@typefox/monaco-editor-react": "2.3.0", + "monaco-editor": "~0.44.0", + "monaco-editor-workers": "~0.44.0", + "monaco-editor-wrapper": "~3.3.0", + "monaco-languageclient": "~6.6.0", + "react": "~18.2.0", + "react-dom": "~18.2.0", + "vscode": "npm:@codingame/monaco-vscode-api@>=1.83.2 <1.84.0", + "vscode-languageserver": "~8.0.2" + }, + "devDependencies": { + "@types/react": "~18.2.28", + "@types/react-dom": "~18.2.13", + "@types/vscode": "~1.83.0", + "typescript": "~5.2.2", + "vite": "~4.4.11" + } + }, "hugo": { "name": "langium-website-hugo", "license": "MIT", @@ -24,7 +74,6 @@ "@babel/core": "~7.20.5", "@babel/preset-react": "~7.18.6", "@babel/preset-typescript": "~7.18.6", - "@typefox/monaco-editor-react": "1.1.1", "@types/d3": "^7.4.0", "clsx": "^1.2.1", "d3": "^7.8.5", @@ -35,21 +84,20 @@ "langium-minilogo": "^1.2.0", "langium-sql": "^0.2.3", "langium-statemachine-dsl": "~1.2.0", + "langium-website-core": "~1.0.0", "lz-string": "^1.4.4", - "monaco-editor-workers": "0.39.0", - "path-browserify": "~1.0.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "vite": "~4.3.9", - "vscode-languageserver": "8.0.2" + "monaco-editor-workers": "~0.44.0", + "react": "~18.2.0", + "react-dom": "~18.2.0", + "vscode-languageserver": "~8.0.2" }, "devDependencies": { - "@rollup/plugin-inject": "^5.0.2", + "@rollup/plugin-inject": "~5.0.4", "@types/lz-string": "^1.3.34", "@types/mustache": "^4.2.1", - "@types/react": "^18.0.25", - "@types/react-dom": "^18.0.9", - "esbuild": "^0.15.7" + "@types/react": "~18.2.28", + "@types/react-dom": "~18.2.13", + "esbuild": "~0.19.4" } }, "node_modules/@ampproject/remapping": { @@ -689,10 +737,83 @@ "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.4.2.tgz", "integrity": "sha512-V34dacxWLwKcvcy32dx96ADJVdB7kOJLm7LyBkBQw5u5HC9WdEFw2G17zml+U3ivavGTrGPJHl8o9/UJm0PlUw==" }, + "node_modules/@codingame/monaco-vscode-configuration-service-override": { + "version": "1.83.2", + "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-configuration-service-override/-/monaco-vscode-configuration-service-override-1.83.2.tgz", + "integrity": "sha512-I13oNZjAs3Ypmo8wQzKRwvTjFhBOYGBR107/MpZI9JJgi16t1DwfL8IaDnc2yOOwNFkVrJ44Wr2TwFKS6RhUHw==", + "dependencies": { + "monaco-editor": "0.44.0", + "vscode": "npm:@codingame/monaco-vscode-api@1.83.2" + } + }, + "node_modules/@codingame/monaco-vscode-editor-service-override": { + "version": "1.83.2", + "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-editor-service-override/-/monaco-vscode-editor-service-override-1.83.2.tgz", + "integrity": "sha512-Ou6StiX26baj98GGKDd5FIICe0pEl6RbopBlrPZ7H20F5T+d5WckEmzopBpGfrnLj/VaOHr8BT6tC3WzaNJWbw==", + "dependencies": { + "monaco-editor": "0.44.0", + "vscode": "npm:@codingame/monaco-vscode-api@1.83.2" + } + }, + "node_modules/@codingame/monaco-vscode-keybindings-service-override": { + "version": "1.83.2", + "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-keybindings-service-override/-/monaco-vscode-keybindings-service-override-1.83.2.tgz", + "integrity": "sha512-zEsTTH/H70DZzyZTu2WeLhakZ8N1W/LlPhgKxksrPluAVMeUAOaU2cuia7PXwxJ7mUtVf13W5BL4HZVwYxngrw==", + "dependencies": { + "monaco-editor": "0.44.0", + "vscode": "npm:@codingame/monaco-vscode-api@1.83.2" + } + }, + "node_modules/@codingame/monaco-vscode-languages-service-override": { + "version": "1.83.2", + "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-languages-service-override/-/monaco-vscode-languages-service-override-1.83.2.tgz", + "integrity": "sha512-re9A6EF4cHzXWGkoZcuUERr+O3JiGMEQ2UsH470gKKzsWfbcJ7Ob8u/G6F06PRZoFuTUTqeTTzL7xdPN8tnjKA==", + "dependencies": { + "monaco-editor": "0.44.0", + "vscode": "npm:@codingame/monaco-vscode-api@1.83.2" + } + }, + "node_modules/@codingame/monaco-vscode-model-service-override": { + "version": "1.83.2", + "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-model-service-override/-/monaco-vscode-model-service-override-1.83.2.tgz", + "integrity": "sha512-hWAbiOcDegRv4ft2HZHMAMisw5U4Vy6iILY3JwNN+y2tNhuRZz4aqHhHVgVz7bIz/iJtS4wmyN7aKmyXtUnokw==", + "dependencies": { + "monaco-editor": "0.44.0", + "vscode": "npm:@codingame/monaco-vscode-api@1.83.2" + } + }, + "node_modules/@codingame/monaco-vscode-textmate-service-override": { + "version": "1.83.2", + "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-textmate-service-override/-/monaco-vscode-textmate-service-override-1.83.2.tgz", + "integrity": "sha512-R7ScgN80uSmNBOHmZop+ae+dbboH3SBCPHOYOctyflD7E8UKrENwEv+4OPJqjUm+HjgrRrDDfgwNzSbvPAhjvw==", + "dependencies": { + "monaco-editor": "0.44.0", + "vscode": "npm:@codingame/monaco-vscode-api@1.83.2", + "vscode-oniguruma": "1.7.0", + "vscode-textmate": "9.0.0" + } + }, + "node_modules/@codingame/monaco-vscode-theme-defaults-default-extension": { + "version": "1.83.2", + "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-theme-defaults-default-extension/-/monaco-vscode-theme-defaults-default-extension-1.83.2.tgz", + "integrity": "sha512-PsFRBLN+ce6bP5PVkTBCTUoHMCALwBWwjDeYfsRWS6RQuIFTL9rTEzS2D1i/gRDNadWN6Emb6tce6D4Oqj+/qQ==", + "dependencies": { + "vscode": "npm:@codingame/monaco-vscode-api@1.83.2" + } + }, + "node_modules/@codingame/monaco-vscode-theme-service-override": { + "version": "1.83.2", + "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-theme-service-override/-/monaco-vscode-theme-service-override-1.83.2.tgz", + "integrity": "sha512-aJWZBrD/c12YGia43iV7JmXFc16MJ3oYS3iYBj8RByV3pWfkhgIGDCGZbenRLdf2R045X1lQ8StAVrZe88oZzw==", + "dependencies": { + "monaco-editor": "0.44.0", + "vscode": "npm:@codingame/monaco-vscode-api@1.83.2" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", - "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.4.tgz", + "integrity": "sha512-uBIbiYMeSsy2U0XQoOGVVcpIktjLMEKa7ryz2RLr7L/vTnANNEsPVAh4xOv7ondGz6ac1zVb0F8Jx20rQikffQ==", "cpu": [ "arm" ], @@ -706,12 +827,13 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", - "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "android" @@ -721,12 +843,13 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", - "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "android" @@ -736,12 +859,13 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", - "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -751,12 +875,13 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", - "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -766,12 +891,13 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", - "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -781,12 +907,13 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", - "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -796,12 +923,13 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", - "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -811,12 +939,13 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", - "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -826,12 +955,13 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", - "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "linux" @@ -841,9 +971,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", - "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.4.tgz", + "integrity": "sha512-WVhIKO26kmm8lPmNrUikxSpXcgd6HDog0cx12BUfA2PkmURHSgx9G6vA19lrlQOMw+UjMZ+l3PpbtzffCxFDRg==", "cpu": [ "loong64" ], @@ -857,12 +987,13 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", - "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", "cpu": [ "mips64el" ], + "dev": true, "optional": true, "os": [ "linux" @@ -872,12 +1003,13 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", - "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", "cpu": [ "ppc64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -887,12 +1019,13 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", - "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", "cpu": [ "riscv64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -902,12 +1035,13 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", - "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", "cpu": [ "s390x" ], + "dev": true, "optional": true, "os": [ "linux" @@ -917,12 +1051,13 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", - "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -932,12 +1067,13 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", - "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "netbsd" @@ -947,12 +1083,13 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", - "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "openbsd" @@ -962,12 +1099,13 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", - "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "sunos" @@ -977,12 +1115,13 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", - "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -992,12 +1131,13 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", - "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -1007,12 +1147,13 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", - "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -1121,9 +1262,9 @@ } }, "node_modules/@rollup/plugin-inject": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.3.tgz", - "integrity": "sha512-411QlbL+z2yXpRWFXSmw/teQRMkXcAAC8aYTemc15gwJRpvEVDQwoe+N/HTFD8RFG8+88Bme9DK2V9CVm7hJdA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.4.tgz", + "integrity": "sha512-dM93Nyqp9Ah14jvThFFA30ifjB8cDKk3Bx69M1nIIHGytXug3VrTv5HEuYBzevu45HvZ0ho7t+40bmScmkzZhg==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -1134,7 +1275,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1196,13 +1337,14 @@ } }, "node_modules/@typefox/monaco-editor-react": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@typefox/monaco-editor-react/-/monaco-editor-react-1.1.1.tgz", - "integrity": "sha512-4LiaDCU3UVH+EvypZV7YbF7Q6zpU9/tafnxBsjUZ6dcJj0187B511qMZumStSgQNisWbPT37fOStufuLQCpxTA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@typefox/monaco-editor-react/-/monaco-editor-react-2.3.0.tgz", + "integrity": "sha512-Q/V4lv1Y7IT5+Dzxz+C/LGR4FkJ5oZMY7irf4EEbI9pEjXeYCc+T1rXPvS2hj/d3ch14FIQwbL8WXQ63Y9TqjQ==", "peerDependencies": { - "monaco-editor-wrapper": "~2.1.1", + "monaco-editor": "~0.44.0", + "monaco-editor-wrapper": "~3.3.0", "react": "~18.2.0", - "react-dom": "~18.2.0" + "vscode": "npm:@codingame/monaco-vscode-api@>=1.83.2 <1.84.0" } }, "node_modules/@types/cacheable-request": { @@ -1500,9 +1642,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.18", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz", - "integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==", + "version": "18.2.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.28.tgz", + "integrity": "sha512-ad4aa/RaaJS3hyGz0BGegdnSRXQBkd1CCYDCdNjBPg90UUpLgo+WlJqb9fMYUxtehmzF3PJaTWqRZjko6BRzBg==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -1511,9 +1653,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz", - "integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.13.tgz", + "integrity": "sha512-eJIUv7rPP+EC45uNYp/ThhSpE16k22VJUknt5OLoH9tbXoi8bMhwLf5xRuWMywamNbWzhrSmU7IBJfPup1+3fw==", "dev": true, "dependencies": { "@types/react": "*" @@ -1538,6 +1680,12 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==" }, + "node_modules/@types/vscode": { + "version": "1.83.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.0.tgz", + "integrity": "sha512-3mUtHqLAVz9hegut9au4xehuBrzRE3UJiQMpoEHkNl6XHliihO7eATx2BMHs0odsmmrwjJrlixx/Pte6M3ygDQ==", + "dev": true + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2120,27 +2268,27 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concurrently": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", - "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.1.tgz", + "integrity": "sha512-nVraf3aXOpIcNud5pB9M82p1tynmZkrSGQ1p6X/VY8cJ+2LMVqAgXsJxYYefACSHbTYlm92O1xuhdGTjwoEvbQ==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "date-fns": "^2.29.1", + "chalk": "^4.1.2", + "date-fns": "^2.30.0", "lodash": "^4.17.21", - "rxjs": "^7.0.0", - "shell-quote": "^1.7.3", - "spawn-command": "^0.0.2-1", - "supports-color": "^8.1.0", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", "tree-kill": "^1.2.2", - "yargs": "^17.3.1" + "yargs": "^17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" }, "engines": { - "node": "^12.20.0 || ^14.13.0 || >=16.0.0" + "node": "^14.13.0 || >=16.0.0" }, "funding": { "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" @@ -2977,9 +3125,9 @@ } }, "node_modules/esbuild": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", - "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.4.tgz", + "integrity": "sha512-x7jL0tbRRpv4QUyuDMjONtWFciygUxWaUM1kMX2zWxI0X2YWOt7MSA0g4UdeSiHM8fcYVzpQhKYOycZwxTdZkA==", "dev": true, "hasInstallScript": true, "bin": { @@ -2989,36 +3137,36 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.15.18", - "@esbuild/linux-loong64": "0.15.18", - "esbuild-android-64": "0.15.18", - "esbuild-android-arm64": "0.15.18", - "esbuild-darwin-64": "0.15.18", - "esbuild-darwin-arm64": "0.15.18", - "esbuild-freebsd-64": "0.15.18", - "esbuild-freebsd-arm64": "0.15.18", - "esbuild-linux-32": "0.15.18", - "esbuild-linux-64": "0.15.18", - "esbuild-linux-arm": "0.15.18", - "esbuild-linux-arm64": "0.15.18", - "esbuild-linux-mips64le": "0.15.18", - "esbuild-linux-ppc64le": "0.15.18", - "esbuild-linux-riscv64": "0.15.18", - "esbuild-linux-s390x": "0.15.18", - "esbuild-netbsd-64": "0.15.18", - "esbuild-openbsd-64": "0.15.18", - "esbuild-sunos-64": "0.15.18", - "esbuild-windows-32": "0.15.18", - "esbuild-windows-64": "0.15.18", - "esbuild-windows-arm64": "0.15.18" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", - "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "@esbuild/android-arm": "0.19.4", + "@esbuild/android-arm64": "0.19.4", + "@esbuild/android-x64": "0.19.4", + "@esbuild/darwin-arm64": "0.19.4", + "@esbuild/darwin-x64": "0.19.4", + "@esbuild/freebsd-arm64": "0.19.4", + "@esbuild/freebsd-x64": "0.19.4", + "@esbuild/linux-arm": "0.19.4", + "@esbuild/linux-arm64": "0.19.4", + "@esbuild/linux-ia32": "0.19.4", + "@esbuild/linux-loong64": "0.19.4", + "@esbuild/linux-mips64el": "0.19.4", + "@esbuild/linux-ppc64": "0.19.4", + "@esbuild/linux-riscv64": "0.19.4", + "@esbuild/linux-s390x": "0.19.4", + "@esbuild/linux-x64": "0.19.4", + "@esbuild/netbsd-x64": "0.19.4", + "@esbuild/openbsd-x64": "0.19.4", + "@esbuild/sunos-x64": "0.19.4", + "@esbuild/win32-arm64": "0.19.4", + "@esbuild/win32-ia32": "0.19.4", + "@esbuild/win32-x64": "0.19.4" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-arm64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.4.tgz", + "integrity": "sha512-mRsi2vJsk4Bx/AFsNBqOH2fqedxn5L/moT58xgg51DjX1la64Z3Npicut2VbhvDFO26qjWtPMsVxCd80YTFVeg==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, @@ -3029,12 +3177,12 @@ "node": ">=12" } }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", - "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "node_modules/esbuild/node_modules/@esbuild/android-x64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.4.tgz", + "integrity": "sha512-4iPufZ1TMOD3oBlGFqHXBpa3KFT46aLl6Vy7gwed0ZSYgHaZ/mihbYb4t7Z9etjkC9Al3ZYIoOaHrU60gcMy7g==", "cpu": [ - "arm64" + "x64" ], "dev": true, "optional": true, @@ -3045,12 +3193,12 @@ "node": ">=12" } }, - "node_modules/esbuild-darwin-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", - "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.4.tgz", + "integrity": "sha512-Lviw8EzxsVQKpbS+rSt6/6zjn9ashUZ7Tbuvc2YENgRl0yZTktGlachZ9KMJUsVjZEGFVu336kl5lBgDN6PmpA==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, @@ -3061,12 +3209,12 @@ "node": ">=12" } }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", - "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "node_modules/esbuild/node_modules/@esbuild/darwin-x64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.4.tgz", + "integrity": "sha512-YHbSFlLgDwglFn0lAO3Zsdrife9jcQXQhgRp77YiTDja23FrC2uwnhXMNkAucthsf+Psr7sTwYEryxz6FPAVqw==", "cpu": [ - "arm64" + "x64" ], "dev": true, "optional": true, @@ -3077,12 +3225,12 @@ "node": ">=12" } }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", - "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.4.tgz", + "integrity": "sha512-vz59ijyrTG22Hshaj620e5yhs2dU1WJy723ofc+KUgxVCM6zxQESmWdMuVmUzxtGqtj5heHyB44PjV/HKsEmuQ==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, @@ -3093,12 +3241,12 @@ "node": ">=12" } }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", - "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.4.tgz", + "integrity": "sha512-3sRbQ6W5kAiVQRBWREGJNd1YE7OgzS0AmOGjDmX/qZZecq8NFlQsQH0IfXjjmD0XtUYqr64e0EKNFjMUlPL3Cw==", "cpu": [ - "arm64" + "x64" ], "dev": true, "optional": true, @@ -3109,12 +3257,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", - "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "node_modules/esbuild/node_modules/@esbuild/linux-arm": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.4.tgz", + "integrity": "sha512-z/4ArqOo9EImzTi4b6Vq+pthLnepFzJ92BnofU1jgNlcVb+UqynVFdoXMCFreTK7FdhqAzH0vmdwW5373Hm9pg==", "cpu": [ - "ia32" + "arm" ], "dev": true, "optional": true, @@ -3125,12 +3273,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", - "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.4.tgz", + "integrity": "sha512-ZWmWORaPbsPwmyu7eIEATFlaqm0QGt+joRE9sKcnVUG3oBbr/KYdNE2TnkzdQwX6EDRdg/x8Q4EZQTXoClUqqA==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, @@ -3141,12 +3289,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", - "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.4.tgz", + "integrity": "sha512-EGc4vYM7i1GRUIMqRZNCTzJh25MHePYsnQfKDexD8uPTCm9mK56NIL04LUfX2aaJ+C9vyEp2fJ7jbqFEYgO9lQ==", "cpu": [ - "arm" + "ia32" ], "dev": true, "optional": true, @@ -3157,12 +3305,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", - "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.4.tgz", + "integrity": "sha512-keYY+Hlj5w86hNp5JJPuZNbvW4jql7c1eXdBUHIJGTeN/+0QFutU3GrS+c27L+NTmzi73yhtojHk+lr2+502Mw==", "cpu": [ - "arm64" + "mips64el" ], "dev": true, "optional": true, @@ -3173,12 +3321,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", - "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.4.tgz", + "integrity": "sha512-tQ92n0WMXyEsCH4m32S21fND8VxNiVazUbU4IUGVXQpWiaAxOBvtOtbEt3cXIV3GEBydYsY8pyeRMJx9kn3rvw==", "cpu": [ - "mips64el" + "ppc64" ], "dev": true, "optional": true, @@ -3189,12 +3337,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", - "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.4.tgz", + "integrity": "sha512-tRRBey6fG9tqGH6V75xH3lFPpj9E8BH+N+zjSUCnFOX93kEzqS0WdyJHkta/mmJHn7MBaa++9P4ARiU4ykjhig==", "cpu": [ - "ppc64" + "riscv64" ], "dev": true, "optional": true, @@ -3205,12 +3353,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", - "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.4.tgz", + "integrity": "sha512-152aLpQqKZYhThiJ+uAM4PcuLCAOxDsCekIbnGzPKVBRUDlgaaAfaUl5NYkB1hgY6WN4sPkejxKlANgVcGl9Qg==", "cpu": [ - "riscv64" + "s390x" ], "dev": true, "optional": true, @@ -3221,12 +3369,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", - "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "node_modules/esbuild/node_modules/@esbuild/linux-x64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.4.tgz", + "integrity": "sha512-Mi4aNA3rz1BNFtB7aGadMD0MavmzuuXNTaYL6/uiYIs08U7YMPETpgNn5oue3ICr+inKwItOwSsJDYkrE9ekVg==", "cpu": [ - "s390x" + "x64" ], "dev": true, "optional": true, @@ -3237,10 +3385,10 @@ "node": ">=12" } }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", - "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.4.tgz", + "integrity": "sha512-9+Wxx1i5N/CYo505CTT7T+ix4lVzEdz0uCoYGxM5JDVlP2YdDC1Bdz+Khv6IbqmisT0Si928eAxbmGkcbiuM/A==", "cpu": [ "x64" ], @@ -3253,10 +3401,10 @@ "node": ">=12" } }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", - "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.4.tgz", + "integrity": "sha512-MFsHleM5/rWRW9EivFssop+OulYVUoVcqkyOkjiynKBCGBj9Lihl7kh9IzrreDyXa4sNkquei5/DTP4uCk25xw==", "cpu": [ "x64" ], @@ -3269,10 +3417,10 @@ "node": ">=12" } }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", - "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.4.tgz", + "integrity": "sha512-6Xq8SpK46yLvrGxjp6HftkDwPP49puU4OF0hEL4dTxqCbfx09LyrbUj/D7tmIRMj5D5FCUPksBbxyQhp8tmHzw==", "cpu": [ "x64" ], @@ -3285,12 +3433,12 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", - "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.4.tgz", + "integrity": "sha512-PkIl7Jq4mP6ke7QKwyg4fD4Xvn8PXisagV/+HntWoDEdmerB2LTukRZg728Yd1Fj+LuEX75t/hKXE2Ppk8Hh1w==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "optional": true, @@ -3301,12 +3449,12 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", - "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.4.tgz", + "integrity": "sha512-ga676Hnvw7/ycdKB53qPusvsKdwrWzEyJ+AtItHGoARszIqvjffTwaaW3b2L6l90i7MO9i+dlAW415INuRhSGg==", "cpu": [ - "x64" + "ia32" ], "dev": true, "optional": true, @@ -3317,12 +3465,12 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", - "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "node_modules/esbuild/node_modules/@esbuild/win32-x64": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.4.tgz", + "integrity": "sha512-HP0GDNla1T3ZL8Ko/SHAS2GgtjOg+VmWnnYLhuTksr++EnduYB0f3Y2LzHsUwb2iQ13JGoY6G3R8h6Du/WG6uA==", "cpu": [ - "arm64" + "x64" ], "dev": true, "optional": true, @@ -3578,6 +3726,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -4253,6 +4402,10 @@ "node": ">=14" } }, + "node_modules/langium-website-core": { + "resolved": "core", + "link": true + }, "node_modules/langium-website-hugo": { "resolved": "hugo", "link": true @@ -4523,9 +4676,9 @@ } }, "node_modules/monaco-editor": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.39.0.tgz", - "integrity": "sha512-zhbZ2Nx93tLR8aJmL2zI1mhJpsl87HMebNBM6R8z4pLfs8pj604pIVIVwyF1TivcfNtIPpMXL+nb3DsBmE/x6Q==" + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.44.0.tgz", + "integrity": "sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==" }, "node_modules/monaco-editor-comp": { "version": "1.6.0", @@ -4620,52 +4773,147 @@ } }, "node_modules/monaco-editor-workers": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/monaco-editor-workers/-/monaco-editor-workers-0.39.0.tgz", - "integrity": "sha512-luUzQPlRP7IGmC6FgR6IrHzqb2Wp0Cw+qDs1ZRdkqOJSAQf8M7+0zpKu7sd8F/NPSYHVfNIcRTIPxePxspUtTw==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/monaco-editor-workers/-/monaco-editor-workers-0.44.0.tgz", + "integrity": "sha512-rvdO292CMnxs9Y3Hl6nAjVx8d0SjcDgmXmZNVoaOCNJrdnTEEzcWcHJzEQsajTAAq4H2oeBmDZRpDE0US5DhXA==", "dependencies": { - "monaco-editor": "~0.39.0" + "monaco-editor": "~0.44.0" }, "peerDependencies": { - "monaco-editor": "~0.39.0" + "monaco-editor": "~0.44.0" } }, "node_modules/monaco-editor-wrapper": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/monaco-editor-wrapper/-/monaco-editor-wrapper-2.1.1.tgz", - "integrity": "sha512-DagfMxfYKtRUEQKKPKfM1jWwoiKzy/F91R+0dyDitLUgbsSNLsKyPpOnx42p00UWryz9anLKALCEJ4OoDivoHQ==", - "peer": true, - "dependencies": { - "monaco-languageclient": "~6.2.0", - "normalize-url": "~8.0.0" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/monaco-editor-wrapper/-/monaco-editor-wrapper-3.3.0.tgz", + "integrity": "sha512-UhGMi2mtgbMiynLnPzr4/V/pCpyohUYjzgl97obW13PW/K84XPnO0TkA7OwMqzzmDzlJlcMF8X2hB3eR1Or2/A==", + "dependencies": { + "@codingame/monaco-vscode-configuration-service-override": "~1.83.2", + "@codingame/monaco-vscode-editor-service-override": "~1.83.2", + "@codingame/monaco-vscode-textmate-service-override": "~1.83.2", + "@codingame/monaco-vscode-theme-defaults-default-extension": "~1.83.2", + "@codingame/monaco-vscode-theme-service-override": "~1.83.2", + "monaco-editor": "~0.44.0", + "monaco-languageclient": "~6.6.0", + "vscode": "npm:@codingame/monaco-vscode-api@>=1.83.2 <1.84.0", + "vscode-languageclient": "~8.1.0", + "vscode-languageserver-protocol": "~3.17.3", + "vscode-ws-jsonrpc": "~3.0.0" }, "peerDependencies": { - "monaco-languageclient": "~6.2.0", + "monaco-languageclient": "~6.6.0", "vscode-ws-jsonrpc": "~3.0.0" } }, - "node_modules/monaco-editor-wrapper/node_modules/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", - "peer": true, + "node_modules/monaco-editor-wrapper/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/monaco-editor-wrapper/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=10" + } + }, + "node_modules/monaco-editor-wrapper/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10" + } + }, + "node_modules/monaco-editor-wrapper/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/monaco-editor-wrapper/node_modules/vscode-languageclient": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.1.0.tgz", + "integrity": "sha512-GL4QdbYUF/XxQlAsvYWZRV3V34kOkpRlvV60/72ghHfsYFnS/v2MANZ9P6sHmxFcZKOse8O+L9G7Czg0NUWing==", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.3" + }, + "engines": { + "vscode": "^1.67.0" + } + }, + "node_modules/monaco-editor-wrapper/node_modules/vscode-languageclient/node_modules/vscode-languageserver-protocol": { + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.3.tgz", + "integrity": "sha512-924/h0AqsMtA5yK22GgMtCYiMdCOtWTSGgUOkgEDX+wk2b0x4sAfLiO4NxBxqbiVtz7K7/1/RgVrVI0NClZwqA==", + "dependencies": { + "vscode-jsonrpc": "8.1.0", + "vscode-languageserver-types": "3.17.3" } }, + "node_modules/monaco-editor-wrapper/node_modules/vscode-languageclient/node_modules/vscode-languageserver-types": { + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.3.tgz", + "integrity": "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==" + }, + "node_modules/monaco-editor-wrapper/node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/monaco-editor-wrapper/node_modules/vscode-languageserver-protocol/node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/monaco-editor-wrapper/node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, + "node_modules/monaco-editor-wrapper/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/monaco-languageclient": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/monaco-languageclient/-/monaco-languageclient-6.2.0.tgz", - "integrity": "sha512-hvEc4/G8gZ6ZM2SQ6xeW/UD7IdO5WioMQPY0V1lK8xEkuY9pI5oASHx4fFiYidyjrTA2ra+s5vK2swsEJxcFyA==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/monaco-languageclient/-/monaco-languageclient-6.6.0.tgz", + "integrity": "sha512-Ued2Tpj2z4NiUy8l8KVM4TAk+sd2I9e78OWdXzwNbZz6nqMSK3w5uZkY3qj3LrlERZjJAITjBdUdplDb25t+fw==", "hasInstallScript": true, - "peer": true, "dependencies": { - "monaco-editor": "~0.39.0", - "vscode": "npm:@codingame/monaco-vscode-api@1.79.3", - "vscode-jsonrpc": "~8.1.0", + "@codingame/monaco-vscode-editor-service-override": "~1.83.2", + "@codingame/monaco-vscode-languages-service-override": "~1.83.2", + "@codingame/monaco-vscode-model-service-override": "~1.83.2", + "monaco-editor": "~0.44.0", + "vscode": "npm:@codingame/monaco-vscode-api@>=1.83.2 <1.84.0", "vscode-languageclient": "~8.1.0" }, "engines": { @@ -4673,8 +4921,8 @@ "npm": ">=9.0.0" }, "peerDependencies": { - "monaco-editor": "~0.39.0", - "vscode": "npm:@codingame/monaco-vscode-api@1.79.3" + "monaco-editor": "~0.44.0", + "vscode": "npm:@codingame/monaco-vscode-api@>=1.83.2 <1.84.0" }, "peerDependenciesMeta": { "monaco-editor": { @@ -4689,7 +4937,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "peer": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -4698,7 +4945,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -4710,7 +4956,6 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "peer": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4722,7 +4967,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "peer": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -4737,7 +4981,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.1.0.tgz", "integrity": "sha512-GL4QdbYUF/XxQlAsvYWZRV3V34kOkpRlvV60/72ghHfsYFnS/v2MANZ9P6sHmxFcZKOse8O+L9G7Czg0NUWing==", - "peer": true, "dependencies": { "minimatch": "^5.1.0", "semver": "^7.3.7", @@ -4751,7 +4994,6 @@ "version": "3.17.3", "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.3.tgz", "integrity": "sha512-924/h0AqsMtA5yK22GgMtCYiMdCOtWTSGgUOkgEDX+wk2b0x4sAfLiO4NxBxqbiVtz7K7/1/RgVrVI0NClZwqA==", - "peer": true, "dependencies": { "vscode-jsonrpc": "8.1.0", "vscode-languageserver-types": "3.17.3" @@ -4760,14 +5002,12 @@ "node_modules/monaco-languageclient/node_modules/vscode-languageserver-types": { "version": "3.17.3", "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.3.tgz", - "integrity": "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==", - "peer": true + "integrity": "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==" }, "node_modules/monaco-languageclient/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "peer": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/ms": { "version": "2.1.2", @@ -4778,6 +5018,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, "funding": [ { "type": "github", @@ -4996,11 +5237,6 @@ "node": ">= 0.8" } }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -5097,6 +5333,7 @@ "version": "8.4.27", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz", "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -5505,9 +5742,10 @@ "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" }, "node_modules/rollup": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.27.0.tgz", - "integrity": "sha512-aOltLCrYZ0FhJDm7fCqwTjIUEVjWjcydKBV/Zeid6Mn8BWgDCUBBWT5beM5ieForYNo/1ZHuGJdka26kvQ3Gzg==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "dev": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -5760,14 +5998,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", "dev": true }, "node_modules/spdx-correct": { @@ -6062,6 +6301,19 @@ "node": ">= 0.6" } }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/unbzip2-stream": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", @@ -6161,13 +6413,14 @@ } }, "node_modules/vite": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", - "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.11.tgz", + "integrity": "sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==", + "dev": true, "dependencies": { - "esbuild": "^0.17.5", - "postcss": "^8.4.23", - "rollup": "^3.21.0" + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" }, "bin": { "vite": "bin/vite.js" @@ -6175,12 +6428,16 @@ "engines": { "node": "^14.18.0 || >=16.0.0" }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@types/node": ">= 14", "less": "*", + "lightningcss": "^1.21.0", "sass": "*", "stylus": "*", "sugarss": "*", @@ -6193,6 +6450,9 @@ "less": { "optional": true }, + "lightningcss": { + "optional": true + }, "sass": { "optional": true }, @@ -6208,12 +6468,13 @@ } }, "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", - "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "android" @@ -6223,12 +6484,13 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", - "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", "cpu": [ "loong64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -6238,9 +6500,10 @@ } }, "node_modules/vite/node_modules/esbuild": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", - "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -6249,58 +6512,46 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.19", - "@esbuild/android-arm64": "0.17.19", - "@esbuild/android-x64": "0.17.19", - "@esbuild/darwin-arm64": "0.17.19", - "@esbuild/darwin-x64": "0.17.19", - "@esbuild/freebsd-arm64": "0.17.19", - "@esbuild/freebsd-x64": "0.17.19", - "@esbuild/linux-arm": "0.17.19", - "@esbuild/linux-arm64": "0.17.19", - "@esbuild/linux-ia32": "0.17.19", - "@esbuild/linux-loong64": "0.17.19", - "@esbuild/linux-mips64el": "0.17.19", - "@esbuild/linux-ppc64": "0.17.19", - "@esbuild/linux-riscv64": "0.17.19", - "@esbuild/linux-s390x": "0.17.19", - "@esbuild/linux-x64": "0.17.19", - "@esbuild/netbsd-x64": "0.17.19", - "@esbuild/openbsd-x64": "0.17.19", - "@esbuild/sunos-x64": "0.17.19", - "@esbuild/win32-arm64": "0.17.19", - "@esbuild/win32-ia32": "0.17.19", - "@esbuild/win32-x64": "0.17.19" + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" } }, "node_modules/vscode": { "name": "@codingame/monaco-vscode-api", - "version": "1.79.3", - "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-api/-/monaco-vscode-api-1.79.3.tgz", - "integrity": "sha512-6cKtLozmKCRXFJH2hUaz4hMK/PsSCmYD/E+bgjIaltKMZYIjHclJyeLRmCdq8ogQaRjOzcR8yp2JMqWnP72XEw==", - "peer": true, + "version": "1.83.2", + "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-api/-/monaco-vscode-api-1.83.2.tgz", + "integrity": "sha512-wTdkrnMZV85jyZQm9PZW98JMTwhzuETALAtTiMVX9Lvw/tdrbRQC5lBZjjEytHGxhSC141rd5JcwPrDkuimZGA==", + "dependencies": { + "monaco-editor": "0.44.0" + }, "bin": { "monaco-treemending": "monaco-treemending.js" - }, - "peerDependencies": { - "monaco-editor": "0.39.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^9.0.0", - "xterm": "5.2.1", - "xterm-addon-canvas": "0.4.0", - "xterm-addon-image": "0.4.1", - "xterm-addon-search": "0.12.0", - "xterm-addon-serialize": "0.10.0", - "xterm-addon-unicode11": "0.5.0", - "xterm-addon-webgl": "0.15.0", - "yauzl": "^2.10.0" } }, "node_modules/vscode-jsonrpc": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.1.0.tgz", "integrity": "sha512-6TDy/abTQk+zDGYazgbIPc+4JoXdwC8NHU9Pbn4UJP1fehUyZmM4RHp5IthX7A6L5KS30PRui+j+tbbMMMafdw==", - "peer": true, "engines": { "node": ">=14.0.0" } @@ -6389,14 +6640,12 @@ "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "peer": true + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" }, "node_modules/vscode-textmate": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-9.0.0.tgz", - "integrity": "sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg==", - "peer": true + "integrity": "sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg==" }, "node_modules/vscode-uri": { "version": "3.0.7", @@ -6407,7 +6656,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/vscode-ws-jsonrpc/-/vscode-ws-jsonrpc-3.0.0.tgz", "integrity": "sha512-22IbVb2K691np9pOubyahNBj1BicsbtlbiaHOJu5/rvyWDqmqPMAqpAfojwGjdBztp8EtO8TAO7lmyY6hnmYAA==", - "peer": true, "dependencies": { "vscode-jsonrpc": "~8.1.0" }, @@ -6461,66 +6709,6 @@ "node": ">=0.4" } }, - "node_modules/xterm": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/xterm/-/xterm-5.2.1.tgz", - "integrity": "sha512-cs5Y1fFevgcdoh2hJROMVIWwoBHD80P1fIP79gopLHJIE4kTzzblanoivxTiQ4+92YM9IxS36H1q0MxIJXQBcA==", - "peer": true - }, - "node_modules/xterm-addon-canvas": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0.tgz", - "integrity": "sha512-iTC8CdjX9+hGX7jiEuiDMXzHsY/FKJdVnbjep5xjRXNu7RKOk15xuecIkJ7HZORqMVPpr4DGS3jyd9XUoBuxqw==", - "peer": true, - "peerDependencies": { - "xterm": "^5.0.0" - } - }, - "node_modules/xterm-addon-image": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/xterm-addon-image/-/xterm-addon-image-0.4.1.tgz", - "integrity": "sha512-iJpYyvtbHg4oXSv+D6J73ZfCjnboZpbZ567MLplXDBlYSUknv3kvPTfVMPJATV7Zsx7+bDgyXboCh9vsDf/m/w==", - "peer": true, - "peerDependencies": { - "xterm": "~5.2.0" - } - }, - "node_modules/xterm-addon-search": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/xterm-addon-search/-/xterm-addon-search-0.12.0.tgz", - "integrity": "sha512-hXAuO7Ts2+Jf9K8mZrUx8IFd7c/Flgks/jyqA1L4reymyfmXtcsd+WDLel8R9Tgy2CLyKABVBP09/Ua/FmXcvg==", - "peer": true, - "peerDependencies": { - "xterm": "^5.0.0" - } - }, - "node_modules/xterm-addon-serialize": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/xterm-addon-serialize/-/xterm-addon-serialize-0.10.0.tgz", - "integrity": "sha512-Syp9eSBypn70iAczcJ+kAi0foQIepAvFS6x53JwI4XylTBHn87Ep9fovslhwmUV3rwH2yMnpdDjXH5W/whx2lA==", - "peer": true, - "peerDependencies": { - "xterm": "^5.0.0" - } - }, - "node_modules/xterm-addon-unicode11": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xterm-addon-unicode11/-/xterm-addon-unicode11-0.5.0.tgz", - "integrity": "sha512-Jm4/g4QiTxiKiTbYICQgC791ubhIZyoIwxAIgOW8z8HWFNY+lwk+dwaKEaEeGBfM48Vk8fklsUW9u/PlenYEBg==", - "peer": true, - "peerDependencies": { - "xterm": "^5.0.0" - } - }, - "node_modules/xterm-addon-webgl": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0.tgz", - "integrity": "sha512-ZLcqogMFHr4g/YRhcCh3xE8tTklnyut/M+O/XhVsFBRB/YCvYhPdLQ5/AQk54V0wjWAQpa8CF3W8DVR9OqyMCg==", - "peer": true, - "peerDependencies": { - "xterm": "^5.0.0" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 510643e1..cb45657c 100644 --- a/package.json +++ b/package.json @@ -5,22 +5,23 @@ "license": "MIT", "private": true, "scripts": { - "watch": "concurrently -c gray,blue -k -n hugo,tailwind \"npm run watch --workspace hugo\" \"npm run watch --workspace tailwind\"", - "watch:gitpod": "concurrently -c gray,blue -k -n hugo,tailwind \"npm run watch:gitpod --workspace hugo\" \"npm run watch --workspace tailwind\"", - "build": "npm run clean && npm run build --workspace=tailwind --workspace=hugo", - "clean": "shx rm -rf public && npm run clean --workspace=tailwind" + "watch": "npm run build --workspace core && concurrently -c gray,blue -k -n hugo,tailwind \"npm run watch --workspace hugo\" \"npm run watch --workspace tailwind\"", + "watch:gitpod": "npm run build --workspace core && concurrently -c gray,blue -k -n hugo,tailwind \"npm run watch:gitpod --workspace hugo\" \"npm run watch --workspace tailwind\"", + "build": "npm run clean && npm run build --workspace core --workspace=tailwind --workspace=hugo", + "clean": "shx rm -rf public && npm run clean --workspace core --workspace=tailwind" }, "devDependencies": { - "concurrently": "~7.6.0", + "concurrently": "~8.2.1", "cross-env": "~7.0.3", "shx": "~0.3.4" }, "workspaces": [ + "core", "hugo", "tailwind" ], "volta": { - "node": "18.17.0", - "npm": "9.6.7" + "node": "18.18.1", + "npm": "9.9.0" } }