adtec-core-package 3.0.4 → 3.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -335,7 +335,7 @@ function buildUmoMountOptions(content: string) {
335
335
  zh_CN: placeholder,
336
336
  },
337
337
  readOnly: !editableNow,
338
- autofocus: editableNow,
338
+ autofocus: false,
339
339
  enableMarkdown: false,
340
340
  enableSpellcheck: false,
341
341
  autoSave: {
@@ -81,7 +81,7 @@ import {
81
81
  } from '../utils/history-record'
82
82
  import { getOpitons } from '../utils/options'
83
83
  import { getSelectionNode, getSelectionText } from '../utils/selection'
84
- import { syncCacheOnEditorSelectionUpdate } from '../composables/toolbarSelection.js'
84
+ import { syncCacheOnEditorSelectionUpdate, bumpToolbarEditorState } from '../composables/toolbarSelection.js'
85
85
  import { shortId } from '../utils/short-id'
86
86
  import { getCurrentInstance } from 'vue'
87
87
 
@@ -332,6 +332,7 @@ watch(
332
332
  editor.value.on('update', ({ editor }) => {
333
333
  emits('changed', { editor })
334
334
  contentUpdated.value = true
335
+ bumpToolbarEditorState()
335
336
  })
336
337
  editor.value.on('selectionUpdate', ({ editor }) => {
337
338
  syncCacheOnEditorSelectionUpdate(editor)
@@ -205,6 +205,7 @@
205
205
  :disabled="
206
206
  !forceEnabled && (disabled || editor?.isEditable === false)
207
207
  "
208
+ @mousedown.prevent="cacheToolbarSelection"
208
209
  >
209
210
  <div class="umo-button-content" @click="menuClick">
210
211
  <slot />
@@ -341,7 +342,7 @@ import { isString } from '@tool-belt/type-predicates'
341
342
  import { getShortcut } from '../../utils/shortcut'
342
343
 
343
344
 
344
- import { useAttrs, inject, watch, ref } from 'vue';
345
+ import { useAttrs, inject, watch, ref, onBeforeUnmount } from 'vue';
345
346
  import { onClickOutside } from '@vueuse/core';
346
347
  const { selectVisible } = useSelect()
347
348
 
@@ -442,24 +443,50 @@ const cacheToolbarSelection = () => {
442
443
  }
443
444
  }
444
445
 
446
+ /** 打开下拉时同一次点击可能落在首项上(幽灵 click),短暂忽略 @change */
447
+ let suppressSelectChange = false
448
+ let suppressSelectChangeTimer = null
449
+
450
+ const clearSuppressSelectChange = () => {
451
+ suppressSelectChange = false
452
+ if (suppressSelectChangeTimer != null) {
453
+ clearTimeout(suppressSelectChangeTimer)
454
+ suppressSelectChangeTimer = null
455
+ }
456
+ }
457
+
458
+ const scheduleSuppressSelectChange = () => {
459
+ clearSuppressSelectChange()
460
+ suppressSelectChange = true
461
+ suppressSelectChangeTimer = setTimeout(clearSuppressSelectChange, 250)
462
+ }
463
+
464
+ onBeforeUnmount(clearSuppressSelectChange)
465
+
445
466
  const onSelectTriggerPress = () => {
446
467
  beginSelectMenuInteraction(editor?.value)
468
+ scheduleSuppressSelectChange()
447
469
  }
448
470
 
449
471
  const selectPopupVisibleChange = (visible) => {
450
472
  popupVisileChange(visible)
451
473
  if (visible) {
452
474
  beginSelectMenuInteraction(editor?.value)
475
+ scheduleSuppressSelectChange()
453
476
  } else {
454
477
  endSelectMenuInteraction()
478
+ clearSuppressSelectChange()
455
479
  }
456
480
  }
457
481
 
458
- const selectMenuClick = (...args) => {
482
+ const selectMenuClick = (value, context, ...rest) => {
483
+ if (suppressSelectChange || context?.trigger === 'default') {
484
+ return
485
+ }
459
486
  if (editor?.value?.state.selection.empty) {
460
487
  restorePendingSelectMenuRange(editor.value)
461
488
  }
462
- menuClick(...args)
489
+ menuClick(value, context, ...rest)
463
490
  }
464
491
 
465
492
  const tooltipVisible = _ref(false)
@@ -28,6 +28,10 @@ import { ref as _ref } from 'vue';
28
28
 
29
29
 
30
30
  import { inject } from 'vue';
31
+ import {
32
+ FOCUS_WITHOUT_SCROLL,
33
+ runPreservingScroll,
34
+ } from '../../../../utils/editor-scroll.js';
31
35
  const props = defineProps({
32
36
  text: {
33
37
  type: String,
@@ -46,6 +50,7 @@ const emits = defineEmits(['change'])
46
50
 
47
51
  const { popupVisible, togglePopup } = usePopup()
48
52
  const editor = inject('editor')
53
+ const container = inject('container')
49
54
 
50
55
  let currentColor = _ref()
51
56
  const colorChange = (color) => {
@@ -57,11 +62,13 @@ const colorChange = (color) => {
57
62
  return
58
63
  }
59
64
 
60
- if (color === '') {
61
- editor.value?.chain().focus().unsetColor().run()
62
- } else {
63
- editor.value?.chain().focus().setColor(color).run()
64
- }
65
+ runPreservingScroll(container, () => {
66
+ if (color === '') {
67
+ editor.value?.chain().focus(undefined, FOCUS_WITHOUT_SCROLL).unsetColor().run()
68
+ } else {
69
+ editor.value?.chain().focus(undefined, FOCUS_WITHOUT_SCROLL).setColor(color).run()
70
+ }
71
+ })
65
72
  }
66
73
  </script>
67
74
 
@@ -57,6 +57,10 @@
57
57
 
58
58
  <script setup>
59
59
  import { t } from '../../../../composables/i18n.js';
60
+ import {
61
+ getToolbarFontFamily,
62
+ toolbarEditorTick,
63
+ } from '../../../../composables/toolbarSelection.js';
60
64
 
61
65
  import { useState } from '../../../../composables/state.js';
62
66
  import { ref as _ref } from 'vue';
@@ -81,13 +85,11 @@ let autoDownloadRunning = _ref(false)
81
85
  let restoringDownloadedFonts = _ref(true)
82
86
 
83
87
  const selectedFont = computed(() => {
88
+ toolbarEditorTick.value
84
89
  if (!editor.value || typeWriterIsRunning.value) {
85
90
  return null
86
91
  }
87
- if (!editor.value?.getAttributes('textStyle').fontFamily) {
88
- return null
89
- }
90
- return editor.value.getAttributes('textStyle').fontFamily.replace(/"/g, '')
92
+ return getToolbarFontFamily(editor.value)
91
93
  })
92
94
 
93
95
  const ensureRecentState = () => {
@@ -6,11 +6,7 @@
6
6
  hide-text
7
7
  style="width: 80px"
8
8
  :select-options="fontSizes"
9
- :select-value="
10
- typeWriterIsRunning
11
- ? null
12
- : editor?.getAttributes('textStyle').fontSize || '14px'
13
- "
9
+ :select-value="selectFontSize"
14
10
  v-bind="$attrs"
15
11
  :placeholder="t('base.fontSize.text')"
16
12
  filterable
@@ -40,10 +36,16 @@
40
36
  import { t } from '../../../../composables/i18n.js';
41
37
  import {
42
38
  applyCachedTextSelection,
39
+ getToolbarFontSize,
43
40
  refreshCachedTextSelection,
44
41
  restorePendingSelectMenuRange,
42
+ toolbarEditorTick,
45
43
  } from '../../../../composables/toolbarSelection.js';
46
- import { inject } from 'vue';
44
+ import { computed, inject } from 'vue';
45
+ import {
46
+ FOCUS_WITHOUT_SCROLL,
47
+ runPreservingScroll,
48
+ } from '../../../../utils/editor-scroll.js';
47
49
 
48
50
  const props = defineProps({
49
51
  select: {
@@ -53,6 +55,7 @@ const props = defineProps({
53
55
  })
54
56
 
55
57
  const editor = inject('editor')
58
+ const container = inject('container')
56
59
  const options = inject('options')
57
60
  const typeWriterIsRunning = inject('typeWriterIsRunning')
58
61
 
@@ -60,6 +63,12 @@ const disableMenu = (name) => {
60
63
  return options.value.disableExtensions.includes(name)
61
64
  }
62
65
 
66
+ const selectFontSize = computed(() => {
67
+ toolbarEditorTick.value
68
+ if (typeWriterIsRunning.value) return null
69
+ return getToolbarFontSize(editor.value)
70
+ })
71
+
63
72
  const fontSizes = [
64
73
  { label: t('base.fontSize.default'), value: '14px', order: 4 },
65
74
  { label: t('base.fontSize.42pt'), value: '42pt', order: 20 }, // 56
@@ -94,36 +103,44 @@ const fontSizes = [
94
103
  { label: '96', value: '96px', order: 22 },
95
104
  ]
96
105
 
97
- // 设置字体大小(连续改字号时保持选区)
106
+ // 设置字体大小(连续改字号时保持选区,且不触发外层页面滚动)
98
107
  const applyFontSize = (fontSize) => {
99
108
  const ed = editor.value
100
109
  if (!ed) return
101
110
 
102
- const { empty, from, to } = ed.state.selection
103
- let chain = ed.chain().focus()
111
+ runPreservingScroll(container, () => {
112
+ const { empty, from, to } = ed.state.selection
113
+ let chain = ed.chain().focus(undefined, FOCUS_WITHOUT_SCROLL)
104
114
 
105
- if (!empty && from !== to) {
106
- chain = chain.setTextSelection({ from, to })
107
- } else if (
108
- !restorePendingSelectMenuRange(ed) &&
109
- !applyCachedTextSelection(ed)
110
- ) {
111
- return
112
- } else {
113
- const sel = ed.state.selection
114
- if (!sel.empty && sel.from !== sel.to) {
115
- chain = ed.chain().focus().setTextSelection({ from: sel.from, to: sel.to })
116
- } else {
115
+ if (!empty && from !== to) {
116
+ chain = chain.setTextSelection({ from, to })
117
+ } else if (
118
+ !restorePendingSelectMenuRange(ed) &&
119
+ !applyCachedTextSelection(ed)
120
+ ) {
117
121
  return
122
+ } else {
123
+ const sel = ed.state.selection
124
+ if (!sel.empty && sel.from !== sel.to) {
125
+ chain = ed
126
+ .chain()
127
+ .focus(undefined, FOCUS_WITHOUT_SCROLL)
128
+ .setTextSelection({ from: sel.from, to: sel.to })
129
+ } else {
130
+ return
131
+ }
118
132
  }
119
- }
120
133
 
121
- if (chain.setFontSize(fontSize).run()) {
122
- refreshCachedTextSelection(ed)
123
- }
134
+ if (chain.setFontSize(fontSize).run()) {
135
+ refreshCachedTextSelection(ed)
136
+ }
137
+ })
124
138
  }
125
139
 
126
140
  const setFontSize = (fontSize) => {
141
+ if (!fontSize) return
142
+ const current = getToolbarFontSize(editor.value)
143
+ if (current === fontSize) return
127
144
  applyFontSize(fontSize)
128
145
  }
129
146
 
@@ -84,8 +84,8 @@ import { inject, ref, computed } from 'vue';
84
84
  import { onClickOutside } from '@vueuse/core';
85
85
  import {
86
86
  applyHeadingWithoutScroll,
87
- captureScrollPositions,
88
- restoreScrollPositions,
87
+ FOCUS_WITHOUT_SCROLL,
88
+ runPreservingScroll,
89
89
  } from '../../../../utils/editor-scroll.js';
90
90
  const { popupVisible } = usePopup()
91
91
  const container = inject('container')
@@ -133,16 +133,14 @@ const currentValue = computed(() => {
133
133
  return ''
134
134
  })
135
135
 
136
- const FOCUS_WITHOUT_SCROLL = { scrollIntoView: false }
137
-
138
136
  const setHeading = (value) => {
139
137
  const ed = editor.value
140
138
  if (!ed) return
141
139
 
142
- const scrollPositions = captureScrollPositions(container)
143
- ed.commands.focus(undefined, FOCUS_WITHOUT_SCROLL)
144
- applyHeadingWithoutScroll(ed, value)
145
- restoreScrollPositions(scrollPositions)
140
+ runPreservingScroll(container, () => {
141
+ ed.commands.focus(undefined, FOCUS_WITHOUT_SCROLL)
142
+ applyHeadingWithoutScroll(ed, value)
143
+ })
146
144
  popupVisible.value = false
147
145
  }
148
146
 
@@ -1,8 +1,17 @@
1
+ import { ref } from 'vue'
2
+
1
3
  /** 工具栏 t-select 等抢焦点时缓存的非空文本选区 */
2
4
  let cachedRange = null
3
5
  /** 当前 t-select 弹层会话内快照(打开下拉时锁定,避免误恢复旧选区) */
4
6
  let pendingSelectRange = null
5
7
 
8
+ /** ProseMirror 选区/mark 变化时递增,供 Vue computed 订阅 */
9
+ export const toolbarEditorTick = ref(0)
10
+
11
+ export function bumpToolbarEditorState() {
12
+ toolbarEditorTick.value += 1
13
+ }
14
+
6
15
  export function cacheEditorTextSelection(editor) {
7
16
  if (!editor?.state) return
8
17
  const { from, to, empty } = editor.state.selection
@@ -17,11 +26,13 @@ export function syncCacheOnEditorSelectionUpdate(editor) {
17
26
  if (!empty && from !== to) {
18
27
  cachedRange = { from, to }
19
28
  }
29
+ bumpToolbarEditorState()
20
30
  }
21
31
 
22
32
  export function beginSelectMenuInteraction(editor) {
23
33
  if (!editor?.state) {
24
34
  pendingSelectRange = cachedRange ? { ...cachedRange } : null
35
+ bumpToolbarEditorState()
25
36
  return
26
37
  }
27
38
  const { from, to, empty } = editor.state.selection
@@ -33,10 +44,12 @@ export function beginSelectMenuInteraction(editor) {
33
44
  } else {
34
45
  pendingSelectRange = null
35
46
  }
47
+ bumpToolbarEditorState()
36
48
  }
37
49
 
38
50
  export function endSelectMenuInteraction() {
39
51
  pendingSelectRange = null
52
+ bumpToolbarEditorState()
40
53
  }
41
54
 
42
55
  function applyTextRange(editor, range) {
@@ -65,4 +78,224 @@ export function refreshCachedTextSelection(editor) {
65
78
  if (!empty && from !== to) {
66
79
  cachedRange = { from, to }
67
80
  }
81
+ bumpToolbarEditorState()
82
+ }
83
+
84
+ function clampRange(editor, range) {
85
+ if (!editor?.state || !range) return null
86
+ const docSize = editor.state.doc.content.size
87
+ const from = Math.max(0, Math.min(range.from, docSize))
88
+ const to = Math.max(from, Math.min(range.to, docSize))
89
+ if (to <= from) return null
90
+ return { from, to }
91
+ }
92
+
93
+ /** Word 中文字号 pt/px 对照(与 richTextHtmlUtils 一致) */
94
+ const CHINESE_FONT_SIZE_PT_PX = [
95
+ { pt: 42, px: 49 },
96
+ { pt: 36, px: 42 },
97
+ { pt: 26, px: 30 },
98
+ { pt: 24, px: 28 },
99
+ { pt: 22, px: 26 },
100
+ { pt: 18, px: 21 },
101
+ { pt: 16, px: 19 },
102
+ { pt: 15, px: 18 },
103
+ { pt: 14, px: 16 },
104
+ { pt: 12, px: 14 },
105
+ { pt: 10.5, px: 12 },
106
+ { pt: 9, px: 11 },
107
+ { pt: 7.5, px: 9 },
108
+ { pt: 6.5, px: 8 },
109
+ ]
110
+
111
+ function normalizeFontSizeValue(raw) {
112
+ if (!raw) return null
113
+ const value = String(raw).trim()
114
+ const pxMatch = value.match(/^(\d+(?:\.\d+)?)px$/i)
115
+ if (pxMatch) {
116
+ return `${Math.round(parseFloat(pxMatch[1]))}px`
117
+ }
118
+ const ptMatch = value.match(/^(\d+(?:\.\d+)?)pt$/i)
119
+ if (ptMatch) {
120
+ return `${parseFloat(ptMatch[1])}pt`
121
+ }
122
+ return value
123
+ }
124
+
125
+ /** 将 DOM/浏览器读到的 px 映射回 pt 选项值,供 t-select 显示中文标签 */
126
+ function resolveFontSizeForToolbarDisplay(raw) {
127
+ const normalized = normalizeFontSizeValue(raw)
128
+ if (!normalized) return null
129
+ if (/pt$/i.test(normalized)) return normalized
130
+
131
+ const pxMatch = normalized.match(/^(\d+(?:\.\d+)?)px$/i)
132
+ if (!pxMatch) return normalized
133
+
134
+ const px = Math.round(parseFloat(pxMatch[1]))
135
+ // 14px 为编辑器「默认」,勿映射为 12pt(小四)
136
+ if (px === 14) return '14px'
137
+
138
+ const byWordPx = CHINESE_FONT_SIZE_PT_PX.find((entry) => entry.px === px)
139
+ if (byWordPx) return `${byWordPx.pt}pt`
140
+
141
+ // 浏览器按 CSS 换算的 px(如 36pt → 48px)
142
+ const cssPt = (px * 72) / 96
143
+ const byCssPt = CHINESE_FONT_SIZE_PT_PX.find(
144
+ (entry) => Math.abs(entry.pt - cssPt) < 0.6,
145
+ )
146
+ if (byCssPt) return `${byCssPt.pt}pt`
147
+
148
+ return normalized
149
+ }
150
+
151
+ function readTextStyleMarkAtPos(editor, pos, attr) {
152
+ const $pos = editor.state.doc.resolve(pos)
153
+ const activeMarks = $pos.marks()
154
+ const storedMarks = editor.state.storedMarks ?? []
155
+ const marks = activeMarks.length ? activeMarks : storedMarks
156
+ const textStyle = marks.find((mark) => mark.type.name === 'textStyle')
157
+ return textStyle?.attrs?.[attr] ?? null
158
+ }
159
+
160
+ function readFontSizeFromDom(editor, pos) {
161
+ if (typeof window === 'undefined') return null
162
+ const view = editor.view
163
+ if (!view?.dom) return null
164
+
165
+ try {
166
+ const domPos = view.domAtPos(pos)
167
+ let node = domPos.node
168
+ if (node.nodeType === Node.TEXT_NODE) {
169
+ node = node.parentElement
170
+ }
171
+
172
+ while (node && node !== view.dom) {
173
+ const inlineSize = node.style?.fontSize
174
+ const computedSize =
175
+ inlineSize && inlineSize !== 'inherit'
176
+ ? inlineSize
177
+ : window.getComputedStyle(node).fontSize
178
+ const normalized = normalizeFontSizeValue(computedSize)
179
+ if (normalized) {
180
+ return normalized
181
+ }
182
+ node = node.parentElement
183
+ }
184
+ } catch {
185
+ return null
186
+ }
187
+
188
+ return null
189
+ }
190
+
191
+ function readFontSizeAtRange(editor, range) {
192
+ const clamped = clampRange(editor, range)
193
+ if (!clamped) return null
194
+
195
+ const { from, to } = clamped
196
+ let fontSize = null
197
+
198
+ editor.state.doc.nodesBetween(from, to, (node, pos) => {
199
+ if (fontSize || !node.isText) return
200
+ const mark = node.marks.find(
201
+ (item) => item.type.name === 'textStyle' && item.attrs?.fontSize,
202
+ )
203
+ if (mark) {
204
+ fontSize = mark.attrs.fontSize
205
+ }
206
+ })
207
+
208
+ if (!fontSize) {
209
+ const readPos = Math.min(from + 1, to - 1, editor.state.doc.content.size - 1)
210
+ fontSize = readTextStyleMarkAtPos(editor, Math.max(from, readPos), 'fontSize')
211
+ }
212
+
213
+ if (!fontSize) {
214
+ fontSize = readFontSizeFromDom(editor, from)
215
+ }
216
+
217
+ return resolveFontSizeForToolbarDisplay(fontSize)
218
+ }
219
+
220
+ function readFontFamilyAtRange(editor, range) {
221
+ const clamped = clampRange(editor, range)
222
+ if (!clamped) return null
223
+
224
+ const { from, to } = clamped
225
+ let fontFamily = null
226
+
227
+ editor.state.doc.nodesBetween(from, to, (node) => {
228
+ if (fontFamily || !node.isText) return
229
+ const mark = node.marks.find(
230
+ (item) => item.type.name === 'textStyle' && item.attrs?.fontFamily,
231
+ )
232
+ if (mark) {
233
+ fontFamily = mark.attrs.fontFamily
234
+ }
235
+ })
236
+
237
+ if (!fontFamily) {
238
+ const readPos = Math.min(from + 1, to - 1, editor.state.doc.content.size - 1)
239
+ fontFamily = readTextStyleMarkAtPos(
240
+ editor,
241
+ Math.max(from, readPos),
242
+ 'fontFamily',
243
+ )
244
+ }
245
+
246
+ return fontFamily ? fontFamily.replace(/"/g, '') : null
247
+ }
248
+
249
+ function getActiveTextRange(editor) {
250
+ if (!editor?.state) return null
251
+ const { from, to, empty } = editor.state.selection
252
+ if (!empty && from !== to) {
253
+ return { from, to }
254
+ }
255
+ return pendingSelectRange ?? cachedRange
256
+ }
257
+
258
+ /** t-select 抢焦点导致选区折叠时,仍从缓存选区读取字号供下拉框展示 */
259
+ export function getToolbarFontSize(editor) {
260
+ if (!editor?.state) return null
261
+
262
+ const { from, to, empty } = editor.state.selection
263
+ if (!empty && from !== to) {
264
+ return (
265
+ readFontSizeAtRange(editor, { from, to }) ??
266
+ resolveFontSizeForToolbarDisplay(
267
+ editor.getAttributes('textStyle').fontSize,
268
+ ) ??
269
+ resolveFontSizeForToolbarDisplay(readFontSizeFromDom(editor, from))
270
+ )
271
+ }
272
+
273
+ const range = getActiveTextRange(editor)
274
+ return (
275
+ readFontSizeAtRange(editor, range) ??
276
+ resolveFontSizeForToolbarDisplay(
277
+ editor.getAttributes('textStyle').fontSize,
278
+ ) ??
279
+ (range
280
+ ? resolveFontSizeForToolbarDisplay(readFontSizeFromDom(editor, range.from))
281
+ : null)
282
+ )
283
+ }
284
+
285
+ /** t-select 抢焦点导致选区折叠时,仍从缓存选区读取字体供下拉框展示 */
286
+ export function getToolbarFontFamily(editor) {
287
+ if (!editor?.state) return null
288
+
289
+ const { from, to, empty } = editor.state.selection
290
+ if (!empty && from !== to) {
291
+ return readFontFamilyAtRange(editor, { from, to })
292
+ }
293
+
294
+ const range = getActiveTextRange(editor)
295
+ return (
296
+ readFontFamilyAtRange(editor, range) ??
297
+ (editor.getAttributes('textStyle').fontFamily
298
+ ? editor.getAttributes('textStyle').fontFamily.replace(/"/g, '')
299
+ : null)
300
+ )
68
301
  }
@@ -51,8 +51,8 @@
51
51
  "12pt": "ཆུང་བའི་བཞི་པ།",
52
52
  "10_5pt": "ཨང་ལྔ་པ།",
53
53
  "9pt": "ཆུང་བའི་ལྔ་པ།",
54
- "7_5pt": "ཆུང་བའི་དྲུག་པ།",
55
- "6_5pt": "སྔོན་སྒྲིག"
54
+ "7_5pt": "དྲུག་པའི་ཨང་།",
55
+ "6_5pt": "ཆུང་བའི་དྲུག་པ།"
56
56
  },
57
57
  "formatPainter": {
58
58
  "text": "རྣམ་གཞག་འབྱུག་པ།",
@@ -66,8 +66,8 @@
66
66
  "12pt": "Sub-fourth Level",
67
67
  "10_5pt": "Fifth Level",
68
68
  "9pt": "Sub-fifth Level",
69
- "7_5pt": "Sub-sixth Level",
70
- "6_5pt": "Default"
69
+ "7_5pt": "Sixth Level",
70
+ "6_5pt": "Sub-sixth Level"
71
71
  },
72
72
  "formatPainter": {
73
73
  "text": "Format Painter",
@@ -51,8 +51,8 @@
51
51
  "12pt": "Sotto livello quattro",
52
52
  "10_5pt": "Quinto livello",
53
53
  "9pt": "Sotto livello cinque",
54
- "7_5pt": "Sotto livello sei",
55
- "6_5pt": "Predefinito"
54
+ "7_5pt": "Sesto livello",
55
+ "6_5pt": "Sotto livello sei"
56
56
  },
57
57
  "formatPainter": {
58
58
  "text": "Copia formato",
@@ -57,8 +57,8 @@
57
57
  "12pt": "Под-четвертый уровень",
58
58
  "10_5pt": "Пятый уровень",
59
59
  "9pt": "Под-пятый уровень",
60
- "7_5pt": "Под-шестой уровень",
61
- "6_5pt": "По умолчанию"
60
+ "7_5pt": "Шестой уровень",
61
+ "6_5pt": "Под-шестой уровень"
62
62
  },
63
63
  "formatPainter": {
64
64
  "text": "Формат по образцу",
@@ -66,8 +66,8 @@
66
66
  "12pt": "小四",
67
67
  "10_5pt": "五号",
68
68
  "9pt": "小五",
69
- "7_5pt": "小六",
70
- "6_5pt": "默认"
69
+ "7_5pt": "六号",
70
+ "6_5pt": "小六"
71
71
  },
72
72
  "formatPainter": {
73
73
  "text": "格式刷",