@chenyomi/leafer-htmltext-editor 1.0.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/LICENSE +21 -0
- package/README.md +177 -0
- package/dist/TextEditTool/index.d.ts +17 -0
- package/dist/TextEditTool/index.d.ts.map +1 -0
- package/dist/TextEditTool/index.js +138 -0
- package/dist/TextEditTool/utils.d.ts +8 -0
- package/dist/TextEditTool/utils.d.ts.map +1 -0
- package/dist/TextEditTool/utils.js +173 -0
- package/dist/TextEditor.d.ts +27 -0
- package/dist/TextEditor.d.ts.map +1 -0
- package/dist/TextEditor.js +166 -0
- package/dist/esm/TextEditTool/index.d.ts +17 -0
- package/dist/esm/TextEditTool/index.d.ts.map +1 -0
- package/dist/esm/TextEditTool/index.js +135 -0
- package/dist/esm/TextEditTool/utils.d.ts +8 -0
- package/dist/esm/TextEditTool/utils.d.ts.map +1 -0
- package/dist/esm/TextEditTool/utils.js +165 -0
- package/dist/esm/TextEditor.d.ts +27 -0
- package/dist/esm/TextEditor.d.ts.map +1 -0
- package/dist/esm/TextEditor.js +163 -0
- package/dist/esm/fonts/font.d.ts +17 -0
- package/dist/esm/fonts/font.d.ts.map +1 -0
- package/dist/esm/fonts/font.js +68 -0
- package/dist/esm/fonts/utils.d.ts +9 -0
- package/dist/esm/fonts/utils.d.ts.map +1 -0
- package/dist/esm/fonts/utils.js +170 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/utils.d.ts +3 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/dist/esm/utils.js +284 -0
- package/dist/fonts/font.d.ts +17 -0
- package/dist/fonts/font.d.ts.map +1 -0
- package/dist/fonts/font.js +72 -0
- package/dist/fonts/utils.d.ts +9 -0
- package/dist/fonts/utils.d.ts.map +1 -0
- package/dist/fonts/utils.js +180 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +79 -0
- package/dist/index.js +92 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +289 -0
- package/package.json +55 -0
- package/src/TextEditTool/index.ts +145 -0
- package/src/TextEditTool/utils.ts +216 -0
- package/src/TextEditor.ts +200 -0
- package/src/fonts/font.ts +86 -0
- package/src/fonts/utils.ts +232 -0
- package/src/index.ts +92 -0
- package/src/utils.ts +331 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var TextEditor_1;
|
|
8
|
+
import { Matrix, PointerEvent } from "@leafer-ui/core";
|
|
9
|
+
import { InnerEditor, registerInnerEditor } from "@leafer-in/editor";
|
|
10
|
+
import { updataHtmlText } from "./utils";
|
|
11
|
+
let TextEditor = TextEditor_1 = class TextEditor extends InnerEditor {
|
|
12
|
+
constructor() {
|
|
13
|
+
super(...arguments);
|
|
14
|
+
this.config = {
|
|
15
|
+
selectAll: false,
|
|
16
|
+
};
|
|
17
|
+
this.eventIds = [];
|
|
18
|
+
this.onSelectionChange = async (e) => {
|
|
19
|
+
e && localStorage.setItem("selection-change", JSON.stringify(e));
|
|
20
|
+
};
|
|
21
|
+
this.onInput = async () => {
|
|
22
|
+
updataHtmlText(this.editTarget);
|
|
23
|
+
};
|
|
24
|
+
this.isUpdatingPoints = false;
|
|
25
|
+
}
|
|
26
|
+
get tag() {
|
|
27
|
+
return "TextEditor";
|
|
28
|
+
}
|
|
29
|
+
onLoad() {
|
|
30
|
+
const { editor } = this;
|
|
31
|
+
const { config } = editor.app;
|
|
32
|
+
const text = this.editTarget;
|
|
33
|
+
const { scaleX, scaleY } = text.worldTransform;
|
|
34
|
+
const zoomScale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
|
|
35
|
+
this.quill = TextEditor_1.quill;
|
|
36
|
+
this.isHTMLText = !(text instanceof Text);
|
|
37
|
+
config.keyEvent = false;
|
|
38
|
+
const element = document.querySelector("#textInnerEditor");
|
|
39
|
+
if (!element || !(element instanceof HTMLDivElement)) {
|
|
40
|
+
console.error("Cannot find #textInnerEditor element or it's not a div");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const div = (this.editDom = element);
|
|
44
|
+
const { style } = div;
|
|
45
|
+
style.visibility = "visible";
|
|
46
|
+
if (text.data?.canChangeBox &&
|
|
47
|
+
text.parent?.width !== undefined &&
|
|
48
|
+
text.parent?.height !== undefined) {
|
|
49
|
+
style.width = text.parent.width * zoomScale + "px";
|
|
50
|
+
style.height = text.parent.height * zoomScale + "px";
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
style.width = "auto";
|
|
54
|
+
style.height = "auto";
|
|
55
|
+
}
|
|
56
|
+
style.outline = "solid #8499EF";
|
|
57
|
+
if (text.data?.textData?.fontSize) {
|
|
58
|
+
div.style.fontSize = `${text.data.textData.fontSize * zoomScale}px`;
|
|
59
|
+
}
|
|
60
|
+
if (text.data?.textData?.fontFamily) {
|
|
61
|
+
div.style.fontFamily = `${text.data.textData.fontFamily}`;
|
|
62
|
+
}
|
|
63
|
+
if (text.data?.textData?.lineHeight) {
|
|
64
|
+
div.style.lineHeight = text.data.textData.lineHeight;
|
|
65
|
+
}
|
|
66
|
+
if (text.data?.textData?.letterSpacing) {
|
|
67
|
+
div.style.letterSpacing = `${text.data.textData.letterSpacing}px`;
|
|
68
|
+
}
|
|
69
|
+
if (text.data?.textData?.textShadow) {
|
|
70
|
+
div.style.textShadow = `${text.data.textData.textShadow}`;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
div.style.textShadow = "none";
|
|
74
|
+
}
|
|
75
|
+
if (text.data?.textData?.alignContent) {
|
|
76
|
+
const qlEditor = div.querySelector(".ql-editor");
|
|
77
|
+
if (qlEditor) {
|
|
78
|
+
qlEditor.style.alignContent = `${text.data.textData.alignContent}`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (this.quill) {
|
|
82
|
+
this.quill.clipboard.dangerouslyPasteHTML(text.text);
|
|
83
|
+
if (text.parent?.children?.[0]?.tag?.includes("Shape")) {
|
|
84
|
+
const parentWidth = text.parent.width;
|
|
85
|
+
if (parentWidth !== undefined) {
|
|
86
|
+
style.width = parentWidth * zoomScale + "px";
|
|
87
|
+
style.left = "0px";
|
|
88
|
+
}
|
|
89
|
+
this.quill.formatLine(0, this.quill.getLength(), "align", "center");
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.quill.setSelection(0, this.quill.getLength() - 1);
|
|
93
|
+
}
|
|
94
|
+
this.quill.on("text-change", this.onInput);
|
|
95
|
+
this.quill.on("selection-change", this.onSelectionChange);
|
|
96
|
+
}
|
|
97
|
+
localStorage.removeItem("selection-change");
|
|
98
|
+
this.eventIds = [
|
|
99
|
+
editor.app.on_(PointerEvent.DOWN, (e) => {
|
|
100
|
+
let { target } = e.origin;
|
|
101
|
+
let find = false;
|
|
102
|
+
while (target) {
|
|
103
|
+
if (target === div)
|
|
104
|
+
find = true;
|
|
105
|
+
target = target.parentElement;
|
|
106
|
+
}
|
|
107
|
+
if (!find) {
|
|
108
|
+
editor.closeInnerEditor();
|
|
109
|
+
editor.cancel();
|
|
110
|
+
}
|
|
111
|
+
}),
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
onUpdate() {
|
|
115
|
+
const { editTarget: text } = this;
|
|
116
|
+
if (!text.parent?.__local)
|
|
117
|
+
return;
|
|
118
|
+
const { scaleX, scaleY } = text.worldTransform;
|
|
119
|
+
const zoomScale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
|
|
120
|
+
const local = text.parent.__local;
|
|
121
|
+
let width = local.width || 0;
|
|
122
|
+
let height = local.height || 0;
|
|
123
|
+
width *= zoomScale;
|
|
124
|
+
height *= zoomScale;
|
|
125
|
+
const { x, y } = this.inBody
|
|
126
|
+
? text.app.clientBounds
|
|
127
|
+
: (text.app.tree?.clientBounds || { x: 0, y: 0 });
|
|
128
|
+
const { a, b, c, d, e, f } = new Matrix(text.worldTransform)
|
|
129
|
+
.scale(1 / zoomScale)
|
|
130
|
+
.translateInner(0, 0);
|
|
131
|
+
if (this.editDom) {
|
|
132
|
+
const { style } = this.editDom;
|
|
133
|
+
style.transform = `matrix(${a},${b},${c},${d},${e},${f})`;
|
|
134
|
+
style.left = x + "px";
|
|
135
|
+
style.top = y + "px";
|
|
136
|
+
}
|
|
137
|
+
text.set({
|
|
138
|
+
visible: false,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
onUnload() {
|
|
142
|
+
const { editTarget: text, editor, editDom: dom } = this;
|
|
143
|
+
if (text) {
|
|
144
|
+
this.onInput();
|
|
145
|
+
editor.off_(this.eventIds);
|
|
146
|
+
if (this.editDom) {
|
|
147
|
+
this.editDom.style.visibility = "hidden";
|
|
148
|
+
}
|
|
149
|
+
this.eventIds = [];
|
|
150
|
+
}
|
|
151
|
+
text.set({
|
|
152
|
+
visible: true,
|
|
153
|
+
});
|
|
154
|
+
if (this.quill) {
|
|
155
|
+
this.quill.off("text-change", this.onInput);
|
|
156
|
+
this.quill.off("selection-change", this.onSelectionChange);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
TextEditor = TextEditor_1 = __decorate([
|
|
161
|
+
registerInnerEditor()
|
|
162
|
+
], TextEditor);
|
|
163
|
+
export { TextEditor };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const defaultFonts: {
|
|
2
|
+
code: string;
|
|
3
|
+
name: string;
|
|
4
|
+
url: string;
|
|
5
|
+
}[];
|
|
6
|
+
export declare class FontManager {
|
|
7
|
+
private fontList;
|
|
8
|
+
private skipLoadFonts;
|
|
9
|
+
private loadFonts;
|
|
10
|
+
constructor();
|
|
11
|
+
initFonts(): Promise<any[]>;
|
|
12
|
+
getFontList(): any[];
|
|
13
|
+
getSkipLoadFonts(): any[];
|
|
14
|
+
getLoadFonts(): any[];
|
|
15
|
+
}
|
|
16
|
+
export declare const fontManager: FontManager;
|
|
17
|
+
//# sourceMappingURL=font.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font.d.ts","sourceRoot":"","sources":["../../../src/fonts/font.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;;;;GA2BxB,CAAC;AAMF,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,aAAa,CAAkD;IACvE,OAAO,CAAC,SAAS,CAAuB;;IASlC,SAAS;IA0Bf,WAAW;IAIX,gBAAgB;IAIhB,YAAY;CAGb;AAGD,eAAO,MAAM,WAAW,aAAoB,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export const defaultFonts = [
|
|
2
|
+
{ code: 'Roboto', name: `"Roboto", sans-serif`, url: '/fonts/Roboto.woff2' },
|
|
3
|
+
{ code: 'Roboto Mono', name: `"Roboto Mono", monospace`, url: '/fonts/RobotoMono.woff2' },
|
|
4
|
+
{ code: 'Inter', name: `"Inter", sans-serif`, url: '/fonts/Inter.woff2' },
|
|
5
|
+
{ code: 'Open Sans', name: `"Open Sans", sans-serif`, url: '/fonts/OpenSans.woff2' },
|
|
6
|
+
{ code: 'Montserrat', name: `"Montserrat", sans-serif`, url: '/fonts/Montserrat.woff2' },
|
|
7
|
+
{ code: 'Roboto Condensed', name: `"Roboto Condensed", sans-serif`, url: '/fonts/RobotoCondensed.woff2' },
|
|
8
|
+
{ code: 'Arimo', name: `"Arimo", sans-serif`, url: '/fonts/Arimo.woff2' },
|
|
9
|
+
{ code: 'Noto Sans', name: `"Noto Sans", sans-serif`, url: '/fonts/NotoSans.woff2' },
|
|
10
|
+
{ code: 'Noto Sans Symbols', name: `"Noto Sans Symbols", sans-serif`, url: '/fonts/NotoSansSymbols.woff2' },
|
|
11
|
+
{ code: 'Merriweather', name: `"Merriweather", serif`, url: '/fonts/Merriweather.woff2' },
|
|
12
|
+
{ code: 'Playfair Display', name: `"Playfair Display", serif`, url: '/fonts/PlayfairDisplay.woff2' },
|
|
13
|
+
{ code: 'Noto Serif', name: `"Noto Serif", serif`, url: '/fonts/NotoSerif.woff2' },
|
|
14
|
+
{ code: 'Lato', name: `"Lato", sans-serif`, url: '/fonts/Lato.woff2' },
|
|
15
|
+
{ code: 'Spectral', name: `"Spectral", serif`, url: '/fonts/Spectral.woff2' },
|
|
16
|
+
{ code: 'Dancing Script', name: `"Dancing Script", cursive`, url: '/fonts/DancingScript.woff2' },
|
|
17
|
+
{ code: 'Noto Sans Simplified Chinese', name: `"Noto Sans SC", sans-serif`, url: '/fonts/NotoSansSimplifiedChinese.woff2' },
|
|
18
|
+
{ code: 'Noto Serif Simplified Chinese', name: `"Noto Serif SC", serif`, url: '/fonts/NotoSerifSimplifiedChinese.woff2' },
|
|
19
|
+
{ code: 'Noto Sans Traditional Chinese', name: `"Noto Sans TC", sans-serif`, url: '/fonts/NotoSansTraditionalChinese.woff2' },
|
|
20
|
+
{ code: 'Noto Sans Hong Kong', name: `"Noto Sans HK", sans-serif`, url: '/fonts/NotoSansHongKong.woff2' },
|
|
21
|
+
{ code: 'Noto Serif Traditional Chinese', name: `"Noto Serif TC", serif`, url: '/fonts/NotoSerifTraditionalChinese.woff2' },
|
|
22
|
+
{ code: 'Noto Serif Hong Kong', name: `"Noto Serif HK", serif`, url: '/fonts/NotoSerifHongKong.woff2' },
|
|
23
|
+
{ code: 'Noto Sans Japanese', name: `"Noto Sans JP", sans-serif`, url: '/fonts/NotoSansJapanese.woff2' },
|
|
24
|
+
{ code: 'Noto Sans Korean', name: `"Noto Sans KR", sans-serif`, url: '/fonts/NotoSansKorean.woff2' },
|
|
25
|
+
{ code: 'Poppins', name: `"Poppins", sans-serif`, url: '/fonts/Poppins.woff2' }
|
|
26
|
+
];
|
|
27
|
+
const FONT_KEY = 'OPEN_FONTS';
|
|
28
|
+
const FONT_VERSION_KEY = 'OPEN_FONTS_VERSION';
|
|
29
|
+
export class FontManager {
|
|
30
|
+
constructor() {
|
|
31
|
+
this.fontList = [];
|
|
32
|
+
this.skipLoadFonts = defaultFonts.map((value) => value.name);
|
|
33
|
+
this.loadFonts = defaultFonts;
|
|
34
|
+
this.initFonts();
|
|
35
|
+
}
|
|
36
|
+
async initFonts() {
|
|
37
|
+
let list = [];
|
|
38
|
+
if (typeof localStorage !== 'undefined') {
|
|
39
|
+
if (localStorage.getItem(FONT_VERSION_KEY) !== '1') {
|
|
40
|
+
localStorage.removeItem(FONT_KEY);
|
|
41
|
+
}
|
|
42
|
+
let localFonts = [];
|
|
43
|
+
try {
|
|
44
|
+
const storedFonts = localStorage.getItem(FONT_KEY);
|
|
45
|
+
localFonts = storedFonts ? JSON.parse(storedFonts) : [];
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
localFonts = [];
|
|
49
|
+
localStorage.removeItem(FONT_KEY);
|
|
50
|
+
}
|
|
51
|
+
if (localFonts.length > 0) {
|
|
52
|
+
list.push(...localFonts);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
this.fontList = defaultFonts.concat(list);
|
|
56
|
+
return list;
|
|
57
|
+
}
|
|
58
|
+
getFontList() {
|
|
59
|
+
return this.fontList;
|
|
60
|
+
}
|
|
61
|
+
getSkipLoadFonts() {
|
|
62
|
+
return this.skipLoadFonts;
|
|
63
|
+
}
|
|
64
|
+
getLoadFonts() {
|
|
65
|
+
return this.loadFonts;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export const fontManager = new FontManager();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function fetchFontAsBase64(url: string): Promise<string>;
|
|
2
|
+
export declare function addCustomFonts(fontList?: any): void;
|
|
3
|
+
export declare function getCustomFontsStyle(): string;
|
|
4
|
+
export declare function addCustomFont(font: any): void;
|
|
5
|
+
export declare function batchLoadFont(fontNameList?: any): Promise<void>;
|
|
6
|
+
export declare function addCustomFontBase64(font: any): Promise<void>;
|
|
7
|
+
export declare function getBase64CustomFontsStyle(): string;
|
|
8
|
+
export declare function loadFont(font: string): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/fonts/utils.ts"],"names":[],"mappings":"AAGA,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsCpE;AAgBD,wBAAgB,cAAc,CAAC,QAAQ,GAAE,GAAQ,QAShD;AAKD,wBAAgB,mBAAmB,WAGlC;AAMD,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,QAgCtC;AAMD,wBAAsB,aAAa,CAAC,YAAY,GAAE,GAAQ,iBAUzD;AAyCD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,GAAG,iBA6ClD;AAKD,wBAAgB,yBAAyB,WAGxC;AAOD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
const FONT_CSS_TAG = "data-fonts";
|
|
2
|
+
const FONT_CSS_TAG_BASE64 = "base64-fonts";
|
|
3
|
+
export async function fetchFontAsBase64(url) {
|
|
4
|
+
const response = await fetch(url);
|
|
5
|
+
if (!response.ok) {
|
|
6
|
+
throw new Error(`Failed to fetch font from ${url}`);
|
|
7
|
+
}
|
|
8
|
+
const contentType = response.headers.get('Content-Type');
|
|
9
|
+
let mimeType;
|
|
10
|
+
if (contentType?.includes('font/woff2')) {
|
|
11
|
+
mimeType = 'font/woff2';
|
|
12
|
+
}
|
|
13
|
+
else if (contentType?.includes('font/woff')) {
|
|
14
|
+
mimeType = 'font/woff';
|
|
15
|
+
}
|
|
16
|
+
else if (contentType?.includes('font/ttf') || contentType?.includes('font/sfnt')) {
|
|
17
|
+
mimeType = 'font/ttf';
|
|
18
|
+
}
|
|
19
|
+
else if (contentType?.includes('application/octet-stream')) {
|
|
20
|
+
const extension = url.split('.').pop()?.toLowerCase();
|
|
21
|
+
if (extension === 'woff2') {
|
|
22
|
+
mimeType = 'font/woff2';
|
|
23
|
+
}
|
|
24
|
+
else if (extension === 'woff') {
|
|
25
|
+
mimeType = 'font/woff';
|
|
26
|
+
}
|
|
27
|
+
else if (extension === 'ttf') {
|
|
28
|
+
mimeType = 'font/ttf';
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
throw new Error(`Unsupported font file type: ${extension}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw new Error(`Unsupported Content-Type: ${contentType}`);
|
|
36
|
+
}
|
|
37
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
38
|
+
const base64String = arrayBufferToBase64(arrayBuffer);
|
|
39
|
+
return `data:${mimeType};charset=utf-8;base64,${base64String}`;
|
|
40
|
+
}
|
|
41
|
+
function arrayBufferToBase64(buffer) {
|
|
42
|
+
let binary = '';
|
|
43
|
+
const bytes = new Uint8Array(buffer);
|
|
44
|
+
const len = bytes.byteLength;
|
|
45
|
+
for (let i = 0; i < len; i++) {
|
|
46
|
+
binary += String.fromCharCode(bytes[i]);
|
|
47
|
+
}
|
|
48
|
+
return window.btoa(binary);
|
|
49
|
+
}
|
|
50
|
+
export function addCustomFonts(fontList = []) {
|
|
51
|
+
let styleTag = document.createElement('style');
|
|
52
|
+
styleTag.setAttribute(FONT_CSS_TAG, 'true');
|
|
53
|
+
let fontRules = fontList.map((font) => `@font-face {
|
|
54
|
+
font-family: "${font.name}";
|
|
55
|
+
src: local("${font.name}"), url("${font.download}")
|
|
56
|
+
}`).join('\n');
|
|
57
|
+
styleTag.textContent = fontRules;
|
|
58
|
+
document.head.appendChild(styleTag);
|
|
59
|
+
}
|
|
60
|
+
export function getCustomFontsStyle() {
|
|
61
|
+
const styleTag = document.querySelector('style[data-fonts]');
|
|
62
|
+
return styleTag?.textContent || '';
|
|
63
|
+
}
|
|
64
|
+
export function addCustomFont(font) {
|
|
65
|
+
let styleTag = document.querySelector('style[data-fonts]');
|
|
66
|
+
if (!styleTag) {
|
|
67
|
+
styleTag = document.createElement('style');
|
|
68
|
+
styleTag.setAttribute(FONT_CSS_TAG, 'true');
|
|
69
|
+
document.head.appendChild(styleTag);
|
|
70
|
+
}
|
|
71
|
+
if (!styleTag.sheet)
|
|
72
|
+
return;
|
|
73
|
+
let existingFonts = [];
|
|
74
|
+
existingFonts = Array.from(styleTag.sheet.cssRules).map((rule) => {
|
|
75
|
+
const match = rule.cssText.match(/font-family: "([^"]+)"/);
|
|
76
|
+
return match ? match[1] : null;
|
|
77
|
+
}).filter((font) => font !== null);
|
|
78
|
+
if (!existingFonts.includes(font.name)) {
|
|
79
|
+
const newFontRule = `@font-face {
|
|
80
|
+
font-family: "${font.name}";
|
|
81
|
+
src: url("${font.download}");
|
|
82
|
+
}`;
|
|
83
|
+
try {
|
|
84
|
+
styleTag.sheet.insertRule(newFontRule, styleTag.sheet.cssRules.length);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
console.error('Failed to insert font rule:', e);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export async function batchLoadFont(fontNameList = []) {
|
|
92
|
+
try {
|
|
93
|
+
for (const fontFamily of fontNameList) {
|
|
94
|
+
await document.fonts.load(`16px ${fontFamily}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
console.warn('Font loading failed:', e);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function getFontUrlFromCSS(selectors, fontFamilyName) {
|
|
102
|
+
const styleTags = document.querySelectorAll(selectors);
|
|
103
|
+
for (let i = 0; i < styleTags.length; i++) {
|
|
104
|
+
const styleTag = styleTags[i];
|
|
105
|
+
const cssText = styleTag.textContent || '';
|
|
106
|
+
const fontFaceRules = cssText.match(/@font-face\s*\{[^}]+\}/g);
|
|
107
|
+
if (fontFaceRules) {
|
|
108
|
+
for (const rule of fontFaceRules) {
|
|
109
|
+
const fontFamilyMatch = rule.match(/font-family:\s*(["'])(.*?)\1/);
|
|
110
|
+
if (fontFamilyMatch && fontFamilyMatch[2] === fontFamilyName) {
|
|
111
|
+
const srcMatch = rule.match(/src:\s*url\((["'])(.*?)\1\)/);
|
|
112
|
+
if (srcMatch) {
|
|
113
|
+
return srcMatch[2];
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
const srcMatch2 = rule.match(/src:\s*(?:local\([^)]+\)\s*,\s*)?url\((["'])(.*?)\1\)/);
|
|
117
|
+
if (srcMatch2) {
|
|
118
|
+
return srcMatch2[2];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
export async function addCustomFontBase64(font) {
|
|
128
|
+
const fontUrl = getFontUrlFromCSS(`style[${FONT_CSS_TAG}]`, font);
|
|
129
|
+
if (!fontUrl) {
|
|
130
|
+
console.warn('Font URL not found for:', font);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
console.log('fontUrl=', fontUrl);
|
|
134
|
+
let styleTag = document.querySelector(`style[${FONT_CSS_TAG_BASE64}]`);
|
|
135
|
+
if (!styleTag) {
|
|
136
|
+
styleTag = document.createElement('style');
|
|
137
|
+
styleTag.setAttribute(FONT_CSS_TAG_BASE64, 'true');
|
|
138
|
+
document.head.appendChild(styleTag);
|
|
139
|
+
}
|
|
140
|
+
if (!styleTag.sheet) {
|
|
141
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
142
|
+
}
|
|
143
|
+
if (!styleTag.sheet)
|
|
144
|
+
return;
|
|
145
|
+
let existingFonts = Array.from(styleTag.sheet.cssRules).map((rule) => {
|
|
146
|
+
const match = rule.cssText.match(/font-family: "([^"]+)"/);
|
|
147
|
+
return match ? match[1] : null;
|
|
148
|
+
}).filter((font) => font !== null);
|
|
149
|
+
if (!existingFonts.includes(font)) {
|
|
150
|
+
const base64Url = await fetchFontAsBase64(fontUrl);
|
|
151
|
+
const newFontRule = `@font-face {
|
|
152
|
+
font-family: "${font}";
|
|
153
|
+
src: local("${font}"), url("${base64Url}");
|
|
154
|
+
}`;
|
|
155
|
+
try {
|
|
156
|
+
styleTag.sheet.insertRule(newFontRule, styleTag.sheet.cssRules.length);
|
|
157
|
+
styleTag.textContent += newFontRule;
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
console.error('Failed to insert font rule:', e);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export function getBase64CustomFontsStyle() {
|
|
165
|
+
const styleTag = document.querySelector(`style[${FONT_CSS_TAG_BASE64}]`);
|
|
166
|
+
return styleTag?.textContent || '';
|
|
167
|
+
}
|
|
168
|
+
export async function loadFont(font) {
|
|
169
|
+
await addCustomFontBase64(font);
|
|
170
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { TextEditor } from "./TextEditor";
|
|
2
|
+
import "./TextEditTool";
|
|
3
|
+
import "quill/dist/quill.core.css";
|
|
4
|
+
export { updataHtmlText, setHTMLText } from "./utils";
|
|
5
|
+
export { fontManager, defaultFonts, FontManager } from "./fonts/font";
|
|
6
|
+
export declare function initTextEditorQuill(container?: HTMLElement): any;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,gBAAgB,CAAC;AAIxB,OAAO,2BAA2B,CAAC;AAGnC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAItE,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE,WAAW,OA6E1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,cAAc,GAAU,IAAI,GAAG,EAAE,aAAa,GAAG,EAAE,UAAU,GAAG,kBAuG5E,CAAC;AAqFF,eAAO,MAAM,WAAW,GACtB,KAAK,MAAM,EACX,QAAQ,GAAG,EACX,aAAa,GAAG,EAChB,SAAS,GAAG,EACZ,gBAAgB,OAAO,SAgIxB,CAAC"}
|