From d464c5043508c63b29174ae05bc37ec66c87d45f Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Tue, 18 Jul 2023 20:33:59 +0800 Subject: [PATCH] refactor: add prettier and format --- .prettierrc | 8 + .vscode/settings.json | 13 +- src/components/dialog/Dialog.ts | 47 +- src/components/signature/Signature.ts | 32 +- src/editor/core/command/Command.ts | 7 +- src/editor/core/command/CommandAdapt.ts | 271 +++-- src/editor/core/contextmenu/ContextMenu.ts | 59 +- .../core/contextmenu/menus/controlMenus.ts | 10 +- .../core/contextmenu/menus/globalMenus.ts | 10 +- .../core/contextmenu/menus/hyperlinkMenus.ts | 28 +- .../core/contextmenu/menus/imageMenus.ts | 41 +- .../core/contextmenu/menus/tableMenus.ts | 14 +- src/editor/core/cursor/Cursor.ts | 38 +- src/editor/core/cursor/CursorAgent.ts | 22 +- src/editor/core/draw/Draw.ts | 300 ++++-- src/editor/core/draw/control/Control.ts | 47 +- .../draw/control/checkbox/CheckboxControl.ts | 4 +- .../core/draw/control/select/SelectControl.ts | 25 +- .../core/draw/control/text/TextControl.ts | 21 +- src/editor/core/draw/frame/Background.ts | 4 +- src/editor/core/draw/frame/Footer.ts | 13 +- src/editor/core/draw/frame/Header.ts | 13 +- src/editor/core/draw/frame/Margin.ts | 16 +- src/editor/core/draw/frame/PageNumber.ts | 32 +- src/editor/core/draw/frame/Placeholder.ts | 22 +- src/editor/core/draw/frame/Watermark.ts | 17 +- src/editor/core/draw/interactive/Search.ts | 83 +- .../core/draw/particle/CheckboxParticle.ts | 16 +- .../core/draw/particle/HyperlinkParticle.ts | 21 +- .../core/draw/particle/ImageParticle.ts | 21 +- src/editor/core/draw/particle/ListParticle.ts | 39 +- src/editor/core/draw/particle/PageBreak.ts | 20 +- src/editor/core/draw/particle/Separator.ts | 11 +- src/editor/core/draw/particle/Subscript.ts | 11 +- src/editor/core/draw/particle/Superscript.ts | 11 +- src/editor/core/draw/particle/TextParticle.ts | 33 +- .../core/draw/particle/block/BlockParticle.ts | 4 +- .../draw/particle/block/modules/BaseBlock.ts | 4 +- .../particle/block/modules/IFrameBlock.ts | 4 +- .../draw/particle/block/modules/VideoBlock.ts | 4 +- .../core/draw/particle/date/DateParticle.ts | 32 +- .../core/draw/particle/date/DatePicker.ts | 151 +-- .../core/draw/particle/latex/LaTexParticle.ts | 12 +- .../draw/particle/latex/utils/LaTexUtils.ts | 414 +++++--- .../core/draw/particle/latex/utils/hershey.ts | 18 +- .../core/draw/particle/latex/utils/symbols.ts | 42 +- .../core/draw/particle/previewer/Previewer.ts | 113 ++- .../core/draw/particle/table/TableParticle.ts | 77 +- .../core/draw/particle/table/TableTool.ts | 185 ++-- .../core/draw/richtext/AbstractRichText.ts | 15 +- src/editor/core/draw/richtext/Highlight.ts | 4 +- src/editor/core/draw/richtext/Strikeout.ts | 4 +- src/editor/core/draw/richtext/Underline.ts | 4 +- src/editor/core/event/CanvasEvent.ts | 17 +- src/editor/core/event/GlobalEvent.ts | 16 +- src/editor/core/event/handlers/click.ts | 12 +- src/editor/core/event/handlers/composition.ts | 2 +- src/editor/core/event/handlers/copy.ts | 2 +- src/editor/core/event/handlers/cut.ts | 2 +- src/editor/core/event/handlers/drag.ts | 6 +- src/editor/core/event/handlers/drop.ts | 2 +- src/editor/core/event/handlers/input.ts | 14 +- src/editor/core/event/handlers/keydown.ts | 73 +- src/editor/core/event/handlers/mousedown.ts | 30 +- src/editor/core/event/handlers/mouseleave.ts | 6 +- src/editor/core/event/handlers/mousemove.ts | 30 +- src/editor/core/event/handlers/mouseup.ts | 89 +- src/editor/core/history/HistoryManager.ts | 4 +- src/editor/core/i18n/I18n.ts | 7 +- src/editor/core/listener/Listener.ts | 4 +- src/editor/core/observer/ImageObserver.ts | 4 +- src/editor/core/observer/ScrollObserver.ts | 18 +- src/editor/core/observer/SelectionObserver.ts | 15 +- src/editor/core/plugin/Plugin.ts | 9 +- src/editor/core/position/Position.ts | 125 ++- src/editor/core/range/RangeManager.ts | 65 +- src/editor/core/register/Register.ts | 10 +- src/editor/core/shortcut/Shortcut.ts | 17 +- src/editor/core/shortcut/keys/listKeys.ts | 2 +- src/editor/core/shortcut/keys/richtextKeys.ts | 2 +- src/editor/core/shortcut/keys/titleKeys.ts | 20 +- src/editor/core/worker/WorkerManager.ts | 13 +- src/editor/core/worker/works/catalog.ts | 8 +- src/editor/core/worker/works/wordCount.ts | 2 +- src/editor/core/zone/Zone.ts | 12 +- src/editor/dataset/constant/Checkbox.ts | 2 +- src/editor/dataset/constant/Common.ts | 19 +- src/editor/dataset/constant/ContextMenu.ts | 2 +- src/editor/dataset/constant/Control.ts | 2 +- src/editor/dataset/constant/Cursor.ts | 2 +- src/editor/dataset/constant/Editor.ts | 2 +- src/editor/dataset/constant/Element.ts | 14 +- src/editor/dataset/constant/Footer.ts | 2 +- src/editor/dataset/constant/Header.ts | 2 +- src/editor/dataset/constant/List.ts | 2 +- src/editor/dataset/constant/PageNumber.ts | 2 +- src/editor/dataset/constant/Placeholder.ts | 2 +- src/editor/dataset/constant/Regular.ts | 2 +- src/editor/dataset/constant/Title.ts | 14 +- src/editor/dataset/constant/Watermark.ts | 2 +- src/editor/dataset/enum/Block.ts | 2 +- src/editor/dataset/enum/Common.ts | 2 +- src/editor/dataset/enum/Control.ts | 2 +- src/editor/dataset/enum/Editor.ts | 2 +- src/editor/dataset/enum/Element.ts | 2 +- src/editor/dataset/enum/ElementStyle.ts | 2 +- src/editor/dataset/enum/Event.ts | 2 +- src/editor/dataset/enum/KeyMap.ts | 2 +- src/editor/dataset/enum/List.ts | 4 +- src/editor/dataset/enum/Observer.ts | 2 +- src/editor/dataset/enum/Row.ts | 2 +- src/editor/dataset/enum/Title.ts | 2 +- src/editor/dataset/enum/VerticalAlign.ts | 2 +- src/editor/dataset/enum/table/Table.ts | 2 +- src/editor/dataset/enum/table/TableTool.ts | 2 +- src/editor/index.ts | 38 +- src/editor/interface/Block.ts | 12 +- src/editor/interface/Catalog.ts | 10 +- src/editor/interface/Checkbox.ts | 20 +- src/editor/interface/Common.ts | 13 +- src/editor/interface/Control.ts | 69 +- src/editor/interface/Cursor.ts | 10 +- src/editor/interface/Draw.ts | 46 +- src/editor/interface/Editor.ts | 117 ++- src/editor/interface/Element.ts | 162 +-- src/editor/interface/Footer.ts | 8 +- src/editor/interface/Header.ts | 8 +- src/editor/interface/Listener.ts | 47 +- src/editor/interface/Margin.ts | 2 +- src/editor/interface/PageNumber.ts | 22 +- src/editor/interface/Placeholder.ts | 12 +- src/editor/interface/Plugin.ts | 7 +- src/editor/interface/Position.ts | 82 +- src/editor/interface/Previewer.ts | 14 +- src/editor/interface/Range.ts | 30 +- src/editor/interface/Row.ts | 24 +- src/editor/interface/Search.ts | 18 +- src/editor/interface/Title.ts | 14 +- src/editor/interface/Watermark.ts | 12 +- .../interface/contextmenu/ContextMenu.ts | 92 +- src/editor/interface/i18n/I18n.ts | 4 +- src/editor/interface/shortcut/Shortcut.ts | 18 +- src/editor/interface/table/Colgroup.ts | 6 +- src/editor/interface/table/Td.ts | 42 +- src/editor/interface/table/Tr.ts | 10 +- src/editor/types/index.d.ts | 6 +- src/editor/utils/clipboard.ts | 106 +- src/editor/utils/element.ts | 119 ++- src/editor/utils/hotkey.ts | 2 +- src/editor/utils/index.ts | 80 +- src/editor/utils/print.ts | 22 +- src/editor/utils/ua.ts | 3 +- src/main.ts | 956 +++++++++++------- src/mock.ts | 466 +++++---- src/plugins/copy/index.ts | 9 +- src/plugins/markdown/index.ts | 44 +- src/utils/index.ts | 2 +- src/utils/prism.ts | 18 +- 158 files changed, 3747 insertions(+), 2263 deletions(-) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..2407e7e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "semi": false, + "singleQuote": true, + "printWidth": 80, + "trailingComma": "none", + "arrowParens": "avoid", + "endOfLine": "lf" +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 44f91a0..4ede554 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,9 +10,11 @@ "CRDT", "deletable", "dppx", + "esbenp", "inputarea", "linebreak", "noopener", + "Parens", "prismjs", "resizer", "richtext", @@ -34,5 +36,14 @@ "typescript.tsdk": "node_modules/typescript/lib", "editor.codeActionsOnSave": { "source.fixAll.eslint": true + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" } -} +} \ No newline at end of file diff --git a/src/components/dialog/Dialog.ts b/src/components/dialog/Dialog.ts index 36c1c05..d3f0112 100644 --- a/src/components/dialog/Dialog.ts +++ b/src/components/dialog/Dialog.ts @@ -2,36 +2,39 @@ import { EditorComponent, EDITOR_COMPONENT } from '../../editor' import './dialog.css' export interface IDialogData { - type: string; - label?: string; - name: string; - value?: string; - options?: { label: string; value: string; }[]; - placeholder?: string; - width?: number; - height?: number; - required?: boolean; + type: string + label?: string + name: string + value?: string + options?: { label: string; value: string }[] + placeholder?: string + width?: number + height?: number + required?: boolean } export interface IDialogConfirm { - name: string; - value: string; + name: string + value: string } export interface IDialogOptions { - onClose?: () => void; - onCancel?: () => void; - onConfirm?: (payload: IDialogConfirm[]) => void; - title: string; - data: IDialogData[]; + onClose?: () => void + onCancel?: () => void + onConfirm?: (payload: IDialogConfirm[]) => void + title: string + data: IDialogData[] } export class Dialog { - private options: IDialogOptions private mask: HTMLDivElement | null private container: HTMLDivElement | null - private inputList: (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[] + private inputList: ( + | HTMLInputElement + | HTMLTextAreaElement + | HTMLSelectElement + )[] constructor(options: IDialogOptions) { this.options = options @@ -90,7 +93,10 @@ export class Dialog { } } // 选项输入框 - let optionInput: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement + let optionInput: + | HTMLInputElement + | HTMLTextAreaElement + | HTMLSelectElement if (option.type === 'select') { optionInput = document.createElement('select') option.options?.forEach(item => { @@ -162,5 +168,4 @@ export class Dialog { this.mask?.remove() this.container?.remove() } - -} \ No newline at end of file +} diff --git a/src/components/signature/Signature.ts b/src/components/signature/Signature.ts index b779810..465a2a9 100644 --- a/src/components/signature/Signature.ts +++ b/src/components/signature/Signature.ts @@ -2,17 +2,17 @@ import { EditorComponent, EDITOR_COMPONENT } from '../../editor' import './signature.css' export interface ISignatureResult { - value: string; - width: number; - height: number; + value: string + width: number + height: number } export interface ISignatureOptions { - width?: number; - height?: number; - onClose?: () => void; - onCancel?: () => void; - onConfirm?: (payload: ISignatureResult | null) => void; + width?: number + height?: number + onClose?: () => void + onCancel?: () => void + onConfirm?: (payload: ISignatureResult | null) => void } export class Signature { @@ -43,7 +43,8 @@ export class Signature { this.dpr = window.devicePixelRatio this.canvasWidth = (options.width || this.DEFAULT_WIDTH) * this.dpr this.canvasHeight = (options.height || this.DEFAULT_HEIGHT) * this.dpr - const { mask, container, trashContainer, undoContainer, canvas } = this._render() + const { mask, container, trashContainer, undoContainer, canvas } = + this._render() this.mask = mask this.container = container this.trashContainer = trashContainer @@ -213,7 +214,8 @@ export class Signature { const targetLineWidth = Math.min(5, Math.max(1, 5 - speed * SPEED_FACTOR)) // 平滑过渡算法(20%的变化比例)调整线条粗细:系数0.2 const SMOOTH_FACTOR = 0.2 - this.ctx.lineWidth = this.ctx.lineWidth * (1 - SMOOTH_FACTOR) + targetLineWidth * SMOOTH_FACTOR + this.ctx.lineWidth = + this.ctx.lineWidth * (1 - SMOOTH_FACTOR) + targetLineWidth * SMOOTH_FACTOR // 绘制 const { offsetX, offsetY } = evt this.ctx.beginPath() @@ -231,7 +233,12 @@ export class Signature { private _stopDraw() { this.isDrawing = false if (this.isDrawn) { - const imageData = this.ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight) + const imageData = this.ctx.getImageData( + 0, + 0, + this.canvasWidth, + this.canvasHeight + ) const self = this this._saveUndoFn(function () { self.ctx.clearRect(0, 0, self.canvasWidth, self.canvasHeight) @@ -299,5 +306,4 @@ export class Signature { this.mask.remove() this.container.remove() } - -} \ No newline at end of file +} diff --git a/src/editor/core/command/Command.ts b/src/editor/core/command/Command.ts index 649deff..a00ff73 100644 --- a/src/editor/core/command/Command.ts +++ b/src/editor/core/command/Command.ts @@ -2,7 +2,6 @@ import { CommandAdapt } from './CommandAdapt' // 通过CommandAdapt中转避免直接暴露编辑器上下文 export class Command { - public executeMode: CommandAdapt['mode'] public executeCut: CommandAdapt['cut'] public executeCopy: CommandAdapt['copy'] @@ -130,7 +129,8 @@ export class Command { this.executeCancelMergeTableCell = adapt.cancelMergeTableCell.bind(adapt) this.executeTableTdVerticalAlign = adapt.tableTdVerticalAlign.bind(adapt) this.executeTableBorderType = adapt.tableBorderType.bind(adapt) - this.executeTableTdBackgroundColor = adapt.tableTdBackgroundColor.bind(adapt) + this.executeTableTdBackgroundColor = + adapt.tableTdBackgroundColor.bind(adapt) this.executeImage = adapt.image.bind(adapt) this.executeHyperlink = adapt.hyperlink.bind(adapt) this.executeDeleteHyperlink = adapt.deleteHyperlink.bind(adapt) @@ -174,5 +174,4 @@ export class Command { this.getPaperMargin = adapt.getPaperMargin.bind(adapt) this.getSearchNavigateInfo = adapt.getSearchNavigateInfo.bind(adapt) } - -} \ No newline at end of file +} diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts index b3e7649..091559e 100644 --- a/src/editor/core/command/CommandAdapt.ts +++ b/src/editor/core/command/CommandAdapt.ts @@ -3,7 +3,12 @@ import { EDITOR_ELEMENT_STYLE_ATTR } from '../../dataset/constant/Element' import { titleSizeMapping } from '../../dataset/constant/Title' import { defaultWatermarkOption } from '../../dataset/constant/Watermark' import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control' -import { EditorContext, EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor' +import { + EditorContext, + EditorMode, + PageMode, + PaperDirection +} from '../../dataset/enum/Editor' import { ElementType } from '../../dataset/enum/Element' import { ElementStyleKey } from '../../dataset/enum/ElementStyle' import { ListStyle, ListType } from '../../dataset/enum/List' @@ -12,8 +17,17 @@ import { TableBorder } from '../../dataset/enum/table/Table' import { TitleLevel } from '../../dataset/enum/Title' import { VerticalAlign } from '../../dataset/enum/VerticalAlign' import { ICatalog } from '../../interface/Catalog' -import { IAppendElementListOption, IDrawImagePayload, IGetValueOption, IPainterOption } from '../../interface/Draw' -import { IEditorData, IEditorOption, IEditorResult } from '../../interface/Editor' +import { + IAppendElementListOption, + IDrawImagePayload, + IGetValueOption, + IPainterOption +} from '../../interface/Draw' +import { + IEditorData, + IEditorOption, + IEditorResult +} from '../../interface/Editor' import { IElement, IElementStyle } from '../../interface/Element' import { IMargin } from '../../interface/Margin' import { RangeContext } from '../../interface/Range' @@ -22,7 +36,12 @@ import { ITd } from '../../interface/table/Td' import { ITr } from '../../interface/table/Tr' import { IWatermark } from '../../interface/Watermark' import { deepClone, downloadFile, getUUID } from '../../utils' -import { formatElementContext, formatElementList, isTextLikeElement, pickElementAttr } from '../../utils/element' +import { + formatElementContext, + formatElementList, + isTextLikeElement, + pickElementAttr +} from '../../utils/element' import { printImageBase64 } from '../../utils/print' import { Control } from '../draw/control/Control' import { Draw } from '../draw/Draw' @@ -36,7 +55,6 @@ import { RangeManager } from '../range/RangeManager' import { WorkerManager } from '../worker/WorkerManager' export class CommandAdapt { - private draw: Draw private range: RangeManager private position: Position @@ -103,11 +121,19 @@ export class CommandAdapt { const { startIndex, endIndex } = this.range.getRange() const isCollapsed = startIndex === endIndex // 首字符禁止删除 - if (isCollapsed && elementList[startIndex].value === ZERO && startIndex === 0) { + if ( + isCollapsed && + elementList[startIndex].value === ZERO && + startIndex === 0 + ) { return } if (!isCollapsed) { - this.draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex) + this.draw.spliceElementList( + elementList, + startIndex + 1, + endIndex - startIndex + ) } else { this.draw.spliceElementList(elementList, startIndex, 1) } @@ -198,7 +224,12 @@ export class CommandAdapt { if (!selection || !selection.length) return let isExistUpdate = false selection.forEach(el => { - if ((!el.size && payload === defaultSize) || (el.size && el.size === payload)) return + if ( + (!el.size && payload === defaultSize) || + (el.size && el.size === payload) + ) { + return + } el.size = payload isExistUpdate = true }) @@ -310,7 +341,9 @@ export class CommandAdapt { if (activeControl) return const selection = this.range.getSelection() if (!selection) return - const superscriptIndex = selection.findIndex(s => s.type === ElementType.SUPERSCRIPT) + const superscriptIndex = selection.findIndex( + s => s.type === ElementType.SUPERSCRIPT + ) selection.forEach(el => { // 取消上标 if (~superscriptIndex) { @@ -320,7 +353,11 @@ export class CommandAdapt { } } else { // 设置上标 - if (!el.type || el.type === ElementType.TEXT || el.type === ElementType.SUBSCRIPT) { + if ( + !el.type || + el.type === ElementType.TEXT || + el.type === ElementType.SUBSCRIPT + ) { el.type = ElementType.SUPERSCRIPT } } @@ -335,7 +372,9 @@ export class CommandAdapt { if (activeControl) return const selection = this.range.getSelection() if (!selection) return - const subscriptIndex = selection.findIndex(s => s.type === ElementType.SUBSCRIPT) + const subscriptIndex = selection.findIndex( + s => s.type === ElementType.SUBSCRIPT + ) selection.forEach(el => { // 取消下标 if (~subscriptIndex) { @@ -345,7 +384,11 @@ export class CommandAdapt { } } else { // 设置下标 - if (!el.type || el.type === ElementType.TEXT || el.type === ElementType.SUPERSCRIPT) { + if ( + !el.type || + el.type === ElementType.TEXT || + el.type === ElementType.SUPERSCRIPT + ) { el.type = ElementType.SUBSCRIPT } } @@ -388,9 +431,10 @@ export class CommandAdapt { if (!~startIndex && !~endIndex) return const elementList = this.draw.getElementList() // 需要改变的元素列表 - const changeElementList = startIndex === endIndex - ? this.range.getRangeElementList() - : elementList.slice(startIndex + 1, endIndex + 1) + const changeElementList = + startIndex === endIndex + ? this.range.getRangeElementList() + : elementList.slice(startIndex + 1, endIndex + 1) if (!changeElementList || !changeElementList.length) return // 设置值 const titleId = getUUID() @@ -428,7 +472,9 @@ export class CommandAdapt { const changeElementList = this.range.getRangeElementList() if (!changeElementList || !changeElementList.length) return // 如果包含列表则设置为取消列表 - const isUnsetList = changeElementList.find(el => el.listType === listType && el.listStyle === listStyle) + const isUnsetList = changeElementList.find( + el => el.listType === listType && el.listStyle === listStyle + ) // 设置值 const listId = getUUID() changeElementList.forEach(el => { @@ -601,13 +647,15 @@ export class CommandAdapt { id: newTdId, rowspan: 1, colspan: curTd.colspan, - value: [{ - value: ZERO, - size: 16, - tableId, - trId: newTrId, - tdId: newTdId - }] + value: [ + { + value: ZERO, + size: 16, + tableId, + trId: newTrId, + tdId: newTdId + } + ] }) } curTrList.splice(trIndex!, 0, newTr) @@ -637,9 +685,8 @@ export class CommandAdapt { const element = originalElementList[index!] const curTrList = element.trList! const curTr = curTrList[trIndex!] - const anchorTr = curTrList.length - 1 === trIndex - ? curTr - : curTrList[trIndex! + 1] + const anchorTr = + curTrList.length - 1 === trIndex ? curTr : curTrList[trIndex! + 1] // 之前/当前行跨行的增加跨行数 if (anchorTr.tdList.length < element.colgroup!.length) { const curTrNo = anchorTr.tdList[0].rowIndex! @@ -667,13 +714,15 @@ export class CommandAdapt { id: newTdId, rowspan: 1, colspan: curTd.colspan, - value: [{ - value: ZERO, - size: 16, - tableId, - trId: newTrId, - tdId: newTdId - }] + value: [ + { + value: ZERO, + size: 16, + tableId, + trId: newTrId, + tdId: newTdId + } + ] }) } curTrList.splice(trIndex! + 1, 0, newTr) @@ -711,13 +760,15 @@ export class CommandAdapt { id: tdId, rowspan: 1, colspan: 1, - value: [{ - value: ZERO, - size: 16, - tableId, - trId: tr.id, - tdId - }] + value: [ + { + value: ZERO, + size: 16, + tableId, + trId: tr.id, + tdId + } + ] }) } // 重新计算宽度 @@ -768,13 +819,15 @@ export class CommandAdapt { id: tdId, rowspan: 1, colspan: 1, - value: [{ - value: ZERO, - size: 16, - tableId, - trId: tr.id, - tdId - }] + value: [ + { + value: ZERO, + size: 16, + tableId, + trId: tr.id, + tdId + } + ] }) } // 重新计算宽度 @@ -834,13 +887,15 @@ export class CommandAdapt { id: tdId, rowspan: 1, colspan: 1, - value: [{ - value: ZERO, - size: 16, - tableId: element.id, - trId: tr.id, - tdId - }] + value: [ + { + value: ZERO, + size: 16, + tableId: element.id, + trId: tr.id, + tdId + } + ] }) start += 1 } @@ -885,7 +940,10 @@ export class CommandAdapt { if (td.colspan > 1) { const tdColIndex = td.colIndex! // 交叉减去一列 - if (tdColIndex <= curColIndex && tdColIndex + td.colspan - 1 >= curColIndex) { + if ( + tdColIndex <= curColIndex && + tdColIndex + td.colspan - 1 >= curColIndex + ) { td.colspan -= 1 } } @@ -940,7 +998,13 @@ export class CommandAdapt { if (isReadonly) return const positionContext = this.position.getPositionContext() if (!positionContext.isTable) return - const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange() + const { + isCrossRowCol, + startTdIndex, + endTdIndex, + startTrIndex, + endTrIndex + } = this.range.getRange() if (!isCrossRowCol) return const { index } = positionContext const originalElementList = this.draw.getOriginalElementList() @@ -966,8 +1030,10 @@ export class CommandAdapt { const tdColIndex = td.colIndex! const tdRowIndex = td.rowIndex! if ( - tdColIndex >= startColIndex && tdColIndex <= endColIndex - && tdRowIndex >= startRowIndex && tdRowIndex <= endRowIndex + tdColIndex >= startColIndex && + tdColIndex <= endColIndex && + tdRowIndex >= startRowIndex && + tdRowIndex <= endRowIndex ) { tdList.push(td) } @@ -994,7 +1060,12 @@ export class CommandAdapt { const tdEndX = tdStartX + td.width! const tdEndY = tdStartY + td.height! // 存在不符合项 - if (startX > tdStartX || startY > tdStartY || endX < tdEndX || endY < tdEndY) { + if ( + startX > tdStartX || + startY > tdStartY || + endX < tdEndX || + endY < tdEndY + ) { return } } @@ -1064,13 +1135,15 @@ export class CommandAdapt { id: tdId, rowspan: 1, colspan: 1, - value: [{ - value: ZERO, - size: 16, - tableId: element.id, - trId: curTr.id, - tdId - }] + value: [ + { + value: ZERO, + size: 16, + tableId: element.id, + trId: curTr.id, + tdId + } + ] }) } curTd.colspan = 1 @@ -1085,13 +1158,15 @@ export class CommandAdapt { id: tdId, rowspan: 1, colspan: 1, - value: [{ - value: ZERO, - size: 16, - tableId: element.id, - trId: tr.id, - tdId - }] + value: [ + { + value: ZERO, + size: 16, + tableId: element.id, + trId: tr.id, + tdId + } + ] }) } } @@ -1241,7 +1316,11 @@ export class CommandAdapt { const elementList = this.draw.getElementList() const [leftIndex, rightIndex] = hyperRange // 删除元素 - this.draw.spliceElementList(elementList, leftIndex, rightIndex - leftIndex + 1) + this.draw.spliceElementList( + elementList, + leftIndex, + rightIndex - leftIndex + 1 + ) this.draw.getHyperlinkParticle().clearHyperlinkPopup() // 重置画布 const newIndex = leftIndex - 1 @@ -1306,7 +1385,12 @@ export class CommandAdapt { // 光标存在分割线,则判断为修改线段逻辑 const endElement = elementList[endIndex + 1] if (endElement && endElement.type === ElementType.SEPARATOR) { - if (endElement.dashArray && endElement.dashArray.join() === payload.join()) return + if ( + endElement.dashArray && + endElement.dashArray.join() === payload.join() + ) { + return + } curIndex = endIndex endElement.dashArray = payload } else { @@ -1334,10 +1418,12 @@ export class CommandAdapt { if (isReadonly) return const activeControl = this.control.getActiveControl() if (activeControl) return - this.insertElementList([{ - type: ElementType.PAGE_BREAK, - value: WRAP - }]) + this.insertElementList([ + { + type: ElementType.PAGE_BREAK, + value: WRAP + } + ]) } public addWatermark(payload: IWatermark) { @@ -1458,7 +1544,8 @@ export class CommandAdapt { } curTdId = tdId! const curTableIndex = tableIndex! + pageDiffCount - const tableElementList = elementList[curTableIndex].trList![trIndex!].tdList[tdIndex!].value + const tableElementList = + elementList[curTableIndex].trList![trIndex!].tdList[tdIndex!].value // 表格内元素 const curIndex = index + tableDiffCount const tableElement = tableElementList[curIndex] @@ -1483,8 +1570,8 @@ export class CommandAdapt { const curIndex = match.index + pageDiffCount const element = elementList[curIndex] if ( - element.type === ElementType.CONTROL - && element.controlComponent !== ControlComponent.VALUE + element.type === ElementType.CONTROL && + element.controlComponent !== ControlComponent.VALUE ) { continue } @@ -1517,7 +1604,8 @@ export class CommandAdapt { const firstIndex = firstMatch.index + (payload.length - 1) if (firstMatch.type === EditorContext.TABLE) { const { tableIndex, trIndex, tdIndex, index } = firstMatch - const element = elementList[tableIndex!].trList![trIndex!].tdList[tdIndex!].value[index] + const element = + elementList[tableIndex!].trList![trIndex!].tdList[tdIndex!].value[index] this.position.setPositionContext({ isTable: true, index: tableIndex, @@ -1607,7 +1695,9 @@ export class CommandAdapt { const isCollapsed = startIndex === endIndex // 元素信息 const elementList = this.draw.getElementList() - const startElement = pickElementAttr(elementList[isCollapsed ? startIndex : startIndex + 1]) + const startElement = pickElementAttr( + elementList[isCollapsed ? startIndex : startIndex + 1] + ) const endElement = pickElementAttr(elementList[endIndex]) // 页码信息 const positionList = this.position.getPositionList() @@ -1676,7 +1766,10 @@ export class CommandAdapt { this.draw.insertElementList(payload) } - public appendElementList(elementList: IElement[], options?: IAppendElementListOption) { + public appendElementList( + elementList: IElement[], + options?: IAppendElementListOption + ) { if (!elementList.length) return const isReadonly = this.draw.isReadonly() if (isReadonly) return @@ -1716,7 +1809,10 @@ export class CommandAdapt { let newIndex = -1 for (let e = 0; e < elementList.length; e++) { const element = elementList[e] - if (element.titleId === titleId && elementList[e + 1]?.titleId !== titleId) { + if ( + element.titleId === titleId && + elementList[e + 1]?.titleId !== titleId + ) { newIndex = e break } @@ -1757,5 +1853,4 @@ export class CommandAdapt { }) } } - -} \ No newline at end of file +} diff --git a/src/editor/core/contextmenu/ContextMenu.ts b/src/editor/core/contextmenu/ContextMenu.ts index d41b156..d32789d 100644 --- a/src/editor/core/contextmenu/ContextMenu.ts +++ b/src/editor/core/contextmenu/ContextMenu.ts @@ -1,7 +1,10 @@ import { NAME_PLACEHOLDER } from '../../dataset/constant/ContextMenu' import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../dataset/constant/Editor' import { EditorComponent } from '../../dataset/enum/Editor' -import { IContextMenuContext, IRegisterContextMenu } from '../../interface/contextmenu/ContextMenu' +import { + IContextMenuContext, + IRegisterContextMenu +} from '../../interface/contextmenu/ContextMenu' import { findParent } from '../../utils' import { Command } from '../command/Command' import { Draw } from '../draw/Draw' @@ -15,14 +18,13 @@ import { imageMenus } from './menus/imageMenus' import { tableMenus } from './menus/tableMenus' interface IRenderPayload { - contextMenuList: IRegisterContextMenu[]; - left: number; - top: number; - parentMenuContainer?: HTMLDivElement; + contextMenuList: IRegisterContextMenu[] + left: number + top: number + parentMenuContainer?: HTMLDivElement } export class ContextMenu { - private draw: Draw private command: Command private range: RangeManager @@ -63,7 +65,10 @@ export class ContextMenu { } public removeEvent() { - this.container.removeEventListener('contextmenu', this._proxyContextMenuEvent) + this.container.removeEventListener( + 'contextmenu', + this._proxyContextMenuEvent + ) document.removeEventListener('mousedown', this._handleEffect) } @@ -88,7 +93,7 @@ export class ContextMenu { this._render({ contextMenuList: renderList, left: evt.x, - top: evt.y, + top: evt.y }) } evt.preventDefault() @@ -99,8 +104,10 @@ export class ContextMenu { // 点击非右键菜单内 const contextMenuDom = findParent( evt.target as Element, - (node: Node & Element) => !!node && node.nodeType === 1 - && node.getAttribute(EDITOR_COMPONENT) === EditorComponent.CONTEXTMENU, + (node: Node & Element) => + !!node && + node.nodeType === 1 && + node.getAttribute(EDITOR_COMPONENT) === EditorComponent.CONTEXTMENU, true ) if (!contextMenuDom) { @@ -112,7 +119,11 @@ export class ContextMenu { private _getContext(): IContextMenuContext { // 是否是只读模式 const isReadonly = this.draw.isReadonly() - const { isCrossRowCol: crossRowCol, startIndex, endIndex } = this.range.getRange() + const { + isCrossRowCol: crossRowCol, + startIndex, + endIndex + } = this.range.getRange() // 是否存在焦点 const editorTextFocus = !!(~startIndex || ~endIndex) // 是否存在选区 @@ -141,7 +152,10 @@ export class ContextMenu { private _createContextMenuContainer(): HTMLDivElement { const contextMenuContainer = document.createElement('div') contextMenuContainer.classList.add(`${EDITOR_PREFIX}-contextmenu-container`) - contextMenuContainer.setAttribute(EDITOR_COMPONENT, EditorComponent.CONTEXTMENU) + contextMenuContainer.setAttribute( + EDITOR_COMPONENT, + EditorComponent.CONTEXTMENU + ) this.container.append(contextMenuContainer) return contextMenuContainer } @@ -155,7 +169,10 @@ export class ContextMenu { let childMenuContainer: HTMLDivElement | null = null // 父菜单添加子菜单映射关系 if (parentMenuContainer) { - this.contextMenuRelationShip.set(parentMenuContainer, contextMenuContainer) + this.contextMenuRelationShip.set( + parentMenuContainer, + contextMenuContainer + ) } for (let c = 0; c < contextMenuList.length; c++) { const menu = contextMenuList[c] @@ -186,9 +203,12 @@ export class ContextMenu { parentMenuContainer: contextMenuContainer }) } - menuItem.onmouseleave = (evt) => { + menuItem.onmouseleave = evt => { // 移动到子菜单选项选中状态不变化 - if (!childMenuContainer || !childMenuContainer.contains(evt.relatedTarget as Node)) { + if ( + !childMenuContainer || + !childMenuContainer.contains(evt.relatedTarget as Node) + ) { this._setHoverStatus(menuItem, false) } } @@ -235,9 +255,8 @@ export class ContextMenu { const innerWidth = window.innerWidth const contextMenuWidth = contextMenuContainer.getBoundingClientRect().width // 右侧空间不足时,以菜单右上角作为起始点 - const adjustLeft = left + contextMenuWidth > innerWidth - ? left - contextMenuWidth - : left + const adjustLeft = + left + contextMenuWidth > innerWidth ? left - contextMenuWidth : left contextMenuContainer.style.left = `${adjustLeft}px` contextMenuContainer.style.top = `${top}px` this.contextMenuContainerList.push(contextMenuContainer) @@ -255,7 +274,8 @@ export class ContextMenu { private _setHoverStatus(payload: HTMLDivElement, status: boolean) { if (status) { - payload.parentNode?.querySelectorAll(`${EDITOR_PREFIX}-contextmenu-item`) + payload.parentNode + ?.querySelectorAll(`${EDITOR_PREFIX}-contextmenu-item`) .forEach(child => child.classList.remove('hover')) payload.classList.add('hover') } else { @@ -287,5 +307,4 @@ export class ContextMenu { this.contextMenuContainerList = [] this.contextMenuRelationShip.clear() } - } diff --git a/src/editor/core/contextmenu/menus/controlMenus.ts b/src/editor/core/contextmenu/menus/controlMenus.ts index 0c10bc4..3ce3121 100644 --- a/src/editor/core/contextmenu/menus/controlMenus.ts +++ b/src/editor/core/contextmenu/menus/controlMenus.ts @@ -5,11 +5,15 @@ import { Command } from '../../command/Command' export const controlMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.control.delete', - when: (payload) => { - return !payload.isReadonly && !payload.editorHasSelection && payload.startElement?.type === ElementType.CONTROL + when: payload => { + return ( + !payload.isReadonly && + !payload.editorHasSelection && + payload.startElement?.type === ElementType.CONTROL + ) }, callback: (command: Command) => { command.executeRemoveControl() } } -] \ No newline at end of file +] diff --git a/src/editor/core/contextmenu/menus/globalMenus.ts b/src/editor/core/contextmenu/menus/globalMenus.ts index 3f72f8e..fa79e49 100644 --- a/src/editor/core/contextmenu/menus/globalMenus.ts +++ b/src/editor/core/contextmenu/menus/globalMenus.ts @@ -6,7 +6,7 @@ export const globalMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.global.cut', shortCut: `${isApple ? '⌘' : 'Ctrl'} + X`, - when: (payload) => { + when: payload => { return !payload.isReadonly }, callback: (command: Command) => { @@ -16,7 +16,7 @@ export const globalMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.global.copy', shortCut: `${isApple ? '⌘' : 'Ctrl'} + C`, - when: (payload) => { + when: payload => { return payload.editorHasSelection }, callback: (command: Command) => { @@ -26,7 +26,7 @@ export const globalMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.global.paste', shortCut: `${isApple ? '⌘' : 'Ctrl'} + V`, - when: (payload) => { + when: payload => { return !payload.isReadonly && payload.editorTextFocus }, callback: (command: Command) => { @@ -36,7 +36,7 @@ export const globalMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.global.selectAll', shortCut: `${isApple ? '⌘' : 'Ctrl'} + A`, - when: (payload) => { + when: payload => { return payload.editorTextFocus }, callback: (command: Command) => { @@ -54,4 +54,4 @@ export const globalMenus: IRegisterContextMenu[] = [ command.executePrint() } } -] \ No newline at end of file +] diff --git a/src/editor/core/contextmenu/menus/hyperlinkMenus.ts b/src/editor/core/contextmenu/menus/hyperlinkMenus.ts index fdd037e..d243f06 100644 --- a/src/editor/core/contextmenu/menus/hyperlinkMenus.ts +++ b/src/editor/core/contextmenu/menus/hyperlinkMenus.ts @@ -1,12 +1,18 @@ import { ElementType } from '../../../dataset/enum/Element' -import { IContextMenuContext, IRegisterContextMenu } from '../../../interface/contextmenu/ContextMenu' +import { + IContextMenuContext, + IRegisterContextMenu +} from '../../../interface/contextmenu/ContextMenu' import { Command } from '../../command/Command' export const hyperlinkMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.hyperlink.delete', - when: (payload) => { - return !payload.isReadonly && payload.startElement?.type === ElementType.HYPERLINK + when: payload => { + return ( + !payload.isReadonly && + payload.startElement?.type === ElementType.HYPERLINK + ) }, callback: (command: Command) => { command.executeDeleteHyperlink() @@ -14,8 +20,11 @@ export const hyperlinkMenus: IRegisterContextMenu[] = [ }, { i18nPath: 'contextmenu.hyperlink.cancel', - when: (payload) => { - return !payload.isReadonly && payload.startElement?.type === ElementType.HYPERLINK + when: payload => { + return ( + !payload.isReadonly && + payload.startElement?.type === ElementType.HYPERLINK + ) }, callback: (command: Command) => { command.executeCancelHyperlink() @@ -23,8 +32,11 @@ export const hyperlinkMenus: IRegisterContextMenu[] = [ }, { i18nPath: 'contextmenu.hyperlink.edit', - when: (payload) => { - return !payload.isReadonly && payload.startElement?.type === ElementType.HYPERLINK + when: payload => { + return ( + !payload.isReadonly && + payload.startElement?.type === ElementType.HYPERLINK + ) }, callback: (command: Command, context: IContextMenuContext) => { const url = window.prompt('编辑链接', context.startElement?.url) @@ -33,4 +45,4 @@ export const hyperlinkMenus: IRegisterContextMenu[] = [ } } } -] \ No newline at end of file +] diff --git a/src/editor/core/contextmenu/menus/imageMenus.ts b/src/editor/core/contextmenu/menus/imageMenus.ts index 04b3d0b..c2b3ead 100644 --- a/src/editor/core/contextmenu/menus/imageMenus.ts +++ b/src/editor/core/contextmenu/menus/imageMenus.ts @@ -1,14 +1,21 @@ import { ImageDisplay } from '../../../dataset/enum/Control' import { ElementType } from '../../../dataset/enum/Element' -import { IContextMenuContext, IRegisterContextMenu } from '../../../interface/contextmenu/ContextMenu' +import { + IContextMenuContext, + IRegisterContextMenu +} from '../../../interface/contextmenu/ContextMenu' import { Command } from '../../command/Command' export const imageMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.image.change', icon: 'image-change', - when: (payload) => { - return !payload.isReadonly && !payload.editorHasSelection && payload.startElement?.type === ElementType.IMAGE + when: payload => { + return ( + !payload.isReadonly && + !payload.editorHasSelection && + payload.startElement?.type === ElementType.IMAGE + ) }, callback: (command: Command) => { // 创建代理元素 @@ -31,8 +38,11 @@ export const imageMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.image.saveAs', icon: 'image', - when: (payload) => { - return !payload.editorHasSelection && payload.startElement?.type === ElementType.IMAGE + when: payload => { + return ( + !payload.editorHasSelection && + payload.startElement?.type === ElementType.IMAGE + ) }, callback: (command: Command) => { command.executeSaveAsImageElement() @@ -40,25 +50,34 @@ export const imageMenus: IRegisterContextMenu[] = [ }, { i18nPath: 'contextmenu.image.textWrap', - when: (payload) => { - return !payload.isReadonly && !payload.editorHasSelection && payload.startElement?.type === ElementType.IMAGE + when: payload => { + return ( + !payload.isReadonly && + !payload.editorHasSelection && + payload.startElement?.type === ElementType.IMAGE + ) }, childMenus: [ { i18nPath: 'contextmenu.image.textWrapType.embed', when: () => true, callback: (command: Command, context: IContextMenuContext) => { - command.executeChangeImageDisplay(context.startElement!, ImageDisplay.BLOCK) + command.executeChangeImageDisplay( + context.startElement!, + ImageDisplay.BLOCK + ) } }, { i18nPath: 'contextmenu.image.textWrapType.upDown', when: () => true, callback: (command: Command, context: IContextMenuContext) => { - command.executeChangeImageDisplay(context.startElement!, ImageDisplay.INLINE) - + command.executeChangeImageDisplay( + context.startElement!, + ImageDisplay.INLINE + ) } } ] } -] \ No newline at end of file +] diff --git a/src/editor/core/contextmenu/menus/tableMenus.ts b/src/editor/core/contextmenu/menus/tableMenus.ts index 73a7934..ca51bc6 100644 --- a/src/editor/core/contextmenu/menus/tableMenus.ts +++ b/src/editor/core/contextmenu/menus/tableMenus.ts @@ -10,7 +10,7 @@ export const tableMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.table.border', icon: 'border-all', - when: (payload) => { + when: payload => { return !payload.isReadonly && payload.isInTable }, childMenus: [ @@ -43,7 +43,7 @@ export const tableMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.table.verticalAlign', icon: 'vertical-align', - when: (payload) => { + when: payload => { return !payload.isReadonly && payload.isInTable }, childMenus: [ @@ -76,7 +76,7 @@ export const tableMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.table.insertRowCol', icon: 'insert-row-col', - when: (payload) => { + when: payload => { return !payload.isReadonly && payload.isInTable }, childMenus: [ @@ -117,7 +117,7 @@ export const tableMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.table.deleteRowCol', icon: 'delete-row-col', - when: (payload) => { + when: payload => { return !payload.isReadonly && payload.isInTable }, childMenus: [ @@ -150,7 +150,7 @@ export const tableMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.table.mergeCell', icon: 'merge-cell', - when: (payload) => { + when: payload => { return !payload.isReadonly && payload.isCrossRowCol }, callback: (command: Command) => { @@ -160,11 +160,11 @@ export const tableMenus: IRegisterContextMenu[] = [ { i18nPath: 'contextmenu.table.mergeCancelCell', icon: 'merge-cancel-cell', - when: (payload) => { + when: payload => { return !payload.isReadonly && payload.isInTable }, callback: (command: Command) => { command.executeCancelMergeTableCell() } } -] \ No newline at end of file +] diff --git a/src/editor/core/cursor/Cursor.ts b/src/editor/core/cursor/Cursor.ts index 02fb342..d6d4931 100644 --- a/src/editor/core/cursor/Cursor.ts +++ b/src/editor/core/cursor/Cursor.ts @@ -8,15 +8,13 @@ import { CanvasEvent } from '../event/CanvasEvent' import { Position } from '../position/Position' import { CursorAgent } from './CursorAgent' -export type IDrawCursorOption = ICursorOption & -{ - isShow?: boolean; - isBlink?: boolean; - isFocus?: boolean; +export type IDrawCursorOption = ICursorOption & { + isShow?: boolean + isBlink?: boolean + isFocus?: boolean } export class Cursor { - private readonly ANIMATION_CLASS = `${EDITOR_PREFIX}-cursor--animation` private draw: Draw @@ -56,8 +54,8 @@ export class Cursor { return this.getAgentDom().value } - public clearAgentDomValue(): string { - return this.getAgentDom().value = '' + public clearAgentDomValue() { + this.getAgentDom().value = '' } private _blinkStart() { @@ -97,9 +95,16 @@ export class Cursor { // 设置光标代理 const height = this.draw.getHeight() const pageGap = this.draw.getPageGap() - const { metrics, coordinate: { leftTop, rightTop }, ascent, pageNo } = cursorPosition + const { + metrics, + coordinate: { leftTop, rightTop }, + ascent, + pageNo + } = cursorPosition const zoneManager = this.draw.getZone() - const curPageNo = zoneManager.isMainActive() ? pageNo : this.draw.getPageNo() + const curPageNo = zoneManager.isMainActive() + ? pageNo + : this.draw.getPageNo() const preY = curPageNo * (height + pageGap) // 增加1/4字体大小 const offsetHeight = metrics.height / 4 @@ -112,11 +117,15 @@ export class Cursor { }) } // fillText位置 + 文字基线到底部距离 - 模拟光标偏移量 - const descent = metrics.boundingBoxDescent < 0 ? 0 : metrics.boundingBoxDescent - const cursorTop = (leftTop[1] + ascent) + descent - (cursorHeight - offsetHeight) + preY + const descent = + metrics.boundingBoxDescent < 0 ? 0 : metrics.boundingBoxDescent + const cursorTop = + leftTop[1] + ascent + descent - (cursorHeight - offsetHeight) + preY const cursorLeft = rightTop[0] agentCursorDom.style.left = `${cursorLeft}px` - agentCursorDom.style.top = `${cursorTop + cursorHeight - CURSOR_AGENT_HEIGHT * scale}px` + agentCursorDom.style.top = `${ + cursorTop + cursorHeight - CURSOR_AGENT_HEIGHT * scale + }px` // 模拟光标显示 if (!isShow) return const isReadonly = this.draw.isReadonly() @@ -137,5 +146,4 @@ export class Cursor { this.cursorDom.style.display = 'none' this._clearBlinkTimeout() } - -} \ No newline at end of file +} diff --git a/src/editor/core/cursor/CursorAgent.ts b/src/editor/core/cursor/CursorAgent.ts index c199959..33a6cb8 100644 --- a/src/editor/core/cursor/CursorAgent.ts +++ b/src/editor/core/cursor/CursorAgent.ts @@ -10,7 +10,6 @@ import { Draw } from '../draw/Draw' import { CanvasEvent } from '../event/CanvasEvent' export class CursorAgent { - private draw: Draw private container: HTMLDivElement private agentCursorDom: HTMLTextAreaElement @@ -31,8 +30,14 @@ export class CursorAgent { agentCursorDom.onkeydown = (evt: KeyboardEvent) => this._keyDown(evt) agentCursorDom.oninput = debounce(this._input.bind(this), 0) agentCursorDom.onpaste = (evt: ClipboardEvent) => this._paste(evt) - agentCursorDom.addEventListener('compositionstart', this._compositionstart.bind(this)) - agentCursorDom.addEventListener('compositionend', this._compositionend.bind(this)) + agentCursorDom.addEventListener( + 'compositionstart', + this._compositionstart.bind(this) + ) + agentCursorDom.addEventListener( + 'compositionend', + this._compositionend.bind(this) + ) } public getAgentCursorDom(): HTMLTextAreaElement { @@ -84,13 +89,17 @@ export class CursorAgent { let start = 0 while (start < pasteElementList.length) { const pasteElement = pasteElementList[start] - if (anchorElement.titleId && /^\n/.test(pasteElement.value)) break + if (anchorElement.titleId && /^\n/.test(pasteElement.value)) { + break + } if (VIRTUAL_ELEMENT_TYPE.includes(pasteElement.type!)) { pasteElementList.splice(start, 1) if (pasteElement.valueList) { for (let v = 0; v < pasteElement.valueList.length; v++) { const element = pasteElement.valueList[v] - if (element.value === ZERO || element.value === '\n') continue + if (element.value === ZERO || element.value === '\n') { + continue + } pasteElementList.splice(start, 0, element) start++ } @@ -145,5 +154,4 @@ export class CursorAgent { private _compositionend(evt: CompositionEvent) { this.canvasEvent.compositionend(evt) } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 7524d3c..bdc1557 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -1,9 +1,25 @@ import { version } from '../../../../package.json' import { ZERO } from '../../dataset/constant/Common' import { RowFlex } from '../../dataset/enum/Row' -import { IAppendElementListOption, IDrawOption, IDrawPagePayload, IDrawRowPayload, IGetValueOption, IPainterOption } from '../../interface/Draw' -import { IEditorData, IEditorOption, IEditorResult } from '../../interface/Editor' -import { IElement, IElementMetrics, IElementFillRect, IElementStyle } from '../../interface/Element' +import { + IAppendElementListOption, + IDrawOption, + IDrawPagePayload, + IDrawRowPayload, + IGetValueOption, + IPainterOption +} from '../../interface/Draw' +import { + IEditorData, + IEditorOption, + IEditorResult +} from '../../interface/Editor' +import { + IElement, + IElementMetrics, + IElementFillRect, + IElementStyle +} from '../../interface/Element' import { IRow, IRowElement } from '../../interface/Row' import { deepClone, getUUID, nextTick } from '../../utils' import { Cursor } from '../cursor/Cursor' @@ -35,7 +51,14 @@ import { SubscriptParticle } from './particle/Subscript' import { SeparatorParticle } from './particle/Separator' import { PageBreakParticle } from './particle/PageBreak' import { Watermark } from './frame/Watermark' -import { EditorComponent, EditorMode, EditorZone, PageMode, PaperDirection, WordBreak } from '../../dataset/enum/Editor' +import { + EditorComponent, + EditorMode, + EditorZone, + PageMode, + PaperDirection, + WordBreak +} from '../../dataset/enum/Editor' import { Control } from './control/Control' import { zipElementList } from '../../utils/element' import { CheckboxParticle } from './particle/CheckboxParticle' @@ -58,7 +81,6 @@ import { Placeholder } from './frame/Placeholder' import { WORD_LIKE_REG } from '../../dataset/constant/Regular' export class Draw { - private container: HTMLDivElement private pageContainer: HTMLDivElement private pageList: HTMLCanvasElement[] @@ -276,7 +298,10 @@ export class Draw { } public getPageNumberBottom(): number { - const { pageNumber: { bottom }, scale } = this.options + const { + pageNumber: { bottom }, + scale + } = this.options return bottom * scale } @@ -444,7 +469,8 @@ export class Draw { public insertElementList(payload: IElement[]) { if (!payload.length) return - const isPartRangeInControlOutside = this.control.isPartRangeInControlOutside() + const isPartRangeInControlOutside = + this.control.isPartRangeInControlOutside() if (isPartRangeInControlOutside) return const { startIndex, endIndex } = this.range.getRange() if (!~startIndex && !~endIndex) return @@ -475,7 +501,10 @@ export class Draw { } } - public appendElementList(elementList: IElement[], options: IAppendElementListOption = {}) { + public appendElementList( + elementList: IElement[], + options: IAppendElementListOption = {} + ) { if (!elementList.length) return formatElementList(elementList, { isHandleFirstElement: false, @@ -496,17 +525,30 @@ export class Draw { }) } - public spliceElementList(elementList: IElement[], start: number, deleteCount: number, ...items: IElement[]) { + public spliceElementList( + elementList: IElement[], + start: number, + deleteCount: number, + ...items: IElement[] + ) { if (deleteCount > 0) { // 当最后元素与开始元素列表信息不一致时:清除当前列表信息 const endIndex = start + deleteCount const endElement = elementList[endIndex] const endElementListId = endElement?.listId - if (endElementListId && elementList[start - 1]?.listId !== endElementListId) { + if ( + endElementListId && + elementList[start - 1]?.listId !== endElementListId + ) { let startIndex = endIndex while (startIndex < elementList.length) { const curElement = elementList[startIndex] - if (curElement.listId !== endElementListId || curElement.value === ZERO) break + if ( + curElement.listId !== endElementListId || + curElement.value === ZERO + ) { + break + } delete curElement.listId delete curElement.listType delete curElement.listStyle @@ -597,18 +639,23 @@ export class Draw { } public getPainterStyle(): IElementStyle | null { - return this.painterStyle && Object.keys(this.painterStyle).length ? this.painterStyle : null + return this.painterStyle && Object.keys(this.painterStyle).length + ? this.painterStyle + : null } public getPainterOptions(): IPainterOption | null { return this.painterOptions } - public setPainterStyle(payload: IElementStyle | null, options?: IPainterOption) { + public setPainterStyle( + payload: IElementStyle | null, + options?: IPainterOption + ) { this.painterStyle = payload this.painterOptions = options || null if (this.getPainterStyle()) { - this.pageList.forEach(c => c.style.cursor = 'copy') + this.pageList.forEach(c => (c.style.cursor = 'copy')) } } @@ -747,8 +794,14 @@ export class Draw { // 数据 const { pageNo } = options let mainElementList = this.elementList - if (Number.isInteger(pageNo) && pageNo! >= 0 && pageNo! < this.pageRowList.length) { - mainElementList = this.pageRowList[pageNo!].flatMap(row => row.elementList) + if ( + Number.isInteger(pageNo) && + pageNo! >= 0 && + pageNo! < this.pageRowList.length + ) { + mainElementList = this.pageRowList[pageNo!].flatMap( + row => row.elementList + ) } const data: IEditorData = { header: zipElementList(this.headerElementList), @@ -850,11 +903,14 @@ export class Draw { const { defaultSize, defaultFont } = this.options const font = el.font || defaultFont const size = el.actualSize || el.size || defaultSize - return `${el.italic ? 'italic ' : ''}${el.bold ? 'bold ' : ''}${size * scale}px ${font}` + return `${el.italic ? 'italic ' : ''}${el.bold ? 'bold ' : ''}${ + size * scale + }px ${font}` } public computeRowList(innerWidth: number, elementList: IElement[]) { - const { defaultSize, defaultRowMargin, scale, tdPadding, defaultTabWidth } = this.options + const { defaultSize, defaultRowMargin, scale, tdPadding, defaultTabWidth } = + this.options const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight() const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') as CanvasRenderingContext2D @@ -877,7 +933,8 @@ export class Draw { for (let i = 0; i < elementList.length; i++) { const curRow: IRow = rowList[rowList.length - 1] const element = elementList[i] - const rowMargin = defaultBasicRowMarginHeight * (element.rowMargin || defaultRowMargin) + const rowMargin = + defaultBasicRowMarginHeight * (element.rowMargin || defaultRowMargin) const metrics: IElementMetrics = { width: 0, height: 0, @@ -887,17 +944,24 @@ export class Draw { // 实际可用宽度 const offsetX = element.listId ? listStyleMap.get(element.listId) || 0 : 0 const availableWidth = innerWidth - offsetX - if (element.type === ElementType.IMAGE || element.type === ElementType.LATEX) { + if ( + element.type === ElementType.IMAGE || + element.type === ElementType.LATEX + ) { const elementWidth = element.width! * scale const elementHeight = element.height! * scale // 图片超出尺寸后自适应 - const curRowWidth = element.imgDisplay === ImageDisplay.INLINE ? 0 : curRow.width + const curRowWidth = + element.imgDisplay === ImageDisplay.INLINE ? 0 : curRow.width if (curRowWidth + elementWidth > availableWidth) { // 计算剩余大小 const surplusWidth = availableWidth - curRowWidth - const adaptiveWidth = surplusWidth > 0 ? surplusWidth : Math.min(elementWidth, availableWidth) + const adaptiveWidth = + surplusWidth > 0 + ? surplusWidth + : Math.min(elementWidth, availableWidth) element.width = adaptiveWidth - element.height = elementHeight * adaptiveWidth / elementWidth + element.height = (elementHeight * adaptiveWidth) / elementWidth metrics.width = element.width metrics.height = element.height metrics.boundingBoxDescent = element.height @@ -917,7 +981,10 @@ export class Draw { const tr = trList[t] for (let d = 0; d < tr.tdList.length; d++) { const td = tr.tdList[d] - const rowList = this.computeRowList((td.width! - tdGap) * scale, td.value) + const rowList = this.computeRowList( + (td.width! - tdGap) * scale, + td.value + ) const rowHeight = rowList.reduce((pre, cur) => pre + cur.height, 0) td.rowList = rowList // 移除缩放导致的行高变化-渲染时会进行缩放调整 @@ -957,9 +1024,10 @@ export class Draw { const curTdHeight = td.mainHeight! const curTdMinHeight = td.realMinHeight! // 获取最大可减少高度 - const curReduceHeight = curTdHeight < curTdMinHeight - ? curTdRealHeight - curTdMinHeight - : curTdRealHeight - curTdHeight + const curReduceHeight = + curTdHeight < curTdMinHeight + ? curTdRealHeight - curTdMinHeight + : curTdRealHeight - curTdHeight if (!~reduceHeight || curReduceHeight < reduceHeight) { reduceHeight = curReduceHeight } @@ -976,7 +1044,10 @@ export class Draw { this.tableParticle.computeRowColInfo(element) // 计算出表格高度 const tableHeight = trList.reduce((pre, cur) => pre + cur.height, 0) - const tableWidth = element.colgroup!.reduce((pre, cur) => pre + cur.width, 0) + const tableWidth = element.colgroup!.reduce( + (pre, cur) => pre + cur.width, + 0 + ) element.width = tableWidth element.height = tableHeight const elementWidth = tableWidth * scale @@ -991,7 +1062,10 @@ export class Draw { let curPagePreHeight = marginHeight for (let r = 0; r < rowList.length; r++) { const row = rowList[r] - if (row.height + curPagePreHeight > height || rowList[r - 1]?.isPageBreak) { + if ( + row.height + curPagePreHeight > height || + rowList[r - 1]?.isPageBreak + ) { curPagePreHeight = marginHeight + row.height } else { curPagePreHeight += row.height @@ -1009,7 +1083,10 @@ export class Draw { for (let r = 0; r < trList.length; r++) { const tr = trList[r] const trHeight = tr.height * scale - if (curPagePreHeight + rowMarginHeight + preTrHeight + trHeight > height) { + if ( + curPagePreHeight + rowMarginHeight + preTrHeight + trHeight > + height + ) { // 是否跨列 if (element.colgroup?.length !== tr.tdList.length) { deleteCount = 0 @@ -1024,7 +1101,10 @@ export class Draw { } if (deleteCount) { const cloneTrList = trList.splice(deleteStart, deleteCount) - const cloneTrHeight = cloneTrList.reduce((pre, cur) => pre + cur.height, 0) + const cloneTrHeight = cloneTrList.reduce( + (pre, cur) => pre + cur.height, + 0 + ) element.height -= cloneTrHeight metrics.height -= cloneTrHeight metrics.boundingBoxDescent -= cloneTrHeight @@ -1035,7 +1115,10 @@ export class Draw { this.spliceElementList(elementList, i + 1, 0, cloneElement) // 换页的是当前行则改变上下文 const positionContext = this.position.getPositionContext() - if (positionContext.isTable && positionContext.trIndex === deleteStart) { + if ( + positionContext.isTable && + positionContext.trIndex === deleteStart + ) { positionContext.index! += 1 positionContext.trIndex = 0 this.position.setPositionContext(positionContext) @@ -1079,7 +1162,10 @@ export class Draw { } else { // 设置上下标真实字体尺寸 const size = element.size || defaultSize - if (element.type === ElementType.SUPERSCRIPT || element.type === ElementType.SUBSCRIPT) { + if ( + element.type === ElementType.SUPERSCRIPT || + element.type === ElementType.SUBSCRIPT + ) { element.actualSize = Math.ceil(size * 0.6) } metrics.height = (element.actualSize || size) * scale @@ -1089,19 +1175,29 @@ export class Draw { if (element.letterSpacing) { metrics.width += element.letterSpacing * scale } - metrics.boundingBoxAscent = (element.value === ZERO ? defaultSize : fontMetrics.actualBoundingBoxAscent) * scale - metrics.boundingBoxDescent = fontMetrics.actualBoundingBoxDescent * scale + metrics.boundingBoxAscent = + (element.value === ZERO + ? defaultSize + : fontMetrics.actualBoundingBoxAscent) * scale + metrics.boundingBoxDescent = + fontMetrics.actualBoundingBoxDescent * scale if (element.type === ElementType.SUPERSCRIPT) { metrics.boundingBoxAscent += metrics.height / 2 } else if (element.type === ElementType.SUBSCRIPT) { metrics.boundingBoxDescent += metrics.height / 2 } } - const ascent = (element.imgDisplay !== ImageDisplay.INLINE && element.type === ElementType.IMAGE) || + const ascent = + (element.imgDisplay !== ImageDisplay.INLINE && + element.type === ElementType.IMAGE) || element.type === ElementType.LATEX - ? metrics.height + rowMargin - : metrics.boundingBoxAscent + rowMargin - const height = rowMargin + metrics.boundingBoxAscent + metrics.boundingBoxDescent + rowMargin + ? metrics.height + rowMargin + : metrics.boundingBoxAscent + rowMargin + const height = + rowMargin + + metrics.boundingBoxAscent + + metrics.boundingBoxDescent + + rowMargin const rowElement: IRowElement = Object.assign(element, { metrics, style: this._getFont(element, scale) @@ -1119,12 +1215,19 @@ export class Draw { // 英文单词 const word = `${preElement?.value || ''}${element.value}` if (WORD_LIKE_REG.test(word)) { - const { width, endElement } = this.textParticle.measureWord(ctx, elementList, i) + const { width, endElement } = this.textParticle.measureWord( + ctx, + elementList, + i + ) curRowWidth += width nextElement = endElement } // 标点符号 - curRowWidth += this.textParticle.measurePunctuationWidth(ctx, nextElement) + curRowWidth += this.textParticle.measurePunctuationWidth( + ctx, + nextElement + ) } } // 列表信息 @@ -1137,15 +1240,15 @@ export class Draw { } listId = element.listId if ( - element.type === ElementType.TABLE - || preElement?.type === ElementType.TABLE - || preElement?.type === ElementType.BLOCK - || element.type === ElementType.BLOCK - || preElement?.imgDisplay === ImageDisplay.INLINE - || element.imgDisplay === ImageDisplay.INLINE - || curRowWidth > availableWidth - || (i !== 0 && element.value === ZERO) - || (preElement?.listId !== element.listId) + element.type === ElementType.TABLE || + preElement?.type === ElementType.TABLE || + preElement?.type === ElementType.BLOCK || + element.type === ElementType.BLOCK || + preElement?.imgDisplay === ImageDisplay.INLINE || + element.imgDisplay === ImageDisplay.INLINE || + curRowWidth > availableWidth || + (i !== 0 && element.value === ZERO) || + preElement?.listId !== element.listId ) { // 减小行元素前第一行空行行高 if ( @@ -1156,8 +1259,12 @@ export class Draw { curRow.height = defaultBasicRowMarginHeight } // 两端对齐 - if (preElement?.rowFlex === RowFlex.ALIGNMENT && curRowWidth > availableWidth) { - const gap = (availableWidth - curRow.width) / curRow.elementList.length + if ( + preElement?.rowFlex === RowFlex.ALIGNMENT && + curRowWidth > availableWidth + ) { + const gap = + (availableWidth - curRow.width) / curRow.elementList.length for (let e = 0; e < curRow.elementList.length; e++) { const el = curRow.elementList[e] el.metrics.width += gap @@ -1217,7 +1324,10 @@ export class Draw { } else { for (let i = 0; i < this.rowList.length; i++) { const row = this.rowList[i] - if (row.height + pageHeight > height || this.rowList[i - 1]?.isPageBreak) { + if ( + row.height + pageHeight > height || + this.rowList[i - 1]?.isPageBreak + ) { pageHeight = marginHeight + row.height pageRowList.push([row]) pageNo++ @@ -1238,7 +1348,8 @@ export class Draw { } public drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) { - const { rowList, pageNo, elementList, positionList, startIndex, zone } = payload + const { rowList, pageNo, elementList, positionList, startIndex, zone } = + payload const { scale, tdPadding } = this.options const { isCrossRowCol, tableId } = this.range.getRange() let index = startIndex @@ -1266,10 +1377,21 @@ export class Draw { // 元素高亮记录 if (element.highlight) { // 高亮元素相连需立即绘制,并记录下一元素坐标 - if (preElement && preElement.highlight && preElement.highlight !== element.highlight) { + if ( + preElement && + preElement.highlight && + preElement.highlight !== element.highlight + ) { this.highlight.render(ctx) } - this.highlight.recordFillInfo(ctx, x, y, metrics.width, curRow.height, element.highlight) + this.highlight.recordFillInfo( + ctx, + x, + y, + metrics.width, + curRow.height, + element.highlight + ) } else if (preElement?.highlight) { this.highlight.render(ctx) } @@ -1325,19 +1447,40 @@ export class Draw { } // 下划线记录 if (element.underline) { - this.underline.recordFillInfo(ctx, x, y + curRow.height, metrics.width, 0, element.color) + this.underline.recordFillInfo( + ctx, + x, + y + curRow.height, + metrics.width, + 0, + element.color + ) } else if (preElement?.underline) { this.underline.render(ctx) } // 删除线记录 if (element.strikeout) { - this.strikeout.recordFillInfo(ctx, x, y + curRow.height / 2, metrics.width) + this.strikeout.recordFillInfo( + ctx, + x, + y + curRow.height / 2, + metrics.width + ) } else if (preElement?.strikeout) { this.strikeout.render(ctx) } // 选区记录 - const { zone: currentZone, startIndex, endIndex } = this.range.getRange() - if (currentZone === zone && startIndex !== endIndex && startIndex <= index && index <= endIndex) { + const { + zone: currentZone, + startIndex, + endIndex + } = this.range.getRange() + if ( + currentZone === zone && + startIndex !== endIndex && + startIndex <= index && + index <= endIndex + ) { // 从行尾开始-绘制最小宽度 if (startIndex === index) { const nextElement = elementList[startIndex + 1] @@ -1351,8 +1494,8 @@ export class Draw { const positionContext = this.position.getPositionContext() // 表格需限定上下文 if ( - (!positionContext.isTable && !element.tdId) - || positionContext.tdId === element.tdId + (!positionContext.isTable && !element.tdId) || + positionContext.tdId === element.tdId ) { let rangeWidth = metrics.width // 最小选区宽度 @@ -1392,7 +1535,11 @@ export class Draw { } // 绘制列表样式 if (curRow.isList) { - this.listParticle.drawListStyle(ctx, curRow, positionList[curRow.startIndex]) + this.listParticle.drawListStyle( + ctx, + curRow, + positionList[curRow.startIndex] + ) } // 绘制富文本及文字 this._drawRichText(ctx) @@ -1401,8 +1548,16 @@ export class Draw { const { x, y, width, height } = rangeRecord this.range.render(ctx, x, y, width, height) } - if (isCrossRowCol && tableRangeElement && tableRangeElement.id === tableId) { - const { coordinate: { leftTop: [x, y] } } = positionList[curRow.startIndex] + if ( + isCrossRowCol && + tableRangeElement && + tableRangeElement.id === tableId + ) { + const { + coordinate: { + leftTop: [x, y] + } + } = positionList[curRow.startIndex] this.tableParticle.drawRange(ctx, tableRangeElement, x, y) } } @@ -1474,7 +1629,7 @@ export class Draw { const positionList = this.position.getOriginalMainPositionList() const elementList = this.getOriginalMainElementList() this._disconnectLazyRender() - this.lazyRenderIntersectionObserver = new IntersectionObserver((entries) => { + this.lazyRenderIntersectionObserver = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { const index = Number((entry.target).dataset.index) @@ -1555,7 +1710,8 @@ export class Draw { if (prePageCount > curPageCount) { const deleteCount = prePageCount - curPageCount this.ctxList.splice(curPageCount, deleteCount) - this.pageList.splice(curPageCount, deleteCount) + this.pageList + .splice(curPageCount, deleteCount) .forEach(page => page.remove()) } // 绘制元素 @@ -1572,14 +1728,17 @@ export class Draw { if (positionContext.isTable) { const { index, trIndex, tdIndex } = positionContext const elementList = this.getOriginalElementList() - const tablePositionList = elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList + const tablePositionList = + elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList if (curIndex === undefined && tablePositionList) { curIndex = tablePositionList.length - 1 } const tablePosition = tablePositionList?.[curIndex!] this.position.setCursorPosition(tablePosition || null) } else { - this.position.setCursorPosition(curIndex !== undefined ? positionList[curIndex] : null) + this.position.setCursorPosition( + curIndex !== undefined ? positionList[curIndex] : null + ) } this.cursor.drawCursor() } @@ -1631,5 +1790,4 @@ export class Draw { this.scrollObserver.removeEvent() this.selectionObserver.removeEvent() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/control/Control.ts b/src/editor/core/draw/control/Control.ts index f5ab642..788eb39 100644 --- a/src/editor/core/draw/control/Control.ts +++ b/src/editor/core/draw/control/Control.ts @@ -1,10 +1,19 @@ import { ControlComponent, ControlType } from '../../../dataset/enum/Control' import { ElementType } from '../../../dataset/enum/Element' -import { IControl, IControlInitOption, IControlInstance, IControlOption } from '../../../interface/Control' +import { + IControl, + IControlInitOption, + IControlInstance, + IControlOption +} from '../../../interface/Control' import { IElement, IElementPosition } from '../../../interface/Element' import { IRange } from '../../../interface/Range' import { deepClone, splitText } from '../../../utils' -import { formatElementContext, pickElementAttr, zipElementList } from '../../../utils/element' +import { + formatElementContext, + pickElementAttr, + zipElementList +} from '../../../utils/element' import { Listener } from '../../listener/Listener' import { RangeManager } from '../../range/RangeManager' import { Draw } from '../Draw' @@ -13,11 +22,10 @@ import { SelectControl } from './select/SelectControl' import { TextControl } from './text/TextControl' interface IMoveCursorResult { - newIndex: number; - newElement: IElement; + newIndex: number + newElement: IElement } export class Control { - private draw: Draw private range: RangeManager private listener: Listener @@ -44,8 +52,9 @@ export class Control { const startElement = elementList[startIndex] const endElement = elementList[endIndex] if ( - (startElement.type === ElementType.CONTROL || endElement.type === ElementType.CONTROL) - && startElement.controlId !== endElement.controlId + (startElement.type === ElementType.CONTROL || + endElement.type === ElementType.CONTROL) && + startElement.controlId !== endElement.controlId ) { return true } @@ -195,8 +204,8 @@ export class Control { while (startIndex < elementList.length) { const nextElement = elementList[startIndex] if ( - nextElement.controlId !== element.controlId - || nextElement.controlComponent !== ControlComponent.PREFIX + nextElement.controlId !== element.controlId || + nextElement.controlComponent !== ControlComponent.PREFIX ) { return { newIndex: startIndex - 1, @@ -211,8 +220,8 @@ export class Control { while (startIndex > 0) { const preElement = elementList[startIndex] if ( - preElement.controlId !== element.controlId - || preElement.controlComponent === ControlComponent.PREFIX + preElement.controlId !== element.controlId || + preElement.controlComponent === ControlComponent.PREFIX ) { return { newIndex: startIndex, @@ -260,7 +269,11 @@ export class Control { if (!~leftIndex && !~rightIndex) return startIndex leftIndex = ~leftIndex ? leftIndex : 0 // 删除元素 - this.draw.spliceElementList(elementList, leftIndex + 1, rightIndex - leftIndex) + this.draw.spliceElementList( + elementList, + leftIndex + 1, + rightIndex - leftIndex + ) return leftIndex } @@ -302,7 +315,12 @@ export class Control { color: this.options.placeholderColor } formatElementContext(elementList, [newElement], startIndex) - this.draw.spliceElementList(elementList, startIndex + p + 1, 0, newElement) + this.draw.spliceElementList( + elementList, + startIndex + p + 1, + 0, + newElement + ) } } @@ -326,5 +344,4 @@ export class Control { } return this.activeControl.cut() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/control/checkbox/CheckboxControl.ts b/src/editor/core/draw/control/checkbox/CheckboxControl.ts index 73e7b09..5d182e6 100644 --- a/src/editor/core/draw/control/checkbox/CheckboxControl.ts +++ b/src/editor/core/draw/control/checkbox/CheckboxControl.ts @@ -5,7 +5,6 @@ import { IElement } from '../../../../interface/Element' import { Control } from '../Control' export class CheckboxControl implements IControlInstance { - private element: IElement private control: Control @@ -124,5 +123,4 @@ export class CheckboxControl implements IControlInstance { public cut(): number { return -1 } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/control/select/SelectControl.ts b/src/editor/core/draw/control/select/SelectControl.ts index a5e134b..2f2967a 100644 --- a/src/editor/core/draw/control/select/SelectControl.ts +++ b/src/editor/core/draw/control/select/SelectControl.ts @@ -1,4 +1,7 @@ -import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../../../dataset/constant/Editor' +import { + EDITOR_COMPONENT, + EDITOR_PREFIX +} from '../../../../dataset/constant/Editor' import { ControlComponent } from '../../../../dataset/enum/Control' import { EditorComponent } from '../../../../dataset/enum/Editor' import { KeyMap } from '../../../../dataset/enum/KeyMap' @@ -9,7 +12,6 @@ import { formatElementContext } from '../../../../utils/element' import { Control } from '../Control' export class SelectControl implements IControlInstance { - private element: IElement private control: Control private isPopup: boolean @@ -105,8 +107,9 @@ export class SelectControl implements IControlInstance { return this.clearSelect() } else { const endNextElement = elementList[endIndex + 1] - if ((startElement.controlComponent === ControlComponent.PREFIX && - endNextElement.controlComponent === ControlComponent.PLACEHOLDER) || + if ( + (startElement.controlComponent === ControlComponent.PREFIX && + endNextElement.controlComponent === ControlComponent.PLACEHOLDER) || endNextElement.controlComponent === ControlComponent.POSTFIX || startElement.controlComponent === ControlComponent.PLACEHOLDER ) { @@ -232,7 +235,12 @@ export class SelectControl implements IControlInstance { } selectPopupContainer.append(ul) // 定位 - const { coordinate: { leftTop: [left, top] }, lineHeight } = position + const { + coordinate: { + leftTop: [left, top] + }, + lineHeight + } = position const preY = this.control.getPreY() selectPopupContainer.style.left = `${left}px` selectPopupContainer.style.top = `${top + preY + lineHeight}px` @@ -246,7 +254,9 @@ export class SelectControl implements IControlInstance { if (this.isPopup) return const { startIndex } = this.control.getRange() const elementList = this.control.getElementList() - if (elementList[startIndex + 1]?.controlId !== this.element.controlId) return + if (elementList[startIndex + 1]?.controlId !== this.element.controlId) { + return + } this._createSelectPopupDom() this.isPopup = true } @@ -256,5 +266,4 @@ export class SelectControl implements IControlInstance { this.selectDom?.remove() this.isPopup = false } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/control/text/TextControl.ts b/src/editor/core/draw/control/text/TextControl.ts index 649536b..4dfe330 100644 --- a/src/editor/core/draw/control/text/TextControl.ts +++ b/src/editor/core/draw/control/text/TextControl.ts @@ -6,7 +6,6 @@ import { formatElementContext } from '../../../../utils/element' import { Control } from '../Control' export class TextControl implements IControlInstance { - private element: IElement private control: Control @@ -99,7 +98,11 @@ export class TextControl implements IControlInstance { if (evt.key === KeyMap.Backspace) { // 移除选区元素 if (startIndex !== endIndex) { - draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex) + draw.spliceElementList( + elementList, + startIndex + 1, + endIndex - startIndex + ) const value = this.getValue() if (!value.length) { this.control.addPlaceholder(startIndex) @@ -126,7 +129,11 @@ export class TextControl implements IControlInstance { } else if (evt.key === KeyMap.Delete) { // 移除选区元素 if (startIndex !== endIndex) { - draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex) + draw.spliceElementList( + elementList, + startIndex + 1, + endIndex - startIndex + ) const value = this.getValue() if (!value.length) { this.control.addPlaceholder(startIndex) @@ -134,8 +141,9 @@ export class TextControl implements IControlInstance { return startIndex } else { const endNextElement = elementList[endIndex + 1] - if ((startElement.controlComponent === ControlComponent.PREFIX && - endNextElement.controlComponent === ControlComponent.PLACEHOLDER) || + if ( + (startElement.controlComponent === ControlComponent.PREFIX && + endNextElement.controlComponent === ControlComponent.PLACEHOLDER) || endNextElement.controlComponent === ControlComponent.POSTFIX || startElement.controlComponent === ControlComponent.PLACEHOLDER ) { @@ -170,5 +178,4 @@ export class TextControl implements IControlInstance { } return startIndex } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/frame/Background.ts b/src/editor/core/draw/frame/Background.ts index d5873af..b05f8e4 100644 --- a/src/editor/core/draw/frame/Background.ts +++ b/src/editor/core/draw/frame/Background.ts @@ -1,7 +1,6 @@ import { Draw } from '../Draw' export class Background { - private draw: Draw constructor(draw: Draw) { @@ -16,5 +15,4 @@ export class Background { ctx.fillRect(0, 0, width, height) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/frame/Footer.ts b/src/editor/core/draw/frame/Footer.ts index c433253..50b046b 100644 --- a/src/editor/core/draw/frame/Footer.ts +++ b/src/editor/core/draw/frame/Footer.ts @@ -8,7 +8,6 @@ import { Position } from '../../position/Position' import { Draw } from '../Draw' export class Footer { - private draw: Draw private position: Position private options: DeepRequired @@ -81,13 +80,18 @@ export class Footer { } public getFooterBottom(): number { - const { footer: { bottom, disabled }, scale } = this.options + const { + footer: { bottom, disabled }, + scale + } = this.options if (disabled) return 0 return Math.floor(bottom * scale) } public getMaxHeight(): number { - const { footer: { maxHeightRadio } } = this.options + const { + footer: { maxHeightRadio } + } = this.options const height = this.draw.getHeight() return Math.floor(height * maxHeightRadioMapping[maxHeightRadio]) } @@ -136,5 +140,4 @@ export class Footer { zone: EditorZone.FOOTER }) } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/frame/Header.ts b/src/editor/core/draw/frame/Header.ts index 6f21127..2b63122 100644 --- a/src/editor/core/draw/frame/Header.ts +++ b/src/editor/core/draw/frame/Header.ts @@ -8,7 +8,6 @@ import { Position } from '../../position/Position' import { Draw } from '../Draw' export class Header { - private draw: Draw private position: Position private options: DeepRequired @@ -78,13 +77,18 @@ export class Header { } public getHeaderTop(): number { - const { header: { top, disabled }, scale } = this.options + const { + header: { top, disabled }, + scale + } = this.options if (disabled) return 0 return Math.floor(top * scale) } public getMaxHeight(): number { - const { header: { maxHeightRadio } } = this.options + const { + header: { maxHeightRadio } + } = this.options const height = this.draw.getHeight() return Math.floor(height * maxHeightRadioMapping[maxHeightRadio]) } @@ -133,5 +137,4 @@ export class Header { zone: EditorZone.HEADER }) } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/frame/Margin.ts b/src/editor/core/draw/frame/Margin.ts index 0e21fb3..74bf333 100644 --- a/src/editor/core/draw/frame/Margin.ts +++ b/src/editor/core/draw/frame/Margin.ts @@ -3,7 +3,6 @@ import { IEditorOption } from '../../../interface/Editor' import { Draw } from '../Draw' export class Margin { - private draw: Draw private options: Required @@ -15,9 +14,10 @@ export class Margin { public render(ctx: CanvasRenderingContext2D, pageNo: number) { const { marginIndicatorColor, pageMode } = this.options const width = this.draw.getWidth() - const height = pageMode === PageMode.CONTINUITY - ? this.draw.getCanvasHeight(pageNo) - : this.draw.getHeight() + const height = + pageMode === PageMode.CONTINUITY + ? this.draw.getCanvasHeight(pageNo) + : this.draw.getHeight() const margins = this.draw.getMargins() const marginIndicatorSize = this.draw.getMarginIndicatorSize() ctx.save() @@ -27,7 +27,10 @@ export class Margin { const leftTopPoint: [number, number] = [margins[3], margins[0]] const rightTopPoint: [number, number] = [width - margins[1], margins[0]] const leftBottomPoint: [number, number] = [margins[3], height - margins[2]] - const rightBottomPoint: [number, number] = [width - margins[1], height - margins[2]] + const rightBottomPoint: [number, number] = [ + width - margins[1], + height - margins[2] + ] // 上左 ctx.moveTo(leftTopPoint[0] - marginIndicatorSize, leftTopPoint[1]) ctx.lineTo(...leftTopPoint) @@ -47,5 +50,4 @@ export class Margin { ctx.stroke() ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/frame/PageNumber.ts b/src/editor/core/draw/frame/PageNumber.ts index f57a4bf..fa86c4b 100644 --- a/src/editor/core/draw/frame/PageNumber.ts +++ b/src/editor/core/draw/frame/PageNumber.ts @@ -8,7 +8,6 @@ import { convertNumberToChinese } from '../../../utils' import { Draw } from '../Draw' export class PageNumber { - private draw: Draw private options: DeepRequired @@ -21,7 +20,16 @@ export class PageNumber { const { scale, pageMode, - pageNumber: { size, font, color, rowFlex, numberType, format, startPageNo, fromPageNo } + pageNumber: { + size, + font, + color, + rowFlex, + numberType, + format, + startPageNo, + fromPageNo + } } = this.options if (pageNo < fromPageNo) return // 处理页码格式 @@ -29,20 +37,27 @@ export class PageNumber { const pageNoReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_NO) if (pageNoReg.test(text)) { const realPageNo = pageNo + startPageNo - fromPageNo - const pageNoText = numberType === NumberType.CHINESE ? convertNumberToChinese(realPageNo) : `${realPageNo}` + const pageNoText = + numberType === NumberType.CHINESE + ? convertNumberToChinese(realPageNo) + : `${realPageNo}` text = text.replace(pageNoReg, pageNoText) } const pageCountReg = new RegExp(FORMAT_PLACEHOLDER.PAGE_COUNT) if (pageCountReg.test(text)) { const pageCount = this.draw.getPageCount() - fromPageNo - const pageCountText = numberType === NumberType.CHINESE ? convertNumberToChinese(pageCount) : `${pageCount}` + const pageCountText = + numberType === NumberType.CHINESE + ? convertNumberToChinese(pageCount) + : `${pageCount}` text = text.replace(pageCountReg, pageCountText) } const width = this.draw.getWidth() // 计算y位置 - const height = pageMode === PageMode.CONTINUITY - ? this.draw.getCanvasHeight(pageNo) - : this.draw.getHeight() + const height = + pageMode === PageMode.CONTINUITY + ? this.draw.getCanvasHeight(pageNo) + : this.draw.getHeight() const pageNumberBottom = this.draw.getPageNumberBottom() const y = height - pageNumberBottom ctx.save() @@ -62,5 +77,4 @@ export class PageNumber { ctx.fillText(text, x, y) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/frame/Placeholder.ts b/src/editor/core/draw/frame/Placeholder.ts index 9e260a1..00ee320 100644 --- a/src/editor/core/draw/frame/Placeholder.ts +++ b/src/editor/core/draw/frame/Placeholder.ts @@ -7,7 +7,6 @@ import { Position } from '../../position/Position' import { Draw } from '../Draw' export class Placeholder { - private draw: Draw private position: Position private options: DeepRequired @@ -61,16 +60,20 @@ export class Placeholder { } public render(ctx: CanvasRenderingContext2D) { - const { placeholder: { data, font, size, color, opacity } } = this.options + const { + placeholder: { data, font, size, color, opacity } + } = this.options if (!data) return this._recovery() // 构建元素列表并格式化 - this.elementList = [{ - value: data, - font, - size, - color - }] + this.elementList = [ + { + value: data, + font, + size, + color + } + ] formatElementList(this.elementList, { editorOptions: this.options }) @@ -90,5 +93,4 @@ export class Placeholder { }) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/frame/Watermark.ts b/src/editor/core/draw/frame/Watermark.ts index 8e833d5..53abcb8 100644 --- a/src/editor/core/draw/frame/Watermark.ts +++ b/src/editor/core/draw/frame/Watermark.ts @@ -3,7 +3,6 @@ import { DeepRequired } from '../../../interface/Common' import { Draw } from '../Draw' export class Watermark { - private draw: Draw private options: DeepRequired @@ -13,7 +12,10 @@ export class Watermark { } public render(ctx: CanvasRenderingContext2D) { - const { watermark: { data, opacity, font, size, color }, scale } = this.options + const { + watermark: { data, opacity, font, size, color }, + scale + } = this.options const width = this.draw.getWidth() const height = this.draw.getHeight() const x = width / 2 @@ -25,9 +27,12 @@ export class Watermark { // 移动到中心位置再旋转 const measureText = ctx.measureText(data) ctx.translate(x, y) - ctx.rotate(-45 * Math.PI / 180) - ctx.fillText(data, - measureText.width / 2, measureText.actualBoundingBoxAscent - size / 2) + ctx.rotate((-45 * Math.PI) / 180) + ctx.fillText( + data, + -measureText.width / 2, + measureText.actualBoundingBoxAscent - size / 2 + ) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/interactive/Search.ts b/src/editor/core/draw/interactive/Search.ts index 349c388..1c15c52 100644 --- a/src/editor/core/draw/interactive/Search.ts +++ b/src/editor/core/draw/interactive/Search.ts @@ -11,12 +11,11 @@ import { Position } from '../../position/Position' import { Draw } from '../Draw' export interface INavigateInfo { - index: number; - count: number; + index: number + count: number } export class Search { - private draw: Draw private options: Required private position: Position @@ -49,7 +48,8 @@ export class Search { } else { let index = this.searchNavigateIndex - 1 let isExistPre = false - const searchNavigateId = this.searchMatchList[this.searchNavigateIndex].groupId + const searchNavigateId = + this.searchMatchList[this.searchNavigateIndex].groupId while (index >= 0) { const match = this.searchMatchList[index] if (searchNavigateId !== match.groupId) { @@ -60,9 +60,11 @@ export class Search { index-- } if (!isExistPre) { - const lastSearchMatch = this.searchMatchList[this.searchMatchList.length - 1] + const lastSearchMatch = + this.searchMatchList[this.searchMatchList.length - 1] if (lastSearchMatch.groupId === searchNavigateId) return null - this.searchNavigateIndex = this.searchMatchList.length - 1 - (this.searchKeyword.length - 1) + this.searchNavigateIndex = + this.searchMatchList.length - 1 - (this.searchKeyword.length - 1) } } return this.searchNavigateIndex @@ -75,7 +77,8 @@ export class Search { } else { let index = this.searchNavigateIndex + 1 let isExistNext = false - const searchNavigateId = this.searchMatchList[this.searchNavigateIndex].groupId + const searchNavigateId = + this.searchMatchList[this.searchNavigateIndex].groupId while (index < this.searchMatchList.length) { const match = this.searchMatchList[index] if (searchNavigateId !== match.groupId) { @@ -95,7 +98,10 @@ export class Search { } public searchNavigateScrollIntoView(position: IElementPosition) { - const { coordinate: { leftTop, leftBottom, rightTop }, pageNo } = position + const { + coordinate: { leftTop, leftBottom, rightTop }, + pageNo + } = position const height = this.draw.getHeight() const pageGap = this.draw.getPageGap() const preY = pageNo * (height + pageGap) @@ -105,7 +111,9 @@ export class Search { // 扩大搜索词尺寸,使可视范围更广 const ANCHOR_OVERFLOW_SIZE = 50 anchor.style.width = `${rightTop[0] - leftTop[0] + ANCHOR_OVERFLOW_SIZE}px` - anchor.style.height = `${leftBottom[1] - leftTop[1] + ANCHOR_OVERFLOW_SIZE}px` + anchor.style.height = `${ + leftBottom[1] - leftTop[1] + ANCHOR_OVERFLOW_SIZE + }px` anchor.style.left = `${leftTop[0]}px` anchor.style.top = `${leftTop[1] + preY}px` this.draw.getContainer().append(anchor) @@ -127,9 +135,10 @@ export class Search { public getSearchNavigateInfo(): null | INavigateInfo { if (!this.searchKeyword || !this.searchMatchList.length) return null - const index = this.searchNavigateIndex !== null - ? (this.searchNavigateIndex / this.searchKeyword.length) + 1 - : 0 + const index = + this.searchNavigateIndex !== null + ? this.searchNavigateIndex / this.searchKeyword.length + 1 + : 0 let count = 0 let groupId = null for (let s = 0; s < this.searchMatchList.length; s++) { @@ -148,7 +157,11 @@ export class Search { const keyword = payload.toLocaleLowerCase() const searchMatchList: ISearchResult[] = [] // 分组 - const elementListGroup: { type: EditorContext, elementList: IElement[], index: number }[] = [] + const elementListGroup: { + type: EditorContext + elementList: IElement[] + index: number + }[] = [] const originalElementList = this.draw.getOriginalElementList() const originalElementListLength = originalElementList.length // 查找表格所在位置 @@ -162,7 +175,9 @@ export class Search { let i = 0 let elementIndex = 0 while (elementIndex < originalElementListLength - 1) { - const endIndex = tableIndexList.length ? tableIndexList[i] : originalElementListLength + const endIndex = tableIndexList.length + ? tableIndexList[i] + : originalElementListLength const pageElement = originalElementList.slice(elementIndex, endIndex) if (pageElement.length) { elementListGroup.push({ @@ -183,12 +198,21 @@ export class Search { i++ } // 搜索文本 - function searchClosure(payload: string | null, type: EditorContext, elementList: IElement[], restArgs?: ISearchResultRestArgs) { + function searchClosure( + payload: string | null, + type: EditorContext, + elementList: IElement[], + restArgs?: ISearchResultRestArgs + ) { if (!payload) return const text = elementList - .map(e => !e.type || (TEXTLIKE_ELEMENT_TYPE.includes(e.type) && e.controlComponent !== ControlComponent.CHECKBOX) - ? e.value - : ZERO) + .map(e => + !e.type || + (TEXTLIKE_ELEMENT_TYPE.includes(e.type) && + e.controlComponent !== ControlComponent.CHECKBOX) + ? e.value + : ZERO + ) .filter(Boolean) .join('') .toLocaleLowerCase() @@ -239,8 +263,15 @@ export class Search { } public render(ctx: CanvasRenderingContext2D, pageIndex: number) { - if (!this.searchMatchList || !this.searchMatchList.length || !this.searchKeyword) return - const { searchMatchAlpha, searchMatchColor, searchNavigateMatchColor } = this.options + if ( + !this.searchMatchList || + !this.searchMatchList.length || + !this.searchKeyword + ) { + return + } + const { searchMatchAlpha, searchMatchColor, searchNavigateMatchColor } = + this.options const positionList = this.position.getOriginalPositionList() const elementList = this.draw.getOriginalElementList() ctx.save() @@ -250,12 +281,17 @@ export class Search { let position: IElementPosition | null = null if (searchMatch.type === EditorContext.TABLE) { const { tableIndex, trIndex, tdIndex, index } = searchMatch - position = elementList[tableIndex!]?.trList![trIndex!].tdList[tdIndex!]?.positionList![index] + position = + elementList[tableIndex!]?.trList![trIndex!].tdList[tdIndex!] + ?.positionList![index] } else { position = positionList[searchMatch.index] } if (!position) continue - const { coordinate: { leftTop, leftBottom, rightTop }, pageNo } = position + const { + coordinate: { leftTop, leftBottom, rightTop }, + pageNo + } = position if (pageNo !== pageIndex) continue // 高亮并定位当前搜索词 const searchMatchIndexList = this.getSearchNavigateIndexList() @@ -277,5 +313,4 @@ export class Search { } ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/CheckboxParticle.ts b/src/editor/core/draw/particle/CheckboxParticle.ts index 85d1704..38dd37b 100644 --- a/src/editor/core/draw/particle/CheckboxParticle.ts +++ b/src/editor/core/draw/particle/CheckboxParticle.ts @@ -4,15 +4,22 @@ import { IRowElement } from '../../../interface/Row' import { Draw } from '../Draw' export class CheckboxParticle { - private options: DeepRequired constructor(draw: Draw) { this.options = draw.getOptions() } - public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) { - const { checkbox: { gap, lineWidth, fillStyle, fontStyle }, scale } = this.options + public render( + ctx: CanvasRenderingContext2D, + element: IRowElement, + x: number, + y: number + ) { + const { + checkbox: { gap, lineWidth, fillStyle, fontStyle }, + scale + } = this.options const { metrics, checkbox } = element // left top 四舍五入避免1像素问题 const left = Math.round(x + gap) @@ -50,5 +57,4 @@ export class CheckboxParticle { ctx.closePath() ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/HyperlinkParticle.ts b/src/editor/core/draw/particle/HyperlinkParticle.ts index e2239d6..394bfe0 100644 --- a/src/editor/core/draw/particle/HyperlinkParticle.ts +++ b/src/editor/core/draw/particle/HyperlinkParticle.ts @@ -6,7 +6,6 @@ import { IRowElement } from '../../../interface/Row' import { Draw } from '../Draw' export class HyperlinkParticle { - private draw: Draw private options: Required private container: HTMLDivElement @@ -17,7 +16,8 @@ export class HyperlinkParticle { this.draw = draw this.options = draw.getOptions() this.container = draw.getContainer() - const { hyperlinkPopupContainer, hyperlinkDom } = this._createHyperlinkPopupDom() + const { hyperlinkPopupContainer, hyperlinkDom } = + this._createHyperlinkPopupDom() this.hyperlinkDom = hyperlinkDom this.hyperlinkPopupContainer = hyperlinkPopupContainer } @@ -34,7 +34,12 @@ export class HyperlinkParticle { } public drawHyperlinkPopup(element: IElement, position: IElementPosition) { - const { coordinate: { leftTop: [left, top] }, lineHeight } = position + const { + coordinate: { + leftTop: [left, top] + }, + lineHeight + } = position const height = this.draw.getHeight() const pageGap = this.draw.getPageGap() const preY = this.draw.getPageNo() * (height + pageGap) @@ -60,7 +65,12 @@ export class HyperlinkParticle { } } - public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) { + public render( + ctx: CanvasRenderingContext2D, + element: IRowElement, + x: number, + y: number + ) { ctx.save() ctx.font = element.style if (!element.color) { @@ -73,5 +83,4 @@ export class HyperlinkParticle { ctx.fillText(element.value, x, y) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/ImageParticle.ts b/src/editor/core/draw/particle/ImageParticle.ts index b4d5324..42c3719 100644 --- a/src/editor/core/draw/particle/ImageParticle.ts +++ b/src/editor/core/draw/particle/ImageParticle.ts @@ -4,7 +4,6 @@ import { convertStringToBase64 } from '../../../utils' import { Draw } from '../Draw' export class ImageParticle { - private draw: Draw protected options: Required protected imageCache: Map @@ -26,18 +25,27 @@ export class ImageParticle { const svg = ` - + ` const fallbackImage = new Image() - fallbackImage.src = `data:image/svg+xml;base64,${convertStringToBase64(svg)}` + fallbackImage.src = `data:image/svg+xml;base64,${convertStringToBase64( + svg + )}` return fallbackImage } - public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) { + public render( + ctx: CanvasRenderingContext2D, + element: IElement, + x: number, + y: number + ) { const { scale } = this.options const width = element.width! * scale const height = element.height! * scale @@ -54,7 +62,7 @@ export class ImageParticle { this.imageCache.set(element.id!, img) resolve(element) } - img.onerror = (error) => { + img.onerror = error => { const fallbackImage = this.getFallbackImage(width, height) fallbackImage.onload = () => { ctx.drawImage(fallbackImage, x, y, width, height) @@ -66,5 +74,4 @@ export class ImageParticle { this.addImageObserver(imageLoadPromise) } } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/ListParticle.ts b/src/editor/core/draw/particle/ListParticle.ts index ea12c97..8c19a87 100644 --- a/src/editor/core/draw/particle/ListParticle.ts +++ b/src/editor/core/draw/particle/ListParticle.ts @@ -9,7 +9,6 @@ import { IRow } from '../../../interface/Row' import { Draw } from '../Draw' export class ListParticle { - private options: DeepRequired // 非递增样式直接返回默认值 @@ -21,7 +20,10 @@ export class ListParticle { this.options = draw.getOptions() } - public computeListStyle(ctx: CanvasRenderingContext2D, elementList: IElement[]): Map { + public computeListStyle( + ctx: CanvasRenderingContext2D, + elementList: IElement[] + ): Map { const listStyleMap = new Map() let start = 0 let curListId = elementList[start].listId @@ -51,11 +53,17 @@ export class ListParticle { return listStyleMap } - public getListStyleWidth(ctx: CanvasRenderingContext2D, listElementList: IElement[]): number { + public getListStyleWidth( + ctx: CanvasRenderingContext2D, + listElementList: IElement[] + ): number { const { scale } = this.options const startElement = listElementList[0] // 非递增样式返回固定值 - if (startElement.listStyle && startElement.listStyle !== ListStyle.DECIMAL) { + if ( + startElement.listStyle && + startElement.listStyle !== ListStyle.DECIMAL + ) { return this.UN_COUNT_STYLE_WIDTH * scale } // 计算列表数量 @@ -67,23 +75,35 @@ export class ListParticle { }, 0) if (!count) return 0 // 以递增样式最大宽度为准 - const text = `${this.MEASURE_BASE_TEXT.repeat(String(count).length)}${KeyMap.PERIOD}` + const text = `${this.MEASURE_BASE_TEXT.repeat(String(count).length)}${ + KeyMap.PERIOD + }` const textMetrics = ctx.measureText(text) return Math.ceil((textMetrics.width + this.LIST_GAP) * scale) } - public drawListStyle(ctx: CanvasRenderingContext2D, row: IRow, position: IElementPosition) { + public drawListStyle( + ctx: CanvasRenderingContext2D, + row: IRow, + position: IElementPosition + ) { const { elementList, offsetX, listIndex, ascent } = row const startElement = elementList[0] if (startElement.value !== ZERO || startElement.listWrap) return let text = '' if (startElement.listType === ListType.UL) { - text = ulStyleMapping[startElement.listStyle] || ulStyleMapping[UlStyle.DISC] + text = + ulStyleMapping[(startElement.listStyle)] || + ulStyleMapping[UlStyle.DISC] } else { text = `${listIndex! + 1}${KeyMap.PERIOD}` } if (!text) return - const { coordinate: { leftTop: [startX, startY] } } = position + const { + coordinate: { + leftTop: [startX, startY] + } + } = position const x = startX - offsetX! const y = startY + ascent const { defaultFont, defaultSize, scale } = this.options @@ -92,5 +112,4 @@ export class ListParticle { ctx.fillText(text, x, y) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/PageBreak.ts b/src/editor/core/draw/particle/PageBreak.ts index ab57032..4df49f5 100644 --- a/src/editor/core/draw/particle/PageBreak.ts +++ b/src/editor/core/draw/particle/PageBreak.ts @@ -3,7 +3,6 @@ import { IRowElement } from '../../../interface/Row' import { Draw } from '../Draw' export class PageBreakParticle { - static readonly font: string = 'Yahei' static readonly fontSize: number = 12 static readonly displayName: string = '分页符' @@ -17,12 +16,18 @@ export class PageBreakParticle { this.options = draw.getOptions() } - public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) { + public render( + ctx: CanvasRenderingContext2D, + element: IRowElement, + x: number, + y: number + ) { const { font, fontSize, displayName, lineDash } = PageBreakParticle const { scale, defaultRowMargin } = this.options const size = fontSize * scale const elementWidth = element.width! - const offsetY = this.draw.getDefaultBasicRowMarginHeight() * defaultRowMargin + const offsetY = + this.draw.getDefaultBasicRowMarginHeight() * defaultRowMargin ctx.save() ctx.font = `${size}px ${font}` const textMeasure = ctx.measureText(displayName) @@ -37,8 +42,11 @@ export class PageBreakParticle { ctx.lineTo(x + elementWidth, y) ctx.stroke() // 文字 - ctx.fillText(displayName, x + halfX, y + textMeasure.actualBoundingBoxAscent - size / 2) + ctx.fillText( + displayName, + x + halfX, + y + textMeasure.actualBoundingBoxAscent - size / 2 + ) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/Separator.ts b/src/editor/core/draw/particle/Separator.ts index 1dc4ffc..7c6e9dd 100644 --- a/src/editor/core/draw/particle/Separator.ts +++ b/src/editor/core/draw/particle/Separator.ts @@ -1,7 +1,11 @@ import { IRowElement } from '../../../interface/Row' export class SeparatorParticle { - - public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) { + public render( + ctx: CanvasRenderingContext2D, + element: IRowElement, + x: number, + y: number + ) { ctx.save() if (element.color) { ctx.strokeStyle = element.color @@ -16,5 +20,4 @@ export class SeparatorParticle { ctx.stroke() ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/Subscript.ts b/src/editor/core/draw/particle/Subscript.ts index d94f9ee..1bfff0e 100644 --- a/src/editor/core/draw/particle/Subscript.ts +++ b/src/editor/core/draw/particle/Subscript.ts @@ -1,8 +1,12 @@ import { IRowElement } from '../../../interface/Row' export class SubscriptParticle { - - public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) { + public render( + ctx: CanvasRenderingContext2D, + element: IRowElement, + x: number, + y: number + ) { ctx.save() ctx.font = element.style if (element.color) { @@ -11,5 +15,4 @@ export class SubscriptParticle { ctx.fillText(element.value, x, y + element.metrics.height / 2) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/Superscript.ts b/src/editor/core/draw/particle/Superscript.ts index 34f1bd1..a698a6b 100644 --- a/src/editor/core/draw/particle/Superscript.ts +++ b/src/editor/core/draw/particle/Superscript.ts @@ -1,8 +1,12 @@ import { IRowElement } from '../../../interface/Row' export class SuperscriptParticle { - - public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) { + public render( + ctx: CanvasRenderingContext2D, + element: IRowElement, + x: number, + y: number + ) { ctx.save() ctx.font = element.style if (element.color) { @@ -11,5 +15,4 @@ export class SuperscriptParticle { ctx.fillText(element.value, x, y - element.metrics.height / 2) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/TextParticle.ts b/src/editor/core/draw/particle/TextParticle.ts index 1702b50..3df406d 100644 --- a/src/editor/core/draw/particle/TextParticle.ts +++ b/src/editor/core/draw/particle/TextParticle.ts @@ -5,12 +5,11 @@ import { IRowElement } from '../../../interface/Row' import { Draw } from '../Draw' export interface IMeasureWordResult { - width: number; - endElement: IElement; + width: number + endElement: IElement } export class TextParticle { - private ctx: CanvasRenderingContext2D private curX: number private curY: number @@ -28,7 +27,11 @@ export class TextParticle { this.cacheMeasureText = new Map() } - public measureWord(ctx: CanvasRenderingContext2D, elementList: IElement[], curIndex: number): IMeasureWordResult { + public measureWord( + ctx: CanvasRenderingContext2D, + elementList: IElement[], + curIndex: number + ): IMeasureWordResult { let width = 0 let endElement: IElement = elementList[curIndex] let i = curIndex @@ -47,12 +50,18 @@ export class TextParticle { } } - public measurePunctuationWidth(ctx: CanvasRenderingContext2D, element: IElement): number { + public measurePunctuationWidth( + ctx: CanvasRenderingContext2D, + element: IElement + ): number { if (!element || !PUNCTUATION_LIST.includes(element.value)) return 0 return this.measureText(ctx, element).width } - public measureText(ctx: CanvasRenderingContext2D, element: IElement): TextMetrics { + public measureText( + ctx: CanvasRenderingContext2D, + element: IElement + ): TextMetrics { const id = `${element.value}${ctx.font}` const cacheTextMetrics = this.cacheMeasureText.get(id) if (cacheTextMetrics) { @@ -68,7 +77,12 @@ export class TextParticle { this.text = '' } - public record(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) { + public record( + ctx: CanvasRenderingContext2D, + element: IRowElement, + x: number, + y: number + ) { this.ctx = ctx // 主动完成的重设起始点 if (!this.text) { @@ -77,7 +91,7 @@ export class TextParticle { // 样式发生改变 if ( (this.curStyle && element.style !== this.curStyle) || - (element.color !== this.curColor) + element.color !== this.curColor ) { this.complete() this._setCurXY(x, y) @@ -102,5 +116,4 @@ export class TextParticle { this.ctx.fillText(this.text, this.curX, this.curY) this.ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/block/BlockParticle.ts b/src/editor/core/draw/particle/block/BlockParticle.ts index 597fddd..2a7364a 100644 --- a/src/editor/core/draw/particle/block/BlockParticle.ts +++ b/src/editor/core/draw/particle/block/BlockParticle.ts @@ -5,7 +5,6 @@ import { Draw } from '../../Draw' import { BaseBlock } from './modules/BaseBlock' export class BlockParticle { - private draw: Draw private container: HTMLDivElement private blockContainer: HTMLDivElement @@ -64,5 +63,4 @@ export class BlockParticle { } }) } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/block/modules/BaseBlock.ts b/src/editor/core/draw/particle/block/modules/BaseBlock.ts index 17b9d4b..b824d4b 100644 --- a/src/editor/core/draw/particle/block/modules/BaseBlock.ts +++ b/src/editor/core/draw/particle/block/modules/BaseBlock.ts @@ -7,7 +7,6 @@ import { IFrameBlock } from './IFrameBlock' import { VideoBlock } from './VideoBlock' export class BaseBlock { - private draw: Draw private element: IRowElement private block: IFrameBlock | VideoBlock | null @@ -60,5 +59,4 @@ export class BaseBlock { public remove() { this.blockItem.remove() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/block/modules/IFrameBlock.ts b/src/editor/core/draw/particle/block/modules/IFrameBlock.ts index b1cc2f8..9fd58cb 100644 --- a/src/editor/core/draw/particle/block/modules/IFrameBlock.ts +++ b/src/editor/core/draw/particle/block/modules/IFrameBlock.ts @@ -1,7 +1,6 @@ import { IRowElement } from '../../../../../interface/Row' export class IFrameBlock { - private static readonly sandbox = [ 'allow-forms', 'allow-scripts', @@ -24,5 +23,4 @@ export class IFrameBlock { iframe.src = block.iframeBlock?.src || '' blockItemContainer.append(iframe) } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/block/modules/VideoBlock.ts b/src/editor/core/draw/particle/block/modules/VideoBlock.ts index eb0a30c..56a7c1c 100644 --- a/src/editor/core/draw/particle/block/modules/VideoBlock.ts +++ b/src/editor/core/draw/particle/block/modules/VideoBlock.ts @@ -1,7 +1,6 @@ import { IRowElement } from '../../../../../interface/Row' export class VideoBlock { - private element: IRowElement constructor(element: IRowElement) { @@ -19,5 +18,4 @@ export class VideoBlock { video.crossOrigin = 'anonymous' blockItemContainer.append(video) } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/date/DateParticle.ts b/src/editor/core/draw/particle/date/DateParticle.ts index 4e91005..088e6b6 100644 --- a/src/editor/core/draw/particle/date/DateParticle.ts +++ b/src/editor/core/draw/particle/date/DateParticle.ts @@ -7,7 +7,6 @@ import { Draw } from '../../Draw' import { DatePicker } from './DatePicker' export class DateParticle { - private draw: Draw private range: RangeManager private datePicker: DatePicker @@ -32,7 +31,7 @@ export class DateParticle { wed: t('datePicker.weeks.wed'), thu: t('datePicker.weeks.thu'), fri: t('datePicker.weeks.fri'), - sat: t('datePicker.weeks.sat'), + sat: t('datePicker.weeks.sat') }, year: t('datePicker.year'), month: t('datePicker.month'), @@ -51,16 +50,22 @@ export class DateParticle { const elementList = this.draw.getElementList() const startElement = elementList[leftIndex + 1] // 删除旧时间 - this.draw.spliceElementList(elementList, leftIndex + 1, rightIndex - leftIndex) + this.draw.spliceElementList( + elementList, + leftIndex + 1, + rightIndex - leftIndex + ) this.range.setRange(leftIndex, leftIndex) // 插入新时间 const dateElement: IElement = { type: ElementType.DATE, value: '', dateFormat: startElement.dateFormat, - valueList: [{ - value: date - }] + valueList: [ + { + value: date + } + ] } formatElementContext(elementList, [dateElement], leftIndex) this.draw.insertElementList([dateElement]) @@ -113,7 +118,10 @@ export class DateParticle { const elementList = this.draw.getElementList() const range = this.getDateElementRange() const value = range - ? elementList.slice(range[0] + 1, range[1] + 1).map(el => el.value).join('') + ? elementList + .slice(range[0] + 1, range[1] + 1) + .map(el => el.value) + .join('') : '' this.datePicker.render({ value, @@ -123,7 +131,12 @@ export class DateParticle { }) } - public render(ctx: CanvasRenderingContext2D, element: IRowElement, x: number, y: number) { + public render( + ctx: CanvasRenderingContext2D, + element: IRowElement, + x: number, + y: number + ) { ctx.save() ctx.font = element.style if (element.color) { @@ -132,5 +145,4 @@ export class DateParticle { ctx.fillText(element.value, x, y) ctx.restore() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/date/DatePicker.ts b/src/editor/core/draw/particle/date/DatePicker.ts index cd6d26a..775596b 100644 --- a/src/editor/core/draw/particle/date/DatePicker.ts +++ b/src/editor/core/draw/particle/date/DatePicker.ts @@ -3,66 +3,65 @@ import { IElement, IElementPosition } from '../../../../interface/Element' import { datePicker } from '../../../i18n/lang/zh-CN.json' export interface IDatePickerLang { - now: string; - confirm: string; - return: string; - timeSelect: string; + now: string + confirm: string + return: string + timeSelect: string weeks: { - sun: string; - mon: string; - tue: string; - wed: string; - thu: string; - fri: string; - sat: string; - }; - year: string; - month: string; - hour: string; - minute: string; - second: string; + sun: string + mon: string + tue: string + wed: string + thu: string + fri: string + sat: string + } + year: string + month: string + hour: string + minute: string + second: string } export interface IDatePickerOption { - mountDom?: HTMLElement; - onSubmit?: (date: string) => any; + mountDom?: HTMLElement + onSubmit?: (date: string) => any getLang?: () => IDatePickerLang } interface IDatePickerDom { - container: HTMLDivElement; - dateWrap: HTMLDivElement; - datePickerWeek: HTMLDivElement; - timeWrap: HTMLUListElement; + container: HTMLDivElement + dateWrap: HTMLDivElement + datePickerWeek: HTMLDivElement + timeWrap: HTMLUListElement title: { - preYear: HTMLSpanElement; - preMonth: HTMLSpanElement; - now: HTMLSpanElement; - nextMonth: HTMLSpanElement; - nextYear: HTMLSpanElement; - }; - day: HTMLDivElement; + preYear: HTMLSpanElement + preMonth: HTMLSpanElement + now: HTMLSpanElement + nextMonth: HTMLSpanElement + nextYear: HTMLSpanElement + } + day: HTMLDivElement time: { - hour: HTMLOListElement; - minute: HTMLOListElement; - second: HTMLOListElement; - }; + hour: HTMLOListElement + minute: HTMLOListElement + second: HTMLOListElement + } menu: { - time: HTMLButtonElement; - now: HTMLButtonElement; - submit: HTMLButtonElement; - }; + time: HTMLButtonElement + now: HTMLButtonElement + submit: HTMLButtonElement + } } interface IRenderOption { - value: string; - element: IElement; - position: IElementPosition; - startTop?: number; + value: string + element: IElement + position: IElementPosition + startTop?: number } export class DatePicker { - private options: IDatePickerOption private now: Date private dom: IDatePickerDom @@ -115,7 +114,9 @@ export class DatePicker { // week-星期显示 const datePickerWeek = document.createElement('div') datePickerWeek.classList.add(`${EDITOR_PREFIX}-date-week`) - const { weeks: { sun, mon, tue, wed, thu, fri, sat } } = this.lang + const { + weeks: { sun, mon, tue, wed, thu, fri, sat } + } = this.lang const weekList = [sun, mon, tue, wed, thu, fri, sat] weekList.forEach(week => { const weekDom = document.createElement('span') @@ -232,7 +233,7 @@ export class DatePicker { this.dispose() this._submit() } - this.dom.time.hour.onclick = (evt) => { + this.dom.time.hour.onclick = evt => { if (!this.pickDate) return const li = evt.target const id = li.dataset.id @@ -240,7 +241,7 @@ export class DatePicker { this.pickDate.setHours(Number(id)) this._setTimePick(false) } - this.dom.time.minute.onclick = (evt) => { + this.dom.time.minute.onclick = evt => { if (!this.pickDate) return const li = evt.target const id = li.dataset.id @@ -248,7 +249,7 @@ export class DatePicker { this.pickDate.setMinutes(Number(id)) this._setTimePick(false) } - this.dom.time.second.onclick = (evt) => { + this.dom.time.second.onclick = evt => { if (!this.pickDate) return const li = evt.target const id = li.dataset.id @@ -293,16 +294,23 @@ export class DatePicker { this.dom.menu.time.innerText = this.lang.timeSelect this.dom.menu.now.innerText = this.lang.now this.dom.menu.submit.innerText = this.lang.confirm - const { weeks: { sun, mon, tue, wed, thu, fri, sat } } = this.lang + const { + weeks: { sun, mon, tue, wed, thu, fri, sat } + } = this.lang const weekList = [sun, mon, tue, wed, thu, fri, sat] this.dom.datePickerWeek.childNodes.forEach((child, i) => { - (child).innerText = weekList[i] + const childElement = child + childElement.innerText = weekList[i] }) - const hourTitle = (this.dom.time.hour.previousElementSibling) + const hourTitle = this.dom.time.hour.previousElementSibling hourTitle.innerText = this.lang.hour - const minuteTitle = (this.dom.time.minute.previousElementSibling) + const minuteTitle = ( + this.dom.time.minute.previousElementSibling + ) minuteTitle.innerText = this.lang.minute - const secondTitle = (this.dom.time.second.previousElementSibling) + const secondTitle = ( + this.dom.time.second.previousElementSibling + ) secondTitle.innerText = this.lang.second } @@ -324,7 +332,9 @@ export class DatePicker { // 当前年月日 const year = this.now.getFullYear() const month = this.now.getMonth() + 1 - this.dom.title.now.innerText = `${year}${this.lang.year} ${String(month).padStart(2, '0')}${this.lang.month}` + this.dom.title.now.innerText = `${year}${this.lang.year} ${String( + month + ).padStart(2, '0')}${this.lang.month}` // 日期补差 const curDate = new Date(year, month, 0) // 当月日期 const curDay = curDate.getDate() // 当月总天数 @@ -353,11 +363,16 @@ export class DatePicker { if (localYear === year && localMonth === month && localDay === i) { dayDom.classList.add('active') } - if (this.pickDate && pickYear === year && pickMonth === month && pickDay === i) { + if ( + this.pickDate && + pickYear === year && + pickMonth === month && + pickDay === i + ) { dayDom.classList.add('select') } dayDom.innerText = `${i}` - dayDom.onclick = (evt) => { + dayDom.onclick = evt => { const newMonth = month - 1 this.now = new Date(year, newMonth, i) this._setDatePick(year, newMonth, i) @@ -405,14 +420,23 @@ export class DatePicker { const hour = this.pickDate?.getHours() || 0 const minute = this.pickDate?.getMinutes() || 0 const second = this.pickDate?.getSeconds() || 0 - const { hour: hourDom, minute: minuteDom, second: secondDom } = this.dom.time + const { + hour: hourDom, + minute: minuteDom, + second: secondDom + } = this.dom.time const timeDomList = [hourDom, minuteDom, secondDom] // 清空 timeDomList.forEach(timeDom => { - timeDom.querySelectorAll('li') + timeDom + .querySelectorAll('li') .forEach(li => li.classList.remove('active')) }) - const pickList: [HTMLOListElement, number][] = [[hourDom, hour], [minuteDom, minute], [secondDom, second]] + const pickList: [HTMLOListElement, number][] = [ + [hourDom, hour], + [minuteDom, minute], + [secondDom, second] + ] pickList.forEach(([dom, time]) => { const pickDom = dom.querySelector(`[data-id='${time}']`)! pickDom.classList.add('active') @@ -433,7 +457,9 @@ export class DatePicker { offsetParents.push(pointer) pointer = pointer.offsetParent } - const top = selected.offsetTop + offsetParents.reduce((prev, curr) => (prev + curr.offsetTop), 0) + const top = + selected.offsetTop + + offsetParents.reduce((prev, curr) => prev + curr.offsetTop, 0) const bottom = top + selected.offsetHeight const viewRectTop = container.scrollTop const viewRectBottom = viewRectTop + container.clientHeight @@ -502,8 +528,8 @@ export class DatePicker { dateString = dateString.replace( reg[1], reg[1].length === 1 - ? (dateOption[key]) - : (dateOption[key].padStart(reg[1].length, '0')) + ? dateOption[key] + : dateOption[key].padStart(reg[1].length, '0') ) } } @@ -527,5 +553,4 @@ export class DatePicker { public dispose() { this._toggleVisible(false) } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/latex/LaTexParticle.ts b/src/editor/core/draw/particle/latex/LaTexParticle.ts index 36cf9d9..bf33c43 100644 --- a/src/editor/core/draw/particle/latex/LaTexParticle.ts +++ b/src/editor/core/draw/particle/latex/LaTexParticle.ts @@ -3,7 +3,6 @@ import { ImageParticle } from '../ImageParticle' import { LaTexSVG, LaTexUtils } from './utils/LaTexUtils' export class LaTexParticle extends ImageParticle { - public static convertLaTextToSVG(laTex: string): LaTexSVG { return new LaTexUtils(laTex).svg({ SCALE_X: 10, @@ -13,7 +12,12 @@ export class LaTexParticle extends ImageParticle { }) } - public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) { + public render( + ctx: CanvasRenderingContext2D, + element: IElement, + x: number, + y: number + ) { const { scale } = this.options const width = element.width! * scale const height = element.height! * scale @@ -29,13 +33,11 @@ export class LaTexParticle extends ImageParticle { this.imageCache.set(element.value, img) resolve(element) } - img.onerror = (error) => { + img.onerror = error => { reject(error) } }) this.addImageObserver(laTexLoadPromise) } } - } - diff --git a/src/editor/core/draw/particle/latex/utils/LaTexUtils.ts b/src/editor/core/draw/particle/latex/utils/LaTexUtils.ts index 59053b3..a29d802 100644 --- a/src/editor/core/draw/particle/latex/utils/LaTexUtils.ts +++ b/src/editor/core/draw/particle/latex/utils/LaTexUtils.ts @@ -6,7 +6,7 @@ const CONFIG: Record = { SQRT_MAG_SCALE: 0.5, FRAC_SCALE: 0.85, LINE_SPACING: 0.5, - FRAC_SPACING: 0.4, + FRAC_SPACING: 0.4 } function tokenize(str: string): string[] { @@ -49,27 +49,40 @@ function tokenize(str: string): string[] { } interface Bbox { - x: number, y: number, w: number, h: number + x: number + y: number + w: number + h: number } interface Expr { - type: string; - text: string; - mode: string; - chld: Expr[]; - bbox: Bbox; + type: string + text: string + mode: string + chld: Expr[] + bbox: Bbox } function parseAtom(x: string): Expr { - // @ts-ignore - return { type: SYMB[x] ? 'symb' : 'char', mode: 'math', text: x, chld: [], bbox: null } + return { + type: SYMB[x] ? 'symb' : 'char', + mode: 'math', + text: x, + chld: [], + // @ts-ignore + bbox: null + } } function parse(tokens: string[]): Expr { let i = 0 let expr: Expr = { + type: 'node', + text: '', + mode: 'math', + chld: [], // @ts-ignore - type: 'node', text: '', mode: 'math', chld: [], bbox: null + bbox: null } function takeOpt(): Expr | null { @@ -133,8 +146,12 @@ function parse(tokens: string[]): Expr { for (i = 0; i < tokens.length; i++) { const s: Symb = SYMB[tokens[i]] const e: Expr = { + type: '', + text: tokens[i], + mode: 'math', + chld: [], // @ts-ignore - type: '', text: tokens[i], mode: 'math', chld: [], bbox: null + bbox: null } if (s) { if (s.arity) { @@ -190,7 +207,14 @@ function environments(exprs: Expr[]) { } } -function transform(expr: Expr, sclx: number, scly: number, x: number, y: number, notFirst?: boolean) { +function transform( + expr: Expr, + sclx: number, + scly: number, + x: number, + y: number, + notFirst?: boolean +) { if (scly == null) { scly = sclx } @@ -209,8 +233,10 @@ function transform(expr: Expr, sclx: number, scly: number, x: number, y: number, } function computeBbox(exprs: Expr[]): Bbox { - let xmin = Infinity; let xmax = -Infinity - let ymin = Infinity; let ymax = -Infinity + let xmin = Infinity + let xmax = -Infinity + let ymin = Infinity + let ymax = -Infinity for (let i = 0; i < exprs.length; i++) { if (!exprs[i].bbox) { continue @@ -238,8 +264,11 @@ function group(exprs: Expr[]): Expr { exprs[i].bbox.y -= bbox.y } const expr: Expr = { - type: 'node', text: '', mode: 'math', - chld: exprs, bbox + type: 'node', + text: '', + mode: 'math', + chld: exprs, + bbox } return expr } @@ -249,7 +278,10 @@ function align(exprs: Expr[], alignment = 'center'): void { if (exprs[i].text == '^' || exprs[i].text == '\'') { let h = 0 let j = i - while (j > 0 && (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'')) { + while ( + j > 0 && + (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'') + ) { j-- } h = exprs[j].bbox.y @@ -269,7 +301,10 @@ function align(exprs: Expr[], alignment = 'center'): void { } else if (exprs[i].text == '_') { let h = 1 let j = i - while (j > 0 && (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'')) { + while ( + j > 0 && + (exprs[j].text == '^' || exprs[j].text == '_' || exprs[j].text == '\'') + ) { j-- } h = exprs[j].bbox.y + exprs[j].bbox.h @@ -284,12 +319,18 @@ function align(exprs: Expr[], alignment = 'center'): void { } } } - function searchHigh(i: number, l: string, r: string, dir: number, lvl0: number): number[] { + function searchHigh( + i: number, + l: string, + r: string, + dir: number, + lvl0: number + ): number[] { let j = i let lvl = lvl0 let ymin = Infinity let ymax = -Infinity - while ((dir > 0) ? (j < exprs.length) : (j >= 0)) { + while (dir > 0 ? j < exprs.length : j >= 0) { if (exprs[j].text == l) { lvl++ } else if (exprs[j].text == r) { @@ -312,13 +353,13 @@ function align(exprs: Expr[], alignment = 'center'): void { const [ymin, ymax] = searchHigh(i, '\\left', '\\right', 1, 0) if (ymin != Infinity && ymax != -Infinity) { exprs[i].bbox.y = ymin - transform(exprs[i], 1, ((ymax - ymin) / exprs[i].bbox.h), 0, 0) + transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0) } } else if (exprs[i].text == '\\right') { const [ymin, ymax] = searchHigh(i, '\\right', '\\left', -1, 0) if (ymin != Infinity && ymax != -Infinity) { exprs[i].bbox.y = ymin - transform(exprs[i], 1, ((ymax - ymin) / exprs[i].bbox.h), 0, 0) + transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0) } } else if (exprs[i].text == '\\middle') { const [lmin, lmax] = searchHigh(i, '\\right', '\\left', -1, 1) @@ -327,12 +368,12 @@ function align(exprs: Expr[], alignment = 'center'): void { const ymax = Math.max(lmax, rmax) if (ymin != Infinity && ymax != -Infinity) { exprs[i].bbox.y = ymin - transform(exprs[i], 1, ((ymax - ymin) / exprs[i].bbox.h), 0, 0) + transform(exprs[i], 1, (ymax - ymin) / exprs[i].bbox.h, 0, 0) } } } - if (!exprs.some((x) => (x.text == '&' || x.text == '\\\\'))) { + if (!exprs.some(x => x.text == '&' || x.text == '\\\\')) { return } @@ -408,28 +449,27 @@ function align(exprs: Expr[], alignment = 'center'): void { ybds[i][1] += shft } - exprs.splice(0, exprs.length) for (let i = 0; i < erows.length; i++) { let dx = 0 for (let j = 0; j < erows[i].length; j++) { const e: Expr = erows[i][j] if (!e) { - dx += (colws[j]) + dx += colws[j] continue } e.bbox.x += dx - dx += (colws[j] - e.bbox.w) + dx += colws[j] - e.bbox.w // e.bbox.w = colws[j]; if (alignment == 'center') { e.bbox.x += (colws[j] - e.bbox.w) / 2 } else if (alignment == 'left') { //ok } else if (alignment == 'right') { - e.bbox.x += (colws[j] - e.bbox.w) + e.bbox.x += colws[j] - e.bbox.w } else if (alignment == 'equation') { if (j != erows[i].length - 1) { - e.bbox.x += (colws[j] - e.bbox.w) + e.bbox.x += colws[j] - e.bbox.w } } exprs.push(e) @@ -438,28 +478,29 @@ function align(exprs: Expr[], alignment = 'center'): void { } function plan(expr: Expr, mode = 'math'): void { - const tmd: string = { - '\\text': 'text', - '\\mathnormal': 'math', - '\\mathrm': 'rm', - '\\mathit': 'it', - '\\mathbf': 'bf', - '\\mathsf': 'sf', - '\\mathtt': 'tt', - '\\mathfrak': 'frak', - '\\mathcal': 'cal', - '\\mathbb': 'bb', - '\\mathscr': 'scr', - '\\rm': 'rm', - '\\it': 'it', - '\\bf': 'bf', - '\\sf': 'tt', - '\\tt': 'tt', - '\\frak': 'frak', - '\\cal': 'cal', - '\\bb': 'bb', - '\\scr': 'scr', - }[expr.text] ?? mode + const tmd: string = + { + '\\text': 'text', + '\\mathnormal': 'math', + '\\mathrm': 'rm', + '\\mathit': 'it', + '\\mathbf': 'bf', + '\\mathsf': 'sf', + '\\mathtt': 'tt', + '\\mathfrak': 'frak', + '\\mathcal': 'cal', + '\\mathbb': 'bb', + '\\mathscr': 'scr', + '\\rm': 'rm', + '\\it': 'it', + '\\bf': 'bf', + '\\sf': 'tt', + '\\tt': 'tt', + '\\frak': 'frak', + '\\cal': 'cal', + '\\bb': 'bb', + '\\scr': 'scr' + }[expr.text] ?? mode if (!expr.chld.length) { if (SYMB[expr.text]) { if (SYMB[expr.text].flags.big) { @@ -517,9 +558,20 @@ function plan(expr: Expr, mode = 'math'): void { const mw: number = Math.max(a.bbox.w, b.bbox.w) * s // @ts-ignore transform(a, s, null, (mw - a.bbox.w * s) / 2, 0) - // @ts-ignore - transform(b, s, null, (mw - b.bbox.w * s) / 2, a.bbox.h + CONFIG.FRAC_SPACING) - expr.bbox = { x: 0, y: -a.bbox.h + 1 - CONFIG.FRAC_SPACING / 2, w: mw, h: a.bbox.h + b.bbox.h + CONFIG.FRAC_SPACING } + transform( + b, + s, + // @ts-ignore + null, + (mw - b.bbox.w * s) / 2, + a.bbox.h + CONFIG.FRAC_SPACING + ) + expr.bbox = { + x: 0, + y: -a.bbox.h + 1 - CONFIG.FRAC_SPACING / 2, + w: mw, + h: a.bbox.h + b.bbox.h + CONFIG.FRAC_SPACING + } } else if (expr.text == '\\binom') { const a: Expr = expr.chld[0] const b: Expr = expr.chld[1] @@ -548,20 +600,22 @@ function plan(expr: Expr, mode = 'math'): void { } // @ts-ignore transform(e, 1, null, 1 + pl, 0.5) - expr.bbox = { x: 0, y: 2 - e.bbox.h - 0.5, w: e.bbox.w + 1 + pl, h: e.bbox.h + 0.5 } - + expr.bbox = { + x: 0, + y: 2 - e.bbox.h - 0.5, + w: e.bbox.w + 1 + pl, + h: e.bbox.h + 0.5 + } } else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) { const e: Expr = expr.chld[0] plan(e) const y0 = e.bbox.y - 0.5 e.bbox.y = 0.5 expr.bbox = { x: 0, y: y0, w: e.bbox.w, h: e.bbox.h + 0.5 } - } else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) { const e: Expr = expr.chld[0] plan(e) expr.bbox = { x: 0, y: 0, w: e.bbox.w, h: e.bbox.h + 0.5 } - } else { let dx = 0 let dy = 0 @@ -569,13 +623,14 @@ function plan(expr: Expr, mode = 'math'): void { for (let i = 0; i < expr.chld.length; i++) { const c: Expr = expr.chld[i] // @ts-ignore - const spac: number = { - '\\quad': 2, - '\\,': 2 * 3 / 18, - '\\:': 2 * 4 / 18, - '\\;': 2 * 5 / 18, - '\\!': 2 * (-3) / 18, - }[c.text] ?? null + const spac: number = + { + '\\quad': 2, + '\\,': (2 * 3) / 18, + '\\:': (2 * 4) / 18, + '\\;': (2 * 5) / 18, + '\\!': (2 * -3) / 18 + }[c.text] ?? null if (c.text == '\\\\') { dy += mh @@ -593,10 +648,16 @@ function plan(expr: Expr, mode = 'math'): void { transform(c, 1, null, dx, dy) if (c.text == '^' || c.text == '_' || c.text == '\'') { let j: number = i - while (j > 0 && (expr.chld[j].text == '^' || expr.chld[j].text == '_' || expr.chld[j].text == '\'')) { + while ( + j > 0 && + (expr.chld[j].text == '^' || + expr.chld[j].text == '_' || + expr.chld[j].text == '\'') + ) { j-- } - const wasBig = SYMB[expr.chld[j].text] && SYMB[expr.chld[j].text].flags.big + const wasBig = + SYMB[expr.chld[j].text] && SYMB[expr.chld[j].text].flags.big if (c.text == '\'') { let k = j + 1 let nth = 0 @@ -606,13 +667,21 @@ function plan(expr: Expr, mode = 'math'): void { } k++ } - c.bbox.x = expr.chld[j].bbox.x + expr.chld[j].bbox.w + c.bbox.w * nth + c.bbox.x = + expr.chld[j].bbox.x + expr.chld[j].bbox.w + c.bbox.w * nth dx = Math.max(dx, c.bbox.x + c.bbox.w) } else { if (wasBig) { - const ex = expr.chld[j].bbox.x + (expr.chld[j].bbox.w - c.bbox.w * CONFIG.SUB_SUP_SCALE) / 2 + const ex = + expr.chld[j].bbox.x + + (expr.chld[j].bbox.w - c.bbox.w * CONFIG.SUB_SUP_SCALE) / 2 c.bbox.x = ex - dx = Math.max(dx, expr.chld[j].bbox.x + expr.chld[j].bbox.w + (c.bbox.w * CONFIG.SUB_SUP_SCALE - expr.chld[j].bbox.w) / 2) + dx = Math.max( + dx, + expr.chld[j].bbox.x + + expr.chld[j].bbox.w + + (c.bbox.w * CONFIG.SUB_SUP_SCALE - expr.chld[j].bbox.w) / 2 + ) } else { c.bbox.x = expr.chld[j].bbox.x + expr.chld[j].bbox.w dx = Math.max(dx, c.bbox.x + c.bbox.w * CONFIG.SUB_SUP_SCALE) @@ -629,19 +698,20 @@ function plan(expr: Expr, mode = 'math'): void { } dy += mh const m2s: Record = { - 'bmatrix': ['[', ']'], - 'pmatrix': ['(', ')'], - 'Bmatrix': ['\\{', '\\}'], - 'cases': ['\\{'] + bmatrix: ['[', ']'], + pmatrix: ['(', ')'], + Bmatrix: ['\\{', '\\}'], + cases: ['\\{'] } - const alt: string = { - 'bmatrix': 'center', - 'pmatrix': 'center', - 'Bmatrix': 'center', - 'cases': 'left', - 'matrix': 'center', - 'aligned': 'equation', - }[expr.text] ?? 'left' + const alt: string = + { + bmatrix: 'center', + pmatrix: 'center', + Bmatrix: 'center', + cases: 'left', + matrix: 'center', + aligned: 'equation' + }[expr.text] ?? 'left' const hasLp = !!m2s[expr.text] const hasRp = !!m2s[expr.text] && m2s[expr.text].length > 1 @@ -657,16 +727,29 @@ function plan(expr: Expr, mode = 'math'): void { // @ts-ignore transform(expr.chld[i], 1, null, -bb.x + (hasLp ? 1.5 : 0), -bb.y) } - expr.bbox = { x: 0, y: 0, w: bb.w + 1.5 * Number(hasLp) + 1.5 * Number(hasRp), h: bb.h } + expr.bbox = { + x: 0, + y: 0, + w: bb.w + 1.5 * Number(hasLp) + 1.5 * Number(hasRp), + h: bb.h + } if (hasLp) { expr.chld.unshift({ - type: 'symb', text: m2s[expr.text][0], mode: expr.mode, chld: [], bbox: { x: 0, y: 0, w: 1, h: bb.h } + type: 'symb', + text: m2s[expr.text][0], + mode: expr.mode, + chld: [], + bbox: { x: 0, y: 0, w: 1, h: bb.h } }) } if (hasRp) { expr.chld.push({ - type: 'symb', text: m2s[expr.text][1], mode: expr.mode, chld: [], bbox: { x: bb.w + 2, y: 0, w: 1, h: bb.h } + type: 'symb', + text: m2s[expr.text][1], + mode: expr.mode, + chld: [], + bbox: { x: bb.w + 2, y: 0, w: 1, h: bb.h } }) } if (hasLp || hasRp || expr.text == 'matrix') { @@ -684,7 +767,8 @@ function flatten(expr: Expr) { dx += expr.bbox.x dy += expr.bbox.y if (expr.text == '\\frac') { - const h: number = expr.chld[1].bbox.y - (expr.chld[0].bbox.y + expr.chld[0].bbox.h) + const h: number = + expr.chld[1].bbox.y - (expr.chld[0].bbox.y + expr.chld[0].bbox.h) const e: Expr = { type: 'symb', mode: expr.mode, @@ -693,13 +777,17 @@ function flatten(expr: Expr) { x: dx, y: dy + (expr.chld[1].bbox.y - h / 2) - h / 2, w: expr.bbox.w, - h: h, - }, chld: [], + h: h + }, + chld: [] } ff.push(e) } else if (expr.text == '\\sqrt') { const h: number = expr.chld[0].bbox.y - const xx: number = Math.max(0, expr.chld[0].bbox.x - expr.chld[0].bbox.h / 2) + const xx: number = Math.max( + 0, + expr.chld[0].bbox.x - expr.chld[0].bbox.h / 2 + ) const e: Expr = { type: 'symb', mode: expr.mode, @@ -708,8 +796,9 @@ function flatten(expr: Expr) { x: dx + xx, y: dy + h / 2, w: expr.chld[0].bbox.x - xx, - h: expr.bbox.h - h / 2, - }, chld: [], + h: expr.bbox.h - h / 2 + }, + chld: [] } ff.push(e) ff.push({ @@ -720,8 +809,9 @@ function flatten(expr: Expr) { x: dx + expr.chld[0].bbox.x, y: dy, w: expr.bbox.w - expr.chld[0].bbox.x, - h: h, - }, chld: [], + h: h + }, + chld: [] }) } else if (expr.text == '\\binom') { const w = Math.min(expr.chld[0].bbox.x, expr.chld[1].bbox.x) @@ -733,8 +823,9 @@ function flatten(expr: Expr) { x: dx, y: dy, w: w, - h: expr.bbox.h, - }, chld: [], + h: expr.bbox.h + }, + chld: [] } ff.push(e) ff.push({ @@ -745,8 +836,9 @@ function flatten(expr: Expr) { x: dx + expr.bbox.w - w, y: dy, w: w, - h: expr.bbox.h, - }, chld: [], + h: expr.bbox.h + }, + chld: [] }) } else if (SYMB[expr.text] && SYMB[expr.text].flags.hat) { const h: number = expr.chld[0].bbox.y @@ -758,8 +850,9 @@ function flatten(expr: Expr) { x: dx, y: dy, w: expr.bbox.w, - h: h, - }, chld: [], + h: h + }, + chld: [] } ff.push(e) } else if (SYMB[expr.text] && SYMB[expr.text].flags.mat) { @@ -772,21 +865,23 @@ function flatten(expr: Expr) { x: dx, y: dy + h, w: expr.bbox.w, - h: expr.bbox.h - h, - }, chld: [], + h: expr.bbox.h - h + }, + chld: [] } ff.push(e) - } else if (expr.type != 'node' - && expr.text != '^' - && expr.text != '_' - ) { + } else if (expr.type != 'node' && expr.text != '^' && expr.text != '_') { const e: Expr = { - type: expr.type == 'func' ? 'symb' : expr.type, text: expr.text, mode: expr.mode, bbox: { + type: expr.type == 'func' ? 'symb' : expr.type, + text: expr.text, + mode: expr.mode, + bbox: { x: dx, y: dy, w: expr.bbox.w, h: expr.bbox.h - }, chld: [], + }, + chld: [] } ff.push(e) } @@ -809,8 +904,12 @@ function render(expr: Expr): number[][][] { const e: Expr = expr.chld[i] let s = e.bbox.h / 2 let isSmallHat = false - if (SYMB[e.text] && SYMB[e.text].flags.hat && - !SYMB[e.text].flags.xfl && !SYMB[e.text].flags.yfl) { + if ( + SYMB[e.text] && + SYMB[e.text].flags.hat && + !SYMB[e.text].flags.xfl && + !SYMB[e.text].flags.yfl + ) { s *= 4 isSmallHat = true } @@ -824,25 +923,24 @@ function render(expr: Expr): number[][][] { let y = d.polylines[j][k][1] if (SYMB[e.text].flags.xfl) { - x = (x - d.xmin) / Math.max(d.xmax - d.xmin, 1) * e.bbox.w + x = ((x - d.xmin) / Math.max(d.xmax - d.xmin, 1)) * e.bbox.w x += e.bbox.x - } else if (d.w / 16 * s > e.bbox.w) { - x = x / Math.max(d.w, 1) * e.bbox.w + } else if ((d.w / 16) * s > e.bbox.w) { + x = (x / Math.max(d.w, 1)) * e.bbox.w x += e.bbox.x } else { - - x = x / 16 * s - const p = (e.bbox.w - d.w / 16 * s) / 2 + x = (x / 16) * s + const p = (e.bbox.w - (d.w / 16) * s) / 2 x += e.bbox.x + p } if (SYMB[e.text].flags.yfl) { - y = (y - d.ymin) / Math.max(d.ymax - d.ymin, 1) * e.bbox.h + y = ((y - d.ymin) / Math.max(d.ymax - d.ymin, 1)) * e.bbox.h y += e.bbox.y } else { - y = y / 16 * s + y = (y / 16) * s if (isSmallHat) { const p = (d.ymax + d.ymin) / 2 - y -= p / 16 * s + y -= (p / 16) * s } y += e.bbox.y + e.bbox.h / 2 } @@ -850,7 +948,7 @@ function render(expr: Expr): number[][][] { } o.push(l) } - } else if ((SYMB[e.text] && SYMB[e.text].flags.txt) || (e.type == 'char')) { + } else if ((SYMB[e.text] && SYMB[e.text].flags.txt) || e.type == 'char') { let x0 = e.bbox.x const isVerb = !!(SYMB[e.text] && SYMB[e.text].flags.txt) for (let n = Number(isVerb); n < e.text.length; n++) { @@ -874,7 +972,6 @@ function render(expr: Expr): number[][][] { } else { x += (16 - d.w) / 2 / 16 } - } x += x0 y += e.bbox.y + e.bbox.h / 2 @@ -885,7 +982,7 @@ function render(expr: Expr): number[][][] { if (e.mode == 'tt') { x0 += s } else { - x0 += d.w / 16 * s + x0 += (d.w / 16) * s } } } @@ -894,16 +991,16 @@ function render(expr: Expr): number[][][] { } interface ExportOpt { - MIN_CHAR_H?: number; - MAX_W?: number; - MAX_H?: number; - MARGIN_X?: number; - MARGIN_Y?: number; - SCALE_X?: number; - SCALE_Y?: number; - STROKE_W?: number; - FG_COLOR?: string; - BG_COLOR?: string; + MIN_CHAR_H?: number + MAX_W?: number + MAX_H?: number + MARGIN_X?: number + MARGIN_Y?: number + SCALE_X?: number + SCALE_Y?: number + STROKE_W?: number + FG_COLOR?: string + BG_COLOR?: string } function nf(x: number): number { @@ -911,16 +1008,16 @@ function nf(x: number): number { } export interface LaTexSVG { - svg: string; - width: number; - height: number; + svg: string + width: number + height: number } export class LaTexUtils { - _latex: string; - _tree: Expr; - _tokens: string[]; - _polylines: number[][][]; + _latex: string + _tree: Expr + _tokens: string[] + _polylines: number[][][] constructor(latex: string) { this._latex = latex @@ -943,9 +1040,11 @@ export class LaTexUtils { let mh = 0 for (let i = 0; i < this._tree.chld.length; i++) { const c: Expr = this._tree.chld[i] - if (c.type == 'char' || + if ( + c.type == 'char' || (SYMB[c.text] && - (SYMB[c.text].flags.txt || !Object.keys(SYMB[c.text].flags).length))) { + (SYMB[c.text].flags.txt || !Object.keys(SYMB[c.text].flags).length)) + ) { mh = Math.min(c.bbox.h, mh) } } @@ -956,12 +1055,12 @@ export class LaTexUtils { if (opt.MAX_W != undefined) { const s0 = sclx sclx = Math.min(sclx, opt.MAX_W / this._tree.bbox.w) - scly *= (sclx / s0) + scly *= sclx / s0 } if (opt.MAX_H != undefined) { const s0 = scly scly = Math.min(scly, opt.MAX_H / this._tree.bbox.h) - sclx *= (scly / s0) + sclx *= scly / s0 } const px: number = opt.MARGIN_X ?? sclx const py: number = opt.MARGIN_Y ?? scly @@ -989,7 +1088,7 @@ export class LaTexUtils { for (let i = 0; i < this._polylines.length; i++) { for (let j = 0; j < this._polylines[i].length; j++) { const [x, y] = this._polylines[i][j] - d += (!j) ? 'M' : 'L' + d += !j ? 'M' : 'L' d += `${nf(px + x * sclx)} ${nf(py + y * scly)}` } } @@ -1004,18 +1103,22 @@ export class LaTexUtils { let o = `` if (opt.BG_COLOR) { - o += `` + o += `` } o += `` @@ -1040,10 +1143,14 @@ export class LaTexUtils { let pdf = '' let count = 4 for (let i = 0; i < this._polylines.length; i++) { - pdf += `${count} 0 obj \n<< /Length 0 >>\n stream\n 1 j 1 J ${opt.STROKE_W ?? 1} w\n` + pdf += `${count} 0 obj \n<< /Length 0 >>\n stream\n 1 j 1 J ${ + opt.STROKE_W ?? 1 + } w\n` for (let j = 0; j < this._polylines[i].length; j++) { const [x, y] = this._polylines[i][j] - pdf += `${nf(px + x * sclx)} ${nf(height - (py + y * scly))} ${j ? 'l' : 'm'} ` + pdf += `${nf(px + x * sclx)} ${nf(height - (py + y * scly))} ${ + j ? 'l' : 'm' + } ` } pdf += '\nS\nendstream\nendobj\n' head += `${count} 0 R ` @@ -1077,6 +1184,13 @@ export class LaTexUtils { } } -const _impl: Record = { tokenize, parse, environments, plan, flatten, render } +const _impl: Record = { + tokenize, + parse, + environments, + plan, + flatten, + render +} -export { CONFIG, _impl } \ No newline at end of file +export { CONFIG, _impl } diff --git a/src/editor/core/draw/particle/latex/utils/hershey.ts b/src/editor/core/draw/particle/latex/utils/hershey.ts index efe4115..159347d 100644 --- a/src/editor/core/draw/particle/latex/utils/hershey.ts +++ b/src/editor/core/draw/particle/latex/utils/hershey.ts @@ -1,10 +1,10 @@ interface HersheyEntry { - w: number; - xmin: number; - xmax: number; - ymin: number; - ymax: number; - polylines: Array>>; + w: number + xmin: number + xmax: number + ymin: number + ymax: number + polylines: Array>> } const ordR = 'R'.charCodeAt(0) @@ -53,7 +53,7 @@ function compile(i: number): void { xmax: zmax, ymin: ymin, ymax: ymax, - polylines: polylines, + polylines: polylines } } const data: Record = {} @@ -1628,5 +1628,5 @@ const raw: Record = { 3923: ' 59E_HMIOIXM[OYQX RINJOJXMZ RHMJNKOKWNYOY RRMPOQPQXU[WY[W RRPSORNQORPRXUZ RRMTOSPSWVYWY RZM\\O[P[W RZP[OZNYOZPZW RZMXOYPYX', 3924: ' 39I[LONPUZV[XY RMNOOUYWZ RLONMONVXXY RXMVMVOXOXMVOSS RQUNYL[N[NYLYL[ RNTQT RSTVT', 3925: ' 49I[KOLOMPMYP[UY RMNNONYPZ RKOMMOOOXRZ RVMXOWPW]V_U`SaQaO`MaObQa RVPWOVNUOVPV^U_ RPaNa RVMTOUPU^T`Sa', - 3926: ' 43L[RNOPOORNTMWOWSRU RTNVOVS RRNUPUSTT RRUWWW]V_U`SaQaO`MaObQa RVWV^U_ RPaNa RTVUWU^T`Sa', -} \ No newline at end of file + 3926: ' 43L[RNOPOORNTMWOWSRU RTNVOVS RRNUPUSTT RRUWWW]V_U`SaQaO`MaObQa RVWV^U_ RPaNa RTVUWU^T`Sa' +} diff --git a/src/editor/core/draw/particle/latex/utils/symbols.ts b/src/editor/core/draw/particle/latex/utils/symbols.ts index b01e0b9..59fbc2b 100644 --- a/src/editor/core/draw/particle/latex/utils/symbols.ts +++ b/src/editor/core/draw/particle/latex/utils/symbols.ts @@ -3,17 +3,21 @@ https://oeis.org/wiki/List_of_LaTeX_mathematical_symbols https://en.wikibooks.org/wiki/LaTeX/Mathematics */ export interface Symb { - glyph: number; - arity?: number; - flags: Record; + glyph: number + arity?: number + flags: Record } const SYMB: Record = { '\\frac': { glyph: 0, arity: 2, flags: {} }, '\\binom': { glyph: 0, arity: 2, flags: {} }, - '\\sqrt': { glyph: 2267, arity: 1, flags: { opt: true, xfl: true, yfl: true } }, + '\\sqrt': { + glyph: 2267, + arity: 1, + flags: { opt: true, xfl: true, yfl: true } + }, '^': { glyph: 0, arity: 1, flags: {} }, - '_': { glyph: 0, arity: 1, flags: {} }, + _: { glyph: 0, arity: 1, flags: {} }, '(': { glyph: 2221, arity: 0, flags: { yfl: true } }, ')': { glyph: 2222, arity: 0, flags: { yfl: true } }, '[': { glyph: 2223, arity: 0, flags: { yfl: true } }, @@ -56,12 +60,28 @@ const SYMB: Record = { '\\ell': { glyph: 662, arity: 0, flags: {} }, /*accents*/ - '\\vec': { glyph: 2261, arity: 1, flags: { hat: true, xfl: true, yfl: true } }, - '\\overrightarrow': { glyph: 2261, arity: 1, flags: { hat: true, xfl: true, yfl: true } }, - '\\overleftarrow': { glyph: 2263, arity: 1, flags: { hat: true, xfl: true, yfl: true } }, + '\\vec': { + glyph: 2261, + arity: 1, + flags: { hat: true, xfl: true, yfl: true } + }, + '\\overrightarrow': { + glyph: 2261, + arity: 1, + flags: { hat: true, xfl: true, yfl: true } + }, + '\\overleftarrow': { + glyph: 2263, + arity: 1, + flags: { hat: true, xfl: true, yfl: true } + }, '\\bar': { glyph: 2231, arity: 1, flags: { hat: true, xfl: true } }, '\\overline': { glyph: 2231, arity: 1, flags: { hat: true, xfl: true } }, - '\\widehat': { glyph: 2247, arity: 1, flags: { hat: true, xfl: true, yfl: true } }, + '\\widehat': { + glyph: 2247, + arity: 1, + flags: { hat: true, xfl: true, yfl: true } + }, '\\hat': { glyph: 2247, arity: 1, flags: { hat: true } }, '\\acute': { glyph: 2248, arity: 1, flags: { hat: true } }, '\\grave': { glyph: 2249, arity: 1, flags: { hat: true } }, @@ -219,7 +239,7 @@ const SYMB: Record = { '\\Phi': { glyph: 2047, flags: {} }, '\\Chi': { glyph: 2048, flags: {} }, '\\Psi': { glyph: 2049, flags: {} }, - '\\Omega': { glyph: 2050, flags: {} }, + '\\Omega': { glyph: 2050, flags: {} } } export { SYMB } @@ -293,6 +313,6 @@ export function asciiMap(x: string, mode = 'math'): number { '>': 2242, '~': 2246, '@': 2273, - '\\': 804, + '\\': 804 }[x] } diff --git a/src/editor/core/draw/particle/previewer/Previewer.ts b/src/editor/core/draw/particle/previewer/Previewer.ts index 84b3a78..17a9b79 100644 --- a/src/editor/core/draw/particle/previewer/Previewer.ts +++ b/src/editor/core/draw/particle/previewer/Previewer.ts @@ -1,12 +1,14 @@ import { EDITOR_PREFIX } from '../../../../dataset/constant/Editor' import { IEditorOption } from '../../../../interface/Editor' import { IElement, IElementPosition } from '../../../../interface/Element' -import { IPreviewerCreateResult, IPreviewerDrawOption } from '../../../../interface/Previewer' +import { + IPreviewerCreateResult, + IPreviewerDrawOption +} from '../../../../interface/Previewer' import { downloadFile } from '../../../../utils' import { Draw } from '../../Draw' export class Previewer { - private container: HTMLDivElement private canvas: HTMLCanvasElement private draw: Draw @@ -39,7 +41,12 @@ export class Previewer { this.previewerDrawOption = {} this.curPosition = null // 图片尺寸缩放 - const { resizerSelection, resizerHandleList, resizerImageContainer, resizerImage } = this._createResizerDom() + const { + resizerSelection, + resizerHandleList, + resizerImageContainer, + resizerImage + } = this._createResizerDom() this.resizerSelection = resizerSelection this.resizerHandleList = resizerHandleList this.resizerImageContainer = resizerImageContainer @@ -79,7 +86,12 @@ export class Previewer { const resizerImage = document.createElement('img') resizerImageContainer.append(resizerImage) this.container.append(resizerImageContainer) - return { resizerSelection, resizerHandleList, resizerImageContainer, resizerImage } + return { + resizerSelection, + resizerHandleList, + resizerImageContainer, + resizerImage + } } private _keydown = () => { @@ -107,7 +119,11 @@ export class Previewer { // 拖拽图片镜像 this.resizerImage.src = this.curElementSrc this.resizerImageContainer.style.display = 'block' - const { coordinate: { leftTop: [left, top] } } = this.curPosition + const { + coordinate: { + leftTop: [left, top] + } + } = this.curPosition const prePageHeight = this.draw.getPageNo() * (height + pageGap) this.resizerImageContainer.style.left = `${left}px` this.resizerImageContainer.style.top = `${top + prePageHeight}px` @@ -116,22 +132,30 @@ export class Previewer { // 追加全局事件 const mousemoveFn = this._mousemove.bind(this) document.addEventListener('mousemove', mousemoveFn) - document.addEventListener('mouseup', () => { - // 改变尺寸 - if (this.curElement && this.curPosition) { - this.curElement.width = this.width - this.curElement.height = this.height - this.draw.render({ isSetCursor: false }) - this.drawResizer(this.curElement, this.curPosition, this.previewerDrawOption) + document.addEventListener( + 'mouseup', + () => { + // 改变尺寸 + if (this.curElement && this.curPosition) { + this.curElement.width = this.width + this.curElement.height = this.height + this.draw.render({ isSetCursor: false }) + this.drawResizer( + this.curElement, + this.curPosition, + this.previewerDrawOption + ) + } + // 还原副作用 + this.resizerImageContainer.style.display = 'none' + document.removeEventListener('mousemove', mousemoveFn) + document.body.style.cursor = '' + this.canvas.style.cursor = 'text' + }, + { + once: true } - // 还原副作用 - this.resizerImageContainer.style.display = 'none' - document.removeEventListener('mousemove', mousemoveFn) - document.body.style.cursor = '' - this.canvas.style.cursor = 'text' - }, { - once: true - }) + ) evt.preventDefault() } @@ -254,7 +278,7 @@ export class Previewer { let startX = 0 let startY = 0 let isAllowDrag = false - img.onmousedown = (evt) => { + img.onmousedown = evt => { isAllowDrag = true startX = evt.x startY = evt.y @@ -262,8 +286,8 @@ export class Previewer { } previewerContainer.onmousemove = (evt: MouseEvent) => { if (!isAllowDrag) return - x += (evt.x - startX) - y += (evt.y - startY) + x += evt.x - startX + y += evt.y - startY startX = evt.x startY = evt.y this._setPreviewerTransform(scaleSize, rotateSize, x, y) @@ -272,7 +296,7 @@ export class Previewer { isAllowDrag = false previewerContainer.style.cursor = 'auto' } - previewerContainer.onwheel = (evt) => { + previewerContainer.onwheel = evt => { evt.preventDefault() if (evt.deltaY < 0) { // 放大 @@ -286,11 +310,18 @@ export class Previewer { } } - public _setPreviewerTransform(scale: number, rotate: number, x: number, y: number) { + public _setPreviewerTransform( + scale: number, + rotate: number, + x: number, + y: number + ) { if (!this.previewerImage) return this.previewerImage.style.left = `${x}px` this.previewerImage.style.top = `${y}px` - this.previewerImage.style.transform = `scale(${scale}) rotate(${rotate * 90}deg)` + this.previewerImage.style.transform = `scale(${scale}) rotate(${ + rotate * 90 + }deg)` } private _clearPreviewer() { @@ -299,10 +330,19 @@ export class Previewer { document.body.style.overflow = 'auto' } - public drawResizer(element: IElement, position: IElementPosition, options: IPreviewerDrawOption = {}) { + public drawResizer( + element: IElement, + position: IElementPosition, + options: IPreviewerDrawOption = {} + ) { this.previewerDrawOption = options const { scale } = this.options - const { coordinate: { leftTop: [left, top] }, ascent } = position + const { + coordinate: { + leftTop: [left, top] + }, + ascent + } = position const elementWidth = element.width! * scale const elementHeight = element.height! * scale const height = this.draw.getHeight() @@ -316,14 +356,16 @@ export class Previewer { this.resizerSelection.style.height = `${elementHeight}px` // handle for (let i = 0; i < 8; i++) { - const left = i === 0 || i === 6 || i === 7 - ? -handleSize - : i === 1 || i === 5 + const left = + i === 0 || i === 6 || i === 7 + ? -handleSize + : i === 1 || i === 5 ? elementWidth / 2 : elementWidth - handleSize - const top = i === 0 || i === 1 || i === 2 - ? -handleSize - : i === 3 || i === 7 + const top = + i === 0 || i === 1 || i === 2 + ? -handleSize + : i === 3 || i === 7 ? elementHeight / 2 - handleSize : elementHeight - handleSize this.resizerHandleList[i].style.left = `${left}px` @@ -342,5 +384,4 @@ export class Previewer { this.resizerSelection.style.display = 'none' document.removeEventListener('keydown', this._keydown) } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/table/TableParticle.ts b/src/editor/core/draw/particle/table/TableParticle.ts index 20b81d2..0ebf996 100644 --- a/src/editor/core/draw/particle/table/TableParticle.ts +++ b/src/editor/core/draw/particle/table/TableParticle.ts @@ -7,16 +7,15 @@ import { RangeManager } from '../../../range/RangeManager' import { Draw } from '../../Draw' interface IDrawTableBorderOption { - ctx: CanvasRenderingContext2D; - startX: number; - startY: number; - width: number; - height: number; - isDrawFullBorder?: boolean; + ctx: CanvasRenderingContext2D + startX: number + startY: number + width: number + height: number + isDrawFullBorder?: boolean } export class TableParticle { - private draw: Draw private range: RangeManager private options: Required @@ -45,9 +44,17 @@ export class TableParticle { } public getRangeRowCol(): ITd[][] | null { - const { isTable, index, trIndex, tdIndex } = this.draw.getPosition().getPositionContext() + const { isTable, index, trIndex, tdIndex } = this.draw + .getPosition() + .getPositionContext() if (!isTable) return null - const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange() + const { + isCrossRowCol, + startTdIndex, + endTdIndex, + startTrIndex, + endTrIndex + } = this.range.getRange() const originalElementList = this.draw.getOriginalElementList() const element = originalElementList[index!] const curTrList = element.trList! @@ -59,6 +66,7 @@ export class TableParticle { let endTd = curTrList[endTrIndex!].tdList[endTdIndex!] // 交换起始位置 if (startTd.x! > endTd.x! || startTd.y! > endTd.y!) { + // prettier-ignore [startTd, endTd] = [endTd, startTd] } const startColIndex = startTd.colIndex! @@ -75,8 +83,10 @@ export class TableParticle { const tdColIndex = td.colIndex! const tdRowIndex = td.rowIndex! if ( - tdColIndex >= startColIndex && tdColIndex <= endColIndex - && tdRowIndex >= startRowIndex && tdRowIndex <= endRowIndex + tdColIndex >= startColIndex && + tdColIndex <= endColIndex && + tdRowIndex >= startRowIndex && + tdRowIndex <= endRowIndex ) { tdList.push(td) } @@ -105,7 +115,12 @@ export class TableParticle { ctx.translate(-0.5, -0.5) } - private _drawBorder(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) { + private _drawBorder( + ctx: CanvasRenderingContext2D, + element: IElement, + startX: number, + startY: number + ) { const { colgroup, trList, borderType } = element if (!colgroup || !trList || borderType === TableBorder.EMPTY) return const { scale } = this.options @@ -146,7 +161,12 @@ export class TableParticle { ctx.restore() } - private _drawBackgroundColor(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) { + private _drawBackgroundColor( + ctx: CanvasRenderingContext2D, + element: IElement, + startX: number, + startY: number + ) { const { trList } = element if (!trList) return const { scale } = this.options @@ -259,11 +279,22 @@ export class TableParticle { } } - public drawRange(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) { + public drawRange( + ctx: CanvasRenderingContext2D, + element: IElement, + startX: number, + startY: number + ) { const { scale, rangeAlpha, rangeColor } = this.options const { type, trList } = element if (!trList || type !== ElementType.TABLE) return - const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange() + const { + isCrossRowCol, + startTdIndex, + endTdIndex, + startTrIndex, + endTrIndex + } = this.range.getRange() // 存在跨行/列 if (!isCrossRowCol) return let startTd = trList[startTrIndex!].tdList[startTdIndex!] @@ -284,8 +315,10 @@ export class TableParticle { const tdColIndex = td.colIndex! const tdRowIndex = td.rowIndex! if ( - tdColIndex >= startColIndex && tdColIndex <= endColIndex - && tdRowIndex >= startRowIndex && tdRowIndex <= endRowIndex + tdColIndex >= startColIndex && + tdColIndex <= endColIndex && + tdRowIndex >= startRowIndex && + tdRowIndex <= endRowIndex ) { const x = td.x! * scale const y = td.y! * scale @@ -300,9 +333,13 @@ export class TableParticle { ctx.restore() } - public render(ctx: CanvasRenderingContext2D, element: IElement, startX: number, startY: number) { + public render( + ctx: CanvasRenderingContext2D, + element: IElement, + startX: number, + startY: number + ) { this._drawBackgroundColor(ctx, element, startX, startY) this._drawBorder(ctx, element, startX, startY) } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/particle/table/TableTool.ts b/src/editor/core/draw/particle/table/TableTool.ts index 28f8465..b31740d 100644 --- a/src/editor/core/draw/particle/table/TableTool.ts +++ b/src/editor/core/draw/particle/table/TableTool.ts @@ -6,14 +6,13 @@ import { Position } from '../../../position/Position' import { Draw } from '../../Draw' interface IAnchorMouseDown { - evt: MouseEvent; - order: TableOrder; - index: number; - element: IElement; + evt: MouseEvent + order: TableOrder + index: number + element: IElement } export class TableTool { - // 单元格最小宽度 private readonly MIN_TD_WIDTH = 20 // 行列工具相对表格偏移值 @@ -58,12 +57,11 @@ export class TableTool { } public render() { - const { isTable, index, trIndex, tdIndex } = this.position.getPositionContext() + const { isTable, index, trIndex, tdIndex } = + this.position.getPositionContext() if (!isTable) return - // 销毁之前工具 this.dispose() - // 渲染所需数据 const { scale } = this.options const elementList = this.draw.getOriginalElementList() @@ -71,7 +69,9 @@ export class TableTool { const element = elementList[index!] const position = positionList[index!] const { colgroup, trList } = element - const { coordinate: { leftTop } } = position + const { + coordinate: { leftTop } + } = position const height = this.draw.getHeight() const pageGap = this.draw.getPageGap() const prePageHeight = this.draw.getPageNo() * (height + pageGap) @@ -80,12 +80,13 @@ export class TableTool { const td = element.trList![trIndex!].tdList[tdIndex!] const rowIndex = td.rowIndex const colIndex = td.colIndex - // 渲染行工具 const rowHeightList = trList!.map(tr => tr.height) const rowContainer = document.createElement('div') rowContainer.classList.add(`${EDITOR_PREFIX}-table-tool__row`) - rowContainer.style.transform = `translateX(-${this.ROW_COL_OFFSET * scale}px)` + rowContainer.style.transform = `translateX(-${ + this.ROW_COL_OFFSET * scale + }px)` for (let r = 0; r < rowHeightList.length; r++) { const rowHeight = rowHeightList[r] * scale const rowItem = document.createElement('div') @@ -95,7 +96,7 @@ export class TableTool { } const rowItemAnchor = document.createElement('div') rowItemAnchor.classList.add(`${EDITOR_PREFIX}-table-tool__anchor`) - rowItemAnchor.onmousedown = (evt) => { + rowItemAnchor.onmousedown = evt => { this._mousedown({ evt, element, @@ -116,7 +117,9 @@ export class TableTool { const colWidthList = colgroup!.map(col => col.width) const colContainer = document.createElement('div') colContainer.classList.add(`${EDITOR_PREFIX}-table-tool__col`) - colContainer.style.transform = `translateY(-${this.ROW_COL_OFFSET * scale}px)` + colContainer.style.transform = `translateY(-${ + this.ROW_COL_OFFSET * scale + }px)` for (let c = 0; c < colWidthList.length; c++) { const colWidth = colWidthList[c] * scale const colItem = document.createElement('div') @@ -126,7 +129,7 @@ export class TableTool { } const colItemAnchor = document.createElement('div') colItemAnchor.classList.add(`${EDITOR_PREFIX}-table-tool__anchor`) - colItemAnchor.onmousedown = (evt) => { + colItemAnchor.onmousedown = evt => { this._mousedown({ evt, element, @@ -160,9 +163,11 @@ export class TableTool { rowBorder.classList.add(`${EDITOR_PREFIX}-table-tool__border__row`) rowBorder.style.width = `${td.width! * scale}px` rowBorder.style.height = `${this.BORDER_VALUE}px` - rowBorder.style.top = `${(td.y! + td.height!) * scale - this.BORDER_VALUE / 2}px` + rowBorder.style.top = `${ + (td.y! + td.height!) * scale - this.BORDER_VALUE / 2 + }px` rowBorder.style.left = `${td.x! * scale}px` - rowBorder.onmousedown = (evt) => { + rowBorder.onmousedown = evt => { this._mousedown({ evt, element, @@ -176,8 +181,10 @@ export class TableTool { colBorder.style.width = `${this.BORDER_VALUE}px` colBorder.style.height = `${td.height! * scale}px` colBorder.style.top = `${td.y! * scale}px` - colBorder.style.left = `${(td.x! + td.width!) * scale - this.BORDER_VALUE / 2}px` - colBorder.onmousedown = (evt) => { + colBorder.style.left = `${ + (td.x! + td.width!) * scale - this.BORDER_VALUE / 2 + }px` + colBorder.onmousedown = evt => { this._mousedown({ evt, element, @@ -239,82 +246,95 @@ export class TableTool { } } document.addEventListener('mousemove', mousemoveFn) - document.addEventListener('mouseup', () => { - let isChangeSize = false - // 改变尺寸 - if (order === TableOrder.ROW) { - const tr = element.trList![index] - // 最大移动高度-向上移动超出最小高度限定,则减少移动量 - const { defaultTrMinHeight } = this.options - if (dy < 0 && tr.height + dy < defaultTrMinHeight) { - dy = defaultTrMinHeight - tr.height - } - if (dy) { - tr.height += dy - tr.minHeight = tr.height - isChangeSize = true - } - } else { - const { colgroup } = element - if (colgroup && dx) { - // 宽度分配 - const innerWidth = this.draw.getInnerWidth() - const curColWidth = colgroup[index].width - // 最小移动距离计算-如果向左移动:使单元格小于最小宽度,则减少移动量 - if (dx < 0 && curColWidth + dx < this.MIN_TD_WIDTH) { - dx = this.MIN_TD_WIDTH - curColWidth + document.addEventListener( + 'mouseup', + () => { + let isChangeSize = false + // 改变尺寸 + if (order === TableOrder.ROW) { + const tr = element.trList![index] + // 最大移动高度-向上移动超出最小高度限定,则减少移动量 + const { defaultTrMinHeight } = this.options + if (dy < 0 && tr.height + dy < defaultTrMinHeight) { + dy = defaultTrMinHeight - tr.height } - // 最大移动距离计算-如果向右移动:使后面一个单元格小于最小宽度,则减少移动量 - const nextColWidth = colgroup[index + 1]?.width - if (dx > 0 && nextColWidth && nextColWidth - dx < this.MIN_TD_WIDTH) { - dx = nextColWidth - this.MIN_TD_WIDTH + if (dy) { + tr.height += dy + tr.minHeight = tr.height + isChangeSize = true } - const moveColWidth = curColWidth + dx - // 开始移动 - let moveTableWidth = 0 - for (let c = 0; c < colgroup.length; c++) { - const group = colgroup[c] - // 下一列减去偏移量 - if (c === index + 1) { - moveTableWidth -= dx + } else { + const { colgroup } = element + if (colgroup && dx) { + // 宽度分配 + const innerWidth = this.draw.getInnerWidth() + const curColWidth = colgroup[index].width + // 最小移动距离计算-如果向左移动:使单元格小于最小宽度,则减少移动量 + if (dx < 0 && curColWidth + dx < this.MIN_TD_WIDTH) { + dx = this.MIN_TD_WIDTH - curColWidth } - // 当前列加上偏移量 - if (c === index) { - moveTableWidth += moveColWidth + // 最大移动距离计算-如果向右移动:使后面一个单元格小于最小宽度,则减少移动量 + const nextColWidth = colgroup[index + 1]?.width + if ( + dx > 0 && + nextColWidth && + nextColWidth - dx < this.MIN_TD_WIDTH + ) { + dx = nextColWidth - this.MIN_TD_WIDTH } - if (c !== index) { - moveTableWidth += group.width + const moveColWidth = curColWidth + dx + // 开始移动 + let moveTableWidth = 0 + for (let c = 0; c < colgroup.length; c++) { + const group = colgroup[c] + // 下一列减去偏移量 + if (c === index + 1) { + moveTableWidth -= dx + } + // 当前列加上偏移量 + if (c === index) { + moveTableWidth += moveColWidth + } + if (c !== index) { + moveTableWidth += group.width + } } - } - if (moveTableWidth > innerWidth) { - const tableWidth = element.width! - dx = innerWidth - tableWidth - } - if (dx) { - // 当前列增加,后列减少 - if (colgroup.length - 1 !== index) { - colgroup[index + 1].width -= dx / scale + if (moveTableWidth > innerWidth) { + const tableWidth = element.width! + dx = innerWidth - tableWidth + } + if (dx) { + // 当前列增加,后列减少 + if (colgroup.length - 1 !== index) { + colgroup[index + 1].width -= dx / scale + } + colgroup[index].width += dx / scale + isChangeSize = true } - colgroup[index].width += dx / scale - isChangeSize = true } } + if (isChangeSize) { + this.draw.render({ isSetCursor: false }) + } + // 还原副作用 + anchorLine.remove() + document.removeEventListener('mousemove', mousemoveFn) + document.body.style.cursor = '' + this.canvas.style.cursor = 'text' + }, + { + once: true } - if (isChangeSize) { - this.draw.render({ isSetCursor: false }) - } - // 还原副作用 - anchorLine.remove() - document.removeEventListener('mousemove', mousemoveFn) - document.body.style.cursor = '' - this.canvas.style.cursor = 'text' - }, { - once: true - }) + ) evt.preventDefault() } - private _mousemove(evt: MouseEvent, tableOrder: TableOrder, startX: number, startY: number): { dx: number; dy: number } | null { + private _mousemove( + evt: MouseEvent, + tableOrder: TableOrder, + startX: number, + startY: number + ): { dx: number; dy: number } | null { if (!this.anchorLine) return null const dx = evt.x - this.mousedownX const dy = evt.y - this.mousedownY @@ -326,5 +346,4 @@ export class TableTool { evt.preventDefault() return { dx, dy } } - } diff --git a/src/editor/core/draw/richtext/AbstractRichText.ts b/src/editor/core/draw/richtext/AbstractRichText.ts index 3cd0ebd..dcb09a6 100644 --- a/src/editor/core/draw/richtext/AbstractRichText.ts +++ b/src/editor/core/draw/richtext/AbstractRichText.ts @@ -10,15 +10,23 @@ export abstract class AbstractRichText { public clearFillInfo() { this.fillColor = undefined - return this.fillRect = { + this.fillRect = { x: 0, y: 0, width: 0, height: 0 } + return this.fillRect } - public recordFillInfo(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height?: number, color?: string) { + public recordFillInfo( + ctx: CanvasRenderingContext2D, + x: number, + y: number, + width: number, + height?: number, + color?: string + ) { const isFirstRecord = !this.fillRect.width if (!isFirstRecord && this.fillColor && this.fillColor !== color) { this.render(ctx) @@ -37,5 +45,4 @@ export abstract class AbstractRichText { } public abstract render(ctx: CanvasRenderingContext2D): void - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/richtext/Highlight.ts b/src/editor/core/draw/richtext/Highlight.ts index 19883f3..a6ad738 100644 --- a/src/editor/core/draw/richtext/Highlight.ts +++ b/src/editor/core/draw/richtext/Highlight.ts @@ -3,7 +3,6 @@ import { IEditorOption } from '../../../interface/Editor' import { Draw } from '../Draw' export class Highlight extends AbstractRichText { - private options: Required constructor(draw: Draw) { @@ -22,5 +21,4 @@ export class Highlight extends AbstractRichText { ctx.restore() this.clearFillInfo() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/richtext/Strikeout.ts b/src/editor/core/draw/richtext/Strikeout.ts index d00e382..ac371ee 100644 --- a/src/editor/core/draw/richtext/Strikeout.ts +++ b/src/editor/core/draw/richtext/Strikeout.ts @@ -3,7 +3,6 @@ import { IEditorOption } from '../../../interface/Editor' import { Draw } from '../Draw' export class Strikeout extends AbstractRichText { - private options: Required constructor(draw: Draw) { @@ -25,5 +24,4 @@ export class Strikeout extends AbstractRichText { ctx.restore() this.clearFillInfo() } - -} \ No newline at end of file +} diff --git a/src/editor/core/draw/richtext/Underline.ts b/src/editor/core/draw/richtext/Underline.ts index 020769e..19dfb04 100644 --- a/src/editor/core/draw/richtext/Underline.ts +++ b/src/editor/core/draw/richtext/Underline.ts @@ -3,7 +3,6 @@ import { IEditorOption } from '../../../interface/Editor' import { Draw } from '../Draw' export class Underline extends AbstractRichText { - private options: Required constructor(draw: Draw) { @@ -25,5 +24,4 @@ export class Underline extends AbstractRichText { ctx.restore() this.clearFillInfo() } - -} \ No newline at end of file +} diff --git a/src/editor/core/event/CanvasEvent.ts b/src/editor/core/event/CanvasEvent.ts index 20b83be..95e49d0 100644 --- a/src/editor/core/event/CanvasEvent.ts +++ b/src/editor/core/event/CanvasEvent.ts @@ -20,14 +20,13 @@ import composition from './handlers/composition' import drag from './handlers/drag' export interface ICompositionInfo { - elementList: IElement[]; - startIndex: number; - endIndex: number; - value: string; + elementList: IElement[] + startIndex: number + endIndex: number + value: string } export class CanvasEvent { - public isAllowSelection: boolean public isComposing: boolean public compositionInfo: ICompositionInfo | null @@ -70,7 +69,10 @@ export class CanvasEvent { public register() { this.pageContainer.addEventListener('mousedown', this.mousedown.bind(this)) this.pageContainer.addEventListener('mouseup', this.mouseup.bind(this)) - this.pageContainer.addEventListener('mouseleave', this.mouseleave.bind(this)) + this.pageContainer.addEventListener( + 'mouseleave', + this.mouseleave.bind(this) + ) this.pageContainer.addEventListener('mousemove', this.mousemove.bind(this)) this.pageContainer.addEventListener('dblclick', this.dblclick.bind(this)) this.pageContainer.addEventListener('dragover', this.dragover.bind(this)) @@ -182,5 +184,4 @@ export class CanvasEvent { public dragover(evt: DragEvent | MouseEvent) { drag.dragover(evt, this) } - -} \ No newline at end of file +} diff --git a/src/editor/core/event/GlobalEvent.ts b/src/editor/core/event/GlobalEvent.ts index 671554a..4465f86 100644 --- a/src/editor/core/event/GlobalEvent.ts +++ b/src/editor/core/event/GlobalEvent.ts @@ -12,7 +12,6 @@ import { RangeManager } from '../range/RangeManager' import { CanvasEvent } from './CanvasEvent' export class GlobalEvent { - private draw: Draw private canvas: HTMLCanvasElement private options: Required @@ -38,7 +37,9 @@ export class GlobalEvent { this.hyperlinkParticle = draw.getHyperlinkParticle() this.dateParticle = draw.getDateParticle() this.control = draw.getControl() - this.dprMediaQueryList = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`) + this.dprMediaQueryList = window.matchMedia( + `(resolution: ${window.devicePixelRatio}dppx)` + ) } public register() { @@ -62,7 +63,10 @@ export class GlobalEvent { document.removeEventListener('click', this.recoverEffect) document.removeEventListener('mouseup', this.setCanvasEventAbility) document.removeEventListener('wheel', this.setPageScale) - document.removeEventListener('visibilitychange', this._handleVisibilityChange) + document.removeEventListener( + 'visibilitychange', + this._handleVisibilityChange + ) this.dprMediaQueryList.removeEventListener('change', this._handleDprChange) } @@ -78,7 +82,8 @@ export class GlobalEvent { // 编辑器外部dom const outerEditorDom = findParent( evt.target as Element, - (node: Node & Element) => !!node && node.nodeType === 1 && !!node.getAttribute(EDITOR_COMPONENT), + (node: Node & Element) => + !!node && node.nodeType === 1 && !!node.getAttribute(EDITOR_COMPONENT), true ) if (outerEditorDom) { @@ -149,5 +154,4 @@ export class GlobalEvent { private _handleDprChange = () => { this.draw.setPageDevicePixel() } - -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/click.ts b/src/editor/core/event/handlers/click.ts index bde2cd1..c017069 100644 --- a/src/editor/core/event/handlers/click.ts +++ b/src/editor/core/event/handlers/click.ts @@ -30,7 +30,10 @@ function dblclick(host: CanvasEvent, evt: MouseEvent) { let upStartIndex = index - 1 while (upStartIndex > 0) { const value = elementList[upStartIndex].value - if ((isNumber && NUMBER_LIKE_REG.test(value)) || (!isNumber && LETTER_REG.test(value))) { + if ( + (isNumber && NUMBER_LIKE_REG.test(value)) || + (!isNumber && LETTER_REG.test(value)) + ) { upCount++ upStartIndex-- } else { @@ -41,7 +44,10 @@ function dblclick(host: CanvasEvent, evt: MouseEvent) { let downStartIndex = index + 1 while (downStartIndex < elementList.length) { const value = elementList[downStartIndex].value - if ((isNumber && NUMBER_LIKE_REG.test(value)) || (!isNumber && LETTER_REG.test(value))) { + if ( + (isNumber && NUMBER_LIKE_REG.test(value)) || + (!isNumber && LETTER_REG.test(value)) + ) { downCount++ downStartIndex++ } else { @@ -106,4 +112,4 @@ function threeClick(host: CanvasEvent) { export default { dblclick, threeClick -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/composition.ts b/src/editor/core/event/handlers/composition.ts index 9dac74c..8399809 100644 --- a/src/editor/core/event/handlers/composition.ts +++ b/src/editor/core/event/handlers/composition.ts @@ -34,4 +34,4 @@ function compositionend(host: CanvasEvent, evt: CompositionEvent) { export default { compositionstart, compositionend -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/copy.ts b/src/editor/core/event/handlers/copy.ts index a83bf5a..5cfc15e 100644 --- a/src/editor/core/event/handlers/copy.ts +++ b/src/editor/core/event/handlers/copy.ts @@ -10,4 +10,4 @@ export function copy(host: CanvasEvent) { const elementList = draw.getElementList() writeElementList(elementList.slice(startIndex + 1, endIndex + 1), options) } -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/cut.ts b/src/editor/core/event/handlers/cut.ts index 53272b0..7196c6b 100644 --- a/src/editor/core/event/handlers/cut.ts +++ b/src/editor/core/event/handlers/cut.ts @@ -46,4 +46,4 @@ export function cut(host: CanvasEvent) { } rangeManager.setRange(curIndex, curIndex) draw.render({ curIndex }) -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/drag.ts b/src/editor/core/event/handlers/drag.ts index 83225b9..2204b15 100644 --- a/src/editor/core/event/handlers/drag.ts +++ b/src/editor/core/event/handlers/drag.ts @@ -36,7 +36,9 @@ function dragover(evt: DragEvent | MouseEvent, host: CanvasEvent) { position.setCursorPosition(positionList[curIndex]) } const cursor = draw.getCursor() - const { cursor: { dragColor, dragWidth } } = draw.getOptions() + const { + cursor: { dragColor, dragWidth } + } = draw.getOptions() cursor.drawCursor({ width: dragWidth, color: dragColor, @@ -46,4 +48,4 @@ function dragover(evt: DragEvent | MouseEvent, host: CanvasEvent) { export default { dragover -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/drop.ts b/src/editor/core/event/handlers/drop.ts index 12435a2..c0b8309 100644 --- a/src/editor/core/event/handlers/drop.ts +++ b/src/editor/core/event/handlers/drop.ts @@ -6,4 +6,4 @@ export function drop(evt: DragEvent, host: CanvasEvent) { if (data) { host.input(data) } -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/input.ts b/src/editor/core/event/handlers/input.ts index 8241de6..a5451f4 100644 --- a/src/editor/core/event/handlers/input.ts +++ b/src/editor/core/event/handlers/input.ts @@ -42,12 +42,12 @@ export function input(data: string, host: CanvasEvent) { } const nextElement = elementList[endIndex + 1] if ( - copyElement.type === TEXT - || (!copyElement.type && copyElement.value !== ZERO) - || (copyElement.type === HYPERLINK && nextElement?.type === HYPERLINK) - || (copyElement.type === DATE && nextElement?.type === DATE) - || (copyElement.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT) - || (copyElement.type === SUPERSCRIPT && nextElement?.type === SUPERSCRIPT) + copyElement.type === TEXT || + (!copyElement.type && copyElement.value !== ZERO) || + (copyElement.type === HYPERLINK && nextElement?.type === HYPERLINK) || + (copyElement.type === DATE && nextElement?.type === DATE) || + (copyElement.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT) || + (copyElement.type === SUPERSCRIPT && nextElement?.type === SUPERSCRIPT) ) { EDITOR_ELEMENT_COPY_ATTR.forEach(attr => { const value = copyElement[attr] as never @@ -98,4 +98,4 @@ export function removeComposingInput(host: CanvasEvent) { const rangeManager = host.getDraw().getRange() rangeManager.setRange(startIndex, startIndex) host.compositionInfo = null -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/keydown.ts b/src/editor/core/event/handlers/keydown.ts index 79bf51d..4ad909a 100644 --- a/src/editor/core/event/handlers/keydown.ts +++ b/src/editor/core/event/handlers/keydown.ts @@ -47,7 +47,11 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { }) } if (!isCollapsed) { - draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex) + draw.spliceElementList( + elementList, + startIndex + 1, + endIndex - startIndex + ) } else { draw.spliceElementList(elementList, index, 1) } @@ -64,7 +68,11 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { curIndex = control.removeControl(endIndex + 1) } else { if (!isCollapsed) { - draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex) + draw.spliceElementList( + elementList, + startIndex + 1, + endIndex - startIndex + ) } else { draw.spliceElementList(elementList, index + 1, 1) } @@ -84,7 +92,12 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { enterText.listWrap = true } // 标题结尾处回车无需格式化 - if (!(endElement.titleId && endElement.titleId !== elementList[endIndex + 1]?.titleId)) { + if ( + !( + endElement.titleId && + endElement.titleId !== elementList[endIndex + 1]?.titleId + ) + ) { formatElementContext(elementList, [enterText], startIndex) } let curIndex: number @@ -94,7 +107,12 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { if (isCollapsed) { draw.spliceElementList(elementList, index + 1, 0, enterText) } else { - draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex, enterText) + draw.spliceElementList( + elementList, + startIndex + 1, + endIndex - startIndex, + enterText + ) } curIndex = index + 1 } @@ -159,7 +177,12 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { } } const maxElementListIndex = elementList.length - 1 - if (anchorStartIndex > maxElementListIndex || anchorEndIndex > maxElementListIndex) return + if ( + anchorStartIndex > maxElementListIndex || + anchorEndIndex > maxElementListIndex + ) { + return + } rangeManager.setRange(anchorStartIndex, anchorEndIndex) const isCollapsed = anchorStartIndex === anchorEndIndex draw.render({ @@ -181,21 +204,31 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { anchorPosition = positionList[startIndex] } } - const { rowNo, index, pageNo, coordinate: { leftTop, rightTop } } = anchorPosition + const { + rowNo, + index, + pageNo, + coordinate: { leftTop, rightTop } + } = anchorPosition if ((isUp && rowNo !== 0) || (!isUp && rowNo !== draw.getRowCount())) { // 下一个光标点所在行位置集合 const probablePosition = isUp - ? positionList.slice(0, index) - .filter(p => p.rowNo === rowNo - 1 && pageNo === p.pageNo) - : positionList.slice(index, positionList.length - 1) - .filter(p => p.rowNo === rowNo + 1 && pageNo === p.pageNo) + ? positionList + .slice(0, index) + .filter(p => p.rowNo === rowNo - 1 && pageNo === p.pageNo) + : positionList + .slice(index, positionList.length - 1) + .filter(p => p.rowNo === rowNo + 1 && pageNo === p.pageNo) // 查找与当前位置元素点交叉最多的位置 let maxIndex = 0 let maxDistance = 0 for (let p = 0; p < probablePosition.length; p++) { const position = probablePosition[p] // 当前光标在前 - if (position.coordinate.leftTop[0] >= leftTop[0] && position.coordinate.leftTop[0] <= rightTop[0]) { + if ( + position.coordinate.leftTop[0] >= leftTop[0] && + position.coordinate.leftTop[0] <= rightTop[0] + ) { const curDistance = rightTop[0] - position.coordinate.leftTop[0] if (curDistance > maxDistance) { maxIndex = position.index @@ -204,7 +237,10 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { } } // 当前光标在后 - else if (position.coordinate.leftTop[0] <= leftTop[0] && position.coordinate.rightTop[0] >= leftTop[0]) { + else if ( + position.coordinate.leftTop[0] <= leftTop[0] && + position.coordinate.rightTop[0] >= leftTop[0] + ) { const curDistance = position.coordinate.rightTop[0] - leftTop[0] if (curDistance > maxDistance) { maxIndex = position.index @@ -237,6 +273,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { } } if (anchorStartIndex > anchorEndIndex) { + // prettier-ignore [anchorStartIndex, anchorEndIndex] = [anchorEndIndex, anchorStartIndex] } rangeManager.setRange(anchorStartIndex, anchorEndIndex) @@ -282,10 +319,12 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { } evt.preventDefault() } else if (evt.key === KeyMap.TAB) { - draw.insertElementList([{ - type: ElementType.TAB, - value: '' - }]) + draw.insertElementList([ + { + type: ElementType.TAB, + value: '' + } + ]) evt.preventDefault() } -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/mousedown.ts b/src/editor/core/event/handlers/mousedown.ts index 8372643..409d178 100644 --- a/src/editor/core/event/handlers/mousedown.ts +++ b/src/editor/core/event/handlers/mousedown.ts @@ -15,7 +15,10 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) { if (!host.isAllowDrag) { const range = rangeManager.getRange() if (!isReadonly && range.startIndex !== range.endIndex) { - const isPointInRange = rangeManager.getIsPointInRange(evt.offsetX, evt.offsetY) + const isPointInRange = rangeManager.getIsPointInRange( + evt.offsetX, + evt.offsetY + ) if (isPointInRange) { host.isAllowDrag = true host.cacheRange = deepClone(range) @@ -37,14 +40,8 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) { y: evt.offsetY }) if (!positionResult) return - const { - index, - isDirectHit, - isCheckbox, - isImage, - isTable, - tdValueIndex, - } = positionResult + const { index, isDirectHit, isCheckbox, isImage, isTable, tdValueIndex } = + positionResult // 记录选区开始位置 host.mouseDownStartPosition = { ...positionResult, @@ -88,13 +85,16 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) { const previewer = draw.getPreviewer() previewer.clearResizer() if (isDirectHitImage && !isReadonly) { - previewer.drawResizer(curElement, positionList[curIndex], + previewer.drawResizer( + curElement, + positionList[curIndex], curElement.type === ElementType.LATEX ? { - mime: 'svg', - srcKey: 'laTexSVG' - } - : {}) + mime: 'svg', + srcKey: 'laTexSVG' + } + : {} + ) // 光标事件代理丢失,重新定位 draw.getCursor().drawCursor({ isShow: false @@ -122,4 +122,4 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) { if (curElement.type === ElementType.DATE && !isReadonly) { dateParticle.renderDatePicker(curElement, positionList[curIndex]) } -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/mouseleave.ts b/src/editor/core/event/handlers/mouseleave.ts index a60a0ec..6d6b8f6 100644 --- a/src/editor/core/event/handlers/mouseleave.ts +++ b/src/editor/core/event/handlers/mouseleave.ts @@ -5,6 +5,8 @@ export function mouseleave(evt: MouseEvent, host: CanvasEvent) { const draw = host.getDraw() const pageContainer = draw.getPageContainer() const { x, y, width, height } = pageContainer.getBoundingClientRect() - if (evt.x >= x && evt.x <= x + width && evt.y >= y && evt.y <= y + height) return + if (evt.x >= x && evt.x <= x + width && evt.y >= y && evt.y <= y + height) { + return + } host.setIsAllowSelection(false) -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/mousemove.ts b/src/editor/core/event/handlers/mousemove.ts index 6643e30..2f00803 100644 --- a/src/editor/core/event/handlers/mousemove.ts +++ b/src/editor/core/event/handlers/mousemove.ts @@ -10,8 +10,15 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) { const { startIndex, endIndex } = host.cacheRange! const positionList = host.cachePositionList! for (let p = startIndex + 1; p <= endIndex; p++) { - const { coordinate: { leftTop, rightBottom } } = positionList[p] - if (x >= leftTop[0] && x <= rightBottom[0] && y >= leftTop[1] && y <= rightBottom[1]) { + const { + coordinate: { leftTop, rightBottom } + } = positionList[p] + if ( + x >= leftTop[0] && + x <= rightBottom[0] && + y >= leftTop[1] && + y <= rightBottom[1] + ) { return } } @@ -33,14 +40,8 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) { y: evt.offsetY }) if (!~positionResult.index) return - const { - index, - isTable, - tdValueIndex, - tdIndex, - trIndex, - tableId - } = positionResult + const { index, isTable, tdValueIndex, tdIndex, trIndex, tableId } = + positionResult const { index: startIndex, isTable: startIsTable, @@ -50,7 +51,11 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) { const endIndex = isTable ? tdValueIndex! : index // 判断是否是表格跨行/列 const rangeManager = draw.getRange() - if (isTable && startIsTable && (tdIndex !== startTdIndex || trIndex !== startTrIndex)) { + if ( + isTable && + startIsTable && + (tdIndex !== startTdIndex || trIndex !== startTrIndex) + ) { rangeManager.setRange( endIndex, endIndex, @@ -65,6 +70,7 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) { // 开始位置 let start = startIndex if (start > end) { + // prettier-ignore [start, end] = [end, start] } if (start === end) return @@ -76,4 +82,4 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) { isSetCursor: false, isCompute: false }) -} \ No newline at end of file +} diff --git a/src/editor/core/event/handlers/mouseup.ts b/src/editor/core/event/handlers/mouseup.ts index af5dda8..ad25c67 100644 --- a/src/editor/core/event/handlers/mouseup.ts +++ b/src/editor/core/event/handlers/mouseup.ts @@ -15,7 +15,7 @@ function createDragId(element: IElement): string { } function getElementIndexByDragId(dragId: string, elementList: IElement[]) { - return (elementList).findIndex((el) => el.dragId === dragId) + return (elementList).findIndex(el => el.dragId === dragId) } export function mouseup(evt: MouseEvent, host: CanvasEvent) { @@ -30,7 +30,10 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { const cachePositionList = host.cachePositionList! const range = rangeManager.getRange() // 是否需要拖拽-位置发生改变 - if (range.startIndex >= cacheRange.startIndex && range.endIndex <= cacheRange.endIndex) { + if ( + range.startIndex >= cacheRange.startIndex && + range.endIndex <= cacheRange.endIndex + ) { rangeManager.replaceRange({ ...cacheRange }) @@ -42,34 +45,29 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { return } // 是否是不可拖拽的控件结构元素 - const dragElementList = cacheElementList.slice(cacheRange.startIndex + 1, cacheRange.endIndex + 1) - const isContainControl = dragElementList.find(element => element.type === ElementType.CONTROL) + const dragElementList = cacheElementList.slice( + cacheRange.startIndex + 1, + cacheRange.endIndex + 1 + ) + const isContainControl = dragElementList.find( + element => element.type === ElementType.CONTROL + ) if (isContainControl) { // 仅允许 (最前/后元素不是控件 || 在控件前后 || 文本控件且是值) 拖拽 const cacheStartElement = cacheElementList[cacheRange.startIndex + 1] const cacheEndElement = cacheElementList[cacheRange.endIndex] const isAllowDragControl = - ( - ( - cacheStartElement.type !== ElementType.CONTROL || - cacheStartElement.controlComponent === ControlComponent.PREFIX - ) && - ( - cacheEndElement.type !== ElementType.CONTROL || - cacheEndElement.controlComponent === ControlComponent.POSTFIX - ) - ) || - ( - cacheStartElement.controlId === cacheEndElement.controlId && + ((cacheStartElement.type !== ElementType.CONTROL || + cacheStartElement.controlComponent === ControlComponent.PREFIX) && + (cacheEndElement.type !== ElementType.CONTROL || + cacheEndElement.controlComponent === ControlComponent.POSTFIX)) || + (cacheStartElement.controlId === cacheEndElement.controlId && cacheStartElement.controlComponent === ControlComponent.PREFIX && - cacheEndElement.controlComponent === ControlComponent.POSTFIX - ) || - ( - cacheStartElement.control?.type === ControlType.TEXT && + cacheEndElement.controlComponent === ControlComponent.POSTFIX) || + (cacheStartElement.control?.type === ControlType.TEXT && cacheStartElement.controlComponent === ControlComponent.VALUE && cacheEndElement.control?.type === ControlType.TEXT && - cacheEndElement.controlComponent === ControlComponent.VALUE - ) + cacheEndElement.controlComponent === ControlComponent.VALUE) if (!isAllowDragControl) { draw.render({ curIndex: range.startIndex, @@ -83,7 +81,11 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { const editorOptions = draw.getOptions() const elementList = draw.getElementList() const replaceElementList = dragElementList.map(el => { - if (!el.type || el.type === ElementType.TEXT || el.control?.type === ControlType.TEXT) { + if ( + !el.type || + el.type === ElementType.TEXT || + el.control?.type === ControlType.TEXT + ) { const newElement: IElement = { value: el.value } @@ -98,14 +100,16 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { const newElement = deepClone(el) formatElementList([newElement], { isHandleFirstElement: false, - editorOptions, + editorOptions }) return newElement } }) formatElementContext(elementList, replaceElementList, range.startIndex) // 缓存拖拽选区开始结束id - const cacheRangeStartId = createDragId(cacheElementList[cacheRange.startIndex]) + const cacheRangeStartId = createDragId( + cacheElementList[cacheRange.startIndex] + ) const cacheRangeEndId = createDragId(cacheElementList[cacheRange.endIndex]) // 设置拖拽值 const replaceLength = replaceElementList.length @@ -113,11 +117,19 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { let rangeEnd = rangeStart + replaceLength const control = draw.getControl() const activeControl = control.getActiveControl() - if (activeControl && cacheElementList[rangeStart].controlComponent !== ControlComponent.POSTFIX) { + if ( + activeControl && + cacheElementList[rangeStart].controlComponent !== ControlComponent.POSTFIX + ) { rangeEnd = activeControl.setValue(replaceElementList) rangeStart = rangeEnd - replaceLength } else { - draw.spliceElementList(elementList, rangeStart + 1, 0, ...replaceElementList) + draw.spliceElementList( + elementList, + rangeStart + 1, + 0, + ...replaceElementList + ) } if (!~rangeEnd) { draw.render({ @@ -129,10 +141,19 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { const rangeStartId = createDragId(elementList[rangeStart]) const rangeEndId = createDragId(elementList[rangeEnd]) // 删除原有拖拽元素 - const cacheRangeStartIndex = getElementIndexByDragId(cacheRangeStartId, cacheElementList) - const cacheRangeEndIndex = getElementIndexByDragId(cacheRangeEndId, cacheElementList) + const cacheRangeStartIndex = getElementIndexByDragId( + cacheRangeStartId, + cacheElementList + ) + const cacheRangeEndIndex = getElementIndexByDragId( + cacheRangeEndId, + cacheElementList + ) const cacheEndElement = cacheElementList[cacheRangeEndIndex] - if (cacheEndElement.type === ElementType.CONTROL && cacheEndElement.controlComponent !== ControlComponent.POSTFIX) { + if ( + cacheEndElement.type === ElementType.CONTROL && + cacheEndElement.controlComponent !== ControlComponent.POSTFIX + ) { rangeManager.replaceRange({ ...cacheRange, startIndex: cacheRangeStartIndex, @@ -140,7 +161,11 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { }) control.getActiveControl()?.cut() } else { - draw.spliceElementList(cacheElementList, cacheRangeStartIndex + 1, cacheRangeEndIndex - cacheRangeStartIndex) + draw.spliceElementList( + cacheElementList, + cacheRangeStartIndex + 1, + cacheRangeEndIndex - cacheRangeStartIndex + ) } // 重设上下文 const startElement = elementList[range.startIndex] @@ -186,4 +211,4 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { // 如果是允许拖拽不允许拖放则光标重置 host.mousedown(evt) } -} \ No newline at end of file +} diff --git a/src/editor/core/history/HistoryManager.ts b/src/editor/core/history/HistoryManager.ts index 371b843..402af8c 100644 --- a/src/editor/core/history/HistoryManager.ts +++ b/src/editor/core/history/HistoryManager.ts @@ -1,7 +1,6 @@ import { Draw } from '../draw/Draw' export class HistoryManager { - private undoStack: Array = [] private redoStack: Array = [] private maxRecordCount: number @@ -51,5 +50,4 @@ export class HistoryManager { this.undoStack = [] this.redoStack = [] } - -} \ No newline at end of file +} diff --git a/src/editor/core/i18n/I18n.ts b/src/editor/core/i18n/I18n.ts index aaafc08..5ba4f28 100644 --- a/src/editor/core/i18n/I18n.ts +++ b/src/editor/core/i18n/I18n.ts @@ -5,7 +5,6 @@ import { mergeObject } from '../../utils' import { DeepPartial } from '../../interface/Common' export class I18n { - private langMap: Map = new Map([ ['zhCN', zhCN], ['en', en] @@ -15,10 +14,7 @@ export class I18n { public registerLangMap(locale: string, lang: DeepPartial) { const sourceLang = this.langMap.get(locale) - this.langMap.set( - locale, - mergeObject(sourceLang || zhCN, lang) - ) + this.langMap.set(locale, mergeObject(sourceLang || zhCN, lang)) } public setLocale(locale: string) { @@ -44,5 +40,4 @@ export class I18n { } return value } - } diff --git a/src/editor/core/listener/Listener.ts b/src/editor/core/listener/Listener.ts index c92242c..27a7d69 100644 --- a/src/editor/core/listener/Listener.ts +++ b/src/editor/core/listener/Listener.ts @@ -12,7 +12,6 @@ import { } from '../../interface/Listener' export class Listener { - public rangeStyleChange: IRangeStyleChange | null public visiblePageNoListChange: IVisiblePageNoListChange | null public intersectionPageNoChange: IIntersectionPageNoChange | null @@ -36,5 +35,4 @@ export class Listener { this.pageModeChange = null this.zoneChange = null } - -} \ No newline at end of file +} diff --git a/src/editor/core/observer/ImageObserver.ts b/src/editor/core/observer/ImageObserver.ts index 589ff09..d91d839 100644 --- a/src/editor/core/observer/ImageObserver.ts +++ b/src/editor/core/observer/ImageObserver.ts @@ -1,5 +1,4 @@ export class ImageObserver { - private promiseList: Promise[] constructor() { @@ -17,5 +16,4 @@ export class ImageObserver { public allSettled() { return Promise.allSettled(this.promiseList) } - -} \ No newline at end of file +} diff --git a/src/editor/core/observer/ScrollObserver.ts b/src/editor/core/observer/ScrollObserver.ts index 794e2e4..19b0aa3 100644 --- a/src/editor/core/observer/ScrollObserver.ts +++ b/src/editor/core/observer/ScrollObserver.ts @@ -2,16 +2,15 @@ import { debounce } from '../../utils' import { Draw } from '../draw/Draw' export interface IElementVisibleInfo { - intersectionHeight: number; + intersectionHeight: number } export interface IPageVisibleInfo { - intersectionPageNo: number; - visiblePageNoList: number[]; + intersectionPageNo: number + visiblePageNoList: number[] } export class ScrollObserver { - private draw: Draw constructor(draw: Draw) { @@ -35,8 +34,12 @@ export class ScrollObserver { public getElementVisibleInfo(element: Element): IElementVisibleInfo { const rect = element.getBoundingClientRect() - const viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight) - const visibleHeight = Math.min(rect.bottom, viewHeight) - Math.max(rect.top, 0) + const viewHeight = Math.max( + document.documentElement.clientHeight, + window.innerHeight + ) + const visibleHeight = + Math.min(rect.bottom, viewHeight) - Math.max(rect.top, 0) return { intersectionHeight: visibleHeight > 0 ? visibleHeight : 0 } @@ -71,5 +74,4 @@ export class ScrollObserver { this.draw.setIntersectionPageNo(intersectionPageNo) this.draw.setVisiblePageNoList(visiblePageNoList) }, 150) - -} \ No newline at end of file +} diff --git a/src/editor/core/observer/SelectionObserver.ts b/src/editor/core/observer/SelectionObserver.ts index 6b5c838..2ab8ab7 100644 --- a/src/editor/core/observer/SelectionObserver.ts +++ b/src/editor/core/observer/SelectionObserver.ts @@ -3,11 +3,15 @@ import { Draw } from '../draw/Draw' import { RangeManager } from '../range/RangeManager' export class SelectionObserver { - // 每次滚动长度 private readonly step: number = 5 // 触发滚动阀值 - private readonly thresholdPoints: [top: number, down: number, left: number, right: number] = [70, 40, 10, 20] + private readonly thresholdPoints: [ + top: number, + down: number, + left: number, + right: number + ] = [70, 40, 10, 20] private rangeManager: RangeManager private requestAnimationFrameId: number | null @@ -74,7 +78,9 @@ export class SelectionObserver { } else { window.scrollTo(x + this.step, y) } - this.requestAnimationFrameId = window.requestAnimationFrame(this._move.bind(this, direction)) + this.requestAnimationFrameId = window.requestAnimationFrame( + this._move.bind(this, direction) + ) } private _startMove(direction: MoveDirection) { @@ -90,5 +96,4 @@ export class SelectionObserver { this.isMoving = false } } - -} \ No newline at end of file +} diff --git a/src/editor/core/plugin/Plugin.ts b/src/editor/core/plugin/Plugin.ts index 4188f0a..d1efcd1 100644 --- a/src/editor/core/plugin/Plugin.ts +++ b/src/editor/core/plugin/Plugin.ts @@ -2,15 +2,16 @@ import Editor from '../..' import { PluginFunction } from '../../interface/Plugin' export class Plugin { - private editor: Editor constructor(editor: Editor) { this.editor = editor } - public use(pluginFunction: PluginFunction, options?: Options) { + public use( + pluginFunction: PluginFunction, + options?: Options + ) { pluginFunction(this.editor, options) } - -} \ No newline at end of file +} diff --git a/src/editor/core/position/Position.ts b/src/editor/core/position/Position.ts index e284c5b..0618eaa 100644 --- a/src/editor/core/position/Position.ts +++ b/src/editor/core/position/Position.ts @@ -1,15 +1,21 @@ import { ElementType, RowFlex, VerticalAlign } from '../..' import { ZERO } from '../../dataset/constant/Common' import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control' -import { IComputePageRowPositionPayload, IComputePageRowPositionResult } from '../../interface/Position' +import { + IComputePageRowPositionPayload, + IComputePageRowPositionResult +} from '../../interface/Position' import { IEditorOption } from '../../interface/Editor' import { IElement, IElementPosition } from '../../interface/Element' -import { ICurrentPosition, IGetPositionByXYPayload, IPositionContext } from '../../interface/Position' +import { + ICurrentPosition, + IGetPositionByXYPayload, + IPositionContext +} from '../../interface/Position' import { Draw } from '../draw/Draw' import { EditorZone } from '../../dataset/enum/Editor' export class Position { - private cursorPosition: IElementPosition | null private positionContext: IPositionContext private positionList: IElementPosition[] @@ -29,9 +35,14 @@ export class Position { this.options = draw.getOptions() } - public getTablePositionList(sourceElementList: IElement[]): IElementPosition[] { + public getTablePositionList( + sourceElementList: IElement[] + ): IElementPosition[] { const { index, trIndex, tdIndex } = this.positionContext - return sourceElementList[index!].trList![trIndex!].tdList[tdIndex!].positionList || [] + return ( + sourceElementList[index!].trList![trIndex!].tdList[tdIndex!] + .positionList || [] + ) } public getPositionList(): IElementPosition[] { @@ -67,8 +78,19 @@ export class Position { this.positionList = payload } - public computePageRowPosition(payload: IComputePageRowPositionPayload): IComputePageRowPositionResult { - const { positionList, rowList, pageNo, startX, startY, startRowIndex, startIndex, innerWidth } = payload + public computePageRowPosition( + payload: IComputePageRowPositionPayload + ): IComputePageRowPositionResult { + const { + positionList, + rowList, + pageNo, + startX, + startY, + startRowIndex, + startIndex, + innerWidth + } = payload const { scale, tdPadding } = this.options let x = startX let y = startY @@ -92,8 +114,9 @@ export class Position { const element = curRow.elementList[j] const metrics = element.metrics const offsetY = - (element.imgDisplay !== ImageDisplay.INLINE && element.type === ElementType.IMAGE) - || element.type === ElementType.LATEX + (element.imgDisplay !== ImageDisplay.INLINE && + element.type === ElementType.IMAGE) || + element.type === ElementType.LATEX ? curRow.ascent - metrics.height : curRow.ascent const positionItem: IElementPosition = { @@ -137,15 +160,23 @@ export class Position { }) // 垂直对齐方式 if ( - td.verticalAlign === VerticalAlign.MIDDLE - || td.verticalAlign === VerticalAlign.BOTTOM + td.verticalAlign === VerticalAlign.MIDDLE || + td.verticalAlign === VerticalAlign.BOTTOM ) { - const rowsHeight = rowList.reduce((pre, cur) => pre + cur.height, 0) + const rowsHeight = rowList.reduce( + (pre, cur) => pre + cur.height, + 0 + ) const blankHeight = (td.height! - tdGap) * scale - rowsHeight - const offsetHeight = td.verticalAlign === VerticalAlign.MIDDLE ? blankHeight / 2 : blankHeight + const offsetHeight = + td.verticalAlign === VerticalAlign.MIDDLE + ? blankHeight / 2 + : blankHeight if (Math.floor(offsetHeight) > 0) { td.positionList.forEach(tdPosition => { - const { coordinate: { leftTop, leftBottom, rightBottom, rightTop } } = tdPosition + const { + coordinate: { leftTop, leftBottom, rightBottom, rightTop } + } = tdPosition leftTop[1] += offsetHeight leftBottom[1] += offsetHeight rightBottom[1] += offsetHeight @@ -228,10 +259,19 @@ export class Position { const isMainActive = zoneManager.isMainActive() const positionNo = isMainActive ? curPageNo : 0 for (let j = 0; j < positionList.length; j++) { - const { index, pageNo, coordinate: { leftTop, rightTop, leftBottom } } = positionList[j] + const { + index, + pageNo, + coordinate: { leftTop, rightTop, leftBottom } + } = positionList[j] if (positionNo !== pageNo) continue // 命中元素 - if (leftTop[0] <= x && rightTop[0] >= x && leftTop[1] <= y && leftBottom[1] >= y) { + if ( + leftTop[0] <= x && + rightTop[0] >= x && + leftTop[1] <= y && + leftBottom[1] >= y + ) { let curPositionIndex = j const element = elementList[j] // 表格被命中 @@ -254,8 +294,10 @@ export class Position { const tdValueElement = td.value[tdValueIndex] return { index, - isCheckbox: tdValueElement.type === ElementType.CHECKBOX || - tdValueElement.controlComponent === ControlComponent.CHECKBOX, + isCheckbox: + tdValueElement.type === ElementType.CHECKBOX || + tdValueElement.controlComponent === + ControlComponent.CHECKBOX, isControl: tdValueElement.type === ElementType.CONTROL, isImage: tablePosition.isImage, isDirectHit: tablePosition.isDirectHit, @@ -272,7 +314,10 @@ export class Position { } } // 图片区域均为命中 - if (element.type === ElementType.IMAGE || element.type === ElementType.LATEX) { + if ( + element.type === ElementType.IMAGE || + element.type === ElementType.LATEX + ) { return { index: curPositionIndex, isDirectHit: true, @@ -298,7 +343,7 @@ export class Position { } return { index: curPositionIndex, - isControl: element.type === ElementType.CONTROL, + isControl: element.type === ElementType.CONTROL } } } @@ -323,18 +368,28 @@ export class Position { } } // 判断所属行是否存在元素 - const lastLetterList = positionList.filter(p => p.isLastLetter && p.pageNo === positionNo) + const lastLetterList = positionList.filter( + p => p.isLastLetter && p.pageNo === positionNo + ) for (let j = 0; j < lastLetterList.length; j++) { - const { index, pageNo, coordinate: { leftTop, leftBottom } } = lastLetterList[j] + const { + index, + pageNo, + coordinate: { leftTop, leftBottom } + } = lastLetterList[j] if (positionNo !== pageNo) continue if (y > leftTop[1] && y <= leftBottom[1]) { const isHead = x < this.options.margins[3] // 是否在头部 if (isHead) { - const headIndex = positionList.findIndex(p => p.pageNo === positionNo && p.rowNo === lastLetterList[j].rowNo) + const headIndex = positionList.findIndex( + p => p.pageNo === positionNo && p.rowNo === lastLetterList[j].rowNo + ) // 头部元素为空元素时无需选中 curPositionIndex = ~headIndex - ? positionList[headIndex].value === ZERO ? headIndex : headIndex - 1 + ? positionList[headIndex].value === ZERO + ? headIndex + : headIndex - 1 : index } else { curPositionIndex = index @@ -350,7 +405,8 @@ export class Position { // 页脚上部距离页面顶部距离 const footer = this.draw.getFooter() const pageHeight = this.draw.getHeight() - const footerTopY = pageHeight - (footer.getFooterBottom() + footer.getHeight()) + const footerTopY = + pageHeight - (footer.getFooterBottom() + footer.getHeight()) // 判断所属位置是否属于页眉页脚区域 if (isMainActive) { // 页眉:当前位置小于页眉底部位置 @@ -378,7 +434,9 @@ export class Position { } // 当前页最后一行 return { - index: lastLetterList[lastLetterList.length - 1]?.index || positionList.length - 1, + index: + lastLetterList[lastLetterList.length - 1]?.index || + positionList.length - 1 } } return { @@ -387,19 +445,15 @@ export class Position { } } - public adjustPositionContext(payload: IGetPositionByXYPayload): ICurrentPosition | null { + public adjustPositionContext( + payload: IGetPositionByXYPayload + ): ICurrentPosition | null { const isReadonly = this.draw.isReadonly() const positionResult = this.getPositionByXY(payload) if (!~positionResult.index) return null // 移动控件内光标 if (positionResult.isControl && !isReadonly) { - const { - index, - isTable, - trIndex, - tdIndex, - tdValueIndex - } = positionResult + const { index, isTable, trIndex, tdIndex, tdValueIndex } = positionResult const control = this.draw.getControl() const { newIndex } = control.moveCursor({ index, @@ -439,5 +493,4 @@ export class Position { }) return positionResult } - -} \ No newline at end of file +} diff --git a/src/editor/core/range/RangeManager.ts b/src/editor/core/range/RangeManager.ts index 4cec0c8..5efee14 100644 --- a/src/editor/core/range/RangeManager.ts +++ b/src/editor/core/range/RangeManager.ts @@ -12,7 +12,6 @@ import { Listener } from '../listener/Listener' import { Position } from '../position/Position' export class RangeManager { - private draw: Draw private options: Required private range: IRange @@ -55,7 +54,9 @@ export class RangeManager { public getTextLikeSelection(): IElement[] | null { const selection = this.getSelection() if (!selection) return null - return selection.filter(s => !s.type || TEXTLIKE_ELEMENT_TYPE.includes(s.type)) + return selection.filter( + s => !s.type || TEXTLIKE_ELEMENT_TYPE.includes(s.type) + ) } // 获取光标所选位置行信息 @@ -100,7 +101,9 @@ export class RangeManager { if ( positionList[start]?.value === ZERO || elementList[start].titleId !== elementList[start - 1]?.titleId - ) break + ) { + break + } start-- } // 中间选择 @@ -125,7 +128,9 @@ export class RangeManager { if ( positionList[end].value === ZERO || elementList[end].titleId !== elementList[end + 1]?.titleId - ) break + ) { + break + } const { pageNo, rowNo } = positionList[end] let rowArray = rangeRow.get(pageNo) if (!rowArray) { @@ -172,8 +177,15 @@ export class RangeManager { const { startIndex, endIndex } = this.range const positionList = this.position.getPositionList() for (let p = startIndex + 1; p <= endIndex; p++) { - const { coordinate: { leftTop, rightBottom } } = positionList[p] - if (x >= leftTop[0] && x <= rightBottom[0] && y >= leftTop[1] && y <= rightBottom[1]) { + const { + coordinate: { leftTop, rightBottom } + } = positionList[p] + if ( + x >= leftTop[0] && + x <= rightBottom[0] && + y >= leftTop[1] && + y <= rightBottom[1] + ) { return true } } @@ -196,7 +208,12 @@ export class RangeManager { this.range.endTdIndex = endTdIndex this.range.startTrIndex = startTrIndex this.range.endTrIndex = endTrIndex - this.range.isCrossRowCol = !!(startTdIndex || endTdIndex || startTrIndex || endTrIndex) + this.range.isCrossRowCol = !!( + startTdIndex || + endTdIndex || + startTrIndex || + endTrIndex + ) this.range.zone = this.draw.getZone().getZone() // 激活控件 const control = this.draw.getControl() @@ -349,8 +366,8 @@ export class RangeManager { while (index > 0) { const preElement = elementList[index] if ( - preElement.controlId !== endElement.controlId - || preElement.controlComponent === ControlComponent.PREFIX + preElement.controlId !== endElement.controlId || + preElement.controlComponent === ControlComponent.PREFIX ) { range.startIndex = index range.endIndex = index @@ -365,12 +382,14 @@ export class RangeManager { while (index < elementList.length) { const nextElement = elementList[index] if ( - nextElement.controlId !== startElement.controlId - || nextElement.controlComponent === ControlComponent.VALUE + nextElement.controlId !== startElement.controlId || + nextElement.controlComponent === ControlComponent.VALUE ) { range.startIndex = index - 1 break - } else if (nextElement.controlComponent === ControlComponent.PLACEHOLDER) { + } else if ( + nextElement.controlComponent === ControlComponent.PLACEHOLDER + ) { range.startIndex = index - 1 range.endIndex = index - 1 return @@ -384,12 +403,14 @@ export class RangeManager { while (index > 0) { const preElement = elementList[index] if ( - preElement.controlId !== startElement.controlId - || preElement.controlComponent === ControlComponent.VALUE + preElement.controlId !== startElement.controlId || + preElement.controlComponent === ControlComponent.VALUE ) { range.startIndex = index break - } else if (preElement.controlComponent === ControlComponent.PLACEHOLDER) { + } else if ( + preElement.controlComponent === ControlComponent.PLACEHOLDER + ) { range.startIndex = index range.endIndex = index return @@ -400,7 +421,13 @@ export class RangeManager { } } - public render(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) { + public render( + ctx: CanvasRenderingContext2D, + x: number, + y: number, + width: number, + height: number + ) { ctx.save() ctx.globalAlpha = this.options.rangeAlpha ctx.fillStyle = this.options.rangeColor @@ -411,9 +438,9 @@ export class RangeManager { public toString(): string { const selection = this.getSelection() if (!selection) return '' - return selection.map(s => s.value) + return selection + .map(s => s.value) .join('') .replace(new RegExp(ZERO, 'g'), '') } - -} \ No newline at end of file +} diff --git a/src/editor/core/register/Register.ts b/src/editor/core/register/Register.ts index d7ac853..c22278e 100644 --- a/src/editor/core/register/Register.ts +++ b/src/editor/core/register/Register.ts @@ -7,13 +7,12 @@ import { ILang } from '../../interface/i18n/I18n' import { DeepPartial } from '../../interface/Common' interface IRegisterPayload { - contextMenu: ContextMenu; - shortcut: Shortcut; - i18n: I18n; + contextMenu: ContextMenu + shortcut: Shortcut + i18n: I18n } export class Register { - public contextMenuList: (payload: IRegisterContextMenu[]) => void public shortcutList: (payload: IRegisterShortcut[]) => void public langMap: (locale: string, lang: DeepPartial) => void @@ -24,5 +23,4 @@ export class Register { this.shortcutList = shortcut.registerShortcutList.bind(shortcut) this.langMap = i18n.registerLangMap.bind(i18n) } - -} \ No newline at end of file +} diff --git a/src/editor/core/shortcut/Shortcut.ts b/src/editor/core/shortcut/Shortcut.ts index 10c172a..dcf8f88 100644 --- a/src/editor/core/shortcut/Shortcut.ts +++ b/src/editor/core/shortcut/Shortcut.ts @@ -7,7 +7,6 @@ import { titleKeys } from './keys/titleKeys' import { listKeys } from './keys/listKeys' export class Shortcut { - private command: Command private globalShortcutList: IRegisterShortcut[] private agentShortcutList: IRegisterShortcut[] @@ -17,11 +16,7 @@ export class Shortcut { this.globalShortcutList = [] this.agentShortcutList = [] // 内部快捷键 - this._addShortcutList([ - ...richtextKeys, - ...titleKeys, - ...listKeys - ]) + this._addShortcutList([...richtextKeys, ...titleKeys, ...listKeys]) // 全局快捷键 this._addEvent() // 编辑器快捷键 @@ -66,11 +61,10 @@ export class Shortcut { for (let s = 0; s < shortCutList.length; s++) { const shortCut = shortCutList[s] if ( - ( - shortCut.mod - ? isMod(evt) === !!shortCut.mod - : evt.ctrlKey === !!shortCut.ctrl && evt.metaKey === !!shortCut.meta - ) && + (shortCut.mod + ? isMod(evt) === !!shortCut.mod + : evt.ctrlKey === !!shortCut.ctrl && + evt.metaKey === !!shortCut.meta) && evt.shiftKey === !!shortCut.shift && evt.altKey === !!shortCut.alt && evt.key === shortCut.key @@ -81,5 +75,4 @@ export class Shortcut { } } } - } diff --git a/src/editor/core/shortcut/keys/listKeys.ts b/src/editor/core/shortcut/keys/listKeys.ts index 5dac017..a56e6d7 100644 --- a/src/editor/core/shortcut/keys/listKeys.ts +++ b/src/editor/core/shortcut/keys/listKeys.ts @@ -19,4 +19,4 @@ export const listKeys: IRegisterShortcut[] = [ command.executeList(ListType.OL) } } -] \ No newline at end of file +] diff --git a/src/editor/core/shortcut/keys/richtextKeys.ts b/src/editor/core/shortcut/keys/richtextKeys.ts index 89575e0..4a9ee3b 100644 --- a/src/editor/core/shortcut/keys/richtextKeys.ts +++ b/src/editor/core/shortcut/keys/richtextKeys.ts @@ -91,4 +91,4 @@ export const richtextKeys: IRegisterShortcut[] = [ command.executeRowFlex(RowFlex.ALIGNMENT) } } -] \ No newline at end of file +] diff --git a/src/editor/core/shortcut/keys/titleKeys.ts b/src/editor/core/shortcut/keys/titleKeys.ts index d96ca57..783c2e0 100644 --- a/src/editor/core/shortcut/keys/titleKeys.ts +++ b/src/editor/core/shortcut/keys/titleKeys.ts @@ -10,42 +10,48 @@ export const titleKeys: IRegisterShortcut[] = [ callback: (command: Command) => { command.executeTitle(null) } - }, { + }, + { key: KeyMap.ONE, alt: true, ctrl: true, callback: (command: Command) => { command.executeTitle(TitleLevel.FIRST) } - }, { + }, + { key: KeyMap.TWO, alt: true, ctrl: true, callback: (command: Command) => { command.executeTitle(TitleLevel.SECOND) } - }, { + }, + { key: KeyMap.THREE, alt: true, ctrl: true, callback: (command: Command) => { command.executeTitle(TitleLevel.THIRD) } - }, { + }, + { key: KeyMap.FOUR, alt: true, ctrl: true, callback: (command: Command) => { command.executeTitle(TitleLevel.FOURTH) } - }, { + }, + { key: KeyMap.FIVE, alt: true, ctrl: true, callback: (command: Command) => { command.executeTitle(TitleLevel.FIFTH) } - }, { + }, + { key: KeyMap.SIX, alt: true, ctrl: true, @@ -53,4 +59,4 @@ export const titleKeys: IRegisterShortcut[] = [ command.executeTitle(TitleLevel.SIXTH) } } -] \ No newline at end of file +] diff --git a/src/editor/core/worker/WorkerManager.ts b/src/editor/core/worker/WorkerManager.ts index 32ca255..982f6c8 100644 --- a/src/editor/core/worker/WorkerManager.ts +++ b/src/editor/core/worker/WorkerManager.ts @@ -3,9 +3,7 @@ import WordCountWorker from './works/wordCount?worker&inline' import CatalogWorker from './works/catalog?worker&inline' import { ICatalog } from '../../interface/Catalog' - export class WorkerManager { - private draw: Draw private wordCountWorker: Worker private catalogWorker: Worker @@ -18,11 +16,11 @@ export class WorkerManager { public getWordCount(): Promise { return new Promise((resolve, reject) => { - this.wordCountWorker.onmessage = (evt) => { + this.wordCountWorker.onmessage = evt => { resolve(evt.data) } - this.wordCountWorker.onerror = (evt) => { + this.wordCountWorker.onerror = evt => { reject(evt) } @@ -33,11 +31,11 @@ export class WorkerManager { public getCatalog(): Promise { return new Promise((resolve, reject) => { - this.catalogWorker.onmessage = (evt) => { + this.catalogWorker.onmessage = evt => { resolve(evt.data) } - this.catalogWorker.onerror = (evt) => { + this.catalogWorker.onerror = evt => { reject(evt) } @@ -45,5 +43,4 @@ export class WorkerManager { this.catalogWorker.postMessage(elementList) }) } - -} \ No newline at end of file +} diff --git a/src/editor/core/worker/works/catalog.ts b/src/editor/core/worker/works/catalog.ts index c300c06..be0f327 100644 --- a/src/editor/core/worker/works/catalog.ts +++ b/src/editor/core/worker/works/catalog.ts @@ -50,7 +50,8 @@ function getCatalog(elementList: IElement[]): ICatalog | null { valueList.push(titleE) t++ } - titleElement.value = valueList.map(s => s.value) + titleElement.value = valueList + .map(s => s.value) .join('') .replace(new RegExp(ZERO, 'g'), '') titleElementList.push(titleElement) @@ -60,7 +61,8 @@ function getCatalog(elementList: IElement[]): ICatalog | null { if (!titleElementList.length) return null // 查找到比最新元素大的标题时终止 const recursiveInsert = (title: IElement, catalogItem: ICatalogItem) => { - const subCatalogItem = catalogItem.subCatalog[catalogItem.subCatalog.length - 1] + const subCatalogItem = + catalogItem.subCatalog[catalogItem.subCatalog.length - 1] const catalogItemLevel = titleOrderNumberMapping[subCatalogItem?.level] const titleLevel = titleOrderNumberMapping[title.level!] if (subCatalogItem && titleLevel > catalogItemLevel) { @@ -97,7 +99,7 @@ function getCatalog(elementList: IElement[]): ICatalog | null { return catalog } -onmessage = (evt) => { +onmessage = evt => { const elementList = evt.data const catalog = getCatalog(elementList) postMessage(catalog) diff --git a/src/editor/core/worker/works/wordCount.ts b/src/editor/core/worker/works/wordCount.ts index 2a98eae..0aad51c 100644 --- a/src/editor/core/worker/works/wordCount.ts +++ b/src/editor/core/worker/works/wordCount.ts @@ -115,7 +115,7 @@ function groupText(text: string): string[] { return characterList } -onmessage = (evt) => { +onmessage = evt => { const elementList = evt.data // 提取文本 const originText = pickText(elementList) diff --git a/src/editor/core/zone/Zone.ts b/src/editor/core/zone/Zone.ts index 3200cdd..0cea548 100644 --- a/src/editor/core/zone/Zone.ts +++ b/src/editor/core/zone/Zone.ts @@ -6,7 +6,6 @@ import { Draw } from '../draw/Draw' import { I18n } from '../i18n/I18n' export class Zone { - private readonly INDICATOR_PADDING = 2 private readonly INDICATOR_TITLE_TRANSLATE = [20, 5] @@ -99,9 +98,13 @@ export class Zone { : startY - this.INDICATOR_PADDING // 标题 const indicatorTitle = document.createElement('div') - indicatorTitle.innerText = this.i18n.t(`frame.${isHeaderActive ? 'header' : 'footer'}`) + indicatorTitle.innerText = this.i18n.t( + `frame.${isHeaderActive ? 'header' : 'footer'}` + ) indicatorTitle.style.top = `${indicatorBottomY}px` - indicatorTitle.style.transform = `translate(${offsetX * scale}px, ${offsetY * scale}px) scale(${scale})` + indicatorTitle.style.transform = `translate(${offsetX * scale}px, ${ + offsetY * scale + }px) scale(${scale})` this.indicatorContainer.append(indicatorTitle) // 上边线 @@ -141,5 +144,4 @@ export class Zone { this.indicatorContainer?.remove() this.indicatorContainer = null } - -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/Checkbox.ts b/src/editor/dataset/constant/Checkbox.ts index 3c478bc..7df38b0 100644 --- a/src/editor/dataset/constant/Checkbox.ts +++ b/src/editor/dataset/constant/Checkbox.ts @@ -7,4 +7,4 @@ export const defaultCheckboxOption: Readonly> = { lineWidth: 1, fillStyle: '#5175f4', fontStyle: '#ffffff' -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/Common.ts b/src/editor/dataset/constant/Common.ts index fe5fedd..91ab243 100644 --- a/src/editor/dataset/constant/Common.ts +++ b/src/editor/dataset/constant/Common.ts @@ -4,10 +4,25 @@ export const ZERO = '\u200B' export const WRAP = '\n' export const HORIZON_TAB = '\t' export const NBSP = '\u0020' -export const PUNCTUATION_LIST = ['·', '、', ':', ':', ',', ',', '.', '。', ';', ';', '?', '?', '!', '!'] +export const PUNCTUATION_LIST = [ + '·', + '、', + ':', + ':', + ',', + ',', + '.', + '。', + ';', + ';', + '?', + '?', + '!', + '!' +] export const maxHeightRadioMapping: Record = { [MaxHeightRatio.HALF]: 1 / 2, [MaxHeightRatio.ONE_THIRD]: 1 / 3, [MaxHeightRatio.QUARTER]: 1 / 4 -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/ContextMenu.ts b/src/editor/dataset/constant/ContextMenu.ts index 48a0c9a..27df619 100644 --- a/src/editor/dataset/constant/ContextMenu.ts +++ b/src/editor/dataset/constant/ContextMenu.ts @@ -1,3 +1,3 @@ export const NAME_PLACEHOLDER = { SELECTED_TEXT: '%s' -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/Control.ts b/src/editor/dataset/constant/Control.ts index 2190bc3..da24297 100644 --- a/src/editor/dataset/constant/Control.ts +++ b/src/editor/dataset/constant/Control.ts @@ -5,4 +5,4 @@ export const defaultControlOption: Readonly> = { bracketColor: '#000000', prefix: '{', postfix: '}' -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/Cursor.ts b/src/editor/dataset/constant/Cursor.ts index 98756dc..16c13d0 100644 --- a/src/editor/dataset/constant/Cursor.ts +++ b/src/editor/dataset/constant/Cursor.ts @@ -7,4 +7,4 @@ export const defaultCursorOption: Readonly> = { color: '#000000', dragWidth: 2, dragColor: '#0000FF' -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/Editor.ts b/src/editor/dataset/constant/Editor.ts index 1b96168..b849285 100644 --- a/src/editor/dataset/constant/Editor.ts +++ b/src/editor/dataset/constant/Editor.ts @@ -1,2 +1,2 @@ export const EDITOR_COMPONENT = 'editor-component' -export const EDITOR_PREFIX = 'ce' \ No newline at end of file +export const EDITOR_PREFIX = 'ce' diff --git a/src/editor/dataset/constant/Element.ts b/src/editor/dataset/constant/Element.ts index 86b8b64..54fbaa1 100644 --- a/src/editor/dataset/constant/Element.ts +++ b/src/editor/dataset/constant/Element.ts @@ -65,10 +65,7 @@ export const TABLE_CONTEXT_ATTR: Array = [ 'tableId' ] -export const TITLE_CONTEXT_ATTR: Array = [ - 'level', - 'titleId', -] +export const TITLE_CONTEXT_ATTR: Array = ['level', 'titleId'] export const LIST_CONTEXT_ATTR: Array = [ 'listId', @@ -98,14 +95,9 @@ export const INLINE_ELEMENT_TYPE: ElementType[] = [ ElementType.TABLE ] -export const INLINE_NODE_NAME: string[] = [ - 'HR', - 'TABLE', - 'UL', - 'OL' -] +export const INLINE_NODE_NAME: string[] = ['HR', 'TABLE', 'UL', 'OL'] export const VIRTUAL_ELEMENT_TYPE: ElementType[] = [ ElementType.TITLE, ElementType.LIST -] \ No newline at end of file +] diff --git a/src/editor/dataset/constant/Footer.ts b/src/editor/dataset/constant/Footer.ts index 8b003a3..abf6255 100644 --- a/src/editor/dataset/constant/Footer.ts +++ b/src/editor/dataset/constant/Footer.ts @@ -5,4 +5,4 @@ export const defaultFooterOption: Readonly> = { bottom: 30, maxHeightRadio: MaxHeightRatio.HALF, disabled: false -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/Header.ts b/src/editor/dataset/constant/Header.ts index 9c974c7..ccaa376 100644 --- a/src/editor/dataset/constant/Header.ts +++ b/src/editor/dataset/constant/Header.ts @@ -5,4 +5,4 @@ export const defaultHeaderOption: Readonly> = { top: 30, maxHeightRadio: MaxHeightRatio.HALF, disabled: false -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/List.ts b/src/editor/dataset/constant/List.ts index 562ad45..49de62e 100644 --- a/src/editor/dataset/constant/List.ts +++ b/src/editor/dataset/constant/List.ts @@ -16,4 +16,4 @@ export const listStyleCSSMapping: Record = { [ListStyle.CIRCLE]: 'circle', [ListStyle.SQUARE]: 'square', [ListStyle.DECIMAL]: 'decimal' -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/PageNumber.ts b/src/editor/dataset/constant/PageNumber.ts index b21d1bc..5449874 100644 --- a/src/editor/dataset/constant/PageNumber.ts +++ b/src/editor/dataset/constant/PageNumber.ts @@ -18,4 +18,4 @@ export const defaultPageNumberOption: Readonly> = { disabled: false, startPageNo: 1, fromPageNo: 0 -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/Placeholder.ts b/src/editor/dataset/constant/Placeholder.ts index a303520..ad2adea 100644 --- a/src/editor/dataset/constant/Placeholder.ts +++ b/src/editor/dataset/constant/Placeholder.ts @@ -6,4 +6,4 @@ export const defaultPlaceholderOption: Readonly> = { opacity: 1, size: 16, font: 'Yahei' -} \ No newline at end of file +} diff --git a/src/editor/dataset/constant/Regular.ts b/src/editor/dataset/constant/Regular.ts index 9d4e4b7..7a181a3 100644 --- a/src/editor/dataset/constant/Regular.ts +++ b/src/editor/dataset/constant/Regular.ts @@ -2,4 +2,4 @@ export const NUMBER_REG = /[0-9]/ export const LETTER_REG = /[a-zA-Z]/ export const NUMBER_LIKE_REG = /[0-9.]/ export const CHINESE_REG = /[\u4e00-\u9fa5]/ -export const WORD_LIKE_REG = /[^a-zA-Z][a-zA-Z]/ \ No newline at end of file +export const WORD_LIKE_REG = /[^a-zA-Z][a-zA-Z]/ diff --git a/src/editor/dataset/constant/Title.ts b/src/editor/dataset/constant/Title.ts index 65dc18f..93fda74 100644 --- a/src/editor/dataset/constant/Title.ts +++ b/src/editor/dataset/constant/Title.ts @@ -29,10 +29,10 @@ export const titleOrderNumberMapping: Record = { } export const titleNodeNameMapping: Record = { - 'H1': TitleLevel.FIRST, - 'H2': TitleLevel.SECOND, - 'H3': TitleLevel.THIRD, - 'H4': TitleLevel.FOURTH, - 'H5': TitleLevel.FIFTH, - 'H6': TitleLevel.SIXTH -} \ No newline at end of file + H1: TitleLevel.FIRST, + H2: TitleLevel.SECOND, + H3: TitleLevel.THIRD, + H4: TitleLevel.FOURTH, + H5: TitleLevel.FIFTH, + H6: TitleLevel.SIXTH +} diff --git a/src/editor/dataset/constant/Watermark.ts b/src/editor/dataset/constant/Watermark.ts index 1152fc5..cd0ad49 100644 --- a/src/editor/dataset/constant/Watermark.ts +++ b/src/editor/dataset/constant/Watermark.ts @@ -6,4 +6,4 @@ export const defaultWatermarkOption: Readonly> = { opacity: 0.3, size: 200, font: 'Yahei' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/Block.ts b/src/editor/dataset/enum/Block.ts index 125c6b5..c881fc1 100644 --- a/src/editor/dataset/enum/Block.ts +++ b/src/editor/dataset/enum/Block.ts @@ -1,4 +1,4 @@ export enum BlockType { IFRAME = 'iframe', VIDEO = 'video' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/Common.ts b/src/editor/dataset/enum/Common.ts index 72029ee..e07d286 100644 --- a/src/editor/dataset/enum/Common.ts +++ b/src/editor/dataset/enum/Common.ts @@ -7,4 +7,4 @@ export enum MaxHeightRatio { export enum NumberType { ARABIC = 'arabic', CHINESE = 'chinese' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/Control.ts b/src/editor/dataset/enum/Control.ts index fcbbbce..d2b90c4 100644 --- a/src/editor/dataset/enum/Control.ts +++ b/src/editor/dataset/enum/Control.ts @@ -15,4 +15,4 @@ export enum ControlComponent { export enum ImageDisplay { INLINE = 'inline', BLOCK = 'block' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/Editor.ts b/src/editor/dataset/enum/Editor.ts index 1c0f8f9..e0134e4 100644 --- a/src/editor/dataset/enum/Editor.ts +++ b/src/editor/dataset/enum/Editor.ts @@ -38,4 +38,4 @@ export enum PaperDirection { export enum WordBreak { BREAK_ALL = 'break-all', BREAK_WORD = 'break-word' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/Element.ts b/src/editor/dataset/enum/Element.ts index 641bc5a..bffe15c 100644 --- a/src/editor/dataset/enum/Element.ts +++ b/src/editor/dataset/enum/Element.ts @@ -15,4 +15,4 @@ export enum ElementType { BLOCK = 'block', TITLE = 'title', LIST = 'list' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/ElementStyle.ts b/src/editor/dataset/enum/ElementStyle.ts index 89444f7..4f21723 100644 --- a/src/editor/dataset/enum/ElementStyle.ts +++ b/src/editor/dataset/enum/ElementStyle.ts @@ -9,4 +9,4 @@ export enum ElementStyleKey { italic = 'italic', underline = 'underline', strikeout = 'strikeout' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/Event.ts b/src/editor/dataset/enum/Event.ts index 823f6a0..c72f601 100644 --- a/src/editor/dataset/enum/Event.ts +++ b/src/editor/dataset/enum/Event.ts @@ -2,4 +2,4 @@ export enum MouseEventButton { LEFT = 0, CENTER = 1, RIGHT = 2 -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/KeyMap.ts b/src/editor/dataset/enum/KeyMap.ts index dfc58ea..d7d1a7a 100644 --- a/src/editor/dataset/enum/KeyMap.ts +++ b/src/editor/dataset/enum/KeyMap.ts @@ -80,4 +80,4 @@ export enum KeyMap { SEVEN = '7', EIGHT = '8', NINE = '9' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/List.ts b/src/editor/dataset/enum/List.ts index de415cd..a7f4fbf 100644 --- a/src/editor/dataset/enum/List.ts +++ b/src/editor/dataset/enum/List.ts @@ -6,7 +6,7 @@ export enum ListType { export enum UlStyle { DISC = 'disc', // 实心圆点 CIRCLE = 'circle', // 空心圆点 - SQUARE = 'square', // 实心方块 + SQUARE = 'square' // 实心方块 } export enum OlStyle { @@ -18,4 +18,4 @@ export enum ListStyle { CIRCLE = UlStyle.CIRCLE, SQUARE = UlStyle.SQUARE, DECIMAL = OlStyle.DECIMAL -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/Observer.ts b/src/editor/dataset/enum/Observer.ts index 2d44c48..9dbf1fa 100644 --- a/src/editor/dataset/enum/Observer.ts +++ b/src/editor/dataset/enum/Observer.ts @@ -3,4 +3,4 @@ export enum MoveDirection { DOWN = 'down', LEFT = 'left', RIGHT = 'right' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/Row.ts b/src/editor/dataset/enum/Row.ts index 089fa52..7041fe0 100644 --- a/src/editor/dataset/enum/Row.ts +++ b/src/editor/dataset/enum/Row.ts @@ -3,4 +3,4 @@ export enum RowFlex { CENTER = 'center', RIGHT = 'right', ALIGNMENT = 'alignment' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/Title.ts b/src/editor/dataset/enum/Title.ts index 3444f4f..2ed83a0 100644 --- a/src/editor/dataset/enum/Title.ts +++ b/src/editor/dataset/enum/Title.ts @@ -5,4 +5,4 @@ export enum TitleLevel { FOURTH = 'fourth', FIFTH = 'fifth', SIXTH = 'sixth' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/VerticalAlign.ts b/src/editor/dataset/enum/VerticalAlign.ts index 8793426..64b0f32 100644 --- a/src/editor/dataset/enum/VerticalAlign.ts +++ b/src/editor/dataset/enum/VerticalAlign.ts @@ -2,4 +2,4 @@ export enum VerticalAlign { TOP = 'top', MIDDLE = 'middle', BOTTOM = 'bottom' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/table/Table.ts b/src/editor/dataset/enum/table/Table.ts index a1dc22d..927075c 100644 --- a/src/editor/dataset/enum/table/Table.ts +++ b/src/editor/dataset/enum/table/Table.ts @@ -2,4 +2,4 @@ export enum TableBorder { ALL = 'all', EMPTY = 'empty', EXTERNAL = 'external' -} \ No newline at end of file +} diff --git a/src/editor/dataset/enum/table/TableTool.ts b/src/editor/dataset/enum/table/TableTool.ts index 2c6cb5f..d1c55c4 100644 --- a/src/editor/dataset/enum/table/TableTool.ts +++ b/src/editor/dataset/enum/table/TableTool.ts @@ -1,4 +1,4 @@ export enum TableOrder { ROW = 'row', COL = 'col' -} \ No newline at end of file +} diff --git a/src/editor/index.ts b/src/editor/index.ts index 0b2a0b8..9ea847f 100644 --- a/src/editor/index.ts +++ b/src/editor/index.ts @@ -10,8 +10,18 @@ import { ElementType } from './dataset/enum/Element' import { formatElementList } from './utils/element' import { Register } from './core/register/Register' import { ContextMenu } from './core/contextmenu/ContextMenu' -import { IContextMenuContext, IRegisterContextMenu } from './interface/contextmenu/ContextMenu' -import { EditorComponent, EditorZone, EditorMode, PageMode, PaperDirection, WordBreak } from './dataset/enum/Editor' +import { + IContextMenuContext, + IRegisterContextMenu +} from './interface/contextmenu/ContextMenu' +import { + EditorComponent, + EditorZone, + EditorMode, + PageMode, + PaperDirection, + WordBreak +} from './dataset/enum/Editor' import { EDITOR_COMPONENT } from './dataset/constant/Editor' import { IHeader } from './interface/Header' import { IWatermark } from './interface/Watermark' @@ -49,14 +59,17 @@ import { Plugin } from './core/plugin/Plugin' import { UsePlugin } from './interface/Plugin' export default class Editor { - public command: Command public listener: Listener public register: Register public destroy: () => void public use: UsePlugin - constructor(container: HTMLDivElement, data: IEditorData | IElement[], options: IEditorOption = {}) { + constructor( + container: HTMLDivElement, + data: IEditorData | IElement[], + options: IEditorOption = {} + ) { const headerOptions: Required = { ...defaultHeaderOption, ...options.header @@ -153,12 +166,16 @@ export default class Editor { mainElementList = data.main footerElementList = data.footer || [] } - [headerElementList, mainElementList, footerElementList] - .forEach(elementList => { - formatElementList(elementList, { - editorOptions - }) + const pageComponentData = [ + headerElementList, + mainElementList, + footerElementList + ] + pageComponentData.forEach(elementList => { + formatElementList(elementList, { + editorOptions }) + }) // 监听 this.listener = new Listener() // 启动 @@ -194,7 +211,6 @@ export default class Editor { const plugin = new Plugin(this) this.use = plugin.use.bind(plugin) } - } // 对外对象 @@ -237,4 +253,4 @@ export type { ILang, ICatalog, ICatalogItem -} \ No newline at end of file +} diff --git a/src/editor/interface/Block.ts b/src/editor/interface/Block.ts index 75ebb1e..603fa21 100644 --- a/src/editor/interface/Block.ts +++ b/src/editor/interface/Block.ts @@ -1,15 +1,15 @@ import { BlockType } from '../dataset/enum/Block' export interface IIFrameBlock { - src: string; + src: string } export interface IVideoBlock { - src: string; + src: string } export interface IBlock { - type: BlockType; - iframeBlock?: IIFrameBlock; - videoBlock?: IVideoBlock; -} \ No newline at end of file + type: BlockType + iframeBlock?: IIFrameBlock + videoBlock?: IVideoBlock +} diff --git a/src/editor/interface/Catalog.ts b/src/editor/interface/Catalog.ts index c9bf6c1..2a07013 100644 --- a/src/editor/interface/Catalog.ts +++ b/src/editor/interface/Catalog.ts @@ -1,10 +1,10 @@ import { TitleLevel } from '../dataset/enum/Title' export interface ICatalogItem { - id: string; - name: string; - level: TitleLevel; - subCatalog: ICatalogItem[]; + id: string + name: string + level: TitleLevel + subCatalog: ICatalogItem[] } -export type ICatalog = ICatalogItem[] \ No newline at end of file +export type ICatalog = ICatalogItem[] diff --git a/src/editor/interface/Checkbox.ts b/src/editor/interface/Checkbox.ts index ee90b22..71fb359 100644 --- a/src/editor/interface/Checkbox.ts +++ b/src/editor/interface/Checkbox.ts @@ -1,14 +1,14 @@ export interface ICheckbox { - value: boolean | null; - code?: string; - disabled?: boolean; + value: boolean | null + code?: string + disabled?: boolean } export interface ICheckboxOption { - width?: number; - height?: number; - gap?: number; - lineWidth?: number; - fillStyle?: string; - fontStyle?: string; -} \ No newline at end of file + width?: number + height?: number + gap?: number + lineWidth?: number + fillStyle?: string + fontStyle?: string +} diff --git a/src/editor/interface/Common.ts b/src/editor/interface/Common.ts index 13fa102..097b771 100644 --- a/src/editor/interface/Common.ts +++ b/src/editor/interface/Common.ts @@ -1,4 +1,11 @@ -export type Primitive = string | number | boolean | bigint | symbol | undefined | null +export type Primitive = + | string + | number + | boolean + | bigint + | symbol + | undefined + | null export type Builtin = Primitive | Function | Date | Error | RegExp @@ -25,5 +32,5 @@ export type DeepRequired = T extends Error : Required export type DeepPartial = { - [P in keyof T]?: DeepPartial; -} \ No newline at end of file + [P in keyof T]?: DeepPartial +} diff --git a/src/editor/interface/Control.ts b/src/editor/interface/Control.ts index d14d7f6..52ab1ad 100644 --- a/src/editor/interface/Control.ts +++ b/src/editor/interface/Control.ts @@ -3,64 +3,63 @@ import { ICheckbox } from './Checkbox' import { IElement } from './Element' export interface IValueSet { - value: string; - code: string; + value: string + code: string } export interface IControlSelect { - code: string | null; - valueSets: IValueSet[]; + code: string | null + valueSets: IValueSet[] } export interface IControlCheckbox { - code: string | null; - min?: number; - max?: number; - valueSets: IValueSet[]; - checkbox?: ICheckbox; + code: string | null + min?: number + max?: number + valueSets: IValueSet[] + checkbox?: ICheckbox } export interface IControlBasic { - type: ControlType; - value: IElement[] | null; - placeholder?: string; - conceptId?: string; - prefix?: string; - postfix?: string; + type: ControlType + value: IElement[] | null + placeholder?: string + conceptId?: string + prefix?: string + postfix?: string } -export type IControl = IControlBasic - & Partial - & Partial - +export type IControl = IControlBasic & + Partial & + Partial export interface IControlOption { - placeholderColor?: string; - bracketColor?: string; - prefix?: string; - postfix?: string; + placeholderColor?: string + bracketColor?: string + prefix?: string + postfix?: string } export interface IControlInitOption { - index: number; - isTable?: boolean; - trIndex?: number; - tdIndex?: number; - tdValueIndex?: number; + index: number + isTable?: boolean + trIndex?: number + tdIndex?: number + tdValueIndex?: number } export interface IControlInitResult { - newIndex: number; + newIndex: number } export interface IControlInstance { - getElement(): IElement; + getElement(): IElement - getValue(): IElement[]; + getValue(): IElement[] - setValue(data: IElement[]): number; + setValue(data: IElement[]): number - keydown(evt: KeyboardEvent): number; + keydown(evt: KeyboardEvent): number - cut(): number; -} \ No newline at end of file + cut(): number +} diff --git a/src/editor/interface/Cursor.ts b/src/editor/interface/Cursor.ts index 0558db9..b1176dd 100644 --- a/src/editor/interface/Cursor.ts +++ b/src/editor/interface/Cursor.ts @@ -1,6 +1,6 @@ export interface ICursorOption { - width?: number; - color?: string; - dragWidth?: number; - dragColor?: string; -} \ No newline at end of file + width?: number + color?: string + dragWidth?: number + dragColor?: string +} diff --git a/src/editor/interface/Draw.ts b/src/editor/interface/Draw.ts index 8a40eb2..13ba2cd 100644 --- a/src/editor/interface/Draw.ts +++ b/src/editor/interface/Draw.ts @@ -3,44 +3,44 @@ import { IElement, IElementPosition } from './Element' import { IRow } from './Row' export interface IDrawOption { - curIndex?: number; - isSetCursor?: boolean; - isSubmitHistory?: boolean; - isCompute?: boolean; - isLazy?: boolean; + curIndex?: number + isSetCursor?: boolean + isSubmitHistory?: boolean + isCompute?: boolean + isLazy?: boolean } export interface IDrawImagePayload { - width: number; - height: number; - value: string; + width: number + height: number + value: string } export interface IDrawRowPayload { - elementList: IElement[]; - positionList: IElementPosition[]; - rowList: IRow[]; - pageNo: number; - startIndex: number; - innerWidth: number; - zone?: EditorZone; + elementList: IElement[] + positionList: IElementPosition[] + rowList: IRow[] + pageNo: number + startIndex: number + innerWidth: number + zone?: EditorZone } export interface IDrawPagePayload { - elementList: IElement[]; - positionList: IElementPosition[]; - rowList: IRow[]; - pageNo: number; + elementList: IElement[] + positionList: IElementPosition[] + rowList: IRow[] + pageNo: number } export interface IPainterOption { - isDblclick: boolean; + isDblclick: boolean } export interface IGetValueOption { - pageNo?: number; + pageNo?: number } export interface IAppendElementListOption { - isPrepend?: boolean; -} \ No newline at end of file + isPrepend?: boolean +} diff --git a/src/editor/interface/Editor.ts b/src/editor/interface/Editor.ts index da08596..7168954 100644 --- a/src/editor/interface/Editor.ts +++ b/src/editor/interface/Editor.ts @@ -1,5 +1,10 @@ import { IElement } from '..' -import { EditorMode, PageMode, PaperDirection, WordBreak } from '../dataset/enum/Editor' +import { + EditorMode, + PageMode, + PaperDirection, + WordBreak +} from '../dataset/enum/Editor' import { ICheckboxOption } from './Checkbox' import { IControlOption } from './Control' import { ICursorOption } from './Cursor' @@ -12,64 +17,64 @@ import { ITitleOption } from './Title' import { IWatermark } from './Watermark' export interface IEditorData { - header?: IElement[]; - main: IElement[]; - footer?: IElement[]; + header?: IElement[] + main: IElement[] + footer?: IElement[] } export interface IEditorOption { - mode?: EditorMode; - defaultType?: string; - defaultFont?: string; - defaultSize?: number; - minSize?: number; - maxSize?: number; - defaultBasicRowMarginHeight?: number; - defaultRowMargin?: number; - defaultTabWidth?: number; - width?: number; - height?: number; - scale?: number; - pageGap?: number; - underlineColor?: string; - strikeoutColor?: string; - rangeColor?: string; - rangeAlpha?: number; - rangeMinWidth?: number; - searchMatchColor?: string; - searchNavigateMatchColor?: string; - searchMatchAlpha?: number; - highlightAlpha?: number; - resizerColor?: string; - resizerSize?: number; - marginIndicatorSize?: number; - marginIndicatorColor?: string, - margins?: IMargin, - pageMode?: PageMode; - tdPadding?: number; - defaultTrMinHeight?: number; - defaultColMinWidth?: number; - defaultHyperlinkColor?: string; - paperDirection?: PaperDirection; - inactiveAlpha?: number; - historyMaxRecordCount?: number; - wordBreak?: WordBreak; - header?: IHeader; - footer?: IFooter; - pageNumber?: IPageNumber; - watermark?: IWatermark; - control?: IControlOption; - checkbox?: ICheckboxOption; - cursor?: ICursorOption; - title?: ITitleOption; - placeholder?: IPlaceholder; + mode?: EditorMode + defaultType?: string + defaultFont?: string + defaultSize?: number + minSize?: number + maxSize?: number + defaultBasicRowMarginHeight?: number + defaultRowMargin?: number + defaultTabWidth?: number + width?: number + height?: number + scale?: number + pageGap?: number + underlineColor?: string + strikeoutColor?: string + rangeColor?: string + rangeAlpha?: number + rangeMinWidth?: number + searchMatchColor?: string + searchNavigateMatchColor?: string + searchMatchAlpha?: number + highlightAlpha?: number + resizerColor?: string + resizerSize?: number + marginIndicatorSize?: number + marginIndicatorColor?: string + margins?: IMargin + pageMode?: PageMode + tdPadding?: number + defaultTrMinHeight?: number + defaultColMinWidth?: number + defaultHyperlinkColor?: string + paperDirection?: PaperDirection + inactiveAlpha?: number + historyMaxRecordCount?: number + wordBreak?: WordBreak + header?: IHeader + footer?: IFooter + pageNumber?: IPageNumber + watermark?: IWatermark + control?: IControlOption + checkbox?: ICheckboxOption + cursor?: ICursorOption + title?: ITitleOption + placeholder?: IPlaceholder } export interface IEditorResult { - version: string; - width: number; - height: number; - margins: IMargin; - watermark?: IWatermark; - data: IEditorData; -} \ No newline at end of file + version: string + width: number + height: number + margins: IMargin + watermark?: IWatermark + data: IEditorData +} diff --git a/src/editor/interface/Element.ts b/src/editor/interface/Element.ts index 28e6eed..deba7f4 100644 --- a/src/editor/interface/Element.ts +++ b/src/editor/interface/Element.ts @@ -11,86 +11,86 @@ import { IColgroup } from './table/Colgroup' import { ITr } from './table/Tr' export interface IElementBasic { - id?: string; - type?: ElementType; - value: string; + id?: string + type?: ElementType + value: string } export interface IElementStyle { - font?: string; - size?: number; - width?: number; - height?: number; - bold?: boolean; - color?: string; - highlight?: string; - italic?: boolean; - underline?: boolean; - strikeout?: boolean; - rowFlex?: RowFlex; - rowMargin?: number; - letterSpacing?: number; + font?: string + size?: number + width?: number + height?: number + bold?: boolean + color?: string + highlight?: string + italic?: boolean + underline?: boolean + strikeout?: boolean + rowFlex?: RowFlex + rowMargin?: number + letterSpacing?: number } export interface ITitleElement { - valueList?: IElement[]; - level?: TitleLevel; - titleId?: string; + valueList?: IElement[] + level?: TitleLevel + titleId?: string } export interface IListElement { - valueList?: IElement[]; - listType?: ListType; - listStyle?: ListStyle; - listId?: string; - listWrap?: boolean; + valueList?: IElement[] + listType?: ListType + listStyle?: ListStyle + listId?: string + listWrap?: boolean } export interface ITableAttr { - colgroup?: IColgroup[]; - trList?: ITr[]; - borderType?: TableBorder; + colgroup?: IColgroup[] + trList?: ITr[] + borderType?: TableBorder } export interface ITableElement { - tdId?: string; - trId?: string; - tableId?: string; + tdId?: string + trId?: string + tableId?: string } export type ITable = ITableAttr & ITableElement export interface IHyperlinkElement { - valueList?: IElement[]; - url?: string; - hyperlinkId?: string; + valueList?: IElement[] + url?: string + hyperlinkId?: string } export interface ISuperscriptSubscript { - actualSize?: number; + actualSize?: number } export interface ISeparator { - dashArray?: number[]; + dashArray?: number[] } export interface IControlElement { - control?: IControl; - controlId?: string; - controlComponent?: ControlComponent; + control?: IControl + controlId?: string + controlComponent?: ControlComponent } export interface ICheckboxElement { - checkbox?: ICheckbox; + checkbox?: ICheckbox } export interface ILaTexElement { - laTexSVG?: string; + laTexSVG?: string } export interface IDateElement { - dateFormat?: string; - dateId?: string; + dateFormat?: string + dateId?: string } export interface IImageElement { @@ -98,52 +98,52 @@ export interface IImageElement { } export interface IBlockElement { - block?: IBlock; -} - -export type IElement = IElementBasic - & IElementStyle - & ITable - & IHyperlinkElement - & ISuperscriptSubscript - & ISeparator - & IControlElement - & ICheckboxElement - & ILaTexElement - & IDateElement - & IImageElement - & IBlockElement - & ITitleElement - & IListElement + block?: IBlock +} + +export type IElement = IElementBasic & + IElementStyle & + ITable & + IHyperlinkElement & + ISuperscriptSubscript & + ISeparator & + IControlElement & + ICheckboxElement & + ILaTexElement & + IDateElement & + IImageElement & + IBlockElement & + ITitleElement & + IListElement export interface IElementMetrics { - width: number; - height: number; - boundingBoxAscent: number; - boundingBoxDescent: number; + width: number + height: number + boundingBoxAscent: number + boundingBoxDescent: number } export interface IElementPosition { - pageNo: number; - index: number; - value: string, - rowIndex: number; - rowNo: number; - ascent: number; - lineHeight: number; - metrics: IElementMetrics; - isLastLetter: boolean, + pageNo: number + index: number + value: string + rowIndex: number + rowNo: number + ascent: number + lineHeight: number + metrics: IElementMetrics + isLastLetter: boolean coordinate: { - leftTop: number[]; - leftBottom: number[]; - rightTop: number[]; - rightBottom: number[]; + leftTop: number[] + leftBottom: number[] + rightTop: number[] + rightBottom: number[] } } export interface IElementFillRect { - x: number; - y: number; - width: number; - height: number; -} \ No newline at end of file + x: number + y: number + width: number + height: number +} diff --git a/src/editor/interface/Footer.ts b/src/editor/interface/Footer.ts index 4dfec7a..f7beaff 100644 --- a/src/editor/interface/Footer.ts +++ b/src/editor/interface/Footer.ts @@ -1,7 +1,7 @@ import { MaxHeightRatio } from '../dataset/enum/Common' export interface IFooter { - bottom?: number; - maxHeightRadio?: MaxHeightRatio; - disabled?: boolean; -} \ No newline at end of file + bottom?: number + maxHeightRadio?: MaxHeightRatio + disabled?: boolean +} diff --git a/src/editor/interface/Header.ts b/src/editor/interface/Header.ts index 5cbeb92..c59daa2 100644 --- a/src/editor/interface/Header.ts +++ b/src/editor/interface/Header.ts @@ -1,7 +1,7 @@ import { MaxHeightRatio } from '../dataset/enum/Common' export interface IHeader { - top?: number; - maxHeightRadio?: MaxHeightRatio; - disabled?: boolean; -} \ No newline at end of file + top?: number + maxHeightRadio?: MaxHeightRatio + disabled?: boolean +} diff --git a/src/editor/interface/Listener.ts b/src/editor/interface/Listener.ts index 2a899d5..e0a57b1 100644 --- a/src/editor/interface/Listener.ts +++ b/src/editor/interface/Listener.ts @@ -1,27 +1,34 @@ -import { EditorZone, ElementType, ListStyle, ListType, PageMode, TitleLevel } from '..' +import { + EditorZone, + ElementType, + ListStyle, + ListType, + PageMode, + TitleLevel +} from '..' import { RowFlex } from '../dataset/enum/Row' import { IControl } from './Control' import { IEditorResult } from './Editor' export interface IRangeStyle { - type: ElementType | null; - undo: boolean; - redo: boolean; - painter: boolean; - font: string; - size: number; - bold: boolean; - italic: boolean; - underline: boolean; - strikeout: boolean; - color: string | null; - highlight: string | null; - rowFlex: RowFlex | null; - rowMargin: number; - dashArray: number[]; - level: TitleLevel | null; - listType: ListType | null; - listStyle: ListStyle | null; + type: ElementType | null + undo: boolean + redo: boolean + painter: boolean + font: string + size: number + bold: boolean + italic: boolean + underline: boolean + strikeout: boolean + color: string | null + highlight: string | null + rowFlex: RowFlex | null + rowMargin: number + dashArray: number[] + level: TitleLevel | null + listType: ListType | null + listStyle: ListStyle | null } export type IRangeStyleChange = (payload: IRangeStyle) => void @@ -42,4 +49,4 @@ export type IControlChange = (payload: IControl | null) => void export type IPageModeChange = (payload: PageMode) => void -export type IZoneChange = (payload: EditorZone) => void \ No newline at end of file +export type IZoneChange = (payload: EditorZone) => void diff --git a/src/editor/interface/Margin.ts b/src/editor/interface/Margin.ts index 64ad02b..e4d995d 100644 --- a/src/editor/interface/Margin.ts +++ b/src/editor/interface/Margin.ts @@ -1 +1 @@ -export type IMargin = [top: number, right: number, bottom: number, left: number] \ No newline at end of file +export type IMargin = [top: number, right: number, bottom: number, left: number] diff --git a/src/editor/interface/PageNumber.ts b/src/editor/interface/PageNumber.ts index 9ef2495..3cdc09a 100644 --- a/src/editor/interface/PageNumber.ts +++ b/src/editor/interface/PageNumber.ts @@ -2,14 +2,14 @@ import { NumberType } from '../dataset/enum/Common' import { RowFlex } from '../dataset/enum/Row' export interface IPageNumber { - bottom?: number; - size?: number; - font?: string; - color?: string; - rowFlex?: RowFlex; - format?: string; - numberType?: NumberType; - disabled?: boolean; - startPageNo?: number; - fromPageNo?: number; -} \ No newline at end of file + bottom?: number + size?: number + font?: string + color?: string + rowFlex?: RowFlex + format?: string + numberType?: NumberType + disabled?: boolean + startPageNo?: number + fromPageNo?: number +} diff --git a/src/editor/interface/Placeholder.ts b/src/editor/interface/Placeholder.ts index 290e530..e226c00 100644 --- a/src/editor/interface/Placeholder.ts +++ b/src/editor/interface/Placeholder.ts @@ -1,7 +1,7 @@ export interface IPlaceholder { - data: string; - color?: string; - opacity?: number; - size?: number; - font?: string; -} \ No newline at end of file + data: string + color?: string + opacity?: number + size?: number + font?: string +} diff --git a/src/editor/interface/Plugin.ts b/src/editor/interface/Plugin.ts index 26d458d..f0f2210 100644 --- a/src/editor/interface/Plugin.ts +++ b/src/editor/interface/Plugin.ts @@ -1,5 +1,8 @@ import Editor from '..' -export type PluginFunction = (editor: Editor, options?: Options) => any; +export type PluginFunction = (editor: Editor, options?: Options) => any -export type UsePlugin = (pluginFunction: PluginFunction, options?: Options) => void; \ No newline at end of file +export type UsePlugin = ( + pluginFunction: PluginFunction, + options?: Options +) => void diff --git a/src/editor/interface/Position.ts b/src/editor/interface/Position.ts index 75594ae..69d1e6f 100644 --- a/src/editor/interface/Position.ts +++ b/src/editor/interface/Position.ts @@ -5,56 +5,56 @@ import { IRow } from './Row' import { ITd } from './table/Td' export interface ICurrentPosition { - index: number; - isCheckbox?: boolean; - isControl?: boolean; - isImage?: boolean; - isTable?: boolean; - isDirectHit?: boolean; - trIndex?: number; - tdIndex?: number; - tdValueIndex?: number; - tdId?: string; - trId?: string; - tableId?: string; - zone?: EditorZone; + index: number + isCheckbox?: boolean + isControl?: boolean + isImage?: boolean + isTable?: boolean + isDirectHit?: boolean + trIndex?: number + tdIndex?: number + tdValueIndex?: number + tdId?: string + trId?: string + tableId?: string + zone?: EditorZone } export interface IGetPositionByXYPayload { - x: number; - y: number; - isTable?: boolean; - td?: ITd; - tablePosition?: IElementPosition; - elementList?: IElement[]; - positionList?: IElementPosition[]; + x: number + y: number + isTable?: boolean + td?: ITd + tablePosition?: IElementPosition + elementList?: IElement[] + positionList?: IElementPosition[] } export interface IPositionContext { - isTable: boolean; - isCheckbox?: boolean; - isControl?: boolean; - index?: number; - trIndex?: number; - tdIndex?: number; - tdId?: string; - trId?: string; - tableId?: string; + isTable: boolean + isCheckbox?: boolean + isControl?: boolean + index?: number + trIndex?: number + tdIndex?: number + tdId?: string + trId?: string + tableId?: string } export interface IComputePageRowPositionPayload { - positionList: IElementPosition[]; - rowList: IRow[]; - pageNo: number; - startRowIndex: number; - startIndex: number; - startX: number; - startY: number; - innerWidth: number; + positionList: IElementPosition[] + rowList: IRow[] + pageNo: number + startRowIndex: number + startIndex: number + startX: number + startY: number + innerWidth: number } export interface IComputePageRowPositionResult { - x: number; - y: number; - index: number; -} \ No newline at end of file + x: number + y: number + index: number +} diff --git a/src/editor/interface/Previewer.ts b/src/editor/interface/Previewer.ts index af69bc3..848e81c 100644 --- a/src/editor/interface/Previewer.ts +++ b/src/editor/interface/Previewer.ts @@ -1,13 +1,13 @@ import { IElement } from './Element' export interface IPreviewerCreateResult { - resizerSelection: HTMLDivElement; - resizerHandleList: HTMLDivElement[]; - resizerImageContainer: HTMLDivElement; - resizerImage: HTMLImageElement; + resizerSelection: HTMLDivElement + resizerHandleList: HTMLDivElement[] + resizerImageContainer: HTMLDivElement + resizerImage: HTMLImageElement } export interface IPreviewerDrawOption { - mime?: 'png' | 'jpg' | 'jpeg' | 'svg'; - srcKey?: keyof Pick; -} \ No newline at end of file + mime?: 'png' | 'jpg' | 'jpeg' | 'svg' + srcKey?: keyof Pick +} diff --git a/src/editor/interface/Range.ts b/src/editor/interface/Range.ts index 05ae3f9..0ffed54 100644 --- a/src/editor/interface/Range.ts +++ b/src/editor/interface/Range.ts @@ -2,15 +2,15 @@ import { EditorZone } from '../dataset/enum/Editor' import { IElement } from './Element' export interface IRange { - startIndex: number; - endIndex: number; - isCrossRowCol?: boolean; - tableId?: string; - startTdIndex?: number; - endTdIndex?: number; - startTrIndex?: number; - endTrIndex?: number; - zone?: EditorZone; + startIndex: number + endIndex: number + isCrossRowCol?: boolean + tableId?: string + startTdIndex?: number + endTdIndex?: number + startTrIndex?: number + endTrIndex?: number + zone?: EditorZone } export type RangeRowArray = Map @@ -18,9 +18,9 @@ export type RangeRowArray = Map export type RangeRowMap = Map> export type RangeContext = { - isCollapsed: boolean; - startElement: IElement; - endElement: IElement; - startPageNo: number; - endPageNo: number; -} \ No newline at end of file + isCollapsed: boolean + startElement: IElement + endElement: IElement + startPageNo: number + endPageNo: number +} diff --git a/src/editor/interface/Row.ts b/src/editor/interface/Row.ts index a46c07a..19f31de 100644 --- a/src/editor/interface/Row.ts +++ b/src/editor/interface/Row.ts @@ -2,19 +2,19 @@ import { RowFlex } from '../dataset/enum/Row' import { IElement, IElementMetrics } from './Element' export type IRowElement = IElement & { - metrics: IElementMetrics; - style: string; + metrics: IElementMetrics + style: string } export interface IRow { - width: number; - height: number; - ascent: number; - rowFlex?: RowFlex; - startIndex: number; - isPageBreak?: boolean; - isList?: boolean; - listIndex?: number; - offsetX?: number; - elementList: IRowElement[]; + width: number + height: number + ascent: number + rowFlex?: RowFlex + startIndex: number + isPageBreak?: boolean + isList?: boolean + listIndex?: number + offsetX?: number + elementList: IRowElement[] } diff --git a/src/editor/interface/Search.ts b/src/editor/interface/Search.ts index e8e5d7e..72ea175 100644 --- a/src/editor/interface/Search.ts +++ b/src/editor/interface/Search.ts @@ -1,17 +1,17 @@ import { EditorContext } from '../dataset/enum/Editor' export interface ISearchResultBasic { - type: EditorContext; - index: number; - groupId: string; + type: EditorContext + index: number + groupId: string } export interface ISearchResultRestArgs { - tableIndex?: number; - trIndex?: number; - tdIndex?: number; - tdId?: string; - startIndex?: number; + tableIndex?: number + trIndex?: number + tdIndex?: number + tdId?: string + startIndex?: number } -export type ISearchResult = ISearchResultBasic & ISearchResultRestArgs \ No newline at end of file +export type ISearchResult = ISearchResultBasic & ISearchResultRestArgs diff --git a/src/editor/interface/Title.ts b/src/editor/interface/Title.ts index ef04ca2..48f13e6 100644 --- a/src/editor/interface/Title.ts +++ b/src/editor/interface/Title.ts @@ -1,10 +1,10 @@ export interface ITitleSizeOption { - defaultFirstSize?: number; - defaultSecondSize?: number; - defaultThirdSize?: number; - defaultFourthSize?: number; - defaultFifthSize?: number; - defaultSixthSize?: number; + defaultFirstSize?: number + defaultSecondSize?: number + defaultThirdSize?: number + defaultFourthSize?: number + defaultFifthSize?: number + defaultSixthSize?: number } -export type ITitleOption = ITitleSizeOption & {} \ No newline at end of file +export type ITitleOption = ITitleSizeOption & {} diff --git a/src/editor/interface/Watermark.ts b/src/editor/interface/Watermark.ts index 4be763c..bf1c395 100644 --- a/src/editor/interface/Watermark.ts +++ b/src/editor/interface/Watermark.ts @@ -1,7 +1,7 @@ export interface IWatermark { - data: string; - color?: string; - opacity?: number; - size?: number; - font?: string; -} \ No newline at end of file + data: string + color?: string + opacity?: number + size?: number + font?: string +} diff --git a/src/editor/interface/contextmenu/ContextMenu.ts b/src/editor/interface/contextmenu/ContextMenu.ts index a156515..ba41fee 100644 --- a/src/editor/interface/contextmenu/ContextMenu.ts +++ b/src/editor/interface/contextmenu/ContextMenu.ts @@ -2,62 +2,62 @@ import { Command } from '../../core/command/Command' import { IElement } from '../Element' export interface IContextMenuContext { - startElement: IElement | null; - endElement: IElement | null; - isReadonly: boolean; - editorHasSelection: boolean; - editorTextFocus: boolean; - isInTable: boolean; - isCrossRowCol: boolean; + startElement: IElement | null + endElement: IElement | null + isReadonly: boolean + editorHasSelection: boolean + editorTextFocus: boolean + isInTable: boolean + isCrossRowCol: boolean } export interface IRegisterContextMenu { - i18nPath?: string; - isDivider?: boolean; - icon?: string; - name?: string; - shortCut?: string; - when?: (payload: IContextMenuContext) => boolean; - callback?: (command: Command, context: IContextMenuContext) => any; - childMenus?: IRegisterContextMenu[]; + i18nPath?: string + isDivider?: boolean + icon?: string + name?: string + shortCut?: string + when?: (payload: IContextMenuContext) => boolean + callback?: (command: Command, context: IContextMenuContext) => any + childMenus?: IRegisterContextMenu[] } export interface IContextmenuLang { global: { - cut: string; - copy: string; - paste: string; - selectAll: string; - print: string; - }; + cut: string + copy: string + paste: string + selectAll: string + print: string + } control: { - delete: string; - }; + delete: string + } hyperlink: { - delete: string; - cancel: string; - edit: string; - }; + delete: string + cancel: string + edit: string + } image: { - change: string; - saveAs: string; - textWrap: string; + change: string + saveAs: string + textWrap: string textWrapType: { - embed: string; - upDown: string; + embed: string + upDown: string } - }; + } table: { - insertRowCol: string; - insertTopRow: string; - insertBottomRow: string; - insertLeftCol: string; - insertRightCol: string; - deleteRowCol: string; - deleteRow: string; - deleteCol: string; - deleteTable: string; - mergeCell: string; - mergeCancelCell: string; - }; -} \ No newline at end of file + insertRowCol: string + insertTopRow: string + insertBottomRow: string + insertLeftCol: string + insertRightCol: string + deleteRowCol: string + deleteRow: string + deleteCol: string + deleteTable: string + mergeCell: string + mergeCancelCell: string + } +} diff --git a/src/editor/interface/i18n/I18n.ts b/src/editor/interface/i18n/I18n.ts index 10ff980..f7e7a1b 100644 --- a/src/editor/interface/i18n/I18n.ts +++ b/src/editor/interface/i18n/I18n.ts @@ -2,6 +2,6 @@ import { IDatePickerLang } from '../../core/draw/particle/date/DatePicker' import { IContextmenuLang } from '../contextmenu/ContextMenu' export interface ILang { - contextmenu: IContextmenuLang; - datePicker: IDatePickerLang; + contextmenu: IContextmenuLang + datePicker: IDatePickerLang } diff --git a/src/editor/interface/shortcut/Shortcut.ts b/src/editor/interface/shortcut/Shortcut.ts index add9b09..d224c2b 100644 --- a/src/editor/interface/shortcut/Shortcut.ts +++ b/src/editor/interface/shortcut/Shortcut.ts @@ -2,12 +2,12 @@ import { Command } from '../../core/command/Command' import { KeyMap } from '../../dataset/enum/KeyMap' export interface IRegisterShortcut { - key: KeyMap; - ctrl?: boolean; - meta?: boolean; - mod?: boolean; // windows:ctrl || mac:command - shift?: boolean; - alt?: boolean; // windows:alt || mac:option - isGlobal?: boolean; - callback: (command: Command) => any; -} \ No newline at end of file + key: KeyMap + ctrl?: boolean + meta?: boolean + mod?: boolean // windows:ctrl || mac:command + shift?: boolean + alt?: boolean // windows:alt || mac:option + isGlobal?: boolean + callback: (command: Command) => any +} diff --git a/src/editor/interface/table/Colgroup.ts b/src/editor/interface/table/Colgroup.ts index 5a85ad1..2a7d467 100644 --- a/src/editor/interface/table/Colgroup.ts +++ b/src/editor/interface/table/Colgroup.ts @@ -1,4 +1,4 @@ export interface IColgroup { - id?: string; - width: number; -} \ No newline at end of file + id?: string + width: number +} diff --git a/src/editor/interface/table/Td.ts b/src/editor/interface/table/Td.ts index 1e8105b..c35e41b 100644 --- a/src/editor/interface/table/Td.ts +++ b/src/editor/interface/table/Td.ts @@ -3,24 +3,24 @@ import { IElement, IElementPosition } from '../Element' import { IRow } from '../Row' export interface ITd { - id?: string; - x?: number; - y?: number; - width?: number; - height?: number; - colspan: number; - rowspan: number; - value: IElement[]; - isLastRowTd?: boolean; - isLastColTd?: boolean; - isLastTd?: boolean; - rowIndex?: number; - colIndex?: number; - rowList?: IRow[]; - positionList?: IElementPosition[]; - verticalAlign?: VerticalAlign; - backgroundColor?: string; - mainHeight?: number; // 内容 + 内边距高度 - realHeight?: number; // 真实高度(包含跨列) - realMinHeight?: number; // 真实最小高度(包含跨列) -} \ No newline at end of file + id?: string + x?: number + y?: number + width?: number + height?: number + colspan: number + rowspan: number + value: IElement[] + isLastRowTd?: boolean + isLastColTd?: boolean + isLastTd?: boolean + rowIndex?: number + colIndex?: number + rowList?: IRow[] + positionList?: IElementPosition[] + verticalAlign?: VerticalAlign + backgroundColor?: string + mainHeight?: number // 内容 + 内边距高度 + realHeight?: number // 真实高度(包含跨列) + realMinHeight?: number // 真实最小高度(包含跨列) +} diff --git a/src/editor/interface/table/Tr.ts b/src/editor/interface/table/Tr.ts index 57457e4..0cebc7a 100644 --- a/src/editor/interface/table/Tr.ts +++ b/src/editor/interface/table/Tr.ts @@ -1,8 +1,8 @@ import { ITd } from './Td' export interface ITr { - id?: string; - height: number; - tdList: ITd[]; - minHeight?: number; -} \ No newline at end of file + id?: string + height: number + tdList: ITd[] + minHeight?: number +} diff --git a/src/editor/types/index.d.ts b/src/editor/types/index.d.ts index cb69423..8c46597 100644 --- a/src/editor/types/index.d.ts +++ b/src/editor/types/index.d.ts @@ -1,5 +1,5 @@ // 部分浏览器canvas上下文支持设置以下属性 interface CanvasRenderingContext2D { - letterSpacing: string; - wordSpacing: string; -} \ No newline at end of file + letterSpacing: string + wordSpacing: string +} diff --git a/src/editor/utils/clipboard.ts b/src/editor/utils/clipboard.ts index 8cdecb8..d08d618 100644 --- a/src/editor/utils/clipboard.ts +++ b/src/editor/utils/clipboard.ts @@ -1,8 +1,17 @@ import { IEditorOption, IElement, ListStyle, ListType, RowFlex } from '..' import { ZERO } from '../dataset/constant/Common' -import { INLINE_NODE_NAME, TEXTLIKE_ELEMENT_TYPE } from '../dataset/constant/Element' -import { listStyleCSSMapping, listTypeElementMapping } from '../dataset/constant/List' -import { titleNodeNameMapping, titleOrderNumberMapping } from '../dataset/constant/Title' +import { + INLINE_NODE_NAME, + TEXTLIKE_ELEMENT_TYPE +} from '../dataset/constant/Element' +import { + listStyleCSSMapping, + listTypeElementMapping +} from '../dataset/constant/List' +import { + titleNodeNameMapping, + titleOrderNumberMapping +} from '../dataset/constant/Title' import { ControlComponent } from '../dataset/enum/Control' import { ElementType } from '../dataset/enum/Element' import { DeepRequired } from '../interface/Common' @@ -37,13 +46,19 @@ export function writeClipboardItem(text: string, html: string) { } } -export function convertElementToDom(element: IElement, options: DeepRequired): HTMLElement { +export function convertElementToDom( + element: IElement, + options: DeepRequired +): HTMLElement { let tagName: keyof HTMLElementTagNameMap = 'span' if (element.type === ElementType.SUPERSCRIPT) { tagName = 'sup' } else if (element.type === ElementType.SUBSCRIPT) { tagName = 'sub' - } else if (element.rowFlex === RowFlex.CENTER || element.rowFlex === RowFlex.RIGHT) { + } else if ( + element.rowFlex === RowFlex.CENTER || + element.rowFlex === RowFlex.RIGHT + ) { tagName = 'p' } const dom = document.createElement(tagName) @@ -69,7 +84,10 @@ export function convertElementToDom(element: IElement, options: DeepRequired) { +export function writeElementList( + elementList: IElement[], + options: DeepRequired +) { function buildDomFromElementList(payload: IElement[]): HTMLDivElement { const clipboardDom = document.createElement('div') for (let e = 0; e < payload.length; e++) { @@ -105,12 +123,18 @@ export function writeElementList(elementList: IElement[], options: DeepRequired< } clipboardDom.append(a) } else if (element.type === ElementType.TITLE) { - const h = document.createElement(`h${titleOrderNumberMapping[element.level!]}`) - const childDom = buildDomFromElementList(zipElementList(element.valueList!)) + const h = document.createElement( + `h${titleOrderNumberMapping[element.level!]}` + ) + const childDom = buildDomFromElementList( + zipElementList(element.valueList!) + ) h.innerHTML = childDom.innerHTML clipboardDom.append(h) } else if (element.type === ElementType.LIST) { - const list = document.createElement(listTypeElementMapping[element.listType!]) + const list = document.createElement( + listTypeElementMapping[element.listType!] + ) if (element.listStyle) { list.style.listStyleType = listStyleCSSMapping[element.listStyle] } @@ -134,7 +158,7 @@ export function writeElementList(elementList: IElement[], options: DeepRequired< const listElementList = listElementListMap.get(curListIndex) || [] listElementList.push({ ...zipElement, - value, + value }) listElementListMap.set(curListIndex, listElementList) } @@ -166,9 +190,9 @@ export function writeElementList(elementList: IElement[], options: DeepRequired< } clipboardDom.append(checkbox) } else if ( - !element.type - || element.type === ElementType.LATEX - || TEXTLIKE_ELEMENT_TYPE.includes(element.type) + !element.type || + element.type === ElementType.LATEX || + TEXTLIKE_ELEMENT_TYPE.includes(element.type) ) { let text = '' if (element.type === ElementType.CONTROL) { @@ -201,12 +225,15 @@ export function writeElementList(elementList: IElement[], options: DeepRequired< writeClipboardItem(text, html) } -export function convertTextNodeToElement(textNode: Element | Node): IElement | null { +export function convertTextNodeToElement( + textNode: Element | Node +): IElement | null { if (!textNode || textNode.nodeType !== 3) return null const parentNode = textNode.parentNode - const anchorNode = parentNode.nodeName === 'FONT' - ? parentNode.parentNode - : parentNode + const anchorNode = + parentNode.nodeName === 'FONT' + ? parentNode.parentNode + : parentNode const rowFlex = getElementRowFlex(anchorNode) const value = textNode.textContent const style = window.getComputedStyle(anchorNode) @@ -236,10 +263,13 @@ export function convertTextNodeToElement(textNode: Element | Node): IElement | n } interface IGetElementListByHTMLOption { - innerWidth: number; + innerWidth: number } -export function getElementListByHTML(htmlText: string, options: IGetElementListByHTMLOption): IElement[] { +export function getElementListByHTML( + htmlText: string, + options: IGetElementListByHTMLOption +): IElement[] { const elementList: IElement[] = [] function findTextNode(dom: Element | Node) { if (dom.nodeType === 3) { @@ -263,9 +293,11 @@ export function getElementListByHTML(htmlText: string, options: IGetElementListB elementList.push({ type: ElementType.HYPERLINK, value: '', - valueList: [{ - value - }], + valueList: [ + { + value + } + ], url: aElement.href }) } @@ -278,7 +310,10 @@ export function getElementListByHTML(htmlText: string, options: IGetElementListB level: titleNodeNameMapping[node.nodeName], valueList }) - if (node.nextSibling && !INLINE_NODE_NAME.includes(node.nextSibling.nodeName)) { + if ( + node.nextSibling && + !INLINE_NODE_NAME.includes(node.nextSibling.nodeName) + ) { elementList.push({ value: '\n' }) @@ -294,7 +329,9 @@ export function getElementListByHTML(htmlText: string, options: IGetElementListB listElement.listType = ListType.OL } else { listElement.listType = ListType.UL - listElement.listStyle = listNode.style.listStyleType + listElement.listStyle = ( + (listNode.style.listStyleType) + ) } listNode.querySelectorAll('li').forEach(li => { const liValueList = getElementListByHTML(li.innerHTML, options) @@ -312,7 +349,7 @@ export function getElementListByHTML(htmlText: string, options: IGetElementListB } else if (node.nodeName === 'HR') { elementList.push({ value: '\n', - type: ElementType.SEPARATOR, + type: ElementType.SEPARATOR }) } else if (node.nodeName === 'IMG') { const { src, width, height } = node as HTMLImageElement @@ -334,14 +371,19 @@ export function getElementListByHTML(htmlText: string, options: IGetElementListB } // 基础数据 tableElement.querySelectorAll('tr').forEach(trElement => { - const trHeightStr = window.getComputedStyle(trElement).height.replace('px', '') + const trHeightStr = window + .getComputedStyle(trElement) + .height.replace('px', '') const tr: ITr = { height: Number(trHeightStr), tdList: [] } trElement.querySelectorAll('th,td').forEach(tdElement => { const tableCell = tdElement - const valueList = getElementListByHTML(tableCell.innerHTML, options) + const valueList = getElementListByHTML( + tableCell.innerHTML, + options + ) const td: ITd = { colspan: tableCell.colSpan, rowspan: tableCell.rowSpan, @@ -358,7 +400,10 @@ export function getElementListByHTML(htmlText: string, options: IGetElementListB }) if (element.trList!.length) { // 列选项数据 - const tdCount = element.trList![0].tdList.reduce((pre, cur) => pre + cur.colspan, 0) + const tdCount = element.trList![0].tdList.reduce( + (pre, cur) => pre + cur.colspan, + 0 + ) const width = Math.ceil(options.innerWidth / tdCount) for (let i = 0; i < tdCount; i++) { element.colgroup!.push({ @@ -367,7 +412,10 @@ export function getElementListByHTML(htmlText: string, options: IGetElementListB } elementList.push(element) } - } else if (node.nodeName === 'INPUT' && (node).type === ControlComponent.CHECKBOX) { + } else if ( + node.nodeName === 'INPUT' && + (node).type === ControlComponent.CHECKBOX + ) { elementList.push({ type: ElementType.CHECKBOX, value: '', diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts index eb23a1c..62f8068 100644 --- a/src/editor/utils/element.ts +++ b/src/editor/utils/element.ts @@ -4,7 +4,12 @@ import { LaTexParticle } from '../core/draw/particle/latex/LaTexParticle' import { defaultCheckboxOption } from '../dataset/constant/Checkbox' import { ZERO } from '../dataset/constant/Common' import { defaultControlOption } from '../dataset/constant/Control' -import { EDITOR_ELEMENT_CONTEXT_ATTR, EDITOR_ELEMENT_ZIP_ATTR, TABLE_CONTEXT_ATTR, TEXTLIKE_ELEMENT_TYPE } from '../dataset/constant/Element' +import { + EDITOR_ELEMENT_CONTEXT_ATTR, + EDITOR_ELEMENT_ZIP_ATTR, + TABLE_CONTEXT_ATTR, + TEXTLIKE_ELEMENT_TYPE +} from '../dataset/constant/Element' import { titleSizeMapping } from '../dataset/constant/Title' import { ControlComponent, ControlType } from '../dataset/enum/Control' import { ITd } from '../interface/table/Td' @@ -22,17 +27,24 @@ export function unzipElementList(elementList: IElement[]): IElement[] { } interface IFormatElementListOption { - isHandleFirstElement?: boolean; - editorOptions: Required; + isHandleFirstElement?: boolean + editorOptions: Required } -export function formatElementList(elementList: IElement[], options: IFormatElementListOption) { +export function formatElementList( + elementList: IElement[], + options: IFormatElementListOption +) { const { isHandleFirstElement, editorOptions } = { isHandleFirstElement: true, ...options } const startElement = elementList[0] - if (isHandleFirstElement && startElement?.value !== ZERO && startElement?.value !== '\n') { + if ( + isHandleFirstElement && + startElement?.value !== ZERO && + startElement?.value !== '\n' + ) { elementList.unshift({ value: ZERO }) @@ -103,7 +115,10 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme const tr = el.trList[t] const trId = getUUID() tr.id = trId - if (!tr.minHeight || tr.minHeight < editorOptions.defaultTrMinHeight) { + if ( + !tr.minHeight || + tr.minHeight < editorOptions.defaultTrMinHeight + ) { tr.minHeight = editorOptions.defaultTrMinHeight } if (tr.height < tr.minHeight) { @@ -163,7 +178,8 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme } i-- } else if (el.type === ElementType.CONTROL) { - const { prefix, postfix, value, placeholder, code, type, valueSets } = el.control! + const { prefix, postfix, value, placeholder, code, type, valueSets } = + el.control! const controlId = getUUID() // 移除父节点 elementList.splice(i, 1) @@ -198,7 +214,10 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme if (Array.isArray(valueSets) && valueSets.length) { // 拆分valueList优先使用其属性 const valueStyleList = valueList.reduce( - (pre, cur) => pre.concat(cur.value.split('').map(v => ({ ...cur, value: v }))), + (pre, cur) => + pre.concat( + cur.value.split('').map(v => ({ ...cur, value: v })) + ), [] as IElement[] ) let valueStyleIndex = 0 @@ -241,9 +260,11 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme if (Array.isArray(valueSets) && valueSets.length) { const valueSet = valueSets.find(v => v.code === code) if (valueSet) { - valueList = [{ - value: valueSet.value - }] + valueList = [ + { + value: valueSet.value + } + ] } } } @@ -299,7 +320,10 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme i++ } i-- - } else if ((!el.type || el.type === ElementType.TEXT) && el.value.length > 1) { + } else if ( + (!el.type || el.type === ElementType.TEXT) && + el.value.length > 1 + ) { elementList.splice(i, 1) const valueList = splitText(el.value) for (let v = 0; v < valueList.length; v++) { @@ -324,7 +348,10 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme } } -export function isSameElementExceptValue(source: IElement, target: IElement): boolean { +export function isSameElementExceptValue( + source: IElement, + target: IElement +): boolean { const sourceKeys = Object.keys(source) const targetKeys = Object.keys(target) if (sourceKeys.length !== targetKeys.length) return false @@ -340,7 +367,7 @@ export function isSameElementExceptValue(source: IElement, target: IElement): bo export function pickElementAttr(payload: IElement): IElement { const element: IElement = { - value: payload.value === ZERO ? `\n` : payload.value, + value: payload.value === ZERO ? `\n` : payload.value } EDITOR_ELEMENT_ZIP_ATTR.forEach(attr => { const value = payload[attr] as never @@ -358,7 +385,11 @@ export function zipElementList(payload: IElement[]): IElement[] { while (e < elementList.length) { let element = elementList[e] // 上下文首字符(占位符) - if (e === 0 && element.value === ZERO && (!element.type || element.type === ElementType.TEXT)) { + if ( + e === 0 && + element.value === ZERO && + (!element.type || element.type === ElementType.TEXT) + ) { e++ continue } @@ -505,19 +536,20 @@ export function zipElementList(payload: IElement[]): IElement[] { // 组合元素 const pickElement = pickElementAttr(element) if ( - !element.type - || element.type === ElementType.TEXT - || element.type === ElementType.SUBSCRIPT - || element.type === ElementType.SUPERSCRIPT + !element.type || + element.type === ElementType.TEXT || + element.type === ElementType.SUBSCRIPT || + element.type === ElementType.SUPERSCRIPT ) { while (e < elementList.length) { const nextElement = elementList[e + 1] e++ if ( - nextElement - && isSameElementExceptValue(pickElement, pickElementAttr(nextElement)) + nextElement && + isSameElementExceptValue(pickElement, pickElementAttr(nextElement)) ) { - const nextValue = nextElement.value === ZERO ? '\n' : nextElement.value + const nextValue = + nextElement.value === ZERO ? '\n' : nextElement.value pickElement.value += nextValue } else { break @@ -553,37 +585,62 @@ export function isTextLikeElement(element: IElement): boolean { return !element.type || TEXTLIKE_ELEMENT_TYPE.includes(element.type) } -export function getAnchorElement(elementList: IElement[], anchorIndex: number): IElement | null { +export function getAnchorElement( + elementList: IElement[], + anchorIndex: number +): IElement | null { const anchorElement = elementList[anchorIndex] if (!anchorElement) return null const anchorNextElement = elementList[anchorIndex + 1] // 非列表元素 && 当前元素是换行符 && 下一个元素不是换行符 则以下一个元素作为参考元素 - return !anchorElement.listId && anchorElement.value === ZERO && anchorNextElement && anchorNextElement.value !== ZERO + return !anchorElement.listId && + anchorElement.value === ZERO && + anchorNextElement && + anchorNextElement.value !== ZERO ? anchorNextElement : anchorElement } export interface IFormatElementContextOption { - isBreakWhenWrap: boolean; + isBreakWhenWrap: boolean } -export function formatElementContext(sourceElementList: IElement[], formatElementList: IElement[], anchorIndex: number, options?: IFormatElementContextOption) { +export function formatElementContext( + sourceElementList: IElement[], + formatElementList: IElement[], + anchorIndex: number, + options?: IFormatElementContextOption +) { const copyElement = getAnchorElement(sourceElementList, anchorIndex) if (!copyElement) return const { isBreakWhenWrap = false } = options || {} for (let e = 0; e < formatElementList.length; e++) { const targetElement = formatElementList[e] - if (isBreakWhenWrap && !copyElement.listId && /^\n/.test(targetElement.value)) break + if ( + isBreakWhenWrap && + !copyElement.listId && + /^\n/.test(targetElement.value) + ) { + break + } // 定位元素非列表,无需处理粘贴列表的上下文 if (!copyElement.listId && targetElement.type === ElementType.LIST) { - targetElement.valueList?.forEach((valueItem) => { + targetElement.valueList?.forEach(valueItem => { cloneProperty(TABLE_CONTEXT_ATTR, copyElement, valueItem) }) continue } if (targetElement.valueList?.length) { - formatElementContext(sourceElementList, targetElement.valueList, anchorIndex) + formatElementContext( + sourceElementList, + targetElement.valueList, + anchorIndex + ) } - cloneProperty(EDITOR_ELEMENT_CONTEXT_ATTR, copyElement, targetElement) + cloneProperty( + EDITOR_ELEMENT_CONTEXT_ATTR, + copyElement, + targetElement + ) } -} \ No newline at end of file +} diff --git a/src/editor/utils/hotkey.ts b/src/editor/utils/hotkey.ts index fafa078..93c54f9 100644 --- a/src/editor/utils/hotkey.ts +++ b/src/editor/utils/hotkey.ts @@ -2,4 +2,4 @@ import { isApple } from './ua' export function isMod(evt: KeyboardEvent | MouseEvent) { return isApple ? evt.metaKey : evt.ctrlKey -} \ No newline at end of file +} diff --git a/src/editor/utils/index.ts b/src/editor/utils/index.ts index c956df3..5babafe 100644 --- a/src/editor/utils/index.ts +++ b/src/editor/utils/index.ts @@ -18,9 +18,9 @@ export function deepClone(obj: T): T { if (Array.isArray(obj)) { newObj = obj.map(item => deepClone(item)) } else { - Object.keys(obj as any).forEach((key) => { + Object.keys(obj as any).forEach(key => { // @ts-ignore - return newObj[key] = deepClone(obj[key]) + return (newObj[key] = deepClone(obj[key])) }) } return newObj @@ -30,14 +30,16 @@ export function isBody(node: Element): boolean { return node && node.nodeType === 1 && node.tagName.toLowerCase() === 'body' } -export function findParent(node: Element, filterFn: Function, includeSelf: boolean) { +export function findParent( + node: Element, + filterFn: Function, + includeSelf: boolean +) { if (node && !isBody(node)) { - node = includeSelf ? node : node.parentNode as Element + node = includeSelf ? node : (node.parentNode as Element) while (node) { if (!filterFn || filterFn(node) || isBody(node)) { - return filterFn && !filterFn(node) && isBody(node) - ? null - : node + return filterFn && !filterFn(node) && isBody(node) ? null : node } node = node.parentNode as Element } @@ -49,7 +51,20 @@ export function getUUID(): string { function S4(): string { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1) } - return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4()) + return ( + S4() + + S4() + + '-' + + S4() + + '-' + + S4() + + '-' + + S4() + + '-' + + S4() + + S4() + + S4() + ) } export function splitText(text: string): string[] { @@ -71,13 +86,17 @@ export function threeClick(dom: HTMLElement, fn: (evt: MouseEvent) => any) { nClickEvent(3, dom, fn) } -function nClickEvent(n: number, dom: HTMLElement, fn: (evt: MouseEvent) => any) { +function nClickEvent( + n: number, + dom: HTMLElement, + fn: (evt: MouseEvent) => any +) { let count = 0 let lastTime = 0 const handler = function (evt: MouseEvent) { const currentTime = new Date().getTime() - count = (currentTime - lastTime < 300) ? count + 1 : 0 + count = currentTime - lastTime < 300 ? count + 1 : 0 lastTime = new Date().getTime() if (count >= n - 1) { fn(evt) @@ -119,8 +138,37 @@ export function nextTick(fn: Function) { } export function convertNumberToChinese(num: number) { - const chineseNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'] - const chineseUnit = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万', '十', '百', '千', '亿'] + const chineseNum = [ + '零', + '一', + '二', + '三', + '四', + '五', + '六', + '七', + '八', + '九' + ] + const chineseUnit = [ + '', + '十', + '百', + '千', + '万', + '十', + '百', + '千', + '亿', + '十', + '百', + '千', + '万', + '十', + '百', + '千', + '亿' + ] if (!num || isNaN(num)) return '零' const numStr = num.toString().split('') let result = '' @@ -138,7 +186,11 @@ export function convertNumberToChinese(num: number) { return result } -export function cloneProperty(properties: (keyof T)[], sourceElement: T, targetElement: T) { +export function cloneProperty( + properties: (keyof T)[], + sourceElement: T, + targetElement: T +) { for (let i = 0; i < properties.length; i++) { const property = properties[i] const value = sourceElement[property] @@ -156,4 +208,4 @@ export function convertStringToBase64(input: string) { const charArray = Array.from(data, byte => String.fromCharCode(byte)) const base64 = window.btoa(charArray.join('')) return base64 -} \ No newline at end of file +} diff --git a/src/editor/utils/print.ts b/src/editor/utils/print.ts index 7522890..5f96e3a 100644 --- a/src/editor/utils/print.ts +++ b/src/editor/utils/print.ts @@ -1,4 +1,8 @@ -export function printImageBase64(base64List: string[], width: number, height: number) { +export function printImageBase64( + base64List: string[], + width: number, + height: number +) { const iframe = document.createElement('iframe') // 离屏渲染 iframe.style.visibility = 'hidden' @@ -28,10 +32,14 @@ export function printImageBase64(base64List: string[], width: number, height: nu contentWindow.print() doc.close() // 移除iframe - window.addEventListener('mouseover', () => { - iframe?.remove() - }, { - once: true - }) + window.addEventListener( + 'mouseover', + () => { + iframe?.remove() + }, + { + once: true + } + ) }) -} \ No newline at end of file +} diff --git a/src/editor/utils/ua.ts b/src/editor/utils/ua.ts index cce6f74..ba1fb34 100644 --- a/src/editor/utils/ua.ts +++ b/src/editor/utils/ua.ts @@ -1 +1,2 @@ -export const isApple = typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent) \ No newline at end of file +export const isApple = + typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent) diff --git a/src/main.ts b/src/main.ts index 63e0ddc..8b0c3d3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,37 +1,60 @@ import { data, options } from './mock' import './style.css' import prism from 'prismjs' -import Editor, { BlockType, Command, ControlType, EditorMode, ElementType, IBlock, ICatalogItem, IElement, KeyMap, ListStyle, ListType, PageMode, PaperDirection, RowFlex, TitleLevel } from './editor' +import Editor, { + BlockType, + Command, + ControlType, + EditorMode, + ElementType, + IBlock, + ICatalogItem, + IElement, + KeyMap, + ListStyle, + ListType, + PageMode, + PaperDirection, + RowFlex, + TitleLevel +} from './editor' import { Dialog } from './components/dialog/Dialog' import { formatPrismToken } from './utils/prism' import { Signature } from './components/signature/Signature' import { debounce } from './utils' window.onload = function () { - const isApple = typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent) + const isApple = + typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent) // 1. 初始化编辑器 const container = document.querySelector('.editor')! const instance = new Editor( container, { - header: [{ - value: '第一人民医院', - size: 32, - rowFlex: RowFlex.CENTER - }, { - value: '\n门诊病历', - size: 18, - rowFlex: RowFlex.CENTER - }, { - value: '\n', - type: ElementType.SEPARATOR - }], + header: [ + { + value: '第一人民医院', + size: 32, + rowFlex: RowFlex.CENTER + }, + { + value: '\n门诊病历', + size: 18, + rowFlex: RowFlex.CENTER + }, + { + value: '\n', + type: ElementType.SEPARATOR + } + ], main: data, - footer: [{ - value: 'canvas-editor', - size: 12 - }] + footer: [ + { + value: 'canvas-editor', + size: 12 + } + ] }, options ) @@ -40,13 +63,17 @@ window.onload = function () { Reflect.set(window, 'editor', instance) // 菜单弹窗销毁 - window.addEventListener('click', (evt) => { - const visibleDom = document.querySelector('.visible') - if (!visibleDom || visibleDom.contains(evt.target)) return - visibleDom.classList.remove('visible') - }, { - capture: true - }) + window.addEventListener( + 'click', + evt => { + const visibleDom = document.querySelector('.visible') + if (!visibleDom || visibleDom.contains(evt.target)) return + visibleDom.classList.remove('visible') + }, + { + capture: true + } + ) // 2. | 撤销 | 重做 | 格式刷 | 清除格式 | const undoDom = document.querySelector('.menu-item__undo')! @@ -63,7 +90,9 @@ window.onload = function () { instance.command.executeRedo() } - const painterDom = document.querySelector('.menu-item__painter')! + const painterDom = document.querySelector( + '.menu-item__painter' + )! painterDom.onclick = function () { console.log('painter') instance.command.executePainter({ @@ -77,10 +106,11 @@ window.onload = function () { }) } - document.querySelector('.menu-item__format')!.onclick = function () { - console.log('format') - instance.command.executeFormat() - } + document.querySelector('.menu-item__format')!.onclick = + function () { + console.log('format') + instance.command.executeFormat() + } // 3. | 字体 | 字体变大 | 字体变小 | 加粗 | 斜体 | 下划线 | 删除线 | 上标 | 下标 | 字体颜色 | 背景色 | const fontDom = document.querySelector('.menu-item__font')! @@ -108,14 +138,18 @@ window.onload = function () { instance.command.executeSize(Number(li.dataset.size!)) } - const sizeAddDom = document.querySelector('.menu-item__size-add')! + const sizeAddDom = document.querySelector( + '.menu-item__size-add' + )! sizeAddDom.title = `增大字号(${isApple ? '⌘' : 'Ctrl'}+[)` sizeAddDom.onclick = function () { console.log('size-add') instance.command.executeSizeAdd() } - const sizeMinusDom = document.querySelector('.menu-item__size-minus')! + const sizeMinusDom = document.querySelector( + '.menu-item__size-minus' + )! sizeMinusDom.title = `减小字号(${isApple ? '⌘' : 'Ctrl'}+])` sizeMinusDom.onclick = function () { console.log('size-minus') @@ -129,34 +163,43 @@ window.onload = function () { instance.command.executeBold() } - const italicDom = document.querySelector('.menu-item__italic')! + const italicDom = + document.querySelector('.menu-item__italic')! italicDom.title = `斜体(${isApple ? '⌘' : 'Ctrl'}+I)` italicDom.onclick = function () { console.log('italic') instance.command.executeItalic() } - const underlineDom = document.querySelector('.menu-item__underline')! + const underlineDom = document.querySelector( + '.menu-item__underline' + )! underlineDom.title = `下划线(${isApple ? '⌘' : 'Ctrl'}+U)` underlineDom.onclick = function () { console.log('underline') instance.command.executeUnderline() } - const strikeoutDom = document.querySelector('.menu-item__strikeout')! + const strikeoutDom = document.querySelector( + '.menu-item__strikeout' + )! strikeoutDom.onclick = function () { console.log('strikeout') instance.command.executeStrikeout() } - const superscriptDom = document.querySelector('.menu-item__superscript')! + const superscriptDom = document.querySelector( + '.menu-item__superscript' + )! superscriptDom.title = `上标(${isApple ? '⌘' : 'Ctrl'}+Shift+,)` superscriptDom.onclick = function () { console.log('superscript') instance.command.executeSuperscript() } - const subscriptDom = document.querySelector('.menu-item__subscript')! + const subscriptDom = document.querySelector( + '.menu-item__subscript' + )! subscriptDom.title = `下标(${isApple ? '⌘' : 'Ctrl'}+Shift+.)` subscriptDom.onclick = function () { console.log('subscript') @@ -174,11 +217,14 @@ window.onload = function () { colorControlDom.click() } - const highlightControlDom = document.querySelector('#highlight')! + const highlightControlDom = + document.querySelector('#highlight')! highlightControlDom.oninput = function () { instance.command.executeHighlight(highlightControlDom.value) } - const highlightDom = document.querySelector('.menu-item__highlight')! + const highlightDom = document.querySelector( + '.menu-item__highlight' + )! const highlightSpanDom = highlightDom.querySelector('span')! highlightDom.onclick = function () { console.log('highlight') @@ -209,7 +255,8 @@ window.onload = function () { instance.command.executeRowFlex(RowFlex.LEFT) } - const centerDom = document.querySelector('.menu-item__center')! + const centerDom = + document.querySelector('.menu-item__center')! centerDom.title = `居中对齐(${isApple ? '⌘' : 'Ctrl'}+E)` centerDom.onclick = function () { console.log('center') @@ -223,14 +270,18 @@ window.onload = function () { instance.command.executeRowFlex(RowFlex.RIGHT) } - const alignmentDom = document.querySelector('.menu-item__alignment')! + const alignmentDom = document.querySelector( + '.menu-item__alignment' + )! alignmentDom.title = `两端对齐(${isApple ? '⌘' : 'Ctrl'}+J)` alignmentDom.onclick = function () { console.log('alignment') instance.command.executeRowFlex(RowFlex.ALIGNMENT) } - const rowMarginDom = document.querySelector('.menu-item__row-margin')! + const rowMarginDom = document.querySelector( + '.menu-item__row-margin' + )! const rowOptionDom = rowMarginDom.querySelector('.options')! rowMarginDom.onclick = function () { console.log('row-margin') @@ -251,13 +302,15 @@ window.onload = function () { listOptionDom.onclick = function (evt) { const li = evt.target as HTMLLIElement const listType = li.dataset.listType || null - const listStyle = li.dataset.listStyle + const listStyle = (li.dataset.listStyle) instance.command.executeList(listType, listStyle) } // 4. | 表格 | 图片 | 超链接 | 分割线 | 水印 | 代码块 | 分隔符 | 控件 | 复选框 | LaTeX | 日期选择器 const tableDom = document.querySelector('.menu-item__table')! - const tablePanelContainer = document.querySelector('.menu-item__table__collapse')! + const tablePanelContainer = document.querySelector( + '.menu-item__table__collapse' + )! const tableClose = document.querySelector('.table-close')! const tableTitle = document.querySelector('.table-select')! const tablePanel = document.querySelector('.table-panel')! @@ -349,32 +402,37 @@ window.onload = function () { instance.command.executeImage({ value, width: image.width, - height: image.height, + height: image.height }) imageFileDom.value = '' } } } - const hyperlinkDom = document.querySelector('.menu-item__hyperlink')! + const hyperlinkDom = document.querySelector( + '.menu-item__hyperlink' + )! hyperlinkDom.onclick = function () { console.log('hyperlink') new Dialog({ title: '超链接', - data: [{ - type: 'text', - label: '文本', - name: 'name', - required: true, - placeholder: '请输入文本' - }, { - type: 'text', - label: '链接', - name: 'url', - required: true, - placeholder: '请输入链接' - }], - onConfirm: (payload) => { + data: [ + { + type: 'text', + label: '文本', + name: 'name', + required: true, + placeholder: '请输入文本' + }, + { + type: 'text', + label: '链接', + name: 'url', + required: true, + placeholder: '请输入链接' + } + ], + onConfirm: payload => { const name = payload.find(p => p.name === 'name')?.value if (!name) return const url = payload.find(p => p.name === 'url')?.value @@ -392,8 +450,11 @@ window.onload = function () { }) } - const separatorDom = document.querySelector('.menu-item__separator')! - const separatorOptionDom = separatorDom.querySelector('.options')! + const separatorDom = document.querySelector( + '.menu-item__separator' + )! + const separatorOptionDom = + separatorDom.querySelector('.options')! separatorDom.onclick = function () { console.log('separator') separatorOptionDom.classList.toggle('visible') @@ -411,14 +472,19 @@ window.onload = function () { instance.command.executeSeparator(payload) } - const pageBreakDom = document.querySelector('.menu-item__page-break')! + const pageBreakDom = document.querySelector( + '.menu-item__page-break' + )! pageBreakDom.onclick = function () { console.log('pageBreak') instance.command.executePageBreak() } - const watermarkDom = document.querySelector('.menu-item__watermark')! - const watermarkOptionDom = watermarkDom.querySelector('.options')! + const watermarkDom = document.querySelector( + '.menu-item__watermark' + )! + const watermarkOptionDom = + watermarkDom.querySelector('.options')! watermarkDom.onclick = function () { console.log('watermark') watermarkOptionDom.classList.toggle('visible') @@ -430,26 +496,30 @@ window.onload = function () { if (menu === 'add') { new Dialog({ title: '水印', - data: [{ - type: 'text', - label: '内容', - name: 'data', - required: true, - placeholder: '请输入内容' - }, { - type: 'color', - label: '颜色', - name: 'color', - required: true, - value: '#AEB5C0' - }, { - type: 'number', - label: '字体大小', - name: 'size', - required: true, - value: '120' - }], - onConfirm: (payload) => { + data: [ + { + type: 'text', + label: '内容', + name: 'data', + required: true, + placeholder: '请输入内容' + }, + { + type: 'color', + label: '颜色', + name: 'color', + required: true, + value: '#AEB5C0' + }, + { + type: 'number', + label: '字体大小', + name: 'size', + required: true, + value: '120' + } + ], + onConfirm: payload => { const nullableIndex = payload.findIndex(p => !p.value) if (~nullableIndex) return const watermark = payload.reduce((pre, cur) => { @@ -468,19 +538,23 @@ window.onload = function () { } } - const codeblockDom = document.querySelector('.menu-item__codeblock')! + const codeblockDom = document.querySelector( + '.menu-item__codeblock' + )! codeblockDom.onclick = function () { console.log('codeblock') new Dialog({ title: '代码块', - data: [{ - type: 'textarea', - name: 'codeblock', - placeholder: '请输入代码', - width: 500, - height: 300 - }], - onConfirm: (payload) => { + data: [ + { + type: 'textarea', + name: 'codeblock', + placeholder: '请输入代码', + width: 500, + height: 300 + } + ], + onConfirm: payload => { const codeblock = payload.find(p => p.name === 'codeblock')?.value if (!codeblock) return const tokenList = prism.tokenize(codeblock, prism.languages.javascript) @@ -514,7 +588,9 @@ window.onload = function () { }) } - const controlDom = document.querySelector('.menu-item__control')! + const controlDom = document.querySelector( + '.menu-item__control' + )! const controlOptionDom = controlDom.querySelector('.options')! controlDom.onclick = function () { console.log('control') @@ -528,110 +604,132 @@ window.onload = function () { case ControlType.TEXT: new Dialog({ title: '文本控件', - data: [{ - type: 'text', - label: '占位符', - name: 'placeholder', - required: true, - placeholder: '请输入占位符' - }, { - type: 'text', - label: '默认值', - name: 'value', - placeholder: '请输入默认值' - }], - onConfirm: (payload) => { - const placeholder = payload.find(p => p.name === 'placeholder')?.value + data: [ + { + type: 'text', + label: '占位符', + name: 'placeholder', + required: true, + placeholder: '请输入占位符' + }, + { + type: 'text', + label: '默认值', + name: 'value', + placeholder: '请输入默认值' + } + ], + onConfirm: payload => { + const placeholder = payload.find( + p => p.name === 'placeholder' + )?.value if (!placeholder) return const value = payload.find(p => p.name === 'value')?.value || '' - instance.command.executeInsertElementList([{ - type: ElementType.CONTROL, - value: '', - control: { - type, - value: value - ? [{ - value - }] - : null, - placeholder + instance.command.executeInsertElementList([ + { + type: ElementType.CONTROL, + value: '', + control: { + type, + value: value + ? [ + { + value + } + ] + : null, + placeholder + } } - }]) + ]) } }) break case ControlType.SELECT: new Dialog({ title: '列举控件', - data: [{ - type: 'text', - label: '占位符', - name: 'placeholder', - required: true, - placeholder: '请输入占位符' - }, { - type: 'text', - label: '默认值', - name: 'code', - placeholder: '请输入默认值' - }, { - type: 'textarea', - label: '值集', - name: 'valueSets', - required: true, - height: 100, - placeholder: `请输入值集JSON,例:\n[{\n"value":"有",\n"code":"98175"\n}]` - }], - onConfirm: (payload) => { - const placeholder = payload.find(p => p.name === 'placeholder')?.value + data: [ + { + type: 'text', + label: '占位符', + name: 'placeholder', + required: true, + placeholder: '请输入占位符' + }, + { + type: 'text', + label: '默认值', + name: 'code', + placeholder: '请输入默认值' + }, + { + type: 'textarea', + label: '值集', + name: 'valueSets', + required: true, + height: 100, + placeholder: `请输入值集JSON,例:\n[{\n"value":"有",\n"code":"98175"\n}]` + } + ], + onConfirm: payload => { + const placeholder = payload.find( + p => p.name === 'placeholder' + )?.value if (!placeholder) return const valueSets = payload.find(p => p.name === 'valueSets')?.value if (!valueSets) return const code = payload.find(p => p.name === 'code')?.value - instance.command.executeInsertElementList([{ - type: ElementType.CONTROL, - value: '', - control: { - type, - code, - value: null, - placeholder, - valueSets: JSON.parse(valueSets) + instance.command.executeInsertElementList([ + { + type: ElementType.CONTROL, + value: '', + control: { + type, + code, + value: null, + placeholder, + valueSets: JSON.parse(valueSets) + } } - }]) + ]) } }) break case ControlType.CHECKBOX: new Dialog({ title: '复选框控件', - data: [{ - type: 'text', - label: '默认值', - name: 'code', - placeholder: '请输入默认值,多个值以英文逗号分割' - }, { - type: 'textarea', - label: '值集', - name: 'valueSets', - required: true, - height: 100, - placeholder: `请输入值集JSON,例:\n[{\n"value":"有",\n"code":"98175"\n}]` - }], - onConfirm: (payload) => { + data: [ + { + type: 'text', + label: '默认值', + name: 'code', + placeholder: '请输入默认值,多个值以英文逗号分割' + }, + { + type: 'textarea', + label: '值集', + name: 'valueSets', + required: true, + height: 100, + placeholder: `请输入值集JSON,例:\n[{\n"value":"有",\n"code":"98175"\n}]` + } + ], + onConfirm: payload => { const valueSets = payload.find(p => p.name === 'valueSets')?.value if (!valueSets) return const code = payload.find(p => p.name === 'code')?.value - instance.command.executeInsertElementList([{ - type: ElementType.CONTROL, - value: '', - control: { - type, - code, - value: null, - valueSets: JSON.parse(valueSets) + instance.command.executeInsertElementList([ + { + type: ElementType.CONTROL, + value: '', + control: { + type, + code, + value: null, + valueSets: JSON.parse(valueSets) + } } - }]) + ]) } }) break @@ -640,13 +738,17 @@ window.onload = function () { } } - const checkboxDom = document.querySelector('.menu-item__checkbox')! + const checkboxDom = document.querySelector( + '.menu-item__checkbox' + )! checkboxDom.onclick = function () { console.log('checkbox') - instance.command.executeInsertElementList([{ - type: ElementType.CHECKBOX, - value: '' - }]) + instance.command.executeInsertElementList([ + { + type: ElementType.CHECKBOX, + value: '' + } + ]) } const latexDom = document.querySelector('.menu-item__latex')! @@ -654,19 +756,23 @@ window.onload = function () { console.log('LaTeX') new Dialog({ title: 'LaTeX', - data: [{ - type: 'textarea', - height: 100, - name: 'value', - placeholder: '请输入LaTeX文本' - }], - onConfirm: (payload) => { + data: [ + { + type: 'textarea', + height: 100, + name: 'value', + placeholder: '请输入LaTeX文本' + } + ], + onConfirm: payload => { const value = payload.find(p => p.name === 'value')?.value if (!value) return - instance.command.executeInsertElementList([{ - type: ElementType.LATEX, - value - }]) + instance.command.executeInsertElementList([ + { + type: ElementType.LATEX, + value + } + ]) } }) } @@ -696,21 +802,27 @@ window.onload = function () { const second = date.getSeconds().toString().padStart(2, '0') const dateString = `${year}-${month}-${day}` const dateTimeString = `${dateString} ${hour}:${minute}:${second}` - dateDomOptionDom.querySelector('li:first-child')!.innerText = dateString - dateDomOptionDom.querySelector('li:last-child')!.innerText = dateTimeString + dateDomOptionDom.querySelector('li:first-child')!.innerText = + dateString + dateDomOptionDom.querySelector('li:last-child')!.innerText = + dateTimeString } dateDomOptionDom.onmousedown = function (evt) { const li = evt.target as HTMLLIElement const dateFormat = li.dataset.format! dateDomOptionDom.classList.toggle('visible') - instance.command.executeInsertElementList([{ - type: ElementType.DATE, - value: '', - dateFormat, - valueList: [{ - value: li.innerText.trim(), - }] - }]) + instance.command.executeInsertElementList([ + { + type: ElementType.DATE, + value: '', + dateFormat, + valueList: [ + { + value: li.innerText.trim() + } + ] + } + ]) } const blockDom = document.querySelector('.menu-item__block')! @@ -718,39 +830,47 @@ window.onload = function () { console.log('block') new Dialog({ title: '内容块', - data: [{ - type: 'select', - label: '类型', - name: 'type', - value: 'iframe', - required: true, - options: [{ - label: '网址', - value: 'iframe' - }, { - label: '视频', - value: 'video' - }] - }, { - type: 'number', - label: '宽度', - name: 'width', - placeholder: '请输入宽度(默认页面内宽度)' - }, { - type: 'number', - label: '高度', - name: 'height', - required: true, - placeholder: '请输入高度' - }, { - type: 'textarea', - label: '地址', - height: 100, - name: 'value', - required: true, - placeholder: '请输入地址' - }], - onConfirm: (payload) => { + data: [ + { + type: 'select', + label: '类型', + name: 'type', + value: 'iframe', + required: true, + options: [ + { + label: '网址', + value: 'iframe' + }, + { + label: '视频', + value: 'video' + } + ] + }, + { + type: 'number', + label: '宽度', + name: 'width', + placeholder: '请输入宽度(默认页面内宽度)' + }, + { + type: 'number', + label: '高度', + name: 'height', + required: true, + placeholder: '请输入高度' + }, + { + type: 'textarea', + label: '地址', + height: 100, + name: 'value', + required: true, + placeholder: '请输入地址' + } + ], + onConfirm: payload => { const type = payload.find(p => p.name === 'type')?.value if (!type) return const value = payload.find(p => p.name === 'value')?.value @@ -785,12 +905,20 @@ window.onload = function () { } // 5. | 搜索&替换 | 打印 | - const searchCollapseDom = document.querySelector('.menu-item__search__collapse')! - const searchInputDom = document.querySelector('.menu-item__search__collapse__search input')! - const replaceInputDom = document.querySelector('.menu-item__search__collapse__replace input')! - const searchDom = document.querySelector('.menu-item__search')! + const searchCollapseDom = document.querySelector( + '.menu-item__search__collapse' + )! + const searchInputDom = document.querySelector( + '.menu-item__search__collapse__search input' + )! + const replaceInputDom = document.querySelector( + '.menu-item__search__collapse__replace input' + )! + const searchDom = + document.querySelector('.menu-item__search')! searchDom.title = `搜索与替换(${isApple ? '⌘' : 'Ctrl'}+F)` - const searchResultDom = searchCollapseDom.querySelector('.search-result')! + const searchResultDom = + searchCollapseDom.querySelector('.search-result')! function setSearchResult() { const result = instance.command.getSearchNavigateInfo() if (result) { @@ -814,13 +942,14 @@ window.onload = function () { } searchInputDom.focus() } - searchCollapseDom.querySelector('span')!.onclick = function () { - searchCollapseDom.style.display = 'none' - searchInputDom.value = '' - replaceInputDom.value = '' - instance.command.executeSearch(null) - setSearchResult() - } + searchCollapseDom.querySelector('span')!.onclick = + function () { + searchCollapseDom.style.display = 'none' + searchInputDom.value = '' + replaceInputDom.value = '' + instance.command.executeSearch(null) + setSearchResult() + } searchInputDom.oninput = function () { instance.command.executeSearch(searchInputDom.value || null) setSearchResult() @@ -831,21 +960,24 @@ window.onload = function () { setSearchResult() } } - searchCollapseDom.querySelector('button')!.onclick = function () { - const searchValue = searchInputDom.value - const replaceValue = replaceInputDom.value - if (searchValue && replaceValue && searchValue !== replaceValue) { - instance.command.executeReplace(replaceValue) + searchCollapseDom.querySelector('button')!.onclick = + function () { + const searchValue = searchInputDom.value + const replaceValue = replaceInputDom.value + if (searchValue && replaceValue && searchValue !== replaceValue) { + instance.command.executeReplace(replaceValue) + } + } + searchCollapseDom.querySelector('.arrow-left')!.onclick = + function () { + instance.command.executeSearchNavigatePre() + setSearchResult() + } + searchCollapseDom.querySelector('.arrow-right')!.onclick = + function () { + instance.command.executeSearchNavigateNext() + setSearchResult() } - } - searchCollapseDom.querySelector('.arrow-left')!.onclick = function () { - instance.command.executeSearchNavigatePre() - setSearchResult() - } - searchCollapseDom.querySelector('.arrow-right')!.onclick = function () { - instance.command.executeSearchNavigateNext() - setSearchResult() - } const printDom = document.querySelector('.menu-item__print')! printDom.title = `打印(${isApple ? '⌘' : 'Ctrl'}+P)` @@ -857,10 +989,14 @@ window.onload = function () { // 6. 目录显隐 | 页面模式 | 纸张缩放 | 纸张大小 | 纸张方向 | 页边距 | 全屏 async function updateCatalog() { const catalog = await instance.command.getCatalog() - const catalogMainDom = document.querySelector('.catalog__main')! + const catalogMainDom = + document.querySelector('.catalog__main')! catalogMainDom.innerHTML = '' if (catalog) { - const appendCatalog = (parent: HTMLDivElement, catalogItems: ICatalogItem[]) => { + const appendCatalog = ( + parent: HTMLDivElement, + catalogItems: ICatalogItem[] + ) => { for (let c = 0; c < catalogItems.length; c++) { const catalogItem = catalogItems[c] const catalogItemDom = document.createElement('div') @@ -888,8 +1024,11 @@ window.onload = function () { } let isCatalogShow = true const catalogDom = document.querySelector('.catalog')! - const catalogModeDom = document.querySelector('.catalog-mode')! - const catalogHeaderCloseDom = document.querySelector('.catalog__header__close')! + const catalogModeDom = + document.querySelector('.catalog-mode')! + const catalogHeaderCloseDom = document.querySelector( + '.catalog__header__close' + )! const switchCatalog = () => { isCatalogShow = !isCatalogShow if (isCatalogShow) { @@ -903,7 +1042,8 @@ window.onload = function () { catalogHeaderCloseDom.onclick = switchCatalog const pageModeDom = document.querySelector('.page-mode')! - const pageModeOptionsDom = pageModeDom.querySelector('.options')! + const pageModeOptionsDom = + pageModeDom.querySelector('.options')! pageModeDom.onclick = function () { pageModeOptionsDom.classList.toggle('visible') } @@ -912,24 +1052,28 @@ window.onload = function () { instance.command.executePageMode(li.dataset.pageMode!) } - document.querySelector('.page-scale-percentage')!.onclick = function () { - console.log('page-scale-recovery') - instance.command.executePageScaleRecovery() - } + document.querySelector('.page-scale-percentage')!.onclick = + function () { + console.log('page-scale-recovery') + instance.command.executePageScaleRecovery() + } - document.querySelector('.page-scale-minus')!.onclick = function () { - console.log('page-scale-minus') - instance.command.executePageScaleMinus() - } + document.querySelector('.page-scale-minus')!.onclick = + function () { + console.log('page-scale-minus') + instance.command.executePageScaleMinus() + } - document.querySelector('.page-scale-add')!.onclick = function () { - console.log('page-scale-add') - instance.command.executePageScaleAdd() - } + document.querySelector('.page-scale-add')!.onclick = + function () { + console.log('page-scale-add') + instance.command.executePageScaleAdd() + } // 纸张大小 const paperSizeDom = document.querySelector('.paper-size')! - const paperSizeDomOptionsDom = paperSizeDom.querySelector('.options')! + const paperSizeDomOptionsDom = + paperSizeDom.querySelector('.options')! paperSizeDom.onclick = function () { paperSizeDomOptionsDom.classList.toggle('visible') } @@ -939,14 +1083,17 @@ window.onload = function () { const [width, height] = paperType.split('*').map(Number) instance.command.executePaperSize(width, height) // 纸张状态回显 - paperSizeDomOptionsDom.querySelectorAll('li') + paperSizeDomOptionsDom + .querySelectorAll('li') .forEach(child => child.classList.remove('active')) li.classList.add('active') } // 纸张方向 - const paperDirectionDom = document.querySelector('.paper-direction')! - const paperDirectionDomOptionsDom = paperDirectionDom.querySelector('.options')! + const paperDirectionDom = + document.querySelector('.paper-direction')! + const paperDirectionDomOptionsDom = + paperDirectionDom.querySelector('.options')! paperDirectionDom.onclick = function () { paperDirectionDomOptionsDom.classList.toggle('visible') } @@ -955,47 +1102,55 @@ window.onload = function () { const paperDirection = li.dataset.paperDirection! instance.command.executePaperDirection(paperDirection) // 纸张方向状态回显 - paperDirectionDomOptionsDom.querySelectorAll('li') + paperDirectionDomOptionsDom + .querySelectorAll('li') .forEach(child => child.classList.remove('active')) li.classList.add('active') } // 页面边距 - const paperMarginDom = document.querySelector('.paper-margin')! + const paperMarginDom = + document.querySelector('.paper-margin')! paperMarginDom.onclick = function () { - const [topMargin, rightMargin, bottomMargin, leftMargin] = instance.command.getPaperMargin() + const [topMargin, rightMargin, bottomMargin, leftMargin] = + instance.command.getPaperMargin() new Dialog({ title: '页边距', - data: [{ - type: 'text', - label: '上边距', - name: 'top', - required: true, - value: `${topMargin}`, - placeholder: '请输入上边距' - }, { - type: 'text', - label: '下边距', - name: 'bottom', - required: true, - value: `${bottomMargin}`, - placeholder: '请输入下边距' - }, { - type: 'text', - label: '左边距', - name: 'left', - required: true, - value: `${leftMargin}`, - placeholder: '请输入左边距' - }, { - type: 'text', - label: '右边距', - name: 'right', - required: true, - value: `${rightMargin}`, - placeholder: '请输入右边距' - }], - onConfirm: (payload) => { + data: [ + { + type: 'text', + label: '上边距', + name: 'top', + required: true, + value: `${topMargin}`, + placeholder: '请输入上边距' + }, + { + type: 'text', + label: '下边距', + name: 'bottom', + required: true, + value: `${bottomMargin}`, + placeholder: '请输入下边距' + }, + { + type: 'text', + label: '左边距', + name: 'left', + required: true, + value: `${leftMargin}`, + placeholder: '请输入左边距' + }, + { + type: 'text', + label: '右边距', + name: 'right', + required: true, + value: `${rightMargin}`, + placeholder: '请输入右边距' + } + ], + onConfirm: payload => { const top = payload.find(p => p.name === 'top')?.value if (!top) return const bottom = payload.find(p => p.name === 'bottom')?.value @@ -1017,7 +1172,7 @@ window.onload = function () { // 全屏 const fullscreenDom = document.querySelector('.fullscreen')! fullscreenDom.onclick = toggleFullscreen - window.addEventListener('keydown', (evt) => { + window.addEventListener('keydown', evt => { if (evt.key === 'F11') { toggleFullscreen() evt.preventDefault() @@ -1037,20 +1192,24 @@ window.onload = function () { // 7. 编辑器使用模式 let modeIndex = 0 - const modeList = [{ - mode: EditorMode.EDIT, - name: '编辑模式' - }, { - mode: EditorMode.CLEAN, - name: '清洁模式' - }, { - mode: EditorMode.READONLY, - name: '只读模式' - }] + const modeList = [ + { + mode: EditorMode.EDIT, + name: '编辑模式' + }, + { + mode: EditorMode.CLEAN, + name: '清洁模式' + }, + { + mode: EditorMode.READONLY, + name: '只读模式' + } + ] const modeElement = document.querySelector('.editor-mode')! modeElement.onclick = function () { // 模式选择循环 - modeIndex === 2 ? modeIndex = 0 : modeIndex++ + modeIndex === 2 ? (modeIndex = 0) : modeIndex++ // 设置模式 const { name, mode } = modeList[modeIndex] modeElement.innerText = name @@ -1069,38 +1228,64 @@ window.onload = function () { // 8. 内部事件监听 instance.listener.rangeStyleChange = function (payload) { // 控件类型 - payload.type === ElementType.SUBSCRIPT ? subscriptDom.classList.add('active') : subscriptDom.classList.remove('active') - payload.type === ElementType.SUPERSCRIPT ? superscriptDom.classList.add('active') : superscriptDom.classList.remove('active') - payload.type === ElementType.SEPARATOR ? separatorDom.classList.add('active') : separatorDom.classList.remove('active') - separatorOptionDom.querySelectorAll('li').forEach(li => li.classList.remove('active')) + payload.type === ElementType.SUBSCRIPT + ? subscriptDom.classList.add('active') + : subscriptDom.classList.remove('active') + payload.type === ElementType.SUPERSCRIPT + ? superscriptDom.classList.add('active') + : superscriptDom.classList.remove('active') + payload.type === ElementType.SEPARATOR + ? separatorDom.classList.add('active') + : separatorDom.classList.remove('active') + separatorOptionDom + .querySelectorAll('li') + .forEach(li => li.classList.remove('active')) if (payload.type === ElementType.SEPARATOR) { const separator = payload.dashArray.join(',') || '0,0' - const curSeparatorDom = separatorOptionDom.querySelector(`[data-separator='${separator}']`)! + const curSeparatorDom = separatorOptionDom.querySelector( + `[data-separator='${separator}']` + )! if (curSeparatorDom) { curSeparatorDom.classList.add('active') } } // 富文本 - fontOptionDom.querySelectorAll('li').forEach(li => li.classList.remove('active')) - const curFontDom = fontOptionDom.querySelector(`[data-family='${payload.font}']`) + fontOptionDom + .querySelectorAll('li') + .forEach(li => li.classList.remove('active')) + const curFontDom = fontOptionDom.querySelector( + `[data-family='${payload.font}']` + ) if (curFontDom) { fontSelectDom.innerText = curFontDom.innerText fontSelectDom.style.fontFamily = payload.font curFontDom.classList.add('active') } - sizeOptionDom.querySelectorAll('li').forEach(li => li.classList.remove('active')) - const curSizeDom = sizeOptionDom.querySelector(`[data-size='${payload.size}']`) + sizeOptionDom + .querySelectorAll('li') + .forEach(li => li.classList.remove('active')) + const curSizeDom = sizeOptionDom.querySelector( + `[data-size='${payload.size}']` + ) if (curSizeDom) { sizeSelectDom.innerText = curSizeDom.innerText curSizeDom.classList.add('active') } else { sizeSelectDom.innerText = `${payload.size}` } - payload.bold ? boldDom.classList.add('active') : boldDom.classList.remove('active') - payload.italic ? italicDom.classList.add('active') : italicDom.classList.remove('active') - payload.underline ? underlineDom.classList.add('active') : underlineDom.classList.remove('active') - payload.strikeout ? strikeoutDom.classList.add('active') : strikeoutDom.classList.remove('active') + payload.bold + ? boldDom.classList.add('active') + : boldDom.classList.remove('active') + payload.italic + ? italicDom.classList.add('active') + : italicDom.classList.remove('active') + payload.underline + ? underlineDom.classList.add('active') + : underlineDom.classList.remove('active') + payload.strikeout + ? strikeoutDom.classList.add('active') + : strikeoutDom.classList.remove('active') if (payload.color) { colorDom.classList.add('active') colorControlDom.value = payload.color @@ -1136,19 +1321,33 @@ window.onload = function () { } // 行间距 - rowOptionDom.querySelectorAll('li').forEach(li => li.classList.remove('active')) - const curRowMarginDom = rowOptionDom.querySelector(`[data-rowmargin='${payload.rowMargin}']`)! + rowOptionDom + .querySelectorAll('li') + .forEach(li => li.classList.remove('active')) + const curRowMarginDom = rowOptionDom.querySelector( + `[data-rowmargin='${payload.rowMargin}']` + )! curRowMarginDom.classList.add('active') // 功能 - payload.undo ? undoDom.classList.remove('no-allow') : undoDom.classList.add('no-allow') - payload.redo ? redoDom.classList.remove('no-allow') : redoDom.classList.add('no-allow') - payload.painter ? painterDom.classList.add('active') : painterDom.classList.remove('active') + payload.undo + ? undoDom.classList.remove('no-allow') + : undoDom.classList.add('no-allow') + payload.redo + ? redoDom.classList.remove('no-allow') + : redoDom.classList.add('no-allow') + payload.painter + ? painterDom.classList.add('active') + : painterDom.classList.remove('active') // 标题 - titleOptionDom.querySelectorAll('li').forEach(li => li.classList.remove('active')) + titleOptionDom + .querySelectorAll('li') + .forEach(li => li.classList.remove('active')) if (payload.level) { - const curTitleDom = titleOptionDom.querySelector(`[data-level='${payload.level}']`)! + const curTitleDom = titleOptionDom.querySelector( + `[data-level='${payload.level}']` + )! titleSelectDom.innerText = curTitleDom.innerText curTitleDom.classList.add('active') } else { @@ -1157,13 +1356,17 @@ window.onload = function () { } // 列表 - listOptionDom.querySelectorAll('li').forEach(li => li.classList.remove('active')) + listOptionDom + .querySelectorAll('li') + .forEach(li => li.classList.remove('active')) if (payload.listType) { listDom.classList.add('active') const listType = payload.listType - const listStyle = payload.listType === ListType.OL ? ListStyle.DECIMAL : payload.listType - const curListDom = listOptionDom - .querySelector(`[data-list-type='${listType}'][data-list-style='${listStyle}']`) + const listStyle = + payload.listType === ListType.OL ? ListStyle.DECIMAL : payload.listType + const curListDom = listOptionDom.querySelector( + `[data-list-type='${listType}'][data-list-style='${listStyle}']` + ) if (curListDom) { curListDom.classList.add('active') } @@ -1178,15 +1381,21 @@ window.onload = function () { } instance.listener.pageSizeChange = function (payload) { - document.querySelector('.page-size')!.innerText = `${payload}` + document.querySelector( + '.page-size' + )!.innerText = `${payload}` } instance.listener.intersectionPageNoChange = function (payload) { - document.querySelector('.page-no')!.innerText = `${payload + 1}` + document.querySelector('.page-no')!.innerText = `${ + payload + 1 + }` } instance.listener.pageScaleChange = function (payload) { - document.querySelector('.page-scale-percentage')!.innerText = `${Math.floor(payload * 10 * 10)}%` + document.querySelector( + '.page-scale-percentage' + )!.innerText = `${Math.floor(payload * 10 * 10)}%` } instance.listener.controlChange = function (payload) { @@ -1204,21 +1413,31 @@ window.onload = function () { ] // 菜单操作权限 disableMenusInControlContext.forEach(menu => { - const menuDom = document.querySelector(`.menu-item__${menu}`)! - payload ? menuDom.classList.add('disable') : menuDom.classList.remove('disable') + const menuDom = document.querySelector( + `.menu-item__${menu}` + )! + payload + ? menuDom.classList.add('disable') + : menuDom.classList.remove('disable') }) } instance.listener.pageModeChange = function (payload) { - const activeMode = pageModeOptionsDom.querySelector(`[data-page-mode='${payload}']`)! - pageModeOptionsDom.querySelectorAll('li').forEach(li => li.classList.remove('active')) + const activeMode = pageModeOptionsDom.querySelector( + `[data-page-mode='${payload}']` + )! + pageModeOptionsDom + .querySelectorAll('li') + .forEach(li => li.classList.remove('active')) activeMode.classList.add('active') } instance.listener.contentChange = debounce(async function () { // 字数 const wordCount = await instance.command.getWordCount() - document.querySelector('.word-count')!.innerText = `${wordCount || 0}` + document.querySelector('.word-count')!.innerText = `${ + wordCount || 0 + }` // 目录 if (isCatalogShow) { updateCatalog() @@ -1234,7 +1453,7 @@ window.onload = function () { { name: '签名', icon: 'signature', - when: (payload) => { + when: payload => { return !payload.isReadonly && payload.editorTextFocus }, callback: (command: Command) => { @@ -1243,12 +1462,14 @@ window.onload = function () { if (!payload) return const { value, width, height } = payload if (!value || !width || !height) return - command.executeInsertElementList([{ - value, - width, - height, - type: ElementType.IMAGE - }]) + command.executeInsertElementList([ + { + value, + width, + height, + type: ElementType.IMAGE + } + ]) } }) } @@ -1256,7 +1477,7 @@ window.onload = function () { { name: '格式整理', icon: 'word-tool', - when: (payload) => { + when: payload => { return !payload.isReadonly }, callback: (command: Command) => { @@ -1314,5 +1535,4 @@ window.onload = function () { } } ]) - -} \ No newline at end of file +} diff --git a/src/mock.ts b/src/mock.ts index bff0365..3f36bba 100644 --- a/src/mock.ts +++ b/src/mock.ts @@ -1,9 +1,27 @@ -import { ControlType, ElementType, IEditorOption, IElement, ListType, TitleLevel } from './editor' +import { + ControlType, + ElementType, + IEditorOption, + IElement, + ListType, + TitleLevel +} from './editor' const text = `主诉:\n发热三天,咳嗽五天。\n现病史:\n患者于三天前无明显诱因,感冒后发现面部水肿,无皮疹,尿量减少,出现乏力,在外治疗无好转,现来我院就诊。\n既往史:\n有糖尿病10年,有高血压2年,有传染性疾病1年。报告其他既往疾病。\n流行病史:\n否认14天内接触过确诊患者、疑似患者、无症状感染者及其密切接触者;否认14天内去过以下场所:水产、肉类批发市场,农贸市场,集市,大型超市,夜市;否认14天内与以下场所工作人员密切接触:水产、肉类批发市场,农贸市场,集市,大型超市;否认14天内周围(如家庭、办公室)有2例以上聚集性发病;否认14天内接触过有发热或呼吸道症状的人员;否认14天内自身有发热或呼吸道症状;否认14天内接触过纳入隔离观察的人员及其他可能与新冠肺炎关联的情形;陪同家属无以上情况。\n体格检查:\nT:39.5℃,P:80bpm,R:20次/分,BP:120/80mmHg;\n辅助检查:\n2020年6月10日,普放:血细胞比容36.50%(偏低)40~50;单核细胞绝对值0.75*10/L(偏高)参考值:0.1~0.6;\n门诊诊断:处置治疗:电子签名:【】\n其他记录:` // 模拟标题 -const titleText = ['主诉:', '现病史:', '既往史:', '流行病史:', '体格检查:', '辅助检查:', '门诊诊断:', '处置治疗:', '电子签名:', '其他记录:'] +const titleText = [ + '主诉:', + '现病史:', + '既往史:', + '流行病史:', + '体格检查:', + '辅助检查:', + '门诊诊断:', + '处置治疗:', + '电子签名:', + '其他记录:' +] const titleMap: Map = new Map() for (let t = 0; t < titleText.length; t++) { const value = titleText[t] @@ -15,17 +33,29 @@ for (let t = 0; t < titleText.length; t++) { // 模拟颜色字 const colorText = ['传染性疾病'] -const colorIndex: number[] = colorText.map(b => { - const i = text.indexOf(b) - return ~i ? Array(b.length).fill(i).map((_, j) => i + j) : [] -}).flat() +const colorIndex: number[] = colorText + .map(b => { + const i = text.indexOf(b) + return ~i + ? Array(b.length) + .fill(i) + .map((_, j) => i + j) + : [] + }) + .flat() // 模拟高亮字 const highlightText = ['血细胞比容'] -const highlightIndex: number[] = highlightText.map(b => { - const i = text.indexOf(b) - return ~i ? Array(b.length).fill(i).map((_, j) => i + j) : [] -}).flat() +const highlightIndex: number[] = highlightText + .map(b => { + const i = text.indexOf(b) + return ~i + ? Array(b.length) + .fill(i) + .map((_, j) => i + j) + : [] + }) + .flat() const elementList: IElement[] = [] // 组合纯文本数据 @@ -39,10 +69,12 @@ while (index < textList.length) { value: '', type: ElementType.TITLE, level: TitleLevel.FIRST, - valueList: [{ - value: title, - size: 18 - }] + valueList: [ + { + value: title, + size: 18 + } + ] }) index += title.length - 1 } else if (colorIndex.includes(index)) { @@ -89,16 +121,20 @@ elementList.splice(94, 0, { placeholder: '有无', prefix: '{', postfix: '}', - valueSets: [{ - value: '有', - code: '98175' - }, { - value: '无', - code: '98176' - }, { - value: '不详', - code: '98177' - }] + valueSets: [ + { + value: '有', + code: '98175' + }, + { + value: '无', + code: '98176' + }, + { + value: '不详', + code: '98177' + } + ] } }) @@ -106,19 +142,24 @@ elementList.splice(94, 0, { elementList.splice(116, 0, { type: ElementType.HYPERLINK, value: '', - valueList: [{ - value: '新', - size: 16 - }, { - value: '冠', - size: 16 - }, { - value: '肺', - size: 16 - }, { - value: '炎', - size: 16 - }], + valueList: [ + { + value: '新', + size: 16 + }, + { + value: '冠', + size: 16 + }, + { + value: '肺', + size: 16 + }, + { + value: '炎', + size: 16 + } + ], url: 'https://hufe.club/canvas-editor' }) @@ -140,18 +181,23 @@ elementList.splice(450, 0, { value: '', type: ElementType.LIST, listType: ListType.OL, - valueList: [{ - value: '高血压\n糖尿病\n病毒性感冒\n过敏性鼻炎\n过敏性鼻息肉' - }] + valueList: [ + { + value: '高血压\n糖尿病\n病毒性感冒\n过敏性鼻炎\n过敏性鼻息肉' + } + ] }) elementList.splice(452, 0, { value: '', type: ElementType.LIST, listType: ListType.OL, - valueList: [{ - value: '超声引导下甲状腺细针穿刺术;\n乙型肝炎表面抗体测定;\n膜式病变细胞采集术、后颈皮下肤层;' - }] + valueList: [ + { + value: + '超声引导下甲状腺细针穿刺术;\n乙型肝炎表面抗体测定;\n膜式病变细胞采集术、后颈皮下肤层;' + } + ] }) // 模拟图片 @@ -167,159 +213,209 @@ elementList.splice(455, 0, { elementList.push({ type: ElementType.TABLE, value: '', - colgroup: [{ - width: 180 - }, { - width: 80 - }, { - width: 130 - }, { - width: 130 - }], - trList: [{ - height: 40, - tdList: [{ - colspan: 1, - rowspan: 2, - value: [ - { value: `1`, size: 16 }, - { value: '.', size: 16 } - ] - }, { - colspan: 1, - rowspan: 1, - value: [ - { value: `2`, size: 16 }, - { value: '.', size: 16 } - ] - }, { - colspan: 2, - rowspan: 1, - value: [ - { value: `3`, size: 16 }, - { value: '.', size: 16 } - ] - }] - }, { - height: 40, - tdList: [{ - colspan: 1, - rowspan: 1, - value: [ - { value: `4`, size: 16 }, - { value: '.', size: 16 } - ] - }, { - colspan: 1, - rowspan: 1, - value: [ - { value: `5`, size: 16 }, - { value: '.', size: 16 } - ] - }, { - colspan: 1, - rowspan: 1, - value: [ - { value: `6`, size: 16 }, - { value: '.', size: 16 } - ] - }] - }, { - height: 40, - tdList: [{ - colspan: 1, - rowspan: 1, - value: [ - { value: `7`, size: 16 }, - { value: '.', size: 16 } - ] - }, { - colspan: 1, - rowspan: 1, - value: [ - { value: `8`, size: 16 }, - { value: '.', size: 16 } + colgroup: [ + { + width: 180 + }, + { + width: 80 + }, + { + width: 130 + }, + { + width: 130 + } + ], + trList: [ + { + height: 40, + tdList: [ + { + colspan: 1, + rowspan: 2, + value: [ + { value: `1`, size: 16 }, + { value: '.', size: 16 } + ] + }, + { + colspan: 1, + rowspan: 1, + value: [ + { value: `2`, size: 16 }, + { value: '.', size: 16 } + ] + }, + { + colspan: 2, + rowspan: 1, + value: [ + { value: `3`, size: 16 }, + { value: '.', size: 16 } + ] + } ] - }, { - colspan: 1, - rowspan: 1, - value: [ - { value: `9`, size: 16 }, - { value: '.', size: 16 } + }, + { + height: 40, + tdList: [ + { + colspan: 1, + rowspan: 1, + value: [ + { value: `4`, size: 16 }, + { value: '.', size: 16 } + ] + }, + { + colspan: 1, + rowspan: 1, + value: [ + { value: `5`, size: 16 }, + { value: '.', size: 16 } + ] + }, + { + colspan: 1, + rowspan: 1, + value: [ + { value: `6`, size: 16 }, + { value: '.', size: 16 } + ] + } ] - }, { - colspan: 1, - rowspan: 1, - value: [ - { value: `1`, size: 16 }, - { value: `0`, size: 16 }, - { value: '.', size: 16 } + }, + { + height: 40, + tdList: [ + { + colspan: 1, + rowspan: 1, + value: [ + { value: `7`, size: 16 }, + { value: '.', size: 16 } + ] + }, + { + colspan: 1, + rowspan: 1, + value: [ + { value: `8`, size: 16 }, + { value: '.', size: 16 } + ] + }, + { + colspan: 1, + rowspan: 1, + value: [ + { value: `9`, size: 16 }, + { value: '.', size: 16 } + ] + }, + { + colspan: 1, + rowspan: 1, + value: [ + { value: `1`, size: 16 }, + { value: `0`, size: 16 }, + { value: '.', size: 16 } + ] + } ] - }] - }] + } + ] }) // 模拟checkbox -elementList.push(...[{ - value: '是否同意以上内容:' -}, { - type: ElementType.CONTROL, - control: { - type: ControlType.CHECKBOX, - code: '98175', - value: '', - valueSets: [{ - value: '同意', - code: '98175' - }, { - value: '否定', - code: '98176' - }] - }, - value: '' -}, { - value: '\n' -}]) +elementList.push( + ...([ + { + value: '是否同意以上内容:' + }, + { + type: ElementType.CONTROL, + control: { + type: ControlType.CHECKBOX, + code: '98175', + value: '', + valueSets: [ + { + value: '同意', + code: '98175' + }, + { + value: '否定', + code: '98176' + } + ] + }, + value: '' + }, + { + value: '\n' + } + ]) +) // LaTex公式 -elementList.push(...[{ - value: '医学公式:' -}, -{ - value: `{E_k} = hv - {W_0}`, - type: ElementType.LATEX -}, { - value: '\n' -}]) +elementList.push( + ...([ + { + value: '医学公式:' + }, + { + value: `{E_k} = hv - {W_0}`, + type: ElementType.LATEX + }, + { + value: '\n' + } + ]) +) // 日期选择 -elementList.push(...[{ - value: '签署日期:' -}, -{ - value: '', - valueList: [{ - value: `2022-08-10 17:30:01` - }], - type: ElementType.DATE -}, { - value: '\n' -}]) +elementList.push( + ...([ + { + value: '签署日期:' + }, + { + value: '', + valueList: [ + { + value: `2022-08-10 17:30:01` + } + ], + type: ElementType.DATE + }, + { + value: '\n' + } + ]) +) // 模拟结尾文本 -elementList.push(...[{ - value: '', - type: ElementType.TAB -}, { - value: 'E', - size: 16 -}, { - value: 'O', - size: 16 -}, { - value: 'F', - size: 16 -}]) +elementList.push( + ...[ + { + value: '', + type: ElementType.TAB + }, + { + value: 'E', + size: 16 + }, + { + value: 'O', + size: 16 + }, + { + value: 'F', + size: 16 + } + ] +) export const data: IElement[] = elementList @@ -335,4 +431,4 @@ export const options: IEditorOption = { placeholder: { data: '请输入正文' } -} \ No newline at end of file +} diff --git a/src/plugins/copy/index.ts b/src/plugins/copy/index.ts index b3c9a6b..fee3fe4 100644 --- a/src/plugins/copy/index.ts +++ b/src/plugins/copy/index.ts @@ -2,10 +2,13 @@ import Editor from '../../editor' export interface ICopyWithCopyrightOption { - copyrightText: string; + copyrightText: string } -export function copyWithCopyrightPlugin(editor: Editor, options?: ICopyWithCopyrightOption) { +export function copyWithCopyrightPlugin( + editor: Editor, + options?: ICopyWithCopyrightOption +) { const copy = editor.command.executeCopy editor.command.executeCopy = () => { @@ -24,4 +27,4 @@ export function copyWithCopyrightPlugin(editor: Editor, options?: ICopyWithCopyr copy() } } -} \ No newline at end of file +} diff --git a/src/plugins/markdown/index.ts b/src/plugins/markdown/index.ts index fa2d627..7c293cf 100644 --- a/src/plugins/markdown/index.ts +++ b/src/plugins/markdown/index.ts @@ -1,8 +1,14 @@ // 简化版markdown转IElement插件示例,代码仅为参考 -import Editor, { Command, ElementType, IElement, ListType, TitleLevel } from '../../editor' +import Editor, { + Command, + ElementType, + IElement, + ListType, + TitleLevel +} from '../../editor' export type CommandWithMarkdown = Command & { - executeInsertMarkdown(markdown: string): void; + executeInsertMarkdown(markdown: string): void } export const titleNodeNameMapping: Record = { @@ -25,36 +31,44 @@ function convertMarkdownToElement(markdown: string): IElement[] { type: ElementType.TITLE, level: titleNodeNameMapping[level], value: '', - valueList: [{ - value: line.slice(level + 1) - }] + valueList: [ + { + value: line.slice(level + 1) + } + ] }) } else if (line.startsWith('- ')) { elementList.push({ type: ElementType.LIST, listType: ListType.UL, value: '', - valueList: [{ - value: line.slice(2) - }] + valueList: [ + { + value: line.slice(2) + } + ] }) } else if (/^\d+\.\s/.test(line)) { elementList.push({ type: ElementType.LIST, listType: ListType.OL, value: '', - valueList: [{ - value: line.replace(/^\d+\.\s/, '') - }] + valueList: [ + { + value: line.replace(/^\d+\.\s/, '') + } + ] }) } else if (/^\[.*?\]\(.*?\)$/.test(line)) { const match = line.match(/^\[(.*?)\]\((.*?)\)$/) elementList.push({ type: ElementType.HYPERLINK, value: '', - valueList: [{ - value: match![1] - }], + valueList: [ + { + value: match![1] + } + ], url: match![2] }) } else if (/^\*\*(.*?)\*\*$/.test(line)) { @@ -101,4 +115,4 @@ export function markdownPlugin(editor: Editor) { const elementList = convertMarkdownToElement(markdown) command.executeInsertElementList(elementList) } -} \ No newline at end of file +} diff --git a/src/utils/index.ts b/src/utils/index.ts index acce137..95cb2e5 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -8,4 +8,4 @@ export function debounce(func: Function, delay: number) { func.apply(this, args) }, delay) } -} \ No newline at end of file +} diff --git a/src/utils/prism.ts b/src/utils/prism.ts index e3cc87b..993f32d 100644 --- a/src/utils/prism.ts +++ b/src/utils/prism.ts @@ -1,8 +1,8 @@ interface IPrismKindStyle { - color?: string; - italic?: boolean; - opacity?: number; - bold?: boolean; + color?: string + italic?: boolean + opacity?: number + bold?: boolean } export function getPrismKindStyle(payload: string): IPrismKindStyle | null { @@ -55,11 +55,13 @@ export function getPrismKindStyle(payload: string): IPrismKindStyle | null { } type IFormatPrismToken = { - type?: string; - content: string; + type?: string + content: string } & IPrismKindStyle -export function formatPrismToken(payload: (Prism.Token | string)[]): IFormatPrismToken[] { +export function formatPrismToken( + payload: (Prism.Token | string)[] +): IFormatPrismToken[] { const formatTokenList: IFormatPrismToken[] = [] function format(tokenList: (Prism.Token | string)[]) { for (let i = 0; i < tokenList.length; i++) { @@ -84,4 +86,4 @@ export function formatPrismToken(payload: (Prism.Token | string)[]): IFormatPris } format(payload) return formatTokenList -} \ No newline at end of file +}