From 406fca359034991fbde568ee3a6f981dac3f73d1 Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Thu, 20 Apr 2023 20:13:33 +0800 Subject: [PATCH] feat: handle list boundary --- src/editor/core/command/CommandAdapt.ts | 43 ++++++++----- src/editor/core/cursor/CursorAgent.ts | 43 +++++++++++-- src/editor/core/draw/Draw.ts | 28 +-------- src/editor/core/draw/control/Control.ts | 8 ++- .../core/draw/control/select/SelectControl.ts | 7 ++- .../core/draw/control/text/TextControl.ts | 7 ++- src/editor/core/draw/particle/ListParticle.ts | 2 +- src/editor/core/event/handlers/input.ts | 2 + src/editor/core/event/handlers/keydown.ts | 2 + src/editor/core/event/handlers/mouseup.ts | 3 +- src/editor/core/range/RangeManager.ts | 24 +++++++- src/editor/dataset/constant/Element.ts | 15 +++-- src/editor/dataset/constant/List.ts | 14 ++++- src/editor/utils/clipboard.ts | 60 +++++++++++++++++-- src/editor/utils/element.ts | 26 +++++++- 15 files changed, 214 insertions(+), 70 deletions(-) diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts index 990431c..58d88dc 100644 --- a/src/editor/core/command/CommandAdapt.ts +++ b/src/editor/core/command/CommandAdapt.ts @@ -20,7 +20,7 @@ import { ITd } from '../../interface/table/Td' import { ITr } from '../../interface/table/Tr' import { IWatermark } from '../../interface/Watermark' import { downloadFile, getUUID } from '../../utils' -import { formatElementList, isTextLikeElement } from '../../utils/element' +import { formatElementContext, formatElementList, isTextLikeElement } from '../../utils/element' import { printImageBase64 } from '../../utils/print' import { Control } from '../draw/control/Control' import { Draw } from '../draw/Draw' @@ -543,12 +543,14 @@ export class CommandAdapt { formatElementList([element], { editorOptions: this.options }) + formatElementContext(elementList, [element], startIndex) const curIndex = startIndex + 1 - if (startIndex === endIndex) { - this.draw.spliceElementList(elementList, curIndex, 0, element) - } else { - this.draw.spliceElementList(elementList, curIndex, endIndex - startIndex, element) - } + this.draw.spliceElementList( + elementList, + curIndex, + startIndex === endIndex ? 0 : endIndex - startIndex, + element + ) this.range.setRange(curIndex, curIndex) this.draw.render({ curIndex, isSetCursor: false }) } @@ -1156,11 +1158,13 @@ export class CommandAdapt { })) if (!newElementList) return const start = startIndex + 1 - if (startIndex === endIndex) { - this.draw.spliceElementList(elementList, start, 0, ...newElementList) - } else { - this.draw.spliceElementList(elementList, start, endIndex - startIndex, ...newElementList) - } + formatElementContext(elementList, newElementList, startIndex) + this.draw.spliceElementList( + elementList, + start, + startIndex === endIndex ? 0 : endIndex - startIndex, + ...newElementList + ) const curIndex = start + newElementList.length - 1 this.range.setRange(curIndex, curIndex) this.draw.render({ curIndex }) @@ -1284,6 +1288,7 @@ export class CommandAdapt { dashArray: payload } // 从行头增加分割线 + formatElementContext(elementList, [newElement], startIndex) if (startIndex !== 0 && elementList[startIndex].value === ZERO) { this.draw.spliceElementList(elementList, startIndex, 1, newElement) curIndex = startIndex - 1 @@ -1355,11 +1360,13 @@ export class CommandAdapt { type: ElementType.IMAGE } const curIndex = startIndex + 1 - if (startIndex === endIndex) { - this.draw.spliceElementList(elementList, curIndex, 0, element) - } else { - this.draw.spliceElementList(elementList, curIndex, endIndex - startIndex, element) - } + formatElementContext(elementList, [element], startIndex) + this.draw.spliceElementList( + elementList, + curIndex, + startIndex === endIndex ? 0 : endIndex - startIndex, + element + ) this.range.setRange(curIndex, curIndex) this.draw.render({ curIndex }) } @@ -1611,6 +1618,10 @@ export class CommandAdapt { if (!payload.length) return const isReadonly = this.draw.isReadonly() if (isReadonly) return + // 格式化上下文信息 + const { startIndex } = this.range.getRange() + const elementList = this.draw.getElementList() + formatElementContext(elementList, payload, startIndex) this.draw.insertElementList(payload) } diff --git a/src/editor/core/cursor/CursorAgent.ts b/src/editor/core/cursor/CursorAgent.ts index c757f39..d55cee9 100644 --- a/src/editor/core/cursor/CursorAgent.ts +++ b/src/editor/core/cursor/CursorAgent.ts @@ -1,7 +1,11 @@ +import { ZERO } from '../../dataset/constant/Common' import { EDITOR_PREFIX } from '../../dataset/constant/Editor' +import { VIRTUAL_ELEMENT_TYPE } from '../../dataset/constant/Element' import { ElementType } from '../../dataset/enum/Element' +import { IElement } from '../../interface/Element' import { debounce } from '../../utils' import { getElementListByHTML } from '../../utils/clipboard' +import { formatElementContext } from '../../utils/element' import { Draw } from '../draw/Draw' import { CanvasEvent } from '../event/CanvasEvent' @@ -47,6 +51,9 @@ export class CursorAgent { private _paste(evt: ClipboardEvent) { const clipboardData = evt.clipboardData if (!clipboardData) return + const rangeManager = this.draw.getRange() + const { startIndex } = rangeManager.getRange() + const elementList = this.draw.getElementList() // 从粘贴板提取数据 let isHTML = false for (let i = 0; i < clipboardData.items.length; i++) { @@ -66,10 +73,34 @@ export class CursorAgent { } if (item.type === 'text/html' && isHTML) { item.getAsString(htmlText => { - const elementList = getElementListByHTML(htmlText, { + const pasteElementList = getElementListByHTML(htmlText, { innerWidth: this.draw.getOriginalInnerWidth() }) - this.draw.insertElementList(elementList) + if (~startIndex) { + // 如果是复制到虚拟元素里,则粘贴列表的虚拟元素需扁平化处理 + const anchorElement = elementList[startIndex] + if (anchorElement?.titleId || anchorElement?.listId) { + let start = 0 + while (start < pasteElementList.length) { + const pasteElement = pasteElementList[start] + 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 + pasteElementList.splice(start, 0, element) + start++ + } + } + start-- + } + start++ + } + } + formatElementContext(elementList, pasteElementList, startIndex) + } + this.draw.insertElementList(pasteElementList) }) } } else if (item.kind === 'file') { @@ -84,12 +115,16 @@ export class CursorAgent { const value = fileReader.result as string image.src = value image.onload = () => { - this.draw.insertElementList([{ + const imageElement: IElement = { value, type: ElementType.IMAGE, width: image.width, height: image.height - }]) + } + if (~startIndex) { + formatElementContext(elementList, [imageElement], startIndex) + } + this.draw.insertElementList([imageElement]) } } } diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 451b01f..322463b 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -52,7 +52,7 @@ import { I18n } from '../i18n/I18n' import { ImageObserver } from '../observer/ImageObserver' import { Zone } from '../zone/Zone' import { Footer } from './frame/Footer' -import { EDITOR_ELEMENT_CONTEXT_ATTR, INLINE_ELEMENT_TYPE } from '../../dataset/constant/Element' +import { INLINE_ELEMENT_TYPE } from '../../dataset/constant/Element' import { ListParticle } from './particle/ListParticle' export class Draw { @@ -438,18 +438,6 @@ export class Draw { return this.footerElementList } - public formatElementContext(anchorElement: IElement, targetElement: IElement) { - for (let i = 0; i < EDITOR_ELEMENT_CONTEXT_ATTR.length; i++) { - const attr = EDITOR_ELEMENT_CONTEXT_ATTR[i] - const value = anchorElement[attr] as never - if (value !== undefined) { - targetElement[attr] = value - } else { - delete targetElement[attr] - } - } - } - public insertElementList(payload: IElement[]) { if (!payload.length) return const isPartRangeInControlOutside = this.control.isPartRangeInControlOutside() @@ -501,20 +489,6 @@ export class Draw { } } } - if (items.length) { - // 格式化新增数据 - const endIndex = start + deleteCount - 1 - const endElement = elementList[endIndex] - const endNextElement = elementList[endIndex + 1] - const anchorElement = endElement?.value === ZERO && endNextElement && endNextElement.value !== ZERO - ? endNextElement - : endElement - if (anchorElement) { - for (let i = 0; i < items.length; i++) { - this.formatElementContext(anchorElement, items[i]) - } - } - } elementList.splice(start, deleteCount, ...items) } diff --git a/src/editor/core/draw/control/Control.ts b/src/editor/core/draw/control/Control.ts index 9ec7151..f5ab642 100644 --- a/src/editor/core/draw/control/Control.ts +++ b/src/editor/core/draw/control/Control.ts @@ -4,7 +4,7 @@ import { IControl, IControlInitOption, IControlInstance, IControlOption } from ' import { IElement, IElementPosition } from '../../../interface/Element' import { IRange } from '../../../interface/Range' import { deepClone, splitText } from '../../../utils' -import { 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' @@ -293,14 +293,16 @@ export class Control { const placeholderStrList = splitText(control.placeholder) for (let p = 0; p < placeholderStrList.length; p++) { const value = placeholderStrList[p] - this.draw.spliceElementList(elementList, startIndex + p + 1, 0, { + const newElement: IElement = { value, controlId: startElement.controlId, type: ElementType.CONTROL, control: startElement.control, controlComponent: ControlComponent.PLACEHOLDER, color: this.options.placeholderColor - }) + } + formatElementContext(elementList, [newElement], startIndex) + this.draw.spliceElementList(elementList, startIndex + p + 1, 0, newElement) } } diff --git a/src/editor/core/draw/control/select/SelectControl.ts b/src/editor/core/draw/control/select/SelectControl.ts index 589b27e..a5e134b 100644 --- a/src/editor/core/draw/control/select/SelectControl.ts +++ b/src/editor/core/draw/control/select/SelectControl.ts @@ -5,6 +5,7 @@ import { KeyMap } from '../../../../dataset/enum/KeyMap' import { IControlInstance } from '../../../../interface/Control' import { IElement } from '../../../../interface/Element' import { splitText } from '../../../../utils' +import { formatElementContext } from '../../../../utils/element' import { Control } from '../Control' export class SelectControl implements IControlInstance { @@ -189,11 +190,13 @@ export class SelectControl implements IControlInstance { const data = splitText(valueSet.value) const draw = this.control.getDraw() for (let i = 0; i < data.length; i++) { - draw.spliceElementList(elementList, start + i, 0, { + const newElement: IElement = { ...startElement, value: data[i], controlComponent: ControlComponent.VALUE - }) + } + formatElementContext(elementList, [newElement], startIndex) + draw.spliceElementList(elementList, start + i, 0, newElement) } // render const newIndex = start + data.length - 1 diff --git a/src/editor/core/draw/control/text/TextControl.ts b/src/editor/core/draw/control/text/TextControl.ts index 2fc8329..649536b 100644 --- a/src/editor/core/draw/control/text/TextControl.ts +++ b/src/editor/core/draw/control/text/TextControl.ts @@ -2,6 +2,7 @@ import { ControlComponent } from '../../../../dataset/enum/Control' import { KeyMap } from '../../../../dataset/enum/KeyMap' import { IControlInstance } from '../../../../interface/Control' import { IElement } from '../../../../interface/Element' +import { formatElementContext } from '../../../../utils/element' import { Control } from '../Control' export class TextControl implements IControlInstance { @@ -74,11 +75,13 @@ export class TextControl implements IControlInstance { const startElement = elementList[startIndex] const start = range.startIndex + 1 for (let i = 0; i < data.length; i++) { - draw.spliceElementList(elementList, start + i, 0, { + const newElement: IElement = { ...startElement, ...data[i], controlComponent: ControlComponent.VALUE - }) + } + formatElementContext(elementList, [newElement], startIndex) + draw.spliceElementList(elementList, start + i, 0, newElement) } return start + data.length - 1 } diff --git a/src/editor/core/draw/particle/ListParticle.ts b/src/editor/core/draw/particle/ListParticle.ts index 4312924..ebf53e7 100644 --- a/src/editor/core/draw/particle/ListParticle.ts +++ b/src/editor/core/draw/particle/ListParticle.ts @@ -78,7 +78,7 @@ export class ListParticle { let text = '' if (startElement.listType === ListType.UL) { if (startElement.listStyle) { - text = ulStyleMapping[startElement.listStyle] + text = ulStyleMapping[startElement.listStyle] || ulStyleMapping[UlStyle.DISC] } } else { text = `${listIndex! + 1}${KeyMap.PERIOD}` diff --git a/src/editor/core/event/handlers/input.ts b/src/editor/core/event/handlers/input.ts index 100ba4e..13306d5 100644 --- a/src/editor/core/event/handlers/input.ts +++ b/src/editor/core/event/handlers/input.ts @@ -3,6 +3,7 @@ import { EDITOR_ELEMENT_COPY_ATTR } from '../../../dataset/constant/Element' import { ElementType } from '../../../dataset/enum/Element' import { IElement } from '../../../interface/Element' import { splitText } from '../../../utils' +import { formatElementContext } from '../../../utils/element' import { CanvasEvent } from '../CanvasEvent' export function input(data: string, host: CanvasEvent) { @@ -72,6 +73,7 @@ export function input(data: string, host: CanvasEvent) { if (startIndex !== endIndex) { draw.spliceElementList(elementList, start, endIndex - startIndex) } + formatElementContext(elementList, inputData, startIndex) draw.spliceElementList(elementList, start, 0, ...inputData) curIndex = startIndex + inputData.length } diff --git a/src/editor/core/event/handlers/keydown.ts b/src/editor/core/event/handlers/keydown.ts index 1379693..10ccdf4 100644 --- a/src/editor/core/event/handlers/keydown.ts +++ b/src/editor/core/event/handlers/keydown.ts @@ -3,6 +3,7 @@ import { ZERO } from '../../../dataset/constant/Common' import { ElementType } from '../../../dataset/enum/Element' import { KeyMap } from '../../../dataset/enum/KeyMap' import { IElement, IElementPosition } from '../../../interface/Element' +import { formatElementContext } from '../../../utils/element' import { isMod } from '../../../utils/hotkey' import { CanvasEvent } from '../CanvasEvent' @@ -76,6 +77,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) { const enterText: IElement = { value: ZERO } + formatElementContext(elementList, [enterText], startIndex) let curIndex: number if (activeControl && !control.isRangInPostfix()) { curIndex = control.setValue([enterText]) diff --git a/src/editor/core/event/handlers/mouseup.ts b/src/editor/core/event/handlers/mouseup.ts index f664a2c..af5dda8 100644 --- a/src/editor/core/event/handlers/mouseup.ts +++ b/src/editor/core/event/handlers/mouseup.ts @@ -3,7 +3,7 @@ import { ControlComponent, ControlType } from '../../../dataset/enum/Control' import { ElementType } from '../../../dataset/enum/Element' import { IElement } from '../../../interface/Element' import { deepClone, getUUID } from '../../../utils' -import { formatElementList } from '../../../utils/element' +import { formatElementContext, formatElementList } from '../../../utils/element' import { CanvasEvent } from '../CanvasEvent' type IDragElement = IElement & { dragId: string } @@ -103,6 +103,7 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { return newElement } }) + formatElementContext(elementList, replaceElementList, range.startIndex) // 缓存拖拽选区开始结束id const cacheRangeStartId = createDragId(cacheElementList[cacheRange.startIndex]) const cacheRangeEndId = createDragId(cacheElementList[cacheRange.endIndex]) diff --git a/src/editor/core/range/RangeManager.ts b/src/editor/core/range/RangeManager.ts index 4af5e4c..b857333 100644 --- a/src/editor/core/range/RangeManager.ts +++ b/src/editor/core/range/RangeManager.ts @@ -95,10 +95,29 @@ export class RangeManager { if (positionList[start]?.value === ZERO) break start-- } + // 中间选择 + if (startIndex !== endIndex) { + let middle = startIndex + 1 + while (middle < endIndex) { + const { pageNo, rowNo } = positionList[middle] + let rowArray = rangeRow.get(pageNo) + if (!rowArray) { + rowArray = [] + rangeRow.set(pageNo, rowArray) + } + if (!rowArray.includes(rowNo)) { + rowArray.push(rowNo) + } + middle++ + } + } // 向下查找 - let end = startIndex + 1 + let end = endIndex while (end < positionList.length) { - if (elementList[end].titleId !== elementList[end + 1]?.titleId) break + if ( + positionList[end].value === ZERO || + elementList[end].titleId !== elementList[end + 1]?.titleId + ) break const { pageNo, rowNo } = positionList[end] let rowArray = rangeRow.get(pageNo) if (!rowArray) { @@ -108,7 +127,6 @@ export class RangeManager { if (!rowArray.includes(rowNo)) { rowArray.push(rowNo) } - if (positionList[end].value === ZERO) break end++ } return rangeRow diff --git a/src/editor/dataset/constant/Element.ts b/src/editor/dataset/constant/Element.ts index 265090a..95ea996 100644 --- a/src/editor/dataset/constant/Element.ts +++ b/src/editor/dataset/constant/Element.ts @@ -26,9 +26,7 @@ export const EDITOR_ELEMENT_COPY_ATTR: Array = [ 'url', 'hyperlinkId', 'dateId', - 'dateFormat', - 'level', - 'titleId' + 'dateFormat' ] export const EDITOR_ELEMENT_ZIP_ATTR: Array = [ @@ -64,6 +62,8 @@ export const EDITOR_ELEMENT_CONTEXT_ATTR: Array = [ 'tdId', 'trId', 'tableId', + 'level', + 'titleId', 'listId', 'listType', 'listStyle' @@ -87,5 +87,12 @@ export const INLINE_ELEMENT_TYPE: ElementType[] = [ export const INLINE_NODE_NAME: string[] = [ 'HR', - 'TABLE' + '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/List.ts b/src/editor/dataset/constant/List.ts index f154fe1..562ad45 100644 --- a/src/editor/dataset/constant/List.ts +++ b/src/editor/dataset/constant/List.ts @@ -1,7 +1,19 @@ -import { UlStyle } from '../enum/List' +import { ListStyle, ListType, UlStyle } from '../enum/List' export const ulStyleMapping: Record = { [UlStyle.DISC]: '•', [UlStyle.CIRCLE]: '◦', [UlStyle.SQUARE]: '▫︎' +} + +export const listTypeElementMapping: Record = { + [ListType.OL]: 'ol', + [ListType.UL]: 'ul' +} + +export const listStyleCSSMapping: Record = { + [ListStyle.DISC]: 'disc', + [ListStyle.CIRCLE]: 'circle', + [ListStyle.SQUARE]: 'square', + [ListStyle.DECIMAL]: 'decimal' } \ No newline at end of file diff --git a/src/editor/utils/clipboard.ts b/src/editor/utils/clipboard.ts index f51c8f6..f999667 100644 --- a/src/editor/utils/clipboard.ts +++ b/src/editor/utils/clipboard.ts @@ -1,6 +1,7 @@ -import { IEditorOption, IElement, RowFlex } from '..' +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 { ControlComponent } from '../dataset/enum/Control' import { ElementType } from '../dataset/enum/Element' @@ -53,9 +54,7 @@ export function convertElementToDom(element: IElement, options: DeepRequired = new Map() + const zipList = zipElementList(element.valueList!) + for (let z = 0; z < zipList.length; z++) { + const zipElement = zipList[z] + const zipValueList = zipElement.value.split('\n') + for (let c = 0; c < zipValueList.length; c++) { + if (c > 0) { + curListIndex += 1 + } + const value = zipValueList[c] + const listElementList = listElementListMap.get(curListIndex) || [] + listElementList.push({ + ...zipElement, + value, + }) + listElementListMap.set(curListIndex, listElementList) + } + } + listElementListMap.forEach(listElementList => { + const li = document.createElement('li') + const childDom = buildDomFromElementList(listElementList) + li.innerHTML = childDom.innerHTML + list.append(li) + }) + clipboardDom.append(list) } else if (element.type === ElementType.IMAGE) { const img = document.createElement('img') if (element.value) { @@ -218,6 +249,27 @@ export function getElementListByHTML(htmlText: string, options: IGetElementListB value: '\n' }) } + } else if (node.nodeName === 'UL' || node.nodeName === 'OL') { + const listNode = node as HTMLOListElement | HTMLUListElement + const listElement: IElement = { + value: '', + type: ElementType.LIST, + valueList: [] + } + if (node.nodeName === 'OL') { + listElement.listType = ListType.OL + } else { + listElement.listType = ListType.UL + listElement.listStyle = listNode.style.listStyleType + } + listNode.querySelectorAll('li').forEach(li => { + const liValueList = getElementListByHTML(li.innerHTML, options) + liValueList.unshift({ + value: '\n' + }) + listElement.valueList!.push(...liValueList) + }) + elementList.push(listElement) } else if (node.nodeName === 'HR') { elementList.push({ value: '\n', diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts index d568dab..8b60e8a 100644 --- a/src/editor/utils/element.ts +++ b/src/editor/utils/element.ts @@ -4,7 +4,7 @@ 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_ZIP_ATTR, TEXTLIKE_ELEMENT_TYPE } from '../dataset/constant/Element' +import { EDITOR_ELEMENT_CONTEXT_ATTR, EDITOR_ELEMENT_ZIP_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' @@ -31,7 +31,8 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme isHandleFirstElement: true, ...options } - if (isHandleFirstElement && elementList[0]?.value !== ZERO) { + const startElement = elementList[0] + if (isHandleFirstElement && startElement?.value !== ZERO && startElement?.value !== '\n') { elementList.unshift({ value: ZERO }) @@ -539,4 +540,25 @@ export function getElementRowFlex(node: HTMLElement) { export function isTextLikeElement(element: IElement): boolean { return !element.type || TEXTLIKE_ELEMENT_TYPE.includes(element.type) +} + +export function formatElementContext(sourceElementList: IElement[], formatElementList: IElement[], anchorIndex: number) { + const anchorElement = sourceElementList[anchorIndex] + const anchorNextElement = sourceElementList[anchorIndex + 1] + const copyElement = anchorElement?.value === ZERO && anchorNextElement && anchorNextElement.value !== ZERO + ? anchorNextElement + : anchorElement + if (!copyElement) return + for (let e = 0; e < formatElementList.length; e++) { + const targetElement = formatElementList[e] + for (let i = 0; i < EDITOR_ELEMENT_CONTEXT_ATTR.length; i++) { + const attr = EDITOR_ELEMENT_CONTEXT_ATTR[i] + const value = copyElement[attr] as never + if (value !== undefined) { + targetElement[attr] = value + } else { + delete targetElement[attr] + } + } + } } \ No newline at end of file