From d5e9ec7dfc6415c7578f3ae7d704d712a72bb6a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Moritz=20H=C3=B6lting?=
<87192362+moritz-hoelting@users.noreply.github.com>
Date: Thu, 20 Jun 2024 20:11:00 +0200
Subject: [PATCH] add shiki for playground highlighting
---
package.json | 3 +
pnpm-lock.yaml | 35 +-
src/assets/playground/pack.toml | 8 +
src/components/Playground.tsx | 26 +-
src/components/playground/Editor.tsx | 56 +
src/components/playground/FileView.tsx | 10 +-
src/styles/playground.scss | 2 +-
src/utils/material-ui-theme.ts | 13 +
src/utils/mcfunction-grammar.ts | 1389 ++++++++++++++++++++++++
src/utils/shiki.ts | 2 +
src/utils/shulkerscript-grammar.ts | 5 +-
11 files changed, 1523 insertions(+), 26 deletions(-)
create mode 100644 src/assets/playground/pack.toml
create mode 100644 src/components/playground/Editor.tsx
create mode 100644 src/utils/mcfunction-grammar.ts
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: [