@mocanvas/mocanvas 4.0.2 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { T, ImageShapeCrop, ARROWHEAD_KINDS, ARROW_SHAPE_KINDS, LINE_SPLINE_KINDS, assetIdValidator, createBuiltInShapePropsMigrationIds, createBindingPropsMigrationSequence, createBuiltInBindingPropsMigrationIds, createShapePropsMigrationSequence, DefaultFontStyle, DefaultSizeStyle, DefaultDashStyle, DefaultFillStyle, DefaultLabelColorStyle, DefaultColorStyle, DefaultVerticalAlignStyle, DefaultHorizontalAlignStyle, GeoShapeGeoStyle, richTextToPlainText, createShapeId, BaseBoxShapeUtil, Rectangle2d, getDefaultDisplayValues } from '@mocanvas/editor';
1
+ import { T, ImageShapeCrop, ARROWHEAD_KINDS, ARROW_SHAPE_KINDS, LINE_SPLINE_KINDS, assetIdValidator, DefaultHorizontalAlignStyle, DefaultFontStyle, DefaultSizeStyle, DefaultColorStyle, DefaultVerticalAlignStyle, DefaultLabelColorStyle, DefaultDashStyle, DefaultFillStyle, GeoShapeGeoStyle, registerDefaultShapeSchema, registerDefaultBindingSchema, createBuiltInShapePropsMigrationIds, createBindingPropsMigrationSequence, createBuiltInBindingPropsMigrationIds, createShapePropsMigrationSequence, richTextToPlainText, createShapeId, BaseBoxShapeUtil, Rectangle2d, getDefaultDisplayValues } from '@mocanvas/editor';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
 
4
4
  // src/text/tiptap-extensions.ts
@@ -465,6 +465,25 @@ var arrowBindingProps = {
465
465
  isExact: T.boolean,
466
466
  isPrecise: T.boolean
467
467
  };
468
+ var builtInShapeProps = {
469
+ arrow: arrowShapeProps,
470
+ bookmark: bookmarkShapeProps,
471
+ draw: drawShapeProps,
472
+ embed: embedShapeProps,
473
+ frame: frameShapeProps,
474
+ geo: geoShapeProps,
475
+ group: groupShapeProps,
476
+ highlight: highlightShapeProps,
477
+ image: imageShapeProps,
478
+ line: lineShapeProps,
479
+ note: noteShapeProps,
480
+ text: textShapeProps,
481
+ video: videoShapeProps
482
+ };
483
+ for (const [type, props] of Object.entries(builtInShapeProps)) {
484
+ registerDefaultShapeSchema(type, { props });
485
+ }
486
+ registerDefaultBindingSchema("arrow", { props: arrowBindingProps });
468
487
  function backfillMigration(type, defaults, options = {}) {
469
488
  const versions = createBuiltInShapePropsMigrationIds(type, { BackfillMissingProps: 1 });
470
489
  return createShapePropsMigrationSequence({
@@ -1113,5 +1132,5 @@ var EmbedShapeUtil = class extends BaseBoxShapeUtil {
1113
1132
  };
1114
1133
 
1115
1134
  export { BOOKMARK_BANNER_FILL, BOOKMARK_BANNER_HEIGHT, BOOKMARK_FAVICON_SIZE, BOOKMARK_FILL, BOOKMARK_GAP, BOOKMARK_HEIGHT, BOOKMARK_META_COLOR, BOOKMARK_META_FONT_SIZE, BOOKMARK_META_HEIGHT, BOOKMARK_MIN_BODY_HEIGHT, BOOKMARK_PADDING, BOOKMARK_RADIUS, BOOKMARK_STROKE, BOOKMARK_STROKE_WIDTH, BOOKMARK_TEXT_COLOR, BOOKMARK_TEXT_FONT_SIZE, BOOKMARK_TITLE_COLOR, BOOKMARK_TITLE_FONT_SIZE, BOOKMARK_TITLE_HEIGHT, BOOKMARK_WIDTH, BookmarkShapeUtil, DEFAULT_EMBED_DEFINITIONS, EMBED_HEIGHT, EMBED_PLACEHOLDER_FILL, EMBED_PLACEHOLDER_FONT_SIZE, EMBED_PLACEHOLDER_PADDING, EMBED_PLACEHOLDER_STROKE, EMBED_PLACEHOLDER_TEXT, EMBED_RADIUS, EMBED_SANDBOX, EMBED_SHAPE_PERMISSION_NAMES, EMBED_WIDTH, EmbedShapeUtil, RICH_TEXT_MARKS, RICH_TEXT_NODES, applyPlainTextToRichText, arrowBindingMigrations, arrowBindingProps, arrowShapeMigrations, arrowShapeProps, arrowShapeVersions, asRichText, bookmarkShapeMigrations, bookmarkShapeProps, boxPath, canBuildPath, createEmptyBookmarkShape, drawShapeMigrations, drawShapeProps, embedDefinitions, embedShapeMigrations, embedShapePermissionsToAllow, embedShapeProps, escapeHtml, frameShapeMigrations, frameShapeProps, geoShapeProps, getBookmarkAsset, getBookmarkCard, getBookmarkHostname, getBookmarkLayout, getEmbedDefinition, getEmbedDisplayValues, getEmbedInfo, getRichTextEditorFactory, groupShapeMigrations, groupShapeProps, highlightShapeMigrations, highlightShapeProps, imageShapeMigrations, imageShapeProps, isRichText, lineShapeMigrations, lineShapeProps, loadTipTapStarterExtensions, noteShapeMigrations, noteShapeProps, polylinePath, propsOf, readArray, readBoolean, readEnum, readNumber, readPoint, readRecord, readRichText, readString, readStyle, readText, rectPath, registerRichTextEditorFactory, richTextEquals, richTextToBlocks, richTextToHtml, richTextToText, richTextValidator, safeHref, svgPath, textShapeMigrations, textShapeProps, tipTapDefaultExtensions, toRichText, unknownEmbedShapePermissionOverrides, videoShapeMigrations, videoShapeProps };
1116
- //# sourceMappingURL=chunk-OCYJAMXT.js.map
1117
- //# sourceMappingURL=chunk-OCYJAMXT.js.map
1135
+ //# sourceMappingURL=chunk-S7FPGQAA.js.map
1136
+ //# sourceMappingURL=chunk-S7FPGQAA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/text/tiptap-extensions.ts","../src/text/rich-text.ts","../src/shapes/prop-access.ts","../src/shapes/indicator-paths.ts","../src/shapes/shape-props.ts","../src/shapes/shape-migrations.ts","../src/shapes/BookmarkShapeUtil.tsx","../src/shapes/EmbedShapeUtil.tsx"],"names":["richTextToPlainText","BaseBoxShapeUtil","Rectangle2d","jsx"],"mappings":"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","file":"chunk-S7FPGQAA.js","sourcesContent":["/**\n * The default rich-text schema, and the seam an app uses to bring its own\n * TipTap along.\n *\n * ## Why TipTap is optional here\n *\n * `tipTapDefaultExtensions` is the list a host passes to\n * `textOptions.tipTapConfig.extensions`. It describes the node and mark types a\n * mocanvas label understands, and everything mocanvas does with rich text —\n * measure it, lay it out, rasterize it, export it to SVG, round-trip it through\n * a `.tldr` file — is derived from the document JSON, not from a live editor.\n * So the default list carries *descriptions* of those types and pulls in no\n * dependency at all.\n *\n * TipTap and ProseMirror are only needed to *edit* rich text in a WYSIWYG\n * surface. They are therefore declared as **optional peer dependencies**:\n *\n * - ProseMirror schemas are instance-identity sensitive. An app that already\n * ships TipTap (the way `@molekula/editor` does) and a bundled copy inside\n * mocanvas would be two ProseMirror instances in one page, which breaks in\n * ways that are hard to diagnose. A peer dependency forces the single copy.\n * - A consumer that only wants plain-text labels should not pay several hundred\n * kilobytes for an editor it never opens.\n *\n * When TipTap is absent the DOM overlay falls back to a plain `<textarea>` over\n * the text projection of the document (see `TextEditor.tsx`); marks the user did\n * not touch survive, marks they edit through do not. When it is present, an app\n * installs its own editor factory through {@link registerRichTextEditorFactory}\n * and gets the full surface.\n */\n\nimport type { RichTextMark, RichTextNode } from \"./rich-text\"\n\n/**\n * The minimum an entry of the extension list has to be.\n *\n * A real TipTap `Node`, `Mark` or `Extension` instance satisfies this, so\n * `[...tipTapDefaultExtensions, MyTipTapExtension]` is well typed and an app can\n * extend the default set without mocanvas depending on TipTap's types.\n */\nexport interface RichTextExtension {\n readonly name: string\n}\n\n/** A node type mocanvas knows how to render, measure and export. */\nexport interface RichTextNodeExtension extends RichTextExtension {\n readonly kind: \"node\"\n /** HTML tag the node serializes to. `null` renders the children with no wrapper. */\n readonly tag: string | null\n /** Void nodes (`<br>`, `<hr>`) render no children and no closing tag. */\n readonly void?: boolean\n /** Per-node tag, for a type whose tag depends on its attrs (a heading's level). */\n readonly tagFor?: (node: RichTextNode) => string | null\n /** Rendered inside the tag when the node has no content, so an empty block still occupies a line. */\n readonly emptyHtml?: string\n}\n\n/** A formatting mark mocanvas knows how to render, measure and export. */\nexport interface RichTextMarkExtension extends RichTextExtension {\n readonly kind: \"mark\"\n readonly tag: string\n /** Attributes for the rendered tag, or `null` to drop the mark (an unsafe `href`, say). */\n readonly attributesFor?: (mark: RichTextMark) => Record<string, string> | null\n}\n\n/** Keeps an empty paragraph one line tall in a measuring probe and in the static label. */\nconst ZERO_WIDTH_SPACE = \"​\"\n\nfunction level(node: RichTextNode): number {\n const value = node.attrs?.[\"level\"]\n return typeof value === \"number\" && value >= 1 && value <= 6 ? Math.floor(value) : 1\n}\n\n/** The block and inline node types a mocanvas label understands out of the box. */\nexport const RICH_TEXT_NODES: readonly RichTextNodeExtension[] = [\n { name: \"paragraph\", kind: \"node\", tag: \"p\", emptyHtml: ZERO_WIDTH_SPACE },\n { name: \"heading\", kind: \"node\", tag: \"h1\", tagFor: (node) => `h${level(node)}`, emptyHtml: ZERO_WIDTH_SPACE },\n { name: \"bulletList\", kind: \"node\", tag: \"ul\" },\n { name: \"orderedList\", kind: \"node\", tag: \"ol\" },\n { name: \"listItem\", kind: \"node\", tag: \"li\", emptyHtml: ZERO_WIDTH_SPACE },\n { name: \"blockquote\", kind: \"node\", tag: \"blockquote\" },\n { name: \"codeBlock\", kind: \"node\", tag: \"pre\" },\n { name: \"hardBreak\", kind: \"node\", tag: \"br\", void: true },\n { name: \"horizontalRule\", kind: \"node\", tag: \"hr\", void: true },\n]\n\n/** The formatting marks a mocanvas label understands out of the box. */\nexport const RICH_TEXT_MARKS: readonly RichTextMarkExtension[] = [\n { name: \"bold\", kind: \"mark\", tag: \"strong\" },\n { name: \"italic\", kind: \"mark\", tag: \"em\" },\n { name: \"underline\", kind: \"mark\", tag: \"u\" },\n { name: \"strike\", kind: \"mark\", tag: \"s\" },\n { name: \"code\", kind: \"mark\", tag: \"code\" },\n { name: \"highlight\", kind: \"mark\", tag: \"mark\" },\n {\n name: \"link\",\n kind: \"mark\",\n tag: \"a\",\n attributesFor: (mark) => {\n const href = mark.attrs?.[\"href\"]\n if (typeof href !== \"string\") return null\n const trimmed = href.trim()\n // Only schemes that cannot execute script; anything else drops the mark\n // and keeps the text.\n return /^(?:https?:|mailto:|tel:|#|\\/|\\.{1,2}\\/)/i.test(trimmed) ? { href: trimmed, rel: \"noopener noreferrer\" } : null\n },\n },\n]\n\n/**\n * The default extension set the canvas text editor uses.\n *\n * Pass it to the editor as `textOptions: { tipTapConfig: { extensions:\n * tipTapDefaultExtensions } }`, or spread it to add your own:\n * `[...tipTapDefaultExtensions, MyExtension]`.\n *\n * Every entry describes one node or mark type. mocanvas reads the descriptions\n * when it serializes a document for measurement, rasterizes a label or writes\n * SVG. Real TipTap extension instances may be appended to the list; they are\n * handed to the editor factory an app registers with\n * {@link registerRichTextEditorFactory} and ignored by the description-driven\n * paths, which fall back to the built-in table for the standard types.\n */\nexport const tipTapDefaultExtensions: readonly RichTextExtension[] = [...RICH_TEXT_NODES, ...RICH_TEXT_MARKS]\n\n/* ---- the optional live-editor seam --------------------------------------- */\n\n/** What mocanvas hands a rich-text editor when the user starts editing a label. */\nexport interface RichTextEditorMountOptions {\n /** The element the editor should mount into. */\n container: HTMLElement\n /** The document to start from. */\n initialValue: RichTextNode & { type: \"doc\" }\n /** The extension list configured on the editor. */\n extensions: readonly RichTextExtension[]\n /** Whether typing should be constrained to one line (a frame's name). */\n singleLine: boolean\n /** Called with the new document as the user types. */\n onChange(value: RichTextNode & { type: \"doc\" }): void\n /** Called when the editor wants editing to stop (Escape, Enter on a single-line label). */\n onFinish(): void\n}\n\n/** A mounted rich-text editor. `destroy` must remove everything the factory added. */\nexport interface RichTextEditorHandle {\n focus(): void\n destroy(): void\n}\n\n/** Creates a rich-text editing surface — a TipTap editor, in practice. */\nexport type RichTextEditorFactory = (options: RichTextEditorMountOptions) => RichTextEditorHandle\n\nlet editorFactory: RichTextEditorFactory | null = null\n\n/**\n * Install the WYSIWYG editing surface used when a label is being edited.\n *\n * An app that already depends on TipTap registers a factory that builds a\n * TipTap editor from `options.extensions`; without one, mocanvas edits labels\n * with a plain `<textarea>` over the text projection of the document. Returns a\n * function that removes the factory again (only if it is still the registered\n * one), so tests can install and undo one.\n */\nexport function registerRichTextEditorFactory(factory: RichTextEditorFactory | null): () => void {\n editorFactory = factory\n return () => {\n if (editorFactory === factory) editorFactory = null\n }\n}\n\n/** The registered rich-text editor factory, or `null` when labels edit as plain text. */\nexport function getRichTextEditorFactory(): RichTextEditorFactory | null {\n return editorFactory\n}\n\n/**\n * Load TipTap's own starter extensions, for an app that has the optional peer\n * dependency installed and wants the standard set rather than mocanvas's\n * descriptions.\n *\n * Rejects with an actionable message when the peer is missing. The import is\n * dynamic and built from a variable so a bundler does not try to resolve it at\n * build time in an app that never calls this.\n */\nexport async function loadTipTapStarterExtensions(): Promise<readonly RichTextExtension[]> {\n const moduleId = \"@tiptap/starter-kit\"\n let loaded: unknown\n try {\n loaded = await import(/* @vite-ignore */ /* webpackIgnore: true */ moduleId)\n } catch (cause) {\n throw new Error(\"mocanvas: `@tiptap/starter-kit` is an optional peer dependency and is not installed. Run `npm install @tiptap/starter-kit@^3 @tiptap/core@^3 @tiptap/pm@^3`, or use `tipTapDefaultExtensions` instead.\", { cause })\n }\n const starterKit = (loaded as { default?: unknown }).default ?? loaded\n return [starterKit as RichTextExtension]\n}\n","/**\n * The canonical rich-text document mocanvas stores in a shape's `richText`\n * prop, plus the pure conversions around it.\n *\n * The value is a ProseMirror/TipTap document: `{ type: \"doc\", content: [...] }`\n * where every node is `{ type, attrs?, content?, marks?, text? }`. That is the\n * shape TipTap's `editor.getJSON()` produces and `.tldr` files already carry\n * (see `src/__fixtures__/compare.tldr`), so a document written by mocanvas\n * loads in a TipTap editor and vice versa.\n *\n * Nothing in this module imports TipTap. The document is plain JSON, and every\n * thing mocanvas itself needs — store round trip, measurement, layout, the GPU\n * texture and SVG export — is derived from that JSON. TipTap is only needed to\n * *edit* rich text in a WYSIWYG surface, which is why it is an optional peer\n * dependency; see `tiptap-extensions.ts`.\n */\n\nimport { richTextToPlainText } from \"@mocanvas/editor\"\nimport { RICH_TEXT_MARKS, RICH_TEXT_NODES, type RichTextExtension, type RichTextMarkExtension, type RichTextNodeExtension } from \"./tiptap-extensions\"\n\n/** A formatting mark on a text node: `{ type: \"bold\" }`, `{ type: \"link\", attrs: { href } }`. */\nexport interface RichTextMark {\n type: string\n attrs?: Record<string, unknown>\n}\n\n/** One node of a rich-text document. Text nodes carry `text`; everything else carries `content`. */\nexport interface RichTextNode {\n type: string\n attrs?: Record<string, unknown>\n content?: RichTextNode[]\n marks?: RichTextMark[]\n text?: string\n}\n\n/** A rich-text document — the value stored in a shape's `richText` prop. */\nexport interface RichText {\n type: \"doc\"\n content: RichTextNode[]\n}\n\n/**\n * Anything a label may be given: a rich-text document, a plain string, or\n * nothing. Every function in the text pipeline takes this, so the store is free\n * to hold either `props.richText` or `props.text`.\n */\nexport type RichTextSource = RichText | string | null | undefined\n\n/**\n * Convert a plain string into a rich-text document.\n *\n * Each line becomes a paragraph; an empty line becomes a paragraph with no\n * content (`{ type: \"paragraph\" }`), which is exactly how the format spells an\n * empty label. `toRichText(\"\")` is therefore a one-empty-paragraph document\n * rather than an empty one, so a shape created from it still has a caret line.\n */\nexport function toRichText(text: string): RichText {\n const source = typeof text === \"string\" ? text : \"\"\n return {\n type: \"doc\",\n content: source.split(\"\\n\").map((line) => (line.length === 0 ? { type: \"paragraph\" } : { type: \"paragraph\", content: [{ type: \"text\", text: line }] })),\n }\n}\n\n/** Whether `value` is a rich-text document rather than a string or junk. */\nexport function isRichText(value: unknown): value is RichText {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false\n const doc = value as { type?: unknown; content?: unknown }\n return doc.type === \"doc\" && (doc.content === undefined || Array.isArray(doc.content))\n}\n\n/**\n * The plain string a label reads as, whatever it was given.\n *\n * Marks and unknown wrappers are flattened away; `hardBreak` becomes a newline\n * and top-level blocks are joined by newlines. Delegates to the editor's\n * `richTextToPlainText` so the load path and the render path agree character\n * for character.\n */\nexport function richTextToText(source: RichTextSource): string {\n if (source === null || source === undefined) return \"\"\n if (typeof source === \"string\") return source\n return richTextToPlainText(source)\n}\n\n/** The rich-text document form of any label source; a string is converted, a document passed through. */\nexport function asRichText(source: RichTextSource): RichText {\n if (isRichText(source)) return source\n return toRichText(typeof source === \"string\" ? source : \"\")\n}\n\n/** Structural equality of two documents, by value. */\nexport function richTextEquals(a: RichTextSource, b: RichTextSource): boolean {\n if (a === b) return true\n return JSON.stringify(asRichText(a)) === JSON.stringify(asRichText(b))\n}\n\n/**\n * Fold a plain-text edit back into a rich-text document.\n *\n * The plain-text editing surface (the `<textarea>` the DOM overlay falls back\n * to when no TipTap editor is installed) can only express text, not marks. When\n * the text did not actually change, the original document is returned unchanged\n * so opening and closing the editor never silently strips formatting. When it\n * did change, the document is rebuilt from the new text — the honest outcome for\n * an editor that cannot represent the marks it would have to preserve.\n *\n * SEMANTICS-ASSUMED: mocanvas owns this seam (it exists because TipTap is\n * optional here), so there is no upstream behaviour to match. \"Keep formatting\n * on a no-op, drop it on a real plain-text edit\" is the conservative choice: it\n * never loses formatting the user did not touch, and never claims to preserve\n * marks it cannot place.\n */\nexport function applyPlainTextToRichText(previous: RichTextSource, nextText: string): RichText {\n const doc = asRichText(previous)\n if (richTextToText(doc) === nextText) return doc\n return toRichText(nextText)\n}\n\n/* ---- HTML ---------------------------------------------------------------- */\n\nexport interface RichTextHtmlOptions {\n /**\n * The node and mark extensions the document is serialized with. Defaults to\n * {@link tipTapDefaultExtensions}; pass an app's own list to render nodes\n * mocanvas does not know about.\n */\n extensions?: readonly RichTextExtension[]\n /** Collects the node and mark types no extension covered, for warnings. */\n unknownTypes?: Set<string>\n}\n\n/** URL schemes a link mark may carry through to the rendered HTML. */\nconst SAFE_URL = /^(?:https?:|mailto:|tel:|#|\\/|\\.{1,2}\\/)/i\n\nconst ESCAPES: Record<string, string> = { \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" }\n\n/** Escape text for insertion into HTML/XML character data or an attribute value. */\nexport function escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/g, (c) => ESCAPES[c]!)\n}\n\ninterface ResolvedExtensions {\n nodes: Map<string, RichTextNodeExtension>\n marks: Map<string, RichTextMarkExtension>\n}\n\nfunction resolve(extensions: readonly RichTextExtension[] | undefined): ResolvedExtensions {\n const nodes = new Map<string, RichTextNodeExtension>()\n const marks = new Map<string, RichTextMarkExtension>()\n for (const extension of extensions ?? [...RICH_TEXT_NODES, ...RICH_TEXT_MARKS]) {\n const kind = (extension as { kind?: unknown }).kind\n if (kind === \"node\") nodes.set(extension.name, extension as RichTextNodeExtension)\n else if (kind === \"mark\") marks.set(extension.name, extension as RichTextMarkExtension)\n // Anything else (a real TipTap extension, say) describes no HTML mapping of\n // its own; the built-in table below still covers the standard node types.\n }\n if (nodes.size === 0) for (const node of RICH_TEXT_NODES) nodes.set(node.name, node)\n if (marks.size === 0) for (const mark of RICH_TEXT_MARKS) marks.set(mark.name, mark)\n return { nodes, marks }\n}\n\n/**\n * Serialize a rich-text document to HTML.\n *\n * The output is generated here from a known set of node and mark types — text\n * is escaped, link hrefs are scheme-checked — so it is safe to hand to\n * `innerHTML`. Unknown node types are recursed into rather than dropped, so\n * their text survives even when their formatting cannot.\n *\n * No whitespace is emitted between tags: the measuring probe renders the result\n * with `white-space: pre-wrap`, where an indenting newline would measure as a\n * space.\n */\nexport function richTextToHtml(source: RichTextSource, options: RichTextHtmlOptions = {}): string {\n const { nodes, marks } = resolve(options.extensions)\n const doc = asRichText(source)\n return (doc.content ?? []).map((node) => nodeToHtml(node, nodes, marks, options.unknownTypes)).join(\"\")\n}\n\nfunction nodeToHtml(node: RichTextNode, nodes: ResolvedExtensions[\"nodes\"], marks: ResolvedExtensions[\"marks\"], unknown?: Set<string>): string {\n if (typeof node !== \"object\" || node === null) return \"\"\n if (node.type === \"text\") return textNodeToHtml(node, marks, unknown)\n\n const extension = nodes.get(node.type)\n if (!extension) {\n unknown?.add(node.type)\n // Keep the text: render the children with no wrapper of their own.\n return (node.content ?? []).map((child) => nodeToHtml(child, nodes, marks, unknown)).join(\"\")\n }\n\n const tag = extension.tagFor ? extension.tagFor(node) : extension.tag\n if (extension.void) return tag === null ? \"\" : `<${tag}>`\n const inner = (node.content ?? []).map((child) => nodeToHtml(child, nodes, marks, unknown)).join(\"\")\n if (tag === null) return inner\n // An empty block still occupies a line, exactly as the plain-text path does.\n return `<${tag}>${inner.length === 0 && extension.emptyHtml !== undefined ? extension.emptyHtml : inner}</${tag}>`\n}\n\nfunction textNodeToHtml(node: RichTextNode, marks: ResolvedExtensions[\"marks\"], unknown?: Set<string>): string {\n let html = escapeHtml(node.text ?? \"\")\n // Innermost mark first, so the outermost mark in `marks` ends up outermost.\n for (const mark of node.marks ?? []) {\n const extension = marks.get(mark.type)\n if (!extension) {\n unknown?.add(mark.type)\n continue\n }\n const attributes = extension.attributesFor?.(mark) ?? null\n if (attributes === null && extension.attributesFor) continue\n const rendered = attributes === null ? \"\" : Object.entries(attributes).map(([k, v]) => ` ${k}=\"${escapeHtml(v)}\"`).join(\"\")\n html = `<${extension.tag}${rendered}>${html}</${extension.tag}>`\n }\n return html\n}\n\n/** A link `href` that is safe to render, or `null` when the scheme is not allowed. */\nexport function safeHref(value: unknown): string | null {\n if (typeof value !== \"string\") return null\n const trimmed = value.trim()\n return SAFE_URL.test(trimmed) ? trimmed : null\n}\n\n/* ---- styled runs --------------------------------------------------------- */\n\n/** The typographic effect of the marks on one run of text. */\nexport interface RichTextRunStyle {\n bold: boolean\n italic: boolean\n underline: boolean\n strike: boolean\n code: boolean\n /** The `href` of an enclosing link mark, when there is one. */\n href?: string\n}\n\n/** A run of text sharing one style — the unit the canvas raster and SVG export draw. */\nexport interface RichTextRun extends RichTextRunStyle {\n text: string\n}\n\n/** A block of the document flattened to styled runs. One block renders as one wrapped paragraph. */\nexport interface RichTextBlock {\n runs: RichTextRun[]\n}\n\nconst PLAIN_STYLE: RichTextRunStyle = { bold: false, italic: false, underline: false, strike: false, code: false }\n\nconst BOLD_MARKS = new Set([\"bold\", \"strong\"])\nconst ITALIC_MARKS = new Set([\"italic\", \"em\"])\nconst UNDERLINE_MARKS = new Set([\"underline\"])\nconst STRIKE_MARKS = new Set([\"strike\", \"strikethrough\", \"s\", \"del\"])\nconst CODE_MARKS = new Set([\"code\"])\n\nfunction styleOf(marks: readonly RichTextMark[] | undefined): RichTextRunStyle {\n const style: RichTextRunStyle = { ...PLAIN_STYLE }\n for (const mark of marks ?? []) {\n if (BOLD_MARKS.has(mark.type)) style.bold = true\n else if (ITALIC_MARKS.has(mark.type)) style.italic = true\n else if (UNDERLINE_MARKS.has(mark.type)) style.underline = true\n else if (STRIKE_MARKS.has(mark.type)) style.strike = true\n else if (CODE_MARKS.has(mark.type)) style.code = true\n else if (mark.type === \"link\") {\n const href = safeHref(mark.attrs?.[\"href\"])\n if (href !== null) style.href = href\n }\n }\n return style\n}\n\n/**\n * Flatten a document to the blocks the renderers draw: one block per top-level\n * block node (a paragraph, a heading, a list item), each a list of styled runs.\n *\n * A `hardBreak` starts a new block, so blocks and the lines of\n * {@link richTextToText} line up one for one.\n */\nexport function richTextToBlocks(source: RichTextSource): RichTextBlock[] {\n if (typeof source === \"string\") return source.split(\"\\n\").map((text) => ({ runs: text.length === 0 ? [] : [{ text, ...PLAIN_STYLE }] }))\n const doc = asRichText(source)\n const blocks: RichTextBlock[] = []\n for (const node of doc.content ?? []) collectBlocks(node, blocks)\n if (blocks.length === 0) blocks.push({ runs: [] })\n return blocks\n}\n\nfunction collectBlocks(node: RichTextNode, out: RichTextBlock[]): void {\n if (typeof node !== \"object\" || node === null) return\n if (node.type === \"text\" || node.type === \"hardBreak\") {\n // A bare text node at block level (or a break) belongs to the block in progress.\n appendInline(node, out)\n return\n }\n const children = node.content ?? []\n if (children.some((child) => isBlockNode(child))) {\n for (const child of children) collectBlocks(child, out)\n return\n }\n out.push({ runs: [] })\n for (const child of children) appendInline(child, out)\n}\n\nconst BLOCK_NODE_TYPES = new Set([\"paragraph\", \"heading\", \"bulletList\", \"orderedList\", \"listItem\", \"blockquote\", \"codeBlock\", \"horizontalRule\", \"taskList\", \"taskItem\", \"table\", \"tableRow\", \"tableCell\", \"tableHeader\"])\n\nfunction isBlockNode(node: RichTextNode): boolean {\n if (typeof node !== \"object\" || node === null) return false\n if (node.type === \"text\" || node.type === \"hardBreak\") return false\n // Marks only ever apply to inline content, so a marked wrapper is inline\n // whatever its type — its runs inherit the mark rather than starting a block.\n if (Array.isArray(node.marks) && node.marks.length > 0) return false\n return BLOCK_NODE_TYPES.has(node.type) || Array.isArray(node.content)\n}\n\nfunction appendInline(node: RichTextNode, out: RichTextBlock[], inherited?: RichTextRunStyle): void {\n if (typeof node !== \"object\" || node === null) return\n if (out.length === 0) out.push({ runs: [] })\n if (node.type === \"hardBreak\") {\n out.push({ runs: [] })\n return\n }\n const style = mergeStyle(inherited, styleOf(node.marks))\n if (node.type === \"text\") {\n const text = node.text ?? \"\"\n if (text.length > 0) out[out.length - 1]!.runs.push({ text, ...style })\n return\n }\n for (const child of node.content ?? []) appendInline(child, out, style)\n}\n\nfunction mergeStyle(base: RichTextRunStyle | undefined, next: RichTextRunStyle): RichTextRunStyle {\n if (!base) return next\n return {\n bold: base.bold || next.bold,\n italic: base.italic || next.italic,\n underline: base.underline || next.underline,\n strike: base.strike || next.strike,\n code: base.code || next.code,\n ...(next.href ?? base.href ? { href: next.href ?? base.href } : {}),\n }\n}\n","/**\n * Tolerant prop reads for the default shape utils.\n *\n * A shape can reach a util with props that do not match its declared shape:\n * a file written by another editor, a record hand-built by an integrator, a\n * partial update. Geometry and rendering must survive that, so the utils read\n * through these helpers rather than trusting the declared types (and rather\n * than sprinkling `?.` and `??` over every access).\n *\n * Each helper takes the shape's props object and returns a usable value of the\n * expected kind, falling back to the util's default when the stored value is\n * missing or of the wrong type.\n */\n\nimport { richTextToPlainText, type EnumStyleProp } from \"@mocanvas/editor\"\n// Imported from the module rather than through `../text`, which would close a\n// cycle back through the label components.\nimport { isRichText, toRichText, type RichText } from \"../text/rich-text\"\n\ntype Props = Record<string, unknown>\n\n/** A shape's props as a bag of unknowns, tolerating a missing or non-object `props`. */\nexport function propsOf(shape: { props?: unknown }): Props {\n const props = shape.props\n return typeof props === \"object\" && props !== null && !Array.isArray(props) ? (props as Props) : {}\n}\n\nexport function readString(props: unknown, key: string, fallback: string): string {\n const value = (props as Props | undefined)?.[key]\n return typeof value === \"string\" ? value : fallback\n}\n\n/** A string prop constrained to a known set; anything else falls back. */\nexport function readEnum<T extends string>(props: unknown, key: string, allowed: readonly T[], fallback: T): T {\n const value = (props as Props | undefined)?.[key]\n return typeof value === \"string\" && (allowed as readonly string[]).includes(value) ? (value as T) : fallback\n}\n\n/** A style prop's value, validated against the style's own set of values. */\nexport function readStyle<T extends string>(props: unknown, key: string, style: EnumStyleProp<T>, fallback: T = style.defaultValue): T {\n return readEnum(props, key, style.values, fallback)\n}\n\nexport function readNumber(props: unknown, key: string, fallback: number): number {\n const value = (props as Props | undefined)?.[key]\n return typeof value === \"number\" && Number.isFinite(value) ? value : fallback\n}\n\nexport function readBoolean(props: unknown, key: string, fallback: boolean): boolean {\n const value = (props as Props | undefined)?.[key]\n return typeof value === \"boolean\" ? value : fallback\n}\n\n/**\n * A shape's label as plain text.\n *\n * A label has two spellings on the record — `props.richText`, the document the\n * store keeps, and `props.text`, its flattened form — and this reconciles them\n * through {@link readRichText} so the two readers can never disagree about what\n * a shape says.\n *\n * `key` names a *plain-text-only* prop (a frame's `name`); only the default\n * `\"text\"` participates in the reconciliation, because only it has a rich\n * counterpart.\n */\nexport function readText(props: unknown, key = \"text\"): string {\n if (key !== \"text\") return readString(props, key, \"\")\n return richTextToPlainText(readRichText(props))\n}\n\n/**\n * A shape's label as a rich-text document — the reader every other label read\n * goes through.\n *\n * A record can carry either spelling, or both, or both *disagreeing*: a v5\n * writer sets `props.richText` and leaves `props.text` at its default, a\n * pre-v5 writer does the reverse, and a partial update touches one without the\n * other. So the rule is stated once, here:\n *\n * 1. a rich-text document that actually says something wins — it is the\n * canonical spelling and the only one that can carry formatting;\n * 2. otherwise a non-empty `props.text` is lifted into a document;\n * 3. otherwise the label is empty, and the stored document (if any) is kept so\n * an empty-but-structured document survives a round trip.\n *\n * An empty label is one empty paragraph, which is what this format spells\n * \"nothing typed yet\" — never a document with no content at all.\n */\nexport function readRichText(props: unknown, key = \"richText\"): RichText {\n const value = (props as Props | undefined)?.[key]\n const stored = isRichText(value) ? value : null\n if (stored !== null && richTextToPlainText(stored).length > 0) return stored\n const text = (props as Props | undefined)?.[\"text\"]\n if (typeof text === \"string\" && text.length > 0) return toRichText(text)\n return stored ?? toRichText(\"\")\n}\n\n/** A `{ x, y }` prop, with each coordinate falling back independently. */\nexport function readPoint(props: unknown, key: string, fallback: { x: number; y: number }): { x: number; y: number } {\n const value = (props as Props | undefined)?.[key]\n if (typeof value !== \"object\" || value === null) return fallback\n return { x: readNumber(value, \"x\", fallback.x), y: readNumber(value, \"y\", fallback.y) }\n}\n\n/** An array prop; a missing or non-array value reads as empty. */\nexport function readArray(props: unknown, key: string): unknown[] {\n const value = (props as Props | undefined)?.[key]\n return Array.isArray(value) ? value : []\n}\n\n/** A record-of-objects prop (a line's points, say); anything else reads as empty. */\nexport function readRecord(props: unknown, key: string): Record<string, unknown> {\n const value = (props as Props | undefined)?.[key]\n return typeof value === \"object\" && value !== null && !Array.isArray(value) ? (value as Record<string, unknown>) : {}\n}\n","/**\n * Small builders for the canvas paths a shape util's `getIndicatorPath`\n * returns, so the built-in shapes all fail soft the same way.\n */\nimport type { VecLike } from \"@mocanvas/editor\"\n\n/**\n * Whether canvas paths can be built at all.\n *\n * `Path2D` is a DOM class: it is absent in Node (unit tests, SSR, the headless\n * export path). A util calls this rather than letting a `ReferenceError` out of\n * a render pass.\n */\nexport function canBuildPath(): boolean {\n return typeof Path2D !== \"undefined\"\n}\n\n/**\n * A rectangle, optionally rounded.\n *\n * `roundRect` is a 2022-era addition; a square corner is a cosmetic regression\n * where a thrown exception would take the whole indicator layer with it, so a\n * missing `roundRect` falls back rather than failing.\n */\nexport function rectPath(w: number, h: number, radius = 0): Path2D {\n const path = new Path2D()\n if (radius > 0 && typeof path.roundRect === \"function\") {\n path.roundRect(0, 0, w, h, radius)\n } else {\n path.rect(0, 0, w, h)\n }\n return path\n}\n\n/** A rectangle at an offset, for a geometry whose bounds do not start at the origin. */\nexport function boxPath(box: { x: number; y: number; w: number; h: number }): Path2D {\n const path = new Path2D()\n path.rect(box.x, box.y, box.w, box.h)\n return path\n}\n\n/**\n * A path from SVG path data.\n *\n * The `Path2D(d)` constructor is the shortest route from the engine's path\n * encoding (which already serializes to a `d` string for export) to a canvas\n * path, and it is what the consumer's own utils use.\n */\nexport function svgPath(d: string): Path2D {\n return new Path2D(d)\n}\n\n/** An open or closed polyline through `points`. */\nexport function polylinePath(points: readonly VecLike[], close = false): Path2D {\n const path = new Path2D()\n const first = points[0]\n if (!first) return path\n path.moveTo(first.x, first.y)\n for (let i = 1; i < points.length; i++) {\n const p = points[i]!\n path.lineTo(p.x, p.y)\n }\n if (close) path.closePath()\n return path\n}\n","/**\n * The validator map of every built-in shape — and of the built-in `arrow`\n * binding.\n *\n * A shape util's `static props` is the map that says what each prop of that\n * shape *is*: a validator, or a {@link StyleProp} (which validates and is\n * additionally shared across shape types, remembered for the next shape, and\n * editable for a whole selection at once). Publishing the maps as named values\n * rather than as anonymous object literals inside each class is what lets an\n * app extend one:\n *\n * ```ts\n * class MyGeoShapeUtil extends GeoShapeUtil {\n * static override props = { ...geoShapeProps, badge: T.string }\n * }\n * ```\n *\n * **Which entries are styles is deliberate, not incidental.** A prop only\n * becomes a style when a shared, remembered, multi-select-editable value is\n * what the user wants; an arrow's routing `kind` and its arrowheads are per\n * arrow, so they are plain validators here even though they are enums. These\n * maps reproduce exactly the style set the built-ins already declared, so\n * wiring them changes what validates, never what the style panel shows.\n */\n\nimport {\n ARROWHEAD_KINDS,\n ARROW_SHAPE_KINDS,\n DefaultColorStyle,\n DefaultDashStyle,\n DefaultFillStyle,\n DefaultFontStyle,\n DefaultHorizontalAlignStyle,\n DefaultLabelColorStyle,\n DefaultSizeStyle,\n DefaultVerticalAlignStyle,\n GeoShapeGeoStyle,\n ImageShapeCrop,\n LINE_SPLINE_KINDS,\n T,\n assetIdValidator,\n registerDefaultBindingSchema,\n registerDefaultShapeSchema,\n type RecordProps,\n type UnknownRecordProps,\n type StyleProp,\n type Validator,\n} from \"@mocanvas/editor\"\nimport { isRichText, type RichText } from \"../text/rich-text\"\nimport type { ArrowBinding } from \"../bindings/ArrowBindingUtil\"\nimport type { ArrowShape } from \"./ArrowShapeUtil\"\nimport type { BookmarkShape } from \"./BookmarkShapeUtil\"\nimport type { DrawShape } from \"./DrawShapeUtil\"\nimport type { EmbedShape } from \"./EmbedShapeUtil\"\nimport type { FrameShape } from \"./FrameShapeUtil\"\nimport type { GeoShape } from \"./GeoShapeUtil\"\nimport type { GroupShape } from \"./GroupShapeUtil\"\nimport type { HighlightShape } from \"./HighlightShapeUtil\"\nimport type { ImageCrop, ImageShape } from \"./ImageShapeUtil\"\nimport type { LineShape } from \"./LineShapeUtil\"\nimport type { NoteShape } from \"./NoteShapeUtil\"\nimport type { TextShape } from \"./TextShapeUtil\"\nimport type { VideoShape } from \"./VideoShapeUtil\"\n\n/* ---- shared prop validators --------------------------------------------- */\n\n/**\n * A rich-text document, as a shape's `richText` prop holds it.\n *\n * Structural rather than exhaustive: the document is TipTap-shaped JSON whose\n * node vocabulary is open (an app may register its own nodes and marks), so\n * validating the node types would reject a document a newer editor wrote. What\n * has to hold is that it is a `doc` with a `content` array — everything the\n * text pipeline dereferences.\n */\nexport const richTextValidator: Validator<RichText> = T.jsonValue.refine((value) => {\n if (!isRichText(value)) throw new Error(`Expected a rich text document, got ${JSON.stringify(value)}`)\n return { type: \"doc\", content: value.content ?? [] }\n})\n\n/**\n * A validator that accepts exactly what `style` accepts, without *being* a\n * style.\n *\n * Used where a prop holds a style's value but the prop itself is per shape —\n * see the module comment. It defers to the live style prop rather than\n * snapshotting its values, so a palette an app registers through its themes is\n * accepted here too.\n */\nfunction styleValue<Value>(style: StyleProp<Value>): Validator<Value> {\n return T.unknown.refine((value) => style.validate(value))\n}\n\n/**\n * An image's crop window.\n *\n * `ImageShapeCrop` validates the stored shape; the mapping afterwards rebuilds\n * the object with `isCircle` *absent* rather than present-and-undefined, which\n * is the difference between the two spellings under\n * `exactOptionalPropertyTypes` and therefore the difference between this and\n * {@link ImageCrop}.\n */\nconst imageCropValidator: Validator<ImageCrop> = ImageShapeCrop.refine((crop) =>\n crop.isCircle === undefined\n ? { topLeft: crop.topLeft, bottomRight: crop.bottomRight }\n : { topLeft: crop.topLeft, bottomRight: crop.bottomRight, isCircle: crop.isCircle },\n)\n\n/** A point on a shape, in the shape's own space. */\nconst pointValidator = T.object({ x: T.number, y: T.number })\n\n/** A point of a freehand stroke: a position plus optional pen pressure. */\nconst drawPointValidator = T.object({ x: T.number, y: T.number, z: T.number.optional() })\n\n/** One run of a freehand stroke — a pen-down-to-pen-up pass, or a straight leg. */\nconst drawSegmentValidator = T.object({\n type: T.literalEnum(\"free\", \"straight\"),\n points: T.arrayOf(drawPointValidator),\n})\n\n/**\n * The derived plain-text label.\n *\n * Optional on purpose: a v5 writer stores only `richText`, so a record that\n * arrives without `text` is correct and must validate. See\n * `NoteShapeProps.text`.\n */\nconst derivedTextValidator = T.string.optional()\n\n/* ---- shapes -------------------------------------------------------------- */\n\n/** `GeoShapeUtil`'s props; see the module comment. */\nexport const geoShapeProps: RecordProps<GeoShape> = {\n geo: GeoShapeGeoStyle,\n w: T.nonZeroNumber,\n h: T.nonZeroNumber,\n color: DefaultColorStyle,\n labelColor: DefaultLabelColorStyle,\n fill: DefaultFillStyle,\n dash: DefaultDashStyle,\n size: DefaultSizeStyle,\n font: DefaultFontStyle,\n align: DefaultHorizontalAlignStyle,\n verticalAlign: DefaultVerticalAlignStyle,\n growY: T.positiveNumber,\n url: T.linkUrl,\n richText: richTextValidator,\n text: derivedTextValidator,\n scale: T.nonZeroNumber,\n flipX: T.boolean,\n flipY: T.boolean,\n}\n\n/**\n * `ArrowShapeUtil`'s props.\n *\n * `kind`, `arrowheadStart` and `arrowheadEnd` are plain enums rather than\n * styles — see the module comment for why routing and terminals belong to the\n * one arrow.\n */\nexport const arrowShapeProps: RecordProps<ArrowShape> = {\n kind: T.literalEnum(...ARROW_SHAPE_KINDS),\n start: pointValidator,\n end: pointValidator,\n bend: T.number,\n elbowMidPoint: T.number,\n color: DefaultColorStyle,\n labelColor: DefaultLabelColorStyle,\n fill: DefaultFillStyle,\n dash: DefaultDashStyle,\n size: DefaultSizeStyle,\n arrowheadStart: T.literalEnum(...ARROWHEAD_KINDS),\n arrowheadEnd: T.literalEnum(...ARROWHEAD_KINDS),\n font: DefaultFontStyle,\n richText: richTextValidator,\n text: derivedTextValidator,\n labelPosition: T.number,\n scale: T.nonZeroNumber,\n}\n\n/** `DrawShapeUtil`'s props. */\nexport const drawShapeProps: RecordProps<DrawShape> = {\n segments: T.arrayOf(drawSegmentValidator),\n color: DefaultColorStyle,\n fill: DefaultFillStyle,\n dash: DefaultDashStyle,\n size: DefaultSizeStyle,\n isComplete: T.boolean,\n isClosed: T.boolean,\n isPen: T.boolean,\n scale: T.nonZeroNumber,\n}\n\n/** `HighlightShapeUtil`'s props: a draw stroke with no fill and no dash. */\nexport const highlightShapeProps: RecordProps<HighlightShape> = {\n segments: T.arrayOf(drawSegmentValidator),\n color: DefaultColorStyle,\n size: DefaultSizeStyle,\n isComplete: T.boolean,\n isPen: T.boolean,\n scale: T.nonZeroNumber,\n}\n\n/** `LineShapeUtil`'s props. */\nexport const lineShapeProps: RecordProps<LineShape> = {\n color: DefaultColorStyle,\n dash: DefaultDashStyle,\n size: DefaultSizeStyle,\n spline: T.literalEnum(...LINE_SPLINE_KINDS),\n points: T.dict(T.string, T.object({ id: T.string, index: T.string, x: T.number, y: T.number })),\n scale: T.nonZeroNumber,\n}\n\n/** `TextShapeUtil`'s props. */\nexport const textShapeProps: RecordProps<TextShape> = {\n color: DefaultColorStyle,\n size: DefaultSizeStyle,\n font: DefaultFontStyle,\n textAlign: DefaultHorizontalAlignStyle,\n w: T.nonZeroNumber,\n richText: richTextValidator,\n text: derivedTextValidator,\n scale: T.nonZeroNumber,\n autoSize: T.boolean,\n}\n\n/** `NoteShapeUtil`'s props. */\nexport const noteShapeProps: RecordProps<NoteShape> = {\n color: DefaultColorStyle,\n labelColor: DefaultLabelColorStyle,\n size: DefaultSizeStyle,\n font: DefaultFontStyle,\n fontSizeAdjustment: T.positiveNumber,\n align: DefaultHorizontalAlignStyle,\n verticalAlign: DefaultVerticalAlignStyle,\n growY: T.positiveNumber,\n url: T.linkUrl,\n richText: richTextValidator,\n text: derivedTextValidator,\n // Who first edited the label by hand, or `null` while nobody has. Absent on\n // every note written before attribution existed, so optional as well.\n textFirstEditedBy: T.string.nullable().optional(),\n scale: T.nonZeroNumber,\n}\n\n/** `FrameShapeUtil`'s props. */\nexport const frameShapeProps: RecordProps<FrameShape> = {\n w: T.nonZeroNumber,\n h: T.nonZeroNumber,\n name: T.string,\n // A frame's colour is per frame: a frame is chrome around other people's\n // shapes, and recolouring a mixed selection should not repaint the frames it\n // happens to contain. Hence a style *value*, not a style.\n color: styleValue(DefaultColorStyle).optional(),\n}\n\n/** `GroupShapeUtil`'s props: a group is a container and carries none. */\nexport const groupShapeProps: RecordProps<GroupShape> = {}\n\n/** `ImageShapeUtil`'s props. */\nexport const imageShapeProps: RecordProps<ImageShape> = {\n w: T.nonZeroNumber,\n h: T.nonZeroNumber,\n assetId: assetIdValidator.nullable(),\n playing: T.boolean,\n url: T.linkUrl,\n crop: imageCropValidator.nullable(),\n flipX: T.boolean,\n flipY: T.boolean,\n altText: T.string,\n}\n\n/** `VideoShapeUtil`'s props. */\nexport const videoShapeProps: RecordProps<VideoShape> = {\n w: T.nonZeroNumber,\n h: T.nonZeroNumber,\n assetId: assetIdValidator.nullable(),\n time: T.number,\n playing: T.boolean,\n url: T.linkUrl,\n altText: T.string,\n}\n\n/** `BookmarkShapeUtil`'s props. */\nexport const bookmarkShapeProps: RecordProps<BookmarkShape> = {\n w: T.nonZeroNumber,\n h: T.nonZeroNumber,\n assetId: assetIdValidator.nullable(),\n url: T.linkUrl,\n}\n\n/**\n * `EmbedShapeUtil`'s props.\n *\n * `url` is the *page* url as the document stored it, not the iframe's `src` —\n * so it validates as an ordinary link, and the permit list decides separately\n * whether it is embeddable at all.\n */\nexport const embedShapeProps: RecordProps<EmbedShape> = {\n w: T.nonZeroNumber,\n h: T.nonZeroNumber,\n url: T.linkUrl,\n}\n\n/* ---- bindings ------------------------------------------------------------ */\n\n/**\n * `ArrowBindingUtil`'s props.\n *\n * `normalizedAnchor` is a fraction of the bound shape's geometry bounds, which\n * is what lets a bound arrow survive the shape being resized; it is validated\n * as a plain point rather than clamped, because a binding briefly outside\n * `0..1` during a drag is legal and self-correcting.\n */\nexport const arrowBindingProps: RecordProps<ArrowBinding> = {\n terminal: T.literalEnum(\"start\", \"end\"),\n normalizedAnchor: pointValidator,\n isExact: T.boolean,\n isPrecise: T.boolean,\n}\n\n/* ---- registering the built-ins ------------------------------------------ */\n\n/**\n * Hand the maps above to `@mocanvas/editor`'s registry.\n *\n * `createSchema()` builds the `shape` and `binding` record types out of the\n * props maps it can see, and it can only see two sources: the utils a caller\n * passed in, and this registry. `@mocanvas/editor` ships no shapes of its own,\n * so without this the registry stays empty and `createSchema()` — the no-argument\n * form an app or a test uses — builds a `shape` record type that knows nothing\n * and therefore checks nothing. That is exactly the hole that let a `geo` shape\n * with `props: {}` into the store.\n *\n * Only the props are registered. Migration sequences already reach the schema\n * through `createPropsMigrationSequences(shapeUtils)`, and registering them\n * here as well would hand `StoreSchema` the same `sequenceId` twice.\n */\nconst builtInShapeProps: Record<string, UnknownRecordProps> = {\n arrow: arrowShapeProps,\n bookmark: bookmarkShapeProps,\n draw: drawShapeProps,\n embed: embedShapeProps,\n frame: frameShapeProps,\n geo: geoShapeProps,\n group: groupShapeProps,\n highlight: highlightShapeProps,\n image: imageShapeProps,\n line: lineShapeProps,\n note: noteShapeProps,\n text: textShapeProps,\n video: videoShapeProps,\n}\n\nfor (const [type, props] of Object.entries(builtInShapeProps)) {\n registerDefaultShapeSchema(type, { props })\n}\n\nregisterDefaultBindingSchema(\"arrow\", { props: arrowBindingProps })\n","/**\n * The props migration sequence of every built-in shape, and of the built-in\n * `arrow` binding.\n *\n * A sequence is what lets a board saved before a prop existed still load. Every\n * built-in's version 1 does the same job: **backfill the props that post-date\n * the shape**, with the value the shape's own `getDefaultProps` would give\n * them. That is not cosmetic — the shape utils read their props through\n * `read*` helpers with defaults precisely because records arrive incomplete,\n * and a consumer reading `shape.props.scale` off the store directly gets\n * `undefined` on an old board unless something fills it in. The migration does\n * it once on load instead of on every read.\n *\n * Two rules this file is careful about:\n *\n * 1. **The sequence id must be ours.** Every id comes from\n * {@link createBuiltInShapePropsMigrationIds}, which puts it under\n * `com.mocanvas.shape.*`. A `.tldr` written by the reference implementation\n * records its own progress under `com.tldraw.shape.<type>` at a version far\n * past 1, and a schema that claims the same id at version 1 makes every such\n * file fail to load with \"data comes from a newer version\".\n * `src/tldr-compat.test.ts` pins it.\n * 2. **No sequence here is empty.** An empty props sequence carries no id of\n * its own — there is no migration to read one off — so the schema falls back\n * to naming it `com.tldraw.shape.<type>`, which is exactly the claim rule 1\n * forbids. A shape with nothing to backfill therefore still declares a\n * version 1, as a no-op whose only job is to name the sequence.\n *\n * `down` is a no-op throughout for the same reason: version 1 adds only values\n * that clients older than it already tolerated — they are the values those\n * clients implied by leaving the prop out — so there is nothing to undo.\n */\n\nimport {\n createBindingPropsMigrationSequence,\n createBuiltInBindingPropsMigrationIds,\n createBuiltInShapePropsMigrationIds,\n createShapePropsMigrationSequence,\n type MigratableProps,\n type PropsMigrations,\n} from \"@mocanvas/editor\"\nimport { toRichText } from \"../text/rich-text\"\n\n/**\n * Build a built-in shape's version-1 sequence: fill in `defaults` for props\n * that are absent, and — for a label-bearing shape — derive `richText` from a\n * legacy plain-text label, which is the shape v5 changed the most.\n */\nfunction backfillMigration(\n type: string,\n defaults: Readonly<Record<string, unknown>>,\n options: { richTextFromText?: boolean } = {},\n): PropsMigrations {\n const versions = createBuiltInShapePropsMigrationIds(type, { BackfillMissingProps: 1 })\n return createShapePropsMigrationSequence({\n sequence: [\n {\n id: versions.BackfillMissingProps,\n up(props: MigratableProps) {\n if (options.richTextFromText && props[\"richText\"] === undefined) {\n props[\"richText\"] = toRichText(typeof props[\"text\"] === \"string\" ? props[\"text\"] : \"\")\n }\n for (const [key, value] of Object.entries(defaults)) {\n if (props[key] === undefined) props[key] = structuredClone(value)\n }\n },\n down() {},\n },\n ],\n })\n}\n\n/** Named versions of the arrow shape's props; see {@link arrowShapeMigrations}. */\nexport const arrowShapeVersions = createBuiltInShapePropsMigrationIds(\"arrow\", {\n BackfillMissingProps: 1,\n})\n\n/**\n * The arrow shape's props migrations.\n *\n * Elbow routing arrived after the arrow did, so an arrow saved before it has\n * neither `kind` nor `elbowMidPoint`. `\"arc\"` is the routing every such arrow\n * was drawn with, and `0.5` puts a middle leg exactly halfway — where an elbow\n * arrow is created — so an old arrow switched to elbow routing by hand looks\n * like a new one.\n */\nexport const arrowShapeMigrations = backfillMigration(\n \"arrow\",\n { kind: \"arc\", elbowMidPoint: 0.5, labelPosition: 0.5, scale: 1 },\n { richTextFromText: true },\n)\n\n/** The draw shape's props migrations; see the module comment. */\nexport const drawShapeMigrations = backfillMigration(\"draw\", {\n isComplete: true,\n isClosed: false,\n isPen: false,\n scale: 1,\n})\n\n/** The highlight shape's props migrations; see the module comment. */\nexport const highlightShapeMigrations = backfillMigration(\"highlight\", {\n isComplete: true,\n isPen: false,\n scale: 1,\n})\n\n/** The line shape's props migrations; see the module comment. */\nexport const lineShapeMigrations = backfillMigration(\"line\", { spline: \"line\", scale: 1 })\n\n/** The text shape's props migrations; see the module comment. */\nexport const textShapeMigrations = backfillMigration(\"text\", { autoSize: true, scale: 1 }, { richTextFromText: true })\n\n/** The note shape's props migrations; see the module comment. */\nexport const noteShapeMigrations = backfillMigration(\n \"note\",\n { fontSizeAdjustment: 0, growY: 0, url: \"\", scale: 1 },\n { richTextFromText: true },\n)\n\n/** The frame shape's props migrations; see the module comment. */\nexport const frameShapeMigrations = backfillMigration(\"frame\", { name: \"\" })\n\n/**\n * The group shape's props migrations.\n *\n * A group carries no props, so version 1 is a no-op — declared anyway so the\n * sequence is named `com.mocanvas.shape.group` rather than falling back to the\n * reference implementation's id. See rule 2 in the module comment.\n */\nexport const groupShapeMigrations = backfillMigration(\"group\", {})\n\n/** The image shape's props migrations; see the module comment. */\nexport const imageShapeMigrations = backfillMigration(\"image\", {\n assetId: null,\n playing: true,\n url: \"\",\n crop: null,\n flipX: false,\n flipY: false,\n altText: \"\",\n})\n\n/** The video shape's props migrations; see the module comment. */\nexport const videoShapeMigrations = backfillMigration(\"video\", {\n assetId: null,\n time: 0,\n playing: true,\n url: \"\",\n altText: \"\",\n})\n\n/** The bookmark shape's props migrations; see the module comment. */\nexport const bookmarkShapeMigrations = backfillMigration(\"bookmark\", { assetId: null, url: \"\" })\n\n/** The embed shape's props migrations; see the module comment. */\nexport const embedShapeMigrations = backfillMigration(\"embed\", { url: \"\" })\n\n/**\n * The arrow binding's props migrations.\n *\n * Nothing to backfill — an arrow binding has carried the same four props for as\n * long as it has existed — but the sequence is still declared, so that the\n * binding's first prop change has somewhere to go and so that its id is ours\n * rather than the fallback `com.tldraw.binding.arrow`.\n */\nexport const arrowBindingMigrations = createBindingPropsMigrationSequence({\n sequence: [\n {\n id: createBuiltInBindingPropsMigrationIds(\"arrow\", { Initial: 1 }).Initial,\n up() {},\n down() {},\n },\n ],\n})\n","import {\n BaseBoxShapeUtil,\n Rectangle2d,\n createShapeId,\n type AssetId,\n type BaseShape,\n type BookmarkAsset,\n type Editor,\n type Geometry2d,\n type ShapeUtilOptions,\n type StyleWords,\n type TLDefaultDisplayValues,\n type VecLike,\n} from \"@mocanvas/editor\"\nimport type { CSSProperties, ReactNode } from \"react\"\nimport { propsOf, readNumber, readString } from \"./prop-access\"\nimport { bookmarkShapeProps } from \"./shape-props\"\nimport { bookmarkShapeMigrations } from \"./shape-migrations\"\nimport { rectPath } from \"./indicator-paths\"\n\nexport interface BookmarkShapeProps {\n w: number\n h: number\n /** The `bookmark` asset holding the scraped preview; `null` when nothing was scraped. */\n assetId: AssetId | null\n /** The page the card points at. Kept on the shape so a card survives a missing asset. */\n url: string\n}\n\nexport type BookmarkShape = BaseShape<\"bookmark\", BookmarkShapeProps>\n\nexport const BOOKMARK_WIDTH = 300\nexport const BOOKMARK_HEIGHT = 320\n\n// ---- card chrome ----------------------------------------------------------\n\nexport const BOOKMARK_FILL = \"#ffffff\"\nexport const BOOKMARK_STROKE = \"#e8e9ea\"\nexport const BOOKMARK_STROKE_WIDTH = 1\nexport const BOOKMARK_RADIUS = 8\n/** The banner strip behind the asset's preview image (and its colour when there is none). */\nexport const BOOKMARK_BANNER_HEIGHT = 160\nexport const BOOKMARK_BANNER_FILL = \"#eceff3\"\nexport const BOOKMARK_PADDING = 12\nexport const BOOKMARK_GAP = 6\nexport const BOOKMARK_TITLE_HEIGHT = 38\nexport const BOOKMARK_META_HEIGHT = 16\nexport const BOOKMARK_FAVICON_SIZE = 14\nexport const BOOKMARK_TITLE_FONT_SIZE = 14\nexport const BOOKMARK_TEXT_FONT_SIZE = 12\nexport const BOOKMARK_META_FONT_SIZE = 11\nexport const BOOKMARK_TITLE_COLOR = \"#1d1d1d\"\nexport const BOOKMARK_TEXT_COLOR = \"#666666\"\nexport const BOOKMARK_META_COLOR = \"#8f8f8f\"\n/** Body left under the banner even on a short card, so the text never disappears. */\nexport const BOOKMARK_MIN_BODY_HEIGHT = 80\n\n/** A rectangle in shape-local space. */\nexport interface BookmarkRect {\n x: number\n y: number\n w: number\n h: number\n}\n\n/** Where each part of the card sits, in shape-local space. Shared by the overlay and the SVG export. */\nexport interface BookmarkLayout {\n banner: BookmarkRect\n title: BookmarkRect\n description: BookmarkRect\n favicon: BookmarkRect\n hostname: BookmarkRect\n}\n\nexport function getBookmarkLayout(w: number, h: number): BookmarkLayout {\n const pad = BOOKMARK_PADDING\n const innerW = Math.max(0, w - pad * 2)\n const bannerH = Math.max(0, Math.min(BOOKMARK_BANNER_HEIGHT, h - BOOKMARK_MIN_BODY_HEIGHT))\n // The host line is placed from the bottom up and the title is what gives way\n // when the card is short, so a resized card loses its description first and\n // still reads as a link to somewhere.\n const metaY = Math.max(bannerH, h - pad - BOOKMARK_META_HEIGHT)\n const titleY = bannerH + pad\n const titleH = Math.max(0, Math.min(BOOKMARK_TITLE_HEIGHT, metaY - BOOKMARK_GAP - titleY))\n const descY = titleY + titleH + BOOKMARK_GAP\n const clamp = (r: BookmarkRect): BookmarkRect => {\n const x = Math.max(0, Math.min(r.x, w))\n const y = Math.max(0, Math.min(r.y, h))\n return { x, y, w: Math.max(0, Math.min(r.w, w - x)), h: Math.max(0, Math.min(r.h, h - y)) }\n }\n return {\n banner: clamp({ x: 0, y: 0, w, h: bannerH }),\n title: clamp({ x: pad, y: titleY, w: innerW, h: titleH }),\n description: clamp({ x: pad, y: descY, w: innerW, h: metaY - BOOKMARK_GAP - descY }),\n favicon: clamp({\n x: pad,\n y: metaY + (BOOKMARK_META_HEIGHT - BOOKMARK_FAVICON_SIZE) / 2,\n w: BOOKMARK_FAVICON_SIZE,\n h: BOOKMARK_FAVICON_SIZE,\n }),\n hostname: clamp({\n x: pad + BOOKMARK_FAVICON_SIZE + BOOKMARK_GAP,\n y: metaY,\n w: innerW - BOOKMARK_FAVICON_SIZE - BOOKMARK_GAP,\n h: BOOKMARK_META_HEIGHT,\n }),\n }\n}\n\n/**\n * The host a bookmark points at, without a `www.` prefix — the one line of a\n * link card that is always available, since it comes from the shape's own url\n * rather than from a scrape. An unparseable url reads as `\"\"`.\n */\nexport function getBookmarkHostname(url: string): string {\n if (!url) return \"\"\n try {\n const host = new URL(url).hostname.toLowerCase()\n return host.startsWith(\"www.\") ? host.slice(4) : host\n } catch {\n return \"\"\n }\n}\n\n/** The shape's `bookmark` asset, or `null` when it has none (or one of another type). */\nexport function getBookmarkAsset(editor: Editor, shape: BookmarkShape): BookmarkAsset | null {\n const assetId = readString(propsOf(shape), \"assetId\", \"\") as AssetId | \"\"\n if (!assetId) return null\n const asset = editor.getAsset<BookmarkAsset>(assetId)\n return asset && asset.type === \"bookmark\" ? asset : null\n}\n\n/** Everything the card draws, with each field falling back to something renderable. */\nexport interface BookmarkCard {\n title: string\n description: string\n image: string\n favicon: string\n hostname: string\n url: string\n /** Whether the card has a scraped asset behind it; `false` renders the placeholder. */\n hasAsset: boolean\n}\n\nexport function getBookmarkCard(editor: Editor, shape: BookmarkShape): BookmarkCard {\n const url = readString(propsOf(shape), \"url\", \"\")\n const asset = getBookmarkAsset(editor, shape)\n const props = asset ? (asset.props as Partial<BookmarkAsset[\"props\"]>) : undefined\n return {\n title: readString(props, \"title\", \"\"),\n description: readString(props, \"description\", \"\"),\n image: readString(props, \"image\", \"\"),\n favicon: readString(props, \"favicon\", \"\"),\n hostname: getBookmarkHostname(url) || getBookmarkHostname(readString(props, \"src\", \"\") ?? \"\"),\n url,\n hasAsset: asset !== null,\n }\n}\n\nfunction readBookmarkBox(shape: { props?: unknown }): { w: number; h: number } {\n const p = propsOf(shape)\n return { w: readNumber(p, \"w\", BOOKMARK_WIDTH), h: readNumber(p, \"h\", BOOKMARK_HEIGHT) }\n}\n\nconst ELLIPSIS: CSSProperties = { overflow: \"hidden\", textOverflow: \"ellipsis\" }\n\n/**\n * What a bookmark card paints with.\n *\n * A type alias rather than an interface with members of its own: a bookmark's\n * card is chrome, not a styled shape — its colours are the card's, fixed by\n * {@link BOOKMARK_FILL} and friends rather than resolved from the palette — so\n * there is nothing beyond the shared set for it to add.\n */\nexport type BookmarkShapeUtilDisplayValues = TLDefaultDisplayValues\n\n/** `BookmarkShapeUtil`'s settings; see {@link ShapeUtil.configure}. */\nexport interface BookmarkShapeOptions extends ShapeUtilOptions<BookmarkShape, BookmarkShapeUtilDisplayValues> {\n /** The width a new card is created at, in page units. */\n cardWidth?: number\n /** The height a new card is created at, in page units. */\n cardHeight?: number\n}\n\n/**\n * Create a bookmark card for `url` with no asset behind it yet.\n *\n * The card is a valid card without one — it renders the host and the url and\n * nothing else — so this is the half of \"paste a link\" that does not need a\n * network round trip, and the half that is safe to do optimistically while an\n * unfurl is still in flight. Attaching the preview afterwards is a matter of\n * setting `props.assetId`.\n *\n * `point` is the card's *centre* in page space, defaulting to the middle of the\n * viewport, which is where a paste with no pointer position belongs.\n */\nexport function createEmptyBookmarkShape(editor: Editor, url: string, point?: VecLike): BookmarkShape {\n const centre = point ?? editor.getViewportPageBounds().center\n const id = createShapeId()\n editor.run(() => {\n editor.markHistoryStoppingPoint(\"insert bookmark\")\n editor.createShape<BookmarkShape>({\n id,\n type: \"bookmark\",\n x: centre.x - BOOKMARK_WIDTH / 2,\n y: centre.y - BOOKMARK_HEIGHT / 2,\n props: { w: BOOKMARK_WIDTH, h: BOOKMARK_HEIGHT, url, assetId: null },\n })\n editor.setSelectedShapes([id])\n })\n return editor.getShape<BookmarkShape>(id)!\n}\n\nexport class BookmarkShapeUtil extends BaseBoxShapeUtil<BookmarkShape> {\n static override type = \"bookmark\" as const\n static override props = bookmarkShapeProps\n static override migrations = bookmarkShapeMigrations\n declare readonly options: BookmarkShapeOptions\n\n getDefaultProps(): BookmarkShapeProps {\n return { w: BOOKMARK_WIDTH, h: BOOKMARK_HEIGHT, assetId: null, url: \"\" }\n }\n\n override getGeometry(shape: BookmarkShape): Geometry2d {\n const { w, h } = readBookmarkBox(shape)\n return new Rectangle2d({ width: Math.max(1, w), height: Math.max(1, h), isFilled: true })\n }\n\n /**\n * The card is html — a banner image over wrapped, ellipsised text — which no\n * single textured quad can stand in for, so the shape always renders through\n * the DOM overlay.\n */\n override getRenderStyle(_shape: BookmarkShape): StyleWords | null {\n return null\n }\n\n component(shape: BookmarkShape): ReactNode {\n const { w, h } = readBookmarkBox(shape)\n const card = getBookmarkCard(this.editor, shape)\n const layout = getBookmarkLayout(w, h)\n const isEditing = this.editor.getEditingShapeId() === shape.id\n const frame: CSSProperties = {\n position: \"absolute\",\n left: 0,\n top: 0,\n width: w,\n height: h,\n boxSizing: \"border-box\",\n overflow: \"hidden\",\n borderRadius: BOOKMARK_RADIUS,\n background: BOOKMARK_FILL,\n border: `${BOOKMARK_STROKE_WIDTH}px solid ${BOOKMARK_STROKE}`,\n fontFamily: 'system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif',\n /*\n * The canvas owns the pointer: a card is a shape you drag and select,\n * not a link you click. The url is still in the DOM as an `<a>` so\n * assistive tech can read and follow it, but it only takes the pointer\n * while the shape is being edited.\n */\n pointerEvents: isEditing ? \"auto\" : \"none\",\n userSelect: \"none\",\n }\n return (\n <a\n href={card.url || undefined}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n draggable={false}\n aria-label={card.title || card.hostname || card.url || \"bookmark\"}\n tabIndex={isEditing ? 0 : -1}\n style={{ ...frame, display: \"block\", color: \"inherit\", textDecoration: \"none\" }}\n >\n {card.hasAsset ? this.renderCard(card, layout) : this.renderPlaceholder(card, layout)}\n </a>\n )\n }\n\n /** The scraped card: banner, title, description, favicon and host. */\n private renderCard(card: BookmarkCard, layout: BookmarkLayout): ReactNode {\n return (\n <>\n <div style={{ position: \"absolute\", ...layout.banner, background: BOOKMARK_BANNER_FILL, overflow: \"hidden\" }}>\n {card.image ? (\n <img\n src={card.image}\n alt=\"\"\n draggable={false}\n style={{ width: \"100%\", height: \"100%\", objectFit: \"cover\", pointerEvents: \"none\" }}\n />\n ) : null}\n </div>\n <div\n style={{\n position: \"absolute\",\n ...layout.title,\n ...ELLIPSIS,\n fontSize: BOOKMARK_TITLE_FONT_SIZE,\n fontWeight: 600,\n lineHeight: 1.3,\n color: BOOKMARK_TITLE_COLOR,\n }}\n >\n {card.title}\n </div>\n <div\n style={{\n position: \"absolute\",\n ...layout.description,\n ...ELLIPSIS,\n fontSize: BOOKMARK_TEXT_FONT_SIZE,\n lineHeight: 1.4,\n color: BOOKMARK_TEXT_COLOR,\n }}\n >\n {card.description}\n </div>\n {card.favicon ? (\n <img\n src={card.favicon}\n alt=\"\"\n draggable={false}\n style={{ position: \"absolute\", ...layout.favicon, objectFit: \"contain\", pointerEvents: \"none\" }}\n />\n ) : null}\n <div\n style={{\n position: \"absolute\",\n ...layout.hostname,\n ...ELLIPSIS,\n whiteSpace: \"nowrap\",\n fontSize: BOOKMARK_META_FONT_SIZE,\n lineHeight: `${BOOKMARK_META_HEIGHT}px`,\n color: BOOKMARK_META_COLOR,\n }}\n >\n {card.hostname}\n </div>\n </>\n )\n }\n\n /** No asset: an empty banner and the host, so the shape still reads as a link to somewhere. */\n private renderPlaceholder(card: BookmarkCard, layout: BookmarkLayout): ReactNode {\n return (\n <>\n <div style={{ position: \"absolute\", ...layout.banner, background: BOOKMARK_BANNER_FILL }} />\n <div\n style={{\n position: \"absolute\",\n ...layout.title,\n ...ELLIPSIS,\n fontSize: BOOKMARK_TITLE_FONT_SIZE,\n lineHeight: 1.3,\n color: BOOKMARK_META_COLOR,\n }}\n >\n {card.hostname || card.url}\n </div>\n </>\n )\n }\n\n override getIndicatorPath(shape: BookmarkShape): Path2D {\n const { w, h } = readBookmarkBox(shape)\n return rectPath(w, h, BOOKMARK_RADIUS)\n }\n}\n","import {\n BaseBoxShapeUtil,\n Rectangle2d,\n getDefaultDisplayValues,\n type BaseShape,\n type Geometry2d,\n type ShapeUtilOptions,\n type StyleWords,\n type TLColorMode,\n type TLDefaultDisplayValues,\n type TLStyledShape,\n type TLTheme,\n} from \"@mocanvas/editor\"\nimport { embedShapeProps } from \"./shape-props\"\nimport { embedShapeMigrations } from \"./shape-migrations\"\nimport type { CSSProperties, ReactNode } from \"react\"\nimport { propsOf, readNumber, readString } from \"./prop-access\"\nimport { rectPath } from \"./indicator-paths\"\n\nexport interface EmbedShapeProps {\n w: number\n h: number\n /** The page being embedded, as the document stored it (not the iframe's src). */\n url: string\n}\n\nexport type EmbedShape = BaseShape<\"embed\", EmbedShapeProps>\n\nexport const EMBED_WIDTH = 720\nexport const EMBED_HEIGHT = 500\n\nexport const EMBED_PLACEHOLDER_FILL = \"#f5f6f8\"\nexport const EMBED_PLACEHOLDER_STROKE = \"#9fa8b2\"\nexport const EMBED_PLACEHOLDER_TEXT = \"#5f6670\"\nexport const EMBED_PLACEHOLDER_FONT_SIZE = 13\nexport const EMBED_PLACEHOLDER_PADDING = 16\nexport const EMBED_RADIUS = 6\n\n/**\n * The sandbox an embedded page runs in. Scripts and same-origin are what makes\n * a player work at all; popups let a \"watch on the site\" button escape. Nothing\n * else is granted — no forms, no top-level navigation, no pointer lock.\n */\nexport const EMBED_SANDBOX = \"allow-scripts allow-same-origin allow-popups\"\n\n// ---- the permit list ------------------------------------------------------\n\n/**\n * Settings for one embeddable service, as the app supplies them: an api key, a\n * player option, a locale. Opaque to mocanvas — only the definition that\n * declared the service looks inside.\n */\nexport type EmbedSettings = Readonly<Record<string, unknown>>\n\n/**\n * Per-service settings, keyed by {@link EmbedDefinition.type}.\n *\n * ```ts\n * EmbedShapeUtil.configure({ embedConfig: { maps: { apiKey: MAPS_KEY } } })\n * ```\n *\n * This is the *only* route a secret takes into an embed url. See\n * {@link EmbedDefinition.toEmbedUrl}.\n */\nexport type EmbedConfig = Readonly<Record<string, EmbedSettings>>\n\n/**\n * One embeddable service: the exact hosts it is recognised by, and how one of\n * its page urls becomes an embeddable one.\n *\n * `hostnames` are matched exactly (case-insensitively, with a leading `www.`\n * ignored), never as a suffix — `youtube.com.evil.test` is a different host and\n * is not on the list. `toEmbedUrl` receives the parsed url and returns an\n * absolute `https:` url, or `null` when this particular page of the service is\n * not embeddable (a channel page rather than a video, say).\n */\nexport interface EmbedDefinition {\n /** Stable id for the service, e.g. `\"youtube\"`. */\n type: string\n /** Human-readable name, shown on the placeholder card. */\n title: string\n hostnames: readonly string[]\n /**\n * `settings` is this service's entry in the editor's {@link EmbedConfig} —\n * an api key, a player flag, a locale. It is passed in rather than read from\n * the environment on purpose: a definition that reached for `process.env`\n * would only work in one bundler, would leak a secret into every client\n * bundle that imported it, and could not differ between two editors on one\n * page. It is `undefined` when the app configured nothing.\n */\n toEmbedUrl(url: URL, settings?: EmbedSettings): string | null\n /**\n * The width ÷ height this service's content actually is, when it has a fixed\n * one — `16 / 9` for a video player. Optional, and unset on every built-in:\n * a service whose pages vary has no such number, and guessing one would\n * resize somebody's embed for no reason.\n *\n * Where it is set, {@link EmbedShapeUtil.resolveAspectRatio} reports it, a\n * new shape is created at it, and resizing preserves it.\n */\n sizeToContentAspectRatio?: number\n /**\n * The inverse: given an already-embeddable url, the *page* url a person\n * would share. Optional — implement it only where the two forms differ\n * enough that `toEmbedUrl` cannot simply be handed its own output.\n *\n * {@link getEmbedInfo} uses it as its second pass, so that pasting an embed\n * url stores the shareable url on the shape rather than the embed one.\n * Return `null` when the url is not one of this service's embed urls.\n */\n fromEmbedUrl?(url: URL): string | null\n}\n\n/** A url that matched the permit list. */\nexport interface EmbedMatch {\n definition: EmbedDefinition\n /** Absolute `https:` url for the iframe's `src`. */\n embedUrl: string\n}\n\n/** `https://` + host + path + query + hash of an already-permitted url, forcing the scheme. */\nfunction httpsUrl(host: string, url: URL, opts: { hash?: boolean } = {}): string {\n return `https://${host}${url.pathname}${url.search}${opts.hash ? url.hash : \"\"}`\n}\n\n/** A youtube video id: the opaque token youtube itself uses, nothing path-like. */\nfunction youTubeId(candidate: string | undefined | null): string | null {\n return candidate && /^[A-Za-z0-9_-]{6,20}$/.test(candidate) ? candidate : null\n}\n\nconst youtube: EmbedDefinition = {\n type: \"youtube\",\n title: \"YouTube\",\n hostnames: [\"youtube.com\", \"m.youtube.com\", \"youtube-nocookie.com\", \"youtu.be\"],\n toEmbedUrl(url) {\n const segments = url.pathname.split(\"/\").filter(Boolean)\n const host = url.hostname.toLowerCase().replace(/^www\\./, \"\")\n const id =\n host === \"youtu.be\"\n ? youTubeId(segments[0])\n : youTubeId(url.searchParams.get(\"v\")) ??\n (segments[0] === \"embed\" || segments[0] === \"shorts\" || segments[0] === \"live\" ? youTubeId(segments[1]) : null)\n // The no-cookie host is the same player without the tracking cookie.\n return id ? `https://www.youtube-nocookie.com/embed/${id}` : null\n },\n}\n\nconst vimeo: EmbedDefinition = {\n type: \"vimeo\",\n title: \"Vimeo\",\n hostnames: [\"vimeo.com\", \"player.vimeo.com\"],\n toEmbedUrl(url) {\n const id = url.pathname.split(\"/\").filter(Boolean).find((s) => /^\\d{6,12}$/.test(s))\n return id ? `https://player.vimeo.com/video/${id}` : null\n },\n}\n\nconst codesandbox: EmbedDefinition = {\n type: \"codesandbox\",\n title: \"CodeSandbox\",\n hostnames: [\"codesandbox.io\"],\n toEmbedUrl(url) {\n const segments = url.pathname.split(\"/\").filter(Boolean)\n // `/s/<id>`, `/embed/<id>` and `/p/sandbox/<id>` all name the same sandbox.\n const id = segments[0] === \"p\" && segments[1] === \"sandbox\" ? segments[2] : segments[0] === \"s\" || segments[0] === \"embed\" ? segments[1] : null\n return id && /^[A-Za-z0-9_-]{3,64}$/.test(id) ? `https://codesandbox.io/embed/${id}` : null\n },\n}\n\nconst figma: EmbedDefinition = {\n type: \"figma\",\n title: \"Figma\",\n hostnames: [\"figma.com\"],\n toEmbedUrl(url) {\n // An embed url is not a page url: wrapping one would nest it inside a\n // second viewer. `fromEmbedUrl` below is the branch that handles it.\n if (url.pathname === \"/embed\") return null\n // Figma's viewer takes the file url as a parameter rather than a path.\n const target = `https://www.figma.com${url.pathname}${url.search}`\n return `https://www.figma.com/embed?embed_host=mocanvas&url=${encodeURIComponent(target)}`\n },\n // The one built-in whose embed form is not also a valid input to its own\n // `toEmbedUrl`: wrapping an already-wrapped url would nest it twice.\n fromEmbedUrl(url) {\n if (url.pathname !== \"/embed\") return null\n const target = url.searchParams.get(\"url\")\n if (!target) return null\n try {\n const parsed = new URL(target)\n return parsed.protocol === \"https:\" && normalizeHost(parsed.hostname) === \"figma.com\" ? parsed.href : null\n } catch {\n return null\n }\n },\n}\n\nconst googleMaps: EmbedDefinition = {\n type: \"google-maps\",\n title: \"Google Maps\",\n hostnames: [\"google.com\", \"maps.google.com\"],\n toEmbedUrl(url) {\n if (!url.pathname.startsWith(\"/maps\")) return null\n if (url.pathname.startsWith(\"/maps/embed\")) return httpsUrl(\"www.google.com\", url)\n const params = new URLSearchParams(url.search)\n params.set(\"output\", \"embed\")\n return `https://www.google.com/maps?${params.toString()}`\n },\n}\n\nconst excalidraw: EmbedDefinition = {\n type: \"excalidraw\",\n title: \"Excalidraw\",\n hostnames: [\"excalidraw.com\"],\n // The scene lives in the fragment (`#json=`, `#room=`), so it has to survive.\n toEmbedUrl: (url) => httpsUrl(\"excalidraw.com\", url, { hash: true }),\n}\n\n/** The services recognised out of the box. */\nexport const DEFAULT_EMBED_DEFINITIONS: readonly EmbedDefinition[] = [youtube, vimeo, codesandbox, figma, googleMaps, excalidraw]\n\n/**\n * The permit list `getEmbedDefinition` consults. It starts as the defaults and\n * is meant to be extended by the app:\n *\n * ```ts\n * embedDefinitions.push({\n * type: \"intranet\",\n * title: \"Intranet\",\n * hostnames: [\"wiki.example.com\"],\n * toEmbedUrl: (url) => `https://wiki.example.com${url.pathname}?embed=1`,\n * })\n * ```\n *\n * Nothing outside the list is ever put in an iframe.\n */\nexport const embedDefinitions: EmbedDefinition[] = [...DEFAULT_EMBED_DEFINITIONS]\n\n/** One identity for \"no embed settings configured\", so a default argument is stable. */\nconst EMPTY_EMBED_CONFIG: EmbedConfig = Object.freeze({})\n\n/** Hosts are compared case-insensitively, and a leading `www.` never distinguishes one. */\nfunction normalizeHost(hostname: string): string {\n const host = hostname.toLowerCase()\n return host.startsWith(\"www.\") ? host.slice(4) : host\n}\n\n/**\n * The permit-list entry for `url`, with the url to actually put in the iframe,\n * or `null` when the url is not one we embed.\n *\n * Rejects anything that is not `http(s)` (a `javascript:` or `data:` url never\n * reaches an iframe), and matches hosts exactly, so a lookalike host that\n * merely *contains* a permitted one is not embedded.\n */\nexport function getEmbedDefinition(\n url: string,\n definitions: readonly EmbedDefinition[] = embedDefinitions,\n config: EmbedConfig = EMPTY_EMBED_CONFIG,\n): EmbedMatch | null {\n if (typeof url !== \"string\" || url.length === 0) return null\n let parsed: URL\n try {\n parsed = new URL(url)\n } catch {\n return null\n }\n if (parsed.protocol !== \"https:\" && parsed.protocol !== \"http:\") return null\n const host = normalizeHost(parsed.hostname)\n for (const definition of definitions) {\n if (!definition.hostnames.some((h) => normalizeHost(h) === host)) continue\n const embedUrl = definition.toEmbedUrl(parsed, config[definition.type])\n // A permitted host with an unembeddable page falls through to the placeholder.\n if (embedUrl && embedUrl.startsWith(\"https://\")) return { definition, embedUrl }\n return null\n }\n return null\n}\n\n/** What {@link getEmbedInfo} resolved a url to. */\nexport interface EmbedInfo {\n /** The definition that recognised it. */\n definition: EmbedDefinition\n /**\n * The *page* url — what a person would share, and what belongs in\n * `shape.props.url`. For an input that was already a page url this is the\n * input verbatim; for an input that was an embed url it is the recovered\n * page url.\n */\n url: string\n /** The url to actually put in the iframe. */\n embedUrl: string\n}\n\n/**\n * Resolve a url against a permit list, in both directions.\n *\n * Two passes, in this order: `toEmbedUrl` (the url is a page url), then\n * `fromEmbedUrl` (the url is already an embed url and the page url has to be\n * recovered). That is what makes a shared link and an already-embeddable link\n * both work from one entry point.\n *\n * Every url-parsing throw is swallowed: garbage input comes back as `undefined`\n * rather than as an exception inside somebody's onChange handler.\n *\n * Unlike {@link getEmbedDefinition} the permit list is the first argument and\n * is required, because the caller is usually a picker deciding what it will\n * accept rather than the shape util deciding what it will render.\n */\nexport function getEmbedInfo(\n definitions: readonly EmbedDefinition[],\n url: string,\n config: EmbedConfig = EMPTY_EMBED_CONFIG,\n): EmbedInfo | undefined {\n const match = getEmbedDefinition(url, definitions, config)\n if (match !== null) return { definition: match.definition, url, embedUrl: match.embedUrl }\n\n if (typeof url !== \"string\" || url.length === 0) return undefined\n let parsed: URL\n try {\n parsed = new URL(url)\n } catch {\n return undefined\n }\n if (parsed.protocol !== \"https:\" && parsed.protocol !== \"http:\") return undefined\n const host = normalizeHost(parsed.hostname)\n for (const definition of definitions) {\n if (definition.fromEmbedUrl === undefined) continue\n if (!definition.hostnames.some((h) => normalizeHost(h) === host)) continue\n let pageUrl: string | null\n try {\n pageUrl = definition.fromEmbedUrl(parsed)\n } catch {\n pageUrl = null\n }\n if (!pageUrl) continue\n // The embed url is the input itself: it is already the form the iframe wants.\n return { definition, url: pageUrl, embedUrl: parsed.href }\n }\n return undefined\n}\n\nfunction readEmbedBox(shape: { props?: unknown }): { w: number; h: number } {\n const p = propsOf(shape)\n return { w: readNumber(p, \"w\", EMBED_WIDTH), h: readNumber(p, \"h\", EMBED_HEIGHT) }\n}\n\n/**\n * `EmbedShapeUtil`'s settings.\n *\n * ```ts\n * const utils = [\n * EmbedShapeUtil.configure({\n * embedDefinitions: [...DEFAULT_EMBED_DEFINITIONS, intranet],\n * embedConfig: { intranet: { apiKey: process.env.INTRANET_KEY } },\n * }),\n * ]\n * ```\n */\n/**\n * What an embed shape paints with.\n *\n * An embed is an iframe: the page inside it paints itself, and the only thing\n * this shape draws is the placeholder card shown before — or instead of — that\n * page. So those are the values it adds to the shared set.\n */\nexport interface EmbedShapeUtilDisplayValues extends TLDefaultDisplayValues {\n /** Fill of the placeholder card. */\n placeholderFill: string\n /** Border of the placeholder card. */\n placeholderStroke: string\n /** Ink of the text on the placeholder card. */\n placeholderTextColor: string\n /** Corner radius of the card and of the iframe, in page units. */\n cornerRadius: number\n}\n\n/** Resolve an embed's display values; see {@link EmbedShapeUtilDisplayValues}. */\nexport function getEmbedDisplayValues(\n editor: unknown,\n shape: { props?: unknown },\n theme: TLTheme,\n colorMode: TLColorMode,\n): EmbedShapeUtilDisplayValues {\n return {\n ...getDefaultDisplayValues(editor, shape as TLStyledShape, theme, colorMode),\n placeholderFill: EMBED_PLACEHOLDER_FILL,\n placeholderStroke: EMBED_PLACEHOLDER_STROKE,\n placeholderTextColor: EMBED_PLACEHOLDER_TEXT,\n cornerRadius: EMBED_RADIUS,\n }\n}\n\n/* ---- iframe permissions --------------------------------------------------- */\n\n/**\n * The powerful features an embedded page may be granted, as the iframe `allow`\n * attribute names them.\n *\n * Deliberately a *permit* vocabulary and not a copy of the browser's whole\n * feature-policy list: everything absent from here can never be granted by a\n * definition, which is what keeps \"add an embed provider\" from turning into\n * \"hand a third-party page the microphone by accident\".\n */\nexport const EMBED_SHAPE_PERMISSION_NAMES = [\n \"accelerometer\",\n \"autoplay\",\n \"camera\",\n \"clipboard-write\",\n \"encrypted-media\",\n \"fullscreen\",\n \"geolocation\",\n \"gyroscope\",\n \"microphone\",\n \"picture-in-picture\",\n] as const\n\n/** One of {@link EMBED_SHAPE_PERMISSION_NAMES}. */\nexport type EmbedShapePermissionName = (typeof EMBED_SHAPE_PERMISSION_NAMES)[number]\n\n/**\n * Which features an embedded page is granted: present and `true` grants,\n * absent or `false` withholds.\n *\n * A partial map rather than a total one so that a definition states only what\n * it needs; anything it does not mention stays off.\n */\nexport type TLEmbedShapePermissions = { readonly [K in EmbedShapePermissionName]?: boolean }\n\n/**\n * The permissions applied to an embed whose url matched no definition.\n *\n * Empty, and that is the whole point: an unrecognised page gets nothing. The\n * value exists as a named constant rather than as an inline `{}` so that an app\n * that deliberately wants a more permissive fallback has something to override,\n * and so the default is visible rather than implied.\n */\nexport const unknownEmbedShapePermissionOverrides: TLEmbedShapePermissions = {}\n\n/** The `allow` attribute for `permissions`, or `undefined` when nothing is granted. */\nexport function embedShapePermissionsToAllow(permissions: TLEmbedShapePermissions): string | undefined {\n const granted = EMBED_SHAPE_PERMISSION_NAMES.filter((name) => permissions[name] === true)\n return granted.length === 0 ? undefined : granted.join(\"; \")\n}\n\nexport interface EmbedShapeOptions extends ShapeUtilOptions<EmbedShape, EmbedShapeUtilDisplayValues> {\n /**\n * The permit list this util embeds from. Defaults to the mutable module-level\n * {@link embedDefinitions}; naming one here is how two editors on a page get\n * different permit lists, and how an app avoids mutating a global.\n */\n embedDefinitions?: readonly EmbedDefinition[]\n /**\n * Per-service settings, keyed by {@link EmbedDefinition.type} — see\n * {@link EmbedConfig}. Read back as {@link EmbedShapeUtil.embedConfig}.\n */\n embedConfig?: EmbedConfig\n}\n\nexport class EmbedShapeUtil extends BaseBoxShapeUtil<EmbedShape> {\n static override type = \"embed\" as const\n static override props = embedShapeProps\n static override migrations = embedShapeMigrations\n static override options: EmbedShapeOptions = { getDefaultDisplayValues: getEmbedDisplayValues }\n declare readonly options: EmbedShapeOptions\n\n getDefaultProps(): EmbedShapeProps {\n return { w: EMBED_WIDTH, h: EMBED_HEIGHT, url: \"\" }\n }\n\n /**\n * The per-service settings this util was configured with, keyed by\n * {@link EmbedDefinition.type}.\n *\n * Always an object, so a definition can index it without a guard. This is\n * where an api key belongs: a definition is handed its own entry and never\n * reaches for `process.env` itself, which would put the secret in every\n * bundle that imported the definition and make it the same for every editor\n * on the page.\n */\n get embedConfig(): EmbedConfig {\n return this.options.embedConfig ?? EMPTY_EMBED_CONFIG\n }\n\n /** The permit list in force for this util; see {@link EmbedShapeOptions.embedDefinitions}. */\n getEmbedDefinitions(): readonly EmbedDefinition[] {\n return this.options.embedDefinitions ?? embedDefinitions\n }\n\n /** This shape's permit-list entry and iframe url, or `null` when it has none. */\n getEmbedMatch(shape: EmbedShape): EmbedMatch | null {\n return getEmbedDefinition(readString(propsOf(shape), \"url\", \"\"), this.getEmbedDefinitions(), this.embedConfig)\n }\n\n /**\n * The width ÷ height this embed's content wants, or `undefined` when nothing\n * has an opinion about it.\n *\n * Public because the app needs the same answer the util uses: a \"fit to\n * content\" command, a paste handler placing a new embed, a layout engine\n * reserving a slot. It comes from the matching definition's\n * {@link EmbedDefinition.sizeToContentAspectRatio}; a url off the permit\n * list, or a service with no fixed shape, answers `undefined`.\n */\n resolveAspectRatio(shape: EmbedShape): number | undefined {\n const ratio = this.getEmbedMatch(shape)?.definition.sizeToContentAspectRatio\n return typeof ratio === \"number\" && Number.isFinite(ratio) && ratio > 0 ? ratio : undefined\n }\n\n override getGeometry(shape: EmbedShape): Geometry2d {\n const { w, h } = readEmbedBox(shape)\n return new Rectangle2d({ width: Math.max(1, w), height: Math.max(1, h), isFilled: true })\n }\n\n /** An iframe is not a quad: embeds always render through the DOM overlay. */\n override getRenderStyle(_shape: EmbedShape): StyleWords | null {\n return null\n }\n\n component(shape: EmbedShape): ReactNode {\n const { w, h } = readEmbedBox(shape)\n const url = readString(propsOf(shape), \"url\", \"\")\n const match = this.getEmbedMatch(shape)\n const box: CSSProperties = {\n position: \"absolute\",\n left: 0,\n top: 0,\n width: w,\n height: h,\n boxSizing: \"border-box\",\n overflow: \"hidden\",\n borderRadius: EMBED_RADIUS,\n }\n if (!match) {\n return (\n <div\n style={{\n ...box,\n background: EMBED_PLACEHOLDER_FILL,\n border: `1px dashed ${EMBED_PLACEHOLDER_STROKE}`,\n padding: EMBED_PLACEHOLDER_PADDING,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n textAlign: \"center\",\n fontFamily: 'system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif',\n fontSize: EMBED_PLACEHOLDER_FONT_SIZE,\n color: EMBED_PLACEHOLDER_TEXT,\n wordBreak: \"break-all\",\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n aria-label={url ? `embed: ${url}` : \"embed\"}\n >\n {url || \"No embed url\"}\n </div>\n )\n }\n /*\n * An iframe that takes the pointer swallows the gesture that was meant to\n * pan or select the canvas — the wheel and the drag never reach us. So the\n * frame is inert until the shape is being edited, and the canvas keeps its\n * own gestures the rest of the time.\n */\n const isEditing = this.editor.getEditingShapeId() === shape.id\n return (\n <div style={box}>\n <iframe\n src={match.embedUrl}\n title={`${match.definition.title} embed`}\n width={w}\n height={h}\n sandbox={EMBED_SANDBOX}\n // The origin, and nothing more. `no-referrer` is the stricter setting and\n // was the obvious one to reach for, but a player that has to check which\n // domain is embedding it cannot: YouTube answers a refererless embed with\n // \"error 153\" and refuses to play. This sends the scheme and host — what\n // the check needs — and never the path or query of the page the canvas is\n // on, and sends nothing at all when a secure page is embedded by an\n // insecure one.\n referrerPolicy=\"strict-origin-when-cross-origin\"\n loading=\"lazy\"\n allowFullScreen\n style={{ display: \"block\", width: \"100%\", height: \"100%\", border: 0, pointerEvents: isEditing ? \"auto\" : \"none\" }}\n />\n </div>\n )\n }\n\n override getIndicatorPath(shape: EmbedShape): Path2D {\n const { w, h } = readEmbedBox(shape)\n return rectPath(w, h, EMBED_RADIUS)\n }\n\n /**\n * \"Editing\" an embed is not typing into it — the shape has no text of its own.\n * It is the state in which the embedded page takes the pointer, and it is the\n * state the iframe above waits for.\n *\n * Saying no here left that state unreachable, so the frame stayed inert for\n * good and the embed was a picture of a page rather than a page: a video that\n * would not play, a map that would not pan. Saying yes gives an embed the same\n * two-step every canvas uses for something that wants the pointer for itself —\n * one click selects the shape and its handles, a double click hands the\n * pointer over, and clicking away takes it back.\n */\n override canEdit(_shape: EmbedShape): boolean {\n return true\n }\n\n /**\n * An embed whose service declared a fixed content shape resizes\n * proportionally; anything else is a free box.\n */\n // SEMANTICS-ASSUMED: tying the lock to `sizeToContentAspectRatio` is the\n // reading that makes the two features one feature — the ratio is declared\n // once and both sizing paths honour it — and it is a no-op for every\n // built-in, none of which declares one.\n override isAspectRatioLocked(shape: EmbedShape): boolean {\n return this.resolveAspectRatio(shape) !== undefined\n }\n\n /**\n * A new embed is created at its service's content ratio, keeping the width\n * it was asked for. Nothing happens for a service with no declared ratio.\n */\n override onBeforeCreate(next: EmbedShape): EmbedShape | void {\n const ratio = this.resolveAspectRatio(next)\n if (ratio === undefined) return\n const { w } = readEmbedBox(next)\n const h = Math.max(1, w / ratio)\n if (h === readEmbedBox(next).h) return\n return { ...next, props: { ...next.props, h } }\n }\n}\n"]}