@alitons/ckeditor5 0.0.30 → 0.0.31
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/build/ckeditor.d.ts +4 -0
- package/build/ckeditor.js +2 -2
- package/build/ckeditor.js.map +1 -1
- package/build/plugins/DocumentosPlugin.d.ts +7 -0
- package/package.json +1 -1
- package/sample/script.js +58 -3
- package/src/ckeditor.ts +20 -2
- package/src/css/custom.css +47 -0
- package/src/plugins/DocumentosPlugin.ts +389 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
|
|
2
|
+
import Widget from '@ckeditor/ckeditor5-widget/src/widget';
|
|
3
|
+
export default class DocumentosPlugin extends Plugin {
|
|
4
|
+
static get pluginName(): string;
|
|
5
|
+
static get requires(): (typeof Widget)[];
|
|
6
|
+
init(): Promise<void>;
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@alitons/ckeditor5",
|
|
3
3
|
"author": "Aliton Silva",
|
|
4
4
|
"description": "Ckeditor 5 Personalizado adicionados campos para atender as demandas da SEAD/AC",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.31",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
7
7
|
"private": false,
|
|
8
8
|
"main": "./build/ckeditor.js",
|
package/sample/script.js
CHANGED
|
@@ -115,7 +115,9 @@ watchdog.create( document.querySelector( '.editor' ), {
|
|
|
115
115
|
'importarsei',
|
|
116
116
|
'documentoModelo',
|
|
117
117
|
'|',
|
|
118
|
-
'conteudoDinamico:produtos'
|
|
118
|
+
'conteudoDinamico:produtos',
|
|
119
|
+
'|',
|
|
120
|
+
'insertDocumento'
|
|
119
121
|
]
|
|
120
122
|
},
|
|
121
123
|
heading: {
|
|
@@ -132,10 +134,50 @@ watchdog.create( document.querySelector( '.editor' ), {
|
|
|
132
134
|
uiClass: 'ui-fancy' // isso é pra UI (dropdown)
|
|
133
135
|
}
|
|
134
136
|
]
|
|
135
|
-
}
|
|
137
|
+
},
|
|
138
|
+
inserirDocumento: {
|
|
139
|
+
dropdownLabel: 'Inserir Documento',
|
|
140
|
+
getItems: async () => {
|
|
141
|
+
const lista = await buscarLista();
|
|
142
|
+
|
|
143
|
+
return lista.map(item => ({
|
|
144
|
+
id: item.id,
|
|
145
|
+
label: item.nome,
|
|
146
|
+
showLabel: false,
|
|
147
|
+
getHtml: async () => {
|
|
148
|
+
const result = await buscarConteudo(item.id);
|
|
149
|
+
return result.html;
|
|
150
|
+
}
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
136
154
|
|
|
137
155
|
})
|
|
138
156
|
|
|
157
|
+
async function buscarLista() {
|
|
158
|
+
// Simula uma chamada AJAX para buscar a lista de documentos
|
|
159
|
+
return new Promise(resolve => {
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
resolve([
|
|
162
|
+
{ id: 1, nome: 'Documento A' },
|
|
163
|
+
{ id: 2, nome: 'Documento B' },
|
|
164
|
+
{ id: 3, nome: 'Documento C' }
|
|
165
|
+
]);
|
|
166
|
+
}, 1500);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function buscarConteudo(id) {
|
|
171
|
+
// Simula uma chamada AJAX para buscar o conteúdo do documento selecionado
|
|
172
|
+
return new Promise(resolve => {
|
|
173
|
+
setTimeout(() => {
|
|
174
|
+
resolve({
|
|
175
|
+
html: `<p>Conteúdo do Documento ${id}</p>`
|
|
176
|
+
});
|
|
177
|
+
}, 1500);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
139
181
|
let prevState = watchdog.state;
|
|
140
182
|
|
|
141
183
|
watchdog.on( 'stateChange', () => {
|
|
@@ -166,11 +208,24 @@ document.getElementById('get-html').addEventListener('click', () => {
|
|
|
166
208
|
document.getElementById('update-content').addEventListener('click', () => {
|
|
167
209
|
const editor = watchdog.editor;
|
|
168
210
|
const conteudoDinamico = editor.plugins.get('ConteudoDinamicoPlugin');
|
|
169
|
-
conteudoDinamico.updateBySourceId('tabela:produtos', `<table
|
|
211
|
+
conteudoDinamico.updateBySourceId('tabela:produtos', `<table><thead>
|
|
170
212
|
<tr>
|
|
171
213
|
<th>Produto</th>
|
|
172
214
|
<th>Preço</th>
|
|
173
215
|
<th>Quantidade</th>
|
|
174
216
|
</tr>
|
|
217
|
+
</thead>
|
|
218
|
+
<tbody>
|
|
219
|
+
<tr>
|
|
220
|
+
<td>Caneta</td>
|
|
221
|
+
<td>R$ 2,50</td>
|
|
222
|
+
<td>${Math.floor(Math.random() * 100)}</td>
|
|
223
|
+
</tr>
|
|
224
|
+
<tr>
|
|
225
|
+
<td>Caderno</td>
|
|
226
|
+
<td>R$ 15,00</td>
|
|
227
|
+
<td>${Math.floor(Math.random() * 100)}</td>
|
|
228
|
+
</tr>
|
|
229
|
+
</tbody>
|
|
175
230
|
</table>`);
|
|
176
231
|
});
|
package/src/ckeditor.ts
CHANGED
|
@@ -91,6 +91,7 @@ import HeadingUiClassPlugin from './plugins/HeadingUiClassPlugin';
|
|
|
91
91
|
// import NumberedDivList from './plugins/listaNumerada';
|
|
92
92
|
// import NumberedDivListSplit from './plugins/NumberedDivListSplit';
|
|
93
93
|
import ConteudoDinamicoPlugin from './plugins/ConteudoDinamicoPlugin';
|
|
94
|
+
import DocumentosPlugin from './plugins/DocumentosPlugin';
|
|
94
95
|
|
|
95
96
|
import './css/custom.css';
|
|
96
97
|
import './css/sei.css';
|
|
@@ -177,6 +178,7 @@ class Editor extends DecoupledEditor {
|
|
|
177
178
|
SalvarComo,
|
|
178
179
|
HeadingUiClassPlugin,
|
|
179
180
|
ConteudoDinamicoPlugin,
|
|
181
|
+
DocumentosPlugin,
|
|
180
182
|
// NumberedDivList,
|
|
181
183
|
// NumberedDivListSplit
|
|
182
184
|
];
|
|
@@ -258,7 +260,8 @@ class Editor extends DecoupledEditor {
|
|
|
258
260
|
'documentoModelo',
|
|
259
261
|
'salvarcomo',
|
|
260
262
|
// 'numberedDivListSplit'
|
|
261
|
-
'conteudoDinamico'
|
|
263
|
+
'conteudoDinamico',
|
|
264
|
+
'insertDocumento'
|
|
262
265
|
],
|
|
263
266
|
shouldNotGroupWhenFull: true
|
|
264
267
|
},
|
|
@@ -289,7 +292,22 @@ class Editor extends DecoupledEditor {
|
|
|
289
292
|
startIndex: true,
|
|
290
293
|
reversed: true
|
|
291
294
|
}
|
|
292
|
-
}
|
|
295
|
+
},
|
|
296
|
+
inserirDocumento: {
|
|
297
|
+
dropdownLabel: 'Inserir Documento',
|
|
298
|
+
getItems: async () => {
|
|
299
|
+
const lista = await buscarListaDocumentos();
|
|
300
|
+
|
|
301
|
+
return lista.map(doc => ({
|
|
302
|
+
id: doc.id,
|
|
303
|
+
label: doc.nome,
|
|
304
|
+
getHtml: async () => {
|
|
305
|
+
const conteudo = await buscarConteudoDocumento(doc.id);
|
|
306
|
+
return conteudo.html;
|
|
307
|
+
}
|
|
308
|
+
}));
|
|
309
|
+
}
|
|
310
|
+
}
|
|
293
311
|
};
|
|
294
312
|
}
|
|
295
313
|
|
package/src/css/custom.css
CHANGED
|
@@ -78,4 +78,51 @@
|
|
|
78
78
|
.num-list,
|
|
79
79
|
.num-list > .num-li {
|
|
80
80
|
text-indent: 0px !important;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.ck-conteudo-dinamico__loading {
|
|
84
|
+
display: inline-flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
gap: 10px;
|
|
87
|
+
padding: 12px 14px;
|
|
88
|
+
border: 1px solid #dcdcdc;
|
|
89
|
+
border-radius: 6px;
|
|
90
|
+
background: #fafafa;
|
|
91
|
+
color: #555;
|
|
92
|
+
min-height: 44px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.ck-conteudo-dinamico__dots {
|
|
96
|
+
display: inline-flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
gap: 4px;
|
|
99
|
+
height: 16px;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.ck-conteudo-dinamico__dots span {
|
|
103
|
+
width: 6px;
|
|
104
|
+
height: 6px;
|
|
105
|
+
border-radius: 50%;
|
|
106
|
+
background: #666;
|
|
107
|
+
display: inline-block;
|
|
108
|
+
animation: ck-dots-swing 1s infinite ease-in-out;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.ck-conteudo-dinamico__dots span:nth-child(2) {
|
|
112
|
+
animation-delay: 0.15s;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.ck-conteudo-dinamico__dots span:nth-child(3) {
|
|
116
|
+
animation-delay: 0.3s;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@keyframes ck-dots-swing {
|
|
120
|
+
0%, 80%, 100% {
|
|
121
|
+
transform: translateY(0);
|
|
122
|
+
opacity: 0.45;
|
|
123
|
+
}
|
|
124
|
+
40% {
|
|
125
|
+
transform: translateY(-4px);
|
|
126
|
+
opacity: 1;
|
|
127
|
+
}
|
|
81
128
|
}
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
|
|
3
|
+
import Command from '@ckeditor/ckeditor5-core/src/command';
|
|
4
|
+
|
|
5
|
+
import Widget from '@ckeditor/ckeditor5-widget/src/widget';
|
|
6
|
+
import { toWidget, viewToModelPositionOutsideModelElement } from '@ckeditor/ckeditor5-widget/src/utils';
|
|
7
|
+
|
|
8
|
+
import Collection from '@ckeditor/ckeditor5-utils/src/collection';
|
|
9
|
+
import Model from '@ckeditor/ckeditor5-ui/src/model';
|
|
10
|
+
import { createDropdown, addListToDropdown } from '@ckeditor/ckeditor5-ui/src/dropdown/utils';
|
|
11
|
+
|
|
12
|
+
export default class DocumentosPlugin extends Plugin {
|
|
13
|
+
static get pluginName() {
|
|
14
|
+
return 'DocumentosPlugin';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static get requires() {
|
|
18
|
+
return [ Widget ];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async init() {
|
|
22
|
+
const editor = this.editor;
|
|
23
|
+
|
|
24
|
+
this._lastHtmlBySourceId = new Map();
|
|
25
|
+
this._pendingUpdates = new Set();
|
|
26
|
+
this._itemsBySourceId = new Map();
|
|
27
|
+
this._getHtmlBySourceId = new Map();
|
|
28
|
+
|
|
29
|
+
const cfg = editor.config.get('inserirDocumento') || {};
|
|
30
|
+
const dropdownLabel = cfg.dropdownLabel || 'Inserir Documento';
|
|
31
|
+
const loadingLabel = cfg.loadingLabel || 'Carregando...';
|
|
32
|
+
const getItems = typeof cfg.getItems === 'function' ? cfg.getItems : null;
|
|
33
|
+
|
|
34
|
+
editor.model.schema.register('inserirDocumento', {
|
|
35
|
+
isObject: true,
|
|
36
|
+
isBlock: true,
|
|
37
|
+
allowWhere: '$block',
|
|
38
|
+
allowAttributes: [ 'sourceId', 'htmlB64' ]
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
editor.editing.mapper.on(
|
|
42
|
+
'viewToModelPosition',
|
|
43
|
+
viewToModelPositionOutsideModelElement(
|
|
44
|
+
editor.model,
|
|
45
|
+
viewElement => viewElement.hasClass('ck-conteudo-dinamico')
|
|
46
|
+
)
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
editor.conversion.for('upcast').elementToElement({
|
|
50
|
+
view: {
|
|
51
|
+
name: 'div',
|
|
52
|
+
attributes: { 'data-conteudo-dinamico': '1' }
|
|
53
|
+
},
|
|
54
|
+
model: (viewElement, { writer }) => {
|
|
55
|
+
const sourceId = viewElement.getAttribute('data-source-id') || '';
|
|
56
|
+
const htmlB64 = viewElement.getAttribute('data-html') || '';
|
|
57
|
+
|
|
58
|
+
return writer.createElement('inserirDocumento', { sourceId, htmlB64 });
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
editor.conversion.for('dataDowncast').elementToElement({
|
|
63
|
+
model: 'inserirDocumento',
|
|
64
|
+
view: (modelItem, { writer }) => {
|
|
65
|
+
const sourceId = modelItem.getAttribute('sourceId') || '';
|
|
66
|
+
const htmlB64 = modelItem.getAttribute('htmlB64') || '';
|
|
67
|
+
const html = decodeHtml(htmlB64) || defaultHtml();
|
|
68
|
+
|
|
69
|
+
return writer.createRawElement(
|
|
70
|
+
'div',
|
|
71
|
+
{
|
|
72
|
+
class: 'ck-conteudo-dinamico',
|
|
73
|
+
'data-conteudo-dinamico': '1',
|
|
74
|
+
'data-source-id': sourceId,
|
|
75
|
+
'data-html': htmlB64
|
|
76
|
+
},
|
|
77
|
+
domElement => {
|
|
78
|
+
domElement.innerHTML = html;
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
editor.conversion.for('editingDowncast').elementToElement({
|
|
85
|
+
model: 'inserirDocumento',
|
|
86
|
+
view: (modelItem, { writer }) => {
|
|
87
|
+
const sourceId = modelItem.getAttribute('sourceId') || '';
|
|
88
|
+
const htmlB64 = modelItem.getAttribute('htmlB64') || '';
|
|
89
|
+
const html = decodeHtml(htmlB64) || defaultHtml();
|
|
90
|
+
|
|
91
|
+
const meta = this._itemsBySourceId.get(sourceId);
|
|
92
|
+
const widgetLabel = meta?.label || sourceId || 'Conteúdo dinâmico';
|
|
93
|
+
|
|
94
|
+
const container = writer.createContainerElement('div', {
|
|
95
|
+
class: 'ck-conteudo-dinamico',
|
|
96
|
+
'data-conteudo-dinamico': '1',
|
|
97
|
+
'data-source-id': sourceId
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (meta?.showLabel !== false) {
|
|
101
|
+
const header = writer.createContainerElement('div', {
|
|
102
|
+
class: 'ck-conteudo-dinamico__header'
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (meta?.iconSvg) {
|
|
106
|
+
const icon = writer.createRawElement(
|
|
107
|
+
'span',
|
|
108
|
+
{ class: 'ck-conteudo-dinamico__icon' },
|
|
109
|
+
domEl => {
|
|
110
|
+
domEl.innerHTML = meta.iconSvg;
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
writer.insert(writer.createPositionAt(header, 'end'), icon);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (meta?.label) {
|
|
117
|
+
const title = writer.createContainerElement('span', {
|
|
118
|
+
class: 'ck-conteudo-dinamico__title'
|
|
119
|
+
});
|
|
120
|
+
writer.insert(writer.createPositionAt(title, 0), writer.createText(meta.label));
|
|
121
|
+
writer.insert(writer.createPositionAt(header, 'end'), title);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
writer.insert(writer.createPositionAt(container, 'end'), header);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const raw = writer.createRawElement(
|
|
128
|
+
'div',
|
|
129
|
+
{ class: 'ck-conteudo-dinamico__inner' },
|
|
130
|
+
domElement => {
|
|
131
|
+
domElement.innerHTML = html;
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
writer.insert(writer.createPositionAt(container, 'end'), raw);
|
|
136
|
+
|
|
137
|
+
return toWidget(container, writer, { label: widgetLabel });
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
editor.commands.add('insertInserirDocumento', new InsertInserirDocumentoCommand(editor));
|
|
142
|
+
|
|
143
|
+
editor.model.document.on('change:data', () => {
|
|
144
|
+
if (!this._lastHtmlBySourceId.size) return;
|
|
145
|
+
|
|
146
|
+
for (const [ sourceId ] of this._lastHtmlBySourceId.entries()) {
|
|
147
|
+
this._pendingUpdates.add(sourceId);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
flushPendingUpdates(editor, this);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
let initialItems = [];
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
if (getItems) {
|
|
157
|
+
const result = await getItems();
|
|
158
|
+
initialItems = Array.isArray(result) ? result : [];
|
|
159
|
+
}
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error('Erro ao carregar lista de documentos na inicialização', error);
|
|
162
|
+
initialItems = [];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (const item of initialItems) {
|
|
166
|
+
if (!item?.id) continue;
|
|
167
|
+
|
|
168
|
+
const sourceId = String(item.id);
|
|
169
|
+
|
|
170
|
+
this._itemsBySourceId.set(sourceId, {
|
|
171
|
+
sourceId,
|
|
172
|
+
label: item.label || sourceId,
|
|
173
|
+
iconSvg: item.iconSvg,
|
|
174
|
+
showLabel: item.showLabel
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (typeof item.getHtml === 'function') {
|
|
178
|
+
this._getHtmlBySourceId.set(sourceId, item.getHtml);
|
|
179
|
+
} else if (typeof item.html === 'string') {
|
|
180
|
+
this._getHtmlBySourceId.set(sourceId, async () => item.html);
|
|
181
|
+
} else if (typeof item.text === 'string') {
|
|
182
|
+
this._getHtmlBySourceId.set(sourceId, async () => `<p>${escapeHtml(item.text)}</p>`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
editor.ui.componentFactory.add('insertDocumento', locale => {
|
|
187
|
+
const dropdown = createDropdown(locale);
|
|
188
|
+
|
|
189
|
+
dropdown.buttonView.set({
|
|
190
|
+
label: dropdownLabel,
|
|
191
|
+
tooltip: true,
|
|
192
|
+
withText: true,
|
|
193
|
+
isVisible: initialItems.length > 0
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const listItems = new Collection();
|
|
197
|
+
addListToDropdown(dropdown, listItems);
|
|
198
|
+
|
|
199
|
+
for (const item of initialItems) {
|
|
200
|
+
if (!item?.id) continue;
|
|
201
|
+
|
|
202
|
+
const sourceId = String(item.id);
|
|
203
|
+
|
|
204
|
+
listItems.add({
|
|
205
|
+
type: 'button',
|
|
206
|
+
model: new Model({
|
|
207
|
+
label: item.label || sourceId,
|
|
208
|
+
withText: true,
|
|
209
|
+
documentItemId: sourceId
|
|
210
|
+
})
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
dropdown.on('execute', async evt => {
|
|
215
|
+
const baseSourceId = evt.source.documentItemId;
|
|
216
|
+
|
|
217
|
+
if (!baseSourceId) return;
|
|
218
|
+
|
|
219
|
+
const getHtmlFn = this._getHtmlBySourceId.get(baseSourceId);
|
|
220
|
+
if (!getHtmlFn) return;
|
|
221
|
+
|
|
222
|
+
const sourceId = createInstanceSourceId(baseSourceId);
|
|
223
|
+
const meta = this._itemsBySourceId.get(baseSourceId);
|
|
224
|
+
|
|
225
|
+
if (meta) {
|
|
226
|
+
this._itemsBySourceId.set(sourceId, {
|
|
227
|
+
...meta,
|
|
228
|
+
sourceId
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
editor.execute('insertInserirDocumento', {
|
|
234
|
+
sourceId,
|
|
235
|
+
html: loadingDotsHtml('Aguarde...')
|
|
236
|
+
});
|
|
237
|
+
editor.editing.view.focus();
|
|
238
|
+
|
|
239
|
+
const html = await getHtmlFn();
|
|
240
|
+
|
|
241
|
+
this.updateBySourceId(sourceId, html);
|
|
242
|
+
} catch (error) {
|
|
243
|
+
console.error('Erro ao carregar conteúdo do documento', error);
|
|
244
|
+
|
|
245
|
+
this.updateBySourceId(
|
|
246
|
+
sourceId,
|
|
247
|
+
`
|
|
248
|
+
<div class="ck-conteudo-dinamico__error" contenteditable="false">
|
|
249
|
+
Não foi possível carregar o conteúdo.
|
|
250
|
+
</div>
|
|
251
|
+
`
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
return dropdown;
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
this.updateBySourceId = (sourceId, html) => {
|
|
260
|
+
this._lastHtmlBySourceId.set(sourceId, html);
|
|
261
|
+
this._pendingUpdates.add(sourceId);
|
|
262
|
+
flushPendingUpdates(editor, this);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
function flushPendingUpdates(editor, plugin) {
|
|
266
|
+
if (!plugin._pendingUpdates.size) return;
|
|
267
|
+
|
|
268
|
+
const ids = Array.from(plugin._pendingUpdates);
|
|
269
|
+
plugin._pendingUpdates.clear();
|
|
270
|
+
|
|
271
|
+
for (const sourceId of ids) {
|
|
272
|
+
const html = plugin._lastHtmlBySourceId.get(sourceId);
|
|
273
|
+
if (html == null) continue;
|
|
274
|
+
updateConteudo(editor, sourceId, html);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
class InsertInserirDocumentoCommand extends Command {
|
|
281
|
+
execute({ sourceId, html }) {
|
|
282
|
+
const editor = this.editor;
|
|
283
|
+
const htmlB64 = encodeHtml(html);
|
|
284
|
+
|
|
285
|
+
editor.model.change(writer => {
|
|
286
|
+
const element = writer.createElement('inserirDocumento', {
|
|
287
|
+
sourceId,
|
|
288
|
+
htmlB64
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
editor.model.insertContent(element);
|
|
292
|
+
writer.setSelection(element, 'on');
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
refresh() {
|
|
297
|
+
const model = this.editor.model;
|
|
298
|
+
const selection = model.document.selection;
|
|
299
|
+
const allowedIn = model.schema.findAllowedParent(
|
|
300
|
+
selection.getFirstPosition(),
|
|
301
|
+
'inserirDocumento'
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
this.isEnabled = !!allowedIn;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function updateConteudo(editor, sourceId, html) {
|
|
309
|
+
const newHtmlB64 = encodeHtml(html);
|
|
310
|
+
|
|
311
|
+
editor.model.change(writer => {
|
|
312
|
+
const root = editor.model.document.getRoot();
|
|
313
|
+
|
|
314
|
+
const targets = [];
|
|
315
|
+
for (const item of editor.model.createRangeIn(root).getItems()) {
|
|
316
|
+
if (
|
|
317
|
+
item.is('element', 'inserirDocumento') &&
|
|
318
|
+
item.getAttribute('sourceId') === sourceId
|
|
319
|
+
) {
|
|
320
|
+
targets.push(item);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
for (const item of targets) {
|
|
325
|
+
const currentB64 = item.getAttribute('htmlB64') || '';
|
|
326
|
+
if (currentB64 === newHtmlB64) continue;
|
|
327
|
+
|
|
328
|
+
const wasSelected = editor.model.document.selection.getSelectedElement() === item;
|
|
329
|
+
const insertPos = writer.createPositionBefore(item);
|
|
330
|
+
|
|
331
|
+
const attrs = Object.fromEntries(item.getAttributes());
|
|
332
|
+
attrs.htmlB64 = newHtmlB64;
|
|
333
|
+
|
|
334
|
+
writer.remove(item);
|
|
335
|
+
|
|
336
|
+
const newElement = writer.createElement('inserirDocumento', attrs);
|
|
337
|
+
writer.insert(newElement, insertPos);
|
|
338
|
+
|
|
339
|
+
if (wasSelected) {
|
|
340
|
+
writer.setSelection(newElement, 'on');
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function defaultHtml() {
|
|
347
|
+
return '';
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function encodeHtml(str) {
|
|
351
|
+
try {
|
|
352
|
+
return btoa(unescape(encodeURIComponent(str)));
|
|
353
|
+
} catch {
|
|
354
|
+
return '';
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function decodeHtml(b64) {
|
|
359
|
+
if (!b64) return '';
|
|
360
|
+
try {
|
|
361
|
+
return decodeURIComponent(escape(atob(b64)));
|
|
362
|
+
} catch {
|
|
363
|
+
return '';
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function escapeHtml(str = '') {
|
|
368
|
+
return String(str)
|
|
369
|
+
.replaceAll('&', '&')
|
|
370
|
+
.replaceAll('<', '<')
|
|
371
|
+
.replaceAll('>', '>')
|
|
372
|
+
.replaceAll('"', '"')
|
|
373
|
+
.replaceAll("'", ''');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function loadingDotsHtml(label = '') {
|
|
377
|
+
return `
|
|
378
|
+
<div class="ck-conteudo-dinamico__loading" contenteditable="false">
|
|
379
|
+
<span class="ck-conteudo-dinamico__dots" aria-hidden="true">
|
|
380
|
+
<span></span><span></span><span></span>
|
|
381
|
+
</span>
|
|
382
|
+
<span class="ck-conteudo-dinamico__loading-text">${escapeHtml(label)}</span>
|
|
383
|
+
</div>
|
|
384
|
+
`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function createInstanceSourceId(baseId) {
|
|
388
|
+
return `${baseId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`;
|
|
389
|
+
}
|