@nks-hub/texy-editor 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"texy-editor.js","sources":["../src/core/Selection.ts","../src/core/TexyFormatter.ts","../src/core/EventBus.ts","../src/core/UndoManager.ts","../src/core/KeyboardManager.ts","../src/core/ToolbarBuilder.ts","../src/core/DialogManager.ts","../src/parser/TexyParser.ts","../src/parser/plugins/youtube.ts","../src/parser/plugins/smiley.ts","../src/parser/plugins/link-redirect.ts","../src/parser/plugins/bbcode.ts","../src/parser/plugins/image-embed.ts","../src/i18n/cs.ts","../src/i18n/en.ts","../src/i18n/index.ts","../src/core/TexyEditor.ts"],"sourcesContent":["import type { SelectionState } from '../types';\r\n\r\n/**\r\n * Textarea selection manager.\r\n * Provides methods to read, manipulate, and replace selected text\r\n * in a standard HTMLTextAreaElement without any external dependencies.\r\n */\r\nexport class Selection {\r\n constructor(private textarea: HTMLTextAreaElement) {}\r\n\r\n /** Detect the line-feed character used in the textarea value */\r\n get lf(): string {\r\n const val = this.textarea.value;\r\n if (val.includes('\\r\\n')) return '\\r\\n';\r\n if (val.includes('\\r')) return '\\r';\r\n return '\\n';\r\n }\r\n\r\n /** Get current selection state snapshot */\r\n getState(): SelectionState {\r\n const { selectionStart: start, selectionEnd: end, value } = this.textarea;\r\n return {\r\n start,\r\n end,\r\n text: value.substring(start, end),\r\n before: value.substring(0, start),\r\n after: value.substring(end),\r\n };\r\n }\r\n\r\n /** Get selected text */\r\n text(): string {\r\n return this.getState().text;\r\n }\r\n\r\n /** Length of current selection */\r\n length(): number {\r\n return this.textarea.selectionEnd - this.textarea.selectionStart;\r\n }\r\n\r\n /** Whether selection is collapsed (cursor without selection) */\r\n isCursor(): boolean {\r\n return this.textarea.selectionStart === this.textarea.selectionEnd;\r\n }\r\n\r\n /** Set selection range programmatically */\r\n select(start: number, length: number): void {\r\n this.textarea.focus();\r\n this.textarea.setSelectionRange(start, start + length);\r\n }\r\n\r\n /** Place cursor at a specific position */\r\n setCursor(position: number): void {\r\n this.select(position, 0);\r\n }\r\n\r\n /**\r\n * Replace currently selected text with new content.\r\n * After replacement, the new text is selected.\r\n */\r\n replace(replacement: string): void {\r\n const state = this.getState();\r\n const scrollTop = this.textarea.scrollTop;\r\n\r\n this.textarea.value = state.before + replacement + state.after;\r\n this.select(state.start, replacement.length);\r\n this.textarea.scrollTop = scrollTop;\r\n\r\n this.dispatchInput();\r\n }\r\n\r\n /**\r\n * Wrap selection with prefix and suffix.\r\n * If nothing is selected (cursor), places cursor between prefix and suffix.\r\n */\r\n tag(prefix: string, suffix: string): void {\r\n const state = this.getState();\r\n const scrollTop = this.textarea.scrollTop;\r\n\r\n const newValue = state.before + prefix + state.text + suffix + state.after;\r\n this.textarea.value = newValue;\r\n\r\n if (this.isCursorAt(state)) {\r\n // Place cursor between prefix and suffix\r\n this.setCursor(state.start + prefix.length);\r\n } else {\r\n // Select the wrapped content (without prefix/suffix)\r\n this.select(state.start + prefix.length, state.text.length);\r\n }\r\n\r\n this.textarea.scrollTop = scrollTop;\r\n this.dispatchInput();\r\n }\r\n\r\n /**\r\n * Wrap selection as an inline phrase.\r\n * Trims trailing whitespace from selection before wrapping.\r\n */\r\n phrase(prefix: string, suffix?: string): void {\r\n this.trimSelect();\r\n this.tag(prefix, suffix ?? prefix);\r\n }\r\n\r\n /**\r\n * Remove trailing whitespace from the selection boundary.\r\n * Useful when double-clicking selects a trailing space.\r\n */\r\n trimSelect(): void {\r\n const state = this.getState();\r\n const trimmed = state.text.replace(/\\s+$/, '');\r\n if (trimmed.length < state.text.length) {\r\n this.select(state.start, trimmed.length);\r\n }\r\n }\r\n\r\n /**\r\n * Expand selection to cover complete lines.\r\n * Useful for block-level operations (lists, headings).\r\n */\r\n selectBlock(): void {\r\n const { value } = this.textarea;\r\n let start = this.textarea.selectionStart;\r\n let end = this.textarea.selectionEnd;\r\n\r\n // Expand start to beginning of line\r\n while (start > 0 && value[start - 1] !== '\\n') {\r\n start--;\r\n }\r\n\r\n // Expand end to end of line\r\n while (end < value.length && value[end] !== '\\n') {\r\n end++;\r\n }\r\n\r\n this.select(start, end - start);\r\n }\r\n\r\n /** Get the full value of the textarea */\r\n getValue(): string {\r\n return this.textarea.value;\r\n }\r\n\r\n /** Set the full value of the textarea */\r\n setValue(value: string): void {\r\n this.textarea.value = value;\r\n this.dispatchInput();\r\n }\r\n\r\n /** Focus the textarea */\r\n focus(): void {\r\n this.textarea.focus();\r\n }\r\n\r\n /** Get the underlying textarea element */\r\n getElement(): HTMLTextAreaElement {\r\n return this.textarea;\r\n }\r\n\r\n private isCursorAt(state: SelectionState): boolean {\r\n return state.start === state.end;\r\n }\r\n\r\n private dispatchInput(): void {\r\n this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n}\r\n","import { Selection } from './Selection';\r\n\r\n/**\r\n * Texy markup insertion and toggle operations.\r\n * Each method manipulates the textarea selection to insert or toggle\r\n * Texy-formatted markup.\r\n */\r\nexport class TexyFormatter {\r\n constructor(private selection: Selection) {}\r\n\r\n // ── Inline Phrases ──────────────────────────────────────────\r\n\r\n bold(): void {\r\n this.selection.trimSelect();\r\n const text = this.selection.text();\r\n\r\n if (text.match(/^\\*\\*.*\\*\\*$/)) {\r\n this.selection.replace(text.substring(2, text.length - 2));\r\n } else {\r\n this.selection.tag('**', '**');\r\n }\r\n }\r\n\r\n italic(): void {\r\n this.selection.trimSelect();\r\n const text = this.selection.text();\r\n\r\n if (text.match(/^\\*\\*\\*.*\\*\\*\\*$/) || text.match(/^\\*[^*]+\\*$/)) {\r\n this.selection.replace(text.substring(1, text.length - 1));\r\n } else {\r\n this.selection.tag('*', '*');\r\n }\r\n }\r\n\r\n deleted(): void {\r\n this.toggleInline('--');\r\n }\r\n\r\n inserted(): void {\r\n this.toggleInline('++');\r\n }\r\n\r\n superscript(): void {\r\n this.toggleInline('^^');\r\n }\r\n\r\n subscript(): void {\r\n this.toggleInline('__');\r\n }\r\n\r\n inlineCode(): void {\r\n this.toggleInline('`');\r\n }\r\n\r\n noTexy(): void {\r\n this.selection.phrase(\"''\", \"''\");\r\n }\r\n\r\n quoted(): void {\r\n this.selection.phrase('>>', '<<');\r\n }\r\n\r\n // ── Links & References ────────────────────────────────────────\r\n\r\n link(url: string, text?: string): void {\r\n if (!url) return;\r\n\r\n if (text) {\r\n this.selection.replace(`\"${text}\":${url}`);\r\n } else if (this.selection.isCursor()) {\r\n this.selection.replace(`\"\":${url}`);\r\n // Place cursor inside the quotes\r\n const state = this.selection.getState();\r\n this.selection.setCursor(state.start + 1);\r\n } else {\r\n this.selection.phrase('\"', `\":${url}`);\r\n }\r\n }\r\n\r\n acronym(title: string): void {\r\n if (!title) return;\r\n\r\n const text = this.selection.text();\r\n\r\n // Single word - no quotes needed: word((title))\r\n if (text.match(/^[\\p{L}\\p{N}]{2,}$/u)) {\r\n this.selection.tag('', `((${title}))`);\r\n } else {\r\n // Phrase - needs quotes: \"phrase\"((title))\r\n this.selection.phrase('\"', `\"((${title}))`);\r\n }\r\n }\r\n\r\n // ── Images ────────────────────────────────────────────────────\r\n\r\n image(src: string, alt?: string, align?: '<' | '>' | '<>' | '*', caption?: string): void {\r\n let markup = '';\r\n\r\n // Center alignment needs paragraph modifier\r\n if (align === '<>') {\r\n markup += this.selection.lf + '.<>' + this.selection.lf;\r\n align = '*';\r\n }\r\n\r\n markup += '[* ' + src + ' ';\r\n if (alt) markup += `.( ${alt}) `;\r\n markup += (align || '*') + ']';\r\n if (caption) markup += ' *** ' + caption;\r\n\r\n this.selection.replace(markup);\r\n }\r\n\r\n // ── Headings ──────────────────────────────────────────────────\r\n\r\n heading(level: 1 | 2 | 3 | 4): void {\r\n const underlineChars: Record<number, string> = { 1: '#', 2: '*', 3: '=', 4: '-' };\r\n const char = underlineChars[level];\r\n const lf = this.selection.lf;\r\n\r\n this.selection.selectBlock();\r\n\r\n if (this.selection.isCursor()) {\r\n return; // Need text or prompt - handled by toolbar action\r\n }\r\n\r\n const text = this.selection.text();\r\n const underline = char.repeat(Math.max(3, text.length));\r\n this.selection.tag('', lf + underline);\r\n }\r\n\r\n headingWithPrompt(level: 1 | 2 | 3 | 4, text: string): void {\r\n if (!text) return;\r\n const underlineChars: Record<number, string> = { 1: '#', 2: '*', 3: '=', 4: '-' };\r\n const char = underlineChars[level];\r\n const lf = this.selection.lf;\r\n const underline = char.repeat(Math.max(3, text.length));\r\n this.selection.tag(text + lf + underline + lf, '');\r\n }\r\n\r\n // ── Lists ─────────────────────────────────────────────────────\r\n\r\n unorderedList(): void {\r\n this.applyList('ul');\r\n }\r\n\r\n orderedList(): void {\r\n this.applyList('ol');\r\n }\r\n\r\n orderedListRoman(): void {\r\n this.applyList('romans');\r\n }\r\n\r\n orderedListRomanSmall(): void {\r\n this.applyList('smallRomans');\r\n }\r\n\r\n orderedListAlpha(): void {\r\n this.applyList('bigAlphabet');\r\n }\r\n\r\n orderedListAlphaSmall(): void {\r\n this.applyList('smallAlphabet');\r\n }\r\n\r\n blockquote(): void {\r\n this.applyList('bq');\r\n }\r\n\r\n // ── Indentation ───────────────────────────────────────────────\r\n\r\n indent(): void {\r\n this.applyList('indent');\r\n }\r\n\r\n unindent(): void {\r\n this.selection.selectBlock();\r\n const lf = this.selection.lf;\r\n const lines = this.selection.text().split(lf);\r\n\r\n const unindented = lines.map((line) => {\r\n const first = line[0];\r\n if (first === ' ' || first === '\\t') {\r\n return line.substring(1);\r\n }\r\n return line;\r\n });\r\n\r\n this.selection.replace(unindented.join(lf));\r\n }\r\n\r\n // ── Alignment ─────────────────────────────────────────────────\r\n\r\n alignLeft(): void {\r\n this.insertAlignment('<');\r\n }\r\n\r\n alignRight(): void {\r\n this.insertAlignment('>');\r\n }\r\n\r\n alignCenter(): void {\r\n this.insertAlignment('<>');\r\n }\r\n\r\n alignJustify(): void {\r\n this.insertAlignment('=');\r\n }\r\n\r\n // ── Block Elements ────────────────────────────────────────────\r\n\r\n codeBlock(language?: string): void {\r\n const lf = this.selection.lf;\r\n const lang = language ? ' ' + language : '';\r\n this.selection.tag(`/--code${lang}${lf}`, `${lf}\\\\--`);\r\n }\r\n\r\n htmlBlock(): void {\r\n const lf = this.selection.lf;\r\n this.selection.tag(`/--html${lf}`, `${lf}\\\\--`);\r\n }\r\n\r\n divBlock(modifier?: string): void {\r\n const lf = this.selection.lf;\r\n const mod = modifier ? ` ${modifier}` : '';\r\n this.selection.tag(`/--div${mod}${lf}`, `${lf}\\\\--`);\r\n }\r\n\r\n textBlock(): void {\r\n const lf = this.selection.lf;\r\n this.selection.tag(`/--text${lf}`, `${lf}\\\\--`);\r\n }\r\n\r\n commentBlock(): void {\r\n const lf = this.selection.lf;\r\n this.selection.tag(`/--comment${lf}`, `${lf}\\\\--`);\r\n }\r\n\r\n horizontalRule(): void {\r\n const lf = this.selection.lf;\r\n const rule = `${lf}${lf}-------------------${lf}${lf}`;\r\n\r\n if (this.selection.isCursor()) {\r\n this.selection.tag(rule, '');\r\n } else {\r\n this.selection.replace(rule);\r\n }\r\n }\r\n\r\n // ── Tables ────────────────────────────────────────────────────\r\n\r\n table(cols: number, rows: number, header?: 'none' | 'top' | 'left'): void {\r\n const lf = this.selection.lf;\r\n let markup = lf;\r\n\r\n for (let i = 0; i < rows; i++) {\r\n // Top header separator\r\n if (header === 'top' && i === 1) {\r\n markup += '|';\r\n for (let j = 0; j < cols; j++) {\r\n markup += '--------';\r\n }\r\n markup += lf;\r\n }\r\n\r\n for (let j = 0; j < cols; j++) {\r\n if (header === 'left' && j === 0) {\r\n markup += '|* \\t';\r\n } else {\r\n markup += '| \\t';\r\n }\r\n }\r\n markup += '|' + lf;\r\n }\r\n markup += lf;\r\n\r\n this.selection.replace(markup);\r\n }\r\n\r\n // ── Modifiers ─────────────────────────────────────────────────\r\n\r\n colorModifier(color: string): void {\r\n this.selection.phrase(`\"`, `\" .{color: ${color}}`);\r\n }\r\n\r\n classModifier(className: string): void {\r\n this.selection.phrase(`\"`, `\" .[${className}]`);\r\n }\r\n\r\n // ── Symbols ───────────────────────────────────────────────────\r\n\r\n insertSymbol(symbol: string): void {\r\n if (this.selection.isCursor()) {\r\n this.selection.tag(symbol, '');\r\n } else {\r\n this.selection.replace(symbol);\r\n }\r\n }\r\n\r\n // ── Private Helpers ───────────────────────────────────────────\r\n\r\n private toggleInline(marker: string): void {\r\n this.selection.trimSelect();\r\n const text = this.selection.text();\r\n const escaped = marker.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n const regex = new RegExp(`^${escaped}.*${escaped}$`);\r\n\r\n if (regex.test(text)) {\r\n this.selection.replace(text.substring(marker.length, text.length - marker.length));\r\n } else {\r\n this.selection.tag(marker, marker);\r\n }\r\n }\r\n\r\n private applyList(type: string): void {\r\n this.selection.selectBlock();\r\n const lf = this.selection.lf;\r\n const lines = this.selection.text().split(lf);\r\n const lineCount = this.selection.isCursor() ? 3 : lines.length;\r\n\r\n const parts: string[] = [];\r\n for (let i = 1; i <= lineCount; i++) {\r\n const bullet = this.getBullet(type, i);\r\n const content = !this.selection.isCursor() ? lines[i - 1] : '';\r\n parts.push(bullet + ' ' + content);\r\n }\r\n\r\n if (this.selection.isCursor()) {\r\n // Place cursor after first bullet\r\n const firstLine = parts[0];\r\n const rest = parts.slice(1).join(lf);\r\n this.selection.tag(firstLine, lf + rest);\r\n } else {\r\n this.selection.replace(parts.join(lf));\r\n }\r\n }\r\n\r\n private getBullet(type: string, index: number): string {\r\n switch (type) {\r\n case 'ul': return '-';\r\n case 'ol': return index + ')';\r\n case 'bq': return '>';\r\n case 'indent': return '';\r\n case 'romans': return this.toRoman(index) + ')';\r\n case 'smallRomans': return this.toRoman(index).toLowerCase() + ')';\r\n case 'smallAlphabet': return this.toLetter(index) + ')';\r\n case 'bigAlphabet': return this.toLetter(index).toUpperCase() + ')';\r\n default: return '-';\r\n }\r\n }\r\n\r\n private toRoman(num: number): string {\r\n num = Math.min(num, 5999);\r\n const mill = ['', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM'];\r\n const cent = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'];\r\n const tens = ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'];\r\n const ones = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'];\r\n\r\n const m = Math.floor(num / 1000);\r\n const c = Math.floor((num % 1000) / 100);\r\n const t = Math.floor((num % 100) / 10);\r\n const o = num % 10;\r\n\r\n return mill[m] + cent[c] + tens[t] + ones[o];\r\n }\r\n\r\n private toLetter(n: number): string {\r\n const alphabet = 'abcdefghijklmnopqrstuvwxyz';\r\n return alphabet[Math.max(0, Math.min(n, 26) - 1)];\r\n }\r\n\r\n private insertAlignment(type: string): void {\r\n const value = this.selection.getValue();\r\n const start = this.selection.getState().start;\r\n const lf = this.selection.lf;\r\n const newPar = lf + lf;\r\n const prefix = '.' + type + lf;\r\n\r\n const found = value.substring(0, start).lastIndexOf(newPar);\r\n\r\n if (found === -1) {\r\n this.selection.setValue(prefix + value);\r\n this.selection.setCursor(start + prefix.length);\r\n } else {\r\n const beforePar = found + newPar.length;\r\n this.selection.setValue(\r\n value.substring(0, beforePar) + prefix + value.substring(beforePar)\r\n );\r\n this.selection.setCursor(start + prefix.length);\r\n }\r\n }\r\n}\r\n","import type { TexyEditorEvents, TexyEventHandler } from '../types';\r\n\r\ntype EventMap = TexyEditorEvents;\r\n\r\nexport class EventBus {\r\n private listeners = new Map<string, Set<TexyEventHandler<unknown>>>();\r\n\r\n on<K extends keyof EventMap>(event: K, handler: TexyEventHandler<EventMap[K]>): void {\r\n if (!this.listeners.has(event as string)) {\r\n this.listeners.set(event as string, new Set());\r\n }\r\n this.listeners.get(event as string)!.add(handler as TexyEventHandler<unknown>);\r\n }\r\n\r\n off<K extends keyof EventMap>(event: K, handler: TexyEventHandler<EventMap[K]>): void {\r\n this.listeners.get(event as string)?.delete(handler as TexyEventHandler<unknown>);\r\n }\r\n\r\n emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void {\r\n this.listeners.get(event as string)?.forEach((handler) => {\r\n try {\r\n handler(data);\r\n } catch (err) {\r\n console.error(`[TexyEditor] Event handler error for \"${event as string}\":`, err);\r\n }\r\n });\r\n }\r\n\r\n removeAll(): void {\r\n this.listeners.clear();\r\n }\r\n}\r\n","export interface UndoState {\r\n value: string;\r\n cursorStart: number;\r\n cursorEnd: number;\r\n}\r\n\r\nexport class UndoManager {\r\n private stack: UndoState[] = [];\r\n private pointer = -1;\r\n private maxSteps: number;\r\n\r\n constructor(maxSteps = 100) {\r\n this.maxSteps = maxSteps;\r\n }\r\n\r\n push(state: UndoState): void {\r\n // Discard any redo states after current pointer\r\n this.stack = this.stack.slice(0, this.pointer + 1);\r\n this.stack.push(state);\r\n\r\n // Enforce max limit\r\n if (this.stack.length > this.maxSteps) {\r\n this.stack.shift();\r\n }\r\n\r\n this.pointer = this.stack.length - 1;\r\n }\r\n\r\n undo(): UndoState | null {\r\n if (this.pointer <= 0) return null;\r\n this.pointer--;\r\n return this.stack[this.pointer];\r\n }\r\n\r\n redo(): UndoState | null {\r\n if (this.pointer >= this.stack.length - 1) return null;\r\n this.pointer++;\r\n return this.stack[this.pointer];\r\n }\r\n\r\n canUndo(): boolean {\r\n return this.pointer > 0;\r\n }\r\n\r\n canRedo(): boolean {\r\n return this.pointer < this.stack.length - 1;\r\n }\r\n\r\n clear(): void {\r\n this.stack = [];\r\n this.pointer = -1;\r\n }\r\n}\r\n","export type ShortcutHandler = () => void;\r\n\r\ninterface ShortcutBinding {\r\n key: string;\r\n ctrl: boolean;\r\n shift: boolean;\r\n alt: boolean;\r\n handler: ShortcutHandler;\r\n}\r\n\r\nconst DEFAULT_SHORTCUTS: Record<string, string> = {\r\n 'bold': 'Ctrl+B',\r\n 'italic': 'Ctrl+I',\r\n 'link': 'Ctrl+K',\r\n 'undo': 'Ctrl+Z',\r\n 'redo': 'Ctrl+Shift+Z',\r\n 'submit': 'Ctrl+S',\r\n 'fullscreen': 'F11',\r\n 'indent': 'Tab',\r\n 'unindent': 'Shift+Tab',\r\n};\r\n\r\nexport class KeyboardManager {\r\n private bindings: ShortcutBinding[] = [];\r\n private boundHandler: ((e: KeyboardEvent) => void) | null = null;\r\n\r\n constructor(\r\n private textarea: HTMLTextAreaElement,\r\n private customShortcuts?: Record<string, string>,\r\n ) {}\r\n\r\n register(actionName: string, handler: ShortcutHandler): void {\r\n const shortcutStr = this.customShortcuts?.[actionName] ?? DEFAULT_SHORTCUTS[actionName];\r\n if (!shortcutStr) return;\r\n\r\n const binding = this.parseShortcut(shortcutStr);\r\n if (binding) {\r\n binding.handler = handler;\r\n this.bindings.push(binding);\r\n }\r\n }\r\n\r\n attach(): void {\r\n this.boundHandler = (e: KeyboardEvent) => this.handleKeydown(e);\r\n this.textarea.addEventListener('keydown', this.boundHandler);\r\n }\r\n\r\n detach(): void {\r\n if (this.boundHandler) {\r\n this.textarea.removeEventListener('keydown', this.boundHandler);\r\n this.boundHandler = null;\r\n }\r\n this.bindings = [];\r\n }\r\n\r\n private handleKeydown(e: KeyboardEvent): void {\r\n for (const binding of this.bindings) {\r\n const ctrlMatch = e.ctrlKey === binding.ctrl || e.metaKey === binding.ctrl;\r\n const shiftMatch = e.shiftKey === binding.shift;\r\n const altMatch = e.altKey === binding.alt;\r\n const keyMatch = e.key.toLowerCase() === binding.key.toLowerCase();\r\n\r\n if (ctrlMatch && shiftMatch && altMatch && keyMatch) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n binding.handler();\r\n return;\r\n }\r\n }\r\n }\r\n\r\n private parseShortcut(str: string): ShortcutBinding | null {\r\n const parts = str.split('+').map((p) => p.trim());\r\n if (parts.length === 0) return null;\r\n\r\n return {\r\n key: parts[parts.length - 1],\r\n ctrl: parts.some((p) => p.toLowerCase() === 'ctrl'),\r\n shift: parts.some((p) => p.toLowerCase() === 'shift'),\r\n alt: parts.some((p) => p.toLowerCase() === 'alt'),\r\n handler: () => {},\r\n };\r\n }\r\n}\r\n","import type {\r\n ToolbarConfig,\r\n ToolbarItem,\r\n ToolbarGroup,\r\n ToolbarCustomButton,\r\n TexyEditorStrings,\r\n} from '../types';\r\n\r\n/** SVG icon paths for built-in toolbar buttons */\r\nconst ICONS: Record<string, string> = {\r\n bold: '<path d=\"M6 4h5a3 3 0 0 1 0 6H6zm0 6h6a3 3 0 0 1 0 6H6z\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"/>',\r\n italic: '<path d=\"M10 4h4M8 20h4M14 4l-4 16\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n deleted: '<path d=\"M6 12h12M7 6h10a2 2 0 0 1 0 4H7M7 14h10a2 2 0 0 1 0 4H7\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/>',\r\n inserted: '<path d=\"M6 18h12\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/><path d=\"M8 4v10M16 4v10\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/>',\r\n superscript: '<path d=\"M4 18l6-10 6 10M15 4h4l-4 5h4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n subscript: '<path d=\"M4 4l6 10 6-10M15 16h4l-4 5h4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n code: '<path d=\"M8 7l-4 5 4 5M16 7l4 5-4 5\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\r\n codeBlock: '<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><path d=\"M8 9l-2 3 2 3M16 9l2 3-2 3\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n heading1: '<path d=\"M4 6v12M12 6v12M4 12h8M17 8v10M15 8h4\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n heading2: '<path d=\"M4 6v12M12 6v12M4 12h8\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/><path d=\"M15 9a2 2 0 0 1 4 0c0 2-4 3-4 5h4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n heading3: '<path d=\"M4 6v12M12 6v12M4 12h8\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/><path d=\"M15 8h3l-2 3 2 0a2 2 0 0 1-3 2\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n heading4: '<path d=\"M4 6v12M12 6v12M4 12h8\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/><path d=\"M15 8v5h4M19 8v8\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n link: '<path d=\"M10 14a3.5 3.5 0 0 0 5-5l-1-1M14 10a3.5 3.5 0 0 0-5 5l1 1\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n image: '<rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><circle cx=\"8.5\" cy=\"10\" r=\"1.5\" fill=\"currentColor\"/><path d=\"M21 15l-5-5L5 19\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/>',\r\n ul: '<path d=\"M9 6h11M9 12h11M9 18h11\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/><circle cx=\"4.5\" cy=\"6\" r=\"1.5\" fill=\"currentColor\"/><circle cx=\"4.5\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"/><circle cx=\"4.5\" cy=\"18\" r=\"1.5\" fill=\"currentColor\"/>',\r\n ol: '<path d=\"M10 6h10M10 12h10M10 18h10\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/><text x=\"4\" y=\"8\" font-size=\"8\" fill=\"currentColor\" font-family=\"sans-serif\">1</text><text x=\"4\" y=\"14\" font-size=\"8\" fill=\"currentColor\" font-family=\"sans-serif\">2</text><text x=\"4\" y=\"20\" font-size=\"8\" fill=\"currentColor\" font-family=\"sans-serif\">3</text>',\r\n blockquote: '<path d=\"M6 10c0-3 2-5 5-5M13 10c0-3 2-5 5-5\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/><path d=\"M6 14c0 3 2 5 5 5M13 14c0 3 2 5 5 5\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n hr: '<path d=\"M3 12h18\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-dasharray=\"2 3\"/>',\r\n table: '<rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><path d=\"M3 10h18M3 16h18M10 4v16\" stroke=\"currentColor\" stroke-width=\"1.5\"/>',\r\n color: '<circle cx=\"12\" cy=\"12\" r=\"8\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"3\" fill=\"currentColor\"/>',\r\n symbol: '<text x=\"6\" y=\"17\" font-size=\"16\" fill=\"currentColor\" font-family=\"serif\">&#937;</text>',\r\n acronym: '<path d=\"M4 16h4l2-6 2 6h4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/><path d=\"M6 13h4\" stroke=\"currentColor\" stroke-width=\"1.5\"/><path d=\"M16 8a2 2 0 1 0 4 0 2 2 0 0 0-4 0\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/>',\r\n alignLeft: '<path d=\"M4 6h16M4 10h10M4 14h16M4 18h10\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>',\r\n alignRight: '<path d=\"M4 6h16M10 10h10M4 14h16M10 18h10\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>',\r\n alignCenter: '<path d=\"M4 6h16M7 10h10M4 14h16M7 18h10\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>',\r\n alignJustify: '<path d=\"M4 6h16M4 10h16M4 14h16M4 18h16\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>',\r\n indent: '<path d=\"M12 6h8M12 12h8M12 18h8M4 8l4 4-4 4\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\r\n unindent: '<path d=\"M12 6h8M12 12h8M12 18h8M8 8l-4 4 4 4\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\r\n undo: '<path d=\"M4 8h12a4 4 0 0 1 0 8H8\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/><path d=\"M7 5l-3 3 3 3\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\r\n redo: '<path d=\"M20 8H8a4 4 0 0 0 0 8h8\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/><path d=\"M17 5l3 3-3 3\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\r\n fullscreen: '<path d=\"M4 9V4h5M15 4h5v5M20 15v5h-5M9 20H4v-5\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\r\n preview: '<path d=\"M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"3\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/>',\r\n edit: '<path d=\"M14 3l3 3L7 16l-4 1 1-4L14 3z\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linejoin=\"round\"/>',\r\n splitView: '<rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><path d=\"M12 4v16\" stroke=\"currentColor\" stroke-width=\"1.5\"/>',\r\n upload: '<path d=\"M12 16V4M8 8l4-4 4 4\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4 14v4a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-4\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/>',\r\n};\r\n\r\nfunction createSvgIcon(name: string): string {\r\n const path = ICONS[name];\r\n if (!path) return '';\r\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" class=\"te-icon\">${path}</svg>`;\r\n}\r\n\r\nexport class ToolbarBuilder {\r\n private toolbar!: HTMLElement;\r\n private bottomBar!: HTMLElement;\r\n\r\n constructor(\r\n private strings: TexyEditorStrings,\r\n private actionHandler: (name: string) => void,\r\n ) {}\r\n\r\n build(config: ToolbarConfig): HTMLElement {\r\n this.toolbar = document.createElement('div');\r\n this.toolbar.className = 'te-toolbar';\r\n this.toolbar.setAttribute('role', 'toolbar');\r\n this.toolbar.setAttribute('aria-label', 'Editor toolbar');\r\n\r\n for (const item of config) {\r\n const el = this.renderItem(item);\r\n if (el) this.toolbar.appendChild(el);\r\n }\r\n\r\n return this.toolbar;\r\n }\r\n\r\n buildBottomBar(\r\n left: string[],\r\n rightEdit: string[],\r\n rightPreview: string[],\r\n ): HTMLElement {\r\n this.bottomBar = document.createElement('div');\r\n this.bottomBar.className = 'te-bottom-bar';\r\n\r\n // Left side (view tabs)\r\n const leftDiv = document.createElement('div');\r\n leftDiv.className = 'te-bottom-left';\r\n for (const name of left) {\r\n leftDiv.appendChild(this.createButton(name));\r\n }\r\n this.bottomBar.appendChild(leftDiv);\r\n\r\n // Right side\r\n const rightDiv = document.createElement('div');\r\n rightDiv.className = 'te-bottom-right';\r\n\r\n const editGroup = document.createElement('div');\r\n editGroup.className = 'te-bottom-right-edit';\r\n for (const name of rightEdit) {\r\n editGroup.appendChild(this.createButton(name));\r\n }\r\n rightDiv.appendChild(editGroup);\r\n\r\n const previewGroup = document.createElement('div');\r\n previewGroup.className = 'te-bottom-right-preview';\r\n previewGroup.style.display = 'none';\r\n for (const name of rightPreview) {\r\n previewGroup.appendChild(this.createButton(name));\r\n }\r\n rightDiv.appendChild(previewGroup);\r\n\r\n this.bottomBar.appendChild(rightDiv);\r\n return this.bottomBar;\r\n }\r\n\r\n private renderItem(item: ToolbarItem): HTMLElement | null {\r\n if (item === null) {\r\n return this.createSeparator();\r\n }\r\n\r\n if (typeof item === 'string') {\r\n return this.createButton(item);\r\n }\r\n\r\n if (this.isGroup(item)) {\r\n return this.createDropdown(item);\r\n }\r\n\r\n if (this.isCustomButton(item)) {\r\n return this.createCustomButton(item);\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private createButton(name: string): HTMLButtonElement {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className = `te-btn te-btn-${name}`;\r\n btn.setAttribute('data-action', name);\r\n\r\n const label = (this.strings as unknown as Record<string, string>)[name] ?? name;\r\n btn.setAttribute('aria-label', label);\r\n btn.setAttribute('title', label);\r\n\r\n const icon = createSvgIcon(name);\r\n if (icon) {\r\n btn.innerHTML = icon;\r\n } else {\r\n btn.textContent = label;\r\n }\r\n\r\n btn.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n this.actionHandler(name);\r\n });\r\n\r\n return btn;\r\n }\r\n\r\n private createCustomButton(config: ToolbarCustomButton): HTMLButtonElement {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className = `te-btn te-btn-custom te-btn-${config.name}`;\r\n btn.setAttribute('aria-label', config.label);\r\n btn.setAttribute('title', config.label);\r\n\r\n if (config.icon) {\r\n btn.innerHTML = config.icon;\r\n } else {\r\n btn.textContent = config.label;\r\n }\r\n\r\n btn.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n this.actionHandler(config.name);\r\n });\r\n\r\n return btn;\r\n }\r\n\r\n private createSeparator(): HTMLElement {\r\n const sep = document.createElement('span');\r\n sep.className = 'te-separator';\r\n sep.setAttribute('role', 'separator');\r\n sep.setAttribute('aria-orientation', 'vertical');\r\n return sep;\r\n }\r\n\r\n private createDropdown(group: ToolbarGroup): HTMLElement {\r\n const wrapper = document.createElement('div');\r\n wrapper.className = 'te-dropdown';\r\n\r\n const trigger = document.createElement('button');\r\n trigger.type = 'button';\r\n trigger.className = 'te-btn te-dropdown-trigger';\r\n trigger.setAttribute('aria-haspopup', 'true');\r\n trigger.setAttribute('aria-expanded', 'false');\r\n trigger.textContent = group.label ?? '...';\r\n\r\n const menu = document.createElement('div');\r\n menu.className = 'te-dropdown-menu';\r\n menu.setAttribute('role', 'menu');\r\n\r\n for (const itemName of group.items) {\r\n const menuItem = this.createButton(itemName);\r\n menuItem.setAttribute('role', 'menuitem');\r\n menu.appendChild(menuItem);\r\n }\r\n\r\n trigger.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n const isOpen = wrapper.classList.toggle('te-dropdown-open');\r\n trigger.setAttribute('aria-expanded', String(isOpen));\r\n });\r\n\r\n // Close on outside click\r\n document.addEventListener('click', () => {\r\n wrapper.classList.remove('te-dropdown-open');\r\n trigger.setAttribute('aria-expanded', 'false');\r\n });\r\n\r\n wrapper.appendChild(trigger);\r\n wrapper.appendChild(menu);\r\n return wrapper;\r\n }\r\n\r\n private isGroup(item: ToolbarItem): item is ToolbarGroup {\r\n return typeof item === 'object' && item !== null && 'type' in item && item.type === 'group';\r\n }\r\n\r\n private isCustomButton(item: ToolbarItem): item is ToolbarCustomButton {\r\n return typeof item === 'object' && item !== null && 'type' in item && item.type === 'button';\r\n }\r\n}\r\n","import type { TexyEditorStrings } from '../types';\r\n\r\nexport interface DialogConfig {\r\n title: string;\r\n width?: number;\r\n content: HTMLElement;\r\n onSubmit: () => void;\r\n onCancel?: () => void;\r\n}\r\n\r\n/**\r\n * Native <dialog> based modal window manager.\r\n * Replaces jQuery UI Dialog with zero dependencies.\r\n */\r\nexport class DialogManager {\r\n private openDialogs = new Map<string, HTMLDialogElement>();\r\n\r\n constructor(\r\n private container: HTMLElement,\r\n private strings: TexyEditorStrings,\r\n ) {}\r\n\r\n open(name: string, config: DialogConfig): HTMLDialogElement {\r\n // Close existing dialog with same name\r\n this.close(name);\r\n\r\n const dialog = document.createElement('dialog');\r\n dialog.className = 'te-dialog';\r\n if (config.width) {\r\n dialog.style.width = config.width + 'px';\r\n }\r\n\r\n // Header\r\n const header = document.createElement('div');\r\n header.className = 'te-dialog-header';\r\n\r\n const title = document.createElement('h3');\r\n title.className = 'te-dialog-title';\r\n title.textContent = config.title;\r\n header.appendChild(title);\r\n\r\n const closeBtn = document.createElement('button');\r\n closeBtn.type = 'button';\r\n closeBtn.className = 'te-dialog-close';\r\n closeBtn.setAttribute('aria-label', this.strings.close);\r\n closeBtn.innerHTML = '&times;';\r\n closeBtn.addEventListener('click', () => this.close(name));\r\n header.appendChild(closeBtn);\r\n\r\n dialog.appendChild(header);\r\n\r\n // Body\r\n const body = document.createElement('div');\r\n body.className = 'te-dialog-body';\r\n body.appendChild(config.content);\r\n dialog.appendChild(body);\r\n\r\n // Footer\r\n const footer = document.createElement('div');\r\n footer.className = 'te-dialog-footer';\r\n\r\n const cancelBtn = document.createElement('button');\r\n cancelBtn.type = 'button';\r\n cancelBtn.className = 'te-btn te-dialog-cancel';\r\n cancelBtn.textContent = this.strings.cancel;\r\n cancelBtn.addEventListener('click', () => {\r\n config.onCancel?.();\r\n this.close(name);\r\n });\r\n footer.appendChild(cancelBtn);\r\n\r\n const submitBtn = document.createElement('button');\r\n submitBtn.type = 'button';\r\n submitBtn.className = 'te-btn te-dialog-submit';\r\n submitBtn.textContent = this.strings.ok;\r\n submitBtn.addEventListener('click', () => {\r\n config.onSubmit();\r\n this.close(name);\r\n });\r\n footer.appendChild(submitBtn);\r\n\r\n dialog.appendChild(footer);\r\n\r\n // Esc key handler\r\n dialog.addEventListener('cancel', (e) => {\r\n e.preventDefault();\r\n config.onCancel?.();\r\n this.close(name);\r\n });\r\n\r\n this.container.appendChild(dialog);\r\n this.openDialogs.set(name, dialog);\r\n dialog.showModal();\r\n\r\n // Focus first input\r\n const firstInput = dialog.querySelector<HTMLInputElement>('input, select, textarea');\r\n firstInput?.focus();\r\n\r\n return dialog;\r\n }\r\n\r\n close(name: string): void {\r\n const dialog = this.openDialogs.get(name);\r\n if (dialog) {\r\n dialog.close();\r\n dialog.remove();\r\n this.openDialogs.delete(name);\r\n }\r\n }\r\n\r\n closeAll(): void {\r\n for (const [name] of this.openDialogs) {\r\n this.close(name);\r\n }\r\n }\r\n\r\n isOpen(name: string): boolean {\r\n return this.openDialogs.has(name);\r\n }\r\n}\r\n","import type { TexyParserOptions, TexyParserPlugin } from '../types';\r\n\r\n/**\r\n * Client-side Texy markup parser.\r\n * Converts Texy source text to HTML for live preview.\r\n * Supports plugin system for custom syntax extensions.\r\n */\r\nexport class TexyParser {\r\n private options: Required<TexyParserOptions>;\r\n private plugins: TexyParserPlugin[];\r\n\r\n constructor(options: TexyParserOptions = {}) {\r\n this.options = {\r\n rules: options.rules ?? [],\r\n plugins: options.plugins ?? [],\r\n enableTypography: options.enableTypography ?? true,\r\n enableAutolinks: options.enableAutolinks ?? true,\r\n };\r\n this.plugins = this.options.plugins;\r\n }\r\n\r\n /** Add a plugin at runtime */\r\n addPlugin(plugin: TexyParserPlugin): void {\r\n this.plugins.push(plugin);\r\n }\r\n\r\n /** Remove a plugin by name */\r\n removePlugin(name: string): void {\r\n this.plugins = this.plugins.filter((p) => p.name !== name);\r\n }\r\n\r\n /** Get registered plugins */\r\n getPlugins(): readonly TexyParserPlugin[] {\r\n return this.plugins;\r\n }\r\n\r\n parse(input: string): string {\r\n if (!input.trim()) return '';\r\n\r\n // Normalize line endings\r\n let text = input.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\r\n\r\n // Run plugin preprocessors\r\n for (const plugin of this.plugins) {\r\n if (plugin.preprocess) {\r\n text = plugin.preprocess(text);\r\n }\r\n }\r\n\r\n // Apply custom block rules (lowest priority number first)\r\n const blockRules = this.options.rules\r\n .filter((r) => r.block)\r\n .sort((a, b) => a.priority - b.priority);\r\n for (const rule of blockRules) {\r\n text = rule.block!(text);\r\n }\r\n\r\n // Process blocks\r\n let html = this.parseBlocks(text);\r\n\r\n // Run plugin postprocessors\r\n for (const plugin of this.plugins) {\r\n if (plugin.postprocess) {\r\n html = plugin.postprocess(html);\r\n }\r\n }\r\n\r\n return html;\r\n }\r\n\r\n // ── Block-level parsing ──────────────────────────────────\r\n\r\n private parseBlocks(text: string): string {\r\n const blocks: string[] = [];\r\n\r\n // Split into raw blocks by double newlines, but preserve special block structures\r\n const segments = this.splitBlockSegments(text);\r\n\r\n for (const segment of segments) {\r\n const trimmed = segment.trim();\r\n if (!trimmed) continue;\r\n\r\n const parsed =\r\n this.tryCommentBlock(trimmed) ??\r\n this.tryCodeBlock(trimmed) ??\r\n this.tryHtmlBlock(trimmed) ??\r\n this.tryDivBlock(trimmed) ??\r\n this.tryTextBlock(trimmed) ??\r\n this.tryTable(trimmed) ??\r\n this.tryHeading(trimmed) ??\r\n this.tryHorizontalRule(trimmed) ??\r\n this.tryBlockquote(trimmed) ??\r\n this.tryList(trimmed) ??\r\n this.tryParagraph(trimmed);\r\n\r\n if (parsed) blocks.push(parsed);\r\n }\r\n\r\n return blocks.join('\\n');\r\n }\r\n\r\n /**\r\n * Split text into block segments.\r\n * Respects /--...\\-- block boundaries.\r\n */\r\n private splitBlockSegments(text: string): string[] {\r\n const segments: string[] = [];\r\n const lines = text.split('\\n');\r\n let current: string[] = [];\r\n let inBlock = false;\r\n\r\n for (const line of lines) {\r\n if (!inBlock && /^\\/--/.test(line)) {\r\n // Start of a special block — flush current paragraph\r\n if (current.length > 0) {\r\n const joined = current.join('\\n');\r\n // Split paragraph-level segments by double newlines\r\n segments.push(...this.splitParagraphs(joined));\r\n current = [];\r\n }\r\n inBlock = true;\r\n current.push(line);\r\n } else if (inBlock && /^\\\\--/.test(line)) {\r\n current.push(line);\r\n segments.push(current.join('\\n'));\r\n current = [];\r\n inBlock = false;\r\n } else if (inBlock) {\r\n current.push(line);\r\n } else {\r\n current.push(line);\r\n }\r\n }\r\n\r\n // Flush remaining\r\n if (current.length > 0) {\r\n const joined = current.join('\\n');\r\n if (inBlock) {\r\n // Unclosed block — treat as-is\r\n segments.push(joined);\r\n } else {\r\n segments.push(...this.splitParagraphs(joined));\r\n }\r\n }\r\n\r\n return segments;\r\n }\r\n\r\n private splitParagraphs(text: string): string[] {\r\n return text.split(/\\n{2,}/).filter((s) => s.trim());\r\n }\r\n\r\n // ── Comment block: /--comment ... \\-- ─────────────────────\r\n\r\n private tryCommentBlock(text: string): string | null {\r\n const match = text.match(/^\\/--comment[ \\t]*\\n([\\s\\S]*?)(?:\\n\\\\--|$)/);\r\n if (!match) return null;\r\n // Comments produce no output\r\n return '<!-- comment -->';\r\n }\r\n\r\n // ── Code block: /--code [lang] ... \\-- ────────────────────\r\n\r\n private tryCodeBlock(text: string): string | null {\r\n const match = text.match(/^\\/--code[ \\t]*(\\S*)[ \\t]*\\n([\\s\\S]*?)(?:\\n\\\\--|$)/);\r\n if (!match) return null;\r\n\r\n const lang = match[1];\r\n const code = this.escapeHtml(match[2]);\r\n const langAttr = lang ? ` class=\"language-${this.escapeHtml(lang)}\"` : '';\r\n return `<pre><code${langAttr}>${code}</code></pre>`;\r\n }\r\n\r\n // ── HTML block: /--html ... \\-- ───────────────────────────\r\n\r\n private tryHtmlBlock(text: string): string | null {\r\n const match = text.match(/^\\/--html[ \\t]*\\n([\\s\\S]*?)(?:\\n\\\\--|$)/);\r\n if (!match) return null;\r\n return match[1]; // Pass HTML through as-is\r\n }\r\n\r\n // ── Div block: /--div [modifier] ... \\-- ──────────────────\r\n\r\n private tryDivBlock(text: string): string | null {\r\n const match = text.match(/^\\/--div[ \\t]*(.*?)[ \\t]*\\n([\\s\\S]*?)(?:\\n\\\\--|$)/);\r\n if (!match) return null;\r\n\r\n const modifier = match[1];\r\n const content = this.parseBlocks(match[2]);\r\n const attrs = modifier ? this.parseModifierAttrs(modifier) : '';\r\n return `<div${attrs}>\\n${content}\\n</div>`;\r\n }\r\n\r\n // ── Text block: /--text ... \\-- ───────────────────────────\r\n\r\n private tryTextBlock(text: string): string | null {\r\n const match = text.match(/^\\/--text[ \\t]*\\n([\\s\\S]*?)(?:\\n\\\\--|$)/);\r\n if (!match) return null;\r\n return `<pre>${this.escapeHtml(match[1])}</pre>`;\r\n }\r\n\r\n // ── Table ─────────────────────────────────────────────────\r\n\r\n private tryTable(text: string): string | null {\r\n const lines = text.split('\\n');\r\n if (!lines[0].match(/^\\|/)) return null;\r\n\r\n // Verify all lines start with | or are separator rows\r\n const isTableLine = (line: string) =>\r\n /^\\|/.test(line.trim()) || /^\\|[-=]+/.test(line.trim());\r\n if (!lines.every((l) => !l.trim() || isTableLine(l))) return null;\r\n\r\n let html = '<table>\\n';\r\n let inHead = false;\r\n let headClosed = false;\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed) continue;\r\n\r\n // Separator row: |-------- or |========\r\n if (/^\\|[-=]+/.test(trimmed)) {\r\n if (inHead && !headClosed) {\r\n html += '</thead>\\n<tbody>\\n';\r\n headClosed = true;\r\n }\r\n continue;\r\n }\r\n\r\n // Parse cells\r\n const cells = this.parseTableRow(trimmed);\r\n if (!cells) continue;\r\n\r\n // Check if any cell is a header cell (starts with *)\r\n const hasHeaderCells = cells.some((c) => c.isHeader);\r\n\r\n if (hasHeaderCells && !headClosed && !inHead) {\r\n html += '<thead>\\n';\r\n inHead = true;\r\n }\r\n\r\n html += '<tr>';\r\n for (const cell of cells) {\r\n const tag = cell.isHeader ? 'th' : 'td';\r\n const content = this.parseInline(cell.content.trim());\r\n html += `<${tag}>${content}</${tag}>`;\r\n }\r\n html += '</tr>\\n';\r\n }\r\n\r\n if (inHead && !headClosed) {\r\n html += '</thead>\\n';\r\n }\r\n if (headClosed) {\r\n html += '</tbody>\\n';\r\n }\r\n\r\n html += '</table>';\r\n return html;\r\n }\r\n\r\n private parseTableRow(line: string): { content: string; isHeader: boolean }[] | null {\r\n // Remove leading and trailing |\r\n let row = line.trim();\r\n if (!row.startsWith('|')) return null;\r\n row = row.substring(1);\r\n if (row.endsWith('|')) row = row.substring(0, row.length - 1);\r\n\r\n const cells = row.split('|');\r\n return cells.map((cell) => {\r\n const trimmed = cell.trim();\r\n if (trimmed.startsWith('*')) {\r\n return { content: trimmed.substring(1).trim(), isHeader: true };\r\n }\r\n return { content: trimmed, isHeader: false };\r\n });\r\n }\r\n\r\n // ── Heading (underline style) ─────────────────────────────\r\n\r\n private tryHeading(text: string): string | null {\r\n const lines = text.split('\\n');\r\n const headingChars: Record<string, number> = { '#': 1, '*': 2, '=': 3, '-': 4 };\r\n\r\n // Check for \"surrounded\" heading style: === heading === (single line)\r\n const surroundMatch = lines[0].match(/^(#{3,}|\\*{3,}|={3,}|-{3,})\\s+(.+?)\\s+\\1\\s*$/);\r\n if (surroundMatch) {\r\n const char = surroundMatch[1][0];\r\n const level = headingChars[char];\r\n if (level) {\r\n const content = this.parseInline(surroundMatch[2]);\r\n const remaining = lines.slice(1).join('\\n').trim();\r\n let result = `<h${level}>${content}</h${level}>`;\r\n if (remaining) result += '\\n' + this.parseBlocks(remaining);\r\n return result;\r\n }\r\n }\r\n\r\n // Standard underline heading (needs at least 2 lines)\r\n if (lines.length >= 2) {\r\n const headingText = lines[0];\r\n const underline = lines[1];\r\n\r\n const underlineMatch = underline.match(/^(#{3,}|\\*{3,}|={3,}|-{3,})\\s*$/);\r\n if (underlineMatch && headingText.trim()) {\r\n const char = underlineMatch[1][0];\r\n const level = headingChars[char];\r\n if (level) {\r\n const content = this.parseInline(headingText.trim());\r\n const remaining = lines.slice(2).join('\\n').trim();\r\n let result = `<h${level}>${content}</h${level}>`;\r\n if (remaining) result += '\\n' + this.parseBlocks(remaining);\r\n return result;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n // ── Horizontal rule ───────────────────────────────────────\r\n\r\n private tryHorizontalRule(text: string): string | null {\r\n if (/^-{3,}\\s*$/.test(text.trim()) && !text.includes('\\n')) {\r\n return '<hr>';\r\n }\r\n if (/^\\*{3,}\\s*$/.test(text.trim()) && !text.includes('\\n')) {\r\n return '<hr>';\r\n }\r\n return null;\r\n }\r\n\r\n // ── Blockquote ────────────────────────────────────────────\r\n\r\n private tryBlockquote(text: string): string | null {\r\n const lines = text.split('\\n');\r\n if (!lines[0].match(/^>\\s/)) return null;\r\n\r\n // All lines should start with >\r\n const allQuoted = lines.every((l) => /^>\\s?/.test(l) || !l.trim());\r\n if (!allQuoted) return null;\r\n\r\n const inner = lines\r\n .map((l) => l.replace(/^>\\s?/, ''))\r\n .join('\\n');\r\n\r\n // Recursively parse inner content (nested blockquotes, paragraphs)\r\n const content = this.parseBlocks(inner);\r\n return `<blockquote>\\n${content}\\n</blockquote>`;\r\n }\r\n\r\n // ── Lists ─────────────────────────────────────────────────\r\n\r\n private tryList(text: string): string | null {\r\n const lines = text.split('\\n');\r\n\r\n // Unordered list: - item, * item, + item\r\n if (/^[-*+]\\s/.test(lines[0])) {\r\n return this.parseListItems(lines, /^[-*+]\\s/, 'ul');\r\n }\r\n\r\n // Ordered list: 1) item, a) item, A) item, I) item, i) item\r\n if (/^(\\d+[).]|[a-z][).]|[A-Z][).]|[IVXLCDM]+[).]|[ivxlcdm]+[).])\\s/.test(lines[0])) {\r\n const firstItem = lines[0];\r\n let type = '';\r\n if (/^\\d/.test(firstItem)) type = '';\r\n else if (/^[ivxlcdm]+\\)/i.test(firstItem) && /^[IV]/.test(firstItem)) type = ' type=\"I\"';\r\n else if (/^[ivxlcdm]+\\)/.test(firstItem)) type = ' type=\"i\"';\r\n else if (/^[A-Z]\\)/.test(firstItem)) type = ' type=\"A\"';\r\n else if (/^[a-z]\\)/.test(firstItem)) type = ' type=\"a\"';\r\n return this.parseListItems(lines, /^(?:\\d+[).]|[a-zA-Z][).]|[IVXLCDM]+[).]|[ivxlcdm]+[).])\\s/, 'ol', type);\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private parseListItems(lines: string[], bulletPattern: RegExp, tag: string, attrs = ''): string {\r\n const items: string[] = [];\r\n let currentItem: string[] = [];\r\n\r\n for (const line of lines) {\r\n if (bulletPattern.test(line)) {\r\n if (currentItem.length > 0) {\r\n items.push(currentItem.join('\\n'));\r\n }\r\n currentItem = [line.replace(bulletPattern, '')];\r\n } else if (/^\\s+/.test(line) && currentItem.length > 0) {\r\n // Continuation line (indented)\r\n currentItem.push(line.replace(/^\\s+/, ''));\r\n } else if (!line.trim() && currentItem.length > 0) {\r\n currentItem.push('');\r\n } else {\r\n currentItem.push(line);\r\n }\r\n }\r\n if (currentItem.length > 0) {\r\n items.push(currentItem.join('\\n'));\r\n }\r\n\r\n let html = `<${tag}${attrs}>\\n`;\r\n for (const item of items) {\r\n // Check for nested list\r\n const trimmed = item.trim();\r\n const nestedList = this.tryList(trimmed);\r\n if (nestedList && trimmed !== item.trim()) {\r\n html += `<li>${nestedList}</li>\\n`;\r\n } else {\r\n html += `<li>${this.parseInline(trimmed)}</li>\\n`;\r\n }\r\n }\r\n html += `</${tag}>`;\r\n return html;\r\n }\r\n\r\n // ── Paragraph ─────────────────────────────────────────────\r\n\r\n private tryParagraph(text: string): string {\r\n // Check for paragraph modifier: .<> or .< or .> or .=\r\n const modifierMatch = text.match(/^\\.([\\<\\>\\=]+)\\n([\\s\\S]+)$/);\r\n if (modifierMatch) {\r\n const align = this.parseAlignModifier(modifierMatch[1]);\r\n const content = this.parseInline(modifierMatch[2].trim());\r\n return `<p${align}>${content}</p>`;\r\n }\r\n\r\n const inline = this.parseInline(text);\r\n return `<p>${inline}</p>`;\r\n }\r\n\r\n private parseAlignModifier(mod: string): string {\r\n switch (mod) {\r\n case '<': return ' style=\"text-align:left\"';\r\n case '>': return ' style=\"text-align:right\"';\r\n case '<>': return ' style=\"text-align:center\"';\r\n case '=': return ' style=\"text-align:justify\"';\r\n default: return '';\r\n }\r\n }\r\n\r\n // ── Inline parsing ────────────────────────────────────────\r\n\r\n parseInline(text: string): string {\r\n // Placeholder maps for protected content\r\n const placeholders = new Map<string, string>();\r\n let pIdx = 0;\r\n const ph = (content: string): string => {\r\n const key = `\\x00PH${pIdx++}\\x00`;\r\n placeholders.set(key, content);\r\n return key;\r\n };\r\n\r\n let src = text;\r\n\r\n // 1. NoTexy zones: ''text'' — extract first to protect content\r\n src = src.replace(/''(.+?)''/g, (_m, content) => ph(content));\r\n\r\n // 2. Inline code: `code` — extract to protect from further parsing\r\n src = src.replace(/`([^`]+)`/g, (_m, content) => ph(`<code>${this.escapeHtml(content)}</code>`));\r\n\r\n // 3. Images: [* src .(alt) align] — extract before italic (* conflicts)\r\n src = src.replace(\r\n /\\[\\*\\s+(\\S+?)(?:\\s+\\.\\(([^)]*)\\))?\\s*([<>*]?)\\s*\\]/g,\r\n (_m, imgSrc, alt, align) => {\r\n let style = '';\r\n if (align === '<') style = ' style=\"float:left\"';\r\n else if (align === '>') style = ' style=\"float:right\"';\r\n const altAttr = alt ? ` alt=\"${this.escapeHtml(alt)}\"` : ' alt=\"\"';\r\n return ph(`<img src=\"${this.escapeHtml(imgSrc)}\"${altAttr}${style}>`);\r\n },\r\n );\r\n\r\n // 4. Apply custom inline rules (on raw text)\r\n const inlineRules = this.options.rules\r\n .filter((r) => r.inline)\r\n .sort((a, b) => a.priority - b.priority);\r\n for (const rule of inlineRules) {\r\n src = rule.inline!(src);\r\n }\r\n\r\n // 4b. Run plugin inline processors (with access to placeholder function)\r\n for (const plugin of this.plugins) {\r\n if (plugin.processInline) {\r\n src = plugin.processInline(src, ph);\r\n }\r\n }\r\n\r\n // 5. Links: \"text\":URL — extract before HTML escaping (quotes are significant)\r\n src = src.replace(\r\n /\"([^\"]+?)\":((?:https?:\\/\\/|ftp:\\/\\/|mailto:)\\S+)/g,\r\n (_m, linkText, url) => ph(`<a href=\"${this.escapeHtml(url)}\">${this.escapeHtml(linkText)}</a>`),\r\n );\r\n // Links with relative URLs: \"text\":path\r\n src = src.replace(\r\n /\"([^\"]+?)\":(\\S+)/g,\r\n (_m, linkText, url) => ph(`<a href=\"${this.escapeHtml(url)}\">${this.escapeHtml(linkText)}</a>`),\r\n );\r\n\r\n // 6. Acronyms: word((title)) — extract before HTML escaping\r\n src = src.replace(\r\n /(\\w+)\\(\\(([^)]+)\\)\\)/g,\r\n (_m, word, title) => ph(`<abbr title=\"${this.escapeHtml(title)}\">${this.escapeHtml(word)}</abbr>`),\r\n );\r\n\r\n // 7. Phrase with modifier: \"text\" .{style}\r\n src = src.replace(\r\n /\"(.+?)\"\\s*\\.\\{([^}]+)\\}/g,\r\n (_m, content, style) => ph(`<span style=\"${this.escapeHtml(style)}\">${this.escapeHtml(content)}</span>`),\r\n );\r\n // Phrase with class modifier: \"text\" .[class]\r\n src = src.replace(\r\n /\"(.+?)\"\\s*\\.\\[([^\\]]+)\\]/g,\r\n (_m, content, cls) => ph(`<span class=\"${this.escapeHtml(cls)}\">${this.escapeHtml(content)}</span>`),\r\n );\r\n\r\n // 8. Typography (apply to raw text before HTML escaping)\r\n if (this.options.enableTypography) {\r\n src = this.applyTypography(src);\r\n }\r\n\r\n // 9. Now escape remaining HTML\r\n src = this.escapeHtmlPreservingPlaceholders(src, placeholders);\r\n\r\n // 10. Inline phrases (on escaped text)\r\n // Bold: **text**\r\n src = src.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\r\n // Italic: *text* (not inside **)\r\n src = src.replace(/(?<!\\*)\\*([^*]+?)\\*(?!\\*)/g, '<em>$1</em>');\r\n // Deleted: --text--\r\n src = src.replace(/--(.+?)--/g, '<del>$1</del>');\r\n // Inserted: ++text++\r\n src = src.replace(/\\+\\+(.+?)\\+\\+/g, '<ins>$1</ins>');\r\n // Superscript: ^^text^^\r\n src = src.replace(/\\^\\^(.+?)\\^\\^/g, '<sup>$1</sup>');\r\n // Subscript: __text__\r\n src = src.replace(/__(.+?)__/g, '<sub>$1</sub>');\r\n // Quoted: >>text<<\r\n src = src.replace(/&gt;&gt;(.+?)&lt;&lt;/g, '<q>$1</q>');\r\n\r\n // 11. Auto-links (bare URLs, on escaped text)\r\n if (this.options.enableAutolinks) {\r\n src = src.replace(\r\n /(?<![&\"=\\/])(?:https?:\\/\\/|www\\.)[^\\s<>&]+/g,\r\n (url) => {\r\n const href = url.startsWith('www.') ? `https://${url}` : url;\r\n return `<a href=\"${href}\">${url}</a>`;\r\n },\r\n );\r\n }\r\n\r\n // 12. Line breaks within paragraphs\r\n src = src.replace(/\\n/g, '<br>\\n');\r\n\r\n // 13. Restore all placeholders\r\n for (const [key, value] of placeholders) {\r\n src = src.replace(key, value);\r\n }\r\n\r\n return src;\r\n }\r\n\r\n private escapeHtmlPreservingPlaceholders(text: string, placeholders: Map<string, string>): string {\r\n // Split on placeholders, escape only non-placeholder parts\r\n const parts: string[] = [];\r\n let remaining = text;\r\n\r\n while (remaining.length > 0) {\r\n const phStart = remaining.indexOf('\\x00PH');\r\n if (phStart === -1) {\r\n parts.push(this.escapeHtml(remaining));\r\n break;\r\n }\r\n\r\n // Escape text before placeholder\r\n if (phStart > 0) {\r\n parts.push(this.escapeHtml(remaining.substring(0, phStart)));\r\n }\r\n\r\n // Find end of placeholder\r\n const phEnd = remaining.indexOf('\\x00', phStart + 1);\r\n if (phEnd === -1) {\r\n parts.push(this.escapeHtml(remaining.substring(phStart)));\r\n break;\r\n }\r\n\r\n const phKey = remaining.substring(phStart, phEnd + 1);\r\n if (placeholders.has(phKey)) {\r\n parts.push(phKey); // Keep placeholder as-is\r\n } else {\r\n parts.push(this.escapeHtml(remaining.substring(phStart, phEnd + 1)));\r\n }\r\n remaining = remaining.substring(phEnd + 1);\r\n }\r\n\r\n return parts.join('');\r\n }\r\n\r\n\r\n // ── Typography ────────────────────────────────────────────\r\n\r\n private applyTypography(text: string): string {\r\n // Typography runs on raw text (before HTML escaping)\r\n // Order matters — longer patterns first\r\n\r\n // Arrows (raw chars, not entities)\r\n text = text.replace(/<->/g, '\\u2194'); // <->\r\n text = text.replace(/<=>/g, '\\u21D4'); // <=>\r\n text = text.replace(/-->/g, '\\u2192'); // -->\r\n text = text.replace(/<--/g, '\\u2190'); // <--\r\n text = text.replace(/==>/g, '\\u21D2'); // ==>\r\n text = text.replace(/<== /g, '\\u21D0 '); // <==\r\n\r\n // Em dash: --- (must be before en dash)\r\n text = text.replace(/---/g, '\\u2014');\r\n\r\n // En dash: -- (between words/numbers or with spaces)\r\n text = text.replace(/(\\w)--(\\w)/g, '$1\\u2013$2');\r\n text = text.replace(/\\s--\\s/g, ' \\u2013 ');\r\n\r\n // Ellipsis: ...\r\n text = text.replace(/\\.\\.\\./g, '\\u2026');\r\n\r\n // Symbols\r\n text = text.replace(/\\(tm\\)/gi, '\\u2122');\r\n text = text.replace(/\\(c\\)/gi, '\\u00A9');\r\n text = text.replace(/\\(r\\)/gi, '\\u00AE');\r\n\r\n // Multiplication sign: 10x20 or 10 x 20\r\n text = text.replace(/(\\d)\\s*x\\s*(\\d)/g, '$1\\u00D7$2');\r\n\r\n // Non-breaking space after single-char prepositions (Czech typography)\r\n text = text.replace(/\\b([ksvzuoiaKSVZUOIA]) /g, '$1\\u00A0');\r\n\r\n return text;\r\n }\r\n\r\n // ── Modifier parsing ──────────────────────────────────────\r\n\r\n private parseModifierAttrs(modifier: string): string {\r\n const attrs: string[] = [];\r\n\r\n // .{style} — inline CSS\r\n const styleMatch = modifier.match(/\\{([^}]+)\\}/);\r\n if (styleMatch) attrs.push(`style=\"${this.escapeHtml(styleMatch[1])}\"`);\r\n\r\n // .[class] — CSS class\r\n const classMatch = modifier.match(/\\[([^\\]]+)\\]/);\r\n if (classMatch) attrs.push(`class=\"${this.escapeHtml(classMatch[1])}\"`);\r\n\r\n // .#id — element ID\r\n const idMatch = modifier.match(/#([a-zA-Z][\\w-]*)/);\r\n if (idMatch) attrs.push(`id=\"${this.escapeHtml(idMatch[1])}\"`);\r\n\r\n // .(title) — title attribute\r\n const titleMatch = modifier.match(/\\(([^)]+)\\)/);\r\n if (titleMatch) attrs.push(`title=\"${this.escapeHtml(titleMatch[1])}\"`);\r\n\r\n return attrs.length > 0 ? ' ' + attrs.join(' ') : '';\r\n }\r\n\r\n // ── Utilities ─────────────────────────────────────────────\r\n\r\n private escapeHtml(text: string): string {\r\n return text\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;');\r\n }\r\n}\r\n","import type { TexyParserPlugin } from '../../types';\r\n\r\nexport interface YouTubePluginOptions {\r\n /** Iframe width (default: 560) */\r\n width?: number;\r\n /** Iframe height (default: 315) */\r\n height?: number;\r\n /** Allow fullscreen (default: true) */\r\n allowFullscreen?: boolean;\r\n /** Responsive wrapper CSS class */\r\n wrapperClass?: string;\r\n}\r\n\r\n/**\r\n * YouTube embed plugin for TexyParser.\r\n *\r\n * Supports Texy image syntax with youtube: prefix:\r\n * [* youtube:VIDEO_ID *]\r\n *\r\n * Also converts YouTube URLs in image syntax:\r\n * [* https://www.youtube.com/watch?v=ID *]\r\n * [* https://youtu.be/ID *]\r\n * [* https://www.youtube.com/shorts/ID *]\r\n */\r\nexport function youtubePlugin(options: YouTubePluginOptions = {}): TexyParserPlugin {\r\n const width = options.width ?? 560;\r\n const height = options.height ?? 315;\r\n const allowFs = options.allowFullscreen !== false;\r\n const wrapperClass = options.wrapperClass ?? 'texy-youtube';\r\n\r\n return {\r\n name: 'youtube',\r\n\r\n preprocess(text: string): string {\r\n // Convert [* youtube:ID *] to placeholder\r\n text = text.replace(\r\n /\\[\\*\\s+youtube:([a-zA-Z0-9_-]+)\\s*\\*?\\]/g,\r\n `{{youtube:$1}}`,\r\n );\r\n\r\n // Convert [* YOUTUBE_URL *] to placeholder (full URLs)\r\n text = text.replace(\r\n /\\[\\*\\s+(https?:\\/\\/(?:www\\.)?youtube\\.com\\/watch\\?v=([a-zA-Z0-9_-]+)[^\\s]*)\\s*\\*?\\]/g,\r\n (_m, _url, id) => `{{youtube:${id}}}`,\r\n );\r\n\r\n // YouTube shorts\r\n text = text.replace(\r\n /\\[\\*\\s+https?:\\/\\/(?:www\\.)?youtube\\.com\\/shorts\\/([a-zA-Z0-9_-]+)[^\\s]*\\s*\\*?\\]/g,\r\n `{{youtube:$1}}`,\r\n );\r\n\r\n // youtu.be short URLs\r\n text = text.replace(\r\n /\\[\\*\\s+https?:\\/\\/youtu\\.be\\/([a-zA-Z0-9_-]+)[^\\s]*\\s*\\*?\\]/g,\r\n `{{youtube:$1}}`,\r\n );\r\n\r\n return text;\r\n },\r\n\r\n processInline(text: string, placeholder: (html: string) => string): string {\r\n return text.replace(/\\{\\{youtube:([a-zA-Z0-9_-]+)\\}\\}/g, (_m, id) => {\r\n const fsAttr = allowFs ? ' allowfullscreen' : '';\r\n const iframe = `<div class=\"${wrapperClass}\"><iframe width=\"${width}\" height=\"${height}\" src=\"https://www.youtube.com/embed/${id}\" frameborder=\"0\"${fsAttr}></iframe></div>`;\r\n return placeholder(iframe);\r\n });\r\n },\r\n };\r\n}\r\n","import type { TexyParserPlugin } from '../../types';\r\n\r\nexport interface SmileyPluginOptions {\r\n /** Base URL for smiley images (required) */\r\n baseUrl: string;\r\n /** Image format extension (default: 'gif') */\r\n format?: string;\r\n /** Optional ARIA labels map: smiley ID → label text */\r\n ariaLabels?: Record<string, string>;\r\n /** CSS class for smiley images */\r\n className?: string;\r\n}\r\n\r\n/**\r\n * Smiley/emoticon plugin for TexyParser.\r\n *\r\n * Converts *ID* syntax to smiley images:\r\n * *123* → <img src=\"baseUrl/123.gif\" alt=\"smiley\" class=\"smiley\">\r\n */\r\nexport function smileyPlugin(options: SmileyPluginOptions): TexyParserPlugin {\r\n const baseUrl = options.baseUrl.replace(/\\/$/, '');\r\n const format = options.format ?? 'gif';\r\n const ariaLabels = options.ariaLabels ?? {};\r\n const className = options.className ?? 'smiley';\r\n\r\n return {\r\n name: 'smiley',\r\n\r\n processInline(text: string, placeholder: (html: string) => string): string {\r\n // Match *ID* where ID is 1-6 digits, but NOT inside ** (bold markers)\r\n return text.replace(\r\n /(?<!\\*)\\*(\\d{1,6})\\*(?!\\*)/g,\r\n (_m, id) => {\r\n const label = ariaLabels[id] ?? 'smiley';\r\n const img = `<img src=\"${baseUrl}/${id}.${format}\" alt=\"${label}\" class=\"${className}\">`;\r\n return placeholder(img);\r\n },\r\n );\r\n },\r\n };\r\n}\r\n","import type { TexyParserPlugin } from '../../types';\r\n\r\nexport interface LinkRedirectPluginOptions {\r\n /** Redirect service base URL (required) */\r\n redirectUrl: string;\r\n /** Domains to exclude from redirect (e.g., own domain) */\r\n excludeDomains?: string[];\r\n /** Add target=\"_blank\" to external links (default: true) */\r\n targetBlank?: boolean;\r\n /** Add rel=\"noopener noreferrer\" (default: true) */\r\n noopener?: boolean;\r\n}\r\n\r\n/**\r\n * Link redirect plugin for TexyParser.\r\n *\r\n * Rewrites external links to go through a redirect service,\r\n * useful for tracking and safety. Adds target=\"_blank\" to external links.\r\n */\r\nexport function linkRedirectPlugin(options: LinkRedirectPluginOptions): TexyParserPlugin {\r\n const redirectUrl = options.redirectUrl;\r\n const excludeDomains = options.excludeDomains ?? [];\r\n const targetBlank = options.targetBlank !== false;\r\n const noopener = options.noopener !== false;\r\n\r\n return {\r\n name: 'link-redirect',\r\n\r\n postprocess(html: string): string {\r\n return html.replace(\r\n /<a\\s+href=\"(https?:\\/\\/[^\"]+)\"/g,\r\n (_m, url) => {\r\n // Check if domain should be excluded\r\n try {\r\n const hostname = new URL(url).hostname;\r\n if (excludeDomains.some((d) => hostname === d || hostname.endsWith('.' + d))) {\r\n return _m;\r\n }\r\n } catch {\r\n return _m;\r\n }\r\n\r\n const encodedUrl = encodeURIComponent(url);\r\n const attrs: string[] = [`href=\"${redirectUrl}?url=${encodedUrl}\"`];\r\n if (targetBlank) attrs.push('target=\"_blank\"');\r\n if (noopener) attrs.push('rel=\"noopener noreferrer\"');\r\n\r\n return `<a ${attrs.join(' ')}`;\r\n },\r\n );\r\n },\r\n };\r\n}\r\n","import type { TexyParserPlugin } from '../../types';\r\n\r\n/**\r\n * BBCode plugin for TexyParser.\r\n *\r\n * Converts common BBCode tags to HTML:\r\n * [b]text[/b] → <strong>text</strong>\r\n * [i]text[/i] → <em>text</em>\r\n * [u]text[/u] → <u>text</u>\r\n * [s]text[/s] → <del>text</del>\r\n * [url=...]text[/url] → <a href=\"...\">text</a>\r\n * [color=...]text[/color] → <span style=\"color:...\">text</span>\r\n *\r\n * Useful for forums and chat applications that support BBCode alongside Texy.\r\n */\r\nexport function bbcodePlugin(): TexyParserPlugin {\r\n return {\r\n name: 'bbcode',\r\n\r\n processInline(text: string, placeholder: (html: string) => string): string {\r\n // [b]text[/b]\r\n text = text.replace(/\\[b\\]([\\s\\S]*?)\\[\\/b\\]/gi, (_m, content) =>\r\n placeholder(`<strong>${content}</strong>`),\r\n );\r\n\r\n // [i]text[/i]\r\n text = text.replace(/\\[i\\]([\\s\\S]*?)\\[\\/i\\]/gi, (_m, content) =>\r\n placeholder(`<em>${content}</em>`),\r\n );\r\n\r\n // [u]text[/u]\r\n text = text.replace(/\\[u\\]([\\s\\S]*?)\\[\\/u\\]/gi, (_m, content) =>\r\n placeholder(`<u>${content}</u>`),\r\n );\r\n\r\n // [s]text[/s]\r\n text = text.replace(/\\[s\\]([\\s\\S]*?)\\[\\/s\\]/gi, (_m, content) =>\r\n placeholder(`<del>${content}</del>`),\r\n );\r\n\r\n // [url=URL]text[/url]\r\n text = text.replace(\r\n /\\[url=([^\\]]+)\\]([\\s\\S]*?)\\[\\/url\\]/gi,\r\n (_m, url, content) => placeholder(`<a href=\"${url}\">${content}</a>`),\r\n );\r\n\r\n // [color=COLOR]text[/color]\r\n text = text.replace(\r\n /\\[color=([^\\]]+)\\]([\\s\\S]*?)\\[\\/color\\]/gi,\r\n (_m, color, content) => placeholder(`<span style=\"color:${color}\">${content}</span>`),\r\n );\r\n\r\n return text;\r\n },\r\n };\r\n}\r\n","import type { TexyParserPlugin } from '../../types';\r\n\r\nexport interface ImageEmbedPluginOptions {\r\n /** Max width for embedded images (default: '300px') */\r\n maxWidth?: string;\r\n /** CSS class for embedded images */\r\n className?: string;\r\n /** Enable linked images: \"[* img *]\":URL syntax (default: true) */\r\n enableLinkedImages?: boolean;\r\n}\r\n\r\n/**\r\n * Enhanced image embed plugin for TexyParser.\r\n *\r\n * Handles external image URLs in Texy image syntax:\r\n * [* https://example.com/photo.jpg *]\r\n * [* https://example.com/photo.jpg .(alt text) *]\r\n *\r\n * Also supports linked images:\r\n * \"[* https://example.com/photo.jpg *]\":https://example.com\r\n */\r\nexport function imageEmbedPlugin(options: ImageEmbedPluginOptions = {}): TexyParserPlugin {\r\n const maxWidth = options.maxWidth ?? '300px';\r\n const className = options.className ?? 'texy-image';\r\n const enableLinkedImages = options.enableLinkedImages !== false;\r\n\r\n return {\r\n name: 'image-embed',\r\n\r\n preprocess(text: string): string {\r\n if (!enableLinkedImages) return text;\r\n\r\n // Convert linked images: \"[* URL *]\":LINK → {{imglink:URL|LINK}}\r\n text = text.replace(\r\n /\"\\[\\*\\s+(\\S+?)(?:\\s+\\.\\(([^)]*)\\))?\\s*\\*?\\]\"\\s*:\\s*(\\S+)/g,\r\n (_m, imgUrl, alt, linkUrl) => {\r\n const altPart = alt ? `|alt:${alt}` : '';\r\n return `{{imglink:${imgUrl}${altPart}|${linkUrl}}}`;\r\n },\r\n );\r\n\r\n return text;\r\n },\r\n\r\n processInline(text: string, placeholder: (html: string) => string): string {\r\n // Expand {{imglink:URL|alt:TEXT|LINK}} placeholders\r\n text = text.replace(\r\n /\\{\\{imglink:(\\S+?)(?:\\|alt:([^|]*))?\\|(\\S+)\\}\\}/g,\r\n (_m, imgUrl, alt, linkUrl) => {\r\n const altAttr = alt ? ` alt=\"${alt}\"` : ' alt=\"\"';\r\n const img = `<a href=\"${linkUrl}\"><img src=\"${imgUrl}\"${altAttr} class=\"${className}\" style=\"max-width:${maxWidth}\"></a>`;\r\n return placeholder(img);\r\n },\r\n );\r\n\r\n return text;\r\n },\r\n };\r\n}\r\n","import type { TexyEditorStrings } from '../types';\r\n\r\nexport const cs: TexyEditorStrings = {\r\n bold: 'Tučně',\r\n italic: 'Kurzíva',\r\n deleted: 'Přeškrtnuté',\r\n inserted: 'Podtržené',\r\n superscript: 'Horní index',\r\n subscript: 'Dolní index',\r\n code: 'Kód',\r\n codeBlock: 'Blok kódu',\r\n heading1: 'Nadpis 1',\r\n heading2: 'Nadpis 2',\r\n heading3: 'Nadpis 3',\r\n heading4: 'Nadpis 4',\r\n link: 'Odkaz',\r\n linkUrl: 'URL odkazu',\r\n linkText: 'Text odkazu',\r\n image: 'Obrázek',\r\n imageUrl: 'URL obrázku',\r\n imageAlt: 'Popis obrázku',\r\n imageAlign: 'Zarovnání',\r\n unorderedList: 'Odrážky',\r\n orderedList: 'Číslovaný seznam',\r\n blockquote: 'Citace',\r\n horizontalRule: 'Vodorovná čára',\r\n table: 'Tabulka',\r\n tableRows: 'Řádky',\r\n tableCols: 'Sloupce',\r\n color: 'Barva textu',\r\n symbol: 'Speciální znak',\r\n acronym: 'Zkratka',\r\n acronymTitle: 'Význam zkratky',\r\n alignLeft: 'Zarovnat vlevo',\r\n alignRight: 'Zarovnat vpravo',\r\n alignCenter: 'Zarovnat na střed',\r\n alignJustify: 'Zarovnat do bloku',\r\n indent: 'Odsadit',\r\n unindent: 'Zrušit odsazení',\r\n fullscreen: 'Celá obrazovka',\r\n preview: 'Náhled',\r\n edit: 'Upravit',\r\n splitView: 'Rozdělený pohled',\r\n undo: 'Zpět',\r\n redo: 'Vpřed',\r\n upload: 'Nahrát soubor',\r\n uploadDragDrop: 'Přetáhněte soubor sem nebo klikněte',\r\n previewEmpty: 'Zadejte text pro zobrazení náhledu.',\r\n previewLoading: 'Načítání náhledu…',\r\n headingPrompt: 'Text nadpisu',\r\n ok: 'OK',\r\n cancel: 'Zrušit',\r\n close: 'Zavřít',\r\n};\r\n","import type { TexyEditorStrings } from '../types';\r\n\r\nexport const en: TexyEditorStrings = {\r\n bold: 'Bold',\r\n italic: 'Italic',\r\n deleted: 'Strikethrough',\r\n inserted: 'Underline',\r\n superscript: 'Superscript',\r\n subscript: 'Subscript',\r\n code: 'Inline code',\r\n codeBlock: 'Code block',\r\n heading1: 'Heading 1',\r\n heading2: 'Heading 2',\r\n heading3: 'Heading 3',\r\n heading4: 'Heading 4',\r\n link: 'Link',\r\n linkUrl: 'Link URL',\r\n linkText: 'Link text',\r\n image: 'Image',\r\n imageUrl: 'Image URL',\r\n imageAlt: 'Image description',\r\n imageAlign: 'Alignment',\r\n unorderedList: 'Bullet list',\r\n orderedList: 'Numbered list',\r\n blockquote: 'Blockquote',\r\n horizontalRule: 'Horizontal rule',\r\n table: 'Table',\r\n tableRows: 'Rows',\r\n tableCols: 'Columns',\r\n color: 'Text color',\r\n symbol: 'Special character',\r\n acronym: 'Acronym',\r\n acronymTitle: 'Acronym meaning',\r\n alignLeft: 'Align left',\r\n alignRight: 'Align right',\r\n alignCenter: 'Align center',\r\n alignJustify: 'Justify',\r\n indent: 'Indent',\r\n unindent: 'Outdent',\r\n fullscreen: 'Fullscreen',\r\n preview: 'Preview',\r\n edit: 'Edit',\r\n splitView: 'Split view',\r\n undo: 'Undo',\r\n redo: 'Redo',\r\n upload: 'Upload file',\r\n uploadDragDrop: 'Drag & drop a file here or click',\r\n previewEmpty: 'Enter some text to see preview.',\r\n previewLoading: 'Loading preview…',\r\n headingPrompt: 'Heading text',\r\n ok: 'OK',\r\n cancel: 'Cancel',\r\n close: 'Close',\r\n};\r\n","import type { TexyEditorStrings } from '../types';\r\nimport { cs } from './cs';\r\nimport { en } from './en';\r\n\r\nconst languages: Record<string, TexyEditorStrings> = { cs, en };\r\n\r\nexport function getStrings(lang: string): TexyEditorStrings {\r\n return languages[lang] ?? languages['en'];\r\n}\r\n\r\nexport function registerLanguage(lang: string, strings: TexyEditorStrings): void {\r\n languages[lang] = strings;\r\n}\r\n\r\nexport { cs, en };\r\n","import type {\r\n TexyEditorOptions,\r\n TexyEditorAPI,\r\n TexyEditorEvents,\r\n TexyEditorStrings,\r\n TexyEventHandler,\r\n TexyPlugin,\r\n ViewMode,\r\n ToolbarConfig,\r\n} from '../types';\r\nimport { Selection } from './Selection';\r\nimport { TexyFormatter } from './TexyFormatter';\r\nimport { EventBus } from './EventBus';\r\nimport { UndoManager } from './UndoManager';\r\nimport { KeyboardManager } from './KeyboardManager';\r\nimport { ToolbarBuilder } from './ToolbarBuilder';\r\nimport { DialogManager } from './DialogManager';\r\nimport { TexyParser } from '../parser';\r\nimport { getStrings } from '../i18n';\r\n\r\nconst DEFAULT_TOOLBAR: ToolbarConfig = [\r\n 'bold', 'italic', null,\r\n 'ul', 'ol', null,\r\n 'link', 'image', null,\r\n 'blockquote', 'code', 'codeBlock', null,\r\n 'heading1', 'heading2', 'heading3', null,\r\n 'hr', 'table', null,\r\n 'color', 'symbol',\r\n];\r\n\r\nconst DEFAULT_OPTIONS: Required<Pick<TexyEditorOptions,\r\n 'language' | 'defaultView' | 'width' | 'livePreview' | 'livePreviewDelay' |\r\n 'theme' | 'splitView' | 'fullscreen' | 'autoResize' | 'maxUndoSteps' |\r\n 'texyCfg'\r\n>> = {\r\n language: 'cs',\r\n defaultView: 'edit',\r\n width: '100%',\r\n livePreview: true,\r\n livePreviewDelay: 400,\r\n theme: 'light',\r\n splitView: false,\r\n fullscreen: false,\r\n autoResize: true,\r\n maxUndoSteps: 100,\r\n texyCfg: '',\r\n};\r\n\r\nexport class TexyEditor implements TexyEditorAPI {\r\n private container!: HTMLElement;\r\n private textarea: HTMLTextAreaElement;\r\n private editDiv!: HTMLElement;\r\n private previewDiv!: HTMLElement;\r\n private previewContent!: HTMLElement;\r\n\r\n private selection!: Selection;\r\n private formatter!: TexyFormatter;\r\n private events!: EventBus;\r\n private undoManager!: UndoManager;\r\n private keyboard!: KeyboardManager;\r\n private toolbarBuilder!: ToolbarBuilder;\r\n private dialogManager!: DialogManager;\r\n private strings!: TexyEditorStrings;\r\n\r\n private options!: TexyEditorOptions;\r\n private currentView: ViewMode = 'edit';\r\n private isFullscreen = false;\r\n private parser!: TexyParser;\r\n private plugins: TexyPlugin[] = [];\r\n private previewDebounceTimer: ReturnType<typeof setTimeout> | null = null;\r\n private lastPreviewedValue = '';\r\n private destroyed = false;\r\n\r\n // Built-in button actions\r\n private actions: Record<string, () => void> = {};\r\n\r\n constructor(\r\n textareaOrSelector: HTMLTextAreaElement | string,\r\n options: TexyEditorOptions = {},\r\n ) {\r\n // Resolve textarea element\r\n if (typeof textareaOrSelector === 'string') {\r\n const el = document.querySelector<HTMLTextAreaElement>(textareaOrSelector);\r\n if (!el) throw new Error(`TexyEditor: textarea \"${textareaOrSelector}\" not found`);\r\n this.textarea = el;\r\n } else {\r\n this.textarea = textareaOrSelector;\r\n }\r\n\r\n // Guard against double-init\r\n if (this.textarea.dataset.texyEditor) return;\r\n this.textarea.dataset.texyEditor = 'true';\r\n\r\n this.options = { ...DEFAULT_OPTIONS, ...options };\r\n this.strings = getStrings(this.options.language ?? 'cs');\r\n\r\n // Core modules\r\n this.selection = new Selection(this.textarea);\r\n this.formatter = new TexyFormatter(this.selection);\r\n this.events = new EventBus();\r\n this.undoManager = new UndoManager(this.options.maxUndoSteps);\r\n this.keyboard = new KeyboardManager(this.textarea, this.options.shortcuts);\r\n this.parser = new TexyParser();\r\n\r\n // Register built-in actions\r\n this.registerActions();\r\n\r\n // Build toolbar\r\n this.toolbarBuilder = new ToolbarBuilder(\r\n this.strings,\r\n (name) => this.execAction(name),\r\n );\r\n\r\n // Build DOM\r\n this.buildDOM();\r\n\r\n // Apply theme\r\n this.applyTheme();\r\n\r\n // Apply CSS var overrides\r\n if (this.options.cssVars) {\r\n for (const [key, value] of Object.entries(this.options.cssVars)) {\r\n this.container.style.setProperty(key, value);\r\n }\r\n }\r\n\r\n // Setup keyboard shortcuts\r\n this.setupKeyboard();\r\n\r\n // Setup auto-resize\r\n if (this.options.autoResize) {\r\n this.setupAutoResize();\r\n }\r\n\r\n // Setup undo tracking\r\n this.setupUndoTracking();\r\n\r\n // Set initial view\r\n this.currentView = this.options.defaultView ?? 'edit';\r\n\r\n // Init plugins\r\n if (this.options.plugins) {\r\n for (const plugin of this.options.plugins) {\r\n this.loadPlugin(plugin);\r\n }\r\n }\r\n\r\n // Save initial undo state\r\n this.undoManager.push({\r\n value: this.textarea.value,\r\n cursorStart: 0,\r\n cursorEnd: 0,\r\n });\r\n }\r\n\r\n // ── Public API ──────────────────────────────────────────────\r\n\r\n getValue(): string {\r\n return this.textarea.value;\r\n }\r\n\r\n setValue(value: string): void {\r\n this.textarea.value = value;\r\n this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n\r\n getSelection(): string {\r\n return this.selection.text();\r\n }\r\n\r\n replaceSelection(text: string): void {\r\n this.selection.replace(text);\r\n }\r\n\r\n wrapSelection(prefix: string, suffix: string): void {\r\n this.selection.tag(prefix, suffix);\r\n }\r\n\r\n insertAtCursor(text: string): void {\r\n if (this.selection.isCursor()) {\r\n this.selection.tag(text, '');\r\n } else {\r\n this.selection.replace(text);\r\n }\r\n }\r\n\r\n focus(): void {\r\n this.textarea.focus();\r\n }\r\n\r\n setView(mode: ViewMode): void {\r\n this.currentView = mode;\r\n this.updateView();\r\n this.events.emit('view:change', { mode });\r\n }\r\n\r\n getView(): ViewMode {\r\n return this.currentView;\r\n }\r\n\r\n execAction(name: string): void {\r\n const action = this.actions[name];\r\n if (action) {\r\n action();\r\n this.events.emit('toolbar:action', { button: name });\r\n }\r\n }\r\n\r\n on<K extends keyof TexyEditorEvents>(event: K, handler: TexyEventHandler<TexyEditorEvents[K]>): void {\r\n this.events.on(event, handler);\r\n }\r\n\r\n off<K extends keyof TexyEditorEvents>(event: K, handler: TexyEventHandler<TexyEditorEvents[K]>): void {\r\n this.events.off(event, handler);\r\n }\r\n\r\n undo(): void {\r\n const state = this.undoManager.undo();\r\n if (state) {\r\n this.textarea.value = state.value;\r\n this.selection.select(state.cursorStart, state.cursorEnd - state.cursorStart);\r\n this.events.emit('undo', undefined as never);\r\n }\r\n }\r\n\r\n redo(): void {\r\n const state = this.undoManager.redo();\r\n if (state) {\r\n this.textarea.value = state.value;\r\n this.selection.select(state.cursorStart, state.cursorEnd - state.cursorStart);\r\n this.events.emit('redo', undefined as never);\r\n }\r\n }\r\n\r\n openWindow(_name: string): void {\r\n // Plugin windows are handled via dialog manager\r\n // This is the public API hook for plugins\r\n }\r\n\r\n closeWindow(name: string): void {\r\n this.dialogManager.close(name);\r\n }\r\n\r\n toggleFullscreen(): void {\r\n this.isFullscreen = !this.isFullscreen;\r\n this.container.classList.toggle('te-fullscreen', this.isFullscreen);\r\n this.events.emit('fullscreen:toggle', { active: this.isFullscreen });\r\n }\r\n\r\n getTextarea(): HTMLTextAreaElement {\r\n return this.textarea;\r\n }\r\n\r\n getContainer(): HTMLElement {\r\n return this.container;\r\n }\r\n\r\n getStrings(): TexyEditorStrings {\r\n return this.strings;\r\n }\r\n\r\n getDialogManager(): DialogManager {\r\n return this.dialogManager;\r\n }\r\n\r\n getFormatter(): TexyFormatter {\r\n return this.formatter;\r\n }\r\n\r\n getSelectionManager(): Selection {\r\n return this.selection;\r\n }\r\n\r\n destroy(): void {\r\n if (this.destroyed) return;\r\n this.destroyed = true;\r\n\r\n // Destroy plugins\r\n for (const plugin of this.plugins) {\r\n plugin.destroy?.();\r\n }\r\n\r\n // Detach keyboard\r\n this.keyboard.detach();\r\n\r\n // Close dialogs\r\n this.dialogManager.closeAll();\r\n\r\n // Remove container, restore textarea\r\n const parent = this.container.parentNode;\r\n if (parent) {\r\n parent.insertBefore(this.textarea, this.container);\r\n parent.removeChild(this.container);\r\n }\r\n\r\n // Cleanup\r\n delete this.textarea.dataset.texyEditor;\r\n this.events.emit('destroy', undefined as never);\r\n this.events.removeAll();\r\n }\r\n\r\n // ── Private: DOM Building ─────────────────────────────────\r\n\r\n private buildDOM(): void {\r\n // Main container\r\n this.container = document.createElement('div');\r\n this.container.className = 'te-editor';\r\n if (this.options.width) {\r\n this.container.style.width = this.options.width;\r\n }\r\n if (this.options.ariaLabel) {\r\n this.container.setAttribute('aria-label', this.options.ariaLabel);\r\n }\r\n\r\n // Top toolbar\r\n const toolbar = this.options.toolbar ?? DEFAULT_TOOLBAR;\r\n const toolbarEl = this.toolbarBuilder.build(toolbar);\r\n this.container.appendChild(toolbarEl);\r\n\r\n // Edit area\r\n this.editDiv = document.createElement('div');\r\n this.editDiv.className = 'te-edit-area';\r\n this.container.appendChild(this.editDiv);\r\n\r\n // Preview area\r\n this.previewDiv = document.createElement('div');\r\n this.previewDiv.className = 'te-preview-area';\r\n this.previewDiv.style.display = 'none';\r\n this.previewContent = document.createElement('div');\r\n this.previewContent.className = 'te-preview-content';\r\n this.previewDiv.appendChild(this.previewContent);\r\n this.container.appendChild(this.previewDiv);\r\n\r\n // Bottom toolbar\r\n const bottomBar = this.toolbarBuilder.buildBottomBar(\r\n this.options.bottomLeftToolbar ?? ['edit', 'preview', 'splitView'],\r\n this.options.bottomRightEditToolbar ?? ['undo', 'redo'],\r\n this.options.bottomRightPreviewToolbar ?? [],\r\n );\r\n this.container.appendChild(bottomBar);\r\n\r\n // Dialog manager\r\n this.dialogManager = new DialogManager(this.container, this.strings);\r\n\r\n // Insert container into DOM, move textarea inside\r\n this.textarea.parentNode?.insertBefore(this.container, this.textarea);\r\n this.editDiv.appendChild(this.textarea);\r\n\r\n // Add te-textarea class\r\n this.textarea.classList.add('te-textarea');\r\n }\r\n\r\n private applyTheme(): void {\r\n const theme = this.options.theme ?? 'light';\r\n this.container.classList.add(`te-theme-${theme}`);\r\n this.container.setAttribute('data-te-theme', theme);\r\n }\r\n\r\n private updateView(): void {\r\n const isEdit = this.currentView === 'edit';\r\n const isPreview = this.currentView === 'preview';\r\n const isSplit = this.currentView === 'split';\r\n\r\n this.editDiv.style.display = (isEdit || isSplit) ? '' : 'none';\r\n this.previewDiv.style.display = (isPreview || isSplit) ? '' : 'none';\r\n\r\n this.container.classList.toggle('te-view-edit', isEdit);\r\n this.container.classList.toggle('te-view-preview', isPreview);\r\n this.container.classList.toggle('te-view-split', isSplit);\r\n\r\n // Update active tab in bottom bar\r\n this.container.querySelectorAll('.te-bottom-left .te-btn').forEach((btn) => {\r\n const action = (btn as HTMLElement).dataset.action;\r\n btn.classList.toggle('te-btn-active', action === this.currentView);\r\n });\r\n\r\n // Trigger preview render if needed\r\n if (!isEdit) {\r\n this.renderPreview();\r\n }\r\n }\r\n\r\n // ── Private: Preview ──────────────────────────────────────\r\n\r\n private renderPreview(): void {\r\n const value = this.textarea.value;\r\n\r\n if (!value.trim()) {\r\n this.previewContent.innerHTML = `<p class=\"te-preview-empty\">${this.strings.previewEmpty}</p>`;\r\n return;\r\n }\r\n\r\n if (value === this.lastPreviewedValue) return;\r\n this.lastPreviewedValue = value;\r\n\r\n // Server-side preview\r\n if (this.options.previewPath) {\r\n this.previewContent.innerHTML = `<p class=\"te-preview-loading\">${this.strings.previewLoading}</p>`;\r\n this.fetchServerPreview(value);\r\n } else if (this.options.livePreview) {\r\n // Client-side Texy parser\r\n this.previewContent.innerHTML = `<div class=\"te-preview-rendered\">${this.parser.parse(value)}</div>`;\r\n }\r\n }\r\n\r\n private async fetchServerPreview(value: string): Promise<void> {\r\n try {\r\n const response = await fetch(this.options.previewPath!, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\r\n body: `texy=${encodeURIComponent(value)}&cfg=${encodeURIComponent(this.options.texyCfg ?? '')}`,\r\n });\r\n const html = await response.text();\r\n this.previewContent.innerHTML = html;\r\n this.events.emit('preview:render', { html });\r\n } catch {\r\n this.previewContent.innerHTML = '<p class=\"te-preview-error\">Preview loading failed.</p>';\r\n }\r\n }\r\n\r\n // ── Private: Actions ──────────────────────────────────────\r\n\r\n private registerActions(): void {\r\n this.actions = {\r\n bold: () => this.formatter.bold(),\r\n italic: () => this.formatter.italic(),\r\n deleted: () => this.formatter.deleted(),\r\n inserted: () => this.formatter.inserted(),\r\n superscript: () => this.formatter.superscript(),\r\n subscript: () => this.formatter.subscript(),\r\n code: () => this.formatter.inlineCode(),\r\n codeBlock: () => this.formatter.codeBlock(),\r\n heading1: () => this.handleHeading(1),\r\n heading2: () => this.handleHeading(2),\r\n heading3: () => this.handleHeading(3),\r\n heading4: () => this.handleHeading(4),\r\n link: () => this.handleLink(),\r\n image: () => this.handleImage(),\r\n ul: () => this.formatter.unorderedList(),\r\n ol: () => this.formatter.orderedList(),\r\n blockquote: () => this.formatter.blockquote(),\r\n hr: () => this.formatter.horizontalRule(),\r\n table: () => this.handleTable(),\r\n color: () => this.handleColor(),\r\n symbol: () => this.handleSymbol(),\r\n acronym: () => this.handleAcronym(),\r\n alignLeft: () => this.formatter.alignLeft(),\r\n alignRight: () => this.formatter.alignRight(),\r\n alignCenter: () => this.formatter.alignCenter(),\r\n alignJustify: () => this.formatter.alignJustify(),\r\n indent: () => this.formatter.indent(),\r\n unindent: () => this.formatter.unindent(),\r\n undo: () => this.undo(),\r\n redo: () => this.redo(),\r\n fullscreen: () => this.toggleFullscreen(),\r\n edit: () => this.setView('edit'),\r\n preview: () => this.setView('preview'),\r\n splitView: () => this.setView('split'),\r\n };\r\n }\r\n\r\n private handleHeading(level: 1 | 2 | 3 | 4): void {\r\n if (this.selection.isCursor()) {\r\n const text = prompt(this.strings.headingPrompt, '');\r\n if (text) this.formatter.headingWithPrompt(level, text);\r\n } else {\r\n this.formatter.heading(level);\r\n }\r\n }\r\n\r\n private handleLink(): void {\r\n const content = document.createElement('div');\r\n content.className = 'te-dialog-form';\r\n\r\n const urlInput = this.createFormField(content, this.strings.linkUrl, 'url', 'https://');\r\n const textInput = this.createFormField(content, this.strings.linkText, 'text', this.selection.text());\r\n\r\n this.dialogManager.open('link', {\r\n title: this.strings.link,\r\n width: 400,\r\n content,\r\n onSubmit: () => {\r\n this.formatter.link(urlInput.value, textInput.value || undefined);\r\n this.focus();\r\n },\r\n });\r\n }\r\n\r\n private handleImage(): void {\r\n const content = document.createElement('div');\r\n content.className = 'te-dialog-form';\r\n\r\n const urlInput = this.createFormField(content, this.strings.imageUrl, 'url', '');\r\n const altInput = this.createFormField(content, this.strings.imageAlt, 'text', '');\r\n\r\n const alignLabel = document.createElement('label');\r\n alignLabel.className = 'te-form-label';\r\n alignLabel.textContent = this.strings.imageAlign;\r\n content.appendChild(alignLabel);\r\n\r\n const alignSelect = document.createElement('select');\r\n alignSelect.className = 'te-form-input';\r\n for (const [value, label] of [['*', '---'], ['<', '← ' + this.strings.alignLeft], ['>', this.strings.alignRight + ' →'], ['<>', '↔ ' + this.strings.alignCenter]]) {\r\n const opt = document.createElement('option');\r\n opt.value = value;\r\n opt.textContent = label;\r\n alignSelect.appendChild(opt);\r\n }\r\n content.appendChild(alignSelect);\r\n\r\n this.dialogManager.open('image', {\r\n title: this.strings.image,\r\n width: 420,\r\n content,\r\n onSubmit: () => {\r\n const align = alignSelect.value as '<' | '>' | '<>' | '*';\r\n this.formatter.image(urlInput.value, altInput.value || undefined, align);\r\n this.focus();\r\n },\r\n });\r\n }\r\n\r\n private handleTable(): void {\r\n const content = document.createElement('div');\r\n content.className = 'te-dialog-form';\r\n\r\n const colsInput = this.createFormField(content, this.strings.tableCols, 'number', '3');\r\n const rowsInput = this.createFormField(content, this.strings.tableRows, 'number', '3');\r\n\r\n this.dialogManager.open('table', {\r\n title: this.strings.table,\r\n width: 320,\r\n content,\r\n onSubmit: () => {\r\n const cols = parseInt(colsInput.value) || 3;\r\n const rows = parseInt(rowsInput.value) || 3;\r\n this.formatter.table(cols, rows, 'top');\r\n this.focus();\r\n },\r\n });\r\n }\r\n\r\n private handleColor(): void {\r\n const COLORS = [\r\n 'red', 'blue', 'green', 'orange', 'purple',\r\n 'brown', 'navy', 'teal', 'gray', 'black',\r\n '#e74c3c', '#3498db', '#2ecc71', '#f39c12', '#9b59b6',\r\n '#1abc9c', '#e67e22', '#95a5a6', '#34495e', '#d35400',\r\n ];\r\n\r\n const content = document.createElement('div');\r\n content.className = 'te-color-grid';\r\n\r\n for (const color of COLORS) {\r\n const swatch = document.createElement('button');\r\n swatch.type = 'button';\r\n swatch.className = 'te-color-swatch';\r\n swatch.style.backgroundColor = color;\r\n swatch.setAttribute('data-color', color);\r\n swatch.setAttribute('title', color);\r\n swatch.addEventListener('click', () => {\r\n this.formatter.colorModifier(color);\r\n this.dialogManager.close('color');\r\n this.focus();\r\n });\r\n content.appendChild(swatch);\r\n }\r\n\r\n this.dialogManager.open('color', {\r\n title: this.strings.color,\r\n width: 300,\r\n content,\r\n onSubmit: () => {},\r\n });\r\n }\r\n\r\n private handleSymbol(): void {\r\n const SYMBOLS = [\r\n '&', '@', '§', '©', '®', '™', '°', '±', '×', '÷',\r\n '€', '£', '¥', '¢', '‰', '†', '‡', '¶', '•', '…',\r\n '←', '→', '↑', '↓', '↔', '⇒', '⇐', '⇔', '≈', '≠',\r\n '≤', '≥', '∞', '∑', '∏', '∫', '√', '∂', '∆', '∇',\r\n 'α', 'β', 'γ', 'δ', 'ε', 'π', 'σ', 'τ', 'φ', 'ω',\r\n '♠', '♣', '♥', '♦', '★', '☆', '✓', '✗', '♪', '♫',\r\n ];\r\n\r\n const content = document.createElement('div');\r\n content.className = 'te-symbol-grid';\r\n\r\n for (const symbol of SYMBOLS) {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className = 'te-symbol-btn';\r\n btn.textContent = symbol;\r\n btn.setAttribute('title', symbol);\r\n btn.addEventListener('click', () => {\r\n this.formatter.insertSymbol(symbol);\r\n this.dialogManager.close('symbol');\r\n this.focus();\r\n });\r\n content.appendChild(btn);\r\n }\r\n\r\n this.dialogManager.open('symbol', {\r\n title: this.strings.symbol,\r\n width: 400,\r\n content,\r\n onSubmit: () => {},\r\n });\r\n }\r\n\r\n private handleAcronym(): void {\r\n const title = prompt(this.strings.acronymTitle, '');\r\n if (title) this.formatter.acronym(title);\r\n }\r\n\r\n // ── Private: Keyboard ─────────────────────────────────────\r\n\r\n private setupKeyboard(): void {\r\n this.keyboard.register('bold', () => this.execAction('bold'));\r\n this.keyboard.register('italic', () => this.execAction('italic'));\r\n this.keyboard.register('link', () => this.execAction('link'));\r\n this.keyboard.register('undo', () => this.undo());\r\n this.keyboard.register('redo', () => this.redo());\r\n this.keyboard.register('fullscreen', () => this.toggleFullscreen());\r\n this.keyboard.register('indent', () => this.formatter.indent());\r\n this.keyboard.register('unindent', () => this.formatter.unindent());\r\n this.keyboard.attach();\r\n }\r\n\r\n // ── Private: Undo ─────────────────────────────────────────\r\n\r\n private setupUndoTracking(): void {\r\n let debounce: ReturnType<typeof setTimeout> | null = null;\r\n\r\n this.textarea.addEventListener('input', () => {\r\n if (debounce) clearTimeout(debounce);\r\n debounce = setTimeout(() => {\r\n this.undoManager.push({\r\n value: this.textarea.value,\r\n cursorStart: this.textarea.selectionStart,\r\n cursorEnd: this.textarea.selectionEnd,\r\n });\r\n }, 300);\r\n\r\n this.events.emit('change', { value: this.textarea.value });\r\n\r\n // Debounced preview update\r\n if (this.currentView !== 'edit' && this.options.livePreview) {\r\n if (this.previewDebounceTimer) clearTimeout(this.previewDebounceTimer);\r\n this.previewDebounceTimer = setTimeout(\r\n () => this.renderPreview(),\r\n this.options.livePreviewDelay ?? 400,\r\n );\r\n }\r\n });\r\n }\r\n\r\n // ── Private: Auto Resize ──────────────────────────────────\r\n\r\n private setupAutoResize(): void {\r\n const resize = () => {\r\n this.textarea.style.height = 'auto';\r\n this.textarea.style.height = this.textarea.scrollHeight + 'px';\r\n };\r\n\r\n this.textarea.addEventListener('input', resize);\r\n // Initial resize\r\n requestAnimationFrame(resize);\r\n }\r\n\r\n // ── Private: Plugins ──────────────────────────────────────\r\n\r\n private loadPlugin(plugin: TexyPlugin): void {\r\n plugin.init(this);\r\n this.plugins.push(plugin);\r\n this.events.emit('plugin:init', { name: plugin.name });\r\n }\r\n\r\n // ── Private: Helpers ──────────────────────────────────────\r\n\r\n private createFormField(\r\n container: HTMLElement,\r\n label: string,\r\n type: string,\r\n defaultValue: string,\r\n ): HTMLInputElement {\r\n const wrapper = document.createElement('div');\r\n wrapper.className = 'te-form-group';\r\n\r\n const labelEl = document.createElement('label');\r\n labelEl.className = 'te-form-label';\r\n labelEl.textContent = label;\r\n wrapper.appendChild(labelEl);\r\n\r\n const input = document.createElement('input');\r\n input.type = type;\r\n input.className = 'te-form-input';\r\n input.value = defaultValue;\r\n wrapper.appendChild(input);\r\n\r\n container.appendChild(wrapper);\r\n return input;\r\n }\r\n}\r\n"],"names":["Selection","textarea","val","start","end","value","length","position","replacement","state","scrollTop","prefix","suffix","newValue","trimmed","TexyFormatter","selection","text","url","title","src","alt","align","caption","markup","level","char","lf","underline","unindented","line","first","language","lang","modifier","mod","rule","cols","rows","header","i","j","color","className","symbol","marker","escaped","type","lines","lineCount","parts","bullet","content","firstLine","rest","index","num","mill","cent","tens","ones","m","c","t","o","n","newPar","found","beforePar","EventBus","__publicField","event","handler","_a","data","err","UndoManager","maxSteps","DEFAULT_SHORTCUTS","KeyboardManager","customShortcuts","actionName","shortcutStr","binding","e","ctrlMatch","shiftMatch","altMatch","keyMatch","str","p","ICONS","createSvgIcon","name","path","ToolbarBuilder","strings","actionHandler","config","item","el","left","rightEdit","rightPreview","leftDiv","rightDiv","editGroup","previewGroup","btn","label","icon","sep","group","wrapper","trigger","menu","itemName","menuItem","isOpen","DialogManager","container","dialog","closeBtn","body","footer","cancelBtn","submitBtn","firstInput","TexyParser","options","plugin","input","blockRules","r","a","b","html","blocks","segments","segment","parsed","current","inBlock","joined","s","match","code","isTableLine","l","inHead","headClosed","cells","cell","tag","row","headingChars","surroundMatch","remaining","result","headingText","underlineMatch","inner","firstItem","bulletPattern","attrs","items","currentItem","nestedList","modifierMatch","placeholders","pIdx","ph","key","_m","imgSrc","style","altAttr","inlineRules","linkText","word","cls","phStart","phEnd","phKey","styleMatch","classMatch","idMatch","titleMatch","youtubePlugin","width","height","allowFs","wrapperClass","_url","id","placeholder","iframe","smileyPlugin","baseUrl","format","ariaLabels","img","linkRedirectPlugin","redirectUrl","excludeDomains","targetBlank","noopener","hostname","d","encodedUrl","bbcodePlugin","imageEmbedPlugin","maxWidth","enableLinkedImages","imgUrl","linkUrl","altPart","cs","en","languages","getStrings","registerLanguage","DEFAULT_TOOLBAR","DEFAULT_OPTIONS","TexyEditor","textareaOrSelector","mode","action","_name","parent","toolbar","toolbarEl","bottomBar","theme","isEdit","isPreview","isSplit","urlInput","textInput","altInput","alignLabel","alignSelect","opt","colsInput","rowsInput","COLORS","swatch","SYMBOLS","debounce","resize","defaultValue","labelEl"],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { TexyEditorStrings } from '../types';
2
+ export interface DialogConfig {
3
+ title: string;
4
+ width?: number;
5
+ content: HTMLElement;
6
+ onSubmit: () => void;
7
+ onCancel?: () => void;
8
+ }
9
+ /**
10
+ * Native <dialog> based modal window manager.
11
+ * Replaces jQuery UI Dialog with zero dependencies.
12
+ */
13
+ export declare class DialogManager {
14
+ private container;
15
+ private strings;
16
+ private openDialogs;
17
+ constructor(container: HTMLElement, strings: TexyEditorStrings);
18
+ open(name: string, config: DialogConfig): HTMLDialogElement;
19
+ close(name: string): void;
20
+ closeAll(): void;
21
+ isOpen(name: string): boolean;
22
+ }
@@ -0,0 +1,10 @@
1
+ import type { TexyEditorEvents, TexyEventHandler } from '../types';
2
+ type EventMap = TexyEditorEvents;
3
+ export declare class EventBus {
4
+ private listeners;
5
+ on<K extends keyof EventMap>(event: K, handler: TexyEventHandler<EventMap[K]>): void;
6
+ off<K extends keyof EventMap>(event: K, handler: TexyEventHandler<EventMap[K]>): void;
7
+ emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void;
8
+ removeAll(): void;
9
+ }
10
+ export {};
@@ -0,0 +1,13 @@
1
+ export type ShortcutHandler = () => void;
2
+ export declare class KeyboardManager {
3
+ private textarea;
4
+ private customShortcuts?;
5
+ private bindings;
6
+ private boundHandler;
7
+ constructor(textarea: HTMLTextAreaElement, customShortcuts?: Record<string, string> | undefined);
8
+ register(actionName: string, handler: ShortcutHandler): void;
9
+ attach(): void;
10
+ detach(): void;
11
+ private handleKeydown;
12
+ private parseShortcut;
13
+ }
@@ -0,0 +1,59 @@
1
+ import type { SelectionState } from '../types';
2
+ /**
3
+ * Textarea selection manager.
4
+ * Provides methods to read, manipulate, and replace selected text
5
+ * in a standard HTMLTextAreaElement without any external dependencies.
6
+ */
7
+ export declare class Selection {
8
+ private textarea;
9
+ constructor(textarea: HTMLTextAreaElement);
10
+ /** Detect the line-feed character used in the textarea value */
11
+ get lf(): string;
12
+ /** Get current selection state snapshot */
13
+ getState(): SelectionState;
14
+ /** Get selected text */
15
+ text(): string;
16
+ /** Length of current selection */
17
+ length(): number;
18
+ /** Whether selection is collapsed (cursor without selection) */
19
+ isCursor(): boolean;
20
+ /** Set selection range programmatically */
21
+ select(start: number, length: number): void;
22
+ /** Place cursor at a specific position */
23
+ setCursor(position: number): void;
24
+ /**
25
+ * Replace currently selected text with new content.
26
+ * After replacement, the new text is selected.
27
+ */
28
+ replace(replacement: string): void;
29
+ /**
30
+ * Wrap selection with prefix and suffix.
31
+ * If nothing is selected (cursor), places cursor between prefix and suffix.
32
+ */
33
+ tag(prefix: string, suffix: string): void;
34
+ /**
35
+ * Wrap selection as an inline phrase.
36
+ * Trims trailing whitespace from selection before wrapping.
37
+ */
38
+ phrase(prefix: string, suffix?: string): void;
39
+ /**
40
+ * Remove trailing whitespace from the selection boundary.
41
+ * Useful when double-clicking selects a trailing space.
42
+ */
43
+ trimSelect(): void;
44
+ /**
45
+ * Expand selection to cover complete lines.
46
+ * Useful for block-level operations (lists, headings).
47
+ */
48
+ selectBlock(): void;
49
+ /** Get the full value of the textarea */
50
+ getValue(): string;
51
+ /** Set the full value of the textarea */
52
+ setValue(value: string): void;
53
+ /** Focus the textarea */
54
+ focus(): void;
55
+ /** Get the underlying textarea element */
56
+ getElement(): HTMLTextAreaElement;
57
+ private isCursorAt;
58
+ private dispatchInput;
59
+ }
@@ -0,0 +1,71 @@
1
+ import type { TexyEditorOptions, TexyEditorAPI, TexyEditorEvents, TexyEditorStrings, TexyEventHandler, ViewMode } from '../types';
2
+ import { Selection } from './Selection';
3
+ import { TexyFormatter } from './TexyFormatter';
4
+ import { DialogManager } from './DialogManager';
5
+ export declare class TexyEditor implements TexyEditorAPI {
6
+ private container;
7
+ private textarea;
8
+ private editDiv;
9
+ private previewDiv;
10
+ private previewContent;
11
+ private selection;
12
+ private formatter;
13
+ private events;
14
+ private undoManager;
15
+ private keyboard;
16
+ private toolbarBuilder;
17
+ private dialogManager;
18
+ private strings;
19
+ private options;
20
+ private currentView;
21
+ private isFullscreen;
22
+ private parser;
23
+ private plugins;
24
+ private previewDebounceTimer;
25
+ private lastPreviewedValue;
26
+ private destroyed;
27
+ private actions;
28
+ constructor(textareaOrSelector: HTMLTextAreaElement | string, options?: TexyEditorOptions);
29
+ getValue(): string;
30
+ setValue(value: string): void;
31
+ getSelection(): string;
32
+ replaceSelection(text: string): void;
33
+ wrapSelection(prefix: string, suffix: string): void;
34
+ insertAtCursor(text: string): void;
35
+ focus(): void;
36
+ setView(mode: ViewMode): void;
37
+ getView(): ViewMode;
38
+ execAction(name: string): void;
39
+ on<K extends keyof TexyEditorEvents>(event: K, handler: TexyEventHandler<TexyEditorEvents[K]>): void;
40
+ off<K extends keyof TexyEditorEvents>(event: K, handler: TexyEventHandler<TexyEditorEvents[K]>): void;
41
+ undo(): void;
42
+ redo(): void;
43
+ openWindow(_name: string): void;
44
+ closeWindow(name: string): void;
45
+ toggleFullscreen(): void;
46
+ getTextarea(): HTMLTextAreaElement;
47
+ getContainer(): HTMLElement;
48
+ getStrings(): TexyEditorStrings;
49
+ getDialogManager(): DialogManager;
50
+ getFormatter(): TexyFormatter;
51
+ getSelectionManager(): Selection;
52
+ destroy(): void;
53
+ private buildDOM;
54
+ private applyTheme;
55
+ private updateView;
56
+ private renderPreview;
57
+ private fetchServerPreview;
58
+ private registerActions;
59
+ private handleHeading;
60
+ private handleLink;
61
+ private handleImage;
62
+ private handleTable;
63
+ private handleColor;
64
+ private handleSymbol;
65
+ private handleAcronym;
66
+ private setupKeyboard;
67
+ private setupUndoTracking;
68
+ private setupAutoResize;
69
+ private loadPlugin;
70
+ private createFormField;
71
+ }