@rg-dev/tinymce-helpers 1.0.11 → 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 +71 -6
- package/index.mjs +297 -184
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -1,29 +1,94 @@
|
|
|
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;
|
|
6
15
|
skin: string;
|
|
7
16
|
}>;
|
|
8
17
|
default: () => Promise<{
|
|
9
|
-
css:
|
|
18
|
+
css: any;
|
|
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> | void);
|
|
30
|
+
declare class ListBuilder {
|
|
31
|
+
private items;
|
|
32
|
+
constructor(existing: string);
|
|
33
|
+
/** Remove everything. */
|
|
34
|
+
clear(): this;
|
|
35
|
+
/** add('btn') appends at the end. add(3, 'btn') inserts at index 3. */
|
|
36
|
+
add(indexOrItem: number | string, item?: string): this;
|
|
37
|
+
start(item: string): this;
|
|
38
|
+
after(target: string, item: string): this;
|
|
39
|
+
before(target: string, item: string): this;
|
|
40
|
+
remove(...names: string[]): this;
|
|
41
|
+
/** Insert a '|' separator at the end, or at a given index. */
|
|
42
|
+
separator(index?: number): this;
|
|
43
|
+
/** Collapses duplicate / leading / trailing separators left behind by remove(). */
|
|
44
|
+
toString(): string;
|
|
45
|
+
}
|
|
46
|
+
type ListPatch = string | ((t: ListBuilder) => ListBuilder | void);
|
|
47
|
+
type MenuEntry = {
|
|
48
|
+
title: string;
|
|
49
|
+
items: string;
|
|
50
|
+
};
|
|
51
|
+
type MenuConfig = Record<string, MenuEntry>;
|
|
52
|
+
declare class MenuBuilder {
|
|
53
|
+
private menus;
|
|
54
|
+
constructor(existing: MenuConfig);
|
|
55
|
+
/** Remove every menu. */
|
|
56
|
+
clear(): this;
|
|
57
|
+
/** Add or replace an entire menu, e.g. m.addMenu('others_menu', { title: 'Others', items: 'foo bar' }) */
|
|
58
|
+
addMenu(key: string, config: MenuEntry): this;
|
|
59
|
+
removeMenu(key: string): this;
|
|
60
|
+
/** Edit one menu's items with the same builder API as toolbar/contextmenu. */
|
|
61
|
+
items(key: string, patch: ListPatch): this;
|
|
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. */
|
|
65
|
+
toObject(): MenuConfig;
|
|
66
|
+
}
|
|
67
|
+
type MenuPatch = MenuConfig | ((m: MenuBuilder) => MenuBuilder | void);
|
|
20
68
|
type MyTinymceOpts = {
|
|
21
69
|
skin?: keyof typeof skinsTable;
|
|
22
70
|
direction?: 'rtl' | 'ltr';
|
|
23
71
|
customSetup?: (editor: Editor) => void;
|
|
24
|
-
|
|
72
|
+
/** Shallow patch applied over the default options (top-level keys are replaced).
|
|
73
|
+
* Accepts a plain partial object, or a function of the defaults
|
|
74
|
+
* that returns a partial object. */
|
|
75
|
+
overrides?: TinyMCEPatch;
|
|
76
|
+
/** Toolbar string, or a builder function: (t) => t.add('btn'), t.after('x','y'), t.clear(), etc. */
|
|
77
|
+
toolbar?: ListPatch;
|
|
78
|
+
/** Context menu string, or a builder function, same API as toolbar. */
|
|
79
|
+
contextmenu?: ListPatch;
|
|
80
|
+
/** Plugin list string, or a builder function, same API as toolbar.
|
|
81
|
+
* Note: this only changes the string passed to tinymce.init - the
|
|
82
|
+
* underlying plugin JS still needs to be imported at the top of this
|
|
83
|
+
* file regardless of what's listed here. */
|
|
84
|
+
plugins?: ListPatch;
|
|
85
|
+
/** Menubar string (top-level menu keys, e.g. 'file edit view'), or a
|
|
86
|
+
* builder function, same API as toolbar. An empty result hides the menubar. */
|
|
87
|
+
menubar?: ListPatch;
|
|
88
|
+
/** Menu config object ({ key: { title, items } }), or a builder
|
|
89
|
+
* function: (m) => m.removeItem('print') / m.clear() */
|
|
90
|
+
menu?: MenuPatch;
|
|
25
91
|
};
|
|
26
|
-
type EditorOpts = Omit<RemoveIndexSignature<RawEditorOptionsExtended>, 'setup' | 'target' | 'selector'> & Record<string, unknown>;
|
|
27
92
|
declare class tinymceHelpers {
|
|
28
93
|
private _editor;
|
|
29
94
|
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
|
|
@@ -51,11 +63,11 @@ import "tinymce/plugins/preview";
|
|
|
51
63
|
import "tinymce/plugins/insertdatetime";
|
|
52
64
|
|
|
53
65
|
// src/client/custom-components/mce.css?raw
|
|
54
|
-
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}';
|
|
55
67
|
|
|
56
68
|
// src/client/custom-components/tinymce-helpers.ts
|
|
57
69
|
import { isNonEmptyString } from "@rg-dev/stdlib/lib/common-env";
|
|
58
|
-
async function defaultSkin(
|
|
70
|
+
async function defaultSkin() {
|
|
59
71
|
const contentSkin = `default`;
|
|
60
72
|
const shellSkin = "oxide";
|
|
61
73
|
await Promise.all([
|
|
@@ -64,11 +76,7 @@ async function defaultSkin(document2 = false) {
|
|
|
64
76
|
import("tinymce/skins/ui/oxide/skin.js")
|
|
65
77
|
]);
|
|
66
78
|
return {
|
|
67
|
-
css: tinymce.Resource.get(`content/${contentSkin}/content.css`) + tinymce.Resource.get(`ui/${shellSkin}/content.css`)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
`,
|
|
79
|
+
css: tinymce.Resource.get(`content/${contentSkin}/content.css`) + tinymce.Resource.get(`ui/${shellSkin}/content.css`),
|
|
72
80
|
skin: shellSkin
|
|
73
81
|
};
|
|
74
82
|
}
|
|
@@ -84,9 +92,6 @@ async function darkSkin() {
|
|
|
84
92
|
);
|
|
85
93
|
return {
|
|
86
94
|
css: tinymce.Resource.get(`content/${contentSkin}/content.css`) + tinymce.Resource.get(`ui/${shellSkin}/content.css`) + `
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
95
|
.mce-content-body {
|
|
91
96
|
--editor-bg: #222f3e;
|
|
92
97
|
--editor-text: #e4e8ec;
|
|
@@ -105,6 +110,136 @@ var skinsTable = {
|
|
|
105
110
|
dark: () => darkSkin(),
|
|
106
111
|
default: () => defaultSkin()
|
|
107
112
|
};
|
|
113
|
+
function resolvePatch(defaults, patch) {
|
|
114
|
+
var _a;
|
|
115
|
+
if (!patch) return {};
|
|
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;
|
|
122
|
+
}
|
|
123
|
+
const _b = resolved, { target, setup, selector } = _b, safe = __objRest(_b, ["target", "setup", "selector"]);
|
|
124
|
+
return safe;
|
|
125
|
+
}
|
|
126
|
+
var ListBuilder = class {
|
|
127
|
+
constructor(existing) {
|
|
128
|
+
__publicField(this, "items");
|
|
129
|
+
this.items = existing.trim() ? existing.trim().split(/\s+/) : [];
|
|
130
|
+
}
|
|
131
|
+
/** Remove everything. */
|
|
132
|
+
clear() {
|
|
133
|
+
this.items = [];
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
/** add('btn') appends at the end. add(3, 'btn') inserts at index 3. */
|
|
137
|
+
add(indexOrItem, item) {
|
|
138
|
+
if (typeof indexOrItem === "number") {
|
|
139
|
+
this.items.splice(indexOrItem, 0, item);
|
|
140
|
+
} else {
|
|
141
|
+
this.items.push(indexOrItem);
|
|
142
|
+
}
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
start(item) {
|
|
146
|
+
this.items.unshift(item);
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
after(target, item) {
|
|
150
|
+
const i = this.items.indexOf(target);
|
|
151
|
+
this.items.splice(i === -1 ? this.items.length : i + 1, 0, item);
|
|
152
|
+
return this;
|
|
153
|
+
}
|
|
154
|
+
before(target, item) {
|
|
155
|
+
const i = this.items.indexOf(target);
|
|
156
|
+
this.items.splice(i === -1 ? this.items.length : i, 0, item);
|
|
157
|
+
return this;
|
|
158
|
+
}
|
|
159
|
+
remove(...names) {
|
|
160
|
+
const removeSet = new Set(names.map((n) => n.toLowerCase()));
|
|
161
|
+
this.items = this.items.filter((i) => i === "|" || !removeSet.has(i.toLowerCase()));
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
/** Insert a '|' separator at the end, or at a given index. */
|
|
165
|
+
separator(index) {
|
|
166
|
+
if (index === void 0) {
|
|
167
|
+
this.items.push("|");
|
|
168
|
+
} else {
|
|
169
|
+
this.items.splice(index, 0, "|");
|
|
170
|
+
}
|
|
171
|
+
return this;
|
|
172
|
+
}
|
|
173
|
+
/** Collapses duplicate / leading / trailing separators left behind by remove(). */
|
|
174
|
+
toString() {
|
|
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(" ");
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
function applyListPatch(existing, patch) {
|
|
185
|
+
var _a;
|
|
186
|
+
if (patch === void 0) return existing;
|
|
187
|
+
if (typeof patch === "string") return patch;
|
|
188
|
+
const builder = new ListBuilder(existing);
|
|
189
|
+
return ((_a = patch(builder)) != null ? _a : builder).toString();
|
|
190
|
+
}
|
|
191
|
+
var MenuBuilder = class {
|
|
192
|
+
constructor(existing) {
|
|
193
|
+
__publicField(this, "menus");
|
|
194
|
+
this.menus = Object.fromEntries(
|
|
195
|
+
Object.entries(existing).map(([k, v]) => [k, __spreadValues({}, v)])
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
/** Remove every menu. */
|
|
199
|
+
clear() {
|
|
200
|
+
this.menus = {};
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
203
|
+
/** Add or replace an entire menu, e.g. m.addMenu('others_menu', { title: 'Others', items: 'foo bar' }) */
|
|
204
|
+
addMenu(key, config) {
|
|
205
|
+
this.menus[key] = __spreadValues({}, config);
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
removeMenu(key) {
|
|
209
|
+
delete this.menus[key];
|
|
210
|
+
return this;
|
|
211
|
+
}
|
|
212
|
+
/** Edit one menu's items with the same builder API as toolbar/contextmenu. */
|
|
213
|
+
items(key, patch) {
|
|
214
|
+
const menu = this.menus[key];
|
|
215
|
+
if (!menu) {
|
|
216
|
+
console.error(`MenuBuilder.items: menu "${key}" does not exist`);
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
219
|
+
menu.items = applyListPatch(menu.items, patch);
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
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;
|
|
228
|
+
}
|
|
229
|
+
/** Empty menus are dropped so TinyMCE never sees a menu with no items. */
|
|
230
|
+
toObject() {
|
|
231
|
+
return Object.fromEntries(
|
|
232
|
+
Object.entries(this.menus).filter(([, m]) => m.items.trim())
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
function applyMenuPatch(existing, patch) {
|
|
237
|
+
var _a;
|
|
238
|
+
if (!patch) return existing;
|
|
239
|
+
if (typeof patch !== "function") return patch;
|
|
240
|
+
const builder = new MenuBuilder(existing);
|
|
241
|
+
return ((_a = patch(builder)) != null ? _a : builder).toObject();
|
|
242
|
+
}
|
|
108
243
|
var tinymceHelpers = class _tinymceHelpers {
|
|
109
244
|
constructor() {
|
|
110
245
|
__publicField(this, "_editor");
|
|
@@ -147,14 +282,12 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
147
282
|
if (parent) {
|
|
148
283
|
e.preventDefault();
|
|
149
284
|
e.stopImmediatePropagation();
|
|
150
|
-
editor.undoManager.transact(
|
|
151
|
-
(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
);
|
|
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
|
+
});
|
|
158
291
|
editor.nodeChanged();
|
|
159
292
|
return;
|
|
160
293
|
}
|
|
@@ -164,123 +297,115 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
164
297
|
editor.getDoc().execCommand("insertParagraph", false, void 0);
|
|
165
298
|
editor.nodeChanged();
|
|
166
299
|
}, true);
|
|
167
|
-
editor.ui.registry.addMenuItem(
|
|
168
|
-
"
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
editor.selection.setCursorLocation(newBlock, 0);
|
|
179
|
-
editor.focus();
|
|
180
|
-
}
|
|
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();
|
|
181
311
|
}
|
|
182
|
-
);
|
|
183
|
-
editor.ui.registry.addMenuItem(
|
|
184
|
-
"
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
editor.selection.setCursorLocation(newBlock, 0);
|
|
196
|
-
editor.focus();
|
|
197
|
-
}
|
|
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();
|
|
198
325
|
}
|
|
199
|
-
);
|
|
200
|
-
editor.ui.registry.addMenuItem(
|
|
201
|
-
"
|
|
202
|
-
{
|
|
203
|
-
|
|
204
|
-
onAction: async () => {
|
|
205
|
-
that.toggleTextDirection();
|
|
206
|
-
}
|
|
326
|
+
});
|
|
327
|
+
editor.ui.registry.addMenuItem("change-dir", {
|
|
328
|
+
text: "Switch text direction",
|
|
329
|
+
onAction: () => {
|
|
330
|
+
that.toggleTextDirection();
|
|
207
331
|
}
|
|
208
|
-
);
|
|
209
|
-
editor.ui.registry.addMenuItem(
|
|
210
|
-
"
|
|
211
|
-
{
|
|
212
|
-
|
|
213
|
-
onAction: async () => {
|
|
214
|
-
that.toggleReadOnly();
|
|
215
|
-
}
|
|
332
|
+
});
|
|
333
|
+
editor.ui.registry.addMenuItem("toggleEdit", {
|
|
334
|
+
text: "toggle readonly",
|
|
335
|
+
onAction: () => {
|
|
336
|
+
that.toggleReadOnly();
|
|
216
337
|
}
|
|
217
|
-
);
|
|
218
|
-
editor.ui.registry.addMenuItem(
|
|
219
|
-
"
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
selectedImage.style.width = "unset";
|
|
227
|
-
selectedImage.style.height = "unset";
|
|
228
|
-
}
|
|
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";
|
|
229
347
|
}
|
|
230
348
|
}
|
|
231
|
-
)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
editor.execCommand("RemoveFormat");
|
|
238
|
-
}
|
|
349
|
+
});
|
|
350
|
+
editor.ui.registry.addMenuItem("clearTextStyle", {
|
|
351
|
+
text: "Clear formatting",
|
|
352
|
+
icon: "removeformat",
|
|
353
|
+
onAction: () => {
|
|
354
|
+
editor.execCommand("RemoveFormat");
|
|
239
355
|
}
|
|
240
|
-
);
|
|
241
|
-
editor.ui.registry.addMenuItem(
|
|
242
|
-
"
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
reader.onload = () => {
|
|
258
|
-
editor.insertContent(`<img src="${reader.result}" alt="">`);
|
|
259
|
-
};
|
|
260
|
-
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="">`);
|
|
261
373
|
};
|
|
262
|
-
|
|
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
|
+
}
|
|
263
390
|
}
|
|
391
|
+
editor.execCommand("FontSize", false, newSize + "px");
|
|
264
392
|
}
|
|
265
|
-
);
|
|
266
|
-
editor.ui.registry.addButton(
|
|
267
|
-
"
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
if (
|
|
275
|
-
|
|
276
|
-
if (!isNaN(sizeNum) && sizeNum > 8) {
|
|
277
|
-
newSize = sizeNum - 2;
|
|
278
|
-
}
|
|
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;
|
|
279
404
|
}
|
|
280
|
-
editor.execCommand("FontSize", false, newSize + "px");
|
|
281
405
|
}
|
|
406
|
+
editor.execCommand("FontSize", false, newSize + "px");
|
|
282
407
|
}
|
|
283
|
-
);
|
|
408
|
+
});
|
|
284
409
|
editor.ui.registry.addButton(
|
|
285
410
|
"myBlockquote",
|
|
286
411
|
{
|
|
@@ -293,7 +418,9 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
293
418
|
() => {
|
|
294
419
|
if (blockquote) {
|
|
295
420
|
const parent = blockquote.parentNode;
|
|
296
|
-
if (!parent)
|
|
421
|
+
if (!parent) {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
297
424
|
while (blockquote.firstChild) {
|
|
298
425
|
parent.insertBefore(blockquote.firstChild, blockquote);
|
|
299
426
|
}
|
|
@@ -313,31 +440,13 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
313
440
|
}
|
|
314
441
|
}
|
|
315
442
|
);
|
|
316
|
-
editor.ui.registry.addButton(
|
|
317
|
-
"increaseFontSize",
|
|
318
|
-
{
|
|
319
|
-
tooltip: "Increase Font Size",
|
|
320
|
-
icon: "plus",
|
|
321
|
-
onAction: () => {
|
|
322
|
-
const currentSize = editor.queryCommandValue("FontSize");
|
|
323
|
-
let newSize = 16;
|
|
324
|
-
if (currentSize) {
|
|
325
|
-
const sizeNum = parseInt(currentSize.toString());
|
|
326
|
-
if (!isNaN(sizeNum)) {
|
|
327
|
-
newSize = sizeNum + 2;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
editor.execCommand("FontSize", false, newSize + "px");
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
);
|
|
334
443
|
(_a2 = customOpts.customSetup) == null ? void 0 : _a2.call(customOpts, editor);
|
|
335
444
|
},
|
|
336
445
|
newline_behavior: "linebreak",
|
|
337
446
|
id: "tinymce",
|
|
338
447
|
extended_valid_elements: "img[drawio-diagram|contenteditable|style|class|src]",
|
|
339
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;",
|
|
340
|
-
|
|
449
|
+
statusbar: false,
|
|
341
450
|
quickbars_insert_toolbar: "",
|
|
342
451
|
skin: theSkin.skin,
|
|
343
452
|
highlight_on_focus: false,
|
|
@@ -353,7 +462,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
353
462
|
height: "100%",
|
|
354
463
|
image_caption: true,
|
|
355
464
|
quickbars_selection_toolbar: "bold italic | quicklink blockquote quickimage quicktable",
|
|
356
|
-
|
|
465
|
+
noneditable_class: "mceNonEditable",
|
|
357
466
|
toolbar_mode: "sliding",
|
|
358
467
|
browser_spellcheck: true,
|
|
359
468
|
menu: {
|
|
@@ -367,27 +476,46 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
367
476
|
}
|
|
368
477
|
},
|
|
369
478
|
menubar: "file edit view insert format tools table others_menu",
|
|
370
|
-
//spellchecker_active: true,
|
|
371
|
-
// spellchecker_languages: 'US English=en-US,Hebrew=he_IL',
|
|
372
|
-
// "spellchecker_rpc_url": "https://spelling.iad.tiny.cloud",
|
|
373
|
-
// "spellchecker_rpc_url": "http://10.0.0.13:7777",
|
|
374
|
-
// "spellchecker_api_key": "qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc",
|
|
375
|
-
// spellchecker_language: 'he_IL',
|
|
376
|
-
//tinymcespellchecker
|
|
377
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",
|
|
378
|
-
// contextmenu: false,
|
|
379
480
|
contextmenu: "insert-image link image table create-block-above create-block-below reset-style-button-img clearTextStyle"
|
|
380
481
|
};
|
|
381
|
-
opts = __spreadValues(__spreadValues({}, opts), (
|
|
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
|
+
}
|
|
494
|
+
}
|
|
495
|
+
if (opts.menu) {
|
|
496
|
+
opts.menu = applyMenuPatch(opts.menu, customOpts.menu);
|
|
497
|
+
}
|
|
498
|
+
if (typeof opts.menubar === "string" && !opts.menubar.trim()) {
|
|
499
|
+
opts.menubar = false;
|
|
500
|
+
}
|
|
382
501
|
if (!opts.skin) {
|
|
383
502
|
throw new Error("no skin");
|
|
384
503
|
}
|
|
385
504
|
const mce = this._editor = await tinymce.init(opts).then((x) => x[0]);
|
|
386
505
|
this.originalContextMenu = mce.options.get("contextmenu");
|
|
387
506
|
const all = mce.ui.registry.getAll();
|
|
388
|
-
console.log(all);
|
|
389
507
|
const availableMenuItems = all.menuItems;
|
|
390
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
|
+
}
|
|
391
519
|
if (typeof opts.toolbar == "string") {
|
|
392
520
|
if (!isNonEmptyString(opts.toolbar.trim())) {
|
|
393
521
|
console.error("Toolbar is missing items");
|
|
@@ -395,9 +523,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
395
523
|
const items = opts.toolbar.trim().split(/\s+/).filter((item) => item !== "|");
|
|
396
524
|
for (const item of items) {
|
|
397
525
|
if (!availableButtons[item.toLowerCase()] && !availableMenuItems[item.toLowerCase()]) {
|
|
398
|
-
console.error(
|
|
399
|
-
`Toolbar references unknown button "${item}"`
|
|
400
|
-
);
|
|
526
|
+
console.error(`Toolbar references unknown button "${item}"`);
|
|
401
527
|
}
|
|
402
528
|
}
|
|
403
529
|
}
|
|
@@ -408,10 +534,8 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
408
534
|
} else {
|
|
409
535
|
const items = opts.contextmenu.trim().split(/\s+/);
|
|
410
536
|
for (const item of items) {
|
|
411
|
-
if (!availableMenuItems[item.toLowerCase()] && !all.contextToolbars[item.
|
|
412
|
-
console.error(
|
|
413
|
-
`Context menu references unknown menu item "${item}"`
|
|
414
|
-
);
|
|
537
|
+
if (!availableMenuItems[item.toLowerCase()] && !all.contextToolbars[item.toLowerCase()]) {
|
|
538
|
+
console.error(`Context menu references unknown menu item "${item}"`);
|
|
415
539
|
}
|
|
416
540
|
}
|
|
417
541
|
}
|
|
@@ -425,9 +549,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
425
549
|
const items = value.items.trim().split(/\s+/);
|
|
426
550
|
for (const item of items) {
|
|
427
551
|
if (!availableMenuItems[item.toLowerCase()]) {
|
|
428
|
-
console.error(
|
|
429
|
-
`Menu "${key}" references unknown menu item "${item}"`
|
|
430
|
-
);
|
|
552
|
+
console.error(`Menu "${key}" references unknown menu item "${item}"`);
|
|
431
553
|
}
|
|
432
554
|
}
|
|
433
555
|
}
|
|
@@ -449,11 +571,7 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
449
571
|
toggleReadOnly(lock) {
|
|
450
572
|
let curr = this.editor.getBody().isContentEditable;
|
|
451
573
|
if (lock) {
|
|
452
|
-
|
|
453
|
-
curr = false;
|
|
454
|
-
} else {
|
|
455
|
-
curr = true;
|
|
456
|
-
}
|
|
574
|
+
curr = lock !== "no";
|
|
457
575
|
}
|
|
458
576
|
const container = this.editor.getContainer();
|
|
459
577
|
const editorBar = container.querySelector(".tox-editor-header");
|
|
@@ -495,14 +613,9 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
495
613
|
if (!styles) {
|
|
496
614
|
return;
|
|
497
615
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
}
|
|
502
|
-
const newDirection = dir;
|
|
503
|
-
styles.direction = newDirection;
|
|
504
|
-
const tds = this._editor.dom.select("td");
|
|
505
|
-
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")) {
|
|
506
619
|
this._editor.dom.setStyle(td, "direction", dir);
|
|
507
620
|
}
|
|
508
621
|
}
|
|
@@ -534,14 +647,14 @@ var tinymceHelpers = class _tinymceHelpers {
|
|
|
534
647
|
color:rgb(255,255,255);
|
|
535
648
|
cursor:pointer;
|
|
536
649
|
box-shadow:0 1px 3px rgba(0,0,0,0.2);
|
|
537
|
-
|
|
538
|
-
btn.style.backgroundColor = getComputedStyle(content).getPropertyValue("--editor-
|
|
539
|
-
btn.addEventListener(
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
650
|
+
`;
|
|
651
|
+
btn.style.backgroundColor = getComputedStyle(content).getPropertyValue("--editor-link").trim() || "black";
|
|
652
|
+
btn.addEventListener(
|
|
653
|
+
"click",
|
|
654
|
+
() => {
|
|
655
|
+
this.toggleReadOnly();
|
|
656
|
+
}
|
|
657
|
+
);
|
|
545
658
|
container.appendChild(btn);
|
|
546
659
|
this._lockButton = btn;
|
|
547
660
|
this.updateLockButton();
|