@textbus/platform-browser 5.2.1 → 5.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +1723 -1019
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2380 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/_utils/uikit.ts","../src/_utils/env.ts","../src/injection-tokens.ts","../src/parser.ts","../src/selection-bridge.ts","../src/types.ts","../src/magic-input.ts","../src/collaborate-cursor.ts","../src/native-input.ts","../src/dom-adapter.ts","../src/browser-module.ts"],"sourcesContent":["/**\n * 选区焦点可视位置\n */\nexport interface Rect {\n left: number\n top: number\n width: number\n height: number\n}\n\nexport interface UIElementParams {\n classes?: string[]\n attrs?: {[key: string]: any}\n props?: {[key: string]: any}\n styles?: {[key: string]: any}\n children?: (Node | null)[]\n on?: Record<string, (ev: Event) => void>\n}\n\nexport function createElement(tagName: string, options: UIElementParams = {}): HTMLElement {\n const el = document.createElement(tagName)\n if (options.classes) {\n el.classList.add(...options.classes)\n }\n if (options.attrs) {\n Object.keys(options.attrs).forEach(key => {\n el.setAttribute(key, options.attrs![key])\n })\n }\n if (options.props) {\n Object.keys(options.props).forEach(key => {\n (el as any)[key] = options.props![key]\n })\n }\n if (options.styles) {\n Object.assign(el.style, options.styles)\n }\n if (options.children) {\n options.children.filter(i => i).forEach(item => {\n el.appendChild(item as Node)\n })\n }\n if (options.on) {\n Object.keys(options.on).forEach(key => {\n el.addEventListener(key, options.on![key])\n })\n }\n return el\n}\n\nexport function getLayoutRectByRange(range: Range): Rect {\n let { startContainer, startOffset } = range\n if (startContainer.nodeType === Node.TEXT_NODE) {\n if (startOffset > 0) {\n return range.getBoundingClientRect()\n }\n const parentNode = startContainer.parentNode!\n startOffset = Array.from(parentNode.childNodes).indexOf(startContainer as any)\n startContainer = parentNode\n }\n\n const beforeNode = startContainer.childNodes[startOffset - 1]\n if (beforeNode) {\n if (beforeNode.nodeType === Node.ELEMENT_NODE && beforeNode.nodeName.toLowerCase() !== 'br') {\n const rect = (beforeNode as HTMLElement).getBoundingClientRect()\n return {\n left: rect.right,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n } else if (beforeNode.nodeType === Node.TEXT_NODE) {\n const range2 = document.createRange()\n range2.setStart(beforeNode, beforeNode.textContent!.length)\n range2.setEnd(beforeNode, beforeNode.textContent!.length)\n const rect = range2.getBoundingClientRect()\n return {\n left: rect.right,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n }\n }\n const offsetNode = startContainer.childNodes[startOffset]\n let isInsertBefore = false\n if (!offsetNode) {\n const lastChild = startContainer.lastChild\n if (lastChild && lastChild.nodeType === Node.ELEMENT_NODE) {\n const rect = (lastChild as HTMLElement).getBoundingClientRect()\n return {\n left: rect.right,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n }\n }\n if (offsetNode) {\n if (offsetNode.nodeType === Node.ELEMENT_NODE && offsetNode.nodeName.toLowerCase() !== 'br') {\n const rect = (offsetNode as HTMLElement).getBoundingClientRect()\n return {\n left: rect.left,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n }\n isInsertBefore = true\n }\n const span = startContainer.ownerDocument!.createElement('span')\n span.innerText = '\\u200b'\n span.style.display = 'inline-block'\n if (isInsertBefore) {\n startContainer.insertBefore(span, offsetNode)\n } else {\n startContainer.appendChild(span)\n }\n const rect = span.getBoundingClientRect()\n startContainer.removeChild(span)\n return {\n left: rect.left,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n}\n","export const isWindows = () => /win(dows|32|64)/i.test(navigator.userAgent)\nexport const isMac = () => /mac os/i.test(navigator.userAgent)\nexport const isSafari = () => /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent)\nexport const isFirefox = () => /Firefox/.test(navigator.userAgent)\n\nexport const isMobileBrowser = () => /Android|iPhone|iPad/.test(navigator.userAgent)\n","import { InjectionToken } from '@viewfly/core'\n\nimport { ViewOptions } from './browser-module'\n\n/**\n * 编辑器可选项依赖注入 token\n */\nexport const EDITOR_OPTIONS = new InjectionToken<ViewOptions>('EDITOR_OPTIONS')\n\n/**\n * 编辑器容器依赖注入 token\n */\nexport const VIEW_CONTAINER = new InjectionToken<HTMLElement>('VIEW_CONTAINER')\n\n/**\n * 编辑器容器依赖注入 token\n */\nexport const VIEW_DOCUMENT = new InjectionToken<HTMLElement>('VIEW_DOCUMENT')\n\n/**\n * 编辑器容器遮罩层 token\n */\nexport const VIEW_MASK = new InjectionToken<HTMLElement>('VIEW_MASK')\n","import { Inject, Injectable } from '@viewfly/core'\nimport { Attribute, Component, ContentType, FormatItem, Formatter, FormatValue, Slot, Textbus } from '@textbus/core'\n\nimport { EDITOR_OPTIONS } from './injection-tokens'\nimport { ViewOptions } from './browser-module'\n\n/**\n * 插槽解析器\n */\nexport interface SlotParser {\n /**\n * 将指定 DOM 节点解析为插槽数据\n * @param childSlot 储存数据的插槽\n * @param slotRootElement 插槽的根节点\n * @param slotContentHostElement 插槽的内容节点\n *\n * 注意:当不传入内容节点时,Textbus 会把根节点当成内容节点\n */<T extends Slot>(childSlot: T, slotRootElement: Element, slotContentHostElement?: Element): T\n}\n\n/**\n * 组件加载器\n */\nexport interface ComponentLoader {\n /** 识别组件的匹配方法 */\n match(element: Element,\n returnableContentTypes: ContentType[]): boolean\n\n /** 读取组件内容的方法 */\n read(element: Element, textbus: Textbus, slotParser: SlotParser): Component | Slot | void\n}\n\nexport interface FormatLoaderReadResult<T = FormatValue> {\n formatter: Formatter<T>\n value: T\n}\n\n/**\n * 格式加载器\n */\nexport interface FormatLoader<T = FormatValue> {\n /**\n * 匹配一个 DOM 节点是否是某个格式节点\n * @param element\n */\n match(element: Element): boolean\n\n /**\n * 读取匹配到的节点,并返回读取后的信息\n * @param element\n */\n read(element: Element): FormatLoaderReadResult<T>\n}\n\nexport interface AttributeLoaderReadResult<T = FormatValue> {\n attribute: Attribute<T>\n value: T\n}\n\n/**\n * 属性加载器\n */\nexport interface AttributeLoader<T = FormatValue> {\n /**\n * 匹配一个 DOM 节点是否是某个属性节点\n * @param element\n */\n match(element: Element): boolean\n\n /**\n * 读取匹配到的节点,并返回读取后的信息\n * @param element\n */\n read(element: Element): AttributeLoaderReadResult<T>\n}\n\n/**\n * 用于解析 HTML,并把 HTML 内容转换为 Textbus 可以支持的组件或插槽数据\n */\n@Injectable()\nexport class Parser {\n static parseHTML(html: string) {\n return new DOMParser().parseFromString(html, 'text/html').body\n }\n\n componentLoaders: ComponentLoader[]\n formatLoaders: FormatLoader<any>[]\n attributeLoaders: AttributeLoader<any>[]\n\n constructor(@Inject(EDITOR_OPTIONS) options: ViewOptions,\n private textbus: Textbus) {\n const componentLoaders = [\n ...(options.componentLoaders || [])\n ]\n const formatLoaders = [\n ...(options.formatLoaders || [])\n ]\n const attributeLoaders = [\n ...(options.attributeLoaders || [])\n ]\n // options.imports?.forEach(i => {\n // componentLoaders.push(...(i.componentLoaders || []))\n // formatLoaders.push(...(i.formatLoaders || []))\n // })\n this.componentLoaders = componentLoaders\n this.formatLoaders = formatLoaders\n this.attributeLoaders = attributeLoaders\n }\n\n /**\n * 使用指定的组件加载器解析一段 HTML 字符串或 DOM 元素\n * @param html\n * @param rootComponentLoader\n */\n parseDoc(html: string | HTMLElement, rootComponentLoader: ComponentLoader) {\n const element = typeof html === 'string' ? Parser.parseHTML(html) : html\n return rootComponentLoader.read(\n element,\n this.textbus,\n (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {\n return this.readSlot(childSlot, slotRootElement, slotContentHostElement)\n }\n )\n }\n\n /**\n * 将一段 HTML 或 DOM 元素解析到指定插槽\n * @param html\n * @param rootSlot\n */\n parse(html: string | HTMLElement, rootSlot: Slot) {\n const element = typeof html === 'string' ? Parser.parseHTML(html) : html\n return this.readFormats(element, rootSlot)\n }\n\n private readComponent(el: Node, slot: Slot) {\n if (el.nodeType === Node.ELEMENT_NODE) {\n if ((el as HTMLElement).tagName === 'BR') {\n slot.insert('\\n')\n return\n }\n const schema = [...slot.schema]\n for (const t of this.componentLoaders) {\n if (t.match(el as HTMLElement, schema)) {\n const result = t.read(\n el as HTMLElement,\n this.textbus,\n (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {\n return this.readSlot(childSlot, slotRootElement, slotContentHostElement)\n }\n )\n if (!result) {\n return\n }\n if (result instanceof Slot) {\n result.toDelta().forEach(i => slot.insert(i.insert, i.formats))\n return\n }\n slot.insert(result)\n return\n }\n }\n this.readFormats(el as HTMLElement, slot)\n } else if (el.nodeType === Node.TEXT_NODE) {\n this.readText(slot, el)\n }\n }\n\n private readText(slot: Slot, el: Node) {\n const textContent = el.textContent\n if (/^\\s*[\\r\\n\\u200b]+\\s*$/.test(textContent as string)) {\n return\n }\n slot.insert(textContent as string)\n }\n\n private readFormats(el: Element, slot: Slot) {\n const formats = this.formatLoaders.filter(f => {\n return f.match(el)\n }).map(f => {\n return f.read(el)\n })\n const startIndex = slot.index\n let startNode = el.firstChild\n while (startNode) {\n this.readComponent(startNode, slot)\n startNode = startNode.nextSibling\n }\n const endIndex = slot.index\n this.applyFormats(slot, formats.map<FormatItem<any>>(i => {\n return {\n formatter: i.formatter,\n value: i.value,\n startIndex,\n endIndex\n }\n }))\n slot.retain(endIndex)\n return slot\n }\n\n private readSlot<T extends Slot>(childSlot: T, slotRootElement: Element, slotContentElement: Element): T {\n if (slotRootElement.nodeType === Node.ELEMENT_NODE) {\n this.attributeLoaders.filter(a => {\n return a.match(slotRootElement)\n }).forEach(a => {\n const r = a.read(slotRootElement)\n childSlot.setAttribute(r.attribute, r.value)\n })\n }\n if (slotContentElement.nodeType === Node.ELEMENT_NODE) {\n this.readFormats(slotContentElement, childSlot)\n } else {\n this.readText(childSlot, slotContentElement)\n }\n return childSlot\n }\n\n private applyFormats(slot: Slot, formatItems: FormatItem<any>[]) {\n slot.background(() => {\n formatItems.forEach(i => {\n slot.retain(i.startIndex)\n slot.retain(i.endIndex - i.startIndex, i.formatter, i.value)\n })\n })\n }\n}\n","import { delay, filter, fromEvent, Observable, Subject, Subscription } from '@tanbo/stream'\nimport { Inject, Injectable } from '@viewfly/core'\nimport {\n NativeSelectionBridge,\n NativeSelectionConnector,\n SelectionPosition,\n Slot,\n AbstractSelection,\n RootComponentRef,\n Controller,\n Selection,\n Textbus,\n Scheduler\n} from '@textbus/core'\n\nimport { EDITOR_OPTIONS, VIEW_DOCUMENT } from './injection-tokens'\nimport { getLayoutRectByRange, Rect } from './_utils/uikit'\nimport { Input } from './types'\nimport { ViewOptions } from './browser-module'\nimport { DomAdapter } from './dom-adapter'\n\n/**\n * Textbus PC 端选区桥接实现\n */\n@Injectable()\nexport class SelectionBridge implements NativeSelectionBridge {\n onSelectionChange: Observable<Range | null>\n nativeSelection = document.getSelection()!\n\n syncSelectionFromNativeSelectionChange = true\n\n private selectionChangeEvent = new Subject<Range | null>()\n\n private subs: Subscription[] = []\n private sub: Subscription\n private connector: NativeSelectionConnector | null = null\n\n private ignoreSelectionChange = false\n\n private changeFromUser = false\n private docContainer: HTMLElement\n\n private cacheCaretPositionTimer!: any\n private oldCaretPosition!: Rect | null\n\n constructor(@Inject(EDITOR_OPTIONS) private config: ViewOptions,\n textbus: Textbus,\n controller: Controller,\n private selection: Selection,\n private rootComponentRef: RootComponentRef,\n private input: Input,\n private scheduler: Scheduler,\n private domAdapter: DomAdapter) {\n this.docContainer = textbus.get(VIEW_DOCUMENT)\n this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(filter(() => {\n return !controller.readonly\n }))\n this.sub = this.onSelectionChange.subscribe((r) => {\n if (r) {\n input.focus(r, this.changeFromUser)\n } else {\n input.blur()\n }\n })\n this.sub.add(\n fromEvent(document, 'focusin').subscribe(ev => {\n let target = ev.target as HTMLElement\n if (/^(input|textarea|select)$/i.test(target.nodeName)) {\n if (target.tagName.toLowerCase() === 'input' && /^(range|date)$/.test((target as HTMLInputElement).type)) {\n return\n }\n this.ignoreSelectionChange = true\n return\n }\n if (!config.useContentEditable) {\n while (target) {\n if (target.contentEditable === 'true') {\n this.ignoreSelectionChange = true\n return\n }\n target = target.parentNode as HTMLElement\n }\n }\n })\n )\n this.sub.add(\n fromEvent(document, 'focusout').subscribe(() => {\n this.ignoreSelectionChange = false\n })\n )\n }\n\n connect(connector: NativeSelectionConnector) {\n this.disConnect()\n this.connector = connector\n this.syncSelection(connector)\n this.listen(connector)\n }\n\n disConnect() {\n this.connector = null\n this.unListen()\n }\n\n getRect(location: SelectionPosition) {\n const { focus, anchor } = this.getPositionByRange({\n focusOffset: location.offset,\n anchorOffset: location.offset,\n focusSlot: location.slot,\n anchorSlot: location.slot\n })\n if (!focus || !anchor) {\n return null\n }\n const nativeRange = document.createRange()\n nativeRange.setStart(focus.node, focus.offset)\n nativeRange.collapse()\n return getLayoutRectByRange(nativeRange)\n }\n\n restore(abstractSelection: AbstractSelection | null, fromLocal: boolean) {\n this.changeFromUser = fromLocal\n if (this.ignoreSelectionChange || !this.connector) {\n return\n }\n this.unListen()\n if (!abstractSelection) {\n this.nativeSelection.removeAllRanges()\n this.selectionChangeEvent.next(null)\n this.listen(this.connector)\n return\n }\n\n const { focus, anchor } = this.getPositionByRange(abstractSelection)\n if (!focus || !anchor) {\n this.nativeSelection.removeAllRanges()\n this.selectionChangeEvent.next(null)\n this.listen(this.connector)\n return\n }\n\n function tryOffset(position: {node: Node, offset: number}) {\n if (!position.node) {\n return\n }\n if (position.node.nodeType === Node.TEXT_NODE) {\n const len = position.node.textContent!.length\n if (position.offset > len) {\n position.offset = len\n }\n } else if (position.node.nodeType === Node.ELEMENT_NODE) {\n const len = position.node.childNodes.length\n if (position.offset > len) {\n position.offset = len\n }\n }\n }\n\n try {\n tryOffset(focus)\n tryOffset(anchor)\n this.nativeSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset)\n } catch (e) {\n setTimeout(() => {\n throw e\n })\n }\n if (this.nativeSelection.rangeCount) {\n const nativeRange = this.nativeSelection.getRangeAt(0)\n this.selectionChangeEvent.next(nativeRange)\n } else {\n this.selectionChangeEvent.next(null)\n }\n\n // hack start 浏览器会触发上面选区更改事件\n const bind = () => {\n if (this.connector) {\n this.listen(this.connector)\n }\n }\n if (fromLocal) {\n Promise.resolve().then(bind)\n return\n }\n if (typeof requestIdleCallback === 'function') {\n requestIdleCallback(bind)\n } else {\n setTimeout(bind, 30)\n }\n // hack end\n }\n\n destroy() {\n this.subs.forEach(i => i.unsubscribe())\n this.sub.unsubscribe()\n }\n\n getPositionByRange(abstractSelection: AbstractSelection) {\n let focus!: {node: Node, offset: number} | null\n let anchor!: {node: Node, offset: number} | null\n try {\n focus = this.findSelectedNodeAndOffset(abstractSelection.focusSlot!, abstractSelection.focusOffset!)\n anchor = focus\n if (abstractSelection.anchorSlot !== abstractSelection.focusSlot ||\n abstractSelection.anchorOffset !== abstractSelection.focusOffset) {\n anchor = this.findSelectedNodeAndOffset(abstractSelection.anchorSlot!, abstractSelection.anchorOffset!)\n }\n return {\n focus,\n anchor\n }\n } catch (e) {\n return {\n focus: null,\n anchor: null\n }\n }\n }\n\n getPreviousLinePositionByCurrent(position: SelectionPosition): SelectionPosition | null {\n return this.getLinePosition(position, false)\n }\n\n getNextLinePositionByCurrent(position: SelectionPosition): SelectionPosition | null {\n return this.getLinePosition(position, true)\n }\n\n private getLinePosition(currentPosition: SelectionPosition, toNext: boolean): SelectionPosition | null {\n clearTimeout(this.cacheCaretPositionTimer)\n let p: SelectionPosition\n if (this.oldCaretPosition) {\n p = toNext ?\n this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :\n this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left)\n } else {\n this.oldCaretPosition = this.getRect(currentPosition)!\n p = toNext ?\n this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :\n this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left)\n }\n this.cacheCaretPositionTimer = setTimeout(() => {\n this.oldCaretPosition = null\n }, 3000)\n return p\n }\n\n /**\n * 获取选区向上移动一行的位置。\n * @param currentPosition\n * @param startLeft 参考位置。\n */\n private getPreviousLinePositionByOffset(currentPosition: SelectionPosition, startLeft: number): SelectionPosition {\n let isToPrevLine = false\n let loopCount = 0\n let minLeft = startLeft\n let focusSlot = currentPosition.slot\n let focusOffset = currentPosition.offset\n let minTop = this.getRect({\n slot: focusSlot,\n offset: focusOffset\n })!.top\n\n let position: SelectionPosition\n let oldPosition!: SelectionPosition\n let oldLeft = 0\n while (true) {\n loopCount++\n position = this.selection.getPreviousPositionByPosition(focusSlot, focusOffset)\n focusSlot = position.slot\n focusOffset = position.offset\n const rect2 = this.getRect(position)!\n if (!isToPrevLine) {\n if (rect2.left > minLeft || rect2.top + rect2.height <= minTop) {\n isToPrevLine = true\n } else if (rect2.left === minLeft && rect2.top === minTop) {\n return position\n }\n minLeft = rect2.left\n minTop = rect2.top\n // oldPosition = position\n }\n if (isToPrevLine) {\n if (rect2.left <= startLeft) {\n return position\n }\n if (oldPosition) {\n if (rect2.left >= oldLeft) {\n return oldPosition\n }\n }\n oldLeft = rect2.left\n oldPosition = position\n }\n if (loopCount > 10000) {\n break\n }\n }\n return position || {\n offset: 0,\n slot: focusSlot\n }\n }\n\n /**\n * 获取选区向下移动一行的位置。\n * @param currentPosition\n * @param startLeft 参考位置。\n */\n private getNextLinePositionByOffset(currentPosition: SelectionPosition, startLeft: number): SelectionPosition {\n let isToNextLine = false\n let loopCount = 0\n let maxRight = startLeft\n let focusSlot = currentPosition.slot\n let focusOffset = currentPosition.offset\n const rect = this.getRect({\n slot: focusSlot,\n offset: focusOffset\n })!\n let minTop = rect.top\n let oldPosition!: SelectionPosition\n let oldLeft = 0\n while (true) {\n loopCount++\n const position = this.selection.getNextPositionByPosition(focusSlot, focusOffset)\n focusSlot = position.slot\n focusOffset = position.offset\n const rect2 = this.getRect(position)!\n if (!isToNextLine) {\n if (rect2.left < maxRight || rect2.top >= minTop + rect.height) {\n isToNextLine = true\n } else if (rect2.left === maxRight && rect2.top === minTop) {\n return position\n }\n maxRight = rect2.left\n minTop = rect2.top\n oldPosition = position\n }\n if (isToNextLine) {\n if (rect2.left > startLeft) {\n return oldPosition\n }\n if (oldPosition) {\n if (rect2.left <= oldLeft) {\n return oldPosition\n }\n }\n oldPosition = position\n oldLeft = rect2.left\n }\n if (loopCount > 10000) {\n break\n }\n }\n return oldPosition || {\n offset: focusSlot.length,\n slot: focusSlot\n }\n }\n\n private unListen() {\n this.subs.forEach(i => i.unsubscribe())\n this.subs = []\n }\n\n private listen(connector: NativeSelectionConnector) {\n if (!this.config.useContentEditable) {\n const selection = this.nativeSelection\n this.subs.push(\n fromEvent<MouseEvent>(this.docContainer, 'mousedown').subscribe(ev => {\n if (this.ignoreSelectionChange || ev.button === 2) {\n return\n }\n if (!ev.shiftKey) {\n selection.removeAllRanges()\n }\n })\n )\n }\n let isUpdating = false\n this.subs.push(\n this.scheduler.onDocChange.subscribe(() => {\n isUpdating = true\n }),\n this.scheduler.onDocChanged.pipe(delay()).subscribe(() => {\n isUpdating = false\n }),\n fromEvent(document, 'selectionchange').subscribe(() => {\n if (isUpdating) {\n return\n }\n if (this.syncSelectionFromNativeSelectionChange) {\n this.syncSelection(connector)\n }\n })\n )\n }\n\n private syncSelection(connector: NativeSelectionConnector) {\n const selection = this.nativeSelection\n this.changeFromUser = true\n if (this.ignoreSelectionChange ||\n this.input.composition ||\n selection.rangeCount === 0 ||\n !this.docContainer.contains(selection.anchorNode) ||\n this.rootComponentRef.component.slots.length === 0) {\n return\n }\n const rawRange = selection.getRangeAt(0)\n const nativeRange = rawRange.cloneRange()\n const isFocusEnd = selection.focusNode === nativeRange.endContainer && selection.focusOffset === nativeRange.endOffset\n const isFocusStart = selection.focusNode === nativeRange.startContainer && selection.focusOffset === nativeRange.startOffset\n if (!this.docContainer.contains(selection.focusNode)) {\n if (isFocusEnd) {\n const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(0)!)\n if (!nativeNode) {\n return\n }\n nativeRange.setEndAfter(nativeNode.lastChild!)\n } else {\n const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(-1)!)\n if (!nativeNode) {\n return\n }\n nativeRange.setStartBefore(nativeNode.firstChild!)\n }\n }\n\n const startPosition = this.getCorrectedPosition(nativeRange.startContainer, nativeRange.startOffset, isFocusStart)\n const endPosition = nativeRange.collapsed ?\n startPosition :\n this.getCorrectedPosition(nativeRange.endContainer, nativeRange.endOffset, isFocusEnd)\n\n if ([Node.ELEMENT_NODE, Node.TEXT_NODE].includes(nativeRange.commonAncestorContainer?.nodeType as any) &&\n startPosition && endPosition) {\n const abstractSelection = connector.beforeChange(isFocusEnd ? {\n anchorSlot: startPosition.slot,\n anchorOffset: startPosition.offset,\n focusSlot: endPosition.slot,\n focusOffset: endPosition.offset\n } : {\n focusSlot: startPosition.slot,\n focusOffset: startPosition.offset,\n anchorSlot: endPosition.slot,\n anchorOffset: endPosition.offset\n })\n if (!abstractSelection) {\n this.selectionChangeEvent.next(null)\n connector.setSelection(null)\n return\n }\n const { focus, anchor } = this.getPositionByRange(abstractSelection)\n if (focus && anchor) {\n let start = anchor\n let end = focus\n if (isFocusStart) {\n start = focus\n end = anchor\n }\n if (nativeRange.startContainer !== start.node || nativeRange.startOffset !== start.offset) {\n nativeRange.setStart(start.node, start.offset)\n }\n if (nativeRange.endContainer !== end.node || nativeRange.endOffset !== end.offset) {\n nativeRange.setEnd(end.node, end.offset)\n }\n connector.setSelection(abstractSelection)\n if (selection.isCollapsed && (\n rawRange.startContainer !== start.node ||\n rawRange.startOffset !== start.offset ||\n rawRange.endContainer !== end.node ||\n rawRange.endOffset !== end.offset\n )) {\n rawRange.setStart(start.node, start.offset)\n rawRange.setEnd(end.node, end.offset)\n }\n this.selectionChangeEvent.next(nativeRange)\n } else {\n connector.setSelection(null)\n }\n return\n }\n connector.setSelection(null)\n }\n\n private findSelectedNodeAndOffset(slot: Slot, offset: number): {node: Node, offset: number} | null {\n const prev = slot.getContentAtIndex(offset - 1)\n const nodes = this.domAdapter.getNodesBySlot(slot)\n\n if (prev) {\n if (typeof prev !== 'string') {\n const nativeNode = this.domAdapter.getNativeNodeByComponent(prev)!\n return {\n node: nativeNode.parentNode!,\n offset: Array.from(nativeNode.parentNode!.childNodes).indexOf(nativeNode) + 1\n }\n } else if (prev === '\\n') {\n for (const node of nodes) {\n if (node instanceof Text) {\n continue\n }\n if (node.nodeName === 'BR') {\n const position = this.domAdapter.getLocationByNativeNode(node)\n if (position) {\n if (position.endIndex === offset) {\n const parentNode = node.parentNode!\n return {\n node: parentNode,\n offset: Array.from(parentNode.childNodes).indexOf(node as ChildNode) + 1\n }\n }\n }\n }\n }\n }\n }\n const current = slot.getContentAtIndex(offset)\n if (current && typeof current !== 'string') {\n const nativeNode = this.domAdapter.getNativeNodeByComponent(current)!\n return {\n node: nativeNode.parentNode!,\n offset: Array.from(nativeNode.parentNode!.childNodes).indexOf(nativeNode)\n }\n }\n for (const node of nodes) {\n if (node instanceof Element) {\n if (node.tagName === 'BR') {\n const position = this.domAdapter.getLocationByNativeNode(node)\n if (position) {\n if (position.startIndex === offset) {\n const parentNode = node.parentNode!\n return {\n node: parentNode,\n offset: Array.from(parentNode.childNodes).indexOf(node)\n }\n }\n }\n }\n continue\n }\n const position = this.domAdapter.getLocationByNativeNode(node)\n if (position) {\n if (offset >= position.startIndex && offset <= position.endIndex) {\n return {\n node: node,\n offset: offset - position.startIndex\n }\n }\n }\n }\n return null\n }\n\n private getCorrectedPosition(node: Node, offset: number, toAfter: boolean, excludeNodes: Node[] = []): SelectionPosition | null {\n excludeNodes.push(node)\n if (node.nodeType === Node.ELEMENT_NODE) {\n const containerPosition = this.domAdapter.getLocationByNativeNode(node)\n const childNode = node.childNodes[offset]\n if (childNode) {\n const childPosition = this.domAdapter.getLocationByNativeNode(childNode)\n if (childPosition) {\n if (containerPosition) {\n return {\n slot: childPosition.slot,\n offset: childPosition.startIndex\n }\n }\n return this.findFocusNode(childNode, toAfter, excludeNodes)\n }\n return this.findFocusNode(childNode, toAfter, excludeNodes)\n }\n const prevNode = node.childNodes[offset - 1]\n if (prevNode) {\n const prevPosition = this.domAdapter.getLocationByNativeNode(prevNode)\n if (prevPosition && containerPosition) {\n return {\n slot: prevPosition.slot,\n offset: prevPosition.endIndex\n }\n }\n }\n if (containerPosition) {\n return {\n slot: containerPosition.slot,\n offset: containerPosition.endIndex\n }\n }\n const nextNode = toAfter ? node.nextSibling : node.previousSibling\n if (nextNode) {\n return this.findFocusNode(nextNode, toAfter, excludeNodes)\n }\n return this.findFocusNodeByParent(node, toAfter, excludeNodes)\n } else if (node.nodeType === Node.TEXT_NODE) {\n const containerPosition = this.domAdapter.getLocationByNativeNode(node)\n if (containerPosition) {\n return {\n slot: containerPosition.slot,\n offset: containerPosition.startIndex + offset\n }\n }\n const nextNode = toAfter ? node.nextSibling : node.previousSibling\n if (nextNode) {\n return this.findFocusNode(nextNode, toAfter, excludeNodes)\n }\n return this.findFocusNodeByParent(node, toAfter, excludeNodes)\n }\n return null\n }\n\n private findFocusNode(node: Node, toAfter = false, excludeNodes: Node[] = []): SelectionPosition | null {\n if (excludeNodes.includes(node)) {\n const next = toAfter ? node.nextSibling : node.previousSibling\n if (next) {\n return this.findFocusNode(next, toAfter, excludeNodes)\n }\n return this.findFocusNodeByParent(node, toAfter, excludeNodes)\n }\n excludeNodes.push(node)\n const position = this.domAdapter.getLocationByNativeNode(node as any)\n if (position) {\n return {\n slot: position.slot,\n offset: toAfter ? position.startIndex : position.endIndex\n }\n }\n const firstChild = toAfter ? node.firstChild : node.lastChild\n if (firstChild) {\n return this.findFocusNode(firstChild, toAfter, excludeNodes)\n }\n const nextSibling = toAfter ? node.nextSibling : node.previousSibling\n if (nextSibling) {\n return this.findFocusNode(nextSibling, toAfter, excludeNodes)\n }\n return this.findFocusNodeByParent(node, toAfter, excludeNodes)\n }\n\n private findFocusNodeByParent(node: Node, toAfter: boolean, excludeNodes: Node[]) {\n const parentNode = node.parentNode\n if (parentNode) {\n const parentPosition = this.domAdapter.getLocationByNativeNode(parentNode)\n if (parentPosition) {\n return {\n slot: parentPosition.slot,\n offset: toAfter ? parentPosition.endIndex : parentPosition.startIndex\n }\n }\n excludeNodes.push(node)\n return this.findFocusNode(parentNode, toAfter, excludeNodes)\n }\n return null\n }\n}\n","import { Observable } from '@tanbo/stream'\n\nimport { Rect } from './_utils/uikit'\n\nexport interface CaretLimit {\n top: number\n bottom: number\n}\n\nexport interface CaretPosition {\n left: number\n top: number\n height: number\n}\n\nexport interface Caret {\n onPositionChange: Observable<CaretPosition | null>\n readonly rect: Rect\n\n refresh(): void\n}\n\nexport abstract class Input {\n /**\n * @experimental\n */\n abstract composition: boolean\n /**\n * @experimental\n */\n abstract onReady: Promise<void>\n abstract caret: Caret\n abstract disabled: boolean\n\n abstract focus(nativeRange: Range, reFlash: boolean): void\n\n abstract blur(): void\n\n abstract destroy(): void\n}\n","import { distinctUntilChanged, filter, fromEvent, map, merge, Observable, Subject, Subscription } from '@tanbo/stream'\nimport { Injectable } from '@viewfly/core'\nimport {\n Commander,\n CompositionStartEventData,\n ContentType,\n Controller,\n Event,\n invokeListener,\n Keyboard,\n Scheduler,\n Selection,\n Slot,\n Textbus\n} from '@textbus/core'\n\nimport { createElement, getLayoutRectByRange } from './_utils/uikit'\nimport { Parser } from './parser'\nimport { isFirefox, isMac, isSafari, isWindows } from './_utils/env'\nimport { VIEW_MASK } from './injection-tokens'\nimport { Caret, CaretLimit, CaretPosition, Input } from './types'\nimport { DomAdapter } from './dom-adapter'\n\nconst iframeHTML = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\n <title>Textbus</title>\n <style>\n html {position: fixed; left:0; overflow: hidden}\n html, body{height: 100%;width:100%}\n body{margin:0; overflow: hidden}\n textarea{width: 2000px;height: 100%;opacity: 0; padding: 0; outline: none; border: none; position: absolute; left:0; top:0;}\n </style>\n</head>\n<body>\n</body>\n</html>\n`\n\ninterface CaretStyle {\n height: string\n lineHeight: string\n fontSize: string\n}\n\nclass ExperimentalCaret implements Caret {\n onPositionChange: Observable<CaretPosition | null>\n onStyleChange: Observable<CaretStyle>\n elementRef: HTMLElement\n changeFromSelf = false\n\n getLimit = function (): CaretLimit {\n return {\n top: 0,\n bottom: document.documentElement.clientHeight\n }\n }\n\n get rect() {\n return this.caret.getBoundingClientRect()\n }\n\n private timer: any = null\n private caret: HTMLElement\n\n private set display(v: boolean) {\n this._display = v\n this.caret.style.visibility = v ? 'visible' : 'hidden'\n }\n\n private get display() {\n return this._display\n }\n\n private _display = true\n private flashing = true\n\n private subscription = new Subscription()\n\n private positionChangeEvent = new Subject<CaretPosition | null>()\n private styleChangeEvent = new Subject<CaretStyle>()\n private oldRange: Range | null = null\n\n constructor(\n private domRenderer: DomAdapter,\n private scheduler: Scheduler,\n private editorMask: HTMLElement) {\n this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged())\n this.onStyleChange = this.styleChangeEvent.asObservable()\n this.elementRef = createElement('div', {\n styles: {\n position: 'absolute',\n width: '2px',\n pointerEvents: 'none'\n },\n children: [\n this.caret = createElement('span', {\n styles: {\n width: '100%',\n height: '100%',\n position: 'absolute',\n left: 0,\n top: 0\n }\n })\n ]\n })\n\n this.subscription.add(\n fromEvent(document, 'mousedown').subscribe(() => {\n this.flashing = false\n }),\n fromEvent(document, 'mouseup').subscribe(() => {\n this.flashing = true\n }),\n )\n this.editorMask.appendChild(this.elementRef)\n }\n\n refresh() {\n if (this.oldRange) {\n this.show(this.oldRange, false)\n }\n }\n\n show(range: Range, restart: boolean) {\n this.oldRange = range\n if (restart || this.scheduler.lastChangesHasLocalUpdate) {\n clearTimeout(this.timer)\n }\n this.updateCursorPosition(range)\n if (range.collapsed) {\n if (restart || this.scheduler.lastChangesHasLocalUpdate) {\n this.display = true\n const toggleShowHide = () => {\n this.display = !this.display || !this.flashing\n this.timer = setTimeout(toggleShowHide, 400)\n }\n clearTimeout(this.timer)\n this.timer = setTimeout(toggleShowHide, 400)\n }\n } else {\n this.display = false\n clearTimeout(this.timer)\n }\n }\n\n hide() {\n this.display = false\n clearTimeout(this.timer)\n this.positionChangeEvent.next(null)\n }\n\n destroy() {\n clearTimeout(this.timer)\n // this.caret.\n this.subscription.unsubscribe()\n }\n\n private updateCursorPosition(nativeRange: Range) {\n const startContainer = nativeRange.startContainer\n\n const node = (startContainer.nodeType === Node.ELEMENT_NODE ? startContainer : startContainer.parentNode) as HTMLElement\n if (node?.nodeType !== Node.ELEMENT_NODE) {\n this.positionChangeEvent.next(null)\n return\n }\n const compositionNode = this.domRenderer.compositionNode\n if (compositionNode) {\n nativeRange = nativeRange.cloneRange()\n nativeRange.selectNodeContents(compositionNode)\n nativeRange.collapse()\n }\n const rect = getLayoutRectByRange(nativeRange)\n const { fontSize, lineHeight, color, writingMode } = getComputedStyle(node)\n\n let height: number\n if (isNaN(+lineHeight)) {\n const f = parseFloat(lineHeight)\n if (isNaN(f)) {\n height = parseFloat(fontSize)\n } else {\n height = f\n }\n } else {\n height = parseFloat(fontSize) * parseFloat(lineHeight)\n }\n\n const boxHeight = Math.max(Math.floor(Math.max(height, rect.height)), 12)\n // const boxHeight = Math.floor(height)\n\n let rectTop = rect.top\n if (rect.height < height) {\n rectTop -= (height - rect.height) / 2\n }\n\n rectTop = Math.floor(rectTop)\n\n const containerRect = this.editorMask.getBoundingClientRect()\n\n const top = Math.floor(rectTop - containerRect.top)\n const left = Math.floor(rect.left + rect.width / 2 - containerRect.left)\n let rotate = 0\n if (nativeRange.collapsed) {\n rotate = Math.round(Math.atan2(rect.width, rect.height) * 180 / Math.PI)\n\n if (rotate !== 0) {\n const hackEle = document.createElement('span')\n // eslint-disable-next-line max-len\n hackEle.style.cssText = 'display: inline-block; width: 10px; height: 10px; position: relative; contain: layout style size; writing-mode: inherit'\n const pointEle = document.createElement('span')\n pointEle.style.cssText = 'position: absolute; left: 0; top: 0; width:0;height:0'\n hackEle.append(pointEle)\n node.append(hackEle)\n\n const p1 = pointEle.getBoundingClientRect()\n pointEle.style.right = '0'\n pointEle.style.left = ''\n const p2 = pointEle.getBoundingClientRect()\n\n const x = p1.x - p2.x\n const y = p1.y - p2.y\n\n rotate = Math.atan2(y, x) * 180 / Math.PI\n hackEle.remove()\n }\n }\n if (writingMode === 'vertical-lr' || writingMode === 'vertical-rl') {\n rotate += 90\n }\n Object.assign(this.elementRef.style, {\n left: left + 'px',\n top: top + 'px',\n height: boxHeight + 'px',\n lineHeight: boxHeight + 'px',\n fontSize,\n transform: `rotate(${rotate}deg)`,\n })\n\n this.caret.style.backgroundColor = color === 'rgba(0, 0, 0, 0)' ? '#000' : color\n this.styleChangeEvent.next({\n height: boxHeight + 'px',\n lineHeight: boxHeight + 'px',\n fontSize\n })\n this.positionChangeEvent.next({\n left,\n top: rectTop,\n height: boxHeight\n })\n\n if (this.changeFromSelf) {\n this.changeFromSelf = false\n const selfRect = this.elementRef.getBoundingClientRect()\n const scrollContainer = this.getScrollContainer(startContainer)\n const scrollRect = scrollContainer === document.documentElement ?\n { top: 0, bottom: document.documentElement.clientHeight } :\n scrollContainer.getBoundingClientRect()\n const limit = this.getLimit()\n\n const top = Math.max(limit.top, scrollRect.top)\n const bottom = Math.min(limit.bottom, scrollRect.bottom)\n\n if (selfRect.top < top) {\n scrollContainer.scrollTop -= top - selfRect.top\n } else if (selfRect.bottom > bottom) {\n scrollContainer.scrollTop += selfRect.bottom - bottom\n }\n }\n }\n\n private getScrollContainer(container: Node): Element {\n while (container) {\n if (container instanceof Element) {\n const styles = getComputedStyle(container)\n if (styles.overflow !== 'visible' || styles.overflowX !== 'visible' || styles.overflowY !== 'visible') {\n return container\n }\n }\n container = container.parentNode as Node\n }\n return document.documentElement\n }\n}\n\n\n/**\n * Textbus PC 端输入实现\n */\n@Injectable()\nexport class MagicInput extends Input {\n composition = false\n onReady: Promise<void>\n caret: ExperimentalCaret\n\n set disabled(b: boolean) {\n this._disabled = b\n if (b && this.textarea) {\n this.textarea.disabled = b\n }\n }\n\n get disabled() {\n return this._disabled\n }\n\n private isSafari = isSafari()\n private isFirefox = isFirefox()\n private isMac = isMac()\n private isWindows = isWindows()\n private _disabled = false\n private container = this.createEditableFrame()\n\n private subscription = new Subscription()\n private doc!: Document\n\n private textarea: HTMLTextAreaElement | null = null\n\n private isFocus = false\n private nativeFocus = false\n\n private ignoreComposition = false // 有 bug 版本搜狗拼音\n\n constructor(private domAdapter: DomAdapter,\n private parser: Parser,\n private keyboard: Keyboard,\n private commander: Commander,\n private selection: Selection,\n private controller: Controller,\n private scheduler: Scheduler,\n private textbus: Textbus) {\n super()\n this.caret = new ExperimentalCaret(this.domAdapter, this.scheduler, this.textbus.get(VIEW_MASK))\n this.onReady = new Promise<void>(resolve => {\n this.subscription.add(\n fromEvent(this.container, 'load').subscribe(() => {\n const doc = this.container.contentDocument!\n doc.open()\n doc.write(iframeHTML)\n doc.close()\n this.doc = doc\n this.init()\n resolve()\n }),\n controller.onReadonlyStateChange.subscribe(() => {\n if (controller.readonly) {\n this.blur()\n }\n })\n )\n })\n\n this.caret.elementRef.append(this.container)\n }\n\n focus(range: Range, restart: boolean) {\n if (!this.disabled) {\n this.caret.show(range, restart)\n }\n if (this.controller.readonly) {\n return\n }\n if (!this.isFocus) {\n this.textarea?.focus()\n setTimeout(() => {\n if (!this.nativeFocus && this.isFocus) {\n this.reInit()\n }\n })\n }\n this.isFocus = true\n }\n\n blur() {\n this.caret.hide()\n this.textarea?.blur()\n this.isFocus = false\n }\n\n destroy() {\n this.caret.destroy()\n this.subscription.unsubscribe()\n }\n\n private reInit(delay = false) {\n this.subscription.unsubscribe()\n this.textarea?.parentNode?.removeChild(this.textarea)\n this.subscription = new Subscription()\n this.init()\n if (delay) {\n setTimeout(() => {\n this.textarea?.focus()\n })\n } else {\n this.textarea?.focus()\n }\n }\n\n private init() {\n const doc = this.doc\n const contentBody = doc.body\n const textarea = doc.createElement('textarea')\n textarea.disabled = this.disabled\n contentBody.appendChild(textarea)\n this.textarea = textarea\n this.subscription.add(\n fromEvent(textarea, 'blur').subscribe(() => {\n // if (this.isFocus) {\n // this.isFocus = false\n // this.reInit(true)\n // }\n this.isFocus = false\n this.nativeFocus = false\n this.caret.hide()\n if (this.domAdapter.composition) {\n const slot = this.domAdapter.composition.slot\n this.domAdapter.composition = null\n this.domAdapter.compositionNode = null\n slot.__changeMarker__.forceMarkDirtied()\n }\n }),\n fromEvent(textarea, 'focus').subscribe(() => {\n this.nativeFocus = true\n }),\n this.caret.onStyleChange.subscribe(style => {\n Object.assign(textarea.style, style)\n })\n )\n this.handleInput(textarea)\n this.handleShortcut(textarea)\n this.handleDefaultActions(textarea)\n }\n\n private handleDefaultActions(textarea: HTMLTextAreaElement) {\n this.subscription.add(\n fromEvent<ClipboardEvent>(isFirefox() ? textarea : document, 'copy').subscribe(ev => {\n this.copyHandler(ev)\n }),\n fromEvent<ClipboardEvent>(textarea, 'paste').subscribe(ev => {\n this.pasteHandler(ev)\n })\n )\n }\n\n copyHandler(ev: ClipboardEvent) {\n const selection = this.selection\n if (!selection.isSelected) {\n return\n }\n if (selection.startSlot === selection.endSlot && selection.endOffset! - selection.startOffset! === 1) {\n const content = selection.startSlot!.getContentAtIndex(selection.startOffset!)\n if (typeof content === 'object') {\n const clipboardData = ev.clipboardData!\n const nativeSelection = document.getSelection()!\n const range = nativeSelection.getRangeAt(0)\n const div = document.createElement('div')\n const fragment = range.cloneContents()\n div.append(fragment)\n clipboardData.setData('text/html', div.innerHTML)\n clipboardData.setData('text', div.innerText)\n ev.preventDefault()\n }\n }\n }\n\n pasteHandler(ev: ClipboardEvent) {\n const text = ev.clipboardData!.getData('Text')\n\n const types = Array.from(ev.clipboardData!.types || [])\n const files = Array.from(ev.clipboardData!.files)\n if (types.every(type => type === 'Files') && files.length) {\n Promise.all(files.filter(i => {\n return /image/i.test(i.type)\n }).map(item => {\n const reader = new FileReader()\n return new Promise(resolve => {\n reader.onload = (event) => {\n resolve(event.target!.result)\n }\n reader.readAsDataURL(item)\n })\n })).then(urls => {\n const html = urls.map(i => {\n return `<img src=${i}>`\n }).join('')\n this.paste(html, text)\n })\n ev.preventDefault()\n return\n }\n\n const div = this.doc.createElement('div')\n div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0'\n div.contentEditable = 'true'\n this.doc.body.appendChild(div)\n div.focus()\n setTimeout(() => {\n this.doc.body.removeChild(div)\n div.style.cssText = ''\n this.paste(div, text)\n })\n }\n\n private paste(dom: HTMLElement | string, text: string) {\n const slot = this.parser.parse(dom, new Slot([\n ContentType.BlockComponent,\n ContentType.InlineComponent,\n ContentType.Text\n ]))\n\n this.commander.paste(slot, text)\n }\n\n private handleShortcut(textarea: HTMLTextAreaElement) {\n let isWriting = false\n let isIgnore = false\n this.subscription.add(\n fromEvent(textarea, 'compositionstart').subscribe(() => {\n isWriting = true\n }),\n fromEvent(textarea, 'compositionend').subscribe(() => {\n isWriting = false\n }),\n fromEvent<InputEvent>(textarea, 'beforeinput').subscribe(ev => {\n this.ignoreComposition = false\n if (this.isSafari) {\n if (ev.inputType === 'insertFromComposition') {\n isIgnore = true\n }\n }\n }),\n fromEvent<KeyboardEvent>(textarea, 'keydown').pipe(filter(() => {\n if (this.isSafari && isIgnore) {\n isIgnore = false\n return false\n }\n return !isWriting // || !this.textarea.value\n })).subscribe(ev => {\n this.ignoreComposition = false\n let key = ev.key\n const keys = ')!@#$%^Z&*('\n const b = key === 'Process' && /Digit\\d/.test(ev.code) && ev.shiftKey\n if (b) {\n // 大小写锁定为大写 + 全角 + shift + 数字键,还存在问题\n key = keys.charAt(+ev.code.substring(5))\n ev.preventDefault()\n }\n this.caret.changeFromSelf = true\n const is = this.keyboard.execShortcut({\n key: key,\n altKey: ev.altKey,\n shiftKey: ev.shiftKey,\n modKey: this.isMac ? ev.metaKey : ev.ctrlKey,\n agent: {\n key: ev.key,\n code: ev.code,\n keyCode: ev.keyCode,\n }\n })\n if (is) {\n this.ignoreComposition = true\n ev.preventDefault()\n } else {\n this.caret.changeFromSelf = false\n }\n })\n )\n }\n\n private handleInput(textarea: HTMLTextAreaElement) {\n let startIndex = 0\n this.subscription.add(\n fromEvent<CompositionEvent>(textarea, 'compositionstart').pipe(filter(() => {\n return !this.ignoreComposition\n })).subscribe(() => {\n if (!this.selection.isCollapsed) {\n this.caret.changeFromSelf = true\n this.commander.delete()\n }\n this.composition = true\n startIndex = this.selection.startOffset!\n const startSlot = this.selection.startSlot!\n const event = new Event<Slot, CompositionStartEventData>(startSlot, {\n index: startIndex\n })\n invokeListener(startSlot.parent!, 'onCompositionStart', event)\n }),\n fromEvent<CompositionEvent>(textarea, 'compositionupdate').pipe(filter(() => {\n return !this.ignoreComposition\n })).pipe(distinctUntilChanged((prev, next) => {\n return prev.data !== next.data\n })).subscribe(ev => {\n if (ev.data === ' ') {\n // 处理搜狗五笔不符合 composition 事件预期,会意外跳光标的问题\n return\n }\n const startSlot = this.selection.startSlot!\n this.domAdapter.composition = {\n slot: startSlot,\n text: ev.data,\n offset: ev.data.length,\n index: startIndex\n }\n\n this.caret.changeFromSelf = true\n this.caret.refresh()\n const event = new Event(startSlot, {\n index: startIndex,\n data: ev.data\n })\n\n invokeListener(startSlot.parent!, 'onCompositionUpdate', event)\n startSlot.__changeMarker__.forceMarkDirtied()\n })\n )\n let isCompositionEnd = false\n this.subscription.add(\n merge(\n fromEvent<InputEvent>(textarea, 'beforeinput').pipe(\n filter(ev => {\n ev.preventDefault()\n if (this.isFirefox && ev.inputType === 'insertFromPaste') {\n return false\n }\n if (this.isSafari) {\n isCompositionEnd = ev.inputType === 'insertFromComposition'\n return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition'\n }\n return !ev.isComposing && !!ev.data\n }),\n map(ev => {\n return ev.data as string\n })\n ),\n this.isSafari ? new Observable<string>() : fromEvent<CompositionEvent>(textarea, 'compositionend')\n .pipe(filter(() => {\n return !this.ignoreComposition\n })).pipe(\n map(ev => {\n isCompositionEnd = true\n ev.preventDefault()\n textarea.value = ''\n return ev.data\n })\n )\n ).subscribe(text => {\n this.composition = false\n this.domAdapter.composition = null\n if (text) {\n this.caret.changeFromSelf = true\n this.commander.write(text)\n } else {\n this.selection.startSlot?.__changeMarker__.forceMarkDirtied()\n }\n if (isCompositionEnd) {\n const startSlot = this.selection.startSlot\n if (startSlot) {\n const event = new Event<Slot>(startSlot, null)\n invokeListener(startSlot.parent!, 'onCompositionEnd', event)\n }\n }\n isCompositionEnd = false\n })\n )\n }\n\n private createEditableFrame() {\n return createElement('iframe', {\n attrs: {\n scrolling: 'no'\n },\n styles: {\n border: 'none',\n width: '100%',\n display: 'block',\n height: '100%',\n position: 'relative',\n top: this.isWindows ? '3px' : '0'\n }\n }) as HTMLIFrameElement\n }\n}\n","import { Injectable, Optional } from '@viewfly/core'\nimport { Selection, AbstractSelection, Scheduler, Textbus, SelectionPaths } from '@textbus/core'\nimport { fromEvent, Subject, Subscription } from '@tanbo/stream'\n\nimport { VIEW_CONTAINER } from './injection-tokens'\nimport { SelectionBridge } from './selection-bridge'\nimport { createElement, getLayoutRectByRange, Rect } from './_utils/uikit'\n\nexport interface SelectionRect extends Rect {\n color: string\n username: string\n}\n\nexport interface RemoteSelectionCursor {\n cursor: HTMLElement\n anchor: HTMLElement\n userTip: HTMLElement\n}\n\n/**\n * 远程光标绘制范围计算代理类,可用于定制特定场景下的远程选区绘制,如表格有选区,不会遵守常见的文档流形式\n */\nexport abstract class CollaborateSelectionAwarenessDelegate {\n abstract getRects(abstractSelection: AbstractSelection,\n nativeRange: Range,\n selectionCursor: UserSelectionCursor): false | Rect[]\n}\n\n/**\n * 协作用户虚拟光标信息\n */\nexport interface UserSelectionCursor {\n username: string\n color: string\n selection: SelectionPaths\n data?: any\n}\n\n/**\n * 协作光标绘制类\n */\n@Injectable()\nexport class CollaborateCursor {\n private host = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n zIndex: 1\n }\n })\n private canvasContainer = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n overflow: 'hidden'\n }\n })\n private canvas = createElement('canvas', {\n styles: {\n position: 'absolute',\n opacity: 0.5,\n left: 0,\n top: 0,\n width: '100%',\n height: document.documentElement.clientHeight + 'px',\n pointerEvents: 'none',\n }\n }) as HTMLCanvasElement\n private context = this.canvas.getContext('2d')!\n private tooltips = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n fontSize: '12px',\n zIndex: 10\n }\n })\n\n private onRectsChange = new Subject<SelectionRect[]>()\n\n private subscription = new Subscription()\n private selectionCursors: UserSelectionCursor[] = []\n private container: HTMLElement\n private ratio = window.devicePixelRatio || 1\n\n constructor(textbus: Textbus,\n private nativeSelection: SelectionBridge,\n private scheduler: Scheduler,\n private selection: Selection,\n @Optional() private awarenessDelegate?: CollaborateSelectionAwarenessDelegate) {\n this.container = textbus.get(VIEW_CONTAINER)\n this.canvasContainer.append(this.canvas)\n this.host.append(this.canvasContainer, this.tooltips)\n this.container.prepend(this.host)\n this.subscription.add(this.onRectsChange.subscribe(rects => {\n for (const rect of rects) {\n this.context.fillStyle = rect.color\n this.context.beginPath()\n this.context.rect(rect.left, rect.top, rect.width, rect.height)\n this.context.fill()\n this.context.closePath()\n }\n }), fromEvent(window, 'resize').subscribe(() => {\n this.canvas.style.height = document.documentElement.clientHeight + 'px'\n this.refresh()\n }), this.scheduler.onDocChanged.subscribe(() => {\n this.refresh()\n }))\n }\n\n /**\n * 刷新协作光标,由于 Textbus 只会绘制可视区域的光标,当可视区域发生变化时,需要重新绘制\n */\n refresh() {\n this.draw(this.selectionCursors)\n }\n\n destroy() {\n this.subscription.unsubscribe()\n }\n\n /**\n * 根据远程用户光标位置,绘制协作光标\n * @param paths\n */\n draw(paths: UserSelectionCursor[]) {\n this.selectionCursors = paths\n const containerRect = this.container.getBoundingClientRect()\n this.canvas.style.top = containerRect.top * -1 + 'px'\n this.canvas.width = this.canvas.offsetWidth * this.ratio\n this.canvas.height = this.canvas.offsetHeight * this.ratio\n this.context.scale(this.ratio, this.ratio)\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)\n\n const users: SelectionRect[] = []\n\n paths.filter(i => {\n return i.selection.anchor.length && i.selection.focus.length\n }).forEach(item => {\n const anchorPaths = [...item.selection.anchor]\n const focusPaths = [...item.selection.focus]\n const anchorOffset = anchorPaths.pop()!\n const anchorSlot = this.selection.findSlotByPaths(anchorPaths)\n const focusOffset = focusPaths.pop()!\n const focusSlot = this.selection.findSlotByPaths(focusPaths)\n if (!anchorSlot || !focusSlot) {\n return\n }\n\n const { focus, anchor } = this.nativeSelection.getPositionByRange({\n focusOffset,\n anchorOffset,\n focusSlot,\n anchorSlot\n })\n if (!focus || !anchor) {\n return\n }\n const nativeRange = document.createRange()\n try {\n nativeRange.setStart(anchor.node, anchor.offset)\n nativeRange.setEnd(focus.node, focus.offset)\n } catch (e) {\n return\n }\n if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {\n nativeRange.setStart(focus.node, focus.offset)\n nativeRange.setEnd(anchor.node, anchor.offset)\n }\n\n let rects: Rect[] | DOMRectList | false = false\n if (this.awarenessDelegate) {\n rects = this.awarenessDelegate.getRects({\n focusOffset,\n anchorOffset,\n focusSlot,\n anchorSlot\n }, nativeRange, item)\n }\n if (!rects) {\n rects = nativeRange.getClientRects()\n }\n const selectionRects: SelectionRect[] = []\n for (let i = rects.length - 1; i >= 0; i--) {\n const rect = rects[i]\n selectionRects.push({\n color: item.color,\n username: item.username,\n left: rect.left - containerRect.left,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n })\n }\n this.onRectsChange.next(selectionRects)\n\n const cursorRange = nativeRange.cloneRange()\n cursorRange.setStart(focus.node, focus.offset)\n cursorRange.collapse(true)\n\n const cursorRect = getLayoutRectByRange(cursorRange)\n\n const rect: SelectionRect = {\n username: item.username,\n color: item.color,\n left: cursorRect.left - containerRect.left,\n top: cursorRect.top - containerRect.top,\n width: 1,\n height: cursorRect.height\n }\n if (rect.left < 0 || rect.top < 0 || rect.left > containerRect.width) {\n return\n }\n users.push(rect)\n })\n this.drawUserCursor(users)\n }\n\n protected drawUserCursor(rects: SelectionRect[]) {\n for (let i = 0; i < rects.length; i++) {\n const rect = rects[i]\n const { cursor, userTip, anchor } = this.getUserCursor(i)\n Object.assign(cursor.style, {\n left: rect.left + 'px',\n top: rect.top + 'px',\n width: rect.width + 'px',\n height: rect.height + 'px',\n background: rect.color,\n display: 'block'\n })\n anchor.style.background = rect.color\n userTip.innerText = rect.username\n userTip.style.background = rect.color\n }\n\n for (let i = rects.length; i < this.tooltips.children.length; i++) {\n this.tooltips.removeChild(this.tooltips.children[i])\n }\n }\n\n private getUserCursor(index: number): RemoteSelectionCursor {\n let child: HTMLElement = this.tooltips.children[index] as HTMLElement\n if (child) {\n const anchor = child.children[0] as HTMLElement\n return {\n cursor: child,\n anchor,\n userTip: anchor.children[0] as HTMLElement\n }\n }\n const userTip = createElement('span', {\n styles: {\n position: 'absolute',\n left: '50%',\n transform: 'translateX(-50%)',\n marginBottom: '2px',\n bottom: '100%',\n whiteSpace: 'nowrap',\n color: '#fff',\n boxShadow: '0 1px 2px rgba(0,0,0,.1)',\n opacity: 0.8,\n borderRadius: '3px',\n padding: '3px 5px',\n pointerEvents: 'none',\n }\n })\n\n const anchor = createElement('span', {\n styles: {\n position: 'absolute',\n top: '-2px',\n left: '-2px',\n width: '5px',\n height: '5px',\n borderRadius: '50%',\n pointerEvents: 'auto',\n pointer: 'cursor',\n },\n children: [userTip]\n })\n child = createElement('span', {\n styles: {\n position: 'absolute',\n },\n children: [\n anchor\n ]\n })\n this.tooltips.append(child)\n return {\n cursor: child,\n anchor,\n userTip\n }\n }\n}\n","import { Injectable } from '@viewfly/core'\nimport {\n distinctUntilChanged,\n filter,\n fromEvent,\n map,\n merge,\n Observable,\n Subject,\n Subscription,\n} from '@tanbo/stream'\nimport {\n Commander,\n CompositionStartEventData,\n CompositionUpdateEventData,\n ContentType,\n Controller,\n Event,\n invokeListener,\n Keyboard,\n Selection,\n Slot,\n Textbus\n} from '@textbus/core'\n\nimport { Caret, CaretPosition, Input } from './types'\nimport { VIEW_DOCUMENT } from './injection-tokens'\nimport { isSafari, isMac, isMobileBrowser, isFirefox } from './_utils/env'\nimport { Parser } from './parser'\nimport { getLayoutRectByRange } from './_utils/uikit'\nimport { DomAdapter } from './dom-adapter'\n\nclass NativeCaret implements Caret {\n onPositionChange: Observable<CaretPosition | null>\n\n set nativeRange(range: Range | null) {\n this._nativeRange = range\n if (range) {\n const r = range.cloneRange()\n r.collapse(true)\n const rect = getLayoutRectByRange(r)\n this.positionChangeEvent.next({\n left: rect.left,\n top: rect.top,\n height: rect.height\n })\n } else {\n this.positionChangeEvent.next(null)\n }\n }\n\n get nativeRange() {\n return this._nativeRange\n }\n\n get rect() {\n if (this.nativeRange) {\n const range = this.nativeRange.cloneRange()\n range.collapse(true)\n return getLayoutRectByRange(range)\n }\n return {\n left: 0,\n top: 0,\n width: 0,\n height: 0\n }\n }\n\n private _nativeRange: Range | null = null\n private subs: Subscription[] = []\n\n private positionChangeEvent = new Subject<CaretPosition | null>()\n\n constructor() {\n this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged())\n }\n\n refresh() {\n //\n }\n\n destroy() {\n this.subs.forEach(i => i.unsubscribe())\n this.subs = []\n }\n}\n\n@Injectable()\nexport class NativeInput extends Input {\n caret = new NativeCaret()\n\n composition = false\n // compositionState: CompositionState | null = null\n\n onReady = Promise.resolve()\n\n set disabled(b: boolean) {\n this._disabled = b\n if (this.controller.readonly) {\n this.documentView.contentEditable = 'false'\n return\n }\n this.documentView.contentEditable = b ? 'false' : 'true'\n }\n\n get disabled() {\n return this._disabled\n }\n\n private _disabled = false\n private documentView: HTMLElement\n private nativeSelection = document.getSelection()!\n\n private subscription = new Subscription()\n private nativeRange: Range | null = null\n\n private isSafari = isSafari()\n private isMac = isMac()\n private isMobileBrowser = isMobileBrowser()\n\n private ignoreComposition = false // 有 bug 版本搜狗拼音\n\n constructor(textbus: Textbus,\n private parser: Parser,\n private selection: Selection,\n private keyboard: Keyboard,\n private domAdapter: DomAdapter,\n private commander: Commander,\n private controller: Controller) {\n super()\n this.documentView = textbus.get(VIEW_DOCUMENT)\n if (!controller.readonly) {\n this.documentView.contentEditable = 'true'\n }\n this.subscription.add(\n controller.onReadonlyStateChange.subscribe(() => {\n this.documentView.contentEditable = controller.readonly ? 'false' : 'true'\n })\n )\n this.handleShortcut(this.documentView)\n this.handleInput(this.documentView)\n this.handleDefaultActions(this.documentView)\n }\n\n focus(nativeRange: Range) {\n if (this.controller.readonly) {\n return\n }\n this.caret.nativeRange = nativeRange\n this.nativeRange = nativeRange\n }\n\n blur() {\n if (this.nativeRange && this.nativeSelection.rangeCount > 0) {\n const current = this.nativeSelection.getRangeAt(0)\n if (current === this.nativeRange) {\n this.nativeSelection.removeAllRanges()\n this.nativeRange = null\n return\n }\n }\n }\n\n destroy() {\n this.caret.destroy()\n this.subscription.unsubscribe()\n }\n\n private handleDefaultActions(textarea: HTMLElement) {\n this.subscription.add(\n fromEvent<ClipboardEvent>(isFirefox() ? textarea : document, 'copy').subscribe(ev => {\n this.copyHandler(ev)\n }),\n fromEvent<ClipboardEvent>(textarea, 'paste').subscribe(ev => {\n this.pasteHandler(ev)\n })\n )\n }\n\n copyHandler(ev: ClipboardEvent) {\n const selection = this.selection\n if (!selection.isSelected) {\n return\n }\n if (selection.startSlot === selection.endSlot && selection.endOffset! - selection.startOffset! === 1) {\n const content = selection.startSlot!.getContentAtIndex(selection.startOffset!)\n if (typeof content === 'object') {\n const clipboardData = ev.clipboardData!\n const nativeSelection = document.getSelection()!\n const range = nativeSelection.getRangeAt(0)\n const div = document.createElement('div')\n const fragment = range.cloneContents()\n div.append(fragment)\n clipboardData.setData('text/html', div.innerHTML)\n clipboardData.setData('text', div.innerText)\n ev.preventDefault()\n }\n }\n }\n\n pasteHandler(ev: ClipboardEvent) {\n const text = ev.clipboardData!.getData('Text')\n\n const types = Array.from(ev.clipboardData!.types || [])\n const files = Array.from(ev.clipboardData!.files)\n if (types.every(type => type === 'Files') && files.length) {\n Promise.all(files.filter(i => {\n return /image/i.test(i.type)\n }).map(item => {\n const reader = new FileReader()\n return new Promise(resolve => {\n reader.onload = (event) => {\n resolve(event.target!.result)\n }\n reader.readAsDataURL(item)\n })\n })).then(urls => {\n const html = urls.map(i => {\n return `<img src=${i}>`\n }).join('')\n this.paste(html, text)\n })\n ev.preventDefault()\n return\n }\n\n const div = document.createElement('div')\n div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0'\n div.contentEditable = 'true'\n document.body.appendChild(div)\n div.focus()\n setTimeout(() => {\n document.body.removeChild(div)\n div.style.cssText = ''\n this.paste(div, text)\n })\n }\n\n private paste(dom: HTMLElement | string, text: string) {\n const slot = this.parser.parse(dom, new Slot([\n ContentType.BlockComponent,\n ContentType.InlineComponent,\n ContentType.Text\n ]))\n\n this.commander.paste(slot, text)\n }\n\n private handleShortcut(input: HTMLElement) {\n let isWriting = false\n let isIgnore = false\n this.subscription.add(\n fromEvent(input, 'compositionstart').subscribe(() => {\n isWriting = true\n }),\n fromEvent(input, 'compositionend').subscribe(() => {\n isWriting = false\n }),\n fromEvent<InputEvent>(input, 'beforeinput').subscribe(ev => {\n if (this.isSafari) {\n if (ev.inputType === 'insertFromComposition') {\n isIgnore = true\n }\n }\n }),\n fromEvent<KeyboardEvent>(input, 'keydown').pipe(filter(() => {\n if (this.isSafari && isIgnore) {\n isIgnore = false\n return false\n }\n return !isWriting // || !this.textarea.value\n })).subscribe(ev => {\n this.ignoreComposition = false\n let key = ev.key\n const keys = ')!@#$%^Z&*('\n const b = key === 'Process' && /Digit\\d/.test(ev.code) && ev.shiftKey\n if (b) {\n key = keys.charAt(+ev.code.substring(5))\n ev.preventDefault()\n }\n const is = this.keyboard.execShortcut({\n key: key,\n altKey: ev.altKey,\n shiftKey: ev.shiftKey,\n modKey: this.isMac ? ev.metaKey : ev.ctrlKey,\n agent: {\n key: ev.key,\n keyCode: ev.keyCode,\n code: ev.code\n }\n })\n if (is) {\n this.ignoreComposition = true\n ev.preventDefault()\n }\n })\n )\n }\n\n private handleInput(input: HTMLElement) {\n if (this.isMobileBrowser) {\n this.handleMobileInput(input)\n } else {\n this.handlePCInput(input)\n }\n }\n\n private handleMobileInput(input: HTMLElement) {\n let isCompositionStart = true\n let startIndex: number\n const compositionStart = () => {\n this.composition = true\n startIndex = this.selection.startOffset!\n const startSlot = this.selection.startSlot!\n const event = new Event<Slot, CompositionStartEventData>(startSlot, {\n index: startIndex\n })\n invokeListener(startSlot.parent!, 'onCompositionStart', event)\n }\n const compositionUpdate = (data: string) => {\n const startSlot = this.selection.startSlot!\n const event = new Event<Slot, CompositionUpdateEventData>(startSlot, {\n index: startIndex,\n data\n })\n\n invokeListener(startSlot.parent!, 'onCompositionUpdate', event)\n }\n const compositionEnd = (data: string) => {\n this.composition = false\n\n if (data) {\n this.commander.write(data)\n }\n const startSlot = this.selection.startSlot\n if (startSlot) {\n const event = new Event<Slot>(startSlot, null)\n invokeListener(startSlot.parent!, 'onCompositionEnd', event)\n }\n }\n this.subscription.add(\n fromEvent(input, 'compositionstart').subscribe(() => {\n compositionStart()\n }),\n fromEvent<CompositionEvent>(input, 'compositionupdate').subscribe(ev => {\n compositionUpdate(ev.data)\n }),\n fromEvent<CompositionEvent>(input, 'compositionend').subscribe(ev => {\n compositionEnd(ev.data)\n const startContainer = this.nativeSelection.focusNode\n if (startContainer instanceof Text && startContainer.textContent === ev.data) {\n startContainer.remove()\n }\n }),\n fromEvent<InputEvent>(input, 'beforeinput').subscribe(ev => {\n switch (ev.inputType) {\n case 'insertText':\n if (ev.data) {\n this.commander.write(ev.data)\n ev.preventDefault()\n }\n break\n case 'insertCompositionText':\n if (isCompositionStart) {\n isCompositionStart = false\n compositionStart()\n } else {\n compositionUpdate(ev.data || '')\n }\n break\n case 'deleteCompositionText':\n this.composition = false\n break\n case 'deleteContentBackward': {\n this.composition = false\n const range = ev.getTargetRanges()[0]\n if (!range) {\n break\n }\n const location = this.domAdapter.getLocationByNativeNode(range.startContainer)!\n const startSlot = this.selection.startSlot\n if (startSlot) {\n this.selection.setBaseAndExtent(\n startSlot,\n location.startIndex + range.startOffset,\n startSlot,\n location.startIndex + range.endOffset)\n\n this.commander.delete()\n }\n break\n }\n case 'insertReplacementText': {\n this.composition = false\n const range = ev.getTargetRanges()[0]\n const location = this.domAdapter.getLocationByNativeNode(range.startContainer)!\n const startSlot = this.selection.startSlot!\n this.selection.setBaseAndExtent(\n startSlot,\n location.startIndex + range.startOffset,\n startSlot,\n location.startIndex + range.endOffset)\n\n this.commander.delete()\n const text = ev.dataTransfer?.getData('text') || ev.data || null\n if (text) {\n this.commander.write(text)\n }\n break\n }\n //\n // case 'insertFromComposition': {\n // compositionEnd(ev.data || '')\n // break\n // }\n }\n })\n )\n }\n\n private handlePCInput(input: HTMLElement) {\n let startIndex = 0\n let isCompositionEnd = false\n this.subscription.add(\n fromEvent(input, 'compositionstart').pipe(filter(() => {\n return !this.ignoreComposition\n })).subscribe(() => {\n this.composition = true\n startIndex = this.selection.startOffset!\n const startSlot = this.selection.startSlot!\n const event = new Event<Slot, CompositionStartEventData>(startSlot, {\n index: startIndex\n })\n invokeListener(startSlot.parent!, 'onCompositionStart', event)\n }),\n fromEvent<CompositionEvent>(input, 'compositionupdate').pipe(filter(() => {\n return !this.ignoreComposition\n })).subscribe(ev => {\n const startSlot = this.selection.startSlot!\n const event = new Event(startSlot, {\n index: startIndex,\n data: ev.data\n })\n\n invokeListener(startSlot.parent!, 'onCompositionUpdate', event)\n }),\n merge(\n fromEvent<InputEvent>(input, 'beforeinput').pipe(\n map(ev => {\n ev.preventDefault()\n if (ev.inputType === 'insertCompositionText') {\n return null\n }\n if (ev.inputType === 'insertReplacementText') {\n const range = ev.getTargetRanges()[0]\n const location = this.domAdapter.getLocationByNativeNode(range.startContainer)!\n const startSlot = this.selection.startSlot!\n this.selection.setBaseAndExtent(\n startSlot,\n location.startIndex + range.startOffset,\n startSlot,\n location.startIndex + range.endOffset)\n\n this.commander.delete()\n return ev.dataTransfer?.getData('text') || ev.data || null\n }\n isCompositionEnd = ev.inputType === 'insertFromComposition'\n if (isCompositionEnd && this.composition) {\n return null\n }\n if (this.isSafari) {\n if (ev.inputType === 'insertText' || isCompositionEnd) {\n return ev.data\n }\n }\n if (!ev.isComposing && !!ev.data) {\n return ev.data\n }\n return null\n }),\n filter(text => {\n return text\n })\n ),\n this.isSafari ? new Observable<string>() :\n fromEvent<CompositionEvent>(input, 'compositionend').pipe(filter(() => {\n return !this.ignoreComposition\n })).pipe(\n filter(() => {\n return this.composition\n }),\n map(ev => {\n isCompositionEnd = true\n ev.preventDefault()\n return ev.data\n }),\n filter(() => {\n const b = this.ignoreComposition\n this.ignoreComposition = false\n return !b\n })\n )\n ).subscribe(text => {\n this.composition = false\n if (text) {\n const startContainer = this.nativeSelection.focusNode\n if (startContainer instanceof Text && startContainer.textContent === text) {\n startContainer.remove()\n }\n this.commander.write(text)\n }\n if (isCompositionEnd) {\n const startSlot = this.selection.startSlot\n if (startSlot) {\n const event = new Event<Slot>(startSlot, null)\n invokeListener(startSlot.parent!, 'onCompositionEnd', event)\n }\n }\n isCompositionEnd = false\n })\n )\n }\n}\n","import { Adapter } from '@textbus/core'\nimport { Subject } from '@tanbo/stream'\n\nimport { createElement } from './_utils/uikit'\nimport { VIEW_DOCUMENT } from './injection-tokens'\n\nexport abstract class DomAdapter<\n ViewComponent extends object = object,\n ViewElement extends object = object> extends Adapter<Element, Node, ViewComponent, ViewElement> {\n onViewUpdated = new Subject<void>()\n host = createElement('div', {\n styles: {\n cursor: 'text',\n wordBreak: 'break-all',\n boxSizing: 'border-box',\n flex: 1,\n outline: 'none'\n },\n attrs: {\n 'data-textbus-view': VIEW_DOCUMENT,\n },\n props: {\n id: 'textbus-' + Number((Math.random() + '').substring(2)).toString(16)\n }\n })\n}\n","import {\n ComponentConstructor,\n Component,\n ComponentLiteral,\n FocusManager,\n makeError,\n Module,\n NativeSelectionBridge,\n Registry,\n Textbus,\n Adapter,\n} from '@textbus/core'\nimport { Provider } from '@viewfly/core'\nimport { distinctUntilChanged, map, Subject } from '@tanbo/stream'\n\nimport { AttributeLoader, ComponentLoader, FormatLoader, Parser } from './parser'\nimport { EDITOR_OPTIONS, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK } from './injection-tokens'\nimport { SelectionBridge } from './selection-bridge'\nimport { Input } from './types'\nimport { MagicInput } from './magic-input'\nimport { CollaborateCursor } from './collaborate-cursor'\nimport { createElement } from './_utils/uikit'\nimport { NativeInput } from './native-input'\nimport { DomAdapter } from './dom-adapter'\n\nconst browserErrorFn = makeError('BrowserModule')\n\n/**\n * Textbus PC 端配置接口\n */\nexport interface ViewOptions {\n /** 跨平台适配器 */\n adapter: DomAdapter<any, any>\n\n /** 编辑器根节点 */\n renderTo(): HTMLElement\n\n /** 自动获取焦点 */\n autoFocus?: boolean\n /** 编辑区最小高度 */\n minHeight?: string\n /** 组件加载器 */\n componentLoaders?: ComponentLoader[]\n /** 格式加载器 */\n formatLoaders?: FormatLoader<any>[]\n /** 属性加载器 */\n attributeLoaders?: AttributeLoader<any>[]\n /** 使用 contentEditable 作为编辑器控制可编辑范围 */\n useContentEditable?: boolean\n}\n\nexport class BrowserModule implements Module {\n providers: Provider[]\n\n private workbench!: HTMLElement\n\n constructor(public config: ViewOptions) {\n const { mask, wrapper } = BrowserModule.createLayout()\n wrapper.prepend(config.adapter.host)\n if (config.minHeight) {\n config.adapter.host.style.minHeight = config.minHeight\n }\n this.providers = [{\n provide: EDITOR_OPTIONS,\n useValue: config\n }, {\n provide: VIEW_CONTAINER,\n useValue: wrapper\n }, {\n provide: VIEW_DOCUMENT,\n useValue: config.adapter.host\n }, {\n provide: VIEW_MASK,\n useValue: mask\n }, {\n provide: NativeSelectionBridge,\n useExisting: SelectionBridge\n }, {\n provide: Input,\n useClass: config.useContentEditable ? NativeInput : MagicInput\n }, {\n provide: Adapter,\n useValue: config.adapter\n }, {\n provide: DomAdapter,\n useValue: config.adapter\n }, {\n provide: FocusManager,\n useFactory: (input: Input): FocusManager => {\n const focusEvent = new Subject<void>()\n const blurEvent = new Subject<void>()\n input.caret.onPositionChange.pipe(\n map(p => !!p),\n distinctUntilChanged()\n ).subscribe(b => {\n if (b) {\n focusEvent.next()\n } else {\n blurEvent.next()\n }\n })\n return {\n onFocus: focusEvent,\n onBlur: blurEvent\n }\n },\n deps: [Input]\n },\n Parser,\n SelectionBridge,\n CollaborateCursor\n ]\n\n this.workbench = wrapper\n }\n\n /**\n * 解析 HTML 并返回一个组件实例\n * @param html 要解析的 HTML\n * @param rootComponentLoader 文档根组件加载器\n * @param textbus\n */\n readDocumentByHTML(html: string, rootComponentLoader: ComponentLoader, textbus: Textbus): Component {\n const parser = textbus.get(Parser)\n const doc = parser.parseDoc(html, rootComponentLoader)\n if (doc instanceof Component) {\n return doc\n }\n throw browserErrorFn('rootComponentLoader must return a component instance.')\n }\n\n /**\n * 将组件数据解析到组件实例中\n * @param data 要解析的 JSON 数据\n * @param rootComponent 根组件\n * @param textbus\n */\n readDocumentByComponentLiteral(data: ComponentLiteral, rootComponent: ComponentConstructor, textbus: Textbus): Component {\n const registry = textbus.get(Registry)\n return registry.createComponentByFactory(data, rootComponent)\n }\n\n async setup(textbus: Textbus) {\n const host = this.config.renderTo()\n if (!(host instanceof HTMLElement)) {\n throw browserErrorFn('view container is not a HTMLElement')\n }\n\n host.append(this.workbench)\n await textbus.get(Input).onReady\n return () => {\n this.workbench.remove()\n }\n }\n\n onAfterStartup(textbus: Textbus) {\n if (this.config.autoFocus) {\n textbus.focus()\n }\n }\n\n onDestroy(textbus: Textbus) {\n textbus.get(Input).destroy()\n textbus.get(SelectionBridge).destroy()\n textbus.get(CollaborateCursor).destroy()\n }\n\n private static createLayout() {\n const mask = createElement('div', {\n attrs: {\n 'data-textbus-view': VIEW_MASK,\n },\n styles: {\n position: 'absolute',\n left: 0,\n right: 0,\n top: 0,\n bottom: 0,\n pointerEvents: 'none',\n // overflow: 'hidden'\n }\n })\n const maskWrapper = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n right: 0,\n top: 0,\n bottom: 0,\n margin: '0 -2px',\n zIndex: 1,\n pointerEvents: 'none',\n overflow: 'hidden'\n },\n children: [mask]\n })\n const wrapper = createElement('div', {\n attrs: {\n 'data-textbus-view': VIEW_CONTAINER,\n },\n styles: {\n display: 'flex',\n minHeight: '100%',\n position: 'relative',\n flexDirection: 'column'\n },\n children: [maskWrapper]\n })\n return {\n wrapper,\n mask\n }\n }\n}\n"],"names":["createElement","tagName","options","el","key","item","getLayoutRectByRange","range","startContainer","startOffset","parentNode","beforeNode","rect","range2","offsetNode","isInsertBefore","lastChild","span","isWindows","isMac","isSafari","isFirefox","isMobileBrowser","EDITOR_OPTIONS","InjectionToken","VIEW_CONTAINER","VIEW_DOCUMENT","VIEW_MASK","Parser","textbus","componentLoaders","formatLoaders","attributeLoaders","html","rootComponentLoader","element","childSlot","slotRootElement","slotContentHostElement","rootSlot","slot","schema","t","result","Slot","i","textContent","formats","f","startIndex","startNode","endIndex","slotContentElement","a","r","formatItems","__decorateClass","Injectable","__decorateParam","SelectionBridge","config","controller","selection","rootComponentRef","input","scheduler","domAdapter","filter","fromEvent","ev","target","Subject","connector","location","focus","anchor","nativeRange","abstractSelection","fromLocal","tryOffset","position","len","e","bind","currentPosition","toNext","p","startLeft","isToPrevLine","loopCount","minLeft","focusSlot","focusOffset","minTop","oldPosition","oldLeft","rect2","isToNextLine","maxRight","isUpdating","delay","rawRange","isFocusEnd","isFocusStart","nativeNode","startPosition","endPosition","start","end","offset","prev","nodes","node","current","toAfter","excludeNodes","containerPosition","childNode","childPosition","prevNode","prevPosition","nextNode","next","firstChild","nextSibling","parentPosition","Input","iframeHTML","ExperimentalCaret","domRenderer","editorMask","distinctUntilChanged","v","Subscription","restart","toggleShowHide","compositionNode","fontSize","lineHeight","color","writingMode","height","boxHeight","rectTop","containerRect","top","left","rotate","hackEle","pointEle","p1","p2","x","y","selfRect","scrollContainer","scrollRect","limit","bottom","container","styles","MagicInput","parser","keyboard","commander","resolve","doc","b","contentBody","textarea","style","clipboardData","div","fragment","text","types","files","type","reader","event","urls","dom","ContentType","isWriting","isIgnore","startSlot","Event","invokeListener","isCompositionEnd","merge","map","Observable","CollaborateSelectionAwarenessDelegate","CollaborateCursor","nativeSelection","awarenessDelegate","rects","paths","users","anchorPaths","focusPaths","anchorOffset","anchorSlot","selectionRects","cursorRange","cursorRect","cursor","userTip","index","child","Optional","NativeCaret","NativeInput","isCompositionStart","compositionStart","compositionUpdate","data","compositionEnd","DomAdapter","Adapter","browserErrorFn","makeError","BrowserModule","mask","wrapper","NativeSelectionBridge","FocusManager","focusEvent","blurEvent","Component","rootComponent","Registry","host","maskWrapper"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/_utils/uikit.ts","../src/_utils/env.ts","../src/injection-tokens.ts","../src/parser.ts","../src/selection-bridge.ts","../src/types.ts","../src/magic-input.ts","../src/collaborate-cursor.ts","../src/native-input.ts","../src/dom-adapter.ts","../src/browser-module.ts"],"sourcesContent":["/**\n * 选区焦点可视位置\n */\nexport interface Rect {\n left: number\n top: number\n width: number\n height: number\n}\n\nexport interface UIElementParams {\n classes?: string[]\n attrs?: {[key: string]: any}\n props?: {[key: string]: any}\n styles?: {[key: string]: any}\n children?: (Node | null)[]\n on?: Record<string, (ev: Event) => void>\n}\n\nexport function createElement(tagName: string, options: UIElementParams = {}): HTMLElement {\n const el = document.createElement(tagName)\n if (options.classes) {\n el.classList.add(...options.classes)\n }\n if (options.attrs) {\n Object.keys(options.attrs).forEach(key => {\n el.setAttribute(key, options.attrs![key])\n })\n }\n if (options.props) {\n Object.keys(options.props).forEach(key => {\n (el as any)[key] = options.props![key]\n })\n }\n if (options.styles) {\n Object.assign(el.style, options.styles)\n }\n if (options.children) {\n options.children.filter(i => i).forEach(item => {\n el.appendChild(item as Node)\n })\n }\n if (options.on) {\n Object.keys(options.on).forEach(key => {\n el.addEventListener(key, options.on![key])\n })\n }\n return el\n}\n\nexport function getLayoutRectByRange(range: Range): Rect {\n let { startContainer, startOffset } = range\n if (startContainer.nodeType === Node.TEXT_NODE) {\n if (startOffset > 0) {\n return range.getBoundingClientRect()\n }\n const parentNode = startContainer.parentNode!\n startOffset = Array.from(parentNode.childNodes).indexOf(startContainer as any)\n startContainer = parentNode\n }\n\n const beforeNode = startContainer.childNodes[startOffset - 1]\n if (beforeNode) {\n if (beforeNode.nodeType === Node.ELEMENT_NODE && beforeNode.nodeName.toLowerCase() !== 'br') {\n const rect = (beforeNode as HTMLElement).getBoundingClientRect()\n return {\n left: rect.right,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n } else if (beforeNode.nodeType === Node.TEXT_NODE) {\n const range2 = document.createRange()\n range2.setStart(beforeNode, beforeNode.textContent!.length)\n range2.setEnd(beforeNode, beforeNode.textContent!.length)\n const rect = range2.getBoundingClientRect()\n return {\n left: rect.right,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n }\n }\n const offsetNode = startContainer.childNodes[startOffset]\n let isInsertBefore = false\n if (!offsetNode) {\n const lastChild = startContainer.lastChild\n if (lastChild && lastChild.nodeType === Node.ELEMENT_NODE) {\n const rect = (lastChild as HTMLElement).getBoundingClientRect()\n return {\n left: rect.right,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n }\n }\n if (offsetNode) {\n if (offsetNode.nodeType === Node.ELEMENT_NODE && offsetNode.nodeName.toLowerCase() !== 'br') {\n const rect = (offsetNode as HTMLElement).getBoundingClientRect()\n return {\n left: rect.left,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n }\n isInsertBefore = true\n }\n const span = startContainer.ownerDocument!.createElement('span')\n span.innerText = '\\u200b'\n span.style.display = 'inline-block'\n if (isInsertBefore) {\n startContainer.insertBefore(span, offsetNode)\n } else {\n startContainer.appendChild(span)\n }\n const rect = span.getBoundingClientRect()\n startContainer.removeChild(span)\n return {\n left: rect.left,\n top: rect.top,\n width: range.collapsed ? 1 : rect.width,\n height: rect.height\n }\n}\n","export const isWindows = () => /win(dows|32|64)/i.test(navigator.userAgent)\nexport const isMac = () => /mac os/i.test(navigator.userAgent)\nexport const isSafari = () => /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent)\nexport const isFirefox = () => /Firefox/.test(navigator.userAgent)\n\nexport const isMobileBrowser = () => /Android|iPhone|iPad/.test(navigator.userAgent)\n","import { InjectionToken } from '@viewfly/core'\n\nimport { ViewOptions } from './browser-module'\n\n/**\n * 编辑器可选项依赖注入 token\n */\nexport const EDITOR_OPTIONS = new InjectionToken<ViewOptions>('EDITOR_OPTIONS')\n\n/**\n * 编辑器容器依赖注入 token\n */\nexport const VIEW_CONTAINER = new InjectionToken<HTMLElement>('VIEW_CONTAINER')\n\n/**\n * 编辑器容器依赖注入 token\n */\nexport const VIEW_DOCUMENT = new InjectionToken<HTMLElement>('VIEW_DOCUMENT')\n\n/**\n * 编辑器容器遮罩层 token\n */\nexport const VIEW_MASK = new InjectionToken<HTMLElement>('VIEW_MASK')\n","import { Inject, Injectable } from '@viewfly/core'\nimport { Attribute, Component, ContentType, FormatItem, Formatter, FormatValue, Slot, Textbus } from '@textbus/core'\n\nimport { EDITOR_OPTIONS } from './injection-tokens'\nimport { ViewOptions } from './browser-module'\n\n/**\n * 插槽解析器\n */\nexport interface SlotParser {\n /**\n * 将指定 DOM 节点解析为插槽数据\n * @param childSlot 储存数据的插槽\n * @param slotRootElement 插槽的根节点\n * @param slotContentHostElement 插槽的内容节点\n *\n * 注意:当不传入内容节点时,Textbus 会把根节点当成内容节点\n */<T extends Slot>(childSlot: T, slotRootElement: Element, slotContentHostElement?: Element): T\n}\n\n/**\n * 组件加载器\n */\nexport interface ComponentLoader {\n /** 识别组件的匹配方法 */\n match(element: Element,\n returnableContentTypes: ContentType[]): boolean\n\n /** 读取组件内容的方法 */\n read(element: Element, textbus: Textbus, slotParser: SlotParser): Component | Slot | void\n}\n\nexport interface FormatLoaderReadResult<T = FormatValue> {\n formatter: Formatter<T>\n value: T\n}\n\n/**\n * 格式加载器\n */\nexport interface FormatLoader<T = FormatValue> {\n /**\n * 匹配一个 DOM 节点是否是某个格式节点\n * @param element\n */\n match(element: Element): boolean\n\n /**\n * 读取匹配到的节点,并返回读取后的信息\n * @param element\n */\n read(element: Element): FormatLoaderReadResult<T>\n}\n\nexport interface AttributeLoaderReadResult<T = FormatValue> {\n attribute: Attribute<T>\n value: T\n}\n\n/**\n * 属性加载器\n */\nexport interface AttributeLoader<T = FormatValue> {\n /**\n * 匹配一个 DOM 节点是否是某个属性节点\n * @param element\n */\n match(element: Element): boolean\n\n /**\n * 读取匹配到的节点,并返回读取后的信息\n * @param element\n */\n read(element: Element): AttributeLoaderReadResult<T>\n}\n\n/**\n * 用于解析 HTML,并把 HTML 内容转换为 Textbus 可以支持的组件或插槽数据\n */\n@Injectable()\nexport class Parser {\n static parseHTML(html: string) {\n return new DOMParser().parseFromString(html, 'text/html').body\n }\n\n componentLoaders: ComponentLoader[]\n formatLoaders: FormatLoader<any>[]\n attributeLoaders: AttributeLoader<any>[]\n\n constructor(@Inject(EDITOR_OPTIONS) options: ViewOptions,\n private textbus: Textbus) {\n const componentLoaders = [\n ...(options.componentLoaders || [])\n ]\n const formatLoaders = [\n ...(options.formatLoaders || [])\n ]\n const attributeLoaders = [\n ...(options.attributeLoaders || [])\n ]\n // options.imports?.forEach(i => {\n // componentLoaders.push(...(i.componentLoaders || []))\n // formatLoaders.push(...(i.formatLoaders || []))\n // })\n this.componentLoaders = componentLoaders\n this.formatLoaders = formatLoaders\n this.attributeLoaders = attributeLoaders\n }\n\n /**\n * 使用指定的组件加载器解析一段 HTML 字符串或 DOM 元素\n * @param html\n * @param rootComponentLoader\n */\n parseDoc(html: string | HTMLElement, rootComponentLoader: ComponentLoader) {\n const element = typeof html === 'string' ? Parser.parseHTML(html) : html\n return rootComponentLoader.read(\n element,\n this.textbus,\n (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {\n return this.readSlot(childSlot, slotRootElement, slotContentHostElement)\n }\n )\n }\n\n /**\n * 将一段 HTML 或 DOM 元素解析到指定插槽\n * @param html\n * @param rootSlot\n */\n parse(html: string | HTMLElement, rootSlot: Slot) {\n const element = typeof html === 'string' ? Parser.parseHTML(html) : html\n return this.readFormats(element, rootSlot)\n }\n\n private readComponent(el: Node, slot: Slot) {\n if (el.nodeType === Node.ELEMENT_NODE) {\n if ((el as HTMLElement).tagName === 'BR') {\n slot.insert('\\n')\n return\n }\n const schema = [...slot.schema]\n for (const t of this.componentLoaders) {\n if (t.match(el as HTMLElement, schema)) {\n const result = t.read(\n el as HTMLElement,\n this.textbus,\n (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {\n return this.readSlot(childSlot, slotRootElement, slotContentHostElement)\n }\n )\n if (!result) {\n return\n }\n if (result instanceof Slot) {\n result.toDelta().forEach(i => slot.insert(i.insert, i.formats))\n return\n }\n slot.insert(result)\n return\n }\n }\n this.readFormats(el as HTMLElement, slot)\n } else if (el.nodeType === Node.TEXT_NODE) {\n this.readText(slot, el)\n }\n }\n\n private readText(slot: Slot, el: Node) {\n const textContent = el.textContent\n if (/^\\s*[\\r\\n\\u200b]+\\s*$/.test(textContent as string)) {\n return\n }\n slot.insert(textContent as string)\n }\n\n private readFormats(el: Element, slot: Slot) {\n const formats = this.formatLoaders.filter(f => {\n return f.match(el)\n }).map(f => {\n return f.read(el)\n })\n const startIndex = slot.index\n let startNode = el.firstChild\n while (startNode) {\n this.readComponent(startNode, slot)\n startNode = startNode.nextSibling\n }\n const endIndex = slot.index\n this.applyFormats(slot, formats.map<FormatItem<any>>(i => {\n return {\n formatter: i.formatter,\n value: i.value,\n startIndex,\n endIndex\n }\n }))\n slot.retain(endIndex)\n return slot\n }\n\n private readSlot<T extends Slot>(childSlot: T, slotRootElement: Element, slotContentElement: Element): T {\n if (slotRootElement.nodeType === Node.ELEMENT_NODE) {\n this.attributeLoaders.filter(a => {\n return a.match(slotRootElement)\n }).forEach(a => {\n const r = a.read(slotRootElement)\n childSlot.setAttribute(r.attribute, r.value)\n })\n }\n if (slotContentElement.nodeType === Node.ELEMENT_NODE) {\n this.readFormats(slotContentElement, childSlot)\n } else {\n this.readText(childSlot, slotContentElement)\n }\n return childSlot\n }\n\n private applyFormats(slot: Slot, formatItems: FormatItem<any>[]) {\n slot.background(() => {\n formatItems.forEach(i => {\n slot.retain(i.startIndex)\n slot.retain(i.endIndex - i.startIndex, i.formatter, i.value)\n })\n })\n }\n}\n","import { delay, filter, fromEvent, Observable, Subject, Subscription } from '@tanbo/stream'\nimport { Inject, Injectable } from '@viewfly/core'\nimport {\n NativeSelectionBridge,\n NativeSelectionConnector,\n SelectionPosition,\n Slot,\n AbstractSelection,\n RootComponentRef,\n Controller,\n Selection,\n Textbus,\n Scheduler\n} from '@textbus/core'\n\nimport { EDITOR_OPTIONS, VIEW_DOCUMENT } from './injection-tokens'\nimport { getLayoutRectByRange, Rect } from './_utils/uikit'\nimport { Input } from './types'\nimport { ViewOptions } from './browser-module'\nimport { DomAdapter } from './dom-adapter'\n\n/**\n * Textbus PC 端选区桥接实现\n */\n@Injectable()\nexport class SelectionBridge implements NativeSelectionBridge {\n onSelectionChange: Observable<Range | null>\n nativeSelection = document.getSelection()!\n\n syncSelectionFromNativeSelectionChange = true\n\n private selectionChangeEvent = new Subject<Range | null>()\n\n private subs: Subscription[] = []\n private sub: Subscription\n private connector: NativeSelectionConnector | null = null\n\n private ignoreSelectionChange = false\n\n private changeFromUser = false\n private docContainer: HTMLElement\n\n private cacheCaretPositionTimer!: any\n private oldCaretPosition!: Rect | null\n\n constructor(@Inject(EDITOR_OPTIONS) private config: ViewOptions,\n textbus: Textbus,\n controller: Controller,\n private selection: Selection,\n private rootComponentRef: RootComponentRef,\n private input: Input,\n private scheduler: Scheduler,\n private domAdapter: DomAdapter) {\n this.docContainer = textbus.get(VIEW_DOCUMENT)\n this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(filter(() => {\n return !controller.readonly\n }))\n this.sub = this.onSelectionChange.subscribe((r) => {\n if (r) {\n input.focus(r, this.changeFromUser)\n } else {\n input.blur()\n }\n })\n this.sub.add(\n fromEvent(document, 'focusin').subscribe(ev => {\n let target = ev.target as HTMLElement\n if (/^(input|textarea|select)$/i.test(target.nodeName)) {\n if (target.tagName.toLowerCase() === 'input' && /^(range|date)$/.test((target as HTMLInputElement).type)) {\n return\n }\n this.ignoreSelectionChange = true\n return\n }\n if (!config.useContentEditable) {\n while (target) {\n if (target.contentEditable === 'true') {\n this.ignoreSelectionChange = true\n return\n }\n target = target.parentNode as HTMLElement\n }\n }\n })\n )\n this.sub.add(\n fromEvent(document, 'focusout').subscribe(() => {\n this.ignoreSelectionChange = false\n })\n )\n }\n\n connect(connector: NativeSelectionConnector) {\n this.disConnect()\n this.connector = connector\n this.syncSelection(connector)\n this.listen(connector)\n }\n\n disConnect() {\n this.connector = null\n this.unListen()\n }\n\n getRect(location: SelectionPosition) {\n const { focus, anchor } = this.getPositionByRange({\n focusOffset: location.offset,\n anchorOffset: location.offset,\n focusSlot: location.slot,\n anchorSlot: location.slot\n })\n if (!focus || !anchor) {\n return null\n }\n const nativeRange = document.createRange()\n nativeRange.setStart(focus.node, focus.offset)\n nativeRange.collapse()\n return getLayoutRectByRange(nativeRange)\n }\n\n restore(abstractSelection: AbstractSelection | null, fromLocal: boolean) {\n this.changeFromUser = fromLocal\n if (this.ignoreSelectionChange || !this.connector) {\n return\n }\n this.unListen()\n if (!abstractSelection) {\n this.nativeSelection.removeAllRanges()\n this.selectionChangeEvent.next(null)\n this.listen(this.connector)\n return\n }\n\n const { focus, anchor } = this.getPositionByRange(abstractSelection)\n if (!focus || !anchor) {\n this.nativeSelection.removeAllRanges()\n this.selectionChangeEvent.next(null)\n this.listen(this.connector)\n return\n }\n\n function tryOffset(position: {node: Node, offset: number}) {\n if (!position.node) {\n return\n }\n if (position.node.nodeType === Node.TEXT_NODE) {\n const len = position.node.textContent!.length\n if (position.offset > len) {\n position.offset = len\n }\n } else if (position.node.nodeType === Node.ELEMENT_NODE) {\n const len = position.node.childNodes.length\n if (position.offset > len) {\n position.offset = len\n }\n }\n }\n\n try {\n tryOffset(focus)\n tryOffset(anchor)\n this.nativeSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset)\n } catch (e) {\n setTimeout(() => {\n throw e\n })\n }\n if (this.nativeSelection.rangeCount) {\n const nativeRange = this.nativeSelection.getRangeAt(0)\n this.selectionChangeEvent.next(nativeRange)\n } else {\n this.selectionChangeEvent.next(null)\n }\n\n // hack start 浏览器会触发上面选区更改事件\n const bind = () => {\n if (this.connector) {\n this.listen(this.connector)\n }\n }\n if (fromLocal) {\n Promise.resolve().then(bind)\n return\n }\n if (typeof requestIdleCallback === 'function') {\n requestIdleCallback(bind)\n } else {\n setTimeout(bind, 30)\n }\n // hack end\n }\n\n destroy() {\n this.subs.forEach(i => i.unsubscribe())\n this.sub.unsubscribe()\n }\n\n getPositionByRange(abstractSelection: AbstractSelection) {\n let focus!: {node: Node, offset: number} | null\n let anchor!: {node: Node, offset: number} | null\n try {\n focus = this.findSelectedNodeAndOffset(abstractSelection.focusSlot!, abstractSelection.focusOffset!)\n anchor = focus\n if (abstractSelection.anchorSlot !== abstractSelection.focusSlot ||\n abstractSelection.anchorOffset !== abstractSelection.focusOffset) {\n anchor = this.findSelectedNodeAndOffset(abstractSelection.anchorSlot!, abstractSelection.anchorOffset!)\n }\n return {\n focus,\n anchor\n }\n } catch (e) {\n return {\n focus: null,\n anchor: null\n }\n }\n }\n\n getPreviousLinePositionByCurrent(position: SelectionPosition): SelectionPosition | null {\n return this.getLinePosition(position, false)\n }\n\n getNextLinePositionByCurrent(position: SelectionPosition): SelectionPosition | null {\n return this.getLinePosition(position, true)\n }\n\n private getLinePosition(currentPosition: SelectionPosition, toNext: boolean): SelectionPosition | null {\n clearTimeout(this.cacheCaretPositionTimer)\n let p: SelectionPosition\n if (this.oldCaretPosition) {\n p = toNext ?\n this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :\n this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left)\n } else {\n this.oldCaretPosition = this.getRect(currentPosition)!\n p = toNext ?\n this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :\n this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left)\n }\n this.cacheCaretPositionTimer = setTimeout(() => {\n this.oldCaretPosition = null\n }, 3000)\n return p\n }\n\n /**\n * 获取选区向上移动一行的位置。\n * @param currentPosition\n * @param startLeft 参考位置。\n */\n private getPreviousLinePositionByOffset(currentPosition: SelectionPosition, startLeft: number): SelectionPosition {\n let isToPrevLine = false\n let loopCount = 0\n let minLeft = startLeft\n let focusSlot = currentPosition.slot\n let focusOffset = currentPosition.offset\n let minTop = this.getRect({\n slot: focusSlot,\n offset: focusOffset\n })!.top\n\n let position: SelectionPosition\n let oldPosition!: SelectionPosition\n let oldLeft = 0\n while (true) {\n loopCount++\n position = this.selection.getPreviousPositionByPosition(focusSlot, focusOffset)\n focusSlot = position.slot\n focusOffset = position.offset\n const rect2 = this.getRect(position)!\n if (!isToPrevLine) {\n if (rect2.left > minLeft || rect2.top + rect2.height <= minTop) {\n isToPrevLine = true\n } else if (rect2.left === minLeft && rect2.top === minTop) {\n return position\n }\n minLeft = rect2.left\n minTop = rect2.top\n // oldPosition = position\n }\n if (isToPrevLine) {\n if (rect2.left <= startLeft) {\n return position\n }\n if (oldPosition) {\n if (rect2.left >= oldLeft) {\n return oldPosition\n }\n }\n oldLeft = rect2.left\n oldPosition = position\n }\n if (loopCount > 10000) {\n break\n }\n }\n return position || {\n offset: 0,\n slot: focusSlot\n }\n }\n\n /**\n * 获取选区向下移动一行的位置。\n * @param currentPosition\n * @param startLeft 参考位置。\n */\n private getNextLinePositionByOffset(currentPosition: SelectionPosition, startLeft: number): SelectionPosition {\n let isToNextLine = false\n let loopCount = 0\n let maxRight = startLeft\n let focusSlot = currentPosition.slot\n let focusOffset = currentPosition.offset\n const rect = this.getRect({\n slot: focusSlot,\n offset: focusOffset\n })!\n let minTop = rect.top\n let oldPosition!: SelectionPosition\n let oldLeft = 0\n while (true) {\n loopCount++\n const position = this.selection.getNextPositionByPosition(focusSlot, focusOffset)\n focusSlot = position.slot\n focusOffset = position.offset\n const rect2 = this.getRect(position)!\n if (!isToNextLine) {\n if (rect2.left < maxRight || rect2.top >= minTop + rect.height) {\n isToNextLine = true\n } else if (rect2.left === maxRight && rect2.top === minTop) {\n return position\n }\n maxRight = rect2.left\n minTop = rect2.top\n oldPosition = position\n }\n if (isToNextLine) {\n if (rect2.left > startLeft) {\n return oldPosition\n }\n if (oldPosition) {\n if (rect2.left <= oldLeft) {\n return oldPosition\n }\n }\n oldPosition = position\n oldLeft = rect2.left\n }\n if (loopCount > 10000) {\n break\n }\n }\n return oldPosition || {\n offset: focusSlot.length,\n slot: focusSlot\n }\n }\n\n private unListen() {\n this.subs.forEach(i => i.unsubscribe())\n this.subs = []\n }\n\n private listen(connector: NativeSelectionConnector) {\n if (!this.config.useContentEditable) {\n const selection = this.nativeSelection\n this.subs.push(\n fromEvent<MouseEvent>(this.docContainer, 'mousedown').subscribe(ev => {\n if (this.ignoreSelectionChange || ev.button === 2) {\n return\n }\n if (!ev.shiftKey) {\n selection.removeAllRanges()\n }\n })\n )\n }\n let isUpdating = false\n this.subs.push(\n this.scheduler.onDocChange.subscribe(() => {\n isUpdating = true\n }),\n this.scheduler.onDocChanged.pipe(delay()).subscribe(() => {\n isUpdating = false\n }),\n fromEvent(document, 'selectionchange').subscribe(() => {\n if (isUpdating) {\n return\n }\n if (this.syncSelectionFromNativeSelectionChange) {\n this.syncSelection(connector)\n }\n })\n )\n }\n\n private syncSelection(connector: NativeSelectionConnector) {\n const selection = this.nativeSelection\n this.changeFromUser = true\n if (this.ignoreSelectionChange ||\n this.input.composition ||\n selection.rangeCount === 0 ||\n !this.docContainer.contains(selection.anchorNode) ||\n this.rootComponentRef.component.slots.length === 0) {\n return\n }\n const rawRange = selection.getRangeAt(0)\n const nativeRange = rawRange.cloneRange()\n const isFocusEnd = selection.focusNode === nativeRange.endContainer && selection.focusOffset === nativeRange.endOffset\n const isFocusStart = selection.focusNode === nativeRange.startContainer && selection.focusOffset === nativeRange.startOffset\n if (!this.docContainer.contains(selection.focusNode)) {\n if (isFocusEnd) {\n const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(0)!)\n if (!nativeNode) {\n return\n }\n nativeRange.setEndAfter(nativeNode.lastChild!)\n } else {\n const nativeNode = this.domAdapter.getNativeNodeBySlot(this.rootComponentRef.component.slots.at(-1)!)\n if (!nativeNode) {\n return\n }\n nativeRange.setStartBefore(nativeNode.firstChild!)\n }\n }\n\n const startPosition = this.getCorrectedPosition(nativeRange.startContainer, nativeRange.startOffset, isFocusStart)\n const endPosition = nativeRange.collapsed ?\n startPosition :\n this.getCorrectedPosition(nativeRange.endContainer, nativeRange.endOffset, isFocusEnd)\n\n if ([Node.ELEMENT_NODE, Node.TEXT_NODE].includes(nativeRange.commonAncestorContainer?.nodeType as any) &&\n startPosition && endPosition) {\n const abstractSelection = connector.beforeChange(isFocusEnd ? {\n anchorSlot: startPosition.slot,\n anchorOffset: startPosition.offset,\n focusSlot: endPosition.slot,\n focusOffset: endPosition.offset\n } : {\n focusSlot: startPosition.slot,\n focusOffset: startPosition.offset,\n anchorSlot: endPosition.slot,\n anchorOffset: endPosition.offset\n })\n if (!abstractSelection) {\n this.selectionChangeEvent.next(null)\n connector.setSelection(null)\n return\n }\n const { focus, anchor } = this.getPositionByRange(abstractSelection)\n if (focus && anchor) {\n let start = anchor\n let end = focus\n if (isFocusStart) {\n start = focus\n end = anchor\n }\n if (nativeRange.startContainer !== start.node || nativeRange.startOffset !== start.offset) {\n nativeRange.setStart(start.node, start.offset)\n }\n if (nativeRange.endContainer !== end.node || nativeRange.endOffset !== end.offset) {\n nativeRange.setEnd(end.node, end.offset)\n }\n connector.setSelection(abstractSelection)\n if (selection.isCollapsed && (\n rawRange.startContainer !== start.node ||\n rawRange.startOffset !== start.offset ||\n rawRange.endContainer !== end.node ||\n rawRange.endOffset !== end.offset\n )) {\n rawRange.setStart(start.node, start.offset)\n rawRange.setEnd(end.node, end.offset)\n }\n this.selectionChangeEvent.next(nativeRange)\n } else {\n connector.setSelection(null)\n }\n return\n }\n connector.setSelection(null)\n }\n\n private findSelectedNodeAndOffset(slot: Slot, offset: number): {node: Node, offset: number} | null {\n const prev = slot.getContentAtIndex(offset - 1)\n const nodes = this.domAdapter.getNodesBySlot(slot)\n\n if (prev) {\n if (typeof prev !== 'string') {\n const nativeNode = this.domAdapter.getNativeNodeByComponent(prev)!\n return {\n node: nativeNode.parentNode!,\n offset: Array.from(nativeNode.parentNode!.childNodes).indexOf(nativeNode) + 1\n }\n } else if (prev === '\\n') {\n for (const node of nodes) {\n if (node instanceof Text) {\n continue\n }\n if (node.nodeName === 'BR') {\n const position = this.domAdapter.getLocationByNativeNode(node)\n if (position) {\n if (position.endIndex === offset) {\n const parentNode = node.parentNode!\n return {\n node: parentNode,\n offset: Array.from(parentNode.childNodes).indexOf(node as ChildNode) + 1\n }\n }\n }\n }\n }\n }\n }\n const current = slot.getContentAtIndex(offset)\n if (current && typeof current !== 'string') {\n const nativeNode = this.domAdapter.getNativeNodeByComponent(current)!\n return {\n node: nativeNode.parentNode!,\n offset: Array.from(nativeNode.parentNode!.childNodes).indexOf(nativeNode)\n }\n }\n for (const node of nodes) {\n if (node instanceof Element) {\n if (node.tagName === 'BR') {\n const position = this.domAdapter.getLocationByNativeNode(node)\n if (position) {\n if (position.startIndex === offset) {\n const parentNode = node.parentNode!\n return {\n node: parentNode,\n offset: Array.from(parentNode.childNodes).indexOf(node)\n }\n }\n }\n }\n continue\n }\n const position = this.domAdapter.getLocationByNativeNode(node)\n if (position) {\n if (offset >= position.startIndex && offset <= position.endIndex) {\n return {\n node: node,\n offset: offset - position.startIndex\n }\n }\n }\n }\n return null\n }\n\n private getCorrectedPosition(node: Node, offset: number, toAfter: boolean, excludeNodes: Node[] = []): SelectionPosition | null {\n excludeNodes.push(node)\n if (node.nodeType === Node.ELEMENT_NODE) {\n const containerPosition = this.domAdapter.getLocationByNativeNode(node)\n const childNode = node.childNodes[offset]\n if (childNode) {\n const childPosition = this.domAdapter.getLocationByNativeNode(childNode)\n if (childPosition) {\n if (containerPosition) {\n return {\n slot: childPosition.slot,\n offset: childPosition.startIndex\n }\n }\n return this.findFocusNode(childNode, toAfter, excludeNodes)\n }\n return this.findFocusNode(childNode, toAfter, excludeNodes)\n }\n const prevNode = node.childNodes[offset - 1]\n if (prevNode) {\n const prevPosition = this.domAdapter.getLocationByNativeNode(prevNode)\n if (prevPosition && containerPosition) {\n return {\n slot: prevPosition.slot,\n offset: prevPosition.endIndex\n }\n }\n }\n if (containerPosition) {\n return {\n slot: containerPosition.slot,\n offset: containerPosition.endIndex\n }\n }\n const nextNode = toAfter ? node.nextSibling : node.previousSibling\n if (nextNode) {\n return this.findFocusNode(nextNode, toAfter, excludeNodes)\n }\n return this.findFocusNodeByParent(node, toAfter, excludeNodes)\n } else if (node.nodeType === Node.TEXT_NODE) {\n const containerPosition = this.domAdapter.getLocationByNativeNode(node)\n if (containerPosition) {\n return {\n slot: containerPosition.slot,\n offset: containerPosition.startIndex + offset\n }\n }\n const nextNode = toAfter ? node.nextSibling : node.previousSibling\n if (nextNode) {\n return this.findFocusNode(nextNode, toAfter, excludeNodes)\n }\n return this.findFocusNodeByParent(node, toAfter, excludeNodes)\n }\n return null\n }\n\n private findFocusNode(node: Node, toAfter = false, excludeNodes: Node[] = []): SelectionPosition | null {\n if (excludeNodes.includes(node)) {\n const next = toAfter ? node.nextSibling : node.previousSibling\n if (next) {\n return this.findFocusNode(next, toAfter, excludeNodes)\n }\n return this.findFocusNodeByParent(node, toAfter, excludeNodes)\n }\n excludeNodes.push(node)\n const position = this.domAdapter.getLocationByNativeNode(node as any)\n if (position) {\n return {\n slot: position.slot,\n offset: toAfter ? position.startIndex : position.endIndex\n }\n }\n const firstChild = toAfter ? node.firstChild : node.lastChild\n if (firstChild) {\n return this.findFocusNode(firstChild, toAfter, excludeNodes)\n }\n const nextSibling = toAfter ? node.nextSibling : node.previousSibling\n if (nextSibling) {\n return this.findFocusNode(nextSibling, toAfter, excludeNodes)\n }\n return this.findFocusNodeByParent(node, toAfter, excludeNodes)\n }\n\n private findFocusNodeByParent(node: Node, toAfter: boolean, excludeNodes: Node[]) {\n const parentNode = node.parentNode\n if (parentNode) {\n const parentPosition = this.domAdapter.getLocationByNativeNode(parentNode)\n if (parentPosition) {\n return {\n slot: parentPosition.slot,\n offset: toAfter ? parentPosition.endIndex : parentPosition.startIndex\n }\n }\n excludeNodes.push(node)\n return this.findFocusNode(parentNode, toAfter, excludeNodes)\n }\n return null\n }\n}\n","import { Observable } from '@tanbo/stream'\n\nimport { Rect } from './_utils/uikit'\n\nexport interface CaretLimit {\n top: number\n bottom: number\n}\n\nexport interface CaretPosition {\n left: number\n top: number\n height: number\n}\n\nexport interface Caret {\n onPositionChange: Observable<CaretPosition | null>\n readonly rect: Rect\n\n refresh(): void\n}\n\nexport abstract class Input {\n /**\n * @experimental\n */\n abstract composition: boolean\n /**\n * @experimental\n */\n abstract onReady: Promise<void>\n abstract caret: Caret\n abstract disabled: boolean\n\n abstract focus(nativeRange: Range, reFlash: boolean): void\n\n abstract blur(): void\n\n abstract destroy(): void\n}\n","import { distinctUntilChanged, filter, fromEvent, map, merge, Observable, Subject, Subscription } from '@tanbo/stream'\nimport { Injectable } from '@viewfly/core'\nimport {\n Commander,\n CompositionStartEventData,\n ContentType,\n Controller,\n Event,\n invokeListener,\n Keyboard,\n Scheduler,\n Selection,\n Slot,\n Textbus\n} from '@textbus/core'\n\nimport { createElement, getLayoutRectByRange } from './_utils/uikit'\nimport { Parser } from './parser'\nimport { isFirefox, isMac, isSafari, isWindows } from './_utils/env'\nimport { VIEW_MASK } from './injection-tokens'\nimport { Caret, CaretLimit, CaretPosition, Input } from './types'\nimport { DomAdapter } from './dom-adapter'\n\nconst iframeHTML = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\n <title>Textbus</title>\n <style>\n html {position: fixed; left:0; overflow: hidden}\n html, body{height: 100%;width:100%}\n body{margin:0; overflow: hidden}\n textarea{width: 2000px;height: 100%;opacity: 0; padding: 0; outline: none; border: none; position: absolute; left:0; top:0;}\n </style>\n</head>\n<body>\n</body>\n</html>\n`\n\ninterface CaretStyle {\n height: string\n lineHeight: string\n fontSize: string\n}\n\nclass ExperimentalCaret implements Caret {\n onPositionChange: Observable<CaretPosition | null>\n onStyleChange: Observable<CaretStyle>\n elementRef: HTMLElement\n changeFromSelf = false\n\n getLimit = function (): CaretLimit {\n return {\n top: 0,\n bottom: document.documentElement.clientHeight\n }\n }\n\n get rect() {\n return this.caret.getBoundingClientRect()\n }\n\n private timer: any = null\n private caret: HTMLElement\n\n private set display(v: boolean) {\n this._display = v\n this.caret.style.visibility = v ? 'visible' : 'hidden'\n }\n\n private get display() {\n return this._display\n }\n\n private _display = true\n private flashing = true\n\n private subscription = new Subscription()\n\n private positionChangeEvent = new Subject<CaretPosition | null>()\n private styleChangeEvent = new Subject<CaretStyle>()\n private oldRange: Range | null = null\n\n constructor(\n private domRenderer: DomAdapter,\n private scheduler: Scheduler,\n private editorMask: HTMLElement) {\n this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged())\n this.onStyleChange = this.styleChangeEvent.asObservable()\n this.elementRef = createElement('div', {\n styles: {\n position: 'absolute',\n width: '2px',\n pointerEvents: 'none'\n },\n children: [\n this.caret = createElement('span', {\n styles: {\n width: '100%',\n height: '100%',\n position: 'absolute',\n left: 0,\n top: 0\n }\n })\n ]\n })\n\n this.subscription.add(\n fromEvent(document, 'mousedown').subscribe(() => {\n this.flashing = false\n }),\n fromEvent(document, 'mouseup').subscribe(() => {\n this.flashing = true\n }),\n )\n this.editorMask.appendChild(this.elementRef)\n }\n\n refresh() {\n if (this.oldRange) {\n this.show(this.oldRange, false)\n }\n }\n\n show(range: Range, restart: boolean) {\n this.oldRange = range\n if (restart || this.scheduler.lastChangesHasLocalUpdate) {\n clearTimeout(this.timer)\n }\n this.updateCursorPosition(range)\n if (range.collapsed) {\n if (restart || this.scheduler.lastChangesHasLocalUpdate) {\n this.display = true\n const toggleShowHide = () => {\n this.display = !this.display || !this.flashing\n this.timer = setTimeout(toggleShowHide, 400)\n }\n clearTimeout(this.timer)\n this.timer = setTimeout(toggleShowHide, 400)\n }\n } else {\n this.display = false\n clearTimeout(this.timer)\n }\n }\n\n hide() {\n this.display = false\n clearTimeout(this.timer)\n this.positionChangeEvent.next(null)\n }\n\n destroy() {\n clearTimeout(this.timer)\n // this.caret.\n this.subscription.unsubscribe()\n }\n\n private updateCursorPosition(nativeRange: Range) {\n const startContainer = nativeRange.startContainer\n\n const node = (startContainer.nodeType === Node.ELEMENT_NODE ? startContainer : startContainer.parentNode) as HTMLElement\n if (node?.nodeType !== Node.ELEMENT_NODE) {\n this.positionChangeEvent.next(null)\n return\n }\n const compositionNode = this.domRenderer.compositionNode\n if (compositionNode) {\n nativeRange = nativeRange.cloneRange()\n nativeRange.selectNodeContents(compositionNode)\n nativeRange.collapse()\n }\n const rect = getLayoutRectByRange(nativeRange)\n const { fontSize, lineHeight, color, writingMode } = getComputedStyle(node)\n\n let height: number\n if (isNaN(+lineHeight)) {\n const f = parseFloat(lineHeight)\n if (isNaN(f)) {\n height = parseFloat(fontSize)\n } else {\n height = f\n }\n } else {\n height = parseFloat(fontSize) * parseFloat(lineHeight)\n }\n\n const boxHeight = Math.max(Math.floor(Math.max(height, rect.height)), 12)\n // const boxHeight = Math.floor(height)\n\n let rectTop = rect.top\n if (rect.height < height) {\n rectTop -= (height - rect.height) / 2\n }\n\n rectTop = Math.floor(rectTop)\n\n const containerRect = this.editorMask.getBoundingClientRect()\n\n const top = Math.floor(rectTop - containerRect.top)\n const left = Math.floor(rect.left + rect.width / 2 - containerRect.left)\n let rotate = 0\n if (nativeRange.collapsed) {\n rotate = Math.round(Math.atan2(rect.width, rect.height) * 180 / Math.PI)\n\n if (rotate !== 0) {\n const hackEle = document.createElement('span')\n // eslint-disable-next-line max-len\n hackEle.style.cssText = 'display: inline-block; width: 10px; height: 10px; position: relative; contain: layout style size; writing-mode: inherit'\n const pointEle = document.createElement('span')\n pointEle.style.cssText = 'position: absolute; left: 0; top: 0; width:0;height:0'\n hackEle.append(pointEle)\n node.append(hackEle)\n\n const p1 = pointEle.getBoundingClientRect()\n pointEle.style.right = '0'\n pointEle.style.left = ''\n const p2 = pointEle.getBoundingClientRect()\n\n const x = p1.x - p2.x\n const y = p1.y - p2.y\n\n rotate = Math.atan2(y, x) * 180 / Math.PI\n hackEle.remove()\n }\n }\n if (writingMode === 'vertical-lr' || writingMode === 'vertical-rl') {\n rotate += 90\n }\n Object.assign(this.elementRef.style, {\n left: left + 'px',\n top: top + 'px',\n height: boxHeight + 'px',\n lineHeight: boxHeight + 'px',\n fontSize,\n transform: `rotate(${rotate}deg)`,\n })\n\n this.caret.style.backgroundColor = color === 'rgba(0, 0, 0, 0)' ? '#000' : color\n this.styleChangeEvent.next({\n height: boxHeight + 'px',\n lineHeight: boxHeight + 'px',\n fontSize\n })\n this.positionChangeEvent.next({\n left,\n top: rectTop,\n height: boxHeight\n })\n\n if (this.changeFromSelf) {\n this.changeFromSelf = false\n const selfRect = this.elementRef.getBoundingClientRect()\n const scrollContainer = this.getScrollContainer(startContainer)\n const scrollRect = scrollContainer === document.documentElement ?\n { top: 0, bottom: document.documentElement.clientHeight } :\n scrollContainer.getBoundingClientRect()\n const limit = this.getLimit()\n\n const top = Math.max(limit.top, scrollRect.top)\n const bottom = Math.min(limit.bottom, scrollRect.bottom)\n\n if (selfRect.top < top) {\n scrollContainer.scrollTop -= top - selfRect.top\n } else if (selfRect.bottom > bottom) {\n scrollContainer.scrollTop += selfRect.bottom - bottom\n }\n }\n }\n\n private getScrollContainer(container: Node): Element {\n while (container) {\n if (container instanceof Element) {\n const styles = getComputedStyle(container)\n if (styles.overflow !== 'visible' || styles.overflowX !== 'visible' || styles.overflowY !== 'visible') {\n return container\n }\n }\n container = container.parentNode as Node\n }\n return document.documentElement\n }\n}\n\n\n/**\n * Textbus PC 端输入实现\n */\n@Injectable()\nexport class MagicInput extends Input {\n composition = false\n onReady: Promise<void>\n caret: ExperimentalCaret\n\n set disabled(b: boolean) {\n this._disabled = b\n if (b && this.textarea) {\n this.textarea.disabled = b\n }\n }\n\n get disabled() {\n return this._disabled\n }\n\n private isSafari = isSafari()\n private isFirefox = isFirefox()\n private isMac = isMac()\n private isWindows = isWindows()\n private _disabled = false\n private container = this.createEditableFrame()\n\n private subscription = new Subscription()\n private doc!: Document\n\n private textarea: HTMLTextAreaElement | null = null\n\n private isFocus = false\n private nativeFocus = false\n\n private ignoreComposition = false // 有 bug 版本搜狗拼音\n\n constructor(private domAdapter: DomAdapter,\n private parser: Parser,\n private keyboard: Keyboard,\n private commander: Commander,\n private selection: Selection,\n private controller: Controller,\n private scheduler: Scheduler,\n private textbus: Textbus) {\n super()\n this.caret = new ExperimentalCaret(this.domAdapter, this.scheduler, this.textbus.get(VIEW_MASK))\n this.onReady = new Promise<void>(resolve => {\n this.subscription.add(\n fromEvent(this.container, 'load').subscribe(() => {\n const doc = this.container.contentDocument!\n doc.open()\n doc.write(iframeHTML)\n doc.close()\n this.doc = doc\n this.init()\n resolve()\n }),\n controller.onReadonlyStateChange.subscribe(() => {\n if (controller.readonly) {\n this.blur()\n }\n })\n )\n })\n\n this.caret.elementRef.append(this.container)\n }\n\n focus(range: Range, restart: boolean) {\n if (!this.disabled) {\n this.caret.show(range, restart)\n }\n if (this.controller.readonly) {\n return\n }\n if (!this.isFocus) {\n this.textarea?.focus()\n setTimeout(() => {\n if (!this.nativeFocus && this.isFocus) {\n this.reInit()\n }\n })\n }\n this.isFocus = true\n }\n\n blur() {\n this.caret.hide()\n this.textarea?.blur()\n this.isFocus = false\n }\n\n destroy() {\n this.caret.destroy()\n this.subscription.unsubscribe()\n }\n\n private reInit(delay = false) {\n this.subscription.unsubscribe()\n this.textarea?.parentNode?.removeChild(this.textarea)\n this.subscription = new Subscription()\n this.init()\n if (delay) {\n setTimeout(() => {\n this.textarea?.focus()\n })\n } else {\n this.textarea?.focus()\n }\n }\n\n private init() {\n const doc = this.doc\n const contentBody = doc.body\n const textarea = doc.createElement('textarea')\n textarea.disabled = this.disabled\n contentBody.appendChild(textarea)\n this.textarea = textarea\n this.subscription.add(\n fromEvent(textarea, 'blur').subscribe(() => {\n // if (this.isFocus) {\n // this.isFocus = false\n // this.reInit(true)\n // }\n this.isFocus = false\n this.nativeFocus = false\n this.caret.hide()\n if (this.domAdapter.composition) {\n const slot = this.domAdapter.composition.slot\n this.domAdapter.composition = null\n this.domAdapter.compositionNode = null\n slot.__changeMarker__.forceMarkDirtied()\n }\n }),\n fromEvent(textarea, 'focus').subscribe(() => {\n this.nativeFocus = true\n }),\n this.caret.onStyleChange.subscribe(style => {\n Object.assign(textarea.style, style)\n })\n )\n this.handleInput(textarea)\n this.handleShortcut(textarea)\n this.handleDefaultActions(textarea)\n }\n\n private handleDefaultActions(textarea: HTMLTextAreaElement) {\n this.subscription.add(\n fromEvent<ClipboardEvent>(isFirefox() ? textarea : document, 'copy').subscribe(ev => {\n this.copyHandler(ev)\n }),\n fromEvent<ClipboardEvent>(textarea, 'paste').subscribe(ev => {\n this.pasteHandler(ev)\n })\n )\n }\n\n copyHandler(ev: ClipboardEvent) {\n const selection = this.selection\n if (!selection.isSelected) {\n return\n }\n if (selection.startSlot === selection.endSlot && selection.endOffset! - selection.startOffset! === 1) {\n const content = selection.startSlot!.getContentAtIndex(selection.startOffset!)\n if (typeof content === 'object') {\n const clipboardData = ev.clipboardData!\n const nativeSelection = document.getSelection()!\n const range = nativeSelection.getRangeAt(0)\n const div = document.createElement('div')\n const fragment = range.cloneContents()\n div.append(fragment)\n clipboardData.setData('text/html', div.innerHTML)\n clipboardData.setData('text', div.innerText)\n ev.preventDefault()\n }\n }\n }\n\n pasteHandler(ev: ClipboardEvent) {\n const text = ev.clipboardData!.getData('Text')\n\n const types = Array.from(ev.clipboardData!.types || [])\n const files = Array.from(ev.clipboardData!.files)\n if (types.every(type => type === 'Files') && files.length) {\n Promise.all(files.filter(i => {\n return /image/i.test(i.type)\n }).map(item => {\n const reader = new FileReader()\n return new Promise(resolve => {\n reader.onload = (event) => {\n resolve(event.target!.result)\n }\n reader.readAsDataURL(item)\n })\n })).then(urls => {\n const html = urls.map(i => {\n return `<img src=${i}>`\n }).join('')\n this.paste(html, text)\n })\n ev.preventDefault()\n return\n }\n\n const div = this.doc.createElement('div')\n div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0'\n div.contentEditable = 'true'\n this.doc.body.appendChild(div)\n div.focus()\n setTimeout(() => {\n this.doc.body.removeChild(div)\n div.style.cssText = ''\n this.paste(div, text)\n })\n }\n\n private paste(dom: HTMLElement | string, text: string) {\n const slot = this.parser.parse(dom, new Slot([\n ContentType.BlockComponent,\n ContentType.InlineComponent,\n ContentType.Text\n ]))\n\n this.commander.paste(slot, text)\n }\n\n private handleShortcut(textarea: HTMLTextAreaElement) {\n let isWriting = false\n let isIgnore = false\n this.subscription.add(\n fromEvent(textarea, 'compositionstart').subscribe(() => {\n isWriting = true\n }),\n fromEvent(textarea, 'compositionend').subscribe(() => {\n isWriting = false\n }),\n fromEvent<InputEvent>(textarea, 'beforeinput').subscribe(ev => {\n this.ignoreComposition = false\n if (this.isSafari) {\n if (ev.inputType === 'insertFromComposition') {\n isIgnore = true\n }\n }\n }),\n fromEvent<KeyboardEvent>(textarea, 'keydown').pipe(filter(() => {\n if (this.isSafari && isIgnore) {\n isIgnore = false\n return false\n }\n return !isWriting // || !this.textarea.value\n })).subscribe(ev => {\n this.ignoreComposition = false\n let key = ev.key\n const keys = ')!@#$%^Z&*('\n const b = key === 'Process' && /Digit\\d/.test(ev.code) && ev.shiftKey\n if (b) {\n // 大小写锁定为大写 + 全角 + shift + 数字键,还存在问题\n key = keys.charAt(+ev.code.substring(5))\n ev.preventDefault()\n }\n this.caret.changeFromSelf = true\n const is = this.keyboard.execShortcut({\n key: key,\n altKey: ev.altKey,\n shiftKey: ev.shiftKey,\n modKey: this.isMac ? ev.metaKey : ev.ctrlKey,\n agent: {\n key: ev.key,\n code: ev.code,\n keyCode: ev.keyCode,\n }\n })\n if (is) {\n this.ignoreComposition = true\n ev.preventDefault()\n } else {\n this.caret.changeFromSelf = false\n }\n })\n )\n }\n\n private handleInput(textarea: HTMLTextAreaElement) {\n let startIndex = 0\n this.subscription.add(\n fromEvent<CompositionEvent>(textarea, 'compositionstart').pipe(filter(() => {\n return !this.ignoreComposition\n })).subscribe(() => {\n if (!this.selection.isCollapsed) {\n this.caret.changeFromSelf = true\n this.commander.delete()\n }\n this.composition = true\n startIndex = this.selection.startOffset!\n const startSlot = this.selection.startSlot!\n const event = new Event<Slot, CompositionStartEventData>(startSlot, {\n index: startIndex\n })\n invokeListener(startSlot.parent!, 'onCompositionStart', event)\n }),\n fromEvent<CompositionEvent>(textarea, 'compositionupdate').pipe(filter(() => {\n return !this.ignoreComposition\n })).pipe(distinctUntilChanged((prev, next) => {\n return prev.data !== next.data\n })).subscribe(ev => {\n if (ev.data === ' ') {\n // 处理搜狗五笔不符合 composition 事件预期,会意外跳光标的问题\n return\n }\n const startSlot = this.selection.startSlot!\n this.domAdapter.composition = {\n slot: startSlot,\n text: ev.data,\n offset: ev.data.length,\n index: startIndex\n }\n\n this.caret.changeFromSelf = true\n this.caret.refresh()\n const event = new Event(startSlot, {\n index: startIndex,\n data: ev.data\n })\n\n invokeListener(startSlot.parent!, 'onCompositionUpdate', event)\n startSlot.__changeMarker__.forceMarkDirtied()\n })\n )\n let isCompositionEnd = false\n this.subscription.add(\n merge(\n fromEvent<InputEvent>(textarea, 'beforeinput').pipe(\n filter(ev => {\n ev.preventDefault()\n if (this.isFirefox && ev.inputType === 'insertFromPaste') {\n return false\n }\n if (this.isSafari) {\n isCompositionEnd = ev.inputType === 'insertFromComposition'\n return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition'\n }\n return !ev.isComposing && !!ev.data\n }),\n map(ev => {\n return ev.data as string\n })\n ),\n this.isSafari ? new Observable<string>() : fromEvent<CompositionEvent>(textarea, 'compositionend')\n .pipe(filter(() => {\n return !this.ignoreComposition\n })).pipe(\n map(ev => {\n isCompositionEnd = true\n ev.preventDefault()\n textarea.value = ''\n return ev.data\n })\n )\n ).subscribe(text => {\n this.composition = false\n this.domAdapter.composition = null\n if (text) {\n this.caret.changeFromSelf = true\n this.commander.write(text)\n } else {\n this.selection.startSlot?.__changeMarker__.forceMarkDirtied()\n }\n if (isCompositionEnd) {\n const startSlot = this.selection.startSlot\n if (startSlot) {\n const event = new Event<Slot>(startSlot, null)\n invokeListener(startSlot.parent!, 'onCompositionEnd', event)\n }\n }\n isCompositionEnd = false\n })\n )\n }\n\n private createEditableFrame() {\n return createElement('iframe', {\n attrs: {\n scrolling: 'no'\n },\n styles: {\n border: 'none',\n width: '100%',\n display: 'block',\n height: '100%',\n position: 'relative',\n top: this.isWindows ? '3px' : '0'\n }\n }) as HTMLIFrameElement\n }\n}\n","import { Injectable, Optional } from '@viewfly/core'\nimport { Selection, AbstractSelection, Scheduler, Textbus, SelectionPaths } from '@textbus/core'\nimport { fromEvent, Subject, Subscription } from '@tanbo/stream'\n\nimport { VIEW_CONTAINER } from './injection-tokens'\nimport { SelectionBridge } from './selection-bridge'\nimport { createElement, getLayoutRectByRange, Rect } from './_utils/uikit'\n\nexport interface SelectionRect extends Rect {\n color: string\n username: string\n}\n\nexport interface RemoteSelectionCursor {\n cursor: HTMLElement\n anchor: HTMLElement\n userTip: HTMLElement\n}\n\n/**\n * 远程光标绘制范围计算代理类,可用于定制特定场景下的远程选区绘制,如表格有选区,不会遵守常见的文档流形式\n */\nexport abstract class CollaborateSelectionAwarenessDelegate {\n abstract getRects(abstractSelection: AbstractSelection,\n nativeRange: Range,\n selectionCursor: UserSelectionCursor): false | Rect[]\n}\n\n/**\n * 协作用户虚拟光标信息\n */\nexport interface UserSelectionCursor {\n username: string\n color: string\n selection: SelectionPaths\n data?: any\n}\n\n/**\n * 协作光标绘制类\n */\n@Injectable()\nexport class CollaborateCursor {\n private host = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n zIndex: 1\n }\n })\n private canvasContainer = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n overflow: 'hidden'\n }\n })\n private canvas = createElement('canvas', {\n styles: {\n position: 'absolute',\n opacity: 0.5,\n left: 0,\n top: 0,\n width: '100%',\n height: document.documentElement.clientHeight + 'px',\n pointerEvents: 'none',\n }\n }) as HTMLCanvasElement\n private context = this.canvas.getContext('2d')!\n private tooltips = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n fontSize: '12px',\n zIndex: 10\n }\n })\n\n private onRectsChange = new Subject<SelectionRect[]>()\n\n private subscription = new Subscription()\n private selectionCursors: UserSelectionCursor[] = []\n private container: HTMLElement\n private ratio = window.devicePixelRatio || 1\n\n constructor(textbus: Textbus,\n private nativeSelection: SelectionBridge,\n private scheduler: Scheduler,\n private selection: Selection,\n @Optional() private awarenessDelegate?: CollaborateSelectionAwarenessDelegate) {\n this.container = textbus.get(VIEW_CONTAINER)\n this.canvasContainer.append(this.canvas)\n this.host.append(this.canvasContainer, this.tooltips)\n this.container.prepend(this.host)\n this.subscription.add(this.onRectsChange.subscribe(rects => {\n for (const rect of rects) {\n this.context.fillStyle = rect.color\n this.context.beginPath()\n this.context.rect(rect.left, rect.top, rect.width, rect.height)\n this.context.fill()\n this.context.closePath()\n }\n }), fromEvent(window, 'resize').subscribe(() => {\n this.canvas.style.height = document.documentElement.clientHeight + 'px'\n this.refresh()\n }), this.scheduler.onDocChanged.subscribe(() => {\n this.refresh()\n }))\n }\n\n /**\n * 刷新协作光标,由于 Textbus 只会绘制可视区域的光标,当可视区域发生变化时,需要重新绘制\n */\n refresh() {\n this.draw(this.selectionCursors)\n }\n\n destroy() {\n this.subscription.unsubscribe()\n }\n\n /**\n * 根据远程用户光标位置,绘制协作光标\n * @param paths\n */\n draw(paths: UserSelectionCursor[]) {\n this.selectionCursors = paths\n const containerRect = this.container.getBoundingClientRect()\n this.canvas.style.top = containerRect.top * -1 + 'px'\n this.canvas.width = this.canvas.offsetWidth * this.ratio\n this.canvas.height = this.canvas.offsetHeight * this.ratio\n this.context.scale(this.ratio, this.ratio)\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)\n\n const users: SelectionRect[] = []\n\n paths.filter(i => {\n return i.selection.anchor.length && i.selection.focus.length\n }).forEach(item => {\n const anchorPaths = [...item.selection.anchor]\n const focusPaths = [...item.selection.focus]\n const anchorOffset = anchorPaths.pop()!\n const anchorSlot = this.selection.findSlotByPaths(anchorPaths)\n const focusOffset = focusPaths.pop()!\n const focusSlot = this.selection.findSlotByPaths(focusPaths)\n if (!anchorSlot || !focusSlot) {\n return\n }\n\n const { focus, anchor } = this.nativeSelection.getPositionByRange({\n focusOffset,\n anchorOffset,\n focusSlot,\n anchorSlot\n })\n if (!focus || !anchor) {\n return\n }\n const nativeRange = document.createRange()\n try {\n nativeRange.setStart(anchor.node, anchor.offset)\n nativeRange.setEnd(focus.node, focus.offset)\n } catch (e) {\n return\n }\n if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {\n nativeRange.setStart(focus.node, focus.offset)\n nativeRange.setEnd(anchor.node, anchor.offset)\n }\n\n let rects: Rect[] | DOMRectList | false = false\n if (this.awarenessDelegate) {\n rects = this.awarenessDelegate.getRects({\n focusOffset,\n anchorOffset,\n focusSlot,\n anchorSlot\n }, nativeRange, item)\n }\n if (!rects) {\n rects = nativeRange.getClientRects()\n }\n const selectionRects: SelectionRect[] = []\n for (let i = rects.length - 1; i >= 0; i--) {\n const rect = rects[i]\n selectionRects.push({\n color: item.color,\n username: item.username,\n left: rect.left - containerRect.left,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n })\n }\n this.onRectsChange.next(selectionRects)\n\n const cursorRange = nativeRange.cloneRange()\n cursorRange.setStart(focus.node, focus.offset)\n cursorRange.collapse(true)\n\n const cursorRect = getLayoutRectByRange(cursorRange)\n\n const rect: SelectionRect = {\n username: item.username,\n color: item.color,\n left: cursorRect.left - containerRect.left,\n top: cursorRect.top - containerRect.top,\n width: 1,\n height: cursorRect.height\n }\n if (rect.left < 0 || rect.top < 0 || rect.left > containerRect.width) {\n return\n }\n users.push(rect)\n })\n this.drawUserCursor(users)\n }\n\n protected drawUserCursor(rects: SelectionRect[]) {\n for (let i = 0; i < rects.length; i++) {\n const rect = rects[i]\n const { cursor, userTip, anchor } = this.getUserCursor(i)\n Object.assign(cursor.style, {\n left: rect.left + 'px',\n top: rect.top + 'px',\n width: rect.width + 'px',\n height: rect.height + 'px',\n background: rect.color,\n display: 'block'\n })\n anchor.style.background = rect.color\n userTip.innerText = rect.username\n userTip.style.background = rect.color\n }\n\n for (let i = rects.length; i < this.tooltips.children.length; i++) {\n this.tooltips.removeChild(this.tooltips.children[i])\n }\n }\n\n private getUserCursor(index: number): RemoteSelectionCursor {\n let child: HTMLElement = this.tooltips.children[index] as HTMLElement\n if (child) {\n const anchor = child.children[0] as HTMLElement\n return {\n cursor: child,\n anchor,\n userTip: anchor.children[0] as HTMLElement\n }\n }\n const userTip = createElement('span', {\n styles: {\n position: 'absolute',\n left: '50%',\n transform: 'translateX(-50%)',\n marginBottom: '2px',\n bottom: '100%',\n whiteSpace: 'nowrap',\n color: '#fff',\n boxShadow: '0 1px 2px rgba(0,0,0,.1)',\n opacity: 0.8,\n borderRadius: '3px',\n padding: '3px 5px',\n pointerEvents: 'none',\n }\n })\n\n const anchor = createElement('span', {\n styles: {\n position: 'absolute',\n top: '-2px',\n left: '-2px',\n width: '5px',\n height: '5px',\n borderRadius: '50%',\n pointerEvents: 'auto',\n pointer: 'cursor',\n },\n children: [userTip]\n })\n child = createElement('span', {\n styles: {\n position: 'absolute',\n },\n children: [\n anchor\n ]\n })\n this.tooltips.append(child)\n return {\n cursor: child,\n anchor,\n userTip\n }\n }\n}\n","import { Injectable } from '@viewfly/core'\nimport {\n distinctUntilChanged,\n filter,\n fromEvent,\n map,\n merge,\n Observable,\n Subject,\n Subscription,\n} from '@tanbo/stream'\nimport {\n Commander,\n CompositionStartEventData,\n CompositionUpdateEventData,\n ContentType,\n Controller,\n Event,\n invokeListener,\n Keyboard,\n Selection,\n Slot,\n Textbus\n} from '@textbus/core'\n\nimport { Caret, CaretPosition, Input } from './types'\nimport { VIEW_DOCUMENT } from './injection-tokens'\nimport { isSafari, isMac, isMobileBrowser, isFirefox } from './_utils/env'\nimport { Parser } from './parser'\nimport { getLayoutRectByRange } from './_utils/uikit'\nimport { DomAdapter } from './dom-adapter'\n\nclass NativeCaret implements Caret {\n onPositionChange: Observable<CaretPosition | null>\n\n set nativeRange(range: Range | null) {\n this._nativeRange = range\n if (range) {\n const r = range.cloneRange()\n r.collapse(true)\n const rect = getLayoutRectByRange(r)\n this.positionChangeEvent.next({\n left: rect.left,\n top: rect.top,\n height: rect.height\n })\n } else {\n this.positionChangeEvent.next(null)\n }\n }\n\n get nativeRange() {\n return this._nativeRange\n }\n\n get rect() {\n if (this.nativeRange) {\n const range = this.nativeRange.cloneRange()\n range.collapse(true)\n return getLayoutRectByRange(range)\n }\n return {\n left: 0,\n top: 0,\n width: 0,\n height: 0\n }\n }\n\n private _nativeRange: Range | null = null\n private subs: Subscription[] = []\n\n private positionChangeEvent = new Subject<CaretPosition | null>()\n\n constructor() {\n this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged())\n }\n\n refresh() {\n //\n }\n\n destroy() {\n this.subs.forEach(i => i.unsubscribe())\n this.subs = []\n }\n}\n\n@Injectable()\nexport class NativeInput extends Input {\n caret = new NativeCaret()\n\n composition = false\n // compositionState: CompositionState | null = null\n\n onReady = Promise.resolve()\n\n set disabled(b: boolean) {\n this._disabled = b\n if (this.controller.readonly) {\n this.documentView.contentEditable = 'false'\n return\n }\n this.documentView.contentEditable = b ? 'false' : 'true'\n }\n\n get disabled() {\n return this._disabled\n }\n\n private _disabled = false\n private documentView: HTMLElement\n private nativeSelection = document.getSelection()!\n\n private subscription = new Subscription()\n private nativeRange: Range | null = null\n\n private isSafari = isSafari()\n private isMac = isMac()\n private isMobileBrowser = isMobileBrowser()\n\n private ignoreComposition = false // 有 bug 版本搜狗拼音\n\n constructor(textbus: Textbus,\n private parser: Parser,\n private selection: Selection,\n private keyboard: Keyboard,\n private domAdapter: DomAdapter,\n private commander: Commander,\n private controller: Controller) {\n super()\n this.documentView = textbus.get(VIEW_DOCUMENT)\n if (!controller.readonly) {\n this.documentView.contentEditable = 'true'\n }\n this.subscription.add(\n controller.onReadonlyStateChange.subscribe(() => {\n this.documentView.contentEditable = controller.readonly ? 'false' : 'true'\n })\n )\n this.handleShortcut(this.documentView)\n this.handleInput(this.documentView)\n this.handleDefaultActions(this.documentView)\n }\n\n focus(nativeRange: Range) {\n if (this.controller.readonly) {\n return\n }\n this.caret.nativeRange = nativeRange\n this.nativeRange = nativeRange\n }\n\n blur() {\n if (this.nativeRange && this.nativeSelection.rangeCount > 0) {\n const current = this.nativeSelection.getRangeAt(0)\n if (current === this.nativeRange) {\n this.nativeSelection.removeAllRanges()\n this.nativeRange = null\n return\n }\n }\n }\n\n destroy() {\n this.caret.destroy()\n this.subscription.unsubscribe()\n }\n\n private handleDefaultActions(textarea: HTMLElement) {\n this.subscription.add(\n fromEvent<ClipboardEvent>(isFirefox() ? textarea : document, 'copy').subscribe(ev => {\n this.copyHandler(ev)\n }),\n fromEvent<ClipboardEvent>(textarea, 'paste').subscribe(ev => {\n this.pasteHandler(ev)\n })\n )\n }\n\n copyHandler(ev: ClipboardEvent) {\n const selection = this.selection\n if (!selection.isSelected) {\n return\n }\n if (selection.startSlot === selection.endSlot && selection.endOffset! - selection.startOffset! === 1) {\n const content = selection.startSlot!.getContentAtIndex(selection.startOffset!)\n if (typeof content === 'object') {\n const clipboardData = ev.clipboardData!\n const nativeSelection = document.getSelection()!\n const range = nativeSelection.getRangeAt(0)\n const div = document.createElement('div')\n const fragment = range.cloneContents()\n div.append(fragment)\n clipboardData.setData('text/html', div.innerHTML)\n clipboardData.setData('text', div.innerText)\n ev.preventDefault()\n }\n }\n }\n\n pasteHandler(ev: ClipboardEvent) {\n const text = ev.clipboardData!.getData('Text')\n\n const types = Array.from(ev.clipboardData!.types || [])\n const files = Array.from(ev.clipboardData!.files)\n if (types.every(type => type === 'Files') && files.length) {\n Promise.all(files.filter(i => {\n return /image/i.test(i.type)\n }).map(item => {\n const reader = new FileReader()\n return new Promise(resolve => {\n reader.onload = (event) => {\n resolve(event.target!.result)\n }\n reader.readAsDataURL(item)\n })\n })).then(urls => {\n const html = urls.map(i => {\n return `<img src=${i}>`\n }).join('')\n this.paste(html, text)\n })\n ev.preventDefault()\n return\n }\n\n const div = document.createElement('div')\n div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0'\n div.contentEditable = 'true'\n document.body.appendChild(div)\n div.focus()\n setTimeout(() => {\n document.body.removeChild(div)\n div.style.cssText = ''\n this.paste(div, text)\n })\n }\n\n private paste(dom: HTMLElement | string, text: string) {\n const slot = this.parser.parse(dom, new Slot([\n ContentType.BlockComponent,\n ContentType.InlineComponent,\n ContentType.Text\n ]))\n\n this.commander.paste(slot, text)\n }\n\n private handleShortcut(input: HTMLElement) {\n let isWriting = false\n let isIgnore = false\n this.subscription.add(\n fromEvent(input, 'compositionstart').subscribe(() => {\n isWriting = true\n }),\n fromEvent(input, 'compositionend').subscribe(() => {\n isWriting = false\n }),\n fromEvent<InputEvent>(input, 'beforeinput').subscribe(ev => {\n if (this.isSafari) {\n if (ev.inputType === 'insertFromComposition') {\n isIgnore = true\n }\n }\n }),\n fromEvent<KeyboardEvent>(input, 'keydown').pipe(filter(() => {\n if (this.isSafari && isIgnore) {\n isIgnore = false\n return false\n }\n return !isWriting // || !this.textarea.value\n })).subscribe(ev => {\n this.ignoreComposition = false\n let key = ev.key\n const keys = ')!@#$%^Z&*('\n const b = key === 'Process' && /Digit\\d/.test(ev.code) && ev.shiftKey\n if (b) {\n key = keys.charAt(+ev.code.substring(5))\n ev.preventDefault()\n }\n const is = this.keyboard.execShortcut({\n key: key,\n altKey: ev.altKey,\n shiftKey: ev.shiftKey,\n modKey: this.isMac ? ev.metaKey : ev.ctrlKey,\n agent: {\n key: ev.key,\n keyCode: ev.keyCode,\n code: ev.code\n }\n })\n if (is) {\n this.ignoreComposition = true\n ev.preventDefault()\n }\n })\n )\n }\n\n private handleInput(input: HTMLElement) {\n if (this.isMobileBrowser) {\n this.handleMobileInput(input)\n } else {\n this.handlePCInput(input)\n }\n }\n\n private handleMobileInput(input: HTMLElement) {\n let isCompositionStart = true\n let startIndex: number\n const compositionStart = () => {\n this.composition = true\n startIndex = this.selection.startOffset!\n const startSlot = this.selection.startSlot!\n const event = new Event<Slot, CompositionStartEventData>(startSlot, {\n index: startIndex\n })\n invokeListener(startSlot.parent!, 'onCompositionStart', event)\n }\n const compositionUpdate = (data: string) => {\n const startSlot = this.selection.startSlot!\n const event = new Event<Slot, CompositionUpdateEventData>(startSlot, {\n index: startIndex,\n data\n })\n\n invokeListener(startSlot.parent!, 'onCompositionUpdate', event)\n }\n const compositionEnd = (data: string) => {\n this.composition = false\n\n if (data) {\n this.commander.write(data)\n }\n const startSlot = this.selection.startSlot\n if (startSlot) {\n const event = new Event<Slot>(startSlot, null)\n invokeListener(startSlot.parent!, 'onCompositionEnd', event)\n }\n }\n this.subscription.add(\n fromEvent(input, 'compositionstart').subscribe(() => {\n compositionStart()\n }),\n fromEvent<CompositionEvent>(input, 'compositionupdate').subscribe(ev => {\n compositionUpdate(ev.data)\n }),\n fromEvent<CompositionEvent>(input, 'compositionend').subscribe(ev => {\n compositionEnd(ev.data)\n const startContainer = this.nativeSelection.focusNode\n if (startContainer instanceof Text && startContainer.textContent === ev.data) {\n startContainer.remove()\n }\n }),\n fromEvent<InputEvent>(input, 'beforeinput').subscribe(ev => {\n switch (ev.inputType) {\n case 'insertText':\n if (ev.data) {\n this.commander.write(ev.data)\n ev.preventDefault()\n }\n break\n case 'insertCompositionText':\n if (isCompositionStart) {\n isCompositionStart = false\n compositionStart()\n } else {\n compositionUpdate(ev.data || '')\n }\n break\n case 'deleteCompositionText':\n this.composition = false\n break\n case 'deleteContentBackward': {\n this.composition = false\n const range = ev.getTargetRanges()[0]\n if (!range) {\n break\n }\n const location = this.domAdapter.getLocationByNativeNode(range.startContainer)!\n const startSlot = this.selection.startSlot\n if (startSlot) {\n this.selection.setBaseAndExtent(\n startSlot,\n location.startIndex + range.startOffset,\n startSlot,\n location.startIndex + range.endOffset)\n\n this.commander.delete()\n }\n break\n }\n case 'insertReplacementText': {\n this.composition = false\n const range = ev.getTargetRanges()[0]\n const location = this.domAdapter.getLocationByNativeNode(range.startContainer)!\n const startSlot = this.selection.startSlot!\n this.selection.setBaseAndExtent(\n startSlot,\n location.startIndex + range.startOffset,\n startSlot,\n location.startIndex + range.endOffset)\n\n this.commander.delete()\n const text = ev.dataTransfer?.getData('text') || ev.data || null\n if (text) {\n this.commander.write(text)\n }\n break\n }\n //\n // case 'insertFromComposition': {\n // compositionEnd(ev.data || '')\n // break\n // }\n }\n })\n )\n }\n\n private handlePCInput(input: HTMLElement) {\n let startIndex = 0\n let isCompositionEnd = false\n this.subscription.add(\n fromEvent(input, 'compositionstart').pipe(filter(() => {\n return !this.ignoreComposition\n })).subscribe(() => {\n this.composition = true\n startIndex = this.selection.startOffset!\n const startSlot = this.selection.startSlot!\n const event = new Event<Slot, CompositionStartEventData>(startSlot, {\n index: startIndex\n })\n invokeListener(startSlot.parent!, 'onCompositionStart', event)\n }),\n fromEvent<CompositionEvent>(input, 'compositionupdate').pipe(filter(() => {\n return !this.ignoreComposition\n })).subscribe(ev => {\n const startSlot = this.selection.startSlot!\n const event = new Event(startSlot, {\n index: startIndex,\n data: ev.data\n })\n\n invokeListener(startSlot.parent!, 'onCompositionUpdate', event)\n }),\n merge(\n fromEvent<InputEvent>(input, 'beforeinput').pipe(\n map(ev => {\n ev.preventDefault()\n if (ev.inputType === 'insertCompositionText') {\n return null\n }\n if (ev.inputType === 'insertReplacementText') {\n const range = ev.getTargetRanges()[0]\n const location = this.domAdapter.getLocationByNativeNode(range.startContainer)!\n const startSlot = this.selection.startSlot!\n this.selection.setBaseAndExtent(\n startSlot,\n location.startIndex + range.startOffset,\n startSlot,\n location.startIndex + range.endOffset)\n\n this.commander.delete()\n return ev.dataTransfer?.getData('text') || ev.data || null\n }\n isCompositionEnd = ev.inputType === 'insertFromComposition'\n if (isCompositionEnd && this.composition) {\n return null\n }\n if (this.isSafari) {\n if (ev.inputType === 'insertText' || isCompositionEnd) {\n return ev.data\n }\n }\n if (!ev.isComposing && !!ev.data) {\n return ev.data\n }\n return null\n }),\n filter(text => {\n return text\n })\n ),\n this.isSafari ? new Observable<string>() :\n fromEvent<CompositionEvent>(input, 'compositionend').pipe(filter(() => {\n return !this.ignoreComposition\n })).pipe(\n filter(() => {\n return this.composition\n }),\n map(ev => {\n isCompositionEnd = true\n ev.preventDefault()\n return ev.data\n }),\n filter(() => {\n const b = this.ignoreComposition\n this.ignoreComposition = false\n return !b\n })\n )\n ).subscribe(text => {\n this.composition = false\n if (text) {\n const startContainer = this.nativeSelection.focusNode\n if (startContainer instanceof Text && startContainer.textContent === text) {\n startContainer.remove()\n }\n this.commander.write(text)\n }\n if (isCompositionEnd) {\n const startSlot = this.selection.startSlot\n if (startSlot) {\n const event = new Event<Slot>(startSlot, null)\n invokeListener(startSlot.parent!, 'onCompositionEnd', event)\n }\n }\n isCompositionEnd = false\n })\n )\n }\n}\n","import { Adapter } from '@textbus/core'\nimport { Subject } from '@tanbo/stream'\n\nimport { createElement } from './_utils/uikit'\nimport { VIEW_DOCUMENT } from './injection-tokens'\n\nexport abstract class DomAdapter<\n ViewComponent extends object = object,\n ViewElement extends object = object> extends Adapter<Element, Node, ViewComponent, ViewElement> {\n onViewUpdated = new Subject<void>()\n host = createElement('div', {\n styles: {\n cursor: 'text',\n wordBreak: 'break-all',\n boxSizing: 'border-box',\n flex: 1,\n outline: 'none'\n },\n attrs: {\n 'data-textbus-view': VIEW_DOCUMENT,\n },\n props: {\n id: 'textbus-' + Number((Math.random() + '').substring(2)).toString(16)\n }\n })\n}\n","import {\n ComponentConstructor,\n Component,\n ComponentLiteral,\n FocusManager,\n makeError,\n Module,\n NativeSelectionBridge,\n Registry,\n Textbus,\n Adapter,\n} from '@textbus/core'\nimport { Provider } from '@viewfly/core'\nimport { distinctUntilChanged, map, Subject } from '@tanbo/stream'\n\nimport { AttributeLoader, ComponentLoader, FormatLoader, Parser } from './parser'\nimport { EDITOR_OPTIONS, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK } from './injection-tokens'\nimport { SelectionBridge } from './selection-bridge'\nimport { Input } from './types'\nimport { MagicInput } from './magic-input'\nimport { CollaborateCursor } from './collaborate-cursor'\nimport { createElement } from './_utils/uikit'\nimport { NativeInput } from './native-input'\nimport { DomAdapter } from './dom-adapter'\n\nconst browserErrorFn = makeError('BrowserModule')\n\n/**\n * Textbus PC 端配置接口\n */\nexport interface ViewOptions {\n /** 跨平台适配器 */\n adapter: DomAdapter<any, any>\n\n /** 编辑器根节点 */\n renderTo(): HTMLElement\n\n /** 自动获取焦点 */\n autoFocus?: boolean\n /** 编辑区最小高度 */\n minHeight?: string\n /** 组件加载器 */\n componentLoaders?: ComponentLoader[]\n /** 格式加载器 */\n formatLoaders?: FormatLoader<any>[]\n /** 属性加载器 */\n attributeLoaders?: AttributeLoader<any>[]\n /** 使用 contentEditable 作为编辑器控制可编辑范围 */\n useContentEditable?: boolean\n}\n\nexport class BrowserModule implements Module {\n providers: Provider[]\n\n private workbench!: HTMLElement\n\n constructor(public config: ViewOptions) {\n const { mask, wrapper } = BrowserModule.createLayout()\n wrapper.prepend(config.adapter.host)\n if (config.minHeight) {\n config.adapter.host.style.minHeight = config.minHeight\n }\n this.providers = [{\n provide: EDITOR_OPTIONS,\n useValue: config\n }, {\n provide: VIEW_CONTAINER,\n useValue: wrapper\n }, {\n provide: VIEW_DOCUMENT,\n useValue: config.adapter.host\n }, {\n provide: VIEW_MASK,\n useValue: mask\n }, {\n provide: NativeSelectionBridge,\n useExisting: SelectionBridge\n }, {\n provide: Input,\n useClass: config.useContentEditable ? NativeInput : MagicInput\n }, {\n provide: Adapter,\n useValue: config.adapter\n }, {\n provide: DomAdapter,\n useValue: config.adapter\n }, {\n provide: FocusManager,\n useFactory: (input: Input): FocusManager => {\n const focusEvent = new Subject<void>()\n const blurEvent = new Subject<void>()\n input.caret.onPositionChange.pipe(\n map(p => !!p),\n distinctUntilChanged()\n ).subscribe(b => {\n if (b) {\n focusEvent.next()\n } else {\n blurEvent.next()\n }\n })\n return {\n onFocus: focusEvent,\n onBlur: blurEvent\n }\n },\n deps: [Input]\n },\n Parser,\n SelectionBridge,\n CollaborateCursor\n ]\n\n this.workbench = wrapper\n }\n\n /**\n * 解析 HTML 并返回一个组件实例\n * @param html 要解析的 HTML\n * @param rootComponentLoader 文档根组件加载器\n * @param textbus\n */\n readDocumentByHTML(html: string, rootComponentLoader: ComponentLoader, textbus: Textbus): Component {\n const parser = textbus.get(Parser)\n const doc = parser.parseDoc(html, rootComponentLoader)\n if (doc instanceof Component) {\n return doc\n }\n throw browserErrorFn('rootComponentLoader must return a component instance.')\n }\n\n /**\n * 将组件数据解析到组件实例中\n * @param data 要解析的 JSON 数据\n * @param rootComponent 根组件\n * @param textbus\n */\n readDocumentByComponentLiteral(data: ComponentLiteral, rootComponent: ComponentConstructor, textbus: Textbus): Component {\n const registry = textbus.get(Registry)\n return registry.createComponentByFactory(data, rootComponent)\n }\n\n async setup(textbus: Textbus) {\n const host = this.config.renderTo()\n if (!(host instanceof HTMLElement)) {\n throw browserErrorFn('view container is not a HTMLElement')\n }\n\n host.append(this.workbench)\n await textbus.get(Input).onReady\n return () => {\n this.workbench.remove()\n }\n }\n\n onAfterStartup(textbus: Textbus) {\n if (this.config.autoFocus) {\n textbus.focus()\n }\n }\n\n onDestroy(textbus: Textbus) {\n textbus.get(Input).destroy()\n textbus.get(SelectionBridge).destroy()\n textbus.get(CollaborateCursor).destroy()\n }\n\n private static createLayout() {\n const mask = createElement('div', {\n attrs: {\n 'data-textbus-view': VIEW_MASK,\n },\n styles: {\n position: 'absolute',\n left: 0,\n right: 0,\n top: 0,\n bottom: 0,\n pointerEvents: 'none',\n // overflow: 'hidden'\n }\n })\n const maskWrapper = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n right: 0,\n top: 0,\n bottom: 0,\n margin: '0 -2px',\n zIndex: 1,\n pointerEvents: 'none',\n overflow: 'hidden'\n },\n children: [mask]\n })\n const wrapper = createElement('div', {\n attrs: {\n 'data-textbus-view': VIEW_CONTAINER,\n },\n styles: {\n display: 'flex',\n minHeight: '100%',\n position: 'relative',\n flexDirection: 'column'\n },\n children: [maskWrapper]\n })\n return {\n wrapper,\n mask\n }\n }\n}\n"],"names":["rect","InjectionToken","Parser","Slot","__decorateClass","Injectable","__decorateParam","SelectionBridge","filter","fromEvent","Subject","delay","position","distinctUntilChanged","Subscription","top","MagicInput","ContentType","Event","invokeListener","merge","map","Observable","CollaborateCursor","anchor","Optional","NativeInput","Adapter","makeError","NativeSelectionBridge","FocusManager","Component","Registry"],"mappings":"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"}
|