jodit 4.17.6 → 4.18.0
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/CHANGELOG.md +10 -0
- package/es2015/jodit.css +87 -3
- package/es2015/jodit.fat.min.css +1 -1
- package/es2015/jodit.fat.min.js +8 -8
- package/es2015/jodit.js +789 -130
- package/es2015/jodit.min.css +1 -1
- package/es2015/jodit.min.js +16 -16
- package/es2015/plugins/debug/debug.css +1 -1
- package/es2015/plugins/debug/debug.js +1 -1
- package/es2015/plugins/debug/debug.min.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2018/jodit.fat.min.css +1 -1
- package/es2018/jodit.fat.min.js +8 -8
- package/es2018/jodit.min.css +1 -1
- package/es2018/jodit.min.js +8 -8
- package/es2018/plugins/debug/debug.min.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021/jodit.css +87 -3
- package/es2021/jodit.fat.min.css +1 -1
- package/es2021/jodit.fat.min.js +14 -14
- package/es2021/jodit.js +769 -130
- package/es2021/jodit.min.css +1 -1
- package/es2021/jodit.min.js +14 -14
- package/es2021/plugins/debug/debug.css +1 -1
- package/es2021/plugins/debug/debug.js +1 -1
- package/es2021/plugins/debug/debug.min.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021.en/jodit.css +87 -3
- package/es2021.en/jodit.fat.min.css +1 -1
- package/es2021.en/jodit.fat.min.js +12 -12
- package/es2021.en/jodit.js +769 -130
- package/es2021.en/jodit.min.css +1 -1
- package/es2021.en/jodit.min.js +12 -12
- package/es2021.en/plugins/debug/debug.css +1 -1
- package/es2021.en/plugins/debug/debug.js +1 -1
- package/es2021.en/plugins/debug/debug.min.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es5/jodit.css +92 -6
- package/es5/jodit.fat.min.css +1 -1
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +1054 -190
- package/es5/jodit.min.css +3 -3
- package/es5/jodit.min.js +2 -2
- package/es5/plugins/debug/debug.css +1 -1
- package/es5/plugins/debug/debug.js +1 -1
- package/es5/plugins/debug/debug.min.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es5/polyfills.fat.min.js +1 -1
- package/es5/polyfills.js +1 -1
- package/es5/polyfills.min.js +1 -1
- package/esm/config.d.ts +65 -2
- package/esm/config.js +29 -2
- package/esm/core/constants.js +1 -1
- package/esm/core/helpers/utils/align.d.ts +11 -5
- package/esm/core/helpers/utils/align.js +28 -8
- package/esm/core/helpers/utils/index.d.ts +1 -0
- package/esm/core/helpers/utils/index.js +1 -0
- package/esm/core/helpers/utils/media-wrapper.d.ts +29 -0
- package/esm/core/helpers/utils/media-wrapper.js +63 -0
- package/esm/core/selection/selection.js +3 -3
- package/esm/modules/toolbar/button/button.d.ts +18 -0
- package/esm/modules/toolbar/button/button.js +75 -5
- package/esm/plugins/font/config.d.ts +12 -0
- package/esm/plugins/font/config.js +25 -10
- package/esm/plugins/font/font-picker.d.ts +51 -0
- package/esm/plugins/font/font-picker.js +238 -0
- package/esm/plugins/font/font.js +12 -0
- package/esm/plugins/font/google-fonts.d.ts +65 -0
- package/esm/plugins/font/google-fonts.js +143 -0
- package/esm/plugins/image-properties/readers/index.js +2 -1
- package/esm/plugins/image-properties/writers/index.js +2 -2
- package/esm/plugins/inline-popup/config/items/img.js +10 -8
- package/esm/plugins/inline-popup/inline-popup.js +13 -6
- package/esm/plugins/media/config.d.ts +26 -1
- package/esm/plugins/media/config.js +1 -3
- package/esm/plugins/media/media.js +12 -4
- package/esm/plugins/video/config.js +24 -4
- package/esm/types/toolbar.d.ts +2 -0
- package/esm/types/types.d.ts +13 -1
- package/package.json +1 -1
- package/types/config.d.ts +65 -2
- package/types/core/helpers/utils/align.d.ts +11 -5
- package/types/core/helpers/utils/index.d.ts +1 -0
- package/types/core/helpers/utils/media-wrapper.d.ts +29 -0
- package/types/modules/toolbar/button/button.d.ts +18 -0
- package/types/plugins/font/config.d.ts +12 -0
- package/types/plugins/font/font-picker.d.ts +51 -0
- package/types/plugins/font/google-fonts.d.ts +65 -0
- package/types/plugins/media/config.d.ts +26 -1
- package/types/types/toolbar.d.ts +2 -0
- package/types/types/types.d.ts +13 -1
|
@@ -6,6 +6,18 @@
|
|
|
6
6
|
declare module 'jodit/config' {
|
|
7
7
|
interface Config {
|
|
8
8
|
defaultFontSizePoints: 'px' | 'pt';
|
|
9
|
+
font: {
|
|
10
|
+
googleFonts: {
|
|
11
|
+
/**
|
|
12
|
+
* Adds the Google Fonts library to the font family dropdown, which then
|
|
13
|
+
* also lists the theme's fonts and the fonts the content uses. The
|
|
14
|
+
* address answers with the JSON of the Google Fonts Developer API:
|
|
15
|
+
* the API itself (`https://www.googleapis.com/webfonts/v1/webfonts?key=…`)
|
|
16
|
+
* or a proxy of it. Empty leaves the dropdown as it is
|
|
17
|
+
*/
|
|
18
|
+
url: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
9
21
|
}
|
|
10
22
|
}
|
|
11
23
|
export {};
|
|
@@ -4,16 +4,23 @@
|
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
6
|
import { Dom } from "../../core/dom/index.js";
|
|
7
|
+
import { isArray } from "../../core/helpers/checker/is-array.js";
|
|
7
8
|
import { trimChars } from "../../core/helpers/string/trim.js";
|
|
8
9
|
import { css } from "../../core/helpers/utils/css.js";
|
|
9
10
|
import { Icon } from "../../core/ui/icon.js";
|
|
10
11
|
import { Config } from "../../config.js";
|
|
11
12
|
import fontIcon from "./icons/font.svg.js";
|
|
12
13
|
import fontsizeIcon from "./icons/fontsize.svg.js";
|
|
14
|
+
import { UIFontPicker } from "./font-picker.js";
|
|
13
15
|
/**
|
|
14
16
|
* Default font-size points
|
|
15
17
|
*/
|
|
16
18
|
Config.prototype.defaultFontSizePoints = 'px';
|
|
19
|
+
Config.prototype.font = {
|
|
20
|
+
googleFonts: {
|
|
21
|
+
url: ''
|
|
22
|
+
}
|
|
23
|
+
};
|
|
17
24
|
Icon.set('font', fontIcon).set('fontsize', fontsizeIcon);
|
|
18
25
|
Config.prototype.controls.fontsize = {
|
|
19
26
|
command: 'fontsize',
|
|
@@ -78,6 +85,7 @@ Config.prototype.controls.fontsize = {
|
|
|
78
85
|
return keySet.has(normalize(value.toString()));
|
|
79
86
|
}
|
|
80
87
|
};
|
|
88
|
+
const hadSelection = new WeakSet();
|
|
81
89
|
Config.prototype.controls.font = {
|
|
82
90
|
...Config.prototype.controls.fontsize,
|
|
83
91
|
command: 'fontname',
|
|
@@ -108,6 +116,9 @@ Config.prototype.controls.font = {
|
|
|
108
116
|
catch (_a) { }
|
|
109
117
|
return `<span data-style="${key}" style="${isAvailable ? `font-family: ${key}!important;` : ''}">${value}</span>`;
|
|
110
118
|
},
|
|
119
|
+
popup: (editor, current, close, button) => editor.o.font.googleFonts.url
|
|
120
|
+
? new UIFontPicker(editor, button, close)
|
|
121
|
+
: false,
|
|
111
122
|
data: {
|
|
112
123
|
cssRule: 'font-family',
|
|
113
124
|
normalize: (v) => {
|
|
@@ -119,19 +130,23 @@ Config.prototype.controls.font = {
|
|
|
119
130
|
},
|
|
120
131
|
// When no font is explicitly set, the computed font-family equals the
|
|
121
132
|
// editor's own default (e.g. `-apple-system, …`). Return '' so the
|
|
122
|
-
// button shows the `Default`
|
|
123
|
-
// See #1370
|
|
124
|
-
value: (editor) => {
|
|
125
|
-
const current = editor.s.current();
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
// button shows the list's `Default` entry, when it has one, instead of
|
|
134
|
+
// that raw stack. See #1370
|
|
135
|
+
value: (editor, button) => {
|
|
136
|
+
const current = editor.s.current(), box = current && Dom.closest(current, Dom.isElement, editor.editor);
|
|
137
|
+
// Until there is a selection the button shows the editor's own font,
|
|
138
|
+
// and afterwards the font of the last one
|
|
139
|
+
if (box) {
|
|
140
|
+
hadSelection.add(button);
|
|
128
141
|
}
|
|
129
|
-
|
|
130
|
-
if (!box) {
|
|
142
|
+
else if (hadSelection.has(button)) {
|
|
131
143
|
return;
|
|
132
144
|
}
|
|
133
|
-
const value = css(box, 'font-family').toString();
|
|
134
|
-
if (value === css(editor.editor, 'font-family').toString()
|
|
145
|
+
const value = css(box || editor.editor, 'font-family').toString(), { list } = button.control;
|
|
146
|
+
if (value === css(editor.editor, 'font-family').toString() &&
|
|
147
|
+
(isArray(list)
|
|
148
|
+
? list.includes('')
|
|
149
|
+
: '' in (list !== null && list !== void 0 ? list : {}))) {
|
|
135
150
|
return '';
|
|
136
151
|
}
|
|
137
152
|
return value;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @module plugins/font
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit, IToolbarButton } from "../../types/index";
|
|
10
|
+
import { UIElement } from "../../core/ui/element";
|
|
11
|
+
/**
|
|
12
|
+
* The font family dropdown with Google Fonts. Under their own headings it
|
|
13
|
+
* lists the fonts the editor's styles give text and headings, the fonts the
|
|
14
|
+
* content uses, the control's list and the Google Fonts library
|
|
15
|
+
*/
|
|
16
|
+
export declare class UIFontPicker extends UIElement<IJodit> {
|
|
17
|
+
private readonly __button;
|
|
18
|
+
private readonly __close;
|
|
19
|
+
className(): string;
|
|
20
|
+
private readonly __googleFonts;
|
|
21
|
+
private readonly __fonts;
|
|
22
|
+
private __observer;
|
|
23
|
+
constructor(jodit: IJodit, __button: IToolbarButton, __close: () => void);
|
|
24
|
+
private __render;
|
|
25
|
+
/**
|
|
26
|
+
* The fonts the editor's styles give text and each heading
|
|
27
|
+
*/
|
|
28
|
+
private __themeFonts;
|
|
29
|
+
/**
|
|
30
|
+
* The fonts the content sets
|
|
31
|
+
*/
|
|
32
|
+
private __usedFonts;
|
|
33
|
+
private __append;
|
|
34
|
+
/**
|
|
35
|
+
* Shows the names of the Google Fonts in view, and those just below it,
|
|
36
|
+
* in their own fonts. Setting every item's font up front would have the
|
|
37
|
+
* browser look for each of the library's families among the installed
|
|
38
|
+
* fonts the first time the list opens
|
|
39
|
+
*/
|
|
40
|
+
private __observeGoogleFonts;
|
|
41
|
+
/**
|
|
42
|
+
* Keeps the editor's selection, as the toolbar buttons do
|
|
43
|
+
*/
|
|
44
|
+
protected onMouseDown(e: MouseEvent): void;
|
|
45
|
+
protected onClick(e: MouseEvent): void;
|
|
46
|
+
/**
|
|
47
|
+
* The font the selected text has without a font of its own: its block's
|
|
48
|
+
*/
|
|
49
|
+
private __blockFont;
|
|
50
|
+
destruct(): void;
|
|
51
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
7
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
9
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else
|
|
11
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
12
|
+
if (d = decorators[i])
|
|
13
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
+
};
|
|
16
|
+
import { component } from "../../core/decorators/component/component.js";
|
|
17
|
+
import { watch } from "../../core/decorators/watch/watch.js";
|
|
18
|
+
import { Dom } from "../../core/dom/dom.js";
|
|
19
|
+
import { uniqueUid } from "../../core/global.js";
|
|
20
|
+
import { isArray } from "../../core/helpers/checker/is-array.js";
|
|
21
|
+
import { attr } from "../../core/helpers/utils/attr.js";
|
|
22
|
+
import { css } from "../../core/helpers/utils/css.js";
|
|
23
|
+
import { keys } from "../../core/helpers/utils/utils.js";
|
|
24
|
+
import { UIElement } from "../../core/ui/element.js";
|
|
25
|
+
import { firstFamily, GoogleFonts } from "./google-fonts.js";
|
|
26
|
+
const HEADINGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
|
|
27
|
+
const GENERIC_FAMILIES = new Set([
|
|
28
|
+
'serif',
|
|
29
|
+
'sans-serif',
|
|
30
|
+
'monospace',
|
|
31
|
+
'cursive',
|
|
32
|
+
'fantasy',
|
|
33
|
+
'system-ui',
|
|
34
|
+
'ui-serif',
|
|
35
|
+
'ui-sans-serif',
|
|
36
|
+
'ui-monospace',
|
|
37
|
+
'ui-rounded'
|
|
38
|
+
]);
|
|
39
|
+
/**
|
|
40
|
+
* A family that names a font, not a generic family or a vendor keyword such
|
|
41
|
+
* as `-apple-system`
|
|
42
|
+
*/
|
|
43
|
+
function isFontName(family) {
|
|
44
|
+
return (Boolean(family) &&
|
|
45
|
+
!family.startsWith('-') &&
|
|
46
|
+
!GENERIC_FAMILIES.has(family));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The font family dropdown with Google Fonts. Under their own headings it
|
|
50
|
+
* lists the fonts the editor's styles give text and headings, the fonts the
|
|
51
|
+
* content uses, the control's list and the Google Fonts library
|
|
52
|
+
*/
|
|
53
|
+
let UIFontPicker = class UIFontPicker extends UIElement {
|
|
54
|
+
className() {
|
|
55
|
+
return 'UIFontPicker';
|
|
56
|
+
}
|
|
57
|
+
constructor(jodit, __button, __close) {
|
|
58
|
+
super(jodit);
|
|
59
|
+
this.__button = __button;
|
|
60
|
+
this.__close = __close;
|
|
61
|
+
this.__fonts = new Map();
|
|
62
|
+
this.__observer = null;
|
|
63
|
+
this.__googleFonts = jodit.getInstance(GoogleFonts);
|
|
64
|
+
this.__render();
|
|
65
|
+
if (!this.__googleFonts.fonts.size) {
|
|
66
|
+
this.__googleFonts.ready.then(() => !this.isDestructed && this.__render());
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
__render() {
|
|
70
|
+
var _a, _b;
|
|
71
|
+
const { control } = this.__button, { list = {} } = control, listed = isArray(list)
|
|
72
|
+
? list.map((key) => ({
|
|
73
|
+
value: key.toString(),
|
|
74
|
+
title: key.toString()
|
|
75
|
+
}))
|
|
76
|
+
: keys(list, false).map((key) => ({
|
|
77
|
+
value: key,
|
|
78
|
+
title: list[key].toString()
|
|
79
|
+
})), google = Array.from(this.__googleFonts.fonts.values(), (font) => ({
|
|
80
|
+
value: this.__googleFonts.value(font),
|
|
81
|
+
title: font.family,
|
|
82
|
+
font
|
|
83
|
+
})), byFamily = new Map();
|
|
84
|
+
[...google, ...listed].forEach(entry => byFamily.set(firstFamily(entry.value), entry));
|
|
85
|
+
const theme = new Map(), used = new Map();
|
|
86
|
+
// The theme's own fonts are listed too, so its body font can be chosen
|
|
87
|
+
// to take a font off
|
|
88
|
+
this.__themeFonts().forEach(fontFamily => {
|
|
89
|
+
var _a;
|
|
90
|
+
const family = firstFamily(fontFamily), title = fontFamily.split(',')[0].replace(/["']/g, '').trim(), entry = (_a = byFamily.get(family)) !== null && _a !== void 0 ? _a : (isFontName(family)
|
|
91
|
+
? { value: fontFamily, title }
|
|
92
|
+
: undefined);
|
|
93
|
+
entry && !theme.has(family) && theme.set(family, entry);
|
|
94
|
+
});
|
|
95
|
+
this.__usedFonts().forEach(fontFamily => {
|
|
96
|
+
const family = firstFamily(fontFamily), entry = byFamily.get(family);
|
|
97
|
+
entry && !theme.has(family) && used.set(family, entry);
|
|
98
|
+
});
|
|
99
|
+
const defaultEntry = listed.find(entry => entry.value === ''), current = firstFamily((_b = (_a = control.value) === null || _a === void 0 ? void 0 : _a.call(control, this.j, this.__button)) !== null && _b !== void 0 ? _b : '');
|
|
100
|
+
Dom.detach(this.container);
|
|
101
|
+
this.__fonts.clear();
|
|
102
|
+
defaultEntry && this.__append(current, [defaultEntry]);
|
|
103
|
+
this.__append(current, [...theme.values()], 'Theme fonts');
|
|
104
|
+
this.__append(current, [...used.values()], 'Used fonts');
|
|
105
|
+
this.__append(current, listed.filter(entry => entry !== defaultEntry), 'System fonts');
|
|
106
|
+
this.__append(current, google, 'Google Fonts');
|
|
107
|
+
this.__observeGoogleFonts();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The fonts the editor's styles give text and each heading
|
|
111
|
+
*/
|
|
112
|
+
__themeFonts() {
|
|
113
|
+
const { editor } = this.j, fonts = [css(editor, 'font-family').toString()];
|
|
114
|
+
HEADINGS.forEach(tag => {
|
|
115
|
+
const heading = this.j.createInside.element(tag, {
|
|
116
|
+
style: 'display: none'
|
|
117
|
+
});
|
|
118
|
+
Dom.append(editor, heading);
|
|
119
|
+
fonts.push(css(heading, 'font-family').toString());
|
|
120
|
+
Dom.safeRemove(heading);
|
|
121
|
+
});
|
|
122
|
+
return fonts;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The fonts the content sets
|
|
126
|
+
*/
|
|
127
|
+
__usedFonts() {
|
|
128
|
+
return Array.from(this.j.editor.querySelectorAll('[style*="font-family"]'), element => element.style.fontFamily);
|
|
129
|
+
}
|
|
130
|
+
__append(current, entries, heading) {
|
|
131
|
+
if (!entries.length) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const { control } = this.__button, group = this.j.c.div(this.getFullElName('group'));
|
|
135
|
+
if (heading) {
|
|
136
|
+
const title = this.j.c.div(this.getFullElName('heading'), {
|
|
137
|
+
id: `${this.getFullElName('heading')}-${uniqueUid()}`
|
|
138
|
+
});
|
|
139
|
+
title.textContent = this.i18n(heading);
|
|
140
|
+
attr(group, { role: 'group', 'aria-labelledby': title.id });
|
|
141
|
+
Dom.append(group, title);
|
|
142
|
+
}
|
|
143
|
+
entries.forEach(entry => {
|
|
144
|
+
var _a, _b;
|
|
145
|
+
const item = this.j.c.element('button', {
|
|
146
|
+
type: 'button',
|
|
147
|
+
class: this.getFullElName('item'),
|
|
148
|
+
'data-value': entry.value,
|
|
149
|
+
'aria-pressed': firstFamily(entry.value) === current
|
|
150
|
+
});
|
|
151
|
+
if (entry.font) {
|
|
152
|
+
item.textContent = entry.title;
|
|
153
|
+
this.__fonts.set(item, entry.font);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
item.innerHTML =
|
|
157
|
+
(_b = (_a = control.childTemplate) === null || _a === void 0 ? void 0 : _a.call(control, this.j, entry.value, entry.title, this.__button)) !== null && _b !== void 0 ? _b : entry.title;
|
|
158
|
+
}
|
|
159
|
+
Dom.append(group, item);
|
|
160
|
+
});
|
|
161
|
+
Dom.append(this.container, group);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Shows the names of the Google Fonts in view, and those just below it,
|
|
165
|
+
* in their own fonts. Setting every item's font up front would have the
|
|
166
|
+
* browser look for each of the library's families among the installed
|
|
167
|
+
* fonts the first time the list opens
|
|
168
|
+
*/
|
|
169
|
+
__observeGoogleFonts() {
|
|
170
|
+
this.j.async.requestAnimationFrame(() => {
|
|
171
|
+
var _a;
|
|
172
|
+
(_a = this.__observer) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
173
|
+
if (this.isDestructed || !this.__fonts.size) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const observer = new IntersectionObserver(entries => {
|
|
177
|
+
const fonts = [];
|
|
178
|
+
entries.forEach(({ isIntersecting, target }) => {
|
|
179
|
+
const font = this.__fonts.get(target);
|
|
180
|
+
if (isIntersecting && font) {
|
|
181
|
+
fonts.push(font);
|
|
182
|
+
css(target, {
|
|
183
|
+
fontFamily: this.__googleFonts.value(font)
|
|
184
|
+
});
|
|
185
|
+
observer.unobserve(target);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
this.__googleFonts.preview(fonts);
|
|
189
|
+
}, {
|
|
190
|
+
root: this.container.parentElement,
|
|
191
|
+
rootMargin: '0px 0px 400px 0px'
|
|
192
|
+
});
|
|
193
|
+
this.__fonts.forEach((_, item) => observer.observe(item));
|
|
194
|
+
this.__observer = observer;
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Keeps the editor's selection, as the toolbar buttons do
|
|
199
|
+
*/
|
|
200
|
+
onMouseDown(e) {
|
|
201
|
+
e.preventDefault();
|
|
202
|
+
}
|
|
203
|
+
onClick(e) {
|
|
204
|
+
var _a;
|
|
205
|
+
const item = Dom.up(e.target, node => Dom.isHTMLElement(node) && node.hasAttribute('data-value'), this.container);
|
|
206
|
+
if (!item) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const value = (_a = attr(item, 'data-value')) !== null && _a !== void 0 ? _a : '', font = this.__googleFonts.find(value),
|
|
210
|
+
// The font the text has anyway is taken off rather than written
|
|
211
|
+
inherited = firstFamily(value) === firstFamily(this.__blockFont());
|
|
212
|
+
font && !inherited && this.__googleFonts.load(font);
|
|
213
|
+
this.j.execCommand('fontname', false, inherited ? '' : value);
|
|
214
|
+
this.__close();
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* The font the selected text has without a font of its own: its block's
|
|
218
|
+
*/
|
|
219
|
+
__blockFont() {
|
|
220
|
+
const block = Dom.up(this.j.s.current(), Dom.isBlock, this.j.editor);
|
|
221
|
+
return css(block !== null && block !== void 0 ? block : this.j.editor, 'font-family').toString();
|
|
222
|
+
}
|
|
223
|
+
destruct() {
|
|
224
|
+
var _a;
|
|
225
|
+
(_a = this.__observer) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
226
|
+
super.destruct();
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
__decorate([
|
|
230
|
+
watch('container:mousedown')
|
|
231
|
+
], UIFontPicker.prototype, "onMouseDown", null);
|
|
232
|
+
__decorate([
|
|
233
|
+
watch('container:click')
|
|
234
|
+
], UIFontPicker.prototype, "onClick", null);
|
|
235
|
+
UIFontPicker = __decorate([
|
|
236
|
+
component
|
|
237
|
+
], UIFontPicker);
|
|
238
|
+
export { UIFontPicker };
|
package/esm/plugins/font/font.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { pluginSystem } from "../../core/global.js";
|
|
7
7
|
import { normalizeSize } from "../../core/helpers/index.js";
|
|
8
8
|
import "./config.js";
|
|
9
|
+
import { GoogleFonts } from "./google-fonts.js";
|
|
9
10
|
/**
|
|
10
11
|
* Process commands `fontsize` and `fontname`
|
|
11
12
|
*/
|
|
@@ -19,6 +20,17 @@ export function font(editor) {
|
|
|
19
20
|
name: 'fontsize',
|
|
20
21
|
group: 'font'
|
|
21
22
|
});
|
|
23
|
+
if (editor.o.font.googleFonts.url) {
|
|
24
|
+
const googleFonts = editor.getInstance(GoogleFonts), loadUsed = editor.async.debounce(() => googleFonts.loadUsed(), editor.defaultTimeout);
|
|
25
|
+
googleFonts.ready.then(loadUsed);
|
|
26
|
+
editor.e.on('afterInit afterSetMode change', loadUsed);
|
|
27
|
+
}
|
|
28
|
+
// An iframe's stylesheets can arrive after the toolbar first shows the
|
|
29
|
+
// editor's font
|
|
30
|
+
editor.e.on('afterInit', () => {
|
|
31
|
+
editor.iframe &&
|
|
32
|
+
editor.e.on(editor.ed, 'load', () => editor.e.fire('updateToolbar'), { capture: true });
|
|
33
|
+
});
|
|
22
34
|
const callback = (command, second, third) => {
|
|
23
35
|
switch (command) {
|
|
24
36
|
case 'fontsize':
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @module plugins/font
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit } from "../../types/index";
|
|
10
|
+
import { ViewComponent } from "../../core/component/view-component";
|
|
11
|
+
/**
|
|
12
|
+
* A font as the Google Fonts Developer API describes it
|
|
13
|
+
*/
|
|
14
|
+
export interface IGoogleFont {
|
|
15
|
+
family: string;
|
|
16
|
+
category: string;
|
|
17
|
+
variants: string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The first family of a `font-family` value, unquoted and in lower case for
|
|
21
|
+
* comparing
|
|
22
|
+
*/
|
|
23
|
+
export declare function firstFamily(fontFamily: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Loads fonts from Google Fonts: the whole of each font the content uses into
|
|
26
|
+
* the editor's document, and just the letters of its name for the font list
|
|
27
|
+
*/
|
|
28
|
+
export declare class GoogleFonts extends ViewComponent<IJodit> {
|
|
29
|
+
className(): string;
|
|
30
|
+
/**
|
|
31
|
+
* The library by lower-case family, empty until it arrives
|
|
32
|
+
*/
|
|
33
|
+
readonly fonts: Map<string, IGoogleFont>;
|
|
34
|
+
readonly ready: Promise<void>;
|
|
35
|
+
private readonly __links;
|
|
36
|
+
private readonly __loaded;
|
|
37
|
+
private readonly __previewed;
|
|
38
|
+
constructor(jodit: IJodit);
|
|
39
|
+
/**
|
|
40
|
+
* The library's font named first in a `font-family` value
|
|
41
|
+
*/
|
|
42
|
+
find(fontFamily: string): IGoogleFont | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* The `font-family` value that applies a font
|
|
45
|
+
*/
|
|
46
|
+
value(font: IGoogleFont): string;
|
|
47
|
+
/**
|
|
48
|
+
* Loads the regular, italic, bold and bold italic styles that a font has
|
|
49
|
+
* into the editor's document
|
|
50
|
+
*/
|
|
51
|
+
load(font: IGoogleFont): void;
|
|
52
|
+
/**
|
|
53
|
+
* Loads every font of the library that the content uses
|
|
54
|
+
*/
|
|
55
|
+
loadUsed(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Loads into the page just the letters of each font's name, so the font
|
|
58
|
+
* list can show the name in its font
|
|
59
|
+
*/
|
|
60
|
+
preview(fonts: IGoogleFont[]): void;
|
|
61
|
+
private __loadedInto;
|
|
62
|
+
private __family;
|
|
63
|
+
private __append;
|
|
64
|
+
destruct(): void;
|
|
65
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
import { ViewComponent } from "../../core/component/view-component.js";
|
|
7
|
+
import { Dom } from "../../core/dom/dom.js";
|
|
8
|
+
import { Ajax } from "../../core/request/ajax.js";
|
|
9
|
+
const CSS_URL = 'https://fonts.googleapis.com/css2';
|
|
10
|
+
// `cursive` and `fantasy` stand in badly for a handwriting or display font
|
|
11
|
+
const GENERIC_FAMILIES = {
|
|
12
|
+
serif: 'serif',
|
|
13
|
+
monospace: 'monospace'
|
|
14
|
+
};
|
|
15
|
+
const libraries = new Map();
|
|
16
|
+
/**
|
|
17
|
+
* The fonts of the library at `url`, fetched once for every editor on the page
|
|
18
|
+
*/
|
|
19
|
+
function library(jodit, url) {
|
|
20
|
+
let fonts = libraries.get(url);
|
|
21
|
+
if (!fonts) {
|
|
22
|
+
const ajax = new Ajax({ url, method: 'GET' }, jodit.o.defaultAjaxOptions);
|
|
23
|
+
fonts = ajax
|
|
24
|
+
.send()
|
|
25
|
+
.then(response => response.json())
|
|
26
|
+
// A font without a regular style can't be asked for by its name alone
|
|
27
|
+
.then(({ items }) => items.filter(font => font.variants.includes('regular')))
|
|
28
|
+
.catch(() => {
|
|
29
|
+
libraries.delete(url);
|
|
30
|
+
return [];
|
|
31
|
+
})
|
|
32
|
+
.finally(() => ajax.destruct());
|
|
33
|
+
libraries.set(url, fonts);
|
|
34
|
+
}
|
|
35
|
+
return fonts;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The first family of a `font-family` value, unquoted and in lower case for
|
|
39
|
+
* comparing
|
|
40
|
+
*/
|
|
41
|
+
export function firstFamily(fontFamily) {
|
|
42
|
+
return fontFamily.split(',')[0].replace(/["']/g, '').trim().toLowerCase();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Loads fonts from Google Fonts: the whole of each font the content uses into
|
|
46
|
+
* the editor's document, and just the letters of its name for the font list
|
|
47
|
+
*/
|
|
48
|
+
export class GoogleFonts extends ViewComponent {
|
|
49
|
+
className() {
|
|
50
|
+
return 'GoogleFonts';
|
|
51
|
+
}
|
|
52
|
+
constructor(jodit) {
|
|
53
|
+
super(jodit);
|
|
54
|
+
/**
|
|
55
|
+
* The library by lower-case family, empty until it arrives
|
|
56
|
+
*/
|
|
57
|
+
this.fonts = new Map();
|
|
58
|
+
this.__links = [];
|
|
59
|
+
this.__loaded = new WeakMap();
|
|
60
|
+
this.__previewed = new Set();
|
|
61
|
+
this.ready = library(jodit, jodit.o.font.googleFonts.url).then(fonts => {
|
|
62
|
+
fonts.forEach(font => this.fonts.set(font.family.toLowerCase(), font));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The library's font named first in a `font-family` value
|
|
67
|
+
*/
|
|
68
|
+
find(fontFamily) {
|
|
69
|
+
return this.fonts.get(firstFamily(fontFamily));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The `font-family` value that applies a font
|
|
73
|
+
*/
|
|
74
|
+
value(font) {
|
|
75
|
+
var _a;
|
|
76
|
+
return `'${font.family}', ${(_a = GENERIC_FAMILIES[font.category]) !== null && _a !== void 0 ? _a : 'sans-serif'}`;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Loads the regular, italic, bold and bold italic styles that a font has
|
|
80
|
+
* into the editor's document
|
|
81
|
+
*/
|
|
82
|
+
load(font) {
|
|
83
|
+
const loaded = this.__loadedInto(this.j.ed);
|
|
84
|
+
if (loaded.has(font.family)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
loaded.add(font.family);
|
|
88
|
+
const styles = [
|
|
89
|
+
['regular', '0,400'],
|
|
90
|
+
['700', '0,700'],
|
|
91
|
+
['italic', '1,400'],
|
|
92
|
+
['700italic', '1,700']
|
|
93
|
+
]
|
|
94
|
+
.filter(([variant]) => font.variants.includes(variant))
|
|
95
|
+
.map(([, style]) => style);
|
|
96
|
+
this.__append(this.j.ed, `family=${this.__family(font)}:ital,wght@${styles.join(';')}`);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Loads every font of the library that the content uses
|
|
100
|
+
*/
|
|
101
|
+
loadUsed() {
|
|
102
|
+
this.j.editor
|
|
103
|
+
.querySelectorAll('[style*="font-family"]')
|
|
104
|
+
.forEach(element => {
|
|
105
|
+
const font = this.find(element.style.fontFamily);
|
|
106
|
+
font && this.load(font);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Loads into the page just the letters of each font's name, so the font
|
|
111
|
+
* list can show the name in its font
|
|
112
|
+
*/
|
|
113
|
+
preview(fonts) {
|
|
114
|
+
const loaded = this.__loadedInto(this.j.od);
|
|
115
|
+
fonts = fonts.filter(font => !this.__previewed.has(font.family) && !loaded.has(font.family));
|
|
116
|
+
if (!fonts.length) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
fonts.forEach(font => this.__previewed.add(font.family));
|
|
120
|
+
const families = fonts.map(font => `family=${this.__family(font)}`), letters = new Set(fonts.map(font => font.family).join(''));
|
|
121
|
+
this.__append(this.j.od, `${families.join('&')}&text=${encodeURIComponent([...letters].join(''))}`);
|
|
122
|
+
}
|
|
123
|
+
__loadedInto(doc) {
|
|
124
|
+
var _a;
|
|
125
|
+
const loaded = (_a = this.__loaded.get(doc)) !== null && _a !== void 0 ? _a : new Set();
|
|
126
|
+
this.__loaded.set(doc, loaded);
|
|
127
|
+
return loaded;
|
|
128
|
+
}
|
|
129
|
+
__family(font) {
|
|
130
|
+
return encodeURIComponent(font.family).replace(/%20/g, '+');
|
|
131
|
+
}
|
|
132
|
+
__append(doc, query) {
|
|
133
|
+
const link = doc.createElement('link');
|
|
134
|
+
link.rel = 'stylesheet';
|
|
135
|
+
link.href = `${CSS_URL}?${query}&display=swap`;
|
|
136
|
+
doc.head.appendChild(link);
|
|
137
|
+
this.__links.push(link);
|
|
138
|
+
}
|
|
139
|
+
destruct() {
|
|
140
|
+
this.__links.forEach(link => Dom.safeRemove(link));
|
|
141
|
+
super.destruct();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
|
+
import { getAlignClasses } from "../../../core/helpers/utils/align.js";
|
|
6
7
|
import { attr } from "../../../core/helpers/utils/attr.js";
|
|
7
8
|
import { cssInline } from "../../../core/helpers/utils/css.js";
|
|
8
9
|
import { readAlign } from "./align.js";
|
|
@@ -15,7 +16,7 @@ import { readSizes } from "./size.js";
|
|
|
15
16
|
*/
|
|
16
17
|
export async function readValuesFromImage(j, state) {
|
|
17
18
|
const { sourceImage: image, values } = state;
|
|
18
|
-
readAlign(image, values, j
|
|
19
|
+
readAlign(image, values, getAlignClasses(j, image));
|
|
19
20
|
// Border radius
|
|
20
21
|
values.borderRadius =
|
|
21
22
|
parseInt(cssInline(image, 'border-radius') || '0', 10) || 0;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
6
|
import { Dom } from "../../../core/dom/dom.js";
|
|
7
|
-
import { attr, hAlignElement } from "../../../core/helpers/utils/index.js";
|
|
7
|
+
import { attr, getAlignClasses, hAlignElement } from "../../../core/helpers/utils/index.js";
|
|
8
8
|
import { css } from "../../../core/helpers/utils/css.js";
|
|
9
9
|
import { applyLink } from "./link.js";
|
|
10
10
|
import { applyMargin } from "./margin.js";
|
|
@@ -49,6 +49,6 @@ export function applyValuesToImage(j, state, image) {
|
|
|
49
49
|
attr(image, 'id', id || null);
|
|
50
50
|
}
|
|
51
51
|
if (opt.image.editAlign) {
|
|
52
|
-
hAlignElement(image, align, j
|
|
52
|
+
hAlignElement(image, align, getAlignClasses(j, image));
|
|
53
53
|
}
|
|
54
54
|
}
|