Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions packages/fluent-editor/src/config/editor.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,49 @@ export function replaceDeltaImage(delta, imageUrls, imagePlaceholder) {
}, new Delta())
}

const WHITE_SPACE_CHAR_RE = /^[\u3000\u0020]$/
const WHITE_SPACE_OR_NBSP_RE = /^[\u3000\u0020\u00A0]$/

/**
* 将连续空格转为不间断空格,以便 innerHTML 输出   并在预览中保留间距。
* - 行首空白:全部转为 \u00A0
* - 正文内连续空白:保留第一个普通空格,其余转为 \u00A0
*/
export function replaceStrWhiteSpace(str: string) {
let textWithWhiteSpace = ''
let beginHasChar = false
let consecutiveSpaces = 0
for (const char of str) {
if (WHITE_SPACE_CHAR_RE.test(char)) {
consecutiveSpaces += 1
if (!beginHasChar) {
textWithWhiteSpace += '\u00A0'
}
else if (consecutiveSpaces === 1) {
textWithWhiteSpace += char
}
else {
textWithWhiteSpace += '\u00A0'
}
}
else {
consecutiveSpaces = 0
textWithWhiteSpace += char
beginHasChar = true
}
}
return textWithWhiteSpace
}

/** 空格键是否应插入不间断空格(与 replaceStrWhiteSpace 规则一致) */
export function shouldInsertNbspOnSpace(prefix: string) {
if (!prefix) {
return true
}
const lastChar = prefix.slice(-1)
return WHITE_SPACE_OR_NBSP_RE.test(lastChar)
}

export function splitWithBreak(insertContent: string) {
const lines = []
const insertStr = insertContent
Expand Down
17 changes: 1 addition & 16 deletions packages/fluent-editor/src/modules/custom-clipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
isNullOrUndefined,
omit,
replaceDeltaImage,
replaceStrWhiteSpace,
splitWithBreak,
} from '../config/editor.utils'
import { isString } from '../utils/is'
Expand Down Expand Up @@ -454,22 +455,6 @@ function rebuildDelta(delta, cellLine) {
return buildedDelta
}

function replaceStrWhiteSpace(str) {
const isWhiteSpace = value => /^(\u3000|\u0020){1}$/.test(value) // 空白字符
let textWithWhiteSpace = ''
let beginHasChar = false
for (const char of str) {
if (isWhiteSpace(char) && !beginHasChar) {
textWithWhiteSpace += '\u00A0'
}
else {
textWithWhiteSpace += char
beginHasChar = true
}
}
return textWithWhiteSpace
}

function replaceDeltaWhiteSpace(delta, rootBgColor?) {
return delta.reduce((newDelta, op) => {
// fix: 当粘贴文字颜色和编辑器背景色一致且自身无背景色的情况下移除文字颜色样式,避免误导用户粘贴无效
Expand Down
19 changes: 18 additions & 1 deletion packages/fluent-editor/src/themes/snow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ThemeOptions } from 'quill/core/theme'
import type TypeToolbar from 'quill/modules/toolbar'
import type TypeIconPicker from 'quill/ui/icon-picker'
import { I18N_LOCALE_CHANGE } from 'quill-i18n'
import { inputFile, isNullOrUndefined } from '../config'
import { inputFile, isNullOrUndefined, shouldInsertNbspOnSpace } from '../config'
import FluentEditor from '../core/fluent-editor'
import { CustomImageSpec } from '../modules/custom-image/specs/custom-image-spec'
import { LinkTooltip } from '../modules/link'
Expand All @@ -21,6 +21,23 @@ OriginSnowTheme.DEFAULTS = {
'keyboard': {
bindings: {
...shortKey,
preserveWhiteSpace: {
key: ' ',
collapsed: true,
handler(this: { quill: FluentEditor }, range, context) {
if (!shouldInsertNbspOnSpace(context.prefix)) {
return true
}
this.quill.insertText(
range.index,
'\u00A0',
context.format,
FluentEditor.sources.USER,
)
this.quill.setSelection(range.index + 1, FluentEditor.sources.SILENT)
return false
},
},
},
},
'toolbar': {
Expand Down
Loading