@mnykj/alleditor-dual 1.1.1 → 1.1.2
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.
- package/README.md +2 -2
- package/package.json +2 -2
- package/src/DualEditor.vue +2 -2
- package/src/UeHtmlEngine.vue +43 -3
package/README.md
CHANGED
|
@@ -58,10 +58,10 @@ const html = ref('<p>hello</p>')
|
|
|
58
58
|
## HTML 协议
|
|
59
59
|
|
|
60
60
|
```html
|
|
61
|
-
<div class="alleditor-root" data-alleditor-engine="ue">…</div>
|
|
61
|
+
<div class="alleditor-root" data-alleditor-engine="wang|ue">…</div>
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
wang / ue 保存时都会包外层;兼容旧注释 `<!--yunkee-editor:ue-html-->`。
|
|
65
65
|
|
|
66
66
|
## 开发(monorepo)
|
|
67
67
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mnykj/alleditor-dual",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "AllEditor dual-engine (wang + UE HTML) Vue3 components, with bundled UEditor static assets",
|
|
5
5
|
"author": "mnykj",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"registry": "https://registry.npmjs.org/"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@mnykj/alleditor": "^1.1.
|
|
40
|
+
"@mnykj/alleditor": "^1.1.1",
|
|
41
41
|
"@mnykj/alleditor-for-vue": "^1.1.0",
|
|
42
42
|
"vue": "^3.0.5",
|
|
43
43
|
"vite": ">=4",
|
package/src/DualEditor.vue
CHANGED
|
@@ -31,8 +31,8 @@ const props = defineProps({
|
|
|
31
31
|
editorConfig: { type: Object, default: () => ({}) },
|
|
32
32
|
/** wang 占位正文(UE 模式下避免把高保真 HTML 喂进 Slate) */
|
|
33
33
|
wangPlaceholder: { type: String, default: '<p><br></p>' },
|
|
34
|
-
/**
|
|
35
|
-
wrapOnlyWhenUe: { type: Boolean, default:
|
|
34
|
+
/** 为 true 时仅 ue 写外层 div;默认 false,wang/ue 都包 data-alleditor-engine */
|
|
35
|
+
wrapOnlyWhenUe: { type: Boolean, default: false },
|
|
36
36
|
toolbarSelector: {
|
|
37
37
|
type: String,
|
|
38
38
|
default: '.alleditor-dual .w-e-toolbar, .alleditor-dual .editor-toolbar',
|
package/src/UeHtmlEngine.vue
CHANGED
|
@@ -95,6 +95,29 @@ function syncDisabled() {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* 清理公众号/Slate 残留:
|
|
100
|
+
* - <span leaf=""> 包住的 img 易让 UEditor 图片缩放框错位,挡住正文无法编辑
|
|
101
|
+
* - 去掉无意义的 leaf 属性
|
|
102
|
+
*/
|
|
103
|
+
function sanitizeUeHtml(html) {
|
|
104
|
+
return String(html ?? '')
|
|
105
|
+
.replace(/<span\b[^>]*\bleaf(?:\s*=\s*(?:""|''|[^>\s]+))?\s*[^>]*>\s*(<img\b[^>]*>)\s*<\/span>/gi, '$1')
|
|
106
|
+
.replace(/\sleaf(?:\s*=\s*(?:""|''|"[^"]*"|'[^']*'|[^\s>]+))?/gi, '')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function hideImageScaleUi(ue) {
|
|
110
|
+
try {
|
|
111
|
+
const uiRoot = ue?.ui?.getDom?.()
|
|
112
|
+
if (!uiRoot) return
|
|
113
|
+
uiRoot.querySelectorAll('.edui-editor-imagescale, [id$="_imagescale"], [id$="_imagescale_cover"]').forEach((el) => {
|
|
114
|
+
el.style.display = 'none'
|
|
115
|
+
})
|
|
116
|
+
} catch {
|
|
117
|
+
/* ignore */
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
98
121
|
function getContent() {
|
|
99
122
|
const ue = instance.value
|
|
100
123
|
if (!ue || !ready) {
|
|
@@ -109,7 +132,7 @@ function getContent() {
|
|
|
109
132
|
}
|
|
110
133
|
|
|
111
134
|
function setContent(html) {
|
|
112
|
-
const next = html || ''
|
|
135
|
+
const next = sanitizeUeHtml(html || '')
|
|
113
136
|
const ue = instance.value
|
|
114
137
|
if (!ue || !ready) {
|
|
115
138
|
pendingHtml = next
|
|
@@ -121,6 +144,7 @@ function setContent(html) {
|
|
|
121
144
|
} finally {
|
|
122
145
|
applying = false
|
|
123
146
|
}
|
|
147
|
+
hideImageScaleUi(ue)
|
|
124
148
|
requestAnimationFrame(() => fitEditorHeight(ue))
|
|
125
149
|
}
|
|
126
150
|
|
|
@@ -251,6 +275,10 @@ onMounted(async () => {
|
|
|
251
275
|
initialFrameHeight: height,
|
|
252
276
|
initialFrameWidth: '100%',
|
|
253
277
|
autoHeightEnabled: false,
|
|
278
|
+
// 关闭图片八爪缩放框:编辑区在 iframe 内时缩放层常错位/关不掉,正文点不动
|
|
279
|
+
imageScaleEnabled: false,
|
|
280
|
+
imagePopup: false,
|
|
281
|
+
scaleEnabled: false,
|
|
254
282
|
serverUrl: '',
|
|
255
283
|
enableAutoSave: false,
|
|
256
284
|
elementPathEnabled: false,
|
|
@@ -269,12 +297,15 @@ onMounted(async () => {
|
|
|
269
297
|
emit('update:modelValue', html)
|
|
270
298
|
emit('change', html)
|
|
271
299
|
})
|
|
300
|
+
// 即便外部配置被覆盖,缩放层弹出时立刻隐藏,避免挡住编辑
|
|
301
|
+
ue.addListener('afterscaleshow', () => hideImageScaleUi(ue))
|
|
272
302
|
|
|
273
303
|
ue.ready(() => {
|
|
274
304
|
if (destroyed) return
|
|
275
305
|
ready = true
|
|
276
|
-
const initial =
|
|
306
|
+
const initial = sanitizeUeHtml(
|
|
277
307
|
pendingHtml !== undefined ? pendingHtml : props.modelValue || ''
|
|
308
|
+
)
|
|
278
309
|
pendingHtml = undefined
|
|
279
310
|
applying = true
|
|
280
311
|
try {
|
|
@@ -283,6 +314,7 @@ onMounted(async () => {
|
|
|
283
314
|
applying = false
|
|
284
315
|
}
|
|
285
316
|
injectReadableBodyStyle(ue)
|
|
317
|
+
hideImageScaleUi(ue)
|
|
286
318
|
fitEditorHeight(ue)
|
|
287
319
|
bindResize(ue)
|
|
288
320
|
requestAnimationFrame(() => fitEditorHeight(ue))
|
|
@@ -300,7 +332,7 @@ watch(
|
|
|
300
332
|
() => props.modelValue,
|
|
301
333
|
(html) => {
|
|
302
334
|
if (destroyed) return
|
|
303
|
-
const next = html || ''
|
|
335
|
+
const next = sanitizeUeHtml(html || '')
|
|
304
336
|
if (!ready || applying) {
|
|
305
337
|
pendingHtml = next
|
|
306
338
|
return
|
|
@@ -382,4 +414,12 @@ defineExpose({
|
|
|
382
414
|
border: none !important;
|
|
383
415
|
background: #fff !important;
|
|
384
416
|
}
|
|
417
|
+
|
|
418
|
+
/* 兜底隐藏图片缩放框(错位时会盖住正文) */
|
|
419
|
+
.alleditor-ue-engine :deep(.edui-editor-imagescale),
|
|
420
|
+
.alleditor-ue-engine :deep([id$='_imagescale']),
|
|
421
|
+
.alleditor-ue-engine :deep([id$='_imagescale_cover']) {
|
|
422
|
+
display: none !important;
|
|
423
|
+
pointer-events: none !important;
|
|
424
|
+
}
|
|
385
425
|
</style>
|