feat: handle list boundary
This commit is contained in:
@@ -20,7 +20,7 @@ import { ITd } from '../../interface/table/Td'
|
|||||||
import { ITr } from '../../interface/table/Tr'
|
import { ITr } from '../../interface/table/Tr'
|
||||||
import { IWatermark } from '../../interface/Watermark'
|
import { IWatermark } from '../../interface/Watermark'
|
||||||
import { downloadFile, getUUID } from '../../utils'
|
import { downloadFile, getUUID } from '../../utils'
|
||||||
import { formatElementList, isTextLikeElement } from '../../utils/element'
|
import { formatElementContext, formatElementList, isTextLikeElement } from '../../utils/element'
|
||||||
import { printImageBase64 } from '../../utils/print'
|
import { printImageBase64 } from '../../utils/print'
|
||||||
import { Control } from '../draw/control/Control'
|
import { Control } from '../draw/control/Control'
|
||||||
import { Draw } from '../draw/Draw'
|
import { Draw } from '../draw/Draw'
|
||||||
@@ -543,12 +543,14 @@ export class CommandAdapt {
|
|||||||
formatElementList([element], {
|
formatElementList([element], {
|
||||||
editorOptions: this.options
|
editorOptions: this.options
|
||||||
})
|
})
|
||||||
|
formatElementContext(elementList, [element], startIndex)
|
||||||
const curIndex = startIndex + 1
|
const curIndex = startIndex + 1
|
||||||
if (startIndex === endIndex) {
|
this.draw.spliceElementList(
|
||||||
this.draw.spliceElementList(elementList, curIndex, 0, element)
|
elementList,
|
||||||
} else {
|
curIndex,
|
||||||
this.draw.spliceElementList(elementList, curIndex, endIndex - startIndex, element)
|
startIndex === endIndex ? 0 : endIndex - startIndex,
|
||||||
}
|
element
|
||||||
|
)
|
||||||
this.range.setRange(curIndex, curIndex)
|
this.range.setRange(curIndex, curIndex)
|
||||||
this.draw.render({ curIndex, isSetCursor: false })
|
this.draw.render({ curIndex, isSetCursor: false })
|
||||||
}
|
}
|
||||||
@@ -1156,11 +1158,13 @@ export class CommandAdapt {
|
|||||||
}))
|
}))
|
||||||
if (!newElementList) return
|
if (!newElementList) return
|
||||||
const start = startIndex + 1
|
const start = startIndex + 1
|
||||||
if (startIndex === endIndex) {
|
formatElementContext(elementList, newElementList, startIndex)
|
||||||
this.draw.spliceElementList(elementList, start, 0, ...newElementList)
|
this.draw.spliceElementList(
|
||||||
} else {
|
elementList,
|
||||||
this.draw.spliceElementList(elementList, start, endIndex - startIndex, ...newElementList)
|
start,
|
||||||
}
|
startIndex === endIndex ? 0 : endIndex - startIndex,
|
||||||
|
...newElementList
|
||||||
|
)
|
||||||
const curIndex = start + newElementList.length - 1
|
const curIndex = start + newElementList.length - 1
|
||||||
this.range.setRange(curIndex, curIndex)
|
this.range.setRange(curIndex, curIndex)
|
||||||
this.draw.render({ curIndex })
|
this.draw.render({ curIndex })
|
||||||
@@ -1284,6 +1288,7 @@ export class CommandAdapt {
|
|||||||
dashArray: payload
|
dashArray: payload
|
||||||
}
|
}
|
||||||
// 从行头增加分割线
|
// 从行头增加分割线
|
||||||
|
formatElementContext(elementList, [newElement], startIndex)
|
||||||
if (startIndex !== 0 && elementList[startIndex].value === ZERO) {
|
if (startIndex !== 0 && elementList[startIndex].value === ZERO) {
|
||||||
this.draw.spliceElementList(elementList, startIndex, 1, newElement)
|
this.draw.spliceElementList(elementList, startIndex, 1, newElement)
|
||||||
curIndex = startIndex - 1
|
curIndex = startIndex - 1
|
||||||
@@ -1355,11 +1360,13 @@ export class CommandAdapt {
|
|||||||
type: ElementType.IMAGE
|
type: ElementType.IMAGE
|
||||||
}
|
}
|
||||||
const curIndex = startIndex + 1
|
const curIndex = startIndex + 1
|
||||||
if (startIndex === endIndex) {
|
formatElementContext(elementList, [element], startIndex)
|
||||||
this.draw.spliceElementList(elementList, curIndex, 0, element)
|
this.draw.spliceElementList(
|
||||||
} else {
|
elementList,
|
||||||
this.draw.spliceElementList(elementList, curIndex, endIndex - startIndex, element)
|
curIndex,
|
||||||
}
|
startIndex === endIndex ? 0 : endIndex - startIndex,
|
||||||
|
element
|
||||||
|
)
|
||||||
this.range.setRange(curIndex, curIndex)
|
this.range.setRange(curIndex, curIndex)
|
||||||
this.draw.render({ curIndex })
|
this.draw.render({ curIndex })
|
||||||
}
|
}
|
||||||
@@ -1611,6 +1618,10 @@ export class CommandAdapt {
|
|||||||
if (!payload.length) return
|
if (!payload.length) return
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
|
// 格式化上下文信息
|
||||||
|
const { startIndex } = this.range.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
formatElementContext(elementList, payload, startIndex)
|
||||||
this.draw.insertElementList(payload)
|
this.draw.insertElementList(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
import { ZERO } from '../../dataset/constant/Common'
|
||||||
import { EDITOR_PREFIX } from '../../dataset/constant/Editor'
|
import { EDITOR_PREFIX } from '../../dataset/constant/Editor'
|
||||||
|
import { VIRTUAL_ELEMENT_TYPE } from '../../dataset/constant/Element'
|
||||||
import { ElementType } from '../../dataset/enum/Element'
|
import { ElementType } from '../../dataset/enum/Element'
|
||||||
|
import { IElement } from '../../interface/Element'
|
||||||
import { debounce } from '../../utils'
|
import { debounce } from '../../utils'
|
||||||
import { getElementListByHTML } from '../../utils/clipboard'
|
import { getElementListByHTML } from '../../utils/clipboard'
|
||||||
|
import { formatElementContext } from '../../utils/element'
|
||||||
import { Draw } from '../draw/Draw'
|
import { Draw } from '../draw/Draw'
|
||||||
import { CanvasEvent } from '../event/CanvasEvent'
|
import { CanvasEvent } from '../event/CanvasEvent'
|
||||||
|
|
||||||
@@ -47,6 +51,9 @@ export class CursorAgent {
|
|||||||
private _paste(evt: ClipboardEvent) {
|
private _paste(evt: ClipboardEvent) {
|
||||||
const clipboardData = evt.clipboardData
|
const clipboardData = evt.clipboardData
|
||||||
if (!clipboardData) return
|
if (!clipboardData) return
|
||||||
|
const rangeManager = this.draw.getRange()
|
||||||
|
const { startIndex } = rangeManager.getRange()
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
// 从粘贴板提取数据
|
// 从粘贴板提取数据
|
||||||
let isHTML = false
|
let isHTML = false
|
||||||
for (let i = 0; i < clipboardData.items.length; i++) {
|
for (let i = 0; i < clipboardData.items.length; i++) {
|
||||||
@@ -66,10 +73,34 @@ export class CursorAgent {
|
|||||||
}
|
}
|
||||||
if (item.type === 'text/html' && isHTML) {
|
if (item.type === 'text/html' && isHTML) {
|
||||||
item.getAsString(htmlText => {
|
item.getAsString(htmlText => {
|
||||||
const elementList = getElementListByHTML(htmlText, {
|
const pasteElementList = getElementListByHTML(htmlText, {
|
||||||
innerWidth: this.draw.getOriginalInnerWidth()
|
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') {
|
} else if (item.kind === 'file') {
|
||||||
@@ -84,12 +115,16 @@ export class CursorAgent {
|
|||||||
const value = fileReader.result as string
|
const value = fileReader.result as string
|
||||||
image.src = value
|
image.src = value
|
||||||
image.onload = () => {
|
image.onload = () => {
|
||||||
this.draw.insertElementList([{
|
const imageElement: IElement = {
|
||||||
value,
|
value,
|
||||||
type: ElementType.IMAGE,
|
type: ElementType.IMAGE,
|
||||||
width: image.width,
|
width: image.width,
|
||||||
height: image.height
|
height: image.height
|
||||||
}])
|
}
|
||||||
|
if (~startIndex) {
|
||||||
|
formatElementContext(elementList, [imageElement], startIndex)
|
||||||
|
}
|
||||||
|
this.draw.insertElementList([imageElement])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ import { I18n } from '../i18n/I18n'
|
|||||||
import { ImageObserver } from '../observer/ImageObserver'
|
import { ImageObserver } from '../observer/ImageObserver'
|
||||||
import { Zone } from '../zone/Zone'
|
import { Zone } from '../zone/Zone'
|
||||||
import { Footer } from './frame/Footer'
|
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'
|
import { ListParticle } from './particle/ListParticle'
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
@@ -438,18 +438,6 @@ export class Draw {
|
|||||||
return this.footerElementList
|
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[]) {
|
public insertElementList(payload: IElement[]) {
|
||||||
if (!payload.length) return
|
if (!payload.length) return
|
||||||
const isPartRangeInControlOutside = this.control.isPartRangeInControlOutside()
|
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)
|
elementList.splice(start, deleteCount, ...items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { IControl, IControlInitOption, IControlInstance, IControlOption } from '
|
|||||||
import { IElement, IElementPosition } from '../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||||
import { IRange } from '../../../interface/Range'
|
import { IRange } from '../../../interface/Range'
|
||||||
import { deepClone, splitText } from '../../../utils'
|
import { deepClone, splitText } from '../../../utils'
|
||||||
import { pickElementAttr, zipElementList } from '../../../utils/element'
|
import { formatElementContext, pickElementAttr, zipElementList } from '../../../utils/element'
|
||||||
import { Listener } from '../../listener/Listener'
|
import { Listener } from '../../listener/Listener'
|
||||||
import { RangeManager } from '../../range/RangeManager'
|
import { RangeManager } from '../../range/RangeManager'
|
||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
@@ -293,14 +293,16 @@ export class Control {
|
|||||||
const placeholderStrList = splitText(control.placeholder)
|
const placeholderStrList = splitText(control.placeholder)
|
||||||
for (let p = 0; p < placeholderStrList.length; p++) {
|
for (let p = 0; p < placeholderStrList.length; p++) {
|
||||||
const value = placeholderStrList[p]
|
const value = placeholderStrList[p]
|
||||||
this.draw.spliceElementList(elementList, startIndex + p + 1, 0, {
|
const newElement: IElement = {
|
||||||
value,
|
value,
|
||||||
controlId: startElement.controlId,
|
controlId: startElement.controlId,
|
||||||
type: ElementType.CONTROL,
|
type: ElementType.CONTROL,
|
||||||
control: startElement.control,
|
control: startElement.control,
|
||||||
controlComponent: ControlComponent.PLACEHOLDER,
|
controlComponent: ControlComponent.PLACEHOLDER,
|
||||||
color: this.options.placeholderColor
|
color: this.options.placeholderColor
|
||||||
})
|
}
|
||||||
|
formatElementContext(elementList, [newElement], startIndex)
|
||||||
|
this.draw.spliceElementList(elementList, startIndex + p + 1, 0, newElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
|||||||
import { IControlInstance } from '../../../../interface/Control'
|
import { IControlInstance } from '../../../../interface/Control'
|
||||||
import { IElement } from '../../../../interface/Element'
|
import { IElement } from '../../../../interface/Element'
|
||||||
import { splitText } from '../../../../utils'
|
import { splitText } from '../../../../utils'
|
||||||
|
import { formatElementContext } from '../../../../utils/element'
|
||||||
import { Control } from '../Control'
|
import { Control } from '../Control'
|
||||||
|
|
||||||
export class SelectControl implements IControlInstance {
|
export class SelectControl implements IControlInstance {
|
||||||
@@ -189,11 +190,13 @@ export class SelectControl implements IControlInstance {
|
|||||||
const data = splitText(valueSet.value)
|
const data = splitText(valueSet.value)
|
||||||
const draw = this.control.getDraw()
|
const draw = this.control.getDraw()
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
draw.spliceElementList(elementList, start + i, 0, {
|
const newElement: IElement = {
|
||||||
...startElement,
|
...startElement,
|
||||||
value: data[i],
|
value: data[i],
|
||||||
controlComponent: ControlComponent.VALUE
|
controlComponent: ControlComponent.VALUE
|
||||||
})
|
}
|
||||||
|
formatElementContext(elementList, [newElement], startIndex)
|
||||||
|
draw.spliceElementList(elementList, start + i, 0, newElement)
|
||||||
}
|
}
|
||||||
// render
|
// render
|
||||||
const newIndex = start + data.length - 1
|
const newIndex = start + data.length - 1
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ControlComponent } from '../../../../dataset/enum/Control'
|
|||||||
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
||||||
import { IControlInstance } from '../../../../interface/Control'
|
import { IControlInstance } from '../../../../interface/Control'
|
||||||
import { IElement } from '../../../../interface/Element'
|
import { IElement } from '../../../../interface/Element'
|
||||||
|
import { formatElementContext } from '../../../../utils/element'
|
||||||
import { Control } from '../Control'
|
import { Control } from '../Control'
|
||||||
|
|
||||||
export class TextControl implements IControlInstance {
|
export class TextControl implements IControlInstance {
|
||||||
@@ -74,11 +75,13 @@ export class TextControl implements IControlInstance {
|
|||||||
const startElement = elementList[startIndex]
|
const startElement = elementList[startIndex]
|
||||||
const start = range.startIndex + 1
|
const start = range.startIndex + 1
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
draw.spliceElementList(elementList, start + i, 0, {
|
const newElement: IElement = {
|
||||||
...startElement,
|
...startElement,
|
||||||
...data[i],
|
...data[i],
|
||||||
controlComponent: ControlComponent.VALUE
|
controlComponent: ControlComponent.VALUE
|
||||||
})
|
}
|
||||||
|
formatElementContext(elementList, [newElement], startIndex)
|
||||||
|
draw.spliceElementList(elementList, start + i, 0, newElement)
|
||||||
}
|
}
|
||||||
return start + data.length - 1
|
return start + data.length - 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export class ListParticle {
|
|||||||
let text = ''
|
let text = ''
|
||||||
if (startElement.listType === ListType.UL) {
|
if (startElement.listType === ListType.UL) {
|
||||||
if (startElement.listStyle) {
|
if (startElement.listStyle) {
|
||||||
text = ulStyleMapping[<UlStyle><unknown>startElement.listStyle]
|
text = ulStyleMapping[<UlStyle><unknown>startElement.listStyle] || ulStyleMapping[UlStyle.DISC]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
text = `${listIndex! + 1}${KeyMap.PERIOD}`
|
text = `${listIndex! + 1}${KeyMap.PERIOD}`
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { EDITOR_ELEMENT_COPY_ATTR } from '../../../dataset/constant/Element'
|
|||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { IElement } from '../../../interface/Element'
|
import { IElement } from '../../../interface/Element'
|
||||||
import { splitText } from '../../../utils'
|
import { splitText } from '../../../utils'
|
||||||
|
import { formatElementContext } from '../../../utils/element'
|
||||||
import { CanvasEvent } from '../CanvasEvent'
|
import { CanvasEvent } from '../CanvasEvent'
|
||||||
|
|
||||||
export function input(data: string, host: CanvasEvent) {
|
export function input(data: string, host: CanvasEvent) {
|
||||||
@@ -72,6 +73,7 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
if (startIndex !== endIndex) {
|
if (startIndex !== endIndex) {
|
||||||
draw.spliceElementList(elementList, start, endIndex - startIndex)
|
draw.spliceElementList(elementList, start, endIndex - startIndex)
|
||||||
}
|
}
|
||||||
|
formatElementContext(elementList, inputData, startIndex)
|
||||||
draw.spliceElementList(elementList, start, 0, ...inputData)
|
draw.spliceElementList(elementList, start, 0, ...inputData)
|
||||||
curIndex = startIndex + inputData.length
|
curIndex = startIndex + inputData.length
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ZERO } from '../../../dataset/constant/Common'
|
|||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { KeyMap } from '../../../dataset/enum/KeyMap'
|
import { KeyMap } from '../../../dataset/enum/KeyMap'
|
||||||
import { IElement, IElementPosition } from '../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||||
|
import { formatElementContext } from '../../../utils/element'
|
||||||
import { isMod } from '../../../utils/hotkey'
|
import { isMod } from '../../../utils/hotkey'
|
||||||
import { CanvasEvent } from '../CanvasEvent'
|
import { CanvasEvent } from '../CanvasEvent'
|
||||||
|
|
||||||
@@ -76,6 +77,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
const enterText: IElement = {
|
const enterText: IElement = {
|
||||||
value: ZERO
|
value: ZERO
|
||||||
}
|
}
|
||||||
|
formatElementContext(elementList, [enterText], startIndex)
|
||||||
let curIndex: number
|
let curIndex: number
|
||||||
if (activeControl && !control.isRangInPostfix()) {
|
if (activeControl && !control.isRangInPostfix()) {
|
||||||
curIndex = control.setValue([enterText])
|
curIndex = control.setValue([enterText])
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ControlComponent, ControlType } from '../../../dataset/enum/Control'
|
|||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { IElement } from '../../../interface/Element'
|
import { IElement } from '../../../interface/Element'
|
||||||
import { deepClone, getUUID } from '../../../utils'
|
import { deepClone, getUUID } from '../../../utils'
|
||||||
import { formatElementList } from '../../../utils/element'
|
import { formatElementContext, formatElementList } from '../../../utils/element'
|
||||||
import { CanvasEvent } from '../CanvasEvent'
|
import { CanvasEvent } from '../CanvasEvent'
|
||||||
|
|
||||||
type IDragElement = IElement & { dragId: string }
|
type IDragElement = IElement & { dragId: string }
|
||||||
@@ -103,6 +103,7 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
return newElement
|
return newElement
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
formatElementContext(elementList, replaceElementList, range.startIndex)
|
||||||
// 缓存拖拽选区开始结束id
|
// 缓存拖拽选区开始结束id
|
||||||
const cacheRangeStartId = createDragId(cacheElementList[cacheRange.startIndex])
|
const cacheRangeStartId = createDragId(cacheElementList[cacheRange.startIndex])
|
||||||
const cacheRangeEndId = createDragId(cacheElementList[cacheRange.endIndex])
|
const cacheRangeEndId = createDragId(cacheElementList[cacheRange.endIndex])
|
||||||
|
|||||||
@@ -95,10 +95,29 @@ export class RangeManager {
|
|||||||
if (positionList[start]?.value === ZERO) break
|
if (positionList[start]?.value === ZERO) break
|
||||||
start--
|
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) {
|
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]
|
const { pageNo, rowNo } = positionList[end]
|
||||||
let rowArray = rangeRow.get(pageNo)
|
let rowArray = rangeRow.get(pageNo)
|
||||||
if (!rowArray) {
|
if (!rowArray) {
|
||||||
@@ -108,7 +127,6 @@ export class RangeManager {
|
|||||||
if (!rowArray.includes(rowNo)) {
|
if (!rowArray.includes(rowNo)) {
|
||||||
rowArray.push(rowNo)
|
rowArray.push(rowNo)
|
||||||
}
|
}
|
||||||
if (positionList[end].value === ZERO) break
|
|
||||||
end++
|
end++
|
||||||
}
|
}
|
||||||
return rangeRow
|
return rangeRow
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ export const EDITOR_ELEMENT_COPY_ATTR: Array<keyof IElement> = [
|
|||||||
'url',
|
'url',
|
||||||
'hyperlinkId',
|
'hyperlinkId',
|
||||||
'dateId',
|
'dateId',
|
||||||
'dateFormat',
|
'dateFormat'
|
||||||
'level',
|
|
||||||
'titleId'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
export const EDITOR_ELEMENT_ZIP_ATTR: Array<keyof IElement> = [
|
export const EDITOR_ELEMENT_ZIP_ATTR: Array<keyof IElement> = [
|
||||||
@@ -64,6 +62,8 @@ export const EDITOR_ELEMENT_CONTEXT_ATTR: Array<keyof IElement> = [
|
|||||||
'tdId',
|
'tdId',
|
||||||
'trId',
|
'trId',
|
||||||
'tableId',
|
'tableId',
|
||||||
|
'level',
|
||||||
|
'titleId',
|
||||||
'listId',
|
'listId',
|
||||||
'listType',
|
'listType',
|
||||||
'listStyle'
|
'listStyle'
|
||||||
@@ -87,5 +87,12 @@ export const INLINE_ELEMENT_TYPE: ElementType[] = [
|
|||||||
|
|
||||||
export const INLINE_NODE_NAME: string[] = [
|
export const INLINE_NODE_NAME: string[] = [
|
||||||
'HR',
|
'HR',
|
||||||
'TABLE'
|
'TABLE',
|
||||||
|
'UL',
|
||||||
|
'OL'
|
||||||
|
]
|
||||||
|
|
||||||
|
export const VIRTUAL_ELEMENT_TYPE: ElementType[] = [
|
||||||
|
ElementType.TITLE,
|
||||||
|
ElementType.LIST
|
||||||
]
|
]
|
||||||
@@ -1,7 +1,19 @@
|
|||||||
import { UlStyle } from '../enum/List'
|
import { ListStyle, ListType, UlStyle } from '../enum/List'
|
||||||
|
|
||||||
export const ulStyleMapping: Record<UlStyle, string> = {
|
export const ulStyleMapping: Record<UlStyle, string> = {
|
||||||
[UlStyle.DISC]: '•',
|
[UlStyle.DISC]: '•',
|
||||||
[UlStyle.CIRCLE]: '◦',
|
[UlStyle.CIRCLE]: '◦',
|
||||||
[UlStyle.SQUARE]: '▫︎'
|
[UlStyle.SQUARE]: '▫︎'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const listTypeElementMapping: Record<ListType, string> = {
|
||||||
|
[ListType.OL]: 'ol',
|
||||||
|
[ListType.UL]: 'ul'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const listStyleCSSMapping: Record<ListStyle, string> = {
|
||||||
|
[ListStyle.DISC]: 'disc',
|
||||||
|
[ListStyle.CIRCLE]: 'circle',
|
||||||
|
[ListStyle.SQUARE]: 'square',
|
||||||
|
[ListStyle.DECIMAL]: 'decimal'
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { IEditorOption, IElement, RowFlex } from '..'
|
import { IEditorOption, IElement, ListStyle, ListType, RowFlex } from '..'
|
||||||
import { ZERO } from '../dataset/constant/Common'
|
import { ZERO } from '../dataset/constant/Common'
|
||||||
import { INLINE_NODE_NAME, TEXTLIKE_ELEMENT_TYPE } from '../dataset/constant/Element'
|
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 { titleNodeNameMapping, titleOrderNumberMapping } from '../dataset/constant/Title'
|
||||||
import { ControlComponent } from '../dataset/enum/Control'
|
import { ControlComponent } from '../dataset/enum/Control'
|
||||||
import { ElementType } from '../dataset/enum/Element'
|
import { ElementType } from '../dataset/enum/Element'
|
||||||
@@ -53,9 +54,7 @@ export function convertElementToDom(element: IElement, options: DeepRequired<IEd
|
|||||||
if (element.italic) {
|
if (element.italic) {
|
||||||
dom.style.fontStyle = 'italic'
|
dom.style.fontStyle = 'italic'
|
||||||
}
|
}
|
||||||
if (element.size) {
|
dom.style.fontSize = `${element.size || options.defaultSize}px`
|
||||||
dom.style.fontSize = `${element.size}px`
|
|
||||||
}
|
|
||||||
if (element.highlight) {
|
if (element.highlight) {
|
||||||
dom.style.backgroundColor = element.highlight
|
dom.style.backgroundColor = element.highlight
|
||||||
}
|
}
|
||||||
@@ -100,6 +99,38 @@ export function writeElementList(elementList: IElement[], options: DeepRequired<
|
|||||||
const childDom = buildDomFromElementList(zipElementList(element.valueList!))
|
const childDom = buildDomFromElementList(zipElementList(element.valueList!))
|
||||||
h.innerHTML = childDom.innerHTML
|
h.innerHTML = childDom.innerHTML
|
||||||
clipboardDom.append(h)
|
clipboardDom.append(h)
|
||||||
|
} else if (element.type === ElementType.LIST) {
|
||||||
|
const list = document.createElement(listTypeElementMapping[element.listType!])
|
||||||
|
if (element.listStyle) {
|
||||||
|
list.style.listStyleType = listStyleCSSMapping[element.listStyle]
|
||||||
|
}
|
||||||
|
// 按照换行符拆分
|
||||||
|
let curListIndex = 0
|
||||||
|
const listElementListMap: Map<number, IElement[]> = 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) {
|
} else if (element.type === ElementType.IMAGE) {
|
||||||
const img = document.createElement('img')
|
const img = document.createElement('img')
|
||||||
if (element.value) {
|
if (element.value) {
|
||||||
@@ -218,6 +249,27 @@ export function getElementListByHTML(htmlText: string, options: IGetElementListB
|
|||||||
value: '\n'
|
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 = <ListStyle><unknown>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') {
|
} else if (node.nodeName === 'HR') {
|
||||||
elementList.push({
|
elementList.push({
|
||||||
value: '\n',
|
value: '\n',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { LaTexParticle } from '../core/draw/particle/latex/LaTexParticle'
|
|||||||
import { defaultCheckboxOption } from '../dataset/constant/Checkbox'
|
import { defaultCheckboxOption } from '../dataset/constant/Checkbox'
|
||||||
import { ZERO } from '../dataset/constant/Common'
|
import { ZERO } from '../dataset/constant/Common'
|
||||||
import { defaultControlOption } from '../dataset/constant/Control'
|
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 { titleSizeMapping } from '../dataset/constant/Title'
|
||||||
import { ControlComponent, ControlType } from '../dataset/enum/Control'
|
import { ControlComponent, ControlType } from '../dataset/enum/Control'
|
||||||
import { ITd } from '../interface/table/Td'
|
import { ITd } from '../interface/table/Td'
|
||||||
@@ -31,7 +31,8 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme
|
|||||||
isHandleFirstElement: true,
|
isHandleFirstElement: true,
|
||||||
...options
|
...options
|
||||||
}
|
}
|
||||||
if (isHandleFirstElement && elementList[0]?.value !== ZERO) {
|
const startElement = elementList[0]
|
||||||
|
if (isHandleFirstElement && startElement?.value !== ZERO && startElement?.value !== '\n') {
|
||||||
elementList.unshift({
|
elementList.unshift({
|
||||||
value: ZERO
|
value: ZERO
|
||||||
})
|
})
|
||||||
@@ -540,3 +541,24 @@ export function getElementRowFlex(node: HTMLElement) {
|
|||||||
export function isTextLikeElement(element: IElement): boolean {
|
export function isTextLikeElement(element: IElement): boolean {
|
||||||
return !element.type || TEXTLIKE_ELEMENT_TYPE.includes(element.type)
|
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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user