refactor: replace command link interception with :cmd[] directive

Replace the previous mechanism of intercepting specific command-prefixed
anchor tags with a dedicated `:cmd[]` markdown directive.

- Implement `cmdDirective` for `marked-directive` support.
- Update `CommandLinkManager` to listen for clicks on `[data-cmd]` spans
  instead of parsing `href` attributes.
- Add CSS styles for the new `.cmd-link` class.
This commit is contained in:
2026-07-12 14:05:07 +08:00
parent 182d7ff28d
commit 42e8971ff7
4 changed files with 69 additions and 50 deletions
+44
View File
@@ -0,0 +1,44 @@
/**
* marked-directive extension: :cmd[command]{label=Display text} inline syntax.
*
* Renders a clickable span that dispatches the command to the journal stream
* when clicked. The CommandLinkManager component handles the actual dispatch.
*
* Usage in markdown:
* :cmd[roll 1d20+5]{label=Roll initiative}
* :cmd[spark dungeon room-type]{label=Random room}
* :cmd[stat set strength=18]{label=Set strength}
*
* If no label is provided, the command text itself is shown.
*/
export const cmdDirective = {
level: "inline" as const,
marker: ":",
renderer(token: any) {
// Only handle :cmd[...], not other :directives
if (token.meta.name !== "cmd") return false;
const command = (token.text || "").trim();
if (!command) return "";
const label = (token.attrs?.label as string) || command;
return `<span class="cmd-link" data-cmd="${escapeAttr(command)}" role="button" tabindex="0">${escapeHtml(label)}</span>`;
},
};
function escapeHtml(s: string): string {
return s
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
function escapeAttr(s: string): string {
return s
.replace(/&/g, "&amp;")
.replace(/"/g, "&quot;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
+2
View File
@@ -7,6 +7,7 @@ import { gfmHeadingId } from "marked-gfm-heading-id";
import markedColumns from "./columns";
import markedCodeBlockYamlTag from "./code-block-yaml-tag";
import { iconDirective, setIconBase } from "./icon";
import { cmdDirective } from "./cmd";
// 使用 marked-directive 来支持指令语法
const marked = new Marked()
@@ -27,6 +28,7 @@ const marked = new Marked()
level: "container",
},
iconDirective,
cmdDirective,
]),
{
extensions: [...markedColumns()],