@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.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -0
  3. package/dist/TextEditTool/index.d.ts +17 -0
  4. package/dist/TextEditTool/index.d.ts.map +1 -0
  5. package/dist/TextEditTool/index.js +138 -0
  6. package/dist/TextEditTool/utils.d.ts +8 -0
  7. package/dist/TextEditTool/utils.d.ts.map +1 -0
  8. package/dist/TextEditTool/utils.js +173 -0
  9. package/dist/TextEditor.d.ts +27 -0
  10. package/dist/TextEditor.d.ts.map +1 -0
  11. package/dist/TextEditor.js +166 -0
  12. package/dist/esm/TextEditTool/index.d.ts +17 -0
  13. package/dist/esm/TextEditTool/index.d.ts.map +1 -0
  14. package/dist/esm/TextEditTool/index.js +135 -0
  15. package/dist/esm/TextEditTool/utils.d.ts +8 -0
  16. package/dist/esm/TextEditTool/utils.d.ts.map +1 -0
  17. package/dist/esm/TextEditTool/utils.js +165 -0
  18. package/dist/esm/TextEditor.d.ts +27 -0
  19. package/dist/esm/TextEditor.d.ts.map +1 -0
  20. package/dist/esm/TextEditor.js +163 -0
  21. package/dist/esm/fonts/font.d.ts +17 -0
  22. package/dist/esm/fonts/font.d.ts.map +1 -0
  23. package/dist/esm/fonts/font.js +68 -0
  24. package/dist/esm/fonts/utils.d.ts +9 -0
  25. package/dist/esm/fonts/utils.d.ts.map +1 -0
  26. package/dist/esm/fonts/utils.js +170 -0
  27. package/dist/esm/index.d.ts +7 -0
  28. package/dist/esm/index.d.ts.map +1 -0
  29. package/dist/esm/utils.d.ts +3 -0
  30. package/dist/esm/utils.d.ts.map +1 -0
  31. package/dist/esm/utils.js +284 -0
  32. package/dist/fonts/font.d.ts +17 -0
  33. package/dist/fonts/font.d.ts.map +1 -0
  34. package/dist/fonts/font.js +72 -0
  35. package/dist/fonts/utils.d.ts +9 -0
  36. package/dist/fonts/utils.d.ts.map +1 -0
  37. package/dist/fonts/utils.js +180 -0
  38. package/dist/index.d.ts +7 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.esm.js +79 -0
  41. package/dist/index.js +92 -0
  42. package/dist/utils.d.ts +3 -0
  43. package/dist/utils.d.ts.map +1 -0
  44. package/dist/utils.js +289 -0
  45. package/package.json +55 -0
  46. package/src/TextEditTool/index.ts +145 -0
  47. package/src/TextEditTool/utils.ts +216 -0
  48. package/src/TextEditor.ts +200 -0
  49. package/src/fonts/font.ts +86 -0
  50. package/src/fonts/utils.ts +232 -0
  51. package/src/index.ts +92 -0
  52. package/src/utils.ts +331 -0
@@ -0,0 +1,284 @@
1
+ import { TextEditor } from './TextEditor';
2
+ function getEditorContext() {
3
+ const quill = TextEditor.quill;
4
+ return { quill };
5
+ }
6
+ export const updataHtmlText = async (e, base64font, fontObj) => {
7
+ const { scaleX, scaleY } = e.worldTransform;
8
+ const zoomScale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
9
+ const dom = document.querySelector('#textInnerEditor');
10
+ if (dom && e.data.textData?.fontFamily) {
11
+ dom.style.fontFamily = e.data.textData.fontFamily;
12
+ }
13
+ if (dom && e.data.textData?.fontSize) {
14
+ dom.style.fontSize = `${e.data.textData.fontSize * zoomScale}px`;
15
+ }
16
+ if (dom && e.data.textData?.lineHeight) {
17
+ dom.style.lineHeight = e.data.textData.lineHeight;
18
+ }
19
+ if (dom && e.data.textData?.letterSpacing) {
20
+ dom.style.letterSpacing = `${e.data.textData.letterSpacing}px`;
21
+ }
22
+ if (dom && e.data.textData?.textShadow) {
23
+ dom.style.textShadow = e.data.textData.textShadow;
24
+ }
25
+ else if (dom) {
26
+ dom.style.textShadow = 'none';
27
+ }
28
+ if (dom && e.data.textData?.alignContent) {
29
+ const qlEditor = dom.querySelector('.ql-editor');
30
+ if (qlEditor) {
31
+ qlEditor.style.alignContent = e.data.textData.alignContent;
32
+ }
33
+ }
34
+ const { quill } = getEditorContext();
35
+ if (!quill)
36
+ return;
37
+ const html = quill.getSemanticHTML();
38
+ if (html === '<p></p>') {
39
+ if (e.text.includes('<style>@font-face')) {
40
+ e.text = e.text.split('</style>')[0] + '</style>';
41
+ }
42
+ else {
43
+ e.text = '';
44
+ }
45
+ return;
46
+ }
47
+ if (e.text.includes('<style>@font-face')) {
48
+ const style = e.text.split('</style>')[0];
49
+ if (fontObj && !style.includes(fontObj.code)) {
50
+ const addStyle = `@font-face {font-family: ${fontObj.code};src: url(${base64font}) format('woff2') } .ql-font-${fontObj?.code?.replace(/\s+/g, '')} {font-family: ${fontObj.name};}`;
51
+ e.text =
52
+ style +
53
+ addStyle +
54
+ '</style>' +
55
+ addFontSizeToP(e, html, e.data.textData.fontSize, e.data.textData.lineHeight, e.data.textData.letterSpacing, e.data.textData.textShadow, e.data.textData?.alignContent);
56
+ }
57
+ else {
58
+ e.text =
59
+ style +
60
+ '</style>' +
61
+ addFontSizeToP(e, html, e.data.textData.fontSize, e.data.textData.lineHeight, e.data.textData.letterSpacing, e.data.textData.textShadow, e.data.textData?.alignContent);
62
+ }
63
+ }
64
+ else if (base64font && fontObj) {
65
+ const style = `<style>@font-face {font-family: ${e.data.textData.fontFamily.split(',')[0]};src: url(${base64font}) format('woff2') } .ql-font-${fontObj?.code?.replace(/\s+/g, '')} {font-family: ${fontObj.name};}</style>`;
66
+ e.text =
67
+ style +
68
+ addFontSizeToP(e, html, e.data.textData.fontSize, e.data.textData.lineHeight, e.data.textData.letterSpacing, e.data.textData.textShadow, e.data.textData?.alignContent);
69
+ }
70
+ else {
71
+ e.text = addFontSizeToP(e, html, e.data.textData.fontSize, e.data.textData.lineHeight, e.data.textData.letterSpacing, e.data.textData.textShadow, e.data.textData?.alignContent);
72
+ }
73
+ };
74
+ const addFontSizeToP = (e, html, fontSize = 16, lineHeight = '1.5', letterSpacing = '0', textShadow = 'none', alignContent = 'start') => {
75
+ const { quill } = getEditorContext();
76
+ if (!quill)
77
+ return html;
78
+ const { scaleX, scaleY } = e.worldTransform;
79
+ const zoomScale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
80
+ const wrapper = document.createElement('div');
81
+ wrapper.innerHTML = html;
82
+ const wrapperStyle = {
83
+ fontSize: `${fontSize}px`,
84
+ lineHeight,
85
+ letterSpacing: `${letterSpacing}px`,
86
+ textShadow
87
+ };
88
+ wrapper.querySelectorAll('p,ol,ul').forEach((p) => {
89
+ Object.assign(p.style, wrapperStyle);
90
+ });
91
+ let str = wrapper.innerHTML;
92
+ if (/<p\b[^>]*><\/p>/.test(str)) {
93
+ str = str.replace(/<p\b([^>]*)><\/p>/g, '<p$1>&nbsp;</p>');
94
+ }
95
+ let height;
96
+ const div = document.querySelector('#textInnerEditor');
97
+ const actualHeight = Number((quill.scroll.domNode.scrollHeight / zoomScale).toFixed(0));
98
+ const actualWidth = Number((quill.scroll.domNode.scrollWidth / zoomScale).toFixed(0));
99
+ if (['center', 'end'].includes(e.data.textData.alignContent)) {
100
+ if (e.parent.height < actualHeight) {
101
+ e.data.textData.alignContent = 'start';
102
+ height = (actualHeight || e.__layout.boxBounds.height) + 'px';
103
+ }
104
+ else {
105
+ height = `${e.parent.height}px`;
106
+ }
107
+ }
108
+ else {
109
+ if (e.parent.height < actualHeight) {
110
+ height = (actualHeight || e.__layout.boxBounds.height) + 'px';
111
+ }
112
+ else {
113
+ height = `${e.parent.height}px`;
114
+ }
115
+ }
116
+ const style = `<style>sub,sup{font-size:63%;}.ql-ui{position:absolute}ol,ul{counter-reset:list-0;padding-left:1.5em;margin:0}ol>li,ul>li{counter-increment:list-0;list-style-type:none;position:relative;padding-left:0;margin:0}ol>li::before{content:counter(list-0,decimal) '. ';position:absolute;left:-1.5em;width:1.2em;text-align:right}ul>li::before{content:'\\u2022';position:absolute;left:-1.5em;width:1.2em;text-align:right}li[data-list]{counter-set:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-align-center{text-align:center}.ql-align-right{text-align:right}.ql-align-left{text-align:left}.ql-align-justify{text-align:justify}</style>`;
117
+ let divBox = '';
118
+ if (e.parent.children[0].tag.includes('Shape')) {
119
+ divBox =
120
+ style +
121
+ `<div style="width: ${e.parent.width}px;height: ${e.parent.height}px;overflow-wrap:break-word;word-break:break-all;align-content:center;">${str}</div>`;
122
+ }
123
+ else if (e.data.canChangeBox) {
124
+ divBox =
125
+ style +
126
+ `<div style="width: ${e.parent.width}px;height:${height};overflow-wrap:break-word;word-break:break-all;align-content:${alignContent};">${str}</div>`;
127
+ }
128
+ else {
129
+ if (e.data.textData.italic) {
130
+ divBox = style + str;
131
+ }
132
+ else {
133
+ divBox = style + `<div style="width: ${actualWidth - 10}px">${str}</div>`;
134
+ }
135
+ }
136
+ console.log(divBox, '最终的html内容');
137
+ return divBox;
138
+ };
139
+ export const setHTMLText = (key, value, base64font, editor, isInnerEditor) => {
140
+ const { quill } = getEditorContext();
141
+ if (!quill) {
142
+ console.error('Quill editor not initialized');
143
+ return;
144
+ }
145
+ const rangeStr = localStorage.getItem('selection-change');
146
+ const range = rangeStr ? JSON.parse(rangeStr) : null;
147
+ if (range && isInnerEditor) {
148
+ quill.setSelection(range.index, range.length);
149
+ }
150
+ if (!editor || !editor.dateEdit) {
151
+ console.warn('Editor context not available for dateEdit');
152
+ return;
153
+ }
154
+ editor.dateEdit(async (e) => {
155
+ if (key === 'font') {
156
+ const fontSimpleName = value.code.replace(/\s+/g, '');
157
+ if (isInnerEditor) {
158
+ if (range && range.length) {
159
+ quill.formatText(range.index, range.length, key, fontSimpleName);
160
+ }
161
+ else {
162
+ quill.formatText(0, quill.getLength() - 1, key, fontSimpleName);
163
+ }
164
+ updataHtmlText(e, base64font ?? null, value ?? null);
165
+ }
166
+ else {
167
+ editor.isMultiSelect && editor.isMultiSelect() && quill.clipboard.dangerouslyPasteHTML(e.text);
168
+ quill.formatText(0, quill.getLength() - 1, key, fontSimpleName);
169
+ updataHtmlText(e, base64font ?? null, value ?? null);
170
+ }
171
+ }
172
+ else if (key === 'fontSize') {
173
+ e.data.textData[key] = value;
174
+ editor.isMultiSelect && editor.isMultiSelect() && quill.clipboard.dangerouslyPasteHTML(e.text);
175
+ updataHtmlText(e, base64font ?? null);
176
+ }
177
+ else if (key === 'textCase') {
178
+ if (isInnerEditor && range) {
179
+ const text = quill.getText(range.index, range.length);
180
+ const formats = quill.getFormat(range.index, range.length);
181
+ quill.deleteText(range.index, range.length);
182
+ let convertedText;
183
+ if (text === text.toUpperCase() && /[A-Z]/.test(text)) {
184
+ convertedText = text.toLowerCase();
185
+ }
186
+ else if (text === text.toLowerCase() && /[a-z]/.test(text)) {
187
+ convertedText = text.toUpperCase();
188
+ }
189
+ else {
190
+ convertedText = text.toUpperCase();
191
+ }
192
+ quill.insertText(range.index, convertedText, formats);
193
+ if (range && isInnerEditor) {
194
+ quill.setSelection(range.index, range.length);
195
+ }
196
+ }
197
+ }
198
+ else if (key === 'script') {
199
+ let val = 'sub';
200
+ if (value === 'super')
201
+ val = 'sup';
202
+ if (isInnerEditor) {
203
+ if (range && range.length) {
204
+ quill.formatText(range.index, range.length, key, quill.getFormat(range).script === value ? false : val);
205
+ }
206
+ else {
207
+ quill.formatText(0, quill.getLength() - 1, key, quill.getFormat().script === value ? false : val);
208
+ }
209
+ }
210
+ else {
211
+ editor.isMultiSelect && editor.isMultiSelect() && quill.clipboard.dangerouslyPasteHTML(e.text);
212
+ quill.formatText(0, quill.getLength() - 1, key, quill.getFormat().script === value ? false : val);
213
+ updataHtmlText(e);
214
+ }
215
+ }
216
+ else if (key === 'align') {
217
+ editor.isMultiSelect && editor.isMultiSelect() && quill.clipboard.dangerouslyPasteHTML(e.text);
218
+ if (isInnerEditor) {
219
+ quill.format(key, value);
220
+ }
221
+ else {
222
+ quill.formatLine(0, quill.getLength(), key, value);
223
+ }
224
+ updataHtmlText(e);
225
+ }
226
+ else if (key === 'alignContent') {
227
+ editor.isMultiSelect && editor.isMultiSelect() && quill.clipboard.dangerouslyPasteHTML(e.text);
228
+ e.data.textData[key] = value;
229
+ updataHtmlText(e);
230
+ }
231
+ else if (key === 'color') {
232
+ editor.isMultiSelect && editor.isMultiSelect() && quill.clipboard.dangerouslyPasteHTML(e.text);
233
+ quill.formatText(0, quill.getLength() - 1, key, value);
234
+ if (e.tag === 'HTMLText') {
235
+ updataHtmlText(e);
236
+ }
237
+ else if (e.parent.findOne && e.parent.findOne('HTMLText')) {
238
+ updataHtmlText(e.parent.findOne('HTMLText'));
239
+ }
240
+ }
241
+ else if (key === 'textShadow') {
242
+ editor.isMultiSelect && editor.isMultiSelect() && quill.clipboard.dangerouslyPasteHTML(e.text);
243
+ e.data.textData[key] = value;
244
+ updataHtmlText(e);
245
+ }
246
+ else if (key === 'list') {
247
+ editor.isMultiSelect && editor.isMultiSelect() && quill.clipboard.dangerouslyPasteHTML(e.text);
248
+ if (isInnerEditor) {
249
+ const [line] = quill.getLine(range?.index || 0);
250
+ if (line.formats().list) {
251
+ quill.format(key, false);
252
+ }
253
+ else {
254
+ quill.format(key, value);
255
+ }
256
+ }
257
+ else {
258
+ const [line] = quill.getLine(range?.index || 0);
259
+ if (line.formats().list) {
260
+ quill.formatLine(0, quill.getLength(), key, false);
261
+ }
262
+ else {
263
+ quill.formatLine(0, quill.getLength(), key, value);
264
+ }
265
+ }
266
+ updataHtmlText(e);
267
+ }
268
+ else {
269
+ if (isInnerEditor) {
270
+ if (range && range.length) {
271
+ quill.formatText(range.index, range.length, key, !quill.getFormat(range)[key]);
272
+ }
273
+ else {
274
+ quill.formatText(0, quill.getLength() - 1, key, !quill.getFormat()[key]);
275
+ }
276
+ }
277
+ else {
278
+ editor.isMultiSelect && editor.isMultiSelect() && quill.clipboard.dangerouslyPasteHTML(e.text);
279
+ quill.formatText(0, quill.getLength() - 1, key, !quill.getFormat()[key]);
280
+ updataHtmlText(e);
281
+ }
282
+ }
283
+ }, 1);
284
+ };
@@ -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,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fontManager = exports.FontManager = exports.defaultFonts = void 0;
4
+ exports.defaultFonts = [
5
+ { code: 'Roboto', name: `"Roboto", sans-serif`, url: '/fonts/Roboto.woff2' },
6
+ { code: 'Roboto Mono', name: `"Roboto Mono", monospace`, url: '/fonts/RobotoMono.woff2' },
7
+ { code: 'Inter', name: `"Inter", sans-serif`, url: '/fonts/Inter.woff2' },
8
+ { code: 'Open Sans', name: `"Open Sans", sans-serif`, url: '/fonts/OpenSans.woff2' },
9
+ { code: 'Montserrat', name: `"Montserrat", sans-serif`, url: '/fonts/Montserrat.woff2' },
10
+ { code: 'Roboto Condensed', name: `"Roboto Condensed", sans-serif`, url: '/fonts/RobotoCondensed.woff2' },
11
+ { code: 'Arimo', name: `"Arimo", sans-serif`, url: '/fonts/Arimo.woff2' },
12
+ { code: 'Noto Sans', name: `"Noto Sans", sans-serif`, url: '/fonts/NotoSans.woff2' },
13
+ { code: 'Noto Sans Symbols', name: `"Noto Sans Symbols", sans-serif`, url: '/fonts/NotoSansSymbols.woff2' },
14
+ { code: 'Merriweather', name: `"Merriweather", serif`, url: '/fonts/Merriweather.woff2' },
15
+ { code: 'Playfair Display', name: `"Playfair Display", serif`, url: '/fonts/PlayfairDisplay.woff2' },
16
+ { code: 'Noto Serif', name: `"Noto Serif", serif`, url: '/fonts/NotoSerif.woff2' },
17
+ { code: 'Lato', name: `"Lato", sans-serif`, url: '/fonts/Lato.woff2' },
18
+ { code: 'Spectral', name: `"Spectral", serif`, url: '/fonts/Spectral.woff2' },
19
+ { code: 'Dancing Script', name: `"Dancing Script", cursive`, url: '/fonts/DancingScript.woff2' },
20
+ { code: 'Noto Sans Simplified Chinese', name: `"Noto Sans SC", sans-serif`, url: '/fonts/NotoSansSimplifiedChinese.woff2' },
21
+ { code: 'Noto Serif Simplified Chinese', name: `"Noto Serif SC", serif`, url: '/fonts/NotoSerifSimplifiedChinese.woff2' },
22
+ { code: 'Noto Sans Traditional Chinese', name: `"Noto Sans TC", sans-serif`, url: '/fonts/NotoSansTraditionalChinese.woff2' },
23
+ { code: 'Noto Sans Hong Kong', name: `"Noto Sans HK", sans-serif`, url: '/fonts/NotoSansHongKong.woff2' },
24
+ { code: 'Noto Serif Traditional Chinese', name: `"Noto Serif TC", serif`, url: '/fonts/NotoSerifTraditionalChinese.woff2' },
25
+ { code: 'Noto Serif Hong Kong', name: `"Noto Serif HK", serif`, url: '/fonts/NotoSerifHongKong.woff2' },
26
+ { code: 'Noto Sans Japanese', name: `"Noto Sans JP", sans-serif`, url: '/fonts/NotoSansJapanese.woff2' },
27
+ { code: 'Noto Sans Korean', name: `"Noto Sans KR", sans-serif`, url: '/fonts/NotoSansKorean.woff2' },
28
+ { code: 'Poppins', name: `"Poppins", sans-serif`, url: '/fonts/Poppins.woff2' }
29
+ ];
30
+ const FONT_KEY = 'OPEN_FONTS';
31
+ const FONT_VERSION_KEY = 'OPEN_FONTS_VERSION';
32
+ class FontManager {
33
+ constructor() {
34
+ this.fontList = [];
35
+ this.skipLoadFonts = exports.defaultFonts.map((value) => value.name);
36
+ this.loadFonts = exports.defaultFonts;
37
+ this.initFonts();
38
+ }
39
+ async initFonts() {
40
+ let list = [];
41
+ if (typeof localStorage !== 'undefined') {
42
+ if (localStorage.getItem(FONT_VERSION_KEY) !== '1') {
43
+ localStorage.removeItem(FONT_KEY);
44
+ }
45
+ let localFonts = [];
46
+ try {
47
+ const storedFonts = localStorage.getItem(FONT_KEY);
48
+ localFonts = storedFonts ? JSON.parse(storedFonts) : [];
49
+ }
50
+ catch {
51
+ localFonts = [];
52
+ localStorage.removeItem(FONT_KEY);
53
+ }
54
+ if (localFonts.length > 0) {
55
+ list.push(...localFonts);
56
+ }
57
+ }
58
+ this.fontList = exports.defaultFonts.concat(list);
59
+ return list;
60
+ }
61
+ getFontList() {
62
+ return this.fontList;
63
+ }
64
+ getSkipLoadFonts() {
65
+ return this.skipLoadFonts;
66
+ }
67
+ getLoadFonts() {
68
+ return this.loadFonts;
69
+ }
70
+ }
71
+ exports.FontManager = FontManager;
72
+ exports.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,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchFontAsBase64 = fetchFontAsBase64;
4
+ exports.addCustomFonts = addCustomFonts;
5
+ exports.getCustomFontsStyle = getCustomFontsStyle;
6
+ exports.addCustomFont = addCustomFont;
7
+ exports.batchLoadFont = batchLoadFont;
8
+ exports.addCustomFontBase64 = addCustomFontBase64;
9
+ exports.getBase64CustomFontsStyle = getBase64CustomFontsStyle;
10
+ exports.loadFont = loadFont;
11
+ const FONT_CSS_TAG = "data-fonts";
12
+ const FONT_CSS_TAG_BASE64 = "base64-fonts";
13
+ async function fetchFontAsBase64(url) {
14
+ const response = await fetch(url);
15
+ if (!response.ok) {
16
+ throw new Error(`Failed to fetch font from ${url}`);
17
+ }
18
+ const contentType = response.headers.get('Content-Type');
19
+ let mimeType;
20
+ if (contentType?.includes('font/woff2')) {
21
+ mimeType = 'font/woff2';
22
+ }
23
+ else if (contentType?.includes('font/woff')) {
24
+ mimeType = 'font/woff';
25
+ }
26
+ else if (contentType?.includes('font/ttf') || contentType?.includes('font/sfnt')) {
27
+ mimeType = 'font/ttf';
28
+ }
29
+ else if (contentType?.includes('application/octet-stream')) {
30
+ const extension = url.split('.').pop()?.toLowerCase();
31
+ if (extension === 'woff2') {
32
+ mimeType = 'font/woff2';
33
+ }
34
+ else if (extension === 'woff') {
35
+ mimeType = 'font/woff';
36
+ }
37
+ else if (extension === 'ttf') {
38
+ mimeType = 'font/ttf';
39
+ }
40
+ else {
41
+ throw new Error(`Unsupported font file type: ${extension}`);
42
+ }
43
+ }
44
+ else {
45
+ throw new Error(`Unsupported Content-Type: ${contentType}`);
46
+ }
47
+ const arrayBuffer = await response.arrayBuffer();
48
+ const base64String = arrayBufferToBase64(arrayBuffer);
49
+ return `data:${mimeType};charset=utf-8;base64,${base64String}`;
50
+ }
51
+ function arrayBufferToBase64(buffer) {
52
+ let binary = '';
53
+ const bytes = new Uint8Array(buffer);
54
+ const len = bytes.byteLength;
55
+ for (let i = 0; i < len; i++) {
56
+ binary += String.fromCharCode(bytes[i]);
57
+ }
58
+ return window.btoa(binary);
59
+ }
60
+ function addCustomFonts(fontList = []) {
61
+ let styleTag = document.createElement('style');
62
+ styleTag.setAttribute(FONT_CSS_TAG, 'true');
63
+ let fontRules = fontList.map((font) => `@font-face {
64
+ font-family: "${font.name}";
65
+ src: local("${font.name}"), url("${font.download}")
66
+ }`).join('\n');
67
+ styleTag.textContent = fontRules;
68
+ document.head.appendChild(styleTag);
69
+ }
70
+ function getCustomFontsStyle() {
71
+ const styleTag = document.querySelector('style[data-fonts]');
72
+ return styleTag?.textContent || '';
73
+ }
74
+ function addCustomFont(font) {
75
+ let styleTag = document.querySelector('style[data-fonts]');
76
+ if (!styleTag) {
77
+ styleTag = document.createElement('style');
78
+ styleTag.setAttribute(FONT_CSS_TAG, 'true');
79
+ document.head.appendChild(styleTag);
80
+ }
81
+ if (!styleTag.sheet)
82
+ return;
83
+ let existingFonts = [];
84
+ existingFonts = Array.from(styleTag.sheet.cssRules).map((rule) => {
85
+ const match = rule.cssText.match(/font-family: "([^"]+)"/);
86
+ return match ? match[1] : null;
87
+ }).filter((font) => font !== null);
88
+ if (!existingFonts.includes(font.name)) {
89
+ const newFontRule = `@font-face {
90
+ font-family: "${font.name}";
91
+ src: url("${font.download}");
92
+ }`;
93
+ try {
94
+ styleTag.sheet.insertRule(newFontRule, styleTag.sheet.cssRules.length);
95
+ }
96
+ catch (e) {
97
+ console.error('Failed to insert font rule:', e);
98
+ }
99
+ }
100
+ }
101
+ async function batchLoadFont(fontNameList = []) {
102
+ try {
103
+ for (const fontFamily of fontNameList) {
104
+ await document.fonts.load(`16px ${fontFamily}`);
105
+ }
106
+ }
107
+ catch (e) {
108
+ console.warn('Font loading failed:', e);
109
+ }
110
+ }
111
+ function getFontUrlFromCSS(selectors, fontFamilyName) {
112
+ const styleTags = document.querySelectorAll(selectors);
113
+ for (let i = 0; i < styleTags.length; i++) {
114
+ const styleTag = styleTags[i];
115
+ const cssText = styleTag.textContent || '';
116
+ const fontFaceRules = cssText.match(/@font-face\s*\{[^}]+\}/g);
117
+ if (fontFaceRules) {
118
+ for (const rule of fontFaceRules) {
119
+ const fontFamilyMatch = rule.match(/font-family:\s*(["'])(.*?)\1/);
120
+ if (fontFamilyMatch && fontFamilyMatch[2] === fontFamilyName) {
121
+ const srcMatch = rule.match(/src:\s*url\((["'])(.*?)\1\)/);
122
+ if (srcMatch) {
123
+ return srcMatch[2];
124
+ }
125
+ else {
126
+ const srcMatch2 = rule.match(/src:\s*(?:local\([^)]+\)\s*,\s*)?url\((["'])(.*?)\1\)/);
127
+ if (srcMatch2) {
128
+ return srcMatch2[2];
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ return null;
136
+ }
137
+ async function addCustomFontBase64(font) {
138
+ const fontUrl = getFontUrlFromCSS(`style[${FONT_CSS_TAG}]`, font);
139
+ if (!fontUrl) {
140
+ console.warn('Font URL not found for:', font);
141
+ return;
142
+ }
143
+ console.log('fontUrl=', fontUrl);
144
+ let styleTag = document.querySelector(`style[${FONT_CSS_TAG_BASE64}]`);
145
+ if (!styleTag) {
146
+ styleTag = document.createElement('style');
147
+ styleTag.setAttribute(FONT_CSS_TAG_BASE64, 'true');
148
+ document.head.appendChild(styleTag);
149
+ }
150
+ if (!styleTag.sheet) {
151
+ await new Promise(resolve => setTimeout(resolve, 10));
152
+ }
153
+ if (!styleTag.sheet)
154
+ return;
155
+ let existingFonts = Array.from(styleTag.sheet.cssRules).map((rule) => {
156
+ const match = rule.cssText.match(/font-family: "([^"]+)"/);
157
+ return match ? match[1] : null;
158
+ }).filter((font) => font !== null);
159
+ if (!existingFonts.includes(font)) {
160
+ const base64Url = await fetchFontAsBase64(fontUrl);
161
+ const newFontRule = `@font-face {
162
+ font-family: "${font}";
163
+ src: local("${font}"), url("${base64Url}");
164
+ }`;
165
+ try {
166
+ styleTag.sheet.insertRule(newFontRule, styleTag.sheet.cssRules.length);
167
+ styleTag.textContent += newFontRule;
168
+ }
169
+ catch (e) {
170
+ console.error('Failed to insert font rule:', e);
171
+ }
172
+ }
173
+ }
174
+ function getBase64CustomFontsStyle() {
175
+ const styleTag = document.querySelector(`style[${FONT_CSS_TAG_BASE64}]`);
176
+ return styleTag?.textContent || '';
177
+ }
178
+ async function loadFont(font) {
179
+ await addCustomFontBase64(font);
180
+ }
@@ -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,79 @@
1
+ import { TextEditor } from "./TextEditor";
2
+ export { TextEditor } from "./TextEditor";
3
+ import "./TextEditTool";
4
+ import { Plugin } from "@leafer-ui/core";
5
+ import { Delta } from "quill";
6
+ import Quill from "quill";
7
+ import "quill/dist/quill.core.css";
8
+ export { updataHtmlText, setHTMLText } from "./utils";
9
+ export { fontManager, defaultFonts, FontManager } from "./fonts/font";
10
+ Plugin.add("leafer-htmltext-editor", "editor");
11
+ export function initTextEditorQuill(container) {
12
+ const textInner = document.getElementById("textInnerEditor");
13
+ if (!textInner) {
14
+ const el = document.createElement("div");
15
+ el.id = "textInnerEditor";
16
+ el.style.position = "fixed";
17
+ el.style.transformOrigin = "left top";
18
+ el.style.overflowWrap = "break-word";
19
+ el.style.wordBreak = "break-all";
20
+ el.style.visibility = "hidden";
21
+ document.body.appendChild(el);
22
+ }
23
+ TextEditor.quill = new Quill("#textInnerEditor", {
24
+ theme: null,
25
+ modules: {
26
+ toolbar: false,
27
+ keyboard: {
28
+ bindings: {
29
+ enter: {
30
+ key: "Enter",
31
+ handler: (range, context) => {
32
+ const [line] = TextEditor.quill.getLine(range.index);
33
+ const BlockBlot = Quill.import("blots/block");
34
+ if (!BlockBlot || !BlockBlot.bubbleFormats)
35
+ return;
36
+ const lineFormats = BlockBlot.bubbleFormats(line);
37
+ const delta = new Delta()
38
+ .retain(range.index)
39
+ .delete(range.length)
40
+ .insert("\n", lineFormats);
41
+ TextEditor.quill.updateContents(delta, Quill.sources.USER);
42
+ TextEditor.quill.setSelection(range.index + 1, Quill.sources.SILENT);
43
+ return false;
44
+ },
45
+ },
46
+ },
47
+ },
48
+ },
49
+ });
50
+ const FontAttributor = Quill.import("attributors/class/font");
51
+ FontAttributor.whitelist = [
52
+ "Roboto",
53
+ "RobotoMono",
54
+ "Inter",
55
+ "OpenSans",
56
+ "Montserrat",
57
+ "RobotoCondensed",
58
+ "Arimo",
59
+ "NotoSans",
60
+ "NotoSansSymbols",
61
+ "Merriweather",
62
+ "PlayfairDisplay",
63
+ "NotoSerif",
64
+ "Lato",
65
+ "Spectral",
66
+ "DancingScript",
67
+ "NotoSansSimplifiedChinese",
68
+ "NotoSerifSimplifiedChinese",
69
+ "NotoSansTraditionalChinese",
70
+ "NotoSansHongKong",
71
+ "NotoSerifTraditionalChinese",
72
+ "NotoSerifHongKong",
73
+ "NotoSansJapanese",
74
+ "NotoSansKorean",
75
+ "Poppins",
76
+ ];
77
+ Quill.register(FontAttributor, true);
78
+ return TextEditor.quill;
79
+ }