@rg-dev/tinymce-helpers 1.0.11 → 1.0.12
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/index.d.mts +65 -5
- package/index.mjs +156 -9
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { Editor, RawEditorOptions } from 'tinymce';
|
|
2
2
|
|
|
3
|
+
type RemoveIndexSignature<T> = {
|
|
4
|
+
[K in keyof T as
|
|
5
|
+
string extends K ? never :
|
|
6
|
+
number extends K ? never :
|
|
7
|
+
symbol extends K ? never :
|
|
8
|
+
K
|
|
9
|
+
]: T[K]
|
|
10
|
+
};
|
|
11
|
+
|
|
3
12
|
declare const skinsTable: {
|
|
4
13
|
dark: () => Promise<{
|
|
5
14
|
css: string;
|
|
@@ -10,20 +19,71 @@ declare const skinsTable: {
|
|
|
10
19
|
skin: string;
|
|
11
20
|
}>;
|
|
12
21
|
};
|
|
13
|
-
type RemoveIndexSignature<T> = {
|
|
14
|
-
[K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
|
|
15
|
-
};
|
|
16
22
|
type RawEditorOptionsExtended = RawEditorOptions & {
|
|
17
23
|
quickbars_insert_toolbar?: string;
|
|
18
24
|
quickbars_selection_toolbar?: string;
|
|
25
|
+
image_advtab: boolean;
|
|
19
26
|
};
|
|
27
|
+
type EditorOpts = Omit<RemoveIndexSignature<RawEditorOptionsExtended>, 'setup' | 'target' | 'selector'> & Record<string, unknown>;
|
|
28
|
+
/** A partial patch object, or a function that derives one from the defaults. */
|
|
29
|
+
type TinyMCEPatch = Partial<EditorOpts> | ((defaults: EditorOpts) => Partial<EditorOpts>);
|
|
30
|
+
declare class ListBuilder {
|
|
31
|
+
private items;
|
|
32
|
+
constructor(existing: string);
|
|
33
|
+
/** add('btn') appends at the end. add(3, 'btn') inserts at index 3. */
|
|
34
|
+
add(indexOrItem: number | string, item?: string): this;
|
|
35
|
+
start(item: string): this;
|
|
36
|
+
after(target: string, item: string): this;
|
|
37
|
+
before(target: string, item: string): this;
|
|
38
|
+
remove(...names: string[]): this;
|
|
39
|
+
/** Insert a '|' separator at the end, or at a given index. */
|
|
40
|
+
separator(index?: number): this;
|
|
41
|
+
toString(): string;
|
|
42
|
+
}
|
|
43
|
+
type ListPatch = string | ((t: ListBuilder) => ListBuilder | void);
|
|
44
|
+
type MenuEntry = {
|
|
45
|
+
title: string;
|
|
46
|
+
items: string;
|
|
47
|
+
};
|
|
48
|
+
type MenuConfig = Record<string, MenuEntry>;
|
|
49
|
+
declare class MenuBuilder {
|
|
50
|
+
private menus;
|
|
51
|
+
constructor(existing: MenuConfig);
|
|
52
|
+
/** Add or replace an entire menu, e.g. m.addMenu('others_menu', { title: 'Others', items: 'foo bar' }) */
|
|
53
|
+
addMenu(key: string, config: MenuEntry): this;
|
|
54
|
+
removeMenu(key: string): this;
|
|
55
|
+
/** Mutate one menu's items string via the same ListBuilder used for toolbar/contextmenu. */
|
|
56
|
+
items(key: string, patch: ListPatch): this;
|
|
57
|
+
/** Shorthand: m.addItem('file', 'newitem') / m.addItem('file', 2, 'newitem') */
|
|
58
|
+
addItem(key: string, indexOrItem: number | string, item?: string): this;
|
|
59
|
+
removeItem(key: string, ...names: string[]): this;
|
|
60
|
+
toObject(): MenuConfig;
|
|
61
|
+
}
|
|
62
|
+
type MenuPatch = MenuConfig | ((m: MenuBuilder) => MenuBuilder | void);
|
|
20
63
|
type MyTinymceOpts = {
|
|
21
64
|
skin?: keyof typeof skinsTable;
|
|
22
65
|
direction?: 'rtl' | 'ltr';
|
|
23
66
|
customSetup?: (editor: Editor) => void;
|
|
24
|
-
|
|
67
|
+
/** Free-form deep-merge patch applied over the default options.
|
|
68
|
+
* Accepts a plain partial object, or a function of the defaults
|
|
69
|
+
* that returns a partial object. */
|
|
70
|
+
overrides?: TinyMCEPatch;
|
|
71
|
+
/** Toolbar string, or a builder function: (t) => t.add('btn'), t.after('x','y'), etc. */
|
|
72
|
+
toolbar?: ListPatch;
|
|
73
|
+
/** Context menu string, or a builder function, same API as toolbar. */
|
|
74
|
+
contextmenu?: ListPatch;
|
|
75
|
+
/** Plugin list string, or a builder function, same API as toolbar.
|
|
76
|
+
* Note: this only toggles the string passed to tinymce.init - the
|
|
77
|
+
* underlying plugin JS still needs to be imported at the top of this
|
|
78
|
+
* file regardless of what's listed here. */
|
|
79
|
+
plugins?: ListPatch;
|
|
80
|
+
/** Menubar string (top-level menu keys, e.g. 'file edit view'), or a
|
|
81
|
+
* builder function, same API as toolbar. */
|
|
82
|
+
menubar?: ListPatch;
|
|
83
|
+
/** Menu config object ({ key: { title, items } }), or a builder
|
|
84
|
+
* function: (m) => m.addItem('file','newitem').removeItem('file','print') */
|
|
85
|
+
menu?: MenuPatch;
|
|
25
86
|
};
|
|
26
|
-
type EditorOpts = Omit<RemoveIndexSignature<RawEditorOptionsExtended>, 'setup' | 'target' | 'selector'> & Record<string, unknown>;
|
|
27
87
|
declare class tinymceHelpers {
|
|
28
88
|
private _editor;
|
|
29
89
|
private _lockButton?;
|
package/index.mjs
CHANGED
|
@@ -14,6 +14,18 @@ var __spreadValues = (a, b) => {
|
|
|
14
14
|
}
|
|
15
15
|
return a;
|
|
16
16
|
};
|
|
17
|
+
var __objRest = (source, exclude) => {
|
|
18
|
+
var target = {};
|
|
19
|
+
for (var prop in source)
|
|
20
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
21
|
+
target[prop] = source[prop];
|
|
22
|
+
if (source != null && __getOwnPropSymbols)
|
|
23
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
24
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
25
|
+
target[prop] = source[prop];
|
|
26
|
+
}
|
|
27
|
+
return target;
|
|
28
|
+
};
|
|
17
29
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
18
30
|
|
|
19
31
|
// src/client/custom-components/tinymce-helpers.ts
|
|
@@ -65,9 +77,9 @@ async function defaultSkin(document2 = false) {
|
|
|
65
77
|
]);
|
|
66
78
|
return {
|
|
67
79
|
css: tinymce.Resource.get(`content/${contentSkin}/content.css`) + tinymce.Resource.get(`ui/${shellSkin}/content.css`) + `
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
71
83
|
`,
|
|
72
84
|
skin: shellSkin
|
|
73
85
|
};
|
|
@@ -84,7 +96,6 @@ async function darkSkin() {
|
|
|
84
96
|
);
|
|
85
97
|
return {
|
|
86
98
|
css: tinymce.Resource.get(`content/${contentSkin}/content.css`) + tinymce.Resource.get(`ui/${shellSkin}/content.css`) + `
|
|
87
|
-
|
|
88
99
|
|
|
89
100
|
|
|
90
101
|
.mce-content-body {
|
|
@@ -105,6 +116,126 @@ var skinsTable = {
|
|
|
105
116
|
dark: () => darkSkin(),
|
|
106
117
|
default: () => defaultSkin()
|
|
107
118
|
};
|
|
119
|
+
function resolvePatch(defaults, patch) {
|
|
120
|
+
if (!patch) return {};
|
|
121
|
+
const resolved = typeof patch === "function" ? patch(defaults) : patch;
|
|
122
|
+
const _a = resolved, { target, setup, selector } = _a, safe = __objRest(_a, ["target", "setup", "selector"]);
|
|
123
|
+
return safe;
|
|
124
|
+
}
|
|
125
|
+
function deepMerge(base, patch) {
|
|
126
|
+
const out = __spreadValues({}, base);
|
|
127
|
+
for (const key in patch) {
|
|
128
|
+
const value = patch[key];
|
|
129
|
+
const baseValue = base[key];
|
|
130
|
+
const isPlainObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
131
|
+
if (isPlainObject(value) && isPlainObject(baseValue)) {
|
|
132
|
+
out[key] = deepMerge(baseValue, value);
|
|
133
|
+
} else {
|
|
134
|
+
out[key] = value;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
var ListBuilder = class {
|
|
140
|
+
constructor(existing) {
|
|
141
|
+
__publicField(this, "items");
|
|
142
|
+
this.items = existing.trim().length ? existing.trim().split(/\s+/) : [];
|
|
143
|
+
}
|
|
144
|
+
/** add('btn') appends at the end. add(3, 'btn') inserts at index 3. */
|
|
145
|
+
add(indexOrItem, item) {
|
|
146
|
+
if (typeof indexOrItem === "number") {
|
|
147
|
+
this.items.splice(indexOrItem, 0, item);
|
|
148
|
+
} else {
|
|
149
|
+
this.items.push(indexOrItem);
|
|
150
|
+
}
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
start(item) {
|
|
154
|
+
this.items.unshift(item);
|
|
155
|
+
return this;
|
|
156
|
+
}
|
|
157
|
+
after(target, item) {
|
|
158
|
+
const i = this.items.indexOf(target);
|
|
159
|
+
this.items.splice(i === -1 ? this.items.length : i + 1, 0, item);
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
before(target, item) {
|
|
163
|
+
const i = this.items.indexOf(target);
|
|
164
|
+
this.items.splice(i === -1 ? this.items.length : i, 0, item);
|
|
165
|
+
return this;
|
|
166
|
+
}
|
|
167
|
+
remove(...names) {
|
|
168
|
+
const removeSet = new Set(names.map((n) => n.toLowerCase()));
|
|
169
|
+
this.items = this.items.filter((i) => i === "|" || !removeSet.has(i.toLowerCase()));
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
/** Insert a '|' separator at the end, or at a given index. */
|
|
173
|
+
separator(index) {
|
|
174
|
+
if (index === void 0) {
|
|
175
|
+
this.items.push("|");
|
|
176
|
+
} else {
|
|
177
|
+
this.items.splice(index, 0, "|");
|
|
178
|
+
}
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
toString() {
|
|
182
|
+
return this.items.join(" ");
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
function applyListPatch(existing, patch) {
|
|
186
|
+
if (!patch) return existing;
|
|
187
|
+
if (typeof patch === "string") return patch;
|
|
188
|
+
const builder = new ListBuilder(existing);
|
|
189
|
+
const result = patch(builder);
|
|
190
|
+
return (result != null ? result : builder).toString();
|
|
191
|
+
}
|
|
192
|
+
var MenuBuilder = class {
|
|
193
|
+
constructor(existing) {
|
|
194
|
+
__publicField(this, "menus");
|
|
195
|
+
this.menus = Object.fromEntries(
|
|
196
|
+
Object.entries(existing).map(([k, v]) => [k, __spreadValues({}, v)])
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
/** Add or replace an entire menu, e.g. m.addMenu('others_menu', { title: 'Others', items: 'foo bar' }) */
|
|
200
|
+
addMenu(key, config) {
|
|
201
|
+
this.menus[key] = __spreadValues({}, config);
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
removeMenu(key) {
|
|
205
|
+
delete this.menus[key];
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
/** Mutate one menu's items string via the same ListBuilder used for toolbar/contextmenu. */
|
|
209
|
+
items(key, patch) {
|
|
210
|
+
const existing = this.menus[key];
|
|
211
|
+
if (!existing) {
|
|
212
|
+
console.error(`MenuBuilder.items: menu "${key}" does not exist`);
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
existing.items = applyListPatch(existing.items, patch);
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
/** Shorthand: m.addItem('file', 'newitem') / m.addItem('file', 2, 'newitem') */
|
|
219
|
+
addItem(key, indexOrItem, item) {
|
|
220
|
+
return this.items(
|
|
221
|
+
key,
|
|
222
|
+
(t) => typeof indexOrItem === "number" ? t.add(indexOrItem, item) : t.add(indexOrItem)
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
removeItem(key, ...names) {
|
|
226
|
+
return this.items(key, (t) => t.remove(...names));
|
|
227
|
+
}
|
|
228
|
+
toObject() {
|
|
229
|
+
return this.menus;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
function applyMenuPatch(existing, patch) {
|
|
233
|
+
if (!patch) return existing;
|
|
234
|
+
if (typeof patch !== "function") return patch;
|
|
235
|
+
const builder = new MenuBuilder(existing);
|
|
236
|
+
const result = patch(builder);
|
|
237
|
+
return (result != null ? result : builder).toObject();
|
|
238
|
+
}
|
|
108
239
|
var tinymceHelpers = class _tinymceHelpers {
|
|
109
240
|
constructor() {
|
|
110
241
|
__publicField(this, "_editor");
|
|
@@ -118,7 +249,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
118
249
|
this.editor.insertContent(`<img src="${src}" alt="">`);
|
|
119
250
|
}
|
|
120
251
|
async _initMce(el, customOpts = Object()) {
|
|
121
|
-
var _a
|
|
252
|
+
var _a;
|
|
122
253
|
if (!(el instanceof HTMLElement)) {
|
|
123
254
|
throw new Error("invalid element");
|
|
124
255
|
}
|
|
@@ -293,7 +424,9 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
293
424
|
() => {
|
|
294
425
|
if (blockquote) {
|
|
295
426
|
const parent = blockquote.parentNode;
|
|
296
|
-
if (!parent)
|
|
427
|
+
if (!parent) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
297
430
|
while (blockquote.firstChild) {
|
|
298
431
|
parent.insertBefore(blockquote.firstChild, blockquote);
|
|
299
432
|
}
|
|
@@ -378,14 +511,28 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
378
511
|
// contextmenu: false,
|
|
379
512
|
contextmenu: "insert-image link image table create-block-above create-block-below reset-style-button-img clearTextStyle"
|
|
380
513
|
};
|
|
381
|
-
opts =
|
|
514
|
+
opts = deepMerge(opts, resolvePatch(opts, customOpts.overrides));
|
|
515
|
+
if (typeof opts.toolbar === "string") {
|
|
516
|
+
opts.toolbar = applyListPatch(opts.toolbar, customOpts.toolbar);
|
|
517
|
+
}
|
|
518
|
+
if (typeof opts.contextmenu === "string") {
|
|
519
|
+
opts.contextmenu = applyListPatch(opts.contextmenu, customOpts.contextmenu);
|
|
520
|
+
}
|
|
521
|
+
if (typeof opts.plugins === "string") {
|
|
522
|
+
opts.plugins = applyListPatch(opts.plugins, customOpts.plugins);
|
|
523
|
+
}
|
|
524
|
+
if (typeof opts.menubar === "string") {
|
|
525
|
+
opts.menubar = applyListPatch(opts.menubar, customOpts.menubar);
|
|
526
|
+
}
|
|
527
|
+
if (opts.menu) {
|
|
528
|
+
opts.menu = applyMenuPatch(opts.menu, customOpts.menu);
|
|
529
|
+
}
|
|
382
530
|
if (!opts.skin) {
|
|
383
531
|
throw new Error("no skin");
|
|
384
532
|
}
|
|
385
533
|
const mce = this._editor = await tinymce.init(opts).then((x) => x[0]);
|
|
386
534
|
this.originalContextMenu = mce.options.get("contextmenu");
|
|
387
535
|
const all = mce.ui.registry.getAll();
|
|
388
|
-
console.log(all);
|
|
389
536
|
const availableMenuItems = all.menuItems;
|
|
390
537
|
const availableButtons = all.buttons;
|
|
391
538
|
if (typeof opts.toolbar == "string") {
|
|
@@ -418,7 +565,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
418
565
|
}
|
|
419
566
|
if (opts.menu) {
|
|
420
567
|
for (const [key, value] of Object.entries(opts.menu)) {
|
|
421
|
-
if (!isNonEmptyString((
|
|
568
|
+
if (!isNonEmptyString((_a = value.items) == null ? void 0 : _a.trim())) {
|
|
422
569
|
console.error(`Menu "${key}" is missing items`);
|
|
423
570
|
continue;
|
|
424
571
|
}
|