diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 43f1c52..db5d75d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -15,28 +15,28 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v1
- with:
- node-version: ${{ matrix.node-version }}
- - run: npm i yarn -g
- - run: yarn
- - run: yarn run build
- - run: mv dist canvas-editor
- - name: Copy folder content recursively to remote
- uses: garygrossgarten/github-action-scp@release
- with:
- local: canvas-editor
- remote: ${{ secrets.PATH }}
- host: ${{ secrets.HOST }}
- username: ${{ secrets.USERNAME }}
- password: ${{ secrets.PASSWORD }}
- rmRemote: true
- - name: Executing remote ssh commands
- uses: appleboy/ssh-action@v1.0.3
- with:
- host: ${{ secrets.HOST }}
- username: ${{ secrets.USERNAME }}
- password: ${{ secrets.PASSWORD }}
- script: sed -i 's/<\/body>/${{ secrets.SCRIPT }}<\/body>/g' ${{ secrets.PATH }}/index.html
+ - uses: actions/checkout@v2
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v1
+ with:
+ node-version: ${{ matrix.node-version }}
+ - run: npm i yarn -g
+ - run: yarn
+ - run: yarn run build
+ - run: mv dist canvas-editor
+ - name: Copy folder content recursively to remote
+ uses: appleboy/scp-action@v0.1.7
+ with:
+ source: canvas-editor
+ target: ${{ secrets.PATH }}
+ host: ${{ secrets.HOST }}
+ username: ${{ secrets.USERNAME }}
+ password: ${{ secrets.PASSWORD }}
+ overwrite: true
+ - name: Executing remote ssh commands
+ uses: appleboy/ssh-action@v1.0.3
+ with:
+ host: ${{ secrets.HOST }}
+ username: ${{ secrets.USERNAME }}
+ password: ${{ secrets.PASSWORD }}
+ script: sed -i 's/<\/body>/${{ secrets.SCRIPT }}<\/body>/g' ${{ secrets.PATH }}/canvas-editor/index.html
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index c8f9b74..215cd4a 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -4,6 +4,7 @@ on:
push:
branches: [main]
paths:
+ - '.github/workflows/docs.yml'
- 'docs/**'
jobs:
@@ -11,21 +12,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v1
- with:
- node-version: ${{ matrix.node-version }}
- - run: npm i yarn -g
- - run: yarn
- - run: yarn run docs:build
- - run: mv ./docs/.vitepress/dist ./docs/.vitepress/canvas-editor-docs
- - name: Copy folder content recursively to remote
- uses: garygrossgarten/github-action-scp@release
- with:
- local: ./docs/.vitepress/canvas-editor-docs
- remote: ${{ secrets.DOCS_PATH }}
- host: ${{ secrets.HOST }}
- username: ${{ secrets.USERNAME }}
- password: ${{ secrets.PASSWORD }}
- rmRemote: true
+ - uses: actions/checkout@v2
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v1
+ with:
+ node-version: ${{ matrix.node-version }}
+ - run: npm i yarn -g
+ - run: yarn
+ - run: yarn run docs:build
+ - run: mv ./docs/.vitepress/dist ./docs/.vitepress/canvas-editor-docs
+ - name: Copy folder content recursively to remote
+ uses: appleboy/scp-action@v0.1.7
+ with:
+ source: docs/.vitepress/canvas-editor-docs
+ target: ${{ secrets.DOCS_PATH }}
+ host: ${{ secrets.HOST }}
+ username: ${{ secrets.USERNAME }}
+ password: ${{ secrets.PASSWORD }}
+ overwrite: true
+ strip_components: 2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f54e074..31e030b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,30 @@
+## [0.9.85](https://github.com/Hufe921/canvas-editor/compare/v0.9.84...v0.9.85) (2024-07-07)
+
+
+### Bug Fixes
+
+* custom override method removes support for asynchronous #672 ([0e705d6](https://github.com/Hufe921/canvas-editor/commit/0e705d6a0bdb0922efd5c47edd8ca9eba9964199)), closes [#672](https://github.com/Hufe921/canvas-editor/issues/672)
+* set control highlight and re render #678 ([24df9d3](https://github.com/Hufe921/canvas-editor/commit/24df9d3b006a8daf795ada677bfd0159e3ccc3f5)), closes [#678](https://github.com/Hufe921/canvas-editor/issues/678)
+
+
+### Chores
+
+* update build.yml ([a40441d](https://github.com/Hufe921/canvas-editor/commit/a40441dc3994a41ae29c341a542be6e0e7dada2e))
+
+
+### Features
+
+* add render mode #667 ([affd191](https://github.com/Hufe921/canvas-editor/commit/affd1911552a73a2b63a13f2c423121637830b99)), closes [#667](https://github.com/Hufe921/canvas-editor/issues/667)
+* add title deletable property #670 ([b3d8413](https://github.com/Hufe921/canvas-editor/commit/b3d8413b35050eac626af1c57beaaf1b8d692a0e)), closes [#670](https://github.com/Hufe921/canvas-editor/issues/670)
+* insert element boundary optimization #669 ([de44bd6](https://github.com/Hufe921/canvas-editor/commit/de44bd68ab01e5ffa8d6a8dc5d566b0cdb8d08e6)), closes [#669](https://github.com/Hufe921/canvas-editor/issues/669)
+
+
+### Tests
+
+* update text test case ([c24da73](https://github.com/Hufe921/canvas-editor/commit/c24da737b15200775a7d4a5edf4e2224f6ec5429))
+
+
+
## [0.9.84](https://github.com/Hufe921/canvas-editor/compare/v0.9.83...v0.9.84) (2024-06-30)
diff --git a/cypress/e2e/menus/text.cy.ts b/cypress/e2e/menus/text.cy.ts
index e75b0da..3c8eeb5 100644
--- a/cypress/e2e/menus/text.cy.ts
+++ b/cypress/e2e/menus/text.cy.ts
@@ -33,7 +33,7 @@ describe('菜单-文本处理', () => {
.then(() => {
const data = editor.command.getValue().data.main
- expect(data[0].font).to.eq('宋体')
+ expect(data[0].font).to.eq('华文宋体')
})
})
})
diff --git a/docs/en/guide/command-execute.md b/docs/en/guide/command-execute.md
index e285dcd..7b0cd77 100644
--- a/docs/en/guide/command-execute.md
+++ b/docs/en/guide/command-execute.md
@@ -932,6 +932,16 @@ Usage:
instance.command.executeLocationControl(controlId: string)
```
+## executeInsertControl
+
+Feature: Insert control
+
+Usage:
+
+```javascript
+instance.command.executeInsertControl(payload: IElement)
+```
+
## executeUpdateOptions
Feature: Update options
diff --git a/docs/en/guide/option.md b/docs/en/guide/option.md
index ff76b45..1b27863 100644
--- a/docs/en/guide/option.md
+++ b/docs/en/guide/option.md
@@ -43,6 +43,7 @@ interface IEditorOption {
marginIndicatorColor?: string // The margin indicator color. default: #BABABA
margins?: IMargin // Page margins. default: [100, 120, 100, 120]
pageMode?: PageMode // Paper mode: Linkage, Pagination. default: Pagination
+ renderMode?: RenderMode // Render mode: speed(multi words combination rendering), compatibility(word by word rendering:avoid environmental differences such as browse,fonts...). default: speed
defaultHyperlinkColor?: string // Default hyperlink color. default: #0000FF
table?: ITableOption // table configuration {tdPadding?:IPadding; defaultTrMinHeight?:number; defaultColMinWidth?:number}
header?: IHeader // Header information.{top?:number; maxHeightRadio?:MaxHeightRatio;}
diff --git a/docs/en/guide/schema.md b/docs/en/guide/schema.md
index 682dd59..e9fe133 100644
--- a/docs/en/guide/schema.md
+++ b/docs/en/guide/schema.md
@@ -154,7 +154,10 @@ interface IElement {
};
// title
level?: TitleLevel;
- title?: ITitle;
+ title?: {
+ conceptId?: string;
+ deletable?: boolean;
+ };
// list
listType?: ListType;
listStyle?: ListStyle;
diff --git a/docs/guide/command-execute.md b/docs/guide/command-execute.md
index e37ca9d..edd3da2 100644
--- a/docs/guide/command-execute.md
+++ b/docs/guide/command-execute.md
@@ -932,6 +932,16 @@ instance.command.executeSetControlHighlight(payload: ISetControlHighlightOption)
instance.command.executeLocationControl(controlId: string)
```
+## executeInsertControl
+
+功能:插入控件
+
+用法:
+
+```javascript
+instance.command.executeInsertControl(payload: IElement)
+```
+
## executeUpdateOptions
功能:修改配置
diff --git a/docs/guide/option.md b/docs/guide/option.md
index 3ec3abb..b3158e7 100644
--- a/docs/guide/option.md
+++ b/docs/guide/option.md
@@ -43,6 +43,7 @@ interface IEditorOption {
marginIndicatorColor?: string // 页边距指示器颜色。默认:#BABABA
margins?: IMargin // 页面边距。默认:[100, 120, 100, 120]
pageMode?: PageMode // 纸张模式:连页、分页。默认:分页
+ renderMode?: RenderMode // 渲染模式:极速(多个字组合渲染)、兼容(逐字渲染:避免浏览器字体等环境差异)。默认:极速
defaultHyperlinkColor?: string // 默认超链接颜色。默认:#0000FF
table?: ITableOption // 表格配置。{tdPadding?:IPadding; defaultTrMinHeight?:number; defaultColMinWidth?:number}
header?: IHeader // 页眉信息。{top?:number; maxHeightRadio?:MaxHeightRatio;}
diff --git a/docs/guide/schema.md b/docs/guide/schema.md
index 8965300..11c5c55 100644
--- a/docs/guide/schema.md
+++ b/docs/guide/schema.md
@@ -154,7 +154,10 @@ interface IElement {
};
// 标题
level?: TitleLevel;
- title?: ITitle;
+ title?: {
+ conceptId?: string;
+ deletable?: boolean;
+ };
// 列表
listType?: ListType;
listStyle?: ListStyle;
diff --git a/index.html b/index.html
index 1b4fbad..e3d64ce 100644
--- a/index.html
+++ b/index.html
@@ -32,11 +32,10 @@
- 微软雅黑
- - 宋体
- - 黑体
- - 仿宋
- - 楷体
- - 等线
+ - 华文宋体
+ - 华文黑体
+ - 华文仿宋
+ - 华文楷体
- 华文琥珀
- 华文楷体
- 华文隶书
diff --git a/package.json b/package.json
index a5155b8..41122bc 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "@hufe921/canvas-editor",
"author": "Hufe",
"license": "MIT",
- "version": "0.9.84",
+ "version": "0.9.85",
"description": "rich text editor by canvas/svg",
"publishConfig": {
"registry": "https://registry.npmjs.org/",
diff --git a/src/editor/core/command/Command.ts b/src/editor/core/command/Command.ts
index 43e82e9..aadab4d 100644
--- a/src/editor/core/command/Command.ts
+++ b/src/editor/core/command/Command.ts
@@ -92,6 +92,7 @@ export class Command {
public executeSetControlProperties: CommandAdapt['setControlProperties']
public executeSetControlHighlight: CommandAdapt['setControlHighlight']
public executeLocationControl: CommandAdapt['locationControl']
+ public executeInsertControl: CommandAdapt['insertControl']
public executeUpdateOptions: CommandAdapt['updateOptions']
public executeInsertTitle: CommandAdapt['insertTitle']
public getCatalog: CommandAdapt['getCatalog']
@@ -242,5 +243,6 @@ export class Command {
this.getControlValue = adapt.getControlValue.bind(adapt)
this.getControlList = adapt.getControlList.bind(adapt)
this.executeLocationControl = adapt.locationControl.bind(adapt)
+ this.executeInsertControl = adapt.insertControl.bind(adapt)
}
}
diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts
index 4cdd86a..9139940 100644
--- a/src/editor/core/command/CommandAdapt.ts
+++ b/src/editor/core/command/CommandAdapt.ts
@@ -2263,7 +2263,9 @@ export class CommandAdapt {
// 格式化上下文信息
const { startIndex } = this.range.getRange()
const elementList = this.draw.getElementList()
- formatElementContext(elementList, cloneElementList, startIndex)
+ formatElementContext(elementList, cloneElementList, startIndex, {
+ isBreakWhenWrap: true
+ })
this.draw.insertElementList(cloneElementList)
}
@@ -2484,6 +2486,9 @@ export class CommandAdapt {
public setControlHighlight(payload: ISetControlHighlightOption) {
this.draw.getControl().setHighlightList(payload)
+ this.draw.render({
+ isSubmitHistory: false
+ })
}
public updateOptions(payload: IUpdateOption) {
@@ -2577,6 +2582,25 @@ export class CommandAdapt {
}
}
+ public insertControl(payload: IElement) {
+ const isReadonly = this.draw.isReadonly()
+ if (isReadonly) return
+ const cloneElement = deepClone(payload)
+ // 格式化上下文信息
+ const { startIndex } = this.range.getRange()
+ const elementList = this.draw.getElementList()
+ const copyElement = getAnchorElement(elementList, startIndex)
+ if (!copyElement) return
+ const cloneAttr = [
+ ...TABLE_CONTEXT_ATTR,
+ ...EDITOR_ROW_ATTR,
+ ...LIST_CONTEXT_ATTR
+ ]
+ cloneProperty(cloneAttr, copyElement, cloneElement)
+ // 插入控件
+ this.draw.insertElementList([cloneElement])
+ }
+
public getContainer(): HTMLDivElement {
return this.draw.getContainer()
}
diff --git a/src/editor/core/cursor/Cursor.ts b/src/editor/core/cursor/Cursor.ts
index 27d5603..b01d5fe 100644
--- a/src/editor/core/cursor/Cursor.ts
+++ b/src/editor/core/cursor/Cursor.ts
@@ -129,8 +129,11 @@ export class Cursor {
const agentCursorDom = this.cursorAgent.getAgentCursorDom()
if (isFocus) {
setTimeout(() => {
- agentCursorDom.focus()
- agentCursorDom.setSelectionRange(0, 0)
+ // 光标不聚焦时重新定位
+ if (document.activeElement !== agentCursorDom) {
+ agentCursorDom.focus()
+ agentCursorDom.setSelectionRange(0, 0)
+ }
})
}
// fillText位置 + 文字基线到底部距离 - 模拟光标偏移量
diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts
index da9b52c..951d814 100644
--- a/src/editor/core/draw/Draw.ts
+++ b/src/editor/core/draw/Draw.ts
@@ -685,7 +685,11 @@ export class Draw {
if (!this.control.getActiveControl()) {
let deleteIndex = endIndex - 1
while (deleteIndex >= start) {
- if (elementList[deleteIndex]?.control?.deletable !== false) {
+ const deleteElement = elementList[deleteIndex]
+ if (
+ deleteElement?.control?.deletable !== false &&
+ deleteElement?.title?.deletable !== false
+ ) {
elementList.splice(deleteIndex, 1)
}
deleteIndex--
diff --git a/src/editor/core/draw/control/Control.ts b/src/editor/core/draw/control/Control.ts
index ff0bb9d..709a30c 100644
--- a/src/editor/core/draw/control/Control.ts
+++ b/src/editor/core/draw/control/Control.ts
@@ -23,7 +23,7 @@ import { IEditorData, IEditorOption } from '../../../interface/Editor'
import { IElement, IElementPosition } from '../../../interface/Element'
import { EventBusMap } from '../../../interface/EventBus'
import { IRange } from '../../../interface/Range'
-import { deepClone, nextTick, splitText } from '../../../utils'
+import { deepClone, nextTick, omitObject, splitText } from '../../../utils'
import {
formatElementContext,
formatElementList,
@@ -42,7 +42,11 @@ import { SelectControl } from './select/SelectControl'
import { TextControl } from './text/TextControl'
import { DateControl } from './date/DateControl'
import { MoveDirection } from '../../../dataset/enum/Observer'
-import { CONTROL_STYLE_ATTR } from '../../../dataset/constant/Element'
+import {
+ CONTROL_STYLE_ATTR,
+ LIST_CONTEXT_ATTR,
+ TITLE_CONTEXT_ATTR
+} from '../../../dataset/constant/Element'
interface IMoveCursorResult {
newIndex: number
@@ -876,7 +880,12 @@ export class Control {
}
}
if (element.controlId) {
- controlElementList.push(element)
+ // 移除控件所在标题及列表上下文信息
+ const controlElement = omitObject(element, [
+ ...TITLE_CONTEXT_ATTR,
+ ...LIST_CONTEXT_ATTR
+ ])
+ controlElementList.push(controlElement)
}
}
}
diff --git a/src/editor/core/draw/control/text/TextControl.ts b/src/editor/core/draw/control/text/TextControl.ts
index 46941b4..ef08b3e 100644
--- a/src/editor/core/draw/control/text/TextControl.ts
+++ b/src/editor/core/draw/control/text/TextControl.ts
@@ -133,7 +133,7 @@ export class TextControl implements IControlInstance {
.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
const value = this.getValue(context)
if (!value.length) {
- this.control.addPlaceholder(startIndex)
+ this.control.addPlaceholder(startIndex, context)
}
return startIndex
}
diff --git a/src/editor/core/draw/particle/TextParticle.ts b/src/editor/core/draw/particle/TextParticle.ts
index b538861..ec4cfc9 100644
--- a/src/editor/core/draw/particle/TextParticle.ts
+++ b/src/editor/core/draw/particle/TextParticle.ts
@@ -1,4 +1,4 @@
-import { ElementType, IEditorOption, IElement } from '../../..'
+import { ElementType, IEditorOption, IElement, RenderMode } from '../../..'
import {
PUNCTUATION_LIST,
METRICS_BASIS_TEXT
@@ -124,6 +124,15 @@ export class TextParticle {
y: number
) {
this.ctx = ctx
+ // 兼容模式立即绘制
+ if (this.options.renderMode === RenderMode.COMPATIBILITY) {
+ this._setCurXY(x, y)
+ this.text = element.value
+ this.curStyle = element.style
+ this.curColor = element.color
+ this.complete()
+ return
+ }
// 主动完成的重设起始点
if (!this.text) {
this._setCurXY(x, y)
diff --git a/src/editor/core/event/handlers/keydown/enter.ts b/src/editor/core/event/handlers/keydown/enter.ts
index 7a8d0a1..5ef46d9 100644
--- a/src/editor/core/event/handlers/keydown/enter.ts
+++ b/src/editor/core/event/handlers/keydown/enter.ts
@@ -38,6 +38,10 @@ export function enter(evt: KeyboardEvent, host: CanvasEvent) {
if (evt.shiftKey && startElement.listId) {
enterText.listWrap = true
}
+ // 格式化上下文
+ formatElementContext(elementList, [enterText], startIndex, {
+ isBreakWhenWrap: true
+ })
// 标题结尾处回车无需格式化及样式复制
if (
!(
@@ -45,8 +49,6 @@ export function enter(evt: KeyboardEvent, host: CanvasEvent) {
endElement.titleId !== elementList[endIndex + 1]?.titleId
)
) {
- // 格式化上下文
- formatElementContext(elementList, [enterText], startIndex)
// 复制样式属性
const copyElement = getAnchorElement(elementList, endIndex)
if (copyElement) {
diff --git a/src/editor/dataset/enum/Editor.ts b/src/editor/dataset/enum/Editor.ts
index 94960a5..c19757a 100644
--- a/src/editor/dataset/enum/Editor.ts
+++ b/src/editor/dataset/enum/Editor.ts
@@ -42,3 +42,8 @@ export enum WordBreak {
BREAK_ALL = 'break-all',
BREAK_WORD = 'break-word'
}
+
+export enum RenderMode {
+ SPEED = 'speed',
+ COMPATIBILITY = 'compatibility'
+}
diff --git a/src/editor/index.ts b/src/editor/index.ts
index 1559544..d8dd3c0 100644
--- a/src/editor/index.ts
+++ b/src/editor/index.ts
@@ -21,7 +21,8 @@ import {
EditorMode,
PageMode,
PaperDirection,
- WordBreak
+ WordBreak,
+ RenderMode
} from './dataset/enum/Editor'
import { EDITOR_COMPONENT } from './dataset/constant/Editor'
import { IWatermark } from './interface/Watermark'
@@ -150,6 +151,7 @@ export {
ControlType,
EditorComponent,
PageMode,
+ RenderMode,
ImageDisplay,
Command,
KeyMap,
diff --git a/src/editor/interface/Editor.ts b/src/editor/interface/Editor.ts
index e05f7c2..ca1495b 100644
--- a/src/editor/interface/Editor.ts
+++ b/src/editor/interface/Editor.ts
@@ -3,6 +3,7 @@ import {
EditorMode,
PageMode,
PaperDirection,
+ RenderMode,
WordBreak
} from '../dataset/enum/Editor'
import { IBackgroundOption } from './Background'
@@ -60,6 +61,7 @@ export interface IEditorOption {
marginIndicatorColor?: string
margins?: IMargin
pageMode?: PageMode
+ renderMode?: RenderMode
defaultHyperlinkColor?: string
paperDirection?: PaperDirection
inactiveAlpha?: number
diff --git a/src/editor/interface/Title.ts b/src/editor/interface/Title.ts
index 0f4641a..1e97ac2 100644
--- a/src/editor/interface/Title.ts
+++ b/src/editor/interface/Title.ts
@@ -12,7 +12,11 @@ export interface ITitleSizeOption {
export type ITitleOption = ITitleSizeOption & {}
-export interface ITitle {
+export interface ITitleRule {
+ deletable?: boolean
+}
+
+export type ITitle = ITitleRule & {
conceptId?: string
}
diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts
index d26d34a..fded443 100644
--- a/src/editor/utils/element.ts
+++ b/src/editor/utils/element.ts
@@ -826,7 +826,7 @@ export function formatElementContext(
if (
isBreakWhenWrap &&
!copyElement.listId &&
- /^\n/.test(targetElement.value)
+ START_LINE_BREAK_REG.test(targetElement.value)
) {
isBreakWarped = true
}
diff --git a/src/editor/utils/option.ts b/src/editor/utils/option.ts
index 65a944c..0121a20 100644
--- a/src/editor/utils/option.ts
+++ b/src/editor/utils/option.ts
@@ -39,6 +39,7 @@ import {
EditorMode,
PageMode,
PaperDirection,
+ RenderMode,
WordBreak
} from '../dataset/enum/Editor'
@@ -144,6 +145,7 @@ export function mergeOption(
marginIndicatorColor: '#BABABA',
margins: [100, 120, 100, 120],
pageMode: PageMode.PAGING,
+ renderMode: RenderMode.SPEED,
defaultHyperlinkColor: '#0000FF',
paperDirection: PaperDirection.VERTICAL,
inactiveAlpha: 0.6,