diff --git a/dist/mcfunction-highlight.min.js b/dist/mcfunction-highlight.min.js index 328fe2c..16feb39 100644 --- a/dist/mcfunction-highlight.min.js +++ b/dist/mcfunction-highlight.min.js @@ -1 +1 @@ -!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.MCFunctionHighlight=n():e.MCFunctionHighlight=n()}(this,(()=>(()=>{var e={723:(e,n)=>{const t={highlight:e=>e.trimEnd().split("\n").map((e=>e.trim()?e.trim().startsWith("#")?`
${this.highlight(e)}`},getCSS:()=>"\n.mcfunction-viewer {\n font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;\n background: #1e1e1e !important;\n color: #d4d4d4;\n text-shadow: 0 1px rgba(0, 0, 0, 0.3);\n text-align: left;\n white-space: pre;\n word-spacing: normal;\n word-break: normal;\n line-height: 1.5;\n tab-size: 4;\n hyphens: none;\n padding: 1em;\n margin: 0;\n overflow: hidden;\n border-radius: 0.3em;\n position: relative;\n display: flex;\n min-height: 50px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.mcfunction-content {\n overflow: auto;\n padding-right: 20px;\n flex: 1;\n min-width: 0;\n width: 100%;\n}\n\n.mcfunction-viewer .command { color: #ffaa00; font-weight: bold; }\n.mcfunction-viewer .selector { color: #55ffff; }\n.mcfunction-viewer .coordinates { color: #55ff55; }\n.mcfunction-viewer .string { color: #ff5555; }\n.mcfunction-viewer .comment { color: #7f7f7f; }\n.mcfunction-viewer .number { color: #55ff55; }\n.mcfunction-viewer .execute-modifier { color: #ff55ff; }\n.mcfunction-viewer .execute-condition { color: #ff5555; }\n.mcfunction-viewer .parameter { color: #55ffff; }\n.mcfunction-viewer .dimension { color: #55ffff; }\n.mcfunction-viewer .boolean { color: #ffaa00; }\n.mcfunction-viewer .gamerule {color:#7fffd4}\n\n/* 只在浏览器环境中显示复制按钮相关样式 */\n"+("undefined"!=typeof window?"\n.mcfunction-copy-button {\n position: sticky;\n right: 0.5em;\n top: 0.5em;\n height: fit-content;\n margin-left: 10px;\n flex-shrink: 0;\n padding: 0.4em 0.8em;\n background: #333;\n border: 1px solid #666;\n border-radius: 0.3em;\n color: #d4d4d4;\n font-size: 0.8em;\n cursor: pointer;\n opacity: 0;\n transition: opacity 0.2s;\n}\n\n.mcfunction-copy-button:hover {\n background: #444;\n}\n\n.mcfunction-copy-button.success {\n background: #28a745;\n border-color: #28a745;\n}\n\n.mcfunction-viewer:hover .mcfunction-copy-button {\n opacity: 1;\n}":"")};"undefined"!=typeof window&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t.init()})):t.init()),"undefined"==typeof window?e.exports&&(e.exports=t):window.MCFunctionHighlight=t,Object.defineProperty(n,"__esModule",{value:!0}),n.default=t}},n={};function t(o){var a=n[o];if(void 0!==a)return a.exports;var i=n[o]={exports:{}};return e[o](i,i.exports,t),i.exports}t.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return t.d(n,{a:n}),n},t.d=(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},t.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n);var o={};return(()=>{"use strict";t.d(o,{default:()=>a});var e=t(723),n=t.n(e);"undefined"!=typeof window&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>n().init())):n().init());const a=n()})(),o=o.default})()));
\ No newline at end of file
+!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.MCFunctionHighlight=n():e.MCFunctionHighlight=n()}(this,(()=>(()=>{var e={723:(e,n)=>{const t=/\b(execute|run)\b/g,o=/\b(align|anchored|as|at|facing|in|positioned|rotated|store|result|success)\b/g,a=/\b(if|unless)\b/g,i=/\b(advancement|agent|alwaysday|attribute|ban|ban-ip|banlist|bossbar|camera|camerashake|clear|clearspawnpoint|teleport|clone|connect|damage|data|datapack|daylock|debug|deop|difficulty|effect|enchant|event|experience|fill|fillbiome|fog|forceload|function|gamemode|gamerule|give|help|hud|immutableworld|inputpermission|item|jfr|kick|kill|list|locate|loot|me|mobevent|msg|music|op|particle|permission|place|playsound|recipe|reload|ride|say|schedule|scoreboard|setblock|setworldspawn|spawnpoint|spreadplayers|stop|stopsound|summon|tag|tell|tellraw|time|title|tp|transfer|weather|whitelist|xp|tick)\b/g,c=/@[apers](?:\[(?:[^\]]*(?:type|distance|limit|sort|x|y|z|dx|dy|dz|scores|tag|team|name|nbt|predicate|gamemode|level|advancements|nbt|rotation|pitch|yaw)=[^\]]*)*\])?/g,r=/(?:^|\s)([~^][-\d]*\.?\d*)/g,s=/\b(\d+(?:\.\.\d+)?)\b/g,d=/\b(true|false)\b/g,l=/\b(type|distance|limit|sort|scores|tag|team|name|nbt|predicate|gamemode|level|advancements|rotation|pitch|yaw|dx|dy|dz|x|y|z|sort|nearest|furthest|random|arbitrary|block|blocks|entity|score|matches|eyes|feet|dimension|storage|bossbar|scale)\b/g,p=/\b(overworld|the_nether|the_end)\b/g,m=/\b(announceAdvancements|blockExplosionDropDecay|commandBlockOutput|commandModificationBlockLimit|disableElytraMovementCheck|disablePlayerMovementCheck|disableRaids|doDaylightCycle|doEntityDrops|doFireTick|doImmediateRespawn|doInsomnia|doLimitedCrafting|doMobLoot|doMobSpawning|doPatrolSpawning|doTileDrops|doTraderSpawning|doVinesSpread|doWardenSpawning|doWeatherCycle|drowningDamage|fallDamage|fireDamage|freezeDamage|functionCommandLimit|keepInventory|maxCommandChainLength|mobGriefing|naturalRegeneration|playersSleepingPercentage|projectilesCanBreakBlocks|pvp|randomTickSpeed|recipesUnlock|respawnBlocksExplode|sendCommandFeedback|showBorderEffect|showCoordinates|showDaysPlayed|showDeathMessages|showRecipeMessages|showTags|spawnRadius|tntExplodes|tntExplosionDropDecay)\b/g,f=/\b(list|add|speed|glowing|remove|modify|get|set|reset|enable|operation|display|numberformat|setdisplay)\b/g,u={highlight:e=>e.trimEnd().split("\n").map((e=>{const n=e.trim();return n?n.startsWith("#")?`${this.highlight(e)}`},getCSS:()=>"\n.mcfunction-viewer {\n font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;\n background: #1e1e1e !important;\n color: #d4d4d4;\n text-shadow: 0 1px rgba(0, 0, 0, 0.3);\n text-align: left;\n white-space: pre;\n word-spacing: normal;\n word-break: normal;\n line-height: 1.5;\n tab-size: 4;\n hyphens: none;\n padding: 1em;\n margin: 0;\n overflow: hidden;\n border-radius: 0.3em;\n position: relative;\n display: flex;\n min-height: 50px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.mcfunction-content {\n overflow: auto;\n padding-right: 20px;\n flex: 1;\n min-width: 0;\n width: 100%;\n}\n\n.mcfunction-viewer .command { color: #ffaa00; font-weight: bold; }\n.mcfunction-viewer .selector { color: #55ffff; }\n.mcfunction-viewer .coordinates { color: #55ff55; }\n.mcfunction-viewer .string { color: #ff5555; }\n.mcfunction-viewer .comment { color: #7f7f7f; }\n.mcfunction-viewer .number { color: #55ff55; }\n.mcfunction-viewer .execute-modifier { color: #ff55ff; }\n.mcfunction-viewer .execute-condition { color: #ff5555; }\n.mcfunction-viewer .parameter { color: #55ffff; }\n.mcfunction-viewer .dimension { color: #55ffff; }\n.mcfunction-viewer .boolean { color: #ffaa00; }\n.mcfunction-viewer .gamerule {color:#7fffd4}\n\n/* 只在浏览器环境中显示复制按钮相关样式 */\n"+("undefined"!=typeof window?"\n.mcfunction-copy-button {\n position: sticky;\n right: 0.5em;\n top: 0.5em;\n height: fit-content;\n margin-left: 10px;\n flex-shrink: 0;\n padding: 0.4em 0.8em;\n background: #333;\n border: 1px solid #666;\n border-radius: 0.3em;\n color: #d4d4d4;\n font-size: 0.8em;\n cursor: pointer;\n opacity: 0;\n transition: opacity 0.2s;\n}\n\n.mcfunction-copy-button:hover {\n background: #444;\n}\n\n.mcfunction-copy-button.success {\n background: #28a745;\n border-color: #28a745;\n}\n\n.mcfunction-viewer:hover .mcfunction-copy-button {\n opacity: 1;\n}":"")};"undefined"!=typeof window&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{u.init()})):u.init()),"undefined"==typeof window?e.exports&&(e.exports=u):window.MCFunctionHighlight=u,Object.defineProperty(n,"__esModule",{value:!0}),n.default=u}},n={};function t(o){var a=n[o];if(void 0!==a)return a.exports;var i=n[o]={exports:{}};return e[o](i,i.exports,t),i.exports}t.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return t.d(n,{a:n}),n},t.d=(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},t.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n);var o={};return(()=>{"use strict";t.d(o,{default:()=>a});var e=t(723),n=t.n(e);"undefined"!=typeof window&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>n().init())):n().init());const a=n()})(),o=o.default})()));
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 8d97099..f0755e4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "mcfunction-highlight",
- "version": "2.0.0",
+ "version": "3.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mcfunction-highlight",
- "version": "2.0.0",
+ "version": "3.1.0",
"license": "MIT",
"devDependencies": {
"css-loader": "^7.1.2",
@@ -1543,9 +1543,9 @@
}
},
"node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"dev": true,
"funding": [
{
diff --git a/src/mcfunction-highlight-universal.js b/src/mcfunction-highlight-universal.js
index 5187167..8e17331 100644
--- a/src/mcfunction-highlight-universal.js
+++ b/src/mcfunction-highlight-universal.js
@@ -1,50 +1,64 @@
+const EXECUTE_REGEX = /\b(execute|run)\b/g;
+const EXECUTE_MODIFIER_REGEX = /\b(align|anchored|as|at|facing|in|positioned|rotated|store|result|success)\b/g;
+const EXECUTE_CONDITION_REGEX = /\b(if|unless)\b/g;
+const COMMAND_REGEX = /\b(advancement|agent|alwaysday|attribute|ban|ban-ip|banlist|bossbar|camera|camerashake|clear|clearspawnpoint|teleport|clone|connect|damage|data|datapack|daylock|debug|deop|difficulty|effect|enchant|event|experience|fill|fillbiome|fog|forceload|function|gamemode|gamerule|give|help|hud|immutableworld|inputpermission|item|jfr|kick|kill|list|locate|loot|me|mobevent|msg|music|op|particle|permission|place|playsound|recipe|reload|ride|say|schedule|scoreboard|setblock|setworldspawn|spawnpoint|spreadplayers|stop|stopsound|summon|tag|tell|tellraw|time|title|tp|transfer|weather|whitelist|xp|tick)\b/g;
+const SELECTOR_REGEX = /@[apers](?:\[(?:[^\]]*(?:type|distance|limit|sort|x|y|z|dx|dy|dz|scores|tag|team|name|nbt|predicate|gamemode|level|advancements|nbt|rotation|pitch|yaw)=[^\]]*)*\])?/g;
+const COORDINATE_REGEX = /(?:^|\s)([~^][-\d]*\.?\d*)/g;
+const NUMBER_REGEX = /\b(\d+(?:\.\.\d+)?)\b/g;
+const BOOLEAN_REGEX = /\b(true|false)\b/g;
+const PARAMETER_REGEX = /\b(type|distance|limit|sort|scores|tag|team|name|nbt|predicate|gamemode|level|advancements|rotation|pitch|yaw|dx|dy|dz|x|y|z|sort|nearest|furthest|random|arbitrary|block|blocks|entity|score|matches|eyes|feet|dimension|storage|bossbar|scale)\b/g;
+const DIMENSION_REGEX = /\b(overworld|the_nether|the_end)\b/g;
+const GAMERULE_REGEX = /\b(announceAdvancements|blockExplosionDropDecay|commandBlockOutput|commandModificationBlockLimit|disableElytraMovementCheck|disablePlayerMovementCheck|disableRaids|doDaylightCycle|doEntityDrops|doFireTick|doImmediateRespawn|doInsomnia|doLimitedCrafting|doMobLoot|doMobSpawning|doPatrolSpawning|doTileDrops|doTraderSpawning|doVinesSpread|doWardenSpawning|doWeatherCycle|drowningDamage|fallDamage|fireDamage|freezeDamage|functionCommandLimit|keepInventory|maxCommandChainLength|mobGriefing|naturalRegeneration|playersSleepingPercentage|projectilesCanBreakBlocks|pvp|randomTickSpeed|recipesUnlock|respawnBlocksExplode|sendCommandFeedback|showBorderEffect|showCoordinates|showDaysPlayed|showDeathMessages|showRecipeMessages|showTags|spawnRadius|tntExplodes|tntExplosionDropDecay)\b/g;
+const STRING_REGEX = /\b(list|add|speed|glowing|remove|modify|get|set|reset|enable|operation|display|numberformat|setdisplay)\b/g;
+
const MCFunctionHighlight = {
highlight(code) {
return code.trimEnd().split('\n').map(line => {
- if (!line.trim()) {
+ const trimmed = line.trim();
+ if (!trimmed) {
return '