quoin-editor 0.3.0 → 0.4.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.
- package/README.md +42 -8
- package/dist/headless.cjs +21 -11
- package/dist/headless.cjs.map +1 -1
- package/dist/headless.d.cts +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +21 -11
- package/dist/headless.js.map +1 -1
- package/dist/index.cjs +301 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -18
- package/dist/index.d.ts +35 -18
- package/dist/index.js +303 -174
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +23 -6
package/dist/headless.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/markdown/edit.ts","../src/markdown/line-at.ts","../src/markdown/line-toggles.ts","../src/markdown/list-continuation.ts","../src/markdown/indent-list.ts","../src/markdown/wrap-selection.ts","../src/markdown/insert-command.ts","../src/markdown/slash-trigger.ts","../src/markdown/shortcut-label.ts","../src/markdown/caret-coordinates.ts","../src/markdown/useMarkdownKeymap.ts","../src/hooks/useAutoGrow.ts"],"sourcesContent":["/** A text transform result: the next value and where the selection should land. */\nexport type Edit = { value: string; selectionStart: number; selectionEnd: number };\n\nfunction changedSpan(before: string, after: string) {\n let start = 0;\n const shortest = Math.min(before.length, after.length);\n while (start < shortest && before[start] === after[start]) start += 1;\n\n let endBefore = before.length;\n let endAfter = after.length;\n while (endBefore > start && endAfter > start && before[endBefore - 1] === after[endAfter - 1]) {\n endBefore -= 1;\n endAfter -= 1;\n }\n\n return { start, endBefore, replacement: after.slice(start, endAfter) };\n}\n\n// Writing through execCommand keeps the transform as one entry on the browser's\n// own undo stack. Either path commits el.value rather than the edit's intended\n// value: a browser is trusted to write what it was asked, and if it ever\n// wrote something else, committing our own intent instead would silently\n// diverge React's state from the DOM.\nfunction writeNatively(el: HTMLTextAreaElement, replacement: string): boolean {\n if (typeof document.execCommand !== 'function') return false;\n try {\n return replacement === ''\n ? document.execCommand('delete')\n : document.execCommand('insertText', false, replacement);\n } catch {\n return false;\n }\n}\n\n/** Applies an edit to a textarea through the native undo stack when the browser allows it, so Ctrl+Z still works. */\nexport function applyEdit(\n el: HTMLTextAreaElement,\n edit: Edit,\n commit: (value: string) => void,\n): void {\n if (el.value !== edit.value) {\n const { start, endBefore, replacement } = changedSpan(el.value, edit.value);\n el.setSelectionRange(start, endBefore);\n if (!writeNatively(el, replacement)) {\n el.value = edit.value;\n }\n commit(el.value);\n }\n el.setSelectionRange(edit.selectionStart, edit.selectionEnd);\n}\n","const FENCE = /^ {0,3}(```|~~~)/;\n\nexport type Line = { start: number; end: number; text: string };\n\n/** The line containing the offset, with its start and end offsets and its text (no trailing newline). */\nexport function lineAt(value: string, offset: number): Line {\n const start = value.lastIndexOf('\\n', offset - 1) + 1;\n const next = value.indexOf('\\n', offset);\n const end = next === -1 ? value.length : next;\n return { start, end, text: value.slice(start, end) };\n}\n\nexport function isFenceDelimiter(text: string): boolean {\n return FENCE.test(text);\n}\n\nexport function insideFence(value: string, offset: number): boolean {\n const lines = value.slice(0, offset).split('\\n');\n if (isFenceDelimiter(lines[lines.length - 1])) return true;\n\n let open = false;\n for (let i = 0; i < lines.length - 1; i += 1) {\n if (isFenceDelimiter(lines[i])) open = !open;\n }\n return open;\n}\n","import type { Edit } from './edit';\nimport { insideFence, isFenceDelimiter, lineAt } from './line-at';\n\n/** A line-level markdown prefix: a heading level, a bullet or a numbered item. */\nexport type LinePrefix = 'h1' | 'h2' | 'h3' | 'bullet' | 'ordered';\n\nconst EXISTING = /^(\\s*)(?:#{1,6} |[-*+] \\[[ xX]\\] |[-*+] |\\d+[.)] )?/;\n\nconst PREFIX: Record<LinePrefix, (index: number) => string> = {\n h1: () => '# ',\n h2: () => '## ',\n h3: () => '### ',\n bullet: () => '- ',\n ordered: (index) => `${index + 1}. `,\n};\n\nconst CARRIES: Record<LinePrefix, RegExp> = {\n h1: /^\\s*# /,\n h2: /^\\s*## /,\n h3: /^\\s*### /,\n bullet: /^\\s*[-*+] /,\n ordered: /^\\s*\\d+[.)] /,\n};\n\n/** Adds the prefix to every line in the selection, or removes it when every line already carries it; fenced code is left alone. */\nexport function toggleLinePrefix(\n kind: LinePrefix,\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): Edit {\n const first = lineAt(value, selectionStart);\n const last = lineAt(value, selectionEnd);\n const block = value.slice(first.start, last.end);\n const lines = block.split('\\n');\n\n let offset = first.start;\n const eligible = lines.map((text) => {\n const at = offset;\n offset += text.length + 1;\n return !insideFence(value, at) && !isFenceDelimiter(text);\n });\n\n const carried = lines.every((text, i) => !eligible[i] || CARRIES[kind].test(text));\n\n const rewritten = lines.map((text, i) => {\n if (!eligible[i]) return text;\n const match = EXISTING.exec(text);\n const indent = match?.[1] ?? '';\n const body = text.slice(match?.[0].length ?? 0);\n return carried ? indent + body : indent + PREFIX[kind](i) + body;\n });\n\n const joined = rewritten.join('\\n');\n const next = value.slice(0, first.start) + joined + value.slice(last.end);\n\n if (selectionStart !== selectionEnd) {\n return { value: next, selectionStart: first.start, selectionEnd: first.start + joined.length };\n }\n\n const caret = Math.max(first.start, selectionStart + (rewritten[0].length - lines[0].length));\n return { value: next, selectionStart: caret, selectionEnd: caret };\n}\n","import type { Edit } from './edit';\nimport { insideFence, lineAt, type Line } from './line-at';\n\nexport const LIST_MARKER = /^(\\s*)((?:[-*+] \\[[ xX]\\] )|(?:[-*+] )|(?:\\d+[.)] )|(?:> ))(.*)$/;\n\nconst INDENT = ' ';\n\nfunction nextMarker(marker: string): string {\n const ordered = /^(\\d+)([.)] )$/.exec(marker);\n if (ordered) return `${Number(ordered[1]) + 1}${ordered[2]}`;\n const task = /^([-*+]) \\[[ xX]\\] $/.exec(marker);\n if (task) return `${task[1]} [ ] `;\n return marker;\n}\n\n// Both the dead item on Enter and the caret at the content start on Backspace\n// mean the same thing: climb out one level, or drop the marker at the top.\nfunction climbOut(value: string, line: Line, indent: string, marker: string, content: string): Edit {\n const outdent = indent.length >= INDENT.length;\n\n if (outdent) {\n const text = indent.slice(INDENT.length) + marker + content;\n const at = line.start + indent.length - INDENT.length + marker.length;\n return {\n value: value.slice(0, line.start) + text + value.slice(line.end),\n selectionStart: at,\n selectionEnd: at,\n };\n }\n\n // A stripped marker with only a single newline above it reads to CommonMark\n // as a lazy continuation of the previous list item's paragraph, not a new\n // block, so a blank line is needed whenever that previous line is a list item.\n const leavesList = line.start > 0 && LIST_MARKER.test(lineAt(value, line.start - 1).text);\n const text = leavesList ? `\\n${content}` : content;\n const at = leavesList ? line.start + 1 : line.start;\n\n return {\n value: value.slice(0, line.start) + text + value.slice(line.end),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n\n/** Continues a list item on Enter, or climbs out of the list on an empty item or Backspace at the marker; returns null when the caret is not in a list item or is inside a code fence, so the default key behaviour runs. */\nexport function continueList(\n value: string,\n caret: number,\n key: 'Enter' | 'Backspace',\n): Edit | null {\n if (insideFence(value, caret)) return null;\n\n const line = lineAt(value, caret);\n const match = LIST_MARKER.exec(line.text);\n if (!match) return null;\n\n const [, indent, marker, content] = match;\n\n if (key === 'Backspace') {\n if (caret !== line.start + indent.length + marker.length) return null;\n return climbOut(value, line, indent, marker, content);\n }\n\n if (content.trim() === '') return climbOut(value, line, indent, marker, content);\n\n const inserted = `\\n${indent}${nextMarker(marker)}`;\n const at = caret + inserted.length;\n return {\n value: value.slice(0, caret) + inserted + value.slice(caret),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n","import type { Edit } from './edit';\nimport { insideFence, lineAt } from './line-at';\nimport { LIST_MARKER } from './list-continuation';\n\nconst INDENT = ' ';\n\nfunction indentOf(text: string): number {\n return /^\\s*/.exec(text)?.[0].length ?? 0;\n}\n\n// Indenting more than one level past the line above turns a list item into an\n// indented code block, so the first line of the range is capped against it.\nfunction shift(text: string, direction: 1 | -1, cap: number | undefined): string {\n const current = indentOf(text);\n if (direction === -1) return text.slice(Math.min(current, INDENT.length));\n if (cap !== undefined && current >= cap + INDENT.length) return text;\n return INDENT + text;\n}\n\n/** Indents or outdents the selected list items; returns null when the selection is not entirely list items, is inside a code fence, or cannot move further, so Tab keeps its default behaviour. */\nexport function indentList(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n direction: 1 | -1,\n): Edit | null {\n if (insideFence(value, selectionStart)) return null;\n\n const first = lineAt(value, selectionStart);\n const last = lineAt(value, selectionEnd);\n const block = value.slice(first.start, last.end);\n const lines = block.split('\\n');\n if (!lines.every((text) => LIST_MARKER.test(text))) return null;\n\n const cap = first.start === 0 ? 0 : indentOf(lineAt(value, first.start - 1).text);\n const shifted = lines.map((text, i) => shift(text, direction, i === 0 ? cap : undefined));\n if (shifted.every((text, i) => text === lines[i])) return null;\n\n const joined = shifted.join('\\n');\n return {\n value: value.slice(0, first.start) + joined + value.slice(last.end),\n selectionStart: selectionStart + (shifted[0].length - lines[0].length),\n selectionEnd: selectionEnd + (joined.length - block.length),\n };\n}\n","import type { Edit } from './edit';\n\n/** An inline markdown wrapper: bold, italic, code or a link. */\nexport type WrapKind = 'bold' | 'italic' | 'code' | 'link';\n\nconst DELIMITER: Record<Exclude<WrapKind, 'link'>, string> = {\n bold: '**',\n italic: '_',\n code: '`',\n};\n\nconst WHOLE_LINK = /^\\[([^\\]]*)\\]\\(([^)]*)\\)$/;\nconst BARE_URL = /^https?:\\/\\/[^\\s]+$/;\n\nfunction unwrap(value: string, start: number, end: number, delimiter: string): Edit | null {\n const selected = value.slice(start, end);\n const width = delimiter.length;\n\n if (selected.length >= 2 * width && selected.startsWith(delimiter) && selected.endsWith(delimiter)) {\n const inner = selected.slice(width, selected.length - width);\n return {\n value: value.slice(0, start) + inner + value.slice(end),\n selectionStart: start,\n selectionEnd: start + inner.length,\n };\n }\n\n const outside =\n start >= width &&\n value.slice(start - width, start) === delimiter &&\n value.slice(end, end + width) === delimiter;\n\n if (!outside) return null;\n\n return {\n value: value.slice(0, start - width) + selected + value.slice(end + width),\n selectionStart: start - width,\n selectionEnd: start - width + selected.length,\n };\n}\n\nfunction link(value: string, start: number, end: number): Edit {\n const selected = value.slice(start, end);\n const whole = WHOLE_LINK.exec(selected);\n\n if (whole) {\n const text = whole[1];\n return {\n value: value.slice(0, start) + text + value.slice(end),\n selectionStart: start,\n selectionEnd: start + text.length,\n };\n }\n\n const opened = `[${selected}](`;\n const at = selected === '' ? start + 1 : start + opened.length;\n return {\n value: value.slice(0, start) + opened + ')' + value.slice(end),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n\n/** Wraps the selection in the markers for the kind, or removes them when it is already wrapped. */\nexport function wrapSelection(\n kind: WrapKind,\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): Edit {\n if (kind === 'link') return link(value, selectionStart, selectionEnd);\n\n const delimiter = DELIMITER[kind];\n const stripped = unwrap(value, selectionStart, selectionEnd, delimiter);\n if (stripped) return stripped;\n\n const selected = value.slice(selectionStart, selectionEnd);\n\n if (kind === 'code' && selected.includes('\\n')) {\n const at = selectionStart + 4;\n return {\n value: value.slice(0, selectionStart) + '```\\n' + selected + '\\n```' + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at + selected.length,\n };\n }\n\n const at = selectionStart + delimiter.length;\n return {\n value: value.slice(0, selectionStart) + delimiter + selected + delimiter + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at + selected.length,\n };\n}\n\n/** Turns a pasted URL over a selection into a markdown link; returns null when nothing is selected or the paste is not a bare URL, so the paste goes through unchanged. */\nexport function linkPaste(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n pasted: string,\n): Edit | null {\n if (selectionStart === selectionEnd) return null;\n\n const url = pasted.trim();\n if (!BARE_URL.test(url)) return null;\n\n const inserted = `[${value.slice(selectionStart, selectionEnd)}](${url})`;\n const at = selectionStart + inserted.length;\n return {\n value: value.slice(0, selectionStart) + inserted + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n","import type { Edit } from './edit';\nimport { lineAt } from './line-at';\n\n/** The fields `insertCommand` needs. `TextCommand` satisfies this structurally. */\nexport type InsertableCommand = {\n insert: string;\n caretOffset: number;\n selectLength?: number;\n separate: boolean;\n};\n\n/** Inserts a command's markdown at the caret, starting a new line (or a blank line if it asks) when the caret is mid-line. */\nexport function insertCommand(command: InsertableCommand, value: string, caret: number): Edit {\n const line = lineAt(value, caret);\n const before = value.slice(line.start, caret).replace(/[ \\t]+$/, '');\n const cut = line.start + before.length;\n const prefix = before.trim() === '' ? '' : command.separate ? '\\n\\n' : '\\n';\n const at = cut + prefix.length + command.caretOffset;\n\n return {\n value: value.slice(0, cut) + prefix + command.insert + value.slice(caret),\n selectionStart: at,\n selectionEnd: at + (command.selectLength ?? 0),\n };\n}\n","import { insideFence } from './line-at';\n\n/** Whether typing \"/\" here should open the command palette: only at a word start, with no selection and outside a code fence. */\nexport function shouldOpenPalette(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): boolean {\n if (selectionStart !== selectionEnd) return false;\n if (insideFence(value, selectionStart)) return false;\n if (selectionStart === 0) return true;\n\n const previous = value[selectionStart - 1];\n return previous === '\\n' || previous === ' ' || previous === '\\t';\n}\n","const MAC_LABEL: Record<string, string> = { mod: '⌘', alt: '⌥', shift: '⇧' };\nconst OTHER_LABEL: Record<string, string> = { mod: 'Ctrl', alt: 'Alt', shift: 'Shift' };\n\nfunction onMac(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /Mac|iPhone|iPad/.test(navigator.userAgent);\n}\n\n/** Renders a \"mod+shift+b\" style hint as the platform's own label, such as ⌘⇧B on a Mac and Ctrl+Shift+B elsewhere. */\nexport function formatShortcut(hint: string): string {\n const mac = onMac();\n const labels = mac ? MAC_LABEL : OTHER_LABEL;\n const parts = hint.split('+').map((part) => labels[part] ?? part.toUpperCase());\n return parts.join(mac ? '' : '+');\n}\n","type CopiedProperty =\n | 'boxSizing'\n | 'fontFamily'\n | 'fontSize'\n | 'fontStyle'\n | 'fontWeight'\n | 'letterSpacing'\n | 'lineHeight'\n | 'paddingBottom'\n | 'paddingLeft'\n | 'paddingRight'\n | 'paddingTop'\n | 'textIndent'\n | 'textTransform'\n | 'wordBreak'\n | 'wordSpacing'\n | 'borderBottomWidth'\n | 'borderLeftWidth'\n | 'borderRightWidth'\n | 'borderTopWidth';\n\nconst COPIED: CopiedProperty[] = [\n 'boxSizing',\n 'fontFamily',\n 'fontSize',\n 'fontStyle',\n 'fontWeight',\n 'letterSpacing',\n 'lineHeight',\n 'paddingBottom',\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'textIndent',\n 'textTransform',\n 'wordBreak',\n 'wordSpacing',\n 'borderBottomWidth',\n 'borderLeftWidth',\n 'borderRightWidth',\n 'borderTopWidth',\n];\n\n/** The caret's position and line height, in pixels relative to the textarea's top left corner. */\nexport type CaretRect = { top: number; left: number; height: number };\n\n/** A textarea exposes no caret geometry, so the text before the caret is laid\n * out again in a hidden div that copies the box's own metrics, and a marker at\n * the end of it is measured. Returns null when the textarea is not laid out\n * (hidden or detached), because there is nothing to measure. */\nexport function caretRect(el: HTMLTextAreaElement): CaretRect | null {\n if (el.offsetWidth === 0) return null;\n\n const style = window.getComputedStyle(el);\n const mirror = document.createElement('div');\n for (const property of COPIED) mirror.style[property] = style[property];\n mirror.style.position = 'absolute';\n mirror.style.top = '0';\n mirror.style.left = '-9999px';\n mirror.style.visibility = 'hidden';\n mirror.style.whiteSpace = 'pre-wrap';\n mirror.style.overflowWrap = 'break-word';\n mirror.style.width = `${el.clientWidth}px`;\n mirror.textContent = el.value.slice(0, el.selectionStart);\n\n const marker = document.createElement('span');\n marker.textContent = '\\u200b';\n mirror.appendChild(marker);\n document.body.appendChild(mirror);\n\n const top = marker.offsetTop;\n const left = marker.offsetLeft;\n const height = marker.offsetHeight || Number.parseFloat(style.lineHeight) || 0;\n mirror.remove();\n\n if (height === 0) return null;\n return { top: top - el.scrollTop, left, height };\n}\n","import * as React from 'react';\nimport { applyEdit, type Edit } from './edit';\nimport { indentList } from './indent-list';\nimport { toggleLinePrefix, type LinePrefix } from './line-toggles';\nimport { continueList } from './list-continuation';\nimport { shouldOpenPalette } from './slash-trigger';\nimport { linkPaste, wrapSelection, type WrapKind } from './wrap-selection';\n\nconst WRAP: Record<string, WrapKind> = { b: 'bold', i: 'italic', e: 'code', k: 'link' };\n\n// Shift turns the 8 key into \"*\", so the physical code is the only stable match.\nconst HEADING: Record<string, LinePrefix> = { Digit1: 'h1', Digit2: 'h2', Digit3: 'h3' };\nconst LIST: Record<string, LinePrefix> = { Digit7: 'ordered', Digit8: 'bullet' };\n\n/** Keyboard and paste handlers that give a plain textarea markdown shortcuts, list continuation, Tab indent and the slash palette trigger. */\nexport function useMarkdownKeymap({\n commit,\n onOpenPalette,\n}: {\n commit: (markdown: string) => void;\n onOpenPalette: () => void;\n}) {\n const onKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n const el = event.currentTarget;\n const { value, selectionStart, selectionEnd } = el;\n const mod = event.metaKey || event.ctrlKey;\n\n const run = (edit: Edit | null) => {\n if (!edit) return;\n event.preventDefault();\n applyEdit(el, edit, commit);\n };\n\n if (mod && event.altKey) {\n const kind = HEADING[event.code];\n if (kind) run(toggleLinePrefix(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (mod && event.shiftKey) {\n const kind = LIST[event.code];\n if (kind) run(toggleLinePrefix(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (mod) {\n const kind = WRAP[event.key.toLowerCase()];\n if (kind) run(wrapSelection(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (event.key === '/') {\n if (!shouldOpenPalette(value, selectionStart, selectionEnd)) return;\n event.preventDefault();\n onOpenPalette();\n return;\n }\n\n if (event.key === 'Enter' && !event.shiftKey) {\n run(continueList(value, selectionStart, 'Enter'));\n return;\n }\n\n if (event.key === 'Backspace' && selectionStart === selectionEnd) {\n run(continueList(value, selectionStart, 'Backspace'));\n return;\n }\n\n if (event.key === 'Tab') {\n run(indentList(value, selectionStart, selectionEnd, event.shiftKey ? -1 : 1));\n }\n },\n [commit, onOpenPalette],\n );\n\n const onPaste = React.useCallback(\n (event: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const el = event.currentTarget;\n const edit = linkPaste(\n el.value,\n el.selectionStart,\n el.selectionEnd,\n event.clipboardData.getData('text/plain'),\n );\n if (!edit) return;\n event.preventDefault();\n applyEdit(el, edit, commit);\n },\n [commit],\n );\n\n return { onKeyDown, onPaste };\n}\n","import * as React from 'react';\n\n/** Height follows the content, and is recomputed when the box gets narrower or\n * wider, because a re-wrap changes the line count without changing the value.\n * Only a width change refits: reacting to the height this hook just set would\n * feed the observer its own output. */\nexport function useAutoGrow<T extends HTMLTextAreaElement>(value: string) {\n const ref = React.useRef<T>(null);\n const lastWidth = React.useRef<number | null>(null);\n\n // Measuring means collapsing to \"auto\" first, which shrinks the page enough that\n // the browser clamps the scroll position, and growing back does not undo that.\n // Both steps run before paint, so restoring the scroll here is not visible.\n const fit = React.useCallback(() => {\n const el = ref.current;\n if (!el) return;\n const scroller = document.scrollingElement ?? document.documentElement;\n const scrollTop = scroller.scrollTop;\n el.style.height = 'auto';\n if (el.scrollHeight > 0) el.style.height = `${el.scrollHeight}px`;\n if (scroller.scrollTop !== scrollTop) scroller.scrollTop = scrollTop;\n }, []);\n\n React.useLayoutEffect(fit, [fit, value]);\n\n React.useEffect(() => {\n const el = ref.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(([entry]) => {\n const width = entry.contentRect.width;\n if (width === lastWidth.current) return;\n lastWidth.current = width;\n fit();\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, [fit]);\n\n return ref;\n}\n"],"mappings":"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","names":["text","at","INDENT","at","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/markdown/edit.ts","../src/markdown/line-at.ts","../src/markdown/line-toggles.ts","../src/markdown/list-continuation.ts","../src/markdown/indent-list.ts","../src/markdown/wrap-selection.ts","../src/markdown/insert-command.ts","../src/markdown/slash-trigger.ts","../src/markdown/platform.ts","../src/markdown/shortcut-label.ts","../src/markdown/caret-coordinates.ts","../src/markdown/useMarkdownKeymap.ts","../src/hooks/useAutoGrow.ts","../src/hooks/use-isomorphic-layout-effect.ts"],"sourcesContent":["/** A text transform result: the next value and where the selection should land. */\nexport type Edit = { value: string; selectionStart: number; selectionEnd: number };\n\nfunction changedSpan(before: string, after: string) {\n let start = 0;\n const shortest = Math.min(before.length, after.length);\n while (start < shortest && before[start] === after[start]) start += 1;\n\n let endBefore = before.length;\n let endAfter = after.length;\n while (endBefore > start && endAfter > start && before[endBefore - 1] === after[endAfter - 1]) {\n endBefore -= 1;\n endAfter -= 1;\n }\n\n return { start, endBefore, replacement: after.slice(start, endAfter) };\n}\n\n// Writing through execCommand keeps the transform as one entry on the browser's\n// own undo stack. Either path commits el.value rather than the edit's intended\n// value: a browser is trusted to write what it was asked, and if it ever\n// wrote something else, committing our own intent instead would silently\n// diverge React's state from the DOM.\nfunction writeNatively(el: HTMLTextAreaElement, replacement: string): boolean {\n if (typeof document.execCommand !== 'function') return false;\n try {\n return replacement === ''\n ? document.execCommand('delete')\n : document.execCommand('insertText', false, replacement);\n } catch {\n return false;\n }\n}\n\n/** Applies an edit to a textarea through the native undo stack when the browser allows it, so Ctrl+Z still works. */\nexport function applyEdit(\n el: HTMLTextAreaElement,\n edit: Edit,\n commit: (value: string) => void,\n): void {\n if (el.value !== edit.value) {\n const { start, endBefore, replacement } = changedSpan(el.value, edit.value);\n el.setSelectionRange(start, endBefore);\n if (!writeNatively(el, replacement)) {\n el.value = edit.value;\n }\n commit(el.value);\n }\n el.setSelectionRange(edit.selectionStart, edit.selectionEnd);\n}\n","const FENCE = /^ {0,3}(```|~~~)/;\n\nexport type Line = { start: number; end: number; text: string };\n\n/** The line containing the offset, with its start and end offsets and its text (no trailing newline). */\nexport function lineAt(value: string, offset: number): Line {\n const start = value.lastIndexOf('\\n', offset - 1) + 1;\n const next = value.indexOf('\\n', offset);\n const end = next === -1 ? value.length : next;\n return { start, end, text: value.slice(start, end) };\n}\n\nexport function isFenceDelimiter(text: string): boolean {\n return FENCE.test(text);\n}\n\nexport function insideFence(value: string, offset: number): boolean {\n const lines = value.slice(0, offset).split('\\n');\n if (isFenceDelimiter(lines[lines.length - 1])) return true;\n\n let open = false;\n for (let i = 0; i < lines.length - 1; i += 1) {\n if (isFenceDelimiter(lines[i])) open = !open;\n }\n return open;\n}\n","import type { Edit } from './edit';\nimport { insideFence, isFenceDelimiter, lineAt } from './line-at';\n\n/** A line-level markdown prefix: a heading level, a bullet or a numbered item. */\nexport type LinePrefix = 'h1' | 'h2' | 'h3' | 'bullet' | 'ordered';\n\nconst EXISTING = /^(\\s*)(?:#{1,6} |[-*+] \\[[ xX]\\] |[-*+] |\\d+[.)] )?/;\n\nconst PREFIX: Record<LinePrefix, (index: number) => string> = {\n h1: () => '# ',\n h2: () => '## ',\n h3: () => '### ',\n bullet: () => '- ',\n ordered: (index) => `${index + 1}. `,\n};\n\nconst CARRIES: Record<LinePrefix, RegExp> = {\n h1: /^\\s*# /,\n h2: /^\\s*## /,\n h3: /^\\s*### /,\n bullet: /^\\s*[-*+] /,\n ordered: /^\\s*\\d+[.)] /,\n};\n\n/** Adds the prefix to every line in the selection, or removes it when every line already carries it; fenced code is left alone. */\nexport function toggleLinePrefix(\n kind: LinePrefix,\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): Edit {\n const first = lineAt(value, selectionStart);\n const last = lineAt(value, selectionEnd);\n const block = value.slice(first.start, last.end);\n const lines = block.split('\\n');\n\n let offset = first.start;\n const eligible = lines.map((text) => {\n const at = offset;\n offset += text.length + 1;\n return !insideFence(value, at) && !isFenceDelimiter(text);\n });\n\n const carried = lines.every((text, i) => !eligible[i] || CARRIES[kind].test(text));\n\n const rewritten = lines.map((text, i) => {\n if (!eligible[i]) return text;\n const match = EXISTING.exec(text);\n const indent = match?.[1] ?? '';\n const body = text.slice(match?.[0].length ?? 0);\n return carried ? indent + body : indent + PREFIX[kind](i) + body;\n });\n\n const joined = rewritten.join('\\n');\n const next = value.slice(0, first.start) + joined + value.slice(last.end);\n\n if (selectionStart !== selectionEnd) {\n return { value: next, selectionStart: first.start, selectionEnd: first.start + joined.length };\n }\n\n const caret = Math.max(first.start, selectionStart + (rewritten[0].length - lines[0].length));\n return { value: next, selectionStart: caret, selectionEnd: caret };\n}\n","import type { Edit } from './edit';\nimport { insideFence, lineAt, type Line } from './line-at';\n\nexport const LIST_MARKER = /^(\\s*)((?:[-*+] \\[[ xX]\\] )|(?:[-*+] )|(?:\\d+[.)] )|(?:> ))(.*)$/;\n\nconst INDENT = ' ';\n\nfunction nextMarker(marker: string): string {\n const ordered = /^(\\d+)([.)] )$/.exec(marker);\n if (ordered) return `${Number(ordered[1]) + 1}${ordered[2]}`;\n const task = /^([-*+]) \\[[ xX]\\] $/.exec(marker);\n if (task) return `${task[1]} [ ] `;\n return marker;\n}\n\n// Both the dead item on Enter and the caret at the content start on Backspace\n// mean the same thing: climb out one level, or drop the marker at the top.\nfunction climbOut(value: string, line: Line, indent: string, marker: string, content: string): Edit {\n const outdent = indent.length >= INDENT.length;\n\n if (outdent) {\n const text = indent.slice(INDENT.length) + marker + content;\n const at = line.start + indent.length - INDENT.length + marker.length;\n return {\n value: value.slice(0, line.start) + text + value.slice(line.end),\n selectionStart: at,\n selectionEnd: at,\n };\n }\n\n // A stripped marker with only a single newline above it reads to CommonMark\n // as a lazy continuation of the previous list item's paragraph, not a new\n // block, so a blank line is needed whenever that previous line is a list item.\n const leavesList = line.start > 0 && LIST_MARKER.test(lineAt(value, line.start - 1).text);\n const text = leavesList ? `\\n${content}` : content;\n const at = leavesList ? line.start + 1 : line.start;\n\n return {\n value: value.slice(0, line.start) + text + value.slice(line.end),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n\n/** Continues a list item on Enter, or climbs out of the list on an empty item or Backspace at the marker; returns null when the caret is not in a list item or is inside a code fence, so the default key behaviour runs. */\nexport function continueList(\n value: string,\n caret: number,\n key: 'Enter' | 'Backspace',\n): Edit | null {\n if (insideFence(value, caret)) return null;\n\n const line = lineAt(value, caret);\n const match = LIST_MARKER.exec(line.text);\n if (!match) return null;\n\n const [, indent, marker, content] = match;\n\n if (key === 'Backspace') {\n if (caret !== line.start + indent.length + marker.length) return null;\n return climbOut(value, line, indent, marker, content);\n }\n\n if (content.trim() === '') return climbOut(value, line, indent, marker, content);\n\n const inserted = `\\n${indent}${nextMarker(marker)}`;\n const at = caret + inserted.length;\n return {\n value: value.slice(0, caret) + inserted + value.slice(caret),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n","import type { Edit } from './edit';\nimport { insideFence, lineAt } from './line-at';\nimport { LIST_MARKER } from './list-continuation';\n\nconst INDENT = ' ';\n\nfunction indentOf(text: string): number {\n return /^\\s*/.exec(text)?.[0].length ?? 0;\n}\n\n// Indenting more than one level past the line above turns a list item into an\n// indented code block, so the first line of the range is capped against it.\nfunction shift(text: string, direction: 1 | -1, cap: number | undefined): string {\n const current = indentOf(text);\n if (direction === -1) return text.slice(Math.min(current, INDENT.length));\n if (cap !== undefined && current >= cap + INDENT.length) return text;\n return INDENT + text;\n}\n\n/** Indents or outdents the selected list items; returns null when the selection is not entirely list items, is inside a code fence, or cannot move further, so Tab keeps its default behaviour. */\nexport function indentList(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n direction: 1 | -1,\n): Edit | null {\n if (insideFence(value, selectionStart)) return null;\n\n const first = lineAt(value, selectionStart);\n const last = lineAt(value, selectionEnd);\n const block = value.slice(first.start, last.end);\n const lines = block.split('\\n');\n if (!lines.every((text) => LIST_MARKER.test(text))) return null;\n\n const cap = first.start === 0 ? 0 : indentOf(lineAt(value, first.start - 1).text);\n const shifted = lines.map((text, i) => shift(text, direction, i === 0 ? cap : undefined));\n if (shifted.every((text, i) => text === lines[i])) return null;\n\n const joined = shifted.join('\\n');\n return {\n value: value.slice(0, first.start) + joined + value.slice(last.end),\n selectionStart: selectionStart + (shifted[0].length - lines[0].length),\n selectionEnd: selectionEnd + (joined.length - block.length),\n };\n}\n","import type { Edit } from './edit';\n\n/** An inline markdown wrapper: bold, italic, code or a link. */\nexport type WrapKind = 'bold' | 'italic' | 'code' | 'link';\n\nconst DELIMITER: Record<Exclude<WrapKind, 'link'>, string> = {\n bold: '**',\n italic: '_',\n code: '`',\n};\n\nconst WHOLE_LINK = /^\\[([^\\]]*)\\]\\(([^)]*)\\)$/;\nconst BARE_URL = /^https?:\\/\\/[^\\s]+$/;\n\nfunction unwrap(value: string, start: number, end: number, delimiter: string): Edit | null {\n const selected = value.slice(start, end);\n const width = delimiter.length;\n\n if (selected.length >= 2 * width && selected.startsWith(delimiter) && selected.endsWith(delimiter)) {\n const inner = selected.slice(width, selected.length - width);\n return {\n value: value.slice(0, start) + inner + value.slice(end),\n selectionStart: start,\n selectionEnd: start + inner.length,\n };\n }\n\n const outside =\n start >= width &&\n value.slice(start - width, start) === delimiter &&\n value.slice(end, end + width) === delimiter;\n\n if (!outside) return null;\n\n return {\n value: value.slice(0, start - width) + selected + value.slice(end + width),\n selectionStart: start - width,\n selectionEnd: start - width + selected.length,\n };\n}\n\nfunction link(value: string, start: number, end: number): Edit {\n const selected = value.slice(start, end);\n const whole = WHOLE_LINK.exec(selected);\n\n if (whole) {\n const text = whole[1];\n return {\n value: value.slice(0, start) + text + value.slice(end),\n selectionStart: start,\n selectionEnd: start + text.length,\n };\n }\n\n const opened = `[${selected}](`;\n const at = selected === '' ? start + 1 : start + opened.length;\n return {\n value: value.slice(0, start) + opened + ')' + value.slice(end),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n\n/** Wraps the selection in the markers for the kind, or removes them when it is already wrapped. */\nexport function wrapSelection(\n kind: WrapKind,\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): Edit {\n if (kind === 'link') return link(value, selectionStart, selectionEnd);\n\n const delimiter = DELIMITER[kind];\n const stripped = unwrap(value, selectionStart, selectionEnd, delimiter);\n if (stripped) return stripped;\n\n const selected = value.slice(selectionStart, selectionEnd);\n\n if (kind === 'code' && selected.includes('\\n')) {\n const at = selectionStart + 4;\n return {\n value: value.slice(0, selectionStart) + '```\\n' + selected + '\\n```' + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at + selected.length,\n };\n }\n\n const at = selectionStart + delimiter.length;\n return {\n value: value.slice(0, selectionStart) + delimiter + selected + delimiter + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at + selected.length,\n };\n}\n\n/** Turns a pasted URL over a selection into a markdown link; returns null when nothing is selected or the paste is not a bare URL, so the paste goes through unchanged. */\nexport function linkPaste(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n pasted: string,\n): Edit | null {\n if (selectionStart === selectionEnd) return null;\n\n const url = pasted.trim();\n if (!BARE_URL.test(url)) return null;\n\n const inserted = `[${value.slice(selectionStart, selectionEnd)}](${url})`;\n const at = selectionStart + inserted.length;\n return {\n value: value.slice(0, selectionStart) + inserted + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n","import type { Edit } from './edit';\nimport { lineAt } from './line-at';\n\n/** The fields `insertCommand` needs. `TextCommand` satisfies this structurally. */\nexport type InsertableCommand = {\n insert: string;\n caretOffset: number;\n selectLength?: number;\n separate: boolean;\n};\n\n/** Inserts a command's markdown at the caret, starting a new line (or a blank line if it asks) when the caret is mid-line. */\nexport function insertCommand(command: InsertableCommand, value: string, caret: number): Edit {\n const line = lineAt(value, caret);\n const before = value.slice(line.start, caret).replace(/[ \\t]+$/, '');\n const cut = line.start + before.length;\n const prefix = before.trim() === '' ? '' : command.separate ? '\\n\\n' : '\\n';\n const at = cut + prefix.length + command.caretOffset;\n\n return {\n value: value.slice(0, cut) + prefix + command.insert + value.slice(caret),\n selectionStart: at,\n selectionEnd: at + (command.selectLength ?? 0),\n };\n}\n","import { insideFence } from './line-at';\n\n/** Whether typing \"/\" here should open the command palette: only at a word start, with no selection and outside a code fence. */\nexport function shouldOpenPalette(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): boolean {\n if (selectionStart !== selectionEnd) return false;\n if (insideFence(value, selectionStart)) return false;\n if (selectionStart === 0) return true;\n\n const previous = value[selectionStart - 1];\n return previous === '\\n' || previous === ' ' || previous === '\\t';\n}\n","type NavigatorWithData = Navigator & { userAgentData?: { platform?: string } };\n\n/** True on macOS and iOS, where the shortcut modifier is Command rather than Ctrl. Read on each call so a stubbed navigator is honoured. */\nexport function isMac(): boolean {\n if (typeof navigator === 'undefined') return false;\n const { userAgentData, platform } = navigator as NavigatorWithData;\n return /mac|iphone|ipad/i.test(userAgentData?.platform || platform || '');\n}\n","import { isMac } from './platform';\n\nconst MAC_LABEL: Record<string, string> = { mod: '⌘', alt: '⌥', shift: '⇧' };\nconst OTHER_LABEL: Record<string, string> = { mod: 'Ctrl', alt: 'Alt', shift: 'Shift' };\n\n/** Renders a \"mod+shift+b\" style hint as the platform's own label, such as ⌘⇧B on a Mac and Ctrl+Shift+B elsewhere. */\nexport function formatShortcut(hint: string): string {\n const mac = isMac();\n const labels = mac ? MAC_LABEL : OTHER_LABEL;\n const parts = hint.split('+').map((part) => labels[part] ?? part.toUpperCase());\n return parts.join(mac ? '' : '+');\n}\n","type CopiedProperty =\n | 'boxSizing'\n | 'fontFamily'\n | 'fontSize'\n | 'fontStyle'\n | 'fontWeight'\n | 'letterSpacing'\n | 'lineHeight'\n | 'paddingBottom'\n | 'paddingLeft'\n | 'paddingRight'\n | 'paddingTop'\n | 'textIndent'\n | 'textTransform'\n | 'wordBreak'\n | 'wordSpacing'\n | 'borderBottomWidth'\n | 'borderLeftWidth'\n | 'borderRightWidth'\n | 'borderTopWidth';\n\nconst COPIED: CopiedProperty[] = [\n 'boxSizing',\n 'fontFamily',\n 'fontSize',\n 'fontStyle',\n 'fontWeight',\n 'letterSpacing',\n 'lineHeight',\n 'paddingBottom',\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'textIndent',\n 'textTransform',\n 'wordBreak',\n 'wordSpacing',\n 'borderBottomWidth',\n 'borderLeftWidth',\n 'borderRightWidth',\n 'borderTopWidth',\n];\n\n/** The caret's position and line height, in pixels relative to the textarea's top left corner. */\nexport type CaretRect = { top: number; left: number; height: number };\n\n/** A textarea exposes no caret geometry, so the text before the caret is laid\n * out again in a hidden div that copies the box's own metrics, and a marker at\n * the end of it is measured. Returns null when the textarea is not laid out\n * (hidden or detached), because there is nothing to measure. */\nexport function caretRect(el: HTMLTextAreaElement): CaretRect | null {\n if (el.offsetWidth === 0) return null;\n\n const style = window.getComputedStyle(el);\n const mirror = document.createElement('div');\n for (const property of COPIED) mirror.style[property] = style[property];\n mirror.style.position = 'absolute';\n mirror.style.top = '0';\n mirror.style.left = '-9999px';\n mirror.style.visibility = 'hidden';\n mirror.style.whiteSpace = 'pre-wrap';\n mirror.style.overflowWrap = 'break-word';\n mirror.style.width = `${el.clientWidth}px`;\n mirror.textContent = el.value.slice(0, el.selectionStart);\n\n const marker = document.createElement('span');\n marker.textContent = '\\u200b';\n mirror.appendChild(marker);\n document.body.appendChild(mirror);\n\n const top = marker.offsetTop;\n const left = marker.offsetLeft;\n const height = marker.offsetHeight || Number.parseFloat(style.lineHeight) || 0;\n mirror.remove();\n\n if (height === 0) return null;\n return { top: top - el.scrollTop, left, height };\n}\n","import * as React from 'react';\nimport { applyEdit, type Edit } from './edit';\nimport { indentList } from './indent-list';\nimport { toggleLinePrefix, type LinePrefix } from './line-toggles';\nimport { continueList } from './list-continuation';\nimport { isMac } from './platform';\nimport { shouldOpenPalette } from './slash-trigger';\nimport { linkPaste, wrapSelection, type WrapKind } from './wrap-selection';\n\nconst WRAP: Record<string, WrapKind> = { b: 'bold', i: 'italic', e: 'code', k: 'link' };\n\n// Shift turns the 8 key into \"*\", so the physical code is the only stable match.\nconst HEADING: Record<string, LinePrefix> = { Digit1: 'h1', Digit2: 'h2', Digit3: 'h3' };\nconst LIST: Record<string, LinePrefix> = { Digit7: 'ordered', Digit8: 'bullet' };\n\n/** Keyboard and paste handlers that give a plain textarea markdown shortcuts, list continuation, Tab indent and the slash palette trigger. */\nexport function useMarkdownKeymap({\n commit,\n onOpenPalette,\n}: {\n commit: (markdown: string) => void;\n onOpenPalette: () => void;\n}) {\n const onKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n // Safari reports keyCode 229 for the keydown that follows compositionend.\n if (event.nativeEvent.isComposing || event.keyCode === 229) return;\n\n const el = event.currentTarget;\n const { value, selectionStart, selectionEnd } = el;\n const mod = isMac() ? event.metaKey : event.ctrlKey;\n\n const run = (edit: Edit | null) => {\n if (!edit) return;\n event.preventDefault();\n applyEdit(el, edit, commit);\n };\n\n if (mod && event.altKey) {\n const kind = HEADING[event.code];\n if (kind) run(toggleLinePrefix(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (mod && event.shiftKey) {\n const kind = LIST[event.code];\n if (kind) run(toggleLinePrefix(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (mod) {\n const kind = WRAP[event.key.toLowerCase()];\n if (kind) run(wrapSelection(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (event.key === '/') {\n if (!shouldOpenPalette(value, selectionStart, selectionEnd)) return;\n event.preventDefault();\n onOpenPalette();\n return;\n }\n\n if (event.key === 'Enter' && !event.shiftKey) {\n run(continueList(value, selectionStart, 'Enter'));\n return;\n }\n\n if (event.key === 'Backspace' && selectionStart === selectionEnd) {\n run(continueList(value, selectionStart, 'Backspace'));\n return;\n }\n\n if (event.key === 'Tab') {\n run(indentList(value, selectionStart, selectionEnd, event.shiftKey ? -1 : 1));\n }\n },\n [commit, onOpenPalette],\n );\n\n const onPaste = React.useCallback(\n (event: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const el = event.currentTarget;\n const edit = linkPaste(\n el.value,\n el.selectionStart,\n el.selectionEnd,\n event.clipboardData.getData('text/plain'),\n );\n if (!edit) return;\n event.preventDefault();\n applyEdit(el, edit, commit);\n },\n [commit],\n );\n\n return { onKeyDown, onPaste };\n}\n","import * as React from 'react';\nimport { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect';\n\n/** Height follows the content, and is recomputed when the box gets narrower or\n * wider, because a re-wrap changes the line count without changing the value.\n * Only a width change refits: reacting to the height this hook just set would\n * feed the observer its own output. */\nexport function useAutoGrow<T extends HTMLTextAreaElement>(value: string): React.RefObject<T> {\n const ref = React.useRef<T>(null);\n const lastWidth = React.useRef<number | null>(null);\n\n // Measuring means collapsing to \"auto\" first, which shrinks the page enough that\n // the browser clamps the scroll position, and growing back does not undo that.\n // Both steps run before paint, so restoring the scroll here is not visible.\n const fit = React.useCallback(() => {\n const el = ref.current;\n if (!el) return;\n const scroller = document.scrollingElement ?? document.documentElement;\n const scrollTop = scroller.scrollTop;\n el.style.height = 'auto';\n if (el.scrollHeight > 0) el.style.height = `${el.scrollHeight}px`;\n if (scroller.scrollTop !== scrollTop) scroller.scrollTop = scrollTop;\n }, []);\n\n useIsomorphicLayoutEffect(fit, [fit, value]);\n\n React.useEffect(() => {\n const el = ref.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(([entry]) => {\n const width = entry.contentRect.width;\n if (width === lastWidth.current) return;\n lastWidth.current = width;\n fit();\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, [fit]);\n\n // React 18's types refuse `RefObject<T | null>` on a `ref` prop, and `RefObject<T>` fits both majors.\n return ref as React.RefObject<T>;\n}\n","import * as React from 'react';\n\nexport const useIsomorphicLayoutEffect = typeof document === 'undefined' ? React.useEffect : React.useLayoutEffect;\n"],"mappings":"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","names":["text","at","INDENT","at","React","React"]}
|