@rg-dev/tinymce-helpers 1.0.12 → 1.0.13
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 +16 -11
- package/index.mjs +197 -231
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -15,7 +15,7 @@ declare const skinsTable: {
|
|
|
15
15
|
skin: string;
|
|
16
16
|
}>;
|
|
17
17
|
default: () => Promise<{
|
|
18
|
-
css:
|
|
18
|
+
css: any;
|
|
19
19
|
skin: string;
|
|
20
20
|
}>;
|
|
21
21
|
};
|
|
@@ -26,10 +26,12 @@ type RawEditorOptionsExtended = RawEditorOptions & {
|
|
|
26
26
|
};
|
|
27
27
|
type EditorOpts = Omit<RemoveIndexSignature<RawEditorOptionsExtended>, 'setup' | 'target' | 'selector'> & Record<string, unknown>;
|
|
28
28
|
/** A partial patch object, or a function that derives one from the defaults. */
|
|
29
|
-
type TinyMCEPatch = Partial<EditorOpts> | ((defaults: EditorOpts) => Partial<EditorOpts>);
|
|
29
|
+
type TinyMCEPatch = Partial<EditorOpts> | ((defaults: EditorOpts) => Partial<EditorOpts> | void);
|
|
30
30
|
declare class ListBuilder {
|
|
31
31
|
private items;
|
|
32
32
|
constructor(existing: string);
|
|
33
|
+
/** Remove everything. */
|
|
34
|
+
clear(): this;
|
|
33
35
|
/** add('btn') appends at the end. add(3, 'btn') inserts at index 3. */
|
|
34
36
|
add(indexOrItem: number | string, item?: string): this;
|
|
35
37
|
start(item: string): this;
|
|
@@ -38,6 +40,7 @@ declare class ListBuilder {
|
|
|
38
40
|
remove(...names: string[]): this;
|
|
39
41
|
/** Insert a '|' separator at the end, or at a given index. */
|
|
40
42
|
separator(index?: number): this;
|
|
43
|
+
/** Collapses duplicate / leading / trailing separators left behind by remove(). */
|
|
41
44
|
toString(): string;
|
|
42
45
|
}
|
|
43
46
|
type ListPatch = string | ((t: ListBuilder) => ListBuilder | void);
|
|
@@ -49,14 +52,16 @@ type MenuConfig = Record<string, MenuEntry>;
|
|
|
49
52
|
declare class MenuBuilder {
|
|
50
53
|
private menus;
|
|
51
54
|
constructor(existing: MenuConfig);
|
|
55
|
+
/** Remove every menu. */
|
|
56
|
+
clear(): this;
|
|
52
57
|
/** Add or replace an entire menu, e.g. m.addMenu('others_menu', { title: 'Others', items: 'foo bar' }) */
|
|
53
58
|
addMenu(key: string, config: MenuEntry): this;
|
|
54
59
|
removeMenu(key: string): this;
|
|
55
|
-
/**
|
|
60
|
+
/** Edit one menu's items with the same builder API as toolbar/contextmenu. */
|
|
56
61
|
items(key: string, patch: ListPatch): this;
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
/** Remove items from one menu, or from every menu if `key` is omitted. */
|
|
63
|
+
removeItem(names: string | string[], key?: string): this;
|
|
64
|
+
/** Empty menus are dropped so TinyMCE never sees a menu with no items. */
|
|
60
65
|
toObject(): MenuConfig;
|
|
61
66
|
}
|
|
62
67
|
type MenuPatch = MenuConfig | ((m: MenuBuilder) => MenuBuilder | void);
|
|
@@ -64,24 +69,24 @@ type MyTinymceOpts = {
|
|
|
64
69
|
skin?: keyof typeof skinsTable;
|
|
65
70
|
direction?: 'rtl' | 'ltr';
|
|
66
71
|
customSetup?: (editor: Editor) => void;
|
|
67
|
-
/**
|
|
72
|
+
/** Shallow patch applied over the default options (top-level keys are replaced).
|
|
68
73
|
* Accepts a plain partial object, or a function of the defaults
|
|
69
74
|
* that returns a partial object. */
|
|
70
75
|
overrides?: TinyMCEPatch;
|
|
71
|
-
/** Toolbar string, or a builder function: (t) => t.add('btn'), t.after('x','y'), etc. */
|
|
76
|
+
/** Toolbar string, or a builder function: (t) => t.add('btn'), t.after('x','y'), t.clear(), etc. */
|
|
72
77
|
toolbar?: ListPatch;
|
|
73
78
|
/** Context menu string, or a builder function, same API as toolbar. */
|
|
74
79
|
contextmenu?: ListPatch;
|
|
75
80
|
/** Plugin list string, or a builder function, same API as toolbar.
|
|
76
|
-
* Note: this only
|
|
81
|
+
* Note: this only changes the string passed to tinymce.init - the
|
|
77
82
|
* underlying plugin JS still needs to be imported at the top of this
|
|
78
83
|
* file regardless of what's listed here. */
|
|
79
84
|
plugins?: ListPatch;
|
|
80
85
|
/** Menubar string (top-level menu keys, e.g. 'file edit view'), or a
|
|
81
|
-
* builder function, same API as toolbar. */
|
|
86
|
+
* builder function, same API as toolbar. An empty result hides the menubar. */
|
|
82
87
|
menubar?: ListPatch;
|
|
83
88
|
/** Menu config object ({ key: { title, items } }), or a builder
|
|
84
|
-
* function: (m) => m.
|
|
89
|
+
* function: (m) => m.removeItem('print') / m.clear() */
|
|
85
90
|
menu?: MenuPatch;
|
|
86
91
|
};
|
|
87
92
|
declare class tinymceHelpers {
|
package/index.mjs
CHANGED
|
@@ -63,11 +63,11 @@ import "tinymce/plugins/preview";
|
|
|
63
63
|
import "tinymce/plugins/insertdatetime";
|
|
64
64
|
|
|
65
65
|
// src/client/custom-components/mce.css?raw
|
|
66
|
-
var mce_default = ':where(.mce-content-body) {\n --editor-text: #000;\n --editor-link: #000;\n --editor-border: #d6d6d6c9;\n --editor-table-header-text: #6e6e6e;\n --editor-table-row-even: #fafafa;\n --editor-hr: #bbb;\n}\n\n\nli::marker {\n color: var(--editor-link) !important;\n}\n\n::-webkit-scrollbar {\n width: 10px;\n}\n\n::-webkit-scrollbar-track {\n background: var(--editor-table-row-even);\n}\n\n::-webkit-scrollbar-thumb {\n background: var(--editor-link);\n border-radius: 35px;\n}\n\n @media print {\n .mce-content-body {\n --editor-text: #000;\n --editor-link: #000;\n --editor-border: #d6d6d6c9;\n --editor-table-header-text: #000;\n --editor-table-row-even: #fafafa;\n --editor-hr: #000;\n }\n\n .mce-content-body table tr:nth-child(even) {\n background: var(--editor-table-row-even) !important;\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n }\n\n \n .mce-content-body blockquote {\n border-inline-start: none !important;\n background: #f9f9f9 !important;\n\n color: #000 !important;\n -webkit-print-color-adjust: exact !important;\n print-color-adjust: exact !important;\n }\n\n \n\n .mce-content-body td[data-mce-selected]::after,\n .mce-content-body th[data-mce-selected]::after {\n display: none !important;\n}\n}\n\n img {\n padding-block: 7px;\n max-width: 100%;\n }\n\n\n\n .mce-content-body blockquote {\n display: flow-root;\n padding: 15px;\n border-radius: 8px;\n margin: 0px !important;\n margin-block: 20px !important;\n overflow: hidden;\n border: none !important;\n background: var(--editor-table-row-even);\n color: var(--editor-text);\n}\n\n\n\n.mce-content-body blockquote p {\n margin: 0;\n}\n\n* {\n border: 0;\n padding: 0;\n margin: 0;\n background: 0 0;\n color: inherit;\n box-sizing: border-box;\n background-repeat: no-repeat;\n background-position: 50% 50%;\n font-weight: 400;\n}\n\n:focus {\n outline: 0;\n}\n\na {\n text-decoration: none;\n cursor: pointer;\n}\n\nb,\nb *,\nstrong,\nstrong * {\n font-weight: 700;\n}\n\nol,\nul {\n list-style: none;\n}\n\npre {\n font: inherit;\n}\n\nbutton,\ninput,\ninput:not([type]),\ninput[type="button"],\ninput[type="color"],\ninput[type="date"],\ninput[type="datetime-local"],\ninput[type="datetime"],\ninput[type="email"],\ninput[type="month"],\ninput[type="number"],\ninput[type="password"],\ninput[type="reset"],\ninput[type="search"],\ninput[type="submit"],\ninput[type="tel"],\ninput[type="text"],\ninput[type="time"],\ninput[type="url"],\ninput[type="week"],\nselect,\ntextarea {\n font: inherit;\n}\n\n.mce-container textarea {\n display: inline-block !important;\n} \n\n\n.my-custom-styles{\n direction: ltr;\n }\n\n.mce-content-body {\n
|
|
66
|
+
var mce_default = ':where(.mce-content-body) {\n --editor-text: #000;\n --editor-link: #000;\n --editor-border: #d6d6d6c9;\n --editor-table-header-text: #6e6e6e;\n --editor-table-row-even: #fafafa;\n --editor-hr: #bbb;\n}\n\n\nli::marker {\n color: var(--editor-link) !important;\n}\n\n::-webkit-scrollbar {\n width: 10px;\n}\n\n::-webkit-scrollbar-track {\n background: var(--editor-table-row-even);\n}\n\n::-webkit-scrollbar-thumb {\n background: var(--editor-link);\n border-radius: 35px;\n}\n\n @media print {\n .mce-content-body {\n --editor-text: #000;\n --editor-link: #000;\n --editor-border: #d6d6d6c9;\n --editor-table-header-text: #000;\n --editor-table-row-even: #fafafa;\n --editor-hr: #000;\n }\n\n .mce-content-body table tr:nth-child(even) {\n background: var(--editor-table-row-even) !important;\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n }\n\n \n .mce-content-body blockquote {\n border-inline-start: none !important;\n background: #f9f9f9 !important;\n\n color: #000 !important;\n -webkit-print-color-adjust: exact !important;\n print-color-adjust: exact !important;\n }\n\n \n\n .mce-content-body td[data-mce-selected]::after,\n .mce-content-body th[data-mce-selected]::after {\n display: none !important;\n}\n}\n\n img {\n padding-block: 7px;\n max-width: 100%;\n }\n\n\n\n .mce-content-body blockquote {\n display: flow-root;\n padding: 15px;\n border-radius: 8px;\n margin: 0px !important;\n margin-block: 20px !important;\n overflow: hidden;\n border: none !important;\n background: var(--editor-table-row-even);\n color: var(--editor-text);\n}\n\n\n\n.mce-content-body blockquote p {\n margin: 0;\n}\n\n* {\n border: 0;\n padding: 0;\n margin: 0;\n background: 0 0;\n color: inherit;\n box-sizing: border-box;\n background-repeat: no-repeat;\n background-position: 50% 50%;\n font-weight: 400;\n}\n\n:focus {\n outline: 0;\n}\n\na {\n text-decoration: none;\n cursor: pointer;\n}\n\nb,\nb *,\nstrong,\nstrong * {\n font-weight: 700;\n}\n\nol,\nul {\n list-style: none;\n}\n\npre {\n font: inherit;\n}\n\nbutton,\ninput,\ninput:not([type]),\ninput[type="button"],\ninput[type="color"],\ninput[type="date"],\ninput[type="datetime-local"],\ninput[type="datetime"],\ninput[type="email"],\ninput[type="month"],\ninput[type="number"],\ninput[type="password"],\ninput[type="reset"],\ninput[type="search"],\ninput[type="submit"],\ninput[type="tel"],\ninput[type="text"],\ninput[type="time"],\ninput[type="url"],\ninput[type="week"],\nselect,\ntextarea {\n font: inherit;\n}\n\n.mce-container textarea {\n display: inline-block !important;\n} \n\n\n.my-custom-styles{\n direction: ltr;\n }\n\n.mce-content-body {\n font-size: 22px;\n font-family: Rubik, Helvetica, Arial, sans-serif;\n padding: 0 25px 25px;\n color: var(--editor-text);\n}\n\n.mce-content-body table {\n width: 100%;\n table-layout: fixed;\n}\n\n\n\n.mce-content-body table td,\n.mce-content-body table th {\n overflow-wrap: anywhere;\n word-break: break-word;\n white-space: normal;\n}\n\n\n.mce-content-body h1 {\n font-size: 34px;\n line-height: 1.4em;\n margin: 25px 0 15px;\n}\n\n.mce-content-body h2 {\n font-size: 30px;\n line-height: 1.4em;\n margin: 25px 0 15px;\n}\n\n.mce-content-body h3 {\n font-size: 26px;\n line-height: 1.4em;\n margin: 25px 0 15px;\n}\n\n.mce-content-body h4 {\n font-size: 22px;\n line-height: 1.4em;\n margin: 25px 0 15px;\n}\n\n.mce-content-body h5 {\n font-size: 18px;\n line-height: 1.4em;\n margin: 25px 0 15px;\n}\n\n.mce-content-body h6 {\n font-size: 14px;\n line-height: 1.4em;\n margin: 25px 0 15px;\n}\n\n.mce-content-body p {\n margin: 25px 0;\n}\n\n.mce-content-body pre {\n font-family: monospace;\n}\n\n.mce-content-body ol,\n.mce-content-body ul {\n margin-left: 15px;\n list-style-position: outside;\n margin-bottom: 20px;\n}\n\n.mce-content-body ol li,\n.mce-content-body ul li {\n margin-left: 10px;\n margin-bottom: 10px;\n color: var(--editor-text);\n}\n\n.mce-content-body ul {\n list-style-type: disc;\n}\n\n.mce-content-body ol {\n list-style-type: decimal;\n}\n\n.mce-content-body a[href] {\n color: var(--editor-link);\n text-decoration: underline;\n}\n\n.mce-content-body table caption,\n.mce-content-body table td,\n.mce-content-body table th {\n padding: 15px 7px;\n font: inherit;\n}\n\n.mce-content-body table td,\n.mce-content-body table th {\n border: 1px solid var(--editor-border) !important;\n border-collapse: collapse;\n}\n\n.mce-content-body table th {\n font-weight: 400;\n color: var(--editor-table-header-text);\n background-position: 100% 100%;\n background-size: 2px 10px;\n background-repeat: no-repeat;\n}\n\n.mce-content-body table {\n width: 100%;\n border-spacing: 0;\n border-collapse: separate;\n \n}\n\n.mce-content-body table tr:nth-child(even) {\n background: var(--editor-table-row-even);\n}\n\n.mce-content-body hr {\n border-top: 2px solid var(--editor-hr);\n}';
|
|
67
67
|
|
|
68
68
|
// src/client/custom-components/tinymce-helpers.ts
|
|
69
69
|
import { isNonEmptyString } from "@rg-dev/stdlib/lib/common-env";
|
|
70
|
-
async function defaultSkin(
|
|
70
|
+
async function defaultSkin() {
|
|
71
71
|
const contentSkin = `default`;
|
|
72
72
|
const shellSkin = "oxide";
|
|
73
73
|
await Promise.all([
|
|
@@ -76,11 +76,7 @@ async function defaultSkin(document2 = false) {
|
|
|
76
76
|
import("tinymce/skins/ui/oxide/skin.js")
|
|
77
77
|
]);
|
|
78
78
|
return {
|
|
79
|
-
css: tinymce.Resource.get(`content/${contentSkin}/content.css`) + tinymce.Resource.get(`ui/${shellSkin}/content.css`)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
`,
|
|
79
|
+
css: tinymce.Resource.get(`content/${contentSkin}/content.css`) + tinymce.Resource.get(`ui/${shellSkin}/content.css`),
|
|
84
80
|
skin: shellSkin
|
|
85
81
|
};
|
|
86
82
|
}
|
|
@@ -96,8 +92,6 @@ async function darkSkin() {
|
|
|
96
92
|
);
|
|
97
93
|
return {
|
|
98
94
|
css: tinymce.Resource.get(`content/${contentSkin}/content.css`) + tinymce.Resource.get(`ui/${shellSkin}/content.css`) + `
|
|
99
|
-
|
|
100
|
-
|
|
101
95
|
.mce-content-body {
|
|
102
96
|
--editor-bg: #222f3e;
|
|
103
97
|
--editor-text: #e4e8ec;
|
|
@@ -117,29 +111,27 @@ var skinsTable = {
|
|
|
117
111
|
default: () => defaultSkin()
|
|
118
112
|
};
|
|
119
113
|
function resolvePatch(defaults, patch) {
|
|
114
|
+
var _a;
|
|
120
115
|
if (!patch) return {};
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
}
|
|
116
|
+
let resolved;
|
|
117
|
+
if (typeof patch === "function") {
|
|
118
|
+
const draft = __spreadValues({}, defaults);
|
|
119
|
+
resolved = (_a = patch(draft)) != null ? _a : draft;
|
|
120
|
+
} else {
|
|
121
|
+
resolved = patch;
|
|
136
122
|
}
|
|
137
|
-
|
|
123
|
+
const _b = resolved, { target, setup, selector } = _b, safe = __objRest(_b, ["target", "setup", "selector"]);
|
|
124
|
+
return safe;
|
|
138
125
|
}
|
|
139
126
|
var ListBuilder = class {
|
|
140
127
|
constructor(existing) {
|
|
141
128
|
__publicField(this, "items");
|
|
142
|
-
this.items = existing.trim()
|
|
129
|
+
this.items = existing.trim() ? existing.trim().split(/\s+/) : [];
|
|
130
|
+
}
|
|
131
|
+
/** Remove everything. */
|
|
132
|
+
clear() {
|
|
133
|
+
this.items = [];
|
|
134
|
+
return this;
|
|
143
135
|
}
|
|
144
136
|
/** add('btn') appends at the end. add(3, 'btn') inserts at index 3. */
|
|
145
137
|
add(indexOrItem, item) {
|
|
@@ -178,16 +170,23 @@ var ListBuilder = class {
|
|
|
178
170
|
}
|
|
179
171
|
return this;
|
|
180
172
|
}
|
|
173
|
+
/** Collapses duplicate / leading / trailing separators left behind by remove(). */
|
|
181
174
|
toString() {
|
|
182
|
-
|
|
175
|
+
const out = [];
|
|
176
|
+
for (const item of this.items) {
|
|
177
|
+
if (item === "|" && (out.length === 0 || out[out.length - 1] === "|")) continue;
|
|
178
|
+
out.push(item);
|
|
179
|
+
}
|
|
180
|
+
if (out[out.length - 1] === "|") out.pop();
|
|
181
|
+
return out.join(" ");
|
|
183
182
|
}
|
|
184
183
|
};
|
|
185
184
|
function applyListPatch(existing, patch) {
|
|
186
|
-
|
|
185
|
+
var _a;
|
|
186
|
+
if (patch === void 0) return existing;
|
|
187
187
|
if (typeof patch === "string") return patch;
|
|
188
188
|
const builder = new ListBuilder(existing);
|
|
189
|
-
|
|
190
|
-
return (result != null ? result : builder).toString();
|
|
189
|
+
return ((_a = patch(builder)) != null ? _a : builder).toString();
|
|
191
190
|
}
|
|
192
191
|
var MenuBuilder = class {
|
|
193
192
|
constructor(existing) {
|
|
@@ -196,6 +195,11 @@ var MenuBuilder = class {
|
|
|
196
195
|
Object.entries(existing).map(([k, v]) => [k, __spreadValues({}, v)])
|
|
197
196
|
);
|
|
198
197
|
}
|
|
198
|
+
/** Remove every menu. */
|
|
199
|
+
clear() {
|
|
200
|
+
this.menus = {};
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
199
203
|
/** Add or replace an entire menu, e.g. m.addMenu('others_menu', { title: 'Others', items: 'foo bar' }) */
|
|
200
204
|
addMenu(key, config) {
|
|
201
205
|
this.menus[key] = __spreadValues({}, config);
|
|
@@ -205,36 +209,36 @@ var MenuBuilder = class {
|
|
|
205
209
|
delete this.menus[key];
|
|
206
210
|
return this;
|
|
207
211
|
}
|
|
208
|
-
/**
|
|
212
|
+
/** Edit one menu's items with the same builder API as toolbar/contextmenu. */
|
|
209
213
|
items(key, patch) {
|
|
210
|
-
const
|
|
211
|
-
if (!
|
|
214
|
+
const menu = this.menus[key];
|
|
215
|
+
if (!menu) {
|
|
212
216
|
console.error(`MenuBuilder.items: menu "${key}" does not exist`);
|
|
213
217
|
return this;
|
|
214
218
|
}
|
|
215
|
-
|
|
219
|
+
menu.items = applyListPatch(menu.items, patch);
|
|
216
220
|
return this;
|
|
217
221
|
}
|
|
218
|
-
/**
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
removeItem(key, ...names) {
|
|
226
|
-
return this.items(key, (t) => t.remove(...names));
|
|
222
|
+
/** Remove items from one menu, or from every menu if `key` is omitted. */
|
|
223
|
+
removeItem(names, key) {
|
|
224
|
+
const list = Array.isArray(names) ? names : [names];
|
|
225
|
+
const keys = key ? [key] : Object.keys(this.menus);
|
|
226
|
+
for (const k of keys) this.items(k, (t) => t.remove(...list));
|
|
227
|
+
return this;
|
|
227
228
|
}
|
|
229
|
+
/** Empty menus are dropped so TinyMCE never sees a menu with no items. */
|
|
228
230
|
toObject() {
|
|
229
|
-
return
|
|
231
|
+
return Object.fromEntries(
|
|
232
|
+
Object.entries(this.menus).filter(([, m]) => m.items.trim())
|
|
233
|
+
);
|
|
230
234
|
}
|
|
231
235
|
};
|
|
232
236
|
function applyMenuPatch(existing, patch) {
|
|
237
|
+
var _a;
|
|
233
238
|
if (!patch) return existing;
|
|
234
239
|
if (typeof patch !== "function") return patch;
|
|
235
240
|
const builder = new MenuBuilder(existing);
|
|
236
|
-
|
|
237
|
-
return (result != null ? result : builder).toObject();
|
|
241
|
+
return ((_a = patch(builder)) != null ? _a : builder).toObject();
|
|
238
242
|
}
|
|
239
243
|
var tinymceHelpers = class _tinymceHelpers {
|
|
240
244
|
constructor() {
|
|
@@ -249,7 +253,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
249
253
|
this.editor.insertContent(`<img src="${src}" alt="">`);
|
|
250
254
|
}
|
|
251
255
|
async _initMce(el, customOpts = Object()) {
|
|
252
|
-
var _a;
|
|
256
|
+
var _a, _b;
|
|
253
257
|
if (!(el instanceof HTMLElement)) {
|
|
254
258
|
throw new Error("invalid element");
|
|
255
259
|
}
|
|
@@ -278,14 +282,12 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
278
282
|
if (parent) {
|
|
279
283
|
e.preventDefault();
|
|
280
284
|
e.stopImmediatePropagation();
|
|
281
|
-
editor.undoManager.transact(
|
|
282
|
-
(
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
);
|
|
285
|
+
editor.undoManager.transact(() => {
|
|
286
|
+
const p = editor.dom.create("p", {}, "<br>");
|
|
287
|
+
parent.insertBefore(p, blockquote.nextSibling);
|
|
288
|
+
editor.selection.select(p, true);
|
|
289
|
+
editor.selection.collapse(true);
|
|
290
|
+
});
|
|
289
291
|
editor.nodeChanged();
|
|
290
292
|
return;
|
|
291
293
|
}
|
|
@@ -295,123 +297,115 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
295
297
|
editor.getDoc().execCommand("insertParagraph", false, void 0);
|
|
296
298
|
editor.nodeChanged();
|
|
297
299
|
}, true);
|
|
298
|
-
editor.ui.registry.addMenuItem(
|
|
299
|
-
"
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
editor.selection.setCursorLocation(newBlock, 0);
|
|
310
|
-
editor.focus();
|
|
311
|
-
}
|
|
300
|
+
editor.ui.registry.addMenuItem("create-block-below", {
|
|
301
|
+
text: "Create block below",
|
|
302
|
+
icon: "plus",
|
|
303
|
+
onAction: () => {
|
|
304
|
+
const node = editor.selection.getNode();
|
|
305
|
+
const body = editor.getBody();
|
|
306
|
+
const topBlock = editor.dom.getParent(node, (n) => n.parentNode === body) || node;
|
|
307
|
+
const newBlock = editor.dom.create("p", {}, '<br data-mce-bogus="1">');
|
|
308
|
+
editor.dom.insertAfter(newBlock, topBlock);
|
|
309
|
+
editor.selection.setCursorLocation(newBlock, 0);
|
|
310
|
+
editor.focus();
|
|
312
311
|
}
|
|
313
|
-
);
|
|
314
|
-
editor.ui.registry.addMenuItem(
|
|
315
|
-
"
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
editor.selection.setCursorLocation(newBlock, 0);
|
|
327
|
-
editor.focus();
|
|
328
|
-
}
|
|
312
|
+
});
|
|
313
|
+
editor.ui.registry.addMenuItem("create-block-above", {
|
|
314
|
+
text: "Create block above",
|
|
315
|
+
icon: "plus",
|
|
316
|
+
onAction: () => {
|
|
317
|
+
var _a3;
|
|
318
|
+
const node = editor.selection.getNode();
|
|
319
|
+
const body = editor.getBody();
|
|
320
|
+
const topBlock = editor.dom.getParent(node, (n) => n.parentNode === body) || node;
|
|
321
|
+
const newBlock = editor.dom.create("p", {}, '<br data-mce-bogus="1">');
|
|
322
|
+
(_a3 = topBlock.parentNode) == null ? void 0 : _a3.insertBefore(newBlock, topBlock);
|
|
323
|
+
editor.selection.setCursorLocation(newBlock, 0);
|
|
324
|
+
editor.focus();
|
|
329
325
|
}
|
|
330
|
-
);
|
|
331
|
-
editor.ui.registry.addMenuItem(
|
|
332
|
-
"
|
|
333
|
-
{
|
|
334
|
-
|
|
335
|
-
onAction: async () => {
|
|
336
|
-
that.toggleTextDirection();
|
|
337
|
-
}
|
|
326
|
+
});
|
|
327
|
+
editor.ui.registry.addMenuItem("change-dir", {
|
|
328
|
+
text: "Switch text direction",
|
|
329
|
+
onAction: () => {
|
|
330
|
+
that.toggleTextDirection();
|
|
338
331
|
}
|
|
339
|
-
);
|
|
340
|
-
editor.ui.registry.addMenuItem(
|
|
341
|
-
"
|
|
342
|
-
{
|
|
343
|
-
|
|
344
|
-
onAction: async () => {
|
|
345
|
-
that.toggleReadOnly();
|
|
346
|
-
}
|
|
332
|
+
});
|
|
333
|
+
editor.ui.registry.addMenuItem("toggleEdit", {
|
|
334
|
+
text: "toggle readonly",
|
|
335
|
+
onAction: () => {
|
|
336
|
+
that.toggleReadOnly();
|
|
347
337
|
}
|
|
348
|
-
);
|
|
349
|
-
editor.ui.registry.addMenuItem(
|
|
350
|
-
"
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
selectedImage.style.width = "unset";
|
|
358
|
-
selectedImage.style.height = "unset";
|
|
359
|
-
}
|
|
338
|
+
});
|
|
339
|
+
editor.ui.registry.addMenuItem("reset-style-button-img", {
|
|
340
|
+
text: "Reset Image Style",
|
|
341
|
+
icon: "resize",
|
|
342
|
+
onAction: () => {
|
|
343
|
+
const selectedImage = editor.selection.getNode();
|
|
344
|
+
if (selectedImage.nodeName === "IMG") {
|
|
345
|
+
selectedImage.style.width = "unset";
|
|
346
|
+
selectedImage.style.height = "unset";
|
|
360
347
|
}
|
|
361
348
|
}
|
|
362
|
-
)
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
editor.execCommand("RemoveFormat");
|
|
369
|
-
}
|
|
349
|
+
});
|
|
350
|
+
editor.ui.registry.addMenuItem("clearTextStyle", {
|
|
351
|
+
text: "Clear formatting",
|
|
352
|
+
icon: "removeformat",
|
|
353
|
+
onAction: () => {
|
|
354
|
+
editor.execCommand("RemoveFormat");
|
|
370
355
|
}
|
|
371
|
-
);
|
|
372
|
-
editor.ui.registry.addMenuItem(
|
|
373
|
-
"
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
reader.onload = () => {
|
|
389
|
-
editor.insertContent(`<img src="${reader.result}" alt="">`);
|
|
390
|
-
};
|
|
391
|
-
reader.readAsDataURL(file);
|
|
356
|
+
});
|
|
357
|
+
editor.ui.registry.addMenuItem("insert-image", {
|
|
358
|
+
text: "Insert image",
|
|
359
|
+
icon: "image",
|
|
360
|
+
onAction: () => {
|
|
361
|
+
const input = document.createElement("input");
|
|
362
|
+
input.type = "file";
|
|
363
|
+
input.accept = "image/*";
|
|
364
|
+
input.onchange = () => {
|
|
365
|
+
var _a3;
|
|
366
|
+
const file = (_a3 = input.files) == null ? void 0 : _a3[0];
|
|
367
|
+
if (!file) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const reader = new FileReader();
|
|
371
|
+
reader.onload = () => {
|
|
372
|
+
editor.insertContent(`<img src="${reader.result}" alt="">`);
|
|
392
373
|
};
|
|
393
|
-
|
|
374
|
+
reader.readAsDataURL(file);
|
|
375
|
+
};
|
|
376
|
+
input.click();
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
editor.ui.registry.addButton("decreaseFontSize", {
|
|
380
|
+
tooltip: "Decrease Font Size",
|
|
381
|
+
icon: "minus",
|
|
382
|
+
onAction: () => {
|
|
383
|
+
const currentSize = editor.queryCommandValue("FontSize");
|
|
384
|
+
let newSize = 16;
|
|
385
|
+
if (currentSize) {
|
|
386
|
+
const sizeNum = parseInt(currentSize.toString());
|
|
387
|
+
if (!isNaN(sizeNum) && sizeNum > 8) {
|
|
388
|
+
newSize = sizeNum - 2;
|
|
389
|
+
}
|
|
394
390
|
}
|
|
391
|
+
editor.execCommand("FontSize", false, newSize + "px");
|
|
395
392
|
}
|
|
396
|
-
);
|
|
397
|
-
editor.ui.registry.addButton(
|
|
398
|
-
"
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if (
|
|
406
|
-
|
|
407
|
-
if (!isNaN(sizeNum) && sizeNum > 8) {
|
|
408
|
-
newSize = sizeNum - 2;
|
|
409
|
-
}
|
|
393
|
+
});
|
|
394
|
+
editor.ui.registry.addButton("increaseFontSize", {
|
|
395
|
+
tooltip: "Increase Font Size",
|
|
396
|
+
icon: "plus",
|
|
397
|
+
onAction: () => {
|
|
398
|
+
const currentSize = editor.queryCommandValue("FontSize");
|
|
399
|
+
let newSize = 16;
|
|
400
|
+
if (currentSize) {
|
|
401
|
+
const sizeNum = parseInt(currentSize.toString());
|
|
402
|
+
if (!isNaN(sizeNum)) {
|
|
403
|
+
newSize = sizeNum + 2;
|
|
410
404
|
}
|
|
411
|
-
editor.execCommand("FontSize", false, newSize + "px");
|
|
412
405
|
}
|
|
406
|
+
editor.execCommand("FontSize", false, newSize + "px");
|
|
413
407
|
}
|
|
414
|
-
);
|
|
408
|
+
});
|
|
415
409
|
editor.ui.registry.addButton(
|
|
416
410
|
"myBlockquote",
|
|
417
411
|
{
|
|
@@ -446,31 +440,13 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
446
440
|
}
|
|
447
441
|
}
|
|
448
442
|
);
|
|
449
|
-
editor.ui.registry.addButton(
|
|
450
|
-
"increaseFontSize",
|
|
451
|
-
{
|
|
452
|
-
tooltip: "Increase Font Size",
|
|
453
|
-
icon: "plus",
|
|
454
|
-
onAction: () => {
|
|
455
|
-
const currentSize = editor.queryCommandValue("FontSize");
|
|
456
|
-
let newSize = 16;
|
|
457
|
-
if (currentSize) {
|
|
458
|
-
const sizeNum = parseInt(currentSize.toString());
|
|
459
|
-
if (!isNaN(sizeNum)) {
|
|
460
|
-
newSize = sizeNum + 2;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
editor.execCommand("FontSize", false, newSize + "px");
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
);
|
|
467
443
|
(_a2 = customOpts.customSetup) == null ? void 0 : _a2.call(customOpts, editor);
|
|
468
444
|
},
|
|
469
445
|
newline_behavior: "linebreak",
|
|
470
446
|
id: "tinymce",
|
|
471
447
|
extended_valid_elements: "img[drawio-diagram|contenteditable|style|class|src]",
|
|
472
448
|
font_family_formats: "Rubik=Rubik, Helvetica, Arial, sans-serif; Andale Mono=andale mono,times; Arial=arial,helvetica,sans-serif; Arial Black=arial black,avant garde; Book Antiqua=book antiqua,palatino; Comic Sans MS=comic sans ms,sans-serif; Courier New=courier new,courier; Georgia=georgia,palatino; Helvetica=helvetica; Impact=impact,chicago; Symbol=symbol; Tahoma=tahoma,arial,helvetica,sans-serif; Terminal=terminal,monaco; Times New Roman=times new roman,times; Trebuchet MS=trebuchet ms,geneva; Verdana=verdana,geneva; Webdings=webdings; Wingdings=wingdings,zapf dingbats; Afacad=afacad,sans-serif; Marcellus=marcellus,serif; Poppins=poppins,sans-serif; Raleway=raleway,sans-serif;",
|
|
473
|
-
|
|
449
|
+
statusbar: false,
|
|
474
450
|
quickbars_insert_toolbar: "",
|
|
475
451
|
skin: theSkin.skin,
|
|
476
452
|
highlight_on_focus: false,
|
|
@@ -486,7 +462,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
486
462
|
height: "100%",
|
|
487
463
|
image_caption: true,
|
|
488
464
|
quickbars_selection_toolbar: "bold italic | quicklink blockquote quickimage quicktable",
|
|
489
|
-
|
|
465
|
+
noneditable_class: "mceNonEditable",
|
|
490
466
|
toolbar_mode: "sliding",
|
|
491
467
|
browser_spellcheck: true,
|
|
492
468
|
menu: {
|
|
@@ -500,33 +476,28 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
500
476
|
}
|
|
501
477
|
},
|
|
502
478
|
menubar: "file edit view insert format tools table others_menu",
|
|
503
|
-
//spellchecker_active: true,
|
|
504
|
-
// spellchecker_languages: 'US English=en-US,Hebrew=he_IL',
|
|
505
|
-
// "spellchecker_rpc_url": "https://spelling.iad.tiny.cloud",
|
|
506
|
-
// "spellchecker_rpc_url": "http://10.0.0.13:7777",
|
|
507
|
-
// "spellchecker_api_key": "qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc",
|
|
508
|
-
// spellchecker_language: 'he_IL',
|
|
509
|
-
//tinymcespellchecker
|
|
510
479
|
plugins: "preview importcss searchreplace autolink directionality code visualblocks visualchars fullscreen image link media codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount charmap quickbars emoticons",
|
|
511
|
-
// contextmenu: false,
|
|
512
480
|
contextmenu: "insert-image link image table create-block-above create-block-below reset-style-button-img clearTextStyle"
|
|
513
481
|
};
|
|
514
|
-
opts =
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
482
|
+
opts = __spreadValues(__spreadValues({}, opts), resolvePatch(opts, customOpts.overrides));
|
|
483
|
+
const listPatches = {
|
|
484
|
+
toolbar: customOpts.toolbar,
|
|
485
|
+
contextmenu: customOpts.contextmenu,
|
|
486
|
+
plugins: customOpts.plugins,
|
|
487
|
+
menubar: customOpts.menubar
|
|
488
|
+
};
|
|
489
|
+
for (const [key, patch] of Object.entries(listPatches)) {
|
|
490
|
+
const current = opts[key];
|
|
491
|
+
if (typeof current === "string") {
|
|
492
|
+
opts[key] = applyListPatch(current, patch);
|
|
493
|
+
}
|
|
526
494
|
}
|
|
527
495
|
if (opts.menu) {
|
|
528
496
|
opts.menu = applyMenuPatch(opts.menu, customOpts.menu);
|
|
529
497
|
}
|
|
498
|
+
if (typeof opts.menubar === "string" && !opts.menubar.trim()) {
|
|
499
|
+
opts.menubar = false;
|
|
500
|
+
}
|
|
530
501
|
if (!opts.skin) {
|
|
531
502
|
throw new Error("no skin");
|
|
532
503
|
}
|
|
@@ -535,6 +506,16 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
535
506
|
const all = mce.ui.registry.getAll();
|
|
536
507
|
const availableMenuItems = all.menuItems;
|
|
537
508
|
const availableButtons = all.buttons;
|
|
509
|
+
const BUILTIN_MENUS = /* @__PURE__ */ new Set(["file", "edit", "view", "insert", "format", "tools", "table", "help"]);
|
|
510
|
+
if (typeof opts.menubar == "string") {
|
|
511
|
+
const menubarItems = opts.menubar.trim().split(/\s+/).filter(Boolean);
|
|
512
|
+
const customMenus = new Set(Object.keys((_a = opts.menu) != null ? _a : {}));
|
|
513
|
+
for (const item of menubarItems) {
|
|
514
|
+
if (!BUILTIN_MENUS.has(item) && !customMenus.has(item)) {
|
|
515
|
+
console.error(`Menubar references unknown menu "${item}"`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
538
519
|
if (typeof opts.toolbar == "string") {
|
|
539
520
|
if (!isNonEmptyString(opts.toolbar.trim())) {
|
|
540
521
|
console.error("Toolbar is missing items");
|
|
@@ -542,9 +523,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
542
523
|
const items = opts.toolbar.trim().split(/\s+/).filter((item) => item !== "|");
|
|
543
524
|
for (const item of items) {
|
|
544
525
|
if (!availableButtons[item.toLowerCase()] && !availableMenuItems[item.toLowerCase()]) {
|
|
545
|
-
console.error(
|
|
546
|
-
`Toolbar references unknown button "${item}"`
|
|
547
|
-
);
|
|
526
|
+
console.error(`Toolbar references unknown button "${item}"`);
|
|
548
527
|
}
|
|
549
528
|
}
|
|
550
529
|
}
|
|
@@ -555,26 +534,22 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
555
534
|
} else {
|
|
556
535
|
const items = opts.contextmenu.trim().split(/\s+/);
|
|
557
536
|
for (const item of items) {
|
|
558
|
-
if (!availableMenuItems[item.toLowerCase()] && !all.contextToolbars[item.
|
|
559
|
-
console.error(
|
|
560
|
-
`Context menu references unknown menu item "${item}"`
|
|
561
|
-
);
|
|
537
|
+
if (!availableMenuItems[item.toLowerCase()] && !all.contextToolbars[item.toLowerCase()]) {
|
|
538
|
+
console.error(`Context menu references unknown menu item "${item}"`);
|
|
562
539
|
}
|
|
563
540
|
}
|
|
564
541
|
}
|
|
565
542
|
}
|
|
566
543
|
if (opts.menu) {
|
|
567
544
|
for (const [key, value] of Object.entries(opts.menu)) {
|
|
568
|
-
if (!isNonEmptyString((
|
|
545
|
+
if (!isNonEmptyString((_b = value.items) == null ? void 0 : _b.trim())) {
|
|
569
546
|
console.error(`Menu "${key}" is missing items`);
|
|
570
547
|
continue;
|
|
571
548
|
}
|
|
572
549
|
const items = value.items.trim().split(/\s+/);
|
|
573
550
|
for (const item of items) {
|
|
574
551
|
if (!availableMenuItems[item.toLowerCase()]) {
|
|
575
|
-
console.error(
|
|
576
|
-
`Menu "${key}" references unknown menu item "${item}"`
|
|
577
|
-
);
|
|
552
|
+
console.error(`Menu "${key}" references unknown menu item "${item}"`);
|
|
578
553
|
}
|
|
579
554
|
}
|
|
580
555
|
}
|
|
@@ -596,11 +571,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
596
571
|
toggleReadOnly(lock) {
|
|
597
572
|
let curr = this.editor.getBody().isContentEditable;
|
|
598
573
|
if (lock) {
|
|
599
|
-
|
|
600
|
-
curr = false;
|
|
601
|
-
} else {
|
|
602
|
-
curr = true;
|
|
603
|
-
}
|
|
574
|
+
curr = lock !== "no";
|
|
604
575
|
}
|
|
605
576
|
const container = this.editor.getContainer();
|
|
606
577
|
const editorBar = container.querySelector(".tox-editor-header");
|
|
@@ -642,14 +613,9 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
642
613
|
if (!styles) {
|
|
643
614
|
return;
|
|
644
615
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
}
|
|
649
|
-
const newDirection = dir;
|
|
650
|
-
styles.direction = newDirection;
|
|
651
|
-
const tds = this._editor.dom.select("td");
|
|
652
|
-
for (let td of tds) {
|
|
616
|
+
const dir = force_dir != null ? force_dir : styles.direction == "rtl" ? "ltr" : "rtl";
|
|
617
|
+
styles.direction = dir;
|
|
618
|
+
for (const td of this._editor.dom.select("td")) {
|
|
653
619
|
this._editor.dom.setStyle(td, "direction", dir);
|
|
654
620
|
}
|
|
655
621
|
}
|
|
@@ -681,14 +647,14 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
681
647
|
color:rgb(255,255,255);
|
|
682
648
|
cursor:pointer;
|
|
683
649
|
box-shadow:0 1px 3px rgba(0,0,0,0.2);
|
|
684
|
-
|
|
685
|
-
btn.style.backgroundColor = getComputedStyle(content).getPropertyValue("--editor-
|
|
686
|
-
btn.addEventListener(
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
650
|
+
`;
|
|
651
|
+
btn.style.backgroundColor = getComputedStyle(content).getPropertyValue("--editor-link").trim() || "black";
|
|
652
|
+
btn.addEventListener(
|
|
653
|
+
"click",
|
|
654
|
+
() => {
|
|
655
|
+
this.toggleReadOnly();
|
|
656
|
+
}
|
|
657
|
+
);
|
|
692
658
|
container.appendChild(btn);
|
|
693
659
|
this._lockButton = btn;
|
|
694
660
|
this.updateLockButton();
|