diff --git a/package.json b/package.json index bbec9ec..7699bc4 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,16 @@ "@monaco-editor/react": "^4.6.0", "@mui/icons-material": "^5.15.20", "@mui/material": "^5.15.20", + "@shikijs/monaco": "^1.7.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "astro": "^4.10.2", "react": "^18.3.1", "react-dom": "^18.3.1", "sharp": "^0.32.6", + "shiki": "^1.7.0", "starlight-links-validator": "^0.7.1", + "tm-themes": "^1.4.3", "typescript": "^5.4.5" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46ad863..2444896 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ dependencies: '@mui/material': specifier: ^5.15.20 version: 5.15.20(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@shikijs/monaco': + specifier: ^1.7.0 + version: 1.7.0 '@types/react': specifier: ^18.3.3 version: 18.3.3 @@ -47,9 +50,15 @@ dependencies: sharp: specifier: ^0.32.6 version: 0.32.6 + shiki: + specifier: ^1.7.0 + version: 1.7.0 starlight-links-validator: specifier: ^0.7.1 version: 0.7.1(@astrojs/starlight@0.24.2)(astro@4.10.2) + tm-themes: + specifier: ^1.4.3 + version: 1.4.3 typescript: specifier: ^5.4.5 version: 5.4.5 @@ -141,7 +150,7 @@ packages: remark-parse: 11.0.0 remark-rehype: 11.1.0 remark-smartypants: 2.1.0 - shiki: 1.6.4 + shiki: 1.7.0 unified: 11.0.4 unist-util-remove-position: 5.0.0 unist-util-visit: 5.0.0 @@ -1131,7 +1140,7 @@ packages: resolution: {integrity: sha512-aFQBPepv0zhVXqJFAvfQ4vXYv/meJKiqmEEKSxdjAfwXllIV49PDlnGEXmbGYjR4hUQQjbfDgzAbrbfePc3YVQ==} dependencies: '@expressive-code/core': 0.35.3 - shiki: 1.6.4 + shiki: 1.7.0 dev: false /@expressive-code/plugin-text-markers@0.35.3: @@ -1822,8 +1831,14 @@ packages: dev: false optional: true - /@shikijs/core@1.6.4: - resolution: {integrity: sha512-WTU9rzZae1p2v6LOxMf6LhtmZOkIHYYW160IuahUyJy7YXPPjyWZLR1ag+SgD22ZMxZtz1gfU6Tccc8t0Il/XA==} + /@shikijs/core@1.7.0: + resolution: {integrity: sha512-O6j27b7dGmJbR3mjwh/aHH8Ld+GQvA0OQsNO43wKWnqbAae3AYXrhFyScHGX8hXZD6vX2ngjzDFkZY5srtIJbQ==} + dev: false + + /@shikijs/monaco@1.7.0: + resolution: {integrity: sha512-7wLuwcMhxYShdSOJ0c8z3puiwi0j9EFzCsIDWo8Q4wWc1sX2XrsGg/e4LyydwwydY4Kwc40KDgXBsX/0A211mg==} + dependencies: + '@shikijs/core': 1.7.0 dev: false /@types/acorn@4.0.6: @@ -2210,7 +2225,7 @@ packages: rehype: 13.0.1 resolve: 1.22.8 semver: 7.6.2 - shiki: 1.6.4 + shiki: 1.7.0 string-width: 7.1.0 strip-ansi: 7.1.0 tsconfck: 3.1.0(typescript@5.4.5) @@ -4989,10 +5004,10 @@ packages: engines: {node: '>=8'} dev: false - /shiki@1.6.4: - resolution: {integrity: sha512-X88chM7w8jnadoZtjPTi5ahCJx9pc9f8GfEkZAEYUTlcUZIEw2D/RY86HI/LkkE7Nj8TQWkiBfaFTJ3VJT6ESg==} + /shiki@1.7.0: + resolution: {integrity: sha512-H5pMn4JA7ayx8H0qOz1k2qANq6mZVCMl1gKLK6kWIrv1s2Ial4EmD4s4jE8QB5Dw03d/oCQUxc24sotuyR5byA==} dependencies: - '@shikijs/core': 1.6.4 + '@shikijs/core': 1.7.0 dev: false /signal-exit@3.0.7: @@ -5246,6 +5261,10 @@ packages: b4a: 1.6.6 dev: false + /tm-themes@1.4.3: + resolution: {integrity: sha512-nsUGwktLaWFMyKw2e/hNyDmcTIO+ue6Q2Mvb8L7WQkKSCflOm2TjGSspcJw6q7hi4QxQQNTuGICyvQN1UqtunQ==} + dev: false + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} diff --git a/src/assets/playground/pack.toml b/src/assets/playground/pack.toml new file mode 100644 index 0000000..9729170 --- /dev/null +++ b/src/assets/playground/pack.toml @@ -0,0 +1,8 @@ +[pack] +name = "my-shulkerscript-pack" +description = "A Minecraft datapack created with shulkerscript" +format = 48 +version = "0.1.0" + +[compiler] +# assets = "./assets" \ No newline at end of file diff --git a/src/components/Playground.tsx b/src/components/Playground.tsx index 21edfb5..49d31bd 100644 --- a/src/components/Playground.tsx +++ b/src/components/Playground.tsx @@ -1,10 +1,13 @@ import React, { useEffect, useState } from "react"; -import Editor, { useMonaco, type Monaco } from "@monaco-editor/react"; +import { useMonaco, type Monaco } from "@monaco-editor/react"; import FileView from "./playground/FileView"; +import Editor from "./playground/Editor"; import "@styles/playground.scss"; import mainFileContent from "@assets/playground/main.shu?raw"; +import packTomlContent from "@assets/playground/pack.toml?raw"; + import Header from "./playground/Header"; export type File = { @@ -24,13 +27,22 @@ export default function Playground() { files: { "main.shu": { content: mainFileContent, + language: "shulkerscript", }, }, }, + dist: { + files: { + "test.mcfunction": { + content: "", + language: "mcfunction", + } + } + } }, files: { "pack.toml": { - content: "pack.toml content", + content: packTomlContent, language: "toml", }, }, @@ -63,15 +75,7 @@ export default function Playground() { fileName={fileName} setSelectedFileName={setFileName} /> -
- -
+ ); diff --git a/src/components/playground/Editor.tsx b/src/components/playground/Editor.tsx new file mode 100644 index 0000000..0ed7695 --- /dev/null +++ b/src/components/playground/Editor.tsx @@ -0,0 +1,56 @@ +import type { File } from "@components/Playground"; +import MonacoEditor, { useMonaco } from "@monaco-editor/react"; +import { getHighlighter, type Highlighter } from "shiki"; +import { shikiToMonaco } from "@shikijs/monaco"; +import { useEffect, useState } from "react"; +import darkPlus from "tm-themes/themes/dark-plus.json"; + +import { shulkerscriptGrammar } from "@utils/shulkerscript-grammar"; +import { mcfunctionGrammar } from "@utils/mcfunction-grammar"; + +export default function Editor({ + fileName, + file, +}: { + fileName: string; + file: File; +}) { + const [highlighter, setHighlighter] = useState(null); + + const monaco = useMonaco(); + useEffect(() => { + if (monaco) { + if (highlighter == null) { + getHighlighter({ + themes: [darkPlus as any], + langs: ["toml", shulkerscriptGrammar, mcfunctionGrammar], + }).then((highlighter) => { + setHighlighter(highlighter); + }); + } else { + shikiToMonaco(highlighter, monaco); + } + + monaco.languages.register({ id: "toml" }); + monaco.languages.register({ id: "shulkerscript" }); + monaco.languages.register({ id: "mcfunction" }); + } + }, [monaco]); + useEffect(() => { + if (highlighter != null) { + shikiToMonaco(highlighter, monaco); + } + }, [highlighter]); + + return ( +
+ +
+ ); +} diff --git a/src/components/playground/FileView.tsx b/src/components/playground/FileView.tsx index 3f81b43..0828b8b 100644 --- a/src/components/playground/FileView.tsx +++ b/src/components/playground/FileView.tsx @@ -90,11 +90,11 @@ function DirElement({ ([dirname, dir]) => { return ( { return ( modSetSelectedFileName(currentName) diff --git a/src/styles/playground.scss b/src/styles/playground.scss index 2ef94ac..edb655b 100644 --- a/src/styles/playground.scss +++ b/src/styles/playground.scss @@ -1,6 +1,6 @@ .playground { display: grid; - grid-template-columns: 1fr 4fr; + grid-template-columns: clamp(100px, 15%, 400px) auto; grid-template-areas: "header header" "files editor"; diff --git a/src/utils/material-ui-theme.ts b/src/utils/material-ui-theme.ts index 914087b..b3a16ad 100644 --- a/src/utils/material-ui-theme.ts +++ b/src/utils/material-ui-theme.ts @@ -15,4 +15,17 @@ export const customTheme = createTheme({ contrastText: '#000', }, }, + typography: { + fontFamily: [ + '-apple-system', + 'BlinkMacSystemFont', + '"Segoe UI"', + '"Helvetica Neue"', + 'Arial', + 'sans-serif', + '"Apple Color Emoji"', + '"Segoe UI Emoji"', + '"Segoe UI Symbol"', + ].join(','), + }, }); diff --git a/src/utils/mcfunction-grammar.ts b/src/utils/mcfunction-grammar.ts new file mode 100644 index 0000000..11b763d --- /dev/null +++ b/src/utils/mcfunction-grammar.ts @@ -0,0 +1,1389 @@ +import type { LanguageInput } from "shiki"; + +export const mcfunctionGrammar: LanguageInput = { + name: "mcfunction", + scopeName: "source.mcfunction", + displayName: "McFunction", + fileTypes: ["mcfunction"], + patterns: [ + { + include: "#comment", + }, + { + include: "#command", + }, + { + include: "#unknown", + }, + ], + repository: { + "$base": {}, + "$self": {}, + comment: { + patterns: [ + { + name: "meta.comment.block.mcfunction", + begin: "^[ \\t]*((#)([\\#\\>\\~\\!\\@\\$\\%\\^\\*]+)((.*)))$", + end: "^(?![ \\t]*#)", + beginCaptures: { + 1: { + name: "comment.block.mcfunction", + }, + 2: { + name: "markup.list.mcfunction", + }, + 3: { + name: "markup.list.mcfunction", + }, + 4: { + name: "markup.bold.mcfunction", + }, + 5: { + name: "markup.list.mcfunction", + }, + }, + patterns: [ + { + include: "#comment.block", + }, + ], + }, + { + name: "meta.comment.line.mcfunction", + match: "^[ \\t]*(#.*)$", + captures: { + 1: { + name: "comment.line.mcfunction", + }, + }, + }, + ], + }, + "comment.block": { + patterns: [ + { + name: "meta.comment.block_line.mcfunction", + begin: "^[ \\t]*((#)[ \\t]*)", + end: "$", + beginCaptures: { + 1: { + name: "comment.block.mcfunction", + }, + 2: { + name: "markup.list.mcfunction", + }, + }, + patterns: [ + { + include: "#comment.block.line", + }, + ], + }, + ], + }, + "comment.block.line": { + patterns: [ + { + name: "meta.comment.block.annotation.mcfunction", + match: "((\\@\\w*)\\b(.*))$", + captures: { + 1: { + name: "comment.block.mcfunction", + }, + 2: { + name: "markup.heading.mcfunction", + }, + 3: { + name: "comment.block.mcfunction", + }, + }, + }, + { + name: "meta.comment.block.heading.mcfunction", + match: "(([\\#\\>\\~\\!\\@\\$\\%\\^\\*]+)((.*)))$", + captures: { + 1: { + name: "comment.block.mcfunction", + }, + 2: { + name: "markup.list.mcfunction", + }, + 3: { + name: "markup.bold.mcfunction", + }, + 4: { + name: "markup.list.mcfunction", + }, + }, + }, + { + name: "meta.comment.block.text.mcfunction", + match: "(.*)$", + captures: { + 1: { + name: "comment.block.mcfunction", + }, + }, + }, + ], + }, + command: { + patterns: [ + { + name: "meta.command.mcfunction", + begin: "^\\s*([a-z_][a-z0-9_]*)[ \\n]", + end: "$", + beginCaptures: { + 1: { + name: "keyword.control.mcfunction", + }, + }, + patterns: [ + { + begin: "(?<= )", + end: "[ \\n]", + contentName: "meta.command.token.mcfunction", + patterns: [ + { + include: "#command.tokens", + }, + ], + }, + ], + }, + ], + }, + unknown: { + patterns: [ + { + name: "meta.unknown.mcfunction", + match: "^(.*)$", + captures: { + 1: { + name: "invalid.illegal.mcfunction", + }, + }, + }, + ], + }, + "command.tokens": { + patterns: [ + { + include: "#command.token.nbt_compound", + }, + { + include: "#command.token.nbt_list", + }, + { + include: "#command.token.selector_with_arguments", + }, + { + include: "#command.token.selector_without_arguments", + }, + { + include: "#command.token.block_predicate", + }, + { + include: "#command.token.block_predicate_without_namespace", + }, + { + include: "#command.token.resource_location", + }, + { + include: "#command.token.tagged_resource_location", + }, + { + include: "#command.token.range", + }, + { + include: "#command.token.number", + }, + { + include: "#command.token.coordinate", + }, + { + include: "#command.token.boolean", + }, + { + include: "#command.token.operation", + }, + { + include: "#command.token.root_redirect", + }, + { + include: "#command.token.greedy_parent", + }, + { + include: "#command.token.literal", + }, + { + include: "#command.token.uuid", + }, + { + include: "#command.token.fakeplayer", + }, + { + include: "#command.token.nbt_path", + }, + { + include: "#command.token.quoted_string", + }, + { + include: "#command.token.single_quoted_string", + }, + { + include: "#command.token.unquoted_string", + }, + { + include: "#command.token.unknown", + }, + ], + }, + "command.token.selector_without_arguments": { + name: "meta.command.token.selector_without_arguments.mcfunction", + match: "(?<= )(\\@[a-z])(?=[ \\n]|$)", + captures: { + 1: { + name: "support.class.mcfunction", + }, + }, + }, + "command.token.resource_location": { + name: "meta.command.token.resource_location.mcfunction", + match: "(?<= )([a-z0-9_\\.\\-]+)(\\:)([a-z0-9_\\.\\-\\/]+)(?=[ \\n]|$)", + captures: { + 1: { + name: "entity.name.function.mcfunction", + }, + 2: { + name: "entity.name.function.mcfunction", + }, + 3: { + name: "entity.name.function.mcfunction", + }, + }, + }, + "command.token.tagged_resource_location": { + name: "meta.command.token.tagged_resource_location.mcfunction", + match: "(?<= )(\\#)([a-z0-9_\\.\\-]+)(\\:)([a-z0-9_\\.\\-\\/]+)(?=[ \\n]|$)", + captures: { + 1: { + name: "entity.name.function.mcfunction", + }, + 2: { + name: "entity.name.function.mcfunction", + }, + 3: { + name: "entity.name.function.mcfunction", + }, + 4: { + name: "entity.name.function.mcfunction", + }, + }, + }, + "command.token.range": { + name: "meta.command.token.range.mcfunction", + match: "(?<= )(\\-?\\d*\\.?\\d+)?(\\.\\.)(\\-?\\d*\\.?\\d+)?(?=[ \\n]|$)", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + 2: { + name: "keyword.control.mcfunction", + }, + 3: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "command.token.number": { + name: "meta.command.token.number.mcfunction", + match: "(?<= )(\\-?\\d*\\.?\\d+)(?=[ \\n]|$)", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "command.token.coordinate": { + name: "meta.command.token.coordinate.mcfunction", + match: "(?<= )([\\~\\^])(\\-?\\d*\\.?\\d+)?(?=[ \\n]|$)", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + 2: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "command.token.boolean": { + name: "meta.command.token.boolean.mcfunction", + match: "(?<= )(true|false)(?=[ \\n]|$)", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "command.token.operation": { + name: "meta.command.token.operation.mcfunction", + match: "(?<= )(\\%\\=|\\*\\=|\\+\\=|\\-\\=|\\/\\=|\\<|\\=|\\>|\\>\\<|\\<\\=|\\>\\=)(?=[ \\n]|$)", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "command.token.literal": { + name: "meta.command.token.literal.mcfunction", + match: "(?<= )([a-z_][a-z0-9_]*)(?=[ \\n]|$)", + captures: { + 1: { + name: "entity.name.mcfunction", + }, + }, + }, + "command.token.uuid": { + name: "meta.command.token.uuid.mcfunction", + match: "(?<= )([0-9a-fA-F]+(?:(-)[0-9a-fA-F]+){4})(?=[ \\n]|$)", + captures: { + 1: { + name: "support.class.mcfunction", + }, + }, + }, + "command.token.fakeplayer": { + name: "meta.command.token.fakeplayer.mcfunction", + match: "(?<= )([\\#\\$\\%]\\S+)(?=[ \\n]|$)", + captures: { + 1: { + name: "support.class.mcfunction", + }, + }, + }, + "command.token.unquoted_string": { + name: "meta.command.token.unquoted_string.mcfunction", + match: "(?<= )(\\S+)(?=[ \\n]|$)", + captures: { + 1: { + name: "string.unquoted.mcfunction", + }, + }, + }, + "command.token.unknown": { + name: "meta.command.token.unknown.mcfunction", + match: "(?<= )([^ \\n]*)(?=[ \\n]|$)", + captures: { + 1: { + name: "invalid.illegal.mcfunction", + }, + }, + }, + "command.token.root_redirect": { + name: "meta.command.token.root_redirect.mcfunction", + match: "(?<= )(run) ([a-z_][a-z0-9_]*)?(?=[ \\n]|$)", + captures: { + 1: { + name: "entity.name.mcfunction", + }, + 2: { + name: "keyword.control.mcfunction", + }, + }, + }, + "command.token.greedy_parent": { + name: "meta.command.token.greedy_parent.mcfunction", + match: "((?<=^say | say ))(.*)$", + captures: { + 1: { + name: "entity.name.mcfunction", + }, + 2: { + name: "string.quoted.mcfunction", + }, + }, + }, + "command.token.nbt_compound": { + name: "meta.command.token.nbt_compound.mcfunction", + begin: "(?<= )(\\{)", + end: "(?=\\n)|(\\})([^ \\n]*)", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.compound", + }, + ], + }, + "command.token.nbt_list": { + name: "meta.command.token.nbt_list.mcfunction", + begin: "(?<= )(\\[)(\\w*;)?", + end: "(?=\\n)|(\\])([^ \\n]*)", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.list", + }, + ], + }, + "nbt.compound": { + patterns: [ + { + match: " +", + }, + { + begin: '(,)? *([A-Za-z0-9_\\.\\-]+|\\"[^\\n\\"]+\\") *(\\:) *', + end: " *(?=[\\n\\}\\,])", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "string.interpolated.mcfunction", + }, + 3: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.value", + }, + ], + }, + { + match: "[^\\n\\}\\,]+", + name: "invalid.illegal.mcfunction", + }, + ], + }, + "nbt.list": { + patterns: [ + { + match: " +", + }, + { + begin: "(,)? *(?=[^\\n\\]\\,])", + end: " *(?=[\\n\\]\\,])", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.value", + }, + ], + }, + { + match: "[^\\n\\]\\,]+", + name: "invalid.illegal.mcfunction", + }, + ], + }, + "nbt.value": { + patterns: [ + { + begin: "(\\{)", + end: "(?=\\n)|(\\})", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.compound", + }, + ], + }, + { + begin: "(\\[)(\\w*;)?", + end: "(?=\\n)|(\\])", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.list", + }, + ], + }, + { + begin: '(\\")', + end: '(?=\\n)|(\\")', + beginCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + }, + patterns: [ + { + include: "#common.quoted_string", + }, + ], + }, + { + begin: "(\\')", + end: "(?=\\n)|(\\')", + beginCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + }, + patterns: [ + { + include: "#common.single_quoted_string", + }, + ], + }, + { + match: "(true|false)", + name: "constant.numeric.mcfunction", + }, + { + match: "(\\-?\\d*\\.?\\d+)", + name: "constant.numeric.mcfunction", + }, + { + match: "([^\\s\\{\\}\\[\\]\\,\\:\\=]+)", + name: "string.unquoted.mcfunction", + }, + { + match: "[^\\n\\,\\]\\}]+", + name: "invalid.illegal.mcfunction", + }, + ], + }, + "command.token.quoted_string": { + name: "meta.command.token.quoted_string.mcfunction", + begin: '(?<= )(\\")', + end: '(?=\\n)|(\\")([^ \\n]*)', + beginCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#common.quoted_string", + }, + ], + }, + "command.token.single_quoted_string": { + name: "meta.command.token.single_quoted_string.mcfunction", + begin: "(?<= )(\\')", + end: "(?=\\n)|(\\')([^ \\n]*)", + beginCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#common.single_quoted_string", + }, + ], + }, + "command.token.block_predicate": { + name: "meta.command.token.block_predicate.mcfunction", + begin: "(?<= )(?=(\\#)?([a-z0-9_\\.\\-]+)(\\:)([a-z0-9_\\.\\-\\/]+)(\\[|\\{))", + end: "(?=\\n)|(?:(?<=\\])(?!\\{)|(?<=\\}))([^ \\n]*)", + endCaptures: { + 1: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#block_predicate", + }, + ], + }, + "command.token.block_predicate_without_namespace": { + name: "meta.command.token.block_predicate_without_namespace.mcfunction", + begin: "(?<= )(?=(\\#)?([a-z0-9_\\.\\-\\/]+)(\\[ *([a-z_][a-z0-9_]*) *\\=))", + end: "(?=\\n)|(?:(?<=\\])(?!\\{)|(?<=\\}))([^ \\n]*)", + endCaptures: { + 1: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#block_predicate", + }, + ], + }, + "command.token.selector_with_arguments": { + name: "meta.command.token.selector_with_arguments.mcfunction", + begin: "(?<= )(\\@[a-z])(\\[)", + end: "(?=\\n)|(\\])([^ \\n]*)", + beginCaptures: { + 1: { + name: "support.class.mcfunction", + }, + 2: { + name: "support.class.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "support.class.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + name: "meta.selector.argument_spacing.mcfunction", + match: " +", + }, + { + name: "meta.selector.argument.mcfunction", + begin: "((?:[a-z_][a-z0-9_]*)|(?:\"[^\"\n]*\")|(?:\\'[^\\'\n]*\\')) *(\\=) *(\\!)? *", + end: "( *\\,)(?=[\\]\\n])|( *\\,)|(?= *[\\]\\n])", + beginCaptures: { + 1: { + name: "variable.other.mcfunction", + }, + 2: { + name: "support.class.mcfunction", + }, + 3: { + name: "keyword.control.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "invalid.illegal.mcfunction", + }, + 2: { + name: "support.class.mcfunction", + }, + }, + patterns: [ + { + include: "#selector.argument.resource_location", + }, + { + include: + "#selector.argument.tagged_resource_location", + }, + { + include: "#selector.argument.range", + }, + { + include: "#selector.argument.number", + }, + { + include: "#selector.argument.boolean", + }, + { + include: "#selector.argument.property_map", + }, + { + include: "#selector.argument.nbt_compound", + }, + { + include: "#selector.argument.quoted_string", + }, + { + include: "#selector.argument.single_quoted_string", + }, + { + include: "#selector.argument.unquoted_string", + }, + { + include: "#selector.argument.unknown", + }, + ], + }, + { + name: "invalid.illegal.mcfunction", + match: "[^\\]\\n]+", + }, + ], + }, + "command.token.nbt_path": { + name: "meta.command.token.nbt_path.mcfunction", + begin: "(?<= )(?=\\w+[\\.\\[\\{])", + end: "(?=[ \\n]|$)", + patterns: [ + { + include: "#nbt_path.property", + }, + ], + }, + "nbt_path.property": { + patterns: [ + { + begin: "(\\.)?(\\w+)?(\\[)", + end: "(\\])|(?=\\n)", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "string.interpolated.mcfunction", + }, + 3: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt_path.index", + }, + ], + }, + { + begin: "(\\.)?(\\w+)(\\{)", + end: "(\\})|(?=\\n)", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "string.interpolated.mcfunction", + }, + 3: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.compound", + }, + ], + }, + { + begin: '(\\")', + end: '(?=\\n)|(\\")([^\\. \\n]*)', + beginCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#common.quoted_string", + }, + ], + }, + { + match: "(\\.)?(\\w+)", + captures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "string.interpolated.mcfunction", + }, + }, + }, + { + match: "(\\.)(?=\\.)", + captures: { + 1: { + name: "invalid.illegal.mcfunction", + }, + }, + }, + { + match: "[^\\.\\s]+", + name: "invalid.illegal.mcfunction", + }, + ], + }, + "nbt_path.index": { + patterns: [ + { + match: "(?<=\\[)(\\-?\\d+)(?=\\])", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + { + begin: "(\\{)", + end: "(?=\\n)|(\\})([^\\]\\,\\n]*)", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.compound", + }, + ], + }, + { + match: "[^\\n\\]]+", + name: "invalid.illegal.mcfunction", + }, + ], + }, + block_predicate: { + patterns: [ + { + match: "(\\#)([a-z0-9_\\.\\-]+)(\\:)([a-z0-9_\\.\\-\\/]+)", + captures: { + 1: { + name: "entity.name.function.mcfunction", + }, + 2: { + name: "entity.name.function.mcfunction", + }, + 3: { + name: "entity.name.function.mcfunction", + }, + 4: { + name: "entity.name.function.mcfunction", + }, + }, + }, + { + match: "([a-z0-9_\\.\\-]+)(\\:)([a-z0-9_\\.\\-\\/]+)", + captures: { + 1: { + name: "entity.name.function.mcfunction", + }, + 2: { + name: "entity.name.function.mcfunction", + }, + 3: { + name: "entity.name.function.mcfunction", + }, + }, + }, + { + match: "([a-z0-9_\\.\\-\\/]+)", + captures: { + 1: { + name: "entity.name.function.mcfunction", + }, + }, + }, + { + begin: "(\\[)", + end: "(\\])", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#block_predicate.arguments", + }, + ], + }, + { + begin: "(\\{)", + end: "(\\})", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.compound", + }, + ], + }, + ], + }, + "block_predicate.arguments": { + patterns: [ + { + name: "meta.block_predicate.argument_spacing.mcfunction", + match: " +", + }, + { + name: "meta.block_predicate.argument.mcfunction", + begin: "([a-z_][a-z0-9_]*) *(\\=) *", + end: "(\\,)(?=[\\]\\n])|(\\,)|(?=[\\]\\n])", + beginCaptures: { + 1: { + name: "variable.other.mcfunction", + }, + 2: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "invalid.illegal.mcfunction", + }, + 2: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#block_predicate.argument.number", + }, + { + include: "#block_predicate.argument.boolean", + }, + { + include: "#block_predicate.argument.literal", + }, + ], + }, + ], + }, + "block_predicate.argument.number": { + name: "meta.block_predicate.argument.number.mcfunction", + match: "(\\-?\\d*\\.?\\d+)(?= *[\\,\\]\\n])", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "block_predicate.argument.boolean": { + name: "meta.block_predicate.argument.boolean.mcfunction", + match: "(true|false)(?= *[\\,\\]\\n])", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "block_predicate.argument.literal": { + name: "meta.block_predicate.argument.literal.mcfunction", + match: "([a-z_][a-z0-9_]*)(?= *[\\,\\]\\n])", + captures: { + 1: { + name: "entity.name.mcfunction", + }, + }, + }, + "selector.argument.resource_location": { + name: "meta.selector.argument.resource_location.mcfunction", + match: "([a-z0-9_\\.\\-]+)(\\:)([a-z0-9_\\.\\-\\/]+)(?= *[\\,\\]\\n])", + captures: { + 1: { + name: "entity.name.function.mcfunction", + }, + 2: { + name: "entity.name.function.mcfunction", + }, + 3: { + name: "entity.name.function.mcfunction", + }, + }, + }, + "selector.argument.tagged_resource_location": { + name: "meta.selector.argument.tagged_resource_location.mcfunction", + match: "(\\#)([a-z0-9_\\.\\-]+)(\\:)([a-z0-9_\\.\\-\\/]+)(?= *[\\,\\]\\n])", + captures: { + 1: { + name: "entity.name.function.mcfunction", + }, + 2: { + name: "entity.name.function.mcfunction", + }, + 3: { + name: "entity.name.function.mcfunction", + }, + 4: { + name: "entity.name.function.mcfunction", + }, + }, + }, + "selector.argument.range": { + name: "meta.selector.argument.range.mcfunction", + match: "(\\-?\\d*\\.?\\d+)?(\\.\\.)(\\-?\\d*\\.?\\d+)?(?= *[\\,\\]\\n])", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + 2: { + name: "keyword.control.mcfunction", + }, + 3: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "selector.argument.number": { + name: "meta.selector.argument.number.mcfunction", + match: "(\\-?\\d*\\.?\\d+)(?= *[\\,\\]\\n])", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "selector.argument.boolean": { + name: "meta.selector.argument.boolean.mcfunction", + match: "(true|false)(?= *[\\,\\]\\n])", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + "selector.argument.unquoted_string": { + name: "meta.selector.argument.unquoted_string.mcfunction", + match: "([^\\s\\{\\}\\[\\]\\,\\:\\=\\!]+)(?= *[\\,\\]\\n])", + captures: { + 1: { + name: "string.unquoted.mcfunction", + }, + }, + }, + "selector.argument.unknown": { + name: "meta.selector.argument.unknown.mcfunction", + match: "([^\\]\\n\\,]+)", + captures: { + 1: { + name: "invalid.illegal.mcfunction", + }, + }, + }, + "selector.argument.quoted_string": { + name: "meta.selector.argument.quoted_string.mcfunction", + begin: '(\\")', + end: '(?=\\n)|(\\") *([^\\]\\,\\n]*)', + beginCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#common.quoted_string", + }, + ], + }, + "selector.argument.single_quoted_string": { + name: "meta.selector.argument.single_quoted_string.mcfunction", + begin: "(\\')", + end: "(?=\\n)|(\\') *([^\\]\\,\\n]*)", + beginCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "string.quoted.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#common.single_quoted_string", + }, + ], + }, + "selector.argument.property_map": { + name: "meta.selector.argument.property_map.mcfunction", + begin: "(\\{)(?= *([a-z0-9_\\.\\-]+\\:[a-z0-9_\\.\\-\\/]+|[a-z0-9_\\.\\-\\/]+|([A-Za-z0-9_\\.\\-]+)) *(\\=))", + end: "(?=\\n)|(\\}) *([^\\]\\,\\n]*)", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#property_map", + }, + ], + }, + "selector.argument.nbt_compound": { + name: "meta.selector.argument.nbt_compound.mcfunction", + begin: "(\\{)", + end: "(?=\\n)|(\\}) *([^\\]\\,\\n]*)", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#nbt.compound", + }, + ], + }, + property_map: { + patterns: [ + { + match: " +", + }, + { + begin: "(,)? *([A-Za-z0-9_\\.\\-]+) *(\\=) *", + end: " *(?=[\\n\\}\\,])", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "entity.name.function.mcfunction", + }, + 3: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#property_map.values", + }, + ], + }, + { + begin: "(,)? *([a-z0-9_\\.\\-]+\\:[a-z0-9_\\.\\-\\/]+|[a-z0-9_\\.\\-\\/]+) *(\\=) *", + end: " *(?=[\\n\\}\\,])", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "entity.name.function.mcfunction", + }, + 3: { + name: "variable.language.mcfunction", + }, + }, + patterns: [ + { + include: "#property_map.values", + }, + ], + }, + { + match: "[^\\n\\}\\,]+", + name: "invalid.illegal.mcfunction", + }, + ], + }, + "property_map.values": { + patterns: [ + { + match: "(true|false)", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + { + match: "(\\-?\\d*\\.?\\d+)?(\\.\\.)(\\-?\\d*\\.?\\d+)?", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + 2: { + name: "keyword.control.mcfunction", + }, + 3: { + name: "constant.numeric.mcfunction", + }, + }, + }, + { + match: "(\\-?\\d*\\.?\\d+)", + captures: { + 1: { + name: "constant.numeric.mcfunction", + }, + }, + }, + { + begin: "(\\{) *", + end: "(?=\\n)|(\\}) *([^\\}\\,\\n]*)", + beginCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + }, + endCaptures: { + 1: { + name: "variable.language.mcfunction", + }, + 2: { + name: "invalid.illegal.mcfunction", + }, + }, + patterns: [ + { + include: "#property_map", + }, + ], + }, + ], + }, + "common.quoted_string": { + patterns: [ + { + match: '[^\\\\\\"\\n]', + name: "string.quoted.mcfunction", + }, + { + match: "\\\\[^\\n]", + name: "constant.character.escape.mcfunction", + }, + { + match: "\\\\", + name: "invalid.illegal.mcfunction", + }, + ], + }, + "common.single_quoted_string": { + patterns: [ + { + match: "[^\\\\\\'\\n]", + name: "string.quoted.mcfunction", + }, + { + match: "\\\\[^\\n]", + name: "constant.character.escape.mcfunction", + }, + { + match: "\\\\", + name: "invalid.illegal.mcfunction", + }, + ], + }, + }, +}; diff --git a/src/utils/shiki.ts b/src/utils/shiki.ts index 7b94868..9e4ca14 100644 --- a/src/utils/shiki.ts +++ b/src/utils/shiki.ts @@ -1,9 +1,11 @@ import type { PluginShikiOptions } from "@astrojs/starlight/expressive-code"; import { shulkerscriptGrammar } from "./shulkerscript-grammar"; +import { mcfunctionGrammar } from "./mcfunction-grammar"; const config: PluginShikiOptions = { langs: [ shulkerscriptGrammar, + mcfunctionGrammar, ], }; diff --git a/src/utils/shulkerscript-grammar.ts b/src/utils/shulkerscript-grammar.ts index f23caae..409a7d8 100644 --- a/src/utils/shulkerscript-grammar.ts +++ b/src/utils/shulkerscript-grammar.ts @@ -1,5 +1,6 @@ +import type { LanguageInput } from "shiki"; -export const shulkerscriptGrammar = { +export const shulkerscriptGrammar: LanguageInput = { name: "shulkerscript", aliases: ["shu"], displayName: "ShulkerScript", @@ -23,6 +24,8 @@ export const shulkerscriptGrammar = { } ], repository: { + "$base": {}, + "$self": {}, // Groupings functionContents: { patterns: [