/** * `inline-atom` — atomic inline node for @date / @status / @label (T-148). * * Canonical stored form is the `@kind(value)` token inside `{ text }` (see * `atom-html.ts`); the node only exists inside the Tiptap editor. Like the * mention chip it is atomic (never split or edited as text) and rendered as * a span so apps/web can style it (badge / pill / chip). */ import { mergeAttributes, Node } from "@tiptap/core"; export interface InlineAtomOptions { readonly HTMLAttributes: Record; } declare module "@tiptap/core" { interface Config { options: InlineAtomOptions; } } export const InlineAtomNode = Node.create({ name: "factoryInlineAtom", group: "inline", inline: true, atom: true, selectable: true, addOptions() { return { HTMLAttributes: { class: "factory-atom" } }; }, addAttributes() { return { kind: { default: "label", parseHTML: (el) => el.getAttribute("data-atom-kind") ?? "label", renderHTML: (attrs) => ({ "data-atom-kind": attrs.kind }), }, value: { default: "", parseHTML: (el) => el.getAttribute("data-atom-value") ?? "", renderHTML: (attrs) => ({ "data-atom-value": attrs.value }), }, }; }, parseHTML() { return [{ tag: "span.factory-atom" }]; }, renderHTML({ node, HTMLAttributes }) { const kind = (node.attrs.kind as string) ?? "label"; const value = (node.attrs.value as string) ?? ""; return [ "span", mergeAttributes( { class: `factory-atom factory-atom-${kind}` }, this.options.HTMLAttributes, HTMLAttributes ), value ]; }, });