diff --git a/src/assets/styles/prosemirror.scss b/src/assets/styles/prosemirror.scss
index 15f1735c..7b7bd1f0 100644
--- a/src/assets/styles/prosemirror.scss
+++ b/src/assets/styles/prosemirror.scss
@@ -17,7 +17,6 @@
}
p {
- text-indent: var(--textIndent);
margin-top: var(--paragraphSpace);
}
p:first-child {
@@ -61,25 +60,28 @@
}
[data-indent='1'] {
- padding-left: 48px;
+ padding-left: 24px;
}
[data-indent='2'] {
- padding-left: 96px;
+ padding-left: 48px;
}
[data-indent='3'] {
- padding-left: 144px;
+ padding-left: 72px;
}
[data-indent='4'] {
- padding-left: 192px;
+ padding-left: 96px;
}
[data-indent='5'] {
- padding-left: 240px;
+ padding-left: 120px;
}
[data-indent='6'] {
- padding-left: 288px;
+ padding-left: 144px;
}
[data-indent='7'] {
- padding-left: 336px;
+ padding-left: 168px;
+ }
+ [data-indent='8'] {
+ padding-left: 192px;
}
}
diff --git a/src/types/slides.ts b/src/types/slides.ts
index 52922885..b594071b 100644
--- a/src/types/slides.ts
+++ b/src/types/slides.ts
@@ -140,8 +140,6 @@ interface PPTBaseElement {
*
* shadow?: 阴影
*
- * textIndent?: 段落首行缩进
- *
* paragraphSpace?: 段间距,默认 5px
*
* vertical?: 竖向文本
@@ -157,7 +155,6 @@ export interface PPTTextElement extends PPTBaseElement {
wordSpace?: number
opacity?: number
shadow?: PPTElementShadow
- textIndent?: number
paragraphSpace?: number
vertical?: boolean
}
diff --git a/src/utils/prosemirror/commands/setTextIndent.ts b/src/utils/prosemirror/commands/setTextIndent.ts
index 4589b58b..78281880 100644
--- a/src/utils/prosemirror/commands/setTextIndent.ts
+++ b/src/utils/prosemirror/commands/setTextIndent.ts
@@ -3,30 +3,32 @@ import { type Transaction, TextSelection, AllSelection } from 'prosemirror-state
import type { EditorView } from 'prosemirror-view'
import { isList } from './toggleList'
-function setNodeIndentMarkup(tr: Transaction, pos: number, delta: number): Transaction {
+type IndentKey = 'indent' | 'textIndent'
+
+function setNodeIndentMarkup(tr: Transaction, pos: number, delta: number, indentKey: IndentKey): Transaction {
if (!tr.doc) return tr
const node = tr.doc.nodeAt(pos)
if (!node) return tr
const minIndent = 0
- const maxIndent = 7
+ const maxIndent = 8
- let indent = (node.attrs.indent || 0) + delta
+ let indent = (node.attrs[indentKey] || 0) + delta
if (indent < minIndent) indent = minIndent
if (indent > maxIndent) indent = maxIndent
- if (indent === node.attrs.indent) return tr
+ if (indent === node.attrs[indentKey]) return tr
const nodeAttrs = {
...node.attrs,
- indent,
+ [indentKey]: indent,
}
return tr.setNodeMarkup(pos, node.type, nodeAttrs, node.marks)
}
-const setTextIndent = (tr: Transaction, schema: Schema, delta: number): Transaction => {
+const setIndent = (tr: Transaction, schema: Schema, delta: number, indentKey: IndentKey): Transaction => {
const { selection, doc } = tr
if (!selection || !doc) return tr
@@ -38,7 +40,7 @@ const setTextIndent = (tr: Transaction, schema: Schema, delta: number): Transact
const nodeType = node.type
if (nodeType.name === 'paragraph' || nodeType.name === 'blockquote') {
- tr = setNodeIndentMarkup(tr, pos, delta)
+ tr = setNodeIndentMarkup(tr, pos, delta, indentKey)
return false
}
else if (isList(node, schema)) return false
@@ -52,10 +54,29 @@ export const indentCommand = (view: EditorView, delta: number) => {
const { state } = view
const { schema, selection } = state
- const tr = setTextIndent(
+ const tr = setIndent(
state.tr.setSelection(selection),
schema,
delta,
+ 'indent',
+ )
+ if (tr.docChanged) {
+ view.dispatch(tr)
+ return true
+ }
+
+ return false
+}
+
+export const textIndentCommand = (view: EditorView, delta: number) => {
+ const { state } = view
+ const { schema, selection } = state
+
+ const tr = setIndent(
+ state.tr.setSelection(selection),
+ schema,
+ delta,
+ 'textIndent',
)
if (tr.docChanged) {
view.dispatch(tr)
diff --git a/src/utils/prosemirror/schema/nodes.ts b/src/utils/prosemirror/schema/nodes.ts
index 08010933..45f22553 100644
--- a/src/utils/prosemirror/schema/nodes.ts
+++ b/src/utils/prosemirror/schema/nodes.ts
@@ -84,6 +84,9 @@ const paragraph: NodeSpec = {
indent: {
default: 0,
},
+ textIndent: {
+ default: 0,
+ },
},
content: 'inline*',
group: 'block',
@@ -91,14 +94,20 @@ const paragraph: NodeSpec = {
{
tag: 'p',
getAttrs: dom => {
- const { textAlign } = (dom as HTMLElement).style
+ const { textAlign, textIndent } = (dom as HTMLElement).style
let align = (dom as HTMLElement).getAttribute('align') || textAlign || ''
align = /(left|right|center|justify)/.test(align) ? align : ''
+ let textIndentLevel = 0
+ if (textIndent) {
+ textIndentLevel = Math.floor(parseInt(textIndent) / 24)
+ if (!textIndentLevel) textIndentLevel = 1
+ }
+
const indent = +((dom as HTMLElement).getAttribute('data-indent') || 0)
- return { align, indent }
+ return { align, indent, textIndent: textIndentLevel }
}
},
{
@@ -111,9 +120,10 @@ const paragraph: NodeSpec = {
},
],
toDOM: (node: Node) => {
- const { align, indent } = node.attrs
+ const { align, indent, textIndent } = node.attrs
let style = ''
if (align && align !== 'left') style += `text-align: ${align};`
+ if (textIndent) style += `text-indent: ${textIndent * 24}px;`
const attr: Attr = { style }
if (indent) attr['data-indent'] = indent
diff --git a/src/views/Editor/Toolbar/ElementStylePanel/TextStylePanel.vue b/src/views/Editor/Toolbar/ElementStylePanel/TextStylePanel.vue
index ef8beedf..e59f57fe 100644
--- a/src/views/Editor/Toolbar/ElementStylePanel/TextStylePanel.vue
+++ b/src/views/Editor/Toolbar/ElementStylePanel/TextStylePanel.vue
@@ -256,14 +256,35 @@
-