@webx-ui/core 0.42.0 → 0.44.0
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.
- package/dist/CodeEditor-gPYUUsSB.js +428 -0
- package/dist/CodeEditor-gPYUUsSB.js.map +1 -0
- package/dist/RichText-Dmaf7-UT.js +805 -0
- package/dist/RichText-Dmaf7-UT.js.map +1 -0
- package/dist/components/CodeEditor/index.d.ts +45 -1
- package/dist/components/CodeEditor/languageCompletions.d.ts +8 -0
- package/dist/components/CodeEditor/types.d.ts +13 -0
- package/dist/components/FileCard/FileCard.d.ts +6 -6
- package/dist/components/Input/Input.d.ts +1 -1
- package/dist/components/RichText/index.d.ts +123 -1
- package/dist/index-OwTgLBpg.js +15756 -0
- package/dist/index-OwTgLBpg.js.map +1 -0
- package/dist/index.js +159 -16854
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RichText-Dmaf7-UT.js","sources":["../src/components/RichText/icons.ts","../src/components/RichText/ToolbarButton.vue","../src/components/RichText/source.ts","../src/components/RichText/tools.ts","../src/components/RichText/RichText.vue"],"sourcesContent":["/**\n * Toolbar glyphs as raw path data, drawn on a 24×24 grid with a 1.7 stroke.\n * Inline rather than an icon package: it is a dozen paths, and a dependency for\n * that would be worse than the duplication.\n */\nexport const richTextIcons: Record<string, string> = {\n bold: 'M7 5h6a3.5 3.5 0 0 1 0 7H7zm0 7h7a3.5 3.5 0 0 1 0 7H7z',\n italic: 'M15 5h-5M14 19H9M13.5 5 10.5 19',\n accent: 'M5 19 12 5l7 14M8 13h8M18 4.5h.01',\n strike:\n 'M5 12h14M8 8.5A3 3 0 0 1 11 6h2a3 3 0 0 1 3 2.5M16 15.5A3 3 0 0 1 13 18h-2a3 3 0 0 1-3-2.5',\n code: 'm9 8-5 4 5 4M15 8l5 4-5 4',\n bulletList: 'M9 6h11M9 12h11M9 18h11M4.5 6h.01M4.5 12h.01M4.5 18h.01',\n orderedList: 'M10 6h10M10 12h10M10 18h10M4 6h1v4M4 10h2M4 14h2v2H4v2h2',\n blockquote: 'M7 15V9h4v6H7l-2 3M15 15V9h4v6h-4l-2 3',\n hr: 'M4 12h16',\n link: 'M10 13a4 4 0 0 0 5.7.4l2.6-2.6a4 4 0 0 0-5.7-5.7l-1.5 1.5M14 11a4 4 0 0 0-5.7-.4l-2.6 2.6a4 4 0 0 0 5.7 5.7l1.5-1.5',\n table: 'M4 6h16v12H4zM4 10h16M10 10v8M4 14h16',\n image: 'M4 6h16v12H4zM4 15l4-4 4 4 3-3 5 5M9 9.5h.01',\n youtube:\n 'M3 8.5A2.5 2.5 0 0 1 5.5 6h13A2.5 2.5 0 0 1 21 8.5v7a2.5 2.5 0 0 1-2.5 2.5h-13A2.5 2.5 0 0 1 3 15.5zM10.5 9.5l4 2.5-4 2.5z',\n undo: 'M4 9h11a4.5 4.5 0 0 1 0 9h-4M4 9l4-4M4 9l4 4',\n redo: 'M20 9H9a4.5 4.5 0 0 0 0 9h4M20 9l-4-4M20 9l-4 4',\n source: 'm8 8-4 4 4 4M16 8l4 4-4 4M13.5 5l-3 14',\n rowAfter: 'M4 5h16M4 11h16M8 15v6M5 18h6',\n rowBefore: 'M4 19h16M4 13h16M8 3v6M5 6h6',\n columnAfter: 'M5 4v16M11 4v16M15 8h6M18 5v6',\n columnBefore: 'M19 4v16M13 4v16M3 8h6M6 5v6',\n deleteRow: 'M4 8h16M4 16h16M9 12h6',\n deleteColumn: 'M8 4v16M16 4v16M12 9v6',\n deleteTable: 'M5 7h14M9 7V5h6v2M7 7l1 12h8l1-12M10 11v4M14 11v4',\n mergeCells: 'M4 6h16v12H4zM12 6v3M12 15v3M9 12h6M9 12l2-2M9 12l2 2',\n token: 'M9 4H6v16h3M15 4h3v16h-3',\n check: 'm5 13 4 4L19 7',\n close: 'M6 6l12 12M18 6 6 18',\n}\n","<script setup lang=\"ts\">\nimport { richTextIcons } from './icons'\n\ndefineOptions({ name: 'WxRichTextToolbarButton' })\n\nwithDefaults(\n defineProps<{\n /** Key into the icon set. Omit it and the `text` shows instead. */\n icon?: string\n /** Short label used for headings, where a glyph reads worse than \"H2\". */\n text?: string\n label: string\n active?: boolean\n disabled?: boolean\n }>(),\n { icon: undefined, text: undefined, active: false, disabled: false },\n)\n\ndefineEmits<{ click: [] }>()\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"wx-rich-text__tool\"\n :class=\"{ 'is-active': active }\"\n :title=\"label\"\n :aria-label=\"label\"\n :aria-pressed=\"active\"\n :disabled=\"disabled\"\n @click=\"$emit('click')\"\n >\n <svg v-if=\"icon\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <path\n :d=\"richTextIcons[icon]\"\n stroke=\"currentColor\"\n stroke-width=\"1.7\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <span v-else class=\"wx-rich-text__tool-text\">{{ text }}</span>\n </button>\n</template>\n\n<style scoped>\n.wx-rich-text__tool {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 30px;\n height: 30px;\n padding: 0;\n background: transparent;\n border: 1px solid transparent;\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-default);\n cursor: pointer;\n transition:\n background-color var(--wx-duration-fast) var(--wx-easing-standard),\n color var(--wx-duration-fast) var(--wx-easing-standard);\n}\n\n.wx-rich-text__tool svg {\n width: 18px;\n height: 18px;\n}\n\n.wx-rich-text__tool-text {\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-rich-text__tool:hover:not(:disabled) {\n background: var(--wx-bg-fill);\n}\n\n.wx-rich-text__tool.is-active {\n background: var(--wx-color-primary-soft);\n color: var(--wx-color-primary);\n}\n\n.wx-rich-text__tool:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-rich-text__tool:disabled {\n color: var(--wx-text-disabled);\n cursor: not-allowed;\n}\n</style>\n","/**\n * The HTML behind the editor, as a person reads and edits it.\n *\n * Tiptap writes the document as one line, which is unreadable past a paragraph. Blocks go on\n * lines of their own here, and whatever holds other blocks indents them. Whitespace between\n * blocks means nothing to the parser, so the document that comes back is the one that went in.\n */\n\n/** Tags whose children are blocks: each child gets a line, one step further in. */\nconst CONTAINERS = new Set([\n 'ul',\n 'ol',\n 'li',\n 'blockquote',\n 'table',\n 'colgroup',\n 'thead',\n 'tbody',\n 'tfoot',\n 'tr',\n 'th',\n 'td',\n 'div',\n 'figure',\n])\n\n/** Tags that start a line and keep their content on it. */\nconst LINES = new Set([\n 'p',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'pre',\n 'hr',\n 'img',\n 'iframe',\n 'col',\n 'figcaption',\n])\n\nconst VOID = new Set(['hr', 'img', 'br', 'col', 'wbr', 'source', 'input'])\n\nconst TAG = /<(\\/?)([a-zA-Z][a-zA-Z0-9-]*)\\b[^>]*?(\\/?)>/g\n\nexport function formatHtml(html: string, indent = ' '): string {\n let out = ''\n let depth = 0\n /** Inside a line block nothing breaks: a newline there would be a space in the text. */\n let inLine = 0\n let inPre = 0\n let last = 0\n\n const breakLine = (): void => {\n out += `\\n${indent.repeat(depth)}`\n }\n\n for (const match of html.matchAll(TAG)) {\n const [token, closing, rawName, selfClosing] = match\n const name = rawName.toLowerCase()\n out += html.slice(last, match.index)\n last = match.index + token.length\n\n if (inPre > 0 && name !== 'pre') {\n out += token\n continue\n }\n\n const free = inLine === 0\n const isVoid = VOID.has(name) || selfClosing === '/'\n\n if (CONTAINERS.has(name) && free) {\n if (closing) {\n depth = Math.max(0, depth - 1)\n breakLine()\n out += token\n } else {\n breakLine()\n out += token\n if (!isVoid) depth += 1\n }\n continue\n }\n\n if (LINES.has(name)) {\n if (!closing && free) breakLine()\n out += token\n if (name === 'pre') inPre += closing ? -1 : 1\n if (!isVoid) inLine += closing ? -1 : 1\n inLine = Math.max(0, inLine)\n continue\n }\n\n out += token\n }\n\n out += html.slice(last)\n\n return out.replace(/^\\n/, '')\n}\n\n/** Tags the editor writes under another name: not a loss, only a spelling. */\nconst SPELLINGS: Record<string, string> = { b: 'strong', i: 'em', del: 's', strike: 's' }\n\nfunction census(html: string): Map<string, number> {\n const counts = new Map<string, number>()\n const add = (key: string): void => {\n counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n const template = document.createElement('template')\n template.innerHTML = html\n\n for (const element of template.content.querySelectorAll('*')) {\n const tag = element.tagName.toLowerCase()\n const name = SPELLINGS[tag] ?? tag\n add(`<${name}>`)\n for (const attribute of element.getAttributeNames()) add(`${attribute} on <${name}>`)\n }\n\n return counts\n}\n\n/**\n * What a document loses on its way into the editor: the tags and attributes the editor's schema\n * does not know, each named once. ProseMirror drops them without a word, which is fine for a\n * paste and not for markup a person has just typed by hand.\n *\n * Counted rather than merely listed, so that one `<span>` the editor keeps does not vouch for\n * the nine it drops. What the editor adds — a paragraph around bare text, its own `rel` on a\n * link — is not a loss and is not reported.\n */\nexport function lostMarkup(before: string, after: string): string[] {\n const had = census(before)\n const kept = census(after)\n const lost: string[] = []\n\n for (const [key, count] of had) {\n if ((kept.get(key) ?? 0) < count) lost.push(key)\n }\n\n // A dropped tag takes its attributes with it; naming both says the same thing twice.\n const droppedTags = new Set(lost.filter((key) => key.startsWith('<')))\n\n return lost.filter((key) => {\n const on = / on (<[^>]+>)$/.exec(key)\n return !on || !droppedTags.has(on[1])\n })\n}\n","import type { RichTextTableTool, RichTextTool } from './types'\n\n/**\n * Kept out of the component because `withDefaults` cannot reference a binding\n * declared inside `<script setup>` — it is hoisted out of `setup()`.\n */\nexport const DEFAULT_TOOLS: RichTextTool[] = [\n 'bold',\n 'italic',\n 'strike',\n 'code',\n 'divider',\n 'h2',\n 'h3',\n 'h4',\n 'divider',\n 'bulletList',\n 'orderedList',\n 'blockquote',\n 'hr',\n 'divider',\n 'link',\n 'table',\n 'image',\n 'youtube',\n 'divider',\n 'undo',\n 'redo',\n 'divider',\n 'source',\n]\n\n/** What an inline field offers: the marks a line of a heading is ever given. */\nexport const INLINE_TOOLS: RichTextTool[] = ['bold', 'italic', 'accent']\n\nexport const DEFAULT_ACCEPT = [\n 'image/png',\n 'image/jpeg',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n]\n\nexport interface ToolMeta {\n label: string\n icon?: string\n text?: string\n}\n\nexport const TOOL_META: Record<Exclude<RichTextTool, 'divider'>, ToolMeta> = {\n bold: { label: 'Bold', icon: 'bold' },\n italic: { label: 'Italic', icon: 'italic' },\n accent: { label: 'Accent', icon: 'accent' },\n strike: { label: 'Strikethrough', icon: 'strike' },\n code: { label: 'Inline code', icon: 'code' },\n h2: { label: 'Heading 2', text: 'H2' },\n h3: { label: 'Heading 3', text: 'H3' },\n h4: { label: 'Heading 4', text: 'H4' },\n bulletList: { label: 'Bulleted list', icon: 'bulletList' },\n orderedList: { label: 'Numbered list', icon: 'orderedList' },\n blockquote: { label: 'Quote', icon: 'blockquote' },\n hr: { label: 'Divider', icon: 'hr' },\n link: { label: 'Link', icon: 'link' },\n table: { label: 'Table', icon: 'table' },\n image: { label: 'Image', icon: 'image' },\n youtube: { label: 'YouTube video', icon: 'youtube' },\n undo: { label: 'Undo', icon: 'undo' },\n redo: { label: 'Redo', icon: 'redo' },\n source: { label: 'HTML source', icon: 'source' },\n}\n\n/** Shown as a second row while the caret sits inside a table. */\nexport const TABLE_TOOLS: { key: RichTextTableTool; label: string; icon: string }[] = [\n { key: 'addRowAfter', label: 'Row below', icon: 'rowAfter' },\n { key: 'addRowBefore', label: 'Row above', icon: 'rowBefore' },\n { key: 'addColumnAfter', label: 'Column after', icon: 'columnAfter' },\n { key: 'addColumnBefore', label: 'Column before', icon: 'columnBefore' },\n { key: 'deleteRow', label: 'Delete row', icon: 'deleteRow' },\n { key: 'deleteColumn', label: 'Delete column', icon: 'deleteColumn' },\n { key: 'mergeOrSplit', label: 'Merge or split cells', icon: 'mergeCells' },\n { key: 'deleteTable', label: 'Delete table', icon: 'deleteTable' },\n]\n\nexport type TableToolKey = RichTextTableTool\n","<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch } from 'vue'\nimport {\n Extension,\n Mark,\n Node,\n createDocument,\n getHTMLFromFragment,\n type Extensions,\n} from '@tiptap/core'\nimport { EditorContent, useEditor } from '@tiptap/vue-3'\nimport StarterKit from '@tiptap/starter-kit'\nimport { TableKit } from '@tiptap/extension-table'\nimport Image from '@tiptap/extension-image'\nimport Youtube from '@tiptap/extension-youtube'\nimport FileHandler from '@tiptap/extension-file-handler'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\nimport { useFormField } from '../../composables/useFormField'\nimport { useLocalized } from '../../composables/useLocalized'\nimport LocalePicker from '../Locales/LocalePicker.vue'\nimport WxTokenMenu from '../../internal/TokenMenu.vue'\nimport {\n fieldAnchor,\n rectOf,\n tokenAnchor,\n tokenSpans,\n tokenText,\n useTokenMenu,\n type TokenAnchor,\n type TokenOption,\n type TokenRange,\n} from '../../composables/useTokens'\nimport WxButton from '../Button/Button.vue'\n// The source view only: CodeMirror comes when somebody opens it, not with every text field.\nimport { WxCodeEditor } from '../CodeEditor'\nimport WxRichTextToolbarButton from './ToolbarButton.vue'\nimport { formatHtml, lostMarkup } from './source'\nimport {\n DEFAULT_ACCEPT,\n DEFAULT_TOOLS,\n INLINE_TOOLS,\n TABLE_TOOLS,\n TOOL_META,\n type TableToolKey,\n} from './tools'\nimport type {\n RichTextEmits,\n RichTextImage,\n RichTextLabelKey,\n RichTextLabels,\n RichTextModelValue,\n RichTextProps,\n RichTextTool,\n} from './types'\n\ndefineOptions({ name: 'WxRichText', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<RichTextProps>(), {\n placeholder: undefined,\n disabled: undefined,\n readonly: false,\n size: undefined,\n status: undefined,\n id: undefined,\n ariaLabel: undefined,\n inline: false,\n // Both left unset rather than defaulted: what they default to depends on `inline`, and\n // `withDefaults` cannot see the other props.\n minHeight: undefined,\n tools: undefined,\n upload: undefined,\n pickImage: undefined,\n accept: () => DEFAULT_ACCEPT,\n labels: undefined,\n localized: false,\n tokens: undefined,\n tokensTitle: 'Placeholders',\n tokensLabel: 'Insert a placeholder',\n})\n\n/**\n * What the editor says when nobody told it otherwise. English is the floor rather than the\n * source of truth: a panel running in ten languages hands its own words in, and a key it\n * forgot stays readable instead of blank.\n */\nconst DEFAULT_LABELS: RichTextLabels = {\n toolbar: 'Text formatting',\n linkAddress: 'Link address',\n youtubeAddress: 'YouTube URL',\n apply: 'Apply',\n cancel: 'Cancel',\n uploading: 'Uploading…',\n sourceLoss: 'The editor does not keep this markup and will remove it:',\n sourceDrop: 'Remove it',\n sourceKeep: 'Keep editing',\n}\n\nfunction label(key: RichTextLabelKey): string {\n const given = props.labels?.[key] ?? DEFAULT_LABELS[key]\n\n if (given !== undefined) return given\n if (key in TOOL_META) return TOOL_META[key as Exclude<RichTextTool, 'divider'>].label\n\n return TABLE_TOOLS.find((tool) => tool.key === key)?.label ?? key\n}\n\nconst emit = defineEmits<RichTextEmits>()\n\n/**\n * The picture node, taught one attribute of its own.\n *\n * ProseMirror keeps only the attributes a node declares — anything else is dropped the first\n * time the document is parsed, silently and in both directions — so the library key has to be\n * a declared attribute rather than something written onto the tag.\n */\nconst LibraryImage = Image.extend({\n addAttributes() {\n return {\n ...this.parent?.(),\n path: {\n default: null,\n parseHTML: (element: HTMLElement) => element.getAttribute('data-wx-path'),\n renderHTML: (attributes: Record<string, unknown>) =>\n attributes.path === null || attributes.path === undefined\n ? {}\n : { 'data-wx-path': String(attributes.path) },\n },\n }\n },\n})\n\n/**\n * The accent of a line: a bare `<span>`, because that is what a heading written by hand already\n * holds — `Deeply heard<span>.</span>` — and what a site's styles colour. No class: a class would\n * be one more thing to agree on between the panel and every theme.\n */\nconst Accent = Mark.create({\n name: 'accent',\n parseHTML: () => [{ tag: 'span' }],\n renderHTML: () => ['span', 0],\n})\n\n/**\n * The document of an inline field is the line itself — text and its marks, no paragraph around\n * it — so `getHTML()` answers with exactly what a template prints inside its `<h1>`.\n */\nconst LineDocument = Node.create({ name: 'doc', topNode: true, content: 'text*' })\n\n/**\n * Enter has nowhere to go in a line. Swallowed rather than left to ProseMirror, which would try\n * to split a block the schema does not have.\n */\nconst OneLine = Extension.create({\n name: 'wxOneLine',\n addKeyboardShortcuts: () => ({\n Enter: () => true,\n 'Shift-Enter': () => true,\n 'Mod-Enter': () => true,\n }),\n})\n\nconst tokens = useTokenMenu(() => props.tokens)\nconst hasTokens = computed(() => tokens.all.value.length > 0)\n\nconst tokenChipsKey = new PluginKey('wxTokenChips')\n\n/**\n * The known placeholders drawn as chips: a decoration over the text `[name]`, not a node.\n *\n * A node would have to be written back as something, and what the site reads is the brackets\n * typed as text — so the document keeps them as text, `getHTML()` answers with them as text,\n * and the chip exists only on screen. A name nobody registered stays plain, which is the hint\n * that it will print as typed.\n */\nconst TokenChips = Extension.create({\n name: 'wxTokenChips',\n addProseMirrorPlugins: () => [\n new Plugin({\n key: tokenChipsKey,\n props: {\n decorations: (state) => {\n const known = tokens.known.value\n if (known.size === 0) return DecorationSet.empty\n\n const chips: Decoration[] = []\n\n state.doc.descendants((node, pos) => {\n if (!node.isText || !node.text) return\n\n for (const span of tokenSpans(node.text, known)) {\n chips.push(\n Decoration.inline(pos + span.from, pos + span.to, {\n class: 'wx-token',\n 'data-token': span.name,\n }),\n )\n }\n })\n\n return DecorationSet.create(state.doc, chips)\n },\n },\n }),\n ],\n})\n\nfunction inlineExtensions(): Extensions {\n return [\n StarterKit.configure({\n document: false,\n paragraph: false,\n heading: false,\n blockquote: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n listKeymap: false,\n codeBlock: false,\n code: false,\n horizontalRule: false,\n hardBreak: false,\n strike: false,\n underline: false,\n link: false,\n trailingNode: false,\n gapcursor: false,\n }),\n LineDocument,\n Accent,\n OneLine,\n TokenChips,\n ]\n}\n\nfunction documentExtensions(): Extensions {\n return [\n StarterKit.configure({\n link: {\n openOnClick: false,\n autolink: true,\n HTMLAttributes: { rel: 'noopener noreferrer nofollow', target: '_blank' },\n },\n }),\n TableKit.configure({ table: { resizable: true } }),\n LibraryImage.configure({ HTMLAttributes: { class: 'wx-rich-text__image' } }),\n Youtube.configure({ nocookie: true, width: 640, height: 360 }),\n FileHandler.configure({\n allowedMimeTypes: props.accept,\n onDrop: (_editor, files, pos) => void uploadFiles(files, pos),\n onPaste: (_editor, files) => void uploadFiles(files),\n }),\n TokenChips,\n ]\n}\n\nconst toolList = computed(() => props.tools ?? (props.inline ? INLINE_TOOLS : DEFAULT_TOOLS))\n\n/** A line is as tall as a line; a document starts tall enough to look like one. */\nconst bodyHeight = computed(() => props.minHeight ?? (props.inline ? undefined : '220px'))\n\nconst model = defineModel<RichTextModelValue>({ default: '' })\n\nconst field = useFormField(props)\n\nconst locales = useLocalized(props, model)\n\n/** The language on screen, or nothing at all when the field is plain. */\nconst editing = computed(() => (locales.on.value ? locales.active.value : undefined))\n\n/*\n * One editor, one language at a time. The other languages are not rendered anywhere — an\n * editor is a document, not a line, and four of them stacked is four documents to scroll past\n * to reach the next field. What the chip does is swap the document in this one.\n */\nconst currentValue = computed(() => locales.read(editing.value))\nconst focused = ref(false)\nconst uploading = ref(0)\nconst fileInput = ref<HTMLInputElement | null>(null)\n\n/** The link and YouTube buttons open one shared bar rather than a `prompt()`. */\nconst prompt = ref<{ kind: 'link' | 'youtube'; value: string } | null>(null)\n\nconst editable = computed(() => !field.disabled.value && !props.readonly)\n\n/** The HTML on screen while the source view is open; `null` while the editor is. */\nconst source = ref<string | null>(null)\n\n/** What leaving the source would cost, while the editor waits to hear whether that is fine. */\nconst losing = ref<string[] | null>(null)\n\n/** The source as it was opened: leaving it untouched has nothing to check and nothing to apply. */\nlet opened = ''\n\n/** Tiptap renders `<p></p>` for an empty document; a backend wants an empty string. */\nfunction readHtml(): string {\n const instance = editor.value\n if (!instance || instance.isEmpty) return ''\n return instance.getHTML()\n}\n\nconst editor = useEditor({\n content: currentValue.value,\n editable: editable.value,\n extensions: props.inline ? inlineExtensions() : documentExtensions(),\n editorProps: {\n // The list's keys first: Enter picks a placeholder rather than splitting the paragraph.\n handleKeyDown: (_view, event) => tokens.keydown(event, insertToken),\n ...(props.inline\n ? {\n // Pasted lines become one line: the breaks would otherwise vanish between the words\n // and glue the last of one line to the first of the next.\n transformPastedText: (text: string) => text.replace(/\\s*[\\r\\n]+\\s*/g, ' '),\n }\n : {}),\n },\n onUpdate: () => {\n const html = readHtml()\n // Tiptap raises an update for things that are not edits too. Writing the same words back\n // still changes the model's shape — an empty `[]` from the server becomes `{ en: '' }` —\n // and a form that compares snapshots reads that as a change and autosaves a draft.\n if (html === currentValue.value) return\n locales.write(editing.value, html)\n emit('change', html)\n suggestTokens()\n },\n onSelectionUpdate: () => {\n // A caret moved by hand: an open list follows it, or goes.\n if (tokens.open.value) suggestTokens()\n },\n onFocus: () => {\n focused.value = true\n emit('focus')\n },\n onBlur: () => {\n focused.value = false\n tokens.close()\n emit('blur')\n },\n})\n\n/**\n * Only replaces the document when the value really differs, or the caret jumps. Watching the\n * language being edited rather than the model: with a localized field those are different\n * things, and switching the chip has to bring the other language's document in.\n */\nwatch(currentValue, (value) => {\n const instance = editor.value\n if (!instance) return\n // The source view owns the value while it is open; another language brings its own source.\n if (source.value !== null) {\n if (value !== source.value) openSource(value)\n return\n }\n if (value === readHtml()) return\n instance.commands.setContent(value, { emitUpdate: false })\n})\n\n/*\n * Without the update Tiptap sends by default: a form locked for the length of a request and\n * unlocked after it would otherwise hear every editor on it \"change\" at once.\n */\nwatch(editable, (value) => editor.value?.setEditable(value, false))\n\n/*\n * Placeholders arrive after the editor — a panel fetches them — and decorations are only drawn\n * again on a transaction, so the arrival is one: empty, and changing nothing in the document.\n */\nwatch(tokens.known, () => {\n const instance = editor.value\n if (instance) instance.view.dispatch(instance.state.tr.setMeta(tokenChipsKey, true))\n})\n\nconst rootRef = ref<HTMLElement | null>(null)\nconst tokenListId = computed(() => `${field.id.value}-tokens`)\n\n/** Under the line at a position of the document; under the field where nothing is measured. */\nfunction caretAnchor(pos: number): TokenAnchor | undefined {\n try {\n const at = editor.value?.view.coordsAtPos(pos)\n if (at && at.bottom > at.top) {\n return tokenAnchor(rectOf(at.left, at.top, 0, at.bottom - at.top), rootRef.value)\n }\n } catch {\n // No layout to ask (a test), or a position the view has not drawn yet.\n }\n return fieldAnchor(rootRef.value, null)\n}\n\n/** After a keystroke or a caret move: open, narrow or close the list by what is before it. */\nfunction suggestTokens(): void {\n const instance = editor.value\n if (!instance || !hasTokens.value || !editable.value) return\n\n const { selection } = instance.state\n const { $from } = selection\n\n if (!selection.empty || !$from.parent.isTextblock) return tokens.close()\n\n // Every leaf inline node counts as one character, so offsets stay document positions.\n const before = $from.parent.textBetween(0, $from.parentOffset, undefined, '')\n tokens.suggest(before, $from.pos, () =>\n caretAnchor($from.pos - before.length + before.lastIndexOf('[')),\n )\n}\n\nfunction insertToken(token: TokenOption, at: TokenRange): void {\n const instance = editor.value\n if (!instance) return\n\n instance\n .chain()\n .focus()\n .command(({ tr }) => {\n tr.insertText(tokenText(token), at.from, at.to)\n return true\n })\n .run()\n}\n\n/** The toolbar's button: every placeholder, going where the caret is or over the selection. */\nfunction browseTokens(): void {\n const instance = editor.value\n if (!instance) return\n if (tokens.open.value && tokens.browsing.value) return tokens.close()\n\n const { from, to } = instance.state.selection\n instance.commands.focus()\n tokens.browse({ from, to }, caretAnchor(from))\n}\n\nconst isEmpty = computed(() => editor.value?.isEmpty ?? true)\nconst inTable = computed(() => editor.value?.isActive('table') ?? false)\n\nconst classes = computed(() => [\n 'wx-rich-text',\n `wx-rich-text--${field.size.value}`,\n {\n [`wx-rich-text--${field.status.value}`]: field.status.value !== 'default',\n 'is-focused': focused.value,\n 'is-disabled': field.disabled.value,\n 'is-readonly': props.readonly,\n 'is-localized': locales.on.value,\n 'is-inline': props.inline,\n },\n])\n\n/** The caret follows the language into the document it just swapped in. */\nfunction chooseLocale(code: string): void {\n locales.active.value = code\n void nextTick(() => editor.value?.commands.focus())\n}\n\nfunction insertImage(image: RichTextImage, pos?: number) {\n const instance = editor.value\n if (!instance) return\n const at = pos ?? instance.state.selection.anchor\n instance\n .chain()\n .focus()\n .insertContentAt(at, {\n type: 'image',\n attrs: { src: image.url, alt: image.alt, path: image.path ?? null },\n })\n .run()\n}\n\n/**\n * Uploads happen one file at a time and insert only on success — a failed upload\n * leaves nothing behind to clean up.\n */\nasync function uploadFiles(files: File[], pos?: number) {\n if (!props.upload) return\n for (const file of files) {\n uploading.value += 1\n try {\n insertImage(await props.upload(file), pos)\n } catch (error) {\n emit('uploadError', error, file)\n } finally {\n uploading.value -= 1\n }\n }\n}\n\nasync function onImageButton() {\n if (props.pickImage) {\n const chosen = await props.pickImage()\n\n if (chosen) insertImage(typeof chosen === 'string' ? { url: chosen } : chosen)\n\n return\n }\n fileInput.value?.click()\n}\n\nfunction onFilePicked(event: Event) {\n const input = event.target as HTMLInputElement\n const files = Array.from(input.files ?? [])\n input.value = ''\n void uploadFiles(files)\n}\n\nfunction openPrompt(kind: 'link' | 'youtube') {\n const current = kind === 'link' ? (editor.value?.getAttributes('link').href ?? '') : ''\n prompt.value = { kind, value: String(current) }\n}\n\nfunction applyPrompt() {\n const instance = editor.value\n const current = prompt.value\n if (!instance || !current) return\n const value = current.value.trim()\n\n if (current.kind === 'link') {\n if (value) instance.chain().focus().extendMarkRange('link').setLink({ href: value }).run()\n else instance.chain().focus().extendMarkRange('link').unsetLink().run()\n } else if (value) {\n instance.commands.setYoutubeVideo({ src: value })\n }\n\n prompt.value = null\n}\n\nfunction openSource(html = readHtml()) {\n prompt.value = null\n losing.value = null\n opened = formatHtml(html)\n source.value = opened\n}\n\n/**\n * The source goes to the model as it is typed, not when the view closes: a form saved with the\n * source still open saves what is on screen. The server's allowlist still applies to it.\n */\nfunction onSourceInput(html: string) {\n source.value = html\n losing.value = null\n if (html === currentValue.value) return\n locales.write(editing.value, html)\n emit('change', html)\n}\n\n/**\n * Back to the editor, which parses the source against its schema. Markup the schema does not\n * know would vanish without a word, so when a hand edit is about to lose some the view stays\n * open and says what, until it is told to go ahead.\n */\nfunction closeSource(force = false) {\n const instance = editor.value\n const html = source.value\n if (!instance || html === null) return\n\n const edited = html !== opened\n\n if (edited && !force) {\n const parsed = createDocument(html, instance.schema)\n const lost = lostMarkup(html, getHTMLFromFragment(parsed.content, instance.schema))\n\n if (lost.length > 0) {\n losing.value = lost\n return\n }\n }\n\n losing.value = null\n source.value = null\n\n if (edited) instance.commands.setContent(html, { emitUpdate: false })\n\n // Written here rather than left to `onUpdate`: a source typed and typed back changes no node,\n // raises no update, and would leave the model holding the indented copy.\n const normalised = readHtml()\n if (normalised !== currentValue.value) {\n locales.write(editing.value, normalised)\n emit('change', normalised)\n }\n\n void nextTick(() => instance.commands.focus())\n}\n\nfunction onSourceFocus(on: boolean) {\n focused.value = on\n if (on) emit('focus')\n else emit('blur')\n}\n\nfunction toggleSource() {\n if (source.value === null) openSource()\n else closeSource()\n}\n\n/**\n * The source button stays usable on a read-only field — reading the markup is half of what it\n * is for — while every other button waits for the editor to come back.\n */\nfunction toolDisabled(tool: RichTextTool): boolean {\n if (tool === 'source') return field.disabled.value\n return !editable.value || source.value !== null\n}\n\n/** Whether a tool should render at all — the image button needs somewhere to get a file. */\nfunction toolVisible(tool: RichTextTool): boolean {\n if (tool === 'image') return Boolean(props.upload || props.pickImage)\n return true\n}\n\nconst visibleTools = computed(() => toolList.value.filter(toolVisible))\n\nfunction isActive(tool: RichTextTool): boolean {\n if (tool === 'source') return source.value !== null\n const instance = editor.value\n if (!instance) return false\n switch (tool) {\n case 'h2':\n return instance.isActive('heading', { level: 2 })\n case 'h3':\n return instance.isActive('heading', { level: 3 })\n case 'h4':\n return instance.isActive('heading', { level: 4 })\n default:\n return instance.isActive(tool)\n }\n}\n\nfunction run(tool: RichTextTool) {\n if (tool === 'source') return toggleSource()\n const instance = editor.value\n if (!instance) return\n const chain = instance.chain().focus()\n\n switch (tool) {\n case 'bold':\n chain.toggleBold().run()\n break\n case 'italic':\n chain.toggleItalic().run()\n break\n case 'accent':\n chain.toggleMark('accent').run()\n break\n case 'strike':\n chain.toggleStrike().run()\n break\n case 'code':\n chain.toggleCode().run()\n break\n case 'h2':\n chain.toggleHeading({ level: 2 }).run()\n break\n case 'h3':\n chain.toggleHeading({ level: 3 }).run()\n break\n case 'h4':\n chain.toggleHeading({ level: 4 }).run()\n break\n case 'bulletList':\n chain.toggleBulletList().run()\n break\n case 'orderedList':\n chain.toggleOrderedList().run()\n break\n case 'blockquote':\n chain.toggleBlockquote().run()\n break\n case 'hr':\n chain.setHorizontalRule().run()\n break\n case 'undo':\n chain.undo().run()\n break\n case 'redo':\n chain.redo().run()\n break\n case 'table':\n chain.insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()\n break\n case 'link':\n openPrompt('link')\n break\n case 'youtube':\n openPrompt('youtube')\n break\n case 'image':\n void onImageButton()\n break\n }\n}\n\nfunction runTableCommand(key: TableToolKey) {\n const instance = editor.value\n if (!instance) return\n const chain = instance.chain().focus() as unknown as Record<string, () => { run: () => void }>\n chain[key]().run()\n}\n\ndefineExpose({\n editor,\n focus: () => editor.value?.commands.focus(),\n clear: () => editor.value?.commands.clearContent(true),\n})\n</script>\n\n<template>\n <div ref=\"rootRef\" :class=\"classes\">\n <div class=\"wx-rich-text__toolbar\" role=\"toolbar\" :aria-label=\"ariaLabel ?? label('toolbar')\">\n <template v-for=\"(tool, index) in visibleTools\" :key=\"`${tool}-${index}`\">\n <span v-if=\"tool === 'divider'\" class=\"wx-rich-text__divider\" aria-hidden=\"true\" />\n <wx-rich-text-toolbar-button\n v-else\n :icon=\"TOOL_META[tool].icon\"\n :text=\"TOOL_META[tool].text\"\n :label=\"label(tool)\"\n :active=\"isActive(tool)\"\n :disabled=\"toolDisabled(tool)\"\n @click=\"run(tool)\"\n />\n </template>\n\n <wx-rich-text-toolbar-button\n v-if=\"hasTokens\"\n class=\"wx-rich-text__tokens\"\n icon=\"token\"\n :label=\"tokensLabel\"\n :active=\"tokens.open.value && tokens.browsing.value\"\n :disabled=\"!editable || source !== null\"\n @mousedown.prevent\n @click=\"browseTokens\"\n />\n\n <span v-if=\"uploading > 0\" class=\"wx-rich-text__uploading\">{{ label('uploading') }}</span>\n </div>\n\n <wx-token-menu\n v-if=\"hasTokens\"\n :open=\"tokens.open.value\"\n :items=\"tokens.items.value\"\n :active=\"tokens.active.value\"\n :anchor=\"tokens.anchor.value\"\n :list-id=\"tokenListId\"\n :title=\"tokens.browsing.value ? tokensTitle : undefined\"\n :owner=\"rootRef\"\n @choose=\"(token) => tokens.choose(token, insertToken)\"\n @hover=\"(index) => (tokens.active.value = index)\"\n @close=\"tokens.close()\"\n />\n\n <locale-picker\n v-if=\"locales.on.value\"\n :locales=\"locales.list.value\"\n :active=\"locales.active.value\"\n @choose=\"chooseLocale\"\n />\n\n <div\n v-if=\"inTable && editable && source === null\"\n class=\"wx-rich-text__toolbar wx-rich-text__toolbar--table\"\n >\n <wx-rich-text-toolbar-button\n v-for=\"tool in TABLE_TOOLS\"\n :key=\"tool.key\"\n :icon=\"tool.icon\"\n :label=\"label(tool.key)\"\n @click=\"runTableCommand(tool.key)\"\n />\n </div>\n\n <form v-if=\"prompt\" class=\"wx-rich-text__prompt\" @submit.prevent=\"applyPrompt\">\n <label class=\"wx-rich-text__prompt-label\" :for=\"`${field.id.value}-prompt`\">\n {{ label(prompt.kind === 'link' ? 'linkAddress' : 'youtubeAddress') }}\n </label>\n <input\n :id=\"`${field.id.value}-prompt`\"\n v-model=\"prompt.value\"\n class=\"wx-rich-text__prompt-input\"\n type=\"url\"\n :placeholder=\"prompt.kind === 'link' ? 'https://example.com' : 'https://youtu.be/…'\"\n @keydown.esc=\"prompt = null\"\n />\n <wx-rich-text-toolbar-button icon=\"check\" :label=\"label('apply')\" @click=\"applyPrompt\" />\n <wx-rich-text-toolbar-button icon=\"close\" :label=\"label('cancel')\" @click=\"prompt = null\" />\n </form>\n\n <div v-if=\"losing\" class=\"wx-rich-text__prompt wx-rich-text__loss\" role=\"alert\">\n <p class=\"wx-rich-text__loss-text\">\n {{ label('sourceLoss') }}\n <template v-for=\"(item, index) in losing\" :key=\"item\">\n <code>{{ item }}</code\n ><template v-if=\"index < losing.length - 1\">, </template>\n </template>\n </p>\n <wx-button size=\"sm\" type=\"danger\" variant=\"outline\" @click=\"closeSource(true)\">\n {{ label('sourceDrop') }}\n </wx-button>\n <wx-button size=\"sm\" variant=\"text\" @click=\"losing = null\">{{\n label('sourceKeep')\n }}</wx-button>\n </div>\n\n <div v-if=\"source !== null\" class=\"wx-rich-text__source\">\n <wx-code-editor\n :model-value=\"source\"\n language=\"html\"\n line-wrapping\n :min-height=\"bodyHeight\"\n :readonly=\"readonly\"\n :disabled=\"field.disabled.value\"\n :aria-label=\"label('source')\"\n @update:model-value=\"onSourceInput\"\n @focus=\"onSourceFocus(true)\"\n @blur=\"onSourceFocus(false)\"\n />\n </div>\n\n <!-- Hidden rather than unmounted: ProseMirror keeps its view, history and selection. -->\n <div v-show=\"source === null\" class=\"wx-rich-text__body\" :style=\"{ minHeight: bodyHeight }\">\n <span v-if=\"placeholder && isEmpty\" class=\"wx-rich-text__placeholder\">{{ placeholder }}</span>\n <editor-content\n :editor=\"editor\"\n class=\"wx-rich-text__content\"\n :aria-describedby=\"field.describedBy.value\"\n />\n </div>\n\n <input\n v-if=\"upload && !pickImage\"\n ref=\"fileInput\"\n class=\"wx-rich-text__file\"\n type=\"file\"\n :accept=\"accept.join(',')\"\n multiple\n @change=\"onFilePicked\"\n />\n </div>\n</template>\n\n<style scoped>\n.wx-rich-text {\n position: relative;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n width: 100%;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n color: var(--wx-text-default);\n transition: border-color var(--wx-duration-normal) var(--wx-easing-standard);\n}\n\n.wx-rich-text.is-focused {\n border-color: var(--wx-border-focus);\n}\n\n.wx-rich-text--error,\n.wx-rich-text--error.is-focused {\n border-color: var(--wx-color-danger);\n}\n\n.wx-rich-text--success {\n border-color: var(--wx-color-success);\n}\n\n.wx-rich-text--warning {\n border-color: var(--wx-color-warning);\n}\n\n/*\n * The chip sits in the top corner, over the end of the toolbar rather than over the text: a\n * document is written from the top left and that corner has to stay clear. The toolbar keeps\n * its distance so the last button is not underneath it.\n */\n.wx-rich-text.is-localized {\n --wx-locale-picker-height: 20px;\n --wx-locale-picker-top: var(--wx-space-4);\n --wx-locale-picker-shift: 0;\n}\n\n.wx-rich-text.is-localized .wx-rich-text__toolbar:first-child {\n padding-right: var(--wx-space-40);\n}\n\n.wx-rich-text.is-disabled {\n background: var(--wx-bg-disabled);\n color: var(--wx-text-disabled);\n}\n\n.wx-rich-text__toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-2);\n padding: var(--wx-space-6);\n border-bottom: 1px solid var(--wx-border-muted);\n}\n\n.wx-rich-text__toolbar--table {\n background: var(--wx-bg-subtle);\n}\n\n.wx-rich-text__divider {\n width: 1px;\n height: 18px;\n margin: 0 var(--wx-space-4);\n background: var(--wx-border-default);\n}\n\n.wx-rich-text__uploading {\n margin-left: auto;\n padding: 0 var(--wx-space-8);\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-rich-text__prompt {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8);\n background: var(--wx-bg-subtle);\n border-bottom: 1px solid var(--wx-border-muted);\n}\n\n.wx-rich-text__prompt-label {\n flex: 0 0 auto;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-rich-text__prompt-input {\n flex: 1 1 auto;\n min-width: 0;\n height: var(--wx-size-control-sm);\n padding: 0 var(--wx-space-10);\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-xs);\n outline: none;\n color: inherit;\n font-family: inherit;\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-rich-text__prompt-input:focus {\n border-color: var(--wx-border-focus);\n}\n\n.wx-rich-text__loss {\n flex-wrap: wrap;\n background: var(--wx-color-danger-soft);\n}\n\n.wx-rich-text__loss-text {\n flex: 1 1 240px;\n margin: 0;\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-rich-text__loss-text code {\n font-family: var(--wx-font-family-mono);\n white-space: nowrap;\n}\n\n/* The field draws the frame; the code editor inside it is only the surface. */\n.wx-rich-text__source {\n flex: 1 1 auto;\n}\n\n.wx-rich-text__source :deep(.wx-code-editor) {\n border: 0;\n border-radius: 0 0 var(--wx-radius-control) var(--wx-radius-control);\n}\n\n.wx-rich-text__body {\n position: relative;\n flex: 1 1 auto;\n padding: var(--wx-space-12) var(--wx-space-16);\n}\n\n.wx-rich-text__placeholder {\n position: absolute;\n top: var(--wx-space-12);\n left: var(--wx-space-16);\n color: var(--wx-text-placeholder);\n pointer-events: none;\n}\n\n/*\n * A line: the toolbar shrinks to a strip of three buttons and the text sits where an input's\n * would, so a form mixing the two does not jump between them.\n */\n.wx-rich-text.is-inline .wx-rich-text__toolbar {\n padding: var(--wx-space-2) var(--wx-space-4);\n}\n\n.wx-rich-text.is-inline .wx-rich-text__body {\n padding: var(--wx-space-6) var(--wx-space-12);\n}\n\n.wx-rich-text.is-inline .wx-rich-text__placeholder {\n top: var(--wx-space-6);\n left: var(--wx-space-12);\n}\n\n/* The accent shows as one: the editor sees which words a site will colour. */\n.wx-rich-text.is-inline .wx-rich-text__content :deep(span) {\n color: var(--wx-color-primary);\n}\n\n.wx-rich-text__file {\n display: none;\n}\n\n/* The editing surface itself is rendered by ProseMirror. */\n.wx-rich-text__content :deep(.ProseMirror) {\n outline: none;\n min-height: inherit;\n line-height: var(--wx-font-line-height-relaxed);\n}\n\n/*\n * Host applications decorate content tags globally — VitePress, which renders these\n * docs, gives every h2 a top border and 24px of padding, and turns tables into\n * `display: block`. The editing surface has to look the same wherever it is\n * embedded, so anything a host is likely to set is stated here instead of inherited.\n */\n.wx-rich-text__content :deep(h1),\n.wx-rich-text__content :deep(h2),\n.wx-rich-text__content :deep(h3),\n.wx-rich-text__content :deep(h4),\n.wx-rich-text__content :deep(h5),\n.wx-rich-text__content :deep(h6) {\n margin: var(--wx-space-18) 0 var(--wx-space-8);\n padding: 0;\n border: 0;\n color: var(--wx-text-strong);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n.wx-rich-text__content :deep(p) {\n margin: 0 0 var(--wx-space-12);\n}\n\n/* Nothing pushes the document away from the top or bottom edge of the field. */\n.wx-rich-text__content :deep(.ProseMirror > :first-child) {\n margin-top: 0;\n}\n\n.wx-rich-text__content :deep(.ProseMirror > :last-child) {\n margin-bottom: 0;\n}\n\n.wx-rich-text__content :deep(h2) {\n font-size: var(--wx-font-size-2xl);\n}\n\n.wx-rich-text__content :deep(h3) {\n font-size: var(--wx-font-size-xl);\n}\n\n.wx-rich-text__content :deep(h4) {\n font-size: var(--wx-font-size-lg);\n}\n\n.wx-rich-text__content :deep(ul),\n.wx-rich-text__content :deep(ol) {\n margin: 0 0 var(--wx-space-12);\n padding-left: var(--wx-space-24);\n}\n\n.wx-rich-text__content :deep(blockquote) {\n margin: 0 0 var(--wx-space-12);\n padding-left: var(--wx-space-16);\n border-left: 3px solid var(--wx-color-primary-soft);\n color: var(--wx-text-muted);\n}\n\n.wx-rich-text__content :deep(a) {\n color: var(--wx-text-link);\n text-decoration: underline;\n}\n\n.wx-rich-text__content :deep(code) {\n padding: 2px var(--wx-space-4);\n background: var(--wx-bg-fill);\n border-radius: var(--wx-radius-xs);\n font-family: var(--wx-font-family-mono);\n font-size: 0.9em;\n}\n\n.wx-rich-text__content :deep(pre) {\n margin: 0 0 var(--wx-space-12);\n padding: var(--wx-space-12);\n background: var(--wx-bg-inverse);\n border-radius: var(--wx-radius-xs);\n color: var(--wx-text-inverse);\n overflow-x: auto;\n}\n\n.wx-rich-text__content :deep(hr) {\n margin: var(--wx-space-18) 0;\n border: none;\n border-top: 1px solid var(--wx-border-default);\n}\n\n.wx-rich-text__content :deep(img),\n.wx-rich-text__content :deep(iframe) {\n max-width: 100%;\n border-radius: var(--wx-radius-xs);\n}\n\n.wx-rich-text__content :deep(img.ProseMirror-selectednode) {\n outline: 2px solid var(--wx-color-primary);\n}\n\n.wx-rich-text__content :deep(table) {\n /* Stated because hosts turn tables into `display: block` for horizontal scrolling. */\n display: table;\n width: 100%;\n margin: 0 0 var(--wx-space-12);\n border-collapse: collapse;\n table-layout: fixed;\n overflow: hidden;\n}\n\n.wx-rich-text__content :deep(th),\n.wx-rich-text__content :deep(td) {\n position: relative;\n padding: var(--wx-space-6) var(--wx-space-10);\n border: 1px solid var(--wx-border-default);\n vertical-align: top;\n}\n\n.wx-rich-text__content :deep(th) {\n background: var(--wx-bg-fill);\n font-weight: var(--wx-font-weight-semibold);\n text-align: left;\n}\n\n.wx-rich-text__content :deep(.selectedCell::after) {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--wx-color-primary-soft);\n pointer-events: none;\n}\n\n.wx-rich-text__content :deep(.column-resize-handle) {\n position: absolute;\n top: 0;\n right: -2px;\n bottom: 0;\n width: 4px;\n background: var(--wx-color-primary);\n cursor: col-resize;\n}\n</style>\n"],"names":["richTextIcons","_createElementBlock","_normalizeClass","__props","$emit","_openBlock","_hoisted_2","_createElementVNode","_unref","_hoisted_4","_toDisplayString","CONTAINERS","LINES","VOID","TAG","formatHtml","html","indent","out","depth","inLine","inPre","last","breakLine","match","token","closing","rawName","selfClosing","name","free","isVoid","SPELLINGS","census","counts","add","key","template","element","tag","attribute","lostMarkup","before","after","had","kept","lost","count","droppedTags","on","DEFAULT_TOOLS","INLINE_TOOLS","DEFAULT_ACCEPT","TOOL_META","TABLE_TOOLS","props","DEFAULT_LABELS","label","given","tool","emit","__emit","LibraryImage","Image","attributes","Accent","Mark","LineDocument","Node","OneLine","Extension","tokens","useTokenMenu","hasTokens","computed","tokenChipsKey","PluginKey","TokenChips","Plugin","state","known","DecorationSet","chips","node","pos","span","tokenSpans","Decoration","inlineExtensions","StarterKit","documentExtensions","TableKit","Youtube","FileHandler","_editor","files","uploadFiles","toolList","bodyHeight","model","_useModel","field","useFormField","locales","useLocalized","editing","currentValue","focused","ref","uploading","fileInput","prompt","editable","source","losing","opened","readHtml","instance","editor","useEditor","_view","event","insertToken","text","suggestTokens","watch","value","openSource","rootRef","tokenListId","caretAnchor","at","tokenAnchor","rectOf","fieldAnchor","selection","$from","tr","tokenText","browseTokens","from","to","isEmpty","inTable","classes","chooseLocale","code","nextTick","insertImage","image","file","error","onImageButton","chosen","onFilePicked","input","openPrompt","kind","current","applyPrompt","onSourceInput","closeSource","force","edited","parsed","createDocument","getHTMLFromFragment","normalised","onSourceFocus","toggleSource","toolDisabled","toolVisible","visibleTools","isActive","run","chain","runTableCommand","__expose","_Fragment","_renderList","index","_createBlock","WxRichTextToolbarButton","$event","_hoisted_3","WxTokenMenu","_cache","LocalePicker","_hoisted_5","_vModelText","_createVNode","_hoisted_7","_hoisted_8","_createTextVNode","item","WxButton","_hoisted_9","WxCodeEditor","_hoisted_10","EditorContent"],"mappings":"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"}
|
|
@@ -1,4 +1,48 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const WxCodeEditor: (<T extends import('./types').CodeEditorModelValue = string>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
|
|
2
|
+
attrs: any;
|
|
3
|
+
emit: (((evt: "change", value: string) => void) & ((evt: "blur") => void) & ((evt: "focus") => void) & ((evt: "lint", diagnostics: import('./types').CodeEditorDiagnostic[]) => void)) & ((evt: "update:modelValue", value: T) => void);
|
|
4
|
+
slots: {};
|
|
5
|
+
}, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
6
|
+
props: {
|
|
7
|
+
readonly onChange?: ((value: string) => any) | undefined;
|
|
8
|
+
readonly "onUpdate:modelValue"?: ((value: T) => any) | undefined;
|
|
9
|
+
readonly onFocus?: (() => any) | undefined;
|
|
10
|
+
readonly onBlur?: (() => any) | undefined;
|
|
11
|
+
readonly onLint?: ((diagnostics: import('./types').CodeEditorDiagnostic[]) => any) | undefined;
|
|
12
|
+
modelValue?: T | undefined;
|
|
13
|
+
language?: import('./types').CodeEditorLanguage | undefined;
|
|
14
|
+
placeholder?: string | undefined;
|
|
15
|
+
disabled?: boolean | undefined;
|
|
16
|
+
readonly?: boolean | undefined;
|
|
17
|
+
size?: import('../..').ControlSize | undefined;
|
|
18
|
+
status?: import('../..').ControlStatus | undefined;
|
|
19
|
+
id?: string | undefined;
|
|
20
|
+
ariaLabel?: string | undefined;
|
|
21
|
+
minHeight?: string | undefined;
|
|
22
|
+
maxHeight?: string | undefined;
|
|
23
|
+
lineNumbers?: boolean | undefined;
|
|
24
|
+
lineWrapping?: boolean | undefined;
|
|
25
|
+
tabSize?: number | undefined;
|
|
26
|
+
lint?: boolean | undefined;
|
|
27
|
+
completions?: import('./types').CodeEditorCompletions | undefined;
|
|
28
|
+
languageCompletions?: boolean | undefined;
|
|
29
|
+
localized?: boolean | undefined;
|
|
30
|
+
singleLine?: boolean | undefined;
|
|
31
|
+
extensions?: import('@codemirror/state').Extension[] | undefined;
|
|
32
|
+
} & import('vue').PublicProps;
|
|
33
|
+
expose(exposed: import('vue').ShallowUnwrapRef<{
|
|
34
|
+
view: import('vue').ShallowRef<import('@codemirror/view').EditorView | null, import('@codemirror/view').EditorView | null>;
|
|
35
|
+
focus: () => void | undefined;
|
|
36
|
+
format: () => boolean;
|
|
37
|
+
}>): void;
|
|
38
|
+
attrs: any;
|
|
39
|
+
slots: {};
|
|
40
|
+
emit: (((evt: "change", value: string) => void) & ((evt: "blur") => void) & ((evt: "focus") => void) & ((evt: "lint", diagnostics: import('./types').CodeEditorDiagnostic[]) => void)) & ((evt: "update:modelValue", value: T) => void);
|
|
41
|
+
}>) => import('vue').VNode & {
|
|
42
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
43
|
+
}) & {
|
|
44
|
+
name: string;
|
|
45
|
+
};
|
|
2
46
|
export type * from './types';
|
|
3
47
|
export { mustacheCompletions, mustacheHighlighting, mustacheProblems, scanMustache, } from './mustache';
|
|
4
48
|
export type { MustacheProblems, MustacheTag, MustacheTagKind } from './mustache';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Extension } from '@codemirror/state';
|
|
2
|
+
/**
|
|
3
|
+
* What the language itself suggests: HTML tags, attributes and their values with the tag closed on
|
|
4
|
+
* `>`, and the JavaScript and CSS nested in it. Each language ships its own source; this switches
|
|
5
|
+
* the list on, adds the globals of the page after a dot — the same `window`, `document` and
|
|
6
|
+
* `console` the code meets on the site — and mends the end of the document.
|
|
7
|
+
*/
|
|
8
|
+
export declare function languageCompletions(): Extension;
|
|
@@ -111,11 +111,24 @@ export interface CodeEditorProps {
|
|
|
111
111
|
* and the caret — `mustacheCompletions(variables)` for a Mustache template.
|
|
112
112
|
*/
|
|
113
113
|
completions?: CodeEditorCompletions;
|
|
114
|
+
/**
|
|
115
|
+
* Suggestions the language knows by itself while typing: HTML tags, attributes and their values
|
|
116
|
+
* with the tag closed on `>`, keywords, snippets, the code's own names and globals after a dot
|
|
117
|
+
* in JavaScript, properties and values in CSS — nested in HTML too. Ignored when `completions`
|
|
118
|
+
* is given: those replace it.
|
|
119
|
+
*/
|
|
120
|
+
languageCompletions?: boolean;
|
|
114
121
|
/**
|
|
115
122
|
* Edits the document in every language the site publishes in, with a selector on the field;
|
|
116
123
|
* the model is then `{ en: '…', uk: '…' }`.
|
|
117
124
|
*/
|
|
118
125
|
localized?: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* One line, as tall as an input: Enter takes a suggestion and inserts no line break, a pasted
|
|
128
|
+
* line break becomes a space, Tab moves on to the next field. For a template of one line — the
|
|
129
|
+
* subject of a letter — that still wants highlighting and `completions`.
|
|
130
|
+
*/
|
|
131
|
+
singleLine?: boolean;
|
|
119
132
|
/** Extra CodeMirror extensions, for anything this component does not wrap. */
|
|
120
133
|
extensions?: Extension[];
|
|
121
134
|
}
|
|
@@ -96,9 +96,9 @@ declare function __VLS_template(): {
|
|
|
96
96
|
clearable: boolean;
|
|
97
97
|
status: import('..').InputStatus;
|
|
98
98
|
id: string;
|
|
99
|
+
autocomplete: string;
|
|
99
100
|
readonly: boolean;
|
|
100
101
|
localized: boolean;
|
|
101
|
-
autocomplete: string;
|
|
102
102
|
maxlength: number;
|
|
103
103
|
showCount: boolean;
|
|
104
104
|
tokens: import('../..').TokenOption[];
|
|
@@ -133,9 +133,9 @@ declare function __VLS_template(): {
|
|
|
133
133
|
clearable: boolean;
|
|
134
134
|
status: import('..').InputStatus;
|
|
135
135
|
id: string;
|
|
136
|
+
autocomplete: string;
|
|
136
137
|
readonly: boolean;
|
|
137
138
|
localized: boolean;
|
|
138
|
-
autocomplete: string;
|
|
139
139
|
maxlength: number;
|
|
140
140
|
showCount: boolean;
|
|
141
141
|
tokens: import('../..').TokenOption[];
|
|
@@ -150,7 +150,7 @@ declare function __VLS_template(): {
|
|
|
150
150
|
onClear?: (() => any) | undefined;
|
|
151
151
|
onBlur?: ((event: FocusEvent) => any) | undefined;
|
|
152
152
|
onFocus?: ((event: FocusEvent) => any) | undefined;
|
|
153
|
-
}>, "input" | "select" | "blur" | "focus" | ("size" | "disabled" | "type" | "placeholder" | "ariaLabel" | "clearable" | "status" | "id" | "
|
|
153
|
+
}>, "input" | "select" | "blur" | "focus" | ("size" | "disabled" | "type" | "placeholder" | "ariaLabel" | "clearable" | "status" | "id" | "autocomplete" | "readonly" | "localized" | "maxlength" | "showCount" | "tokens" | "tokensTitle" | "tokensLabel")> & {
|
|
154
154
|
focus: () => void | undefined;
|
|
155
155
|
blur: () => void | undefined;
|
|
156
156
|
select: () => void | undefined;
|
|
@@ -285,9 +285,9 @@ declare const __VLS_component: import('vue').DefineComponent<FileCardProps, {},
|
|
|
285
285
|
clearable: boolean;
|
|
286
286
|
status: import('..').InputStatus;
|
|
287
287
|
id: string;
|
|
288
|
+
autocomplete: string;
|
|
288
289
|
readonly: boolean;
|
|
289
290
|
localized: boolean;
|
|
290
|
-
autocomplete: string;
|
|
291
291
|
maxlength: number;
|
|
292
292
|
showCount: boolean;
|
|
293
293
|
tokens: import('../..').TokenOption[];
|
|
@@ -322,9 +322,9 @@ declare const __VLS_component: import('vue').DefineComponent<FileCardProps, {},
|
|
|
322
322
|
clearable: boolean;
|
|
323
323
|
status: import('..').InputStatus;
|
|
324
324
|
id: string;
|
|
325
|
+
autocomplete: string;
|
|
325
326
|
readonly: boolean;
|
|
326
327
|
localized: boolean;
|
|
327
|
-
autocomplete: string;
|
|
328
328
|
maxlength: number;
|
|
329
329
|
showCount: boolean;
|
|
330
330
|
tokens: import('../..').TokenOption[];
|
|
@@ -339,7 +339,7 @@ declare const __VLS_component: import('vue').DefineComponent<FileCardProps, {},
|
|
|
339
339
|
onClear?: (() => any) | undefined;
|
|
340
340
|
onBlur?: ((event: FocusEvent) => any) | undefined;
|
|
341
341
|
onFocus?: ((event: FocusEvent) => any) | undefined;
|
|
342
|
-
}>, "input" | "select" | "blur" | "focus" | ("size" | "disabled" | "type" | "placeholder" | "ariaLabel" | "clearable" | "status" | "id" | "
|
|
342
|
+
}>, "input" | "select" | "blur" | "focus" | ("size" | "disabled" | "type" | "placeholder" | "ariaLabel" | "clearable" | "status" | "id" | "autocomplete" | "readonly" | "localized" | "maxlength" | "showCount" | "tokens" | "tokensTitle" | "tokensLabel")> & {
|
|
343
343
|
focus: () => void | undefined;
|
|
344
344
|
blur: () => void | undefined;
|
|
345
345
|
select: () => void | undefined;
|
|
@@ -46,9 +46,9 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_PublicProps,
|
|
|
46
46
|
clearable: boolean;
|
|
47
47
|
status: import('./types').InputStatus;
|
|
48
48
|
id: string;
|
|
49
|
+
autocomplete: string;
|
|
49
50
|
readonly: boolean;
|
|
50
51
|
localized: boolean;
|
|
51
|
-
autocomplete: string;
|
|
52
52
|
maxlength: number;
|
|
53
53
|
showCount: boolean;
|
|
54
54
|
tokens: TokenOption[];
|
|
@@ -1,2 +1,124 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const WxRichText: {
|
|
2
|
+
new (...args: any[]): import('vue').CreateComponentPublicInstanceWithMixins<Readonly<{
|
|
3
|
+
modelValue?: import('./types').RichTextModelValue;
|
|
4
|
+
} & import('./types').RichTextProps> & Readonly<{
|
|
5
|
+
onChange?: ((html: string) => any) | undefined;
|
|
6
|
+
"onUpdate:modelValue"?: ((value: import('./types').RichTextModelValue) => any) | undefined;
|
|
7
|
+
onBlur?: (() => any) | undefined;
|
|
8
|
+
onFocus?: (() => any) | undefined;
|
|
9
|
+
onUploadError?: ((error: unknown, file: File) => any) | undefined;
|
|
10
|
+
}>, {
|
|
11
|
+
editor: import('vue').ShallowRef<import('@tiptap/vue-3').Editor | undefined, import('@tiptap/vue-3').Editor | undefined>;
|
|
12
|
+
focus: () => boolean | undefined;
|
|
13
|
+
clear: () => boolean | undefined;
|
|
14
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
15
|
+
change: (html: string) => any;
|
|
16
|
+
"update:modelValue": (value: import('./types').RichTextModelValue) => any;
|
|
17
|
+
blur: () => any;
|
|
18
|
+
focus: () => any;
|
|
19
|
+
uploadError: (error: unknown, file: File) => any;
|
|
20
|
+
}, import('vue').PublicProps, {
|
|
21
|
+
size: import('../..').ControlSize;
|
|
22
|
+
disabled: boolean;
|
|
23
|
+
placeholder: string;
|
|
24
|
+
upload: import('./types').RichTextUpload;
|
|
25
|
+
ariaLabel: string;
|
|
26
|
+
status: import('../..').ControlStatus;
|
|
27
|
+
id: string;
|
|
28
|
+
inline: boolean;
|
|
29
|
+
readonly: boolean;
|
|
30
|
+
minHeight: string;
|
|
31
|
+
localized: boolean;
|
|
32
|
+
tokens: import('../..').TokenOption[];
|
|
33
|
+
tokensTitle: string;
|
|
34
|
+
tokensLabel: string;
|
|
35
|
+
tools: import('./types').RichTextTool[];
|
|
36
|
+
pickImage: import('./types').RichTextImagePicker;
|
|
37
|
+
accept: string[];
|
|
38
|
+
labels: import('./types').RichTextLabels;
|
|
39
|
+
}, false, {}, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, {
|
|
40
|
+
rootRef: HTMLDivElement;
|
|
41
|
+
fileInput: HTMLInputElement;
|
|
42
|
+
}, any, import('vue').ComponentProvideOptions, {
|
|
43
|
+
P: {};
|
|
44
|
+
B: {};
|
|
45
|
+
D: {};
|
|
46
|
+
C: {};
|
|
47
|
+
M: {};
|
|
48
|
+
Defaults: {};
|
|
49
|
+
}, Readonly<{
|
|
50
|
+
modelValue?: import('./types').RichTextModelValue;
|
|
51
|
+
} & import('./types').RichTextProps> & Readonly<{
|
|
52
|
+
onChange?: ((html: string) => any) | undefined;
|
|
53
|
+
"onUpdate:modelValue"?: ((value: import('./types').RichTextModelValue) => any) | undefined;
|
|
54
|
+
onBlur?: (() => any) | undefined;
|
|
55
|
+
onFocus?: (() => any) | undefined;
|
|
56
|
+
onUploadError?: ((error: unknown, file: File) => any) | undefined;
|
|
57
|
+
}>, {
|
|
58
|
+
editor: import('vue').ShallowRef<import('@tiptap/vue-3').Editor | undefined, import('@tiptap/vue-3').Editor | undefined>;
|
|
59
|
+
focus: () => boolean | undefined;
|
|
60
|
+
clear: () => boolean | undefined;
|
|
61
|
+
}, {}, {}, {}, {
|
|
62
|
+
size: import('../..').ControlSize;
|
|
63
|
+
disabled: boolean;
|
|
64
|
+
placeholder: string;
|
|
65
|
+
upload: import('./types').RichTextUpload;
|
|
66
|
+
ariaLabel: string;
|
|
67
|
+
status: import('../..').ControlStatus;
|
|
68
|
+
id: string;
|
|
69
|
+
inline: boolean;
|
|
70
|
+
readonly: boolean;
|
|
71
|
+
minHeight: string;
|
|
72
|
+
localized: boolean;
|
|
73
|
+
tokens: import('../..').TokenOption[];
|
|
74
|
+
tokensTitle: string;
|
|
75
|
+
tokensLabel: string;
|
|
76
|
+
tools: import('./types').RichTextTool[];
|
|
77
|
+
pickImage: import('./types').RichTextImagePicker;
|
|
78
|
+
accept: string[];
|
|
79
|
+
labels: import('./types').RichTextLabels;
|
|
80
|
+
}>;
|
|
81
|
+
__isFragment?: never;
|
|
82
|
+
__isTeleport?: never;
|
|
83
|
+
__isSuspense?: never;
|
|
84
|
+
} & import('vue').ComponentOptionsBase<Readonly<{
|
|
85
|
+
modelValue?: import('./types').RichTextModelValue;
|
|
86
|
+
} & import('./types').RichTextProps> & Readonly<{
|
|
87
|
+
onChange?: ((html: string) => any) | undefined;
|
|
88
|
+
"onUpdate:modelValue"?: ((value: import('./types').RichTextModelValue) => any) | undefined;
|
|
89
|
+
onBlur?: (() => any) | undefined;
|
|
90
|
+
onFocus?: (() => any) | undefined;
|
|
91
|
+
onUploadError?: ((error: unknown, file: File) => any) | undefined;
|
|
92
|
+
}>, {
|
|
93
|
+
editor: import('vue').ShallowRef<import('@tiptap/vue-3').Editor | undefined, import('@tiptap/vue-3').Editor | undefined>;
|
|
94
|
+
focus: () => boolean | undefined;
|
|
95
|
+
clear: () => boolean | undefined;
|
|
96
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
97
|
+
change: (html: string) => any;
|
|
98
|
+
"update:modelValue": (value: import('./types').RichTextModelValue) => any;
|
|
99
|
+
blur: () => any;
|
|
100
|
+
focus: () => any;
|
|
101
|
+
uploadError: (error: unknown, file: File) => any;
|
|
102
|
+
}, string, {
|
|
103
|
+
size: import('../..').ControlSize;
|
|
104
|
+
disabled: boolean;
|
|
105
|
+
placeholder: string;
|
|
106
|
+
upload: import('./types').RichTextUpload;
|
|
107
|
+
ariaLabel: string;
|
|
108
|
+
status: import('../..').ControlStatus;
|
|
109
|
+
id: string;
|
|
110
|
+
inline: boolean;
|
|
111
|
+
readonly: boolean;
|
|
112
|
+
minHeight: string;
|
|
113
|
+
localized: boolean;
|
|
114
|
+
tokens: import('../..').TokenOption[];
|
|
115
|
+
tokensTitle: string;
|
|
116
|
+
tokensLabel: string;
|
|
117
|
+
tools: import('./types').RichTextTool[];
|
|
118
|
+
pickImage: import('./types').RichTextImagePicker;
|
|
119
|
+
accept: string[];
|
|
120
|
+
labels: import('./types').RichTextLabels;
|
|
121
|
+
}, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps & {
|
|
122
|
+
name: string;
|
|
123
|
+
};
|
|
2
124
|
export type * from './types';
|