@formulaxjs/editor 0.1.1 → 0.3.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/README.md +41 -20
- package/dist/index.cjs +184 -859
- package/dist/index.cjs.map +1 -1
- package/dist/index.global.js +935 -1171
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +176 -849
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -20,450 +20,178 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
24
|
-
DEFAULT_FORMULA_CLASS: () => DEFAULT_FORMULA_CLASS,
|
|
25
|
-
FORMULA_FLAG_ATTRIBUTE: () => FORMULA_FLAG_ATTRIBUTE,
|
|
26
|
-
FormulaEditor: () => FormulaEditor,
|
|
27
|
-
createFormulaElement: () => createFormulaElement,
|
|
28
|
-
createFormulaMarkup: () => createFormulaMarkup,
|
|
29
|
-
editorStyles: () => editorStyles,
|
|
23
|
+
clearFormulaXPerfMarks: () => clearFormulaXPerfMarks,
|
|
30
24
|
ensureFormulaXModalStyles: () => ensureFormulaXModalStyles,
|
|
31
|
-
escapeAttribute: () => escapeAttribute,
|
|
32
|
-
escapeHtml: () => escapeHtml,
|
|
33
|
-
findFormulaElement: () => findFormulaElement,
|
|
34
25
|
formulaXModalStyles: () => formulaXModalStyles,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
26
|
+
markFormulaXPerf: () => markFormulaXPerf,
|
|
27
|
+
measureFormulaXPerf: () => measureFormulaXPerf,
|
|
28
|
+
mountFormulaXEditor: () => mountFormulaXEditor,
|
|
29
|
+
preloadFormulaXEditor: () => preloadFormulaXEditor,
|
|
30
|
+
recordFormulaXPerfPoint: () => recordFormulaXPerfPoint,
|
|
31
|
+
renderFormulaXEditorLoadingState: () => renderFormulaXEditorLoadingState,
|
|
32
|
+
scheduleFormulaXEditorPreload: () => scheduleFormulaXEditorPreload,
|
|
33
|
+
waitForFormulaXAnimationFrame: () => waitForFormulaXAnimationFrame
|
|
43
34
|
});
|
|
44
35
|
module.exports = __toCommonJS(index_exports);
|
|
45
36
|
|
|
46
|
-
// src/
|
|
47
|
-
var joinPath = (path) => path.join(".");
|
|
48
|
-
var renderInteractiveHtml = (doc, activePath) => `
|
|
49
|
-
<div class="fx-editor-surface" data-role="surface">
|
|
50
|
-
${renderChildren(doc.body, [], activePath)}
|
|
51
|
-
</div>
|
|
52
|
-
`;
|
|
53
|
-
var renderChildren = (nodes, basePath, activePath) => {
|
|
54
|
-
const html = [];
|
|
55
|
-
for (let index = 0; index <= nodes.length; index += 1) {
|
|
56
|
-
const path = joinPath([...basePath, index]);
|
|
57
|
-
const isActive = path === joinPath(activePath);
|
|
58
|
-
html.push(
|
|
59
|
-
`<button class="fx-slot${isActive ? " is-active" : ""}" data-path="${path}" type="button" title="${path}"></button>`
|
|
60
|
-
);
|
|
61
|
-
if (index < nodes.length) {
|
|
62
|
-
html.push(renderNode(nodes[index], [...basePath, index], activePath));
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return html.join("");
|
|
66
|
-
};
|
|
67
|
-
var renderNode = (node, path, activePath) => {
|
|
68
|
-
const pathValue = joinPath(path);
|
|
69
|
-
const isActive = (p) => joinPath(p) === joinPath(activePath);
|
|
70
|
-
switch (node.type) {
|
|
71
|
-
case "text":
|
|
72
|
-
return `<span class="fx-node fx-text" data-node-path="${pathValue}">${node.value}</span>`;
|
|
73
|
-
case "group":
|
|
74
|
-
return `<span class="fx-node fx-group" data-node-path="${pathValue}">${renderChildren(node.body, [...path, 0], activePath)}</span>`;
|
|
75
|
-
case "frac":
|
|
76
|
-
return `<span class="fx-node fx-frac" data-node-path="${pathValue}">
|
|
77
|
-
<span class="fx-frac-num${isActive([...path, 0]) ? " is-active" : ""}" data-path="${joinPath([...path, 0])}">${renderChildren(node.numerator, [...path, 0], activePath)}</span>
|
|
78
|
-
<span class="fx-frac-line"></span>
|
|
79
|
-
<span class="fx-frac-den${isActive([...path, 1]) ? " is-active" : ""}" data-path="${joinPath([...path, 1])}">${renderChildren(node.denominator, [...path, 1], activePath)}</span>
|
|
80
|
-
</span>`;
|
|
81
|
-
case "supsub":
|
|
82
|
-
return `<span class="fx-node fx-supsub" data-node-path="${pathValue}">
|
|
83
|
-
<span class="fx-supsub-base">${renderChildren(node.base, [...path, 0], activePath)}</span>
|
|
84
|
-
<span class="fx-supsub-stack">
|
|
85
|
-
<span class="fx-sup${isActive([...path, 1]) ? " is-active" : ""}" data-path="${joinPath([...path, 1])}">${renderChildren(node.sup ?? [], [...path, 1], activePath)}</span>
|
|
86
|
-
<span class="fx-sub${isActive([...path, 2]) ? " is-active" : ""}" data-path="${joinPath([...path, 2])}">${renderChildren(node.sub ?? [], [...path, 2], activePath)}</span>
|
|
87
|
-
</span>
|
|
88
|
-
</span>`;
|
|
89
|
-
case "sqrt":
|
|
90
|
-
return `<span class="fx-node fx-sqrt" data-node-path="${pathValue}">
|
|
91
|
-
<span class="fx-sqrt-symbol">\u221A</span>
|
|
92
|
-
<span class="fx-sqrt-body${isActive([...path, 0]) ? " is-active" : ""}" data-path="${joinPath([...path, 0])}">${renderChildren(node.value, [...path, 0], activePath)}</span>
|
|
93
|
-
</span>`;
|
|
94
|
-
case "fenced":
|
|
95
|
-
return `<span class="fx-node fx-fenced" data-node-path="${pathValue}">
|
|
96
|
-
<span class="fx-fence">${node.left}</span>
|
|
97
|
-
<span class="fx-fenced-body${isActive([...path, 0]) ? " is-active" : ""}" data-path="${joinPath([...path, 0])}">${renderChildren(node.body, [...path, 0], activePath)}</span>
|
|
98
|
-
<span class="fx-fence">${node.right}</span>
|
|
99
|
-
</span>`;
|
|
100
|
-
case "doc":
|
|
101
|
-
return renderChildren(node.body, [0], activePath);
|
|
102
|
-
}
|
|
103
|
-
throw new Error(`Unsupported node type: ${String(node.type)}`);
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
// src/editor.ts
|
|
37
|
+
// src/formula-modal.ts
|
|
107
38
|
var import_core = require("@formulaxjs/core");
|
|
39
|
+
var import_kity_runtime2 = require("@formulaxjs/kity-runtime");
|
|
40
|
+
var import_renderer = require("@formulaxjs/renderer");
|
|
41
|
+
var import_renderer_kity = require("@formulaxjs/renderer-kity");
|
|
108
42
|
|
|
109
|
-
// src/
|
|
110
|
-
var
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
font-family: Cambria, 'Times New Roman', serif;
|
|
122
|
-
font-size: 25px;
|
|
123
|
-
line-height: 1.7;
|
|
124
|
-
min-height: 120px;
|
|
125
|
-
position: relative;
|
|
126
|
-
}
|
|
127
|
-
.fx-editor:focus-within {
|
|
128
|
-
border-color: #7bbb59;
|
|
129
|
-
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.7), 0 0 0 3px rgba(123, 187, 89, 0.18);
|
|
130
|
-
}
|
|
131
|
-
.fx-editor-surface {
|
|
132
|
-
display: flex;
|
|
133
|
-
flex-wrap: wrap;
|
|
134
|
-
align-items: baseline;
|
|
135
|
-
gap: 3px;
|
|
136
|
-
cursor: text;
|
|
137
|
-
}
|
|
138
|
-
.fx-node {
|
|
139
|
-
position: relative;
|
|
140
|
-
display: inline-flex;
|
|
141
|
-
align-items: center;
|
|
142
|
-
padding: 2px 3px;
|
|
143
|
-
border-radius: 2px;
|
|
144
|
-
transition: background 0.12s ease;
|
|
145
|
-
}
|
|
146
|
-
.fx-node:hover {
|
|
147
|
-
background: rgba(122, 186, 89, 0.12);
|
|
148
|
-
}
|
|
149
|
-
.fx-text {
|
|
150
|
-
color: #2b2925;
|
|
151
|
-
}
|
|
152
|
-
.fx-group {
|
|
153
|
-
background: rgba(243, 241, 230, 0.82);
|
|
154
|
-
border: 1px dashed #c8c0a8;
|
|
155
|
-
}
|
|
156
|
-
.fx-frac {
|
|
157
|
-
display: inline-flex;
|
|
158
|
-
flex-direction: column;
|
|
159
|
-
align-items: center;
|
|
160
|
-
vertical-align: middle;
|
|
161
|
-
padding: 0 5px;
|
|
162
|
-
}
|
|
163
|
-
.fx-frac-num, .fx-frac-den {
|
|
164
|
-
display: flex;
|
|
165
|
-
flex-wrap: wrap;
|
|
166
|
-
align-items: center;
|
|
167
|
-
justify-content: center;
|
|
168
|
-
padding: 3px 8px;
|
|
169
|
-
min-width: 24px;
|
|
170
|
-
min-height: 28px;
|
|
171
|
-
border-radius: 2px;
|
|
172
|
-
transition: all 0.15s ease;
|
|
173
|
-
}
|
|
174
|
-
.fx-frac-num {
|
|
175
|
-
border-bottom: 2px solid #2e2c29;
|
|
176
|
-
padding-bottom: 6px;
|
|
177
|
-
}
|
|
178
|
-
.fx-frac-den {
|
|
179
|
-
border-top: 2px solid #2e2c29;
|
|
180
|
-
padding-top: 6px;
|
|
181
|
-
}
|
|
182
|
-
.fx-frac-num:hover, .fx-frac-den:hover {
|
|
183
|
-
background: rgba(122, 186, 89, 0.1);
|
|
184
|
-
}
|
|
185
|
-
.fx-frac-num.is-active, .fx-frac-den.is-active {
|
|
186
|
-
background: rgba(122, 186, 89, 0.16);
|
|
187
|
-
box-shadow: inset 0 0 0 1px rgba(83, 184, 86, 0.5);
|
|
188
|
-
}
|
|
189
|
-
.fx-supsub {
|
|
190
|
-
display: inline-flex;
|
|
191
|
-
align-items: baseline;
|
|
192
|
-
gap: 0;
|
|
193
|
-
}
|
|
194
|
-
.fx-supsub-base {
|
|
195
|
-
display: inline-flex;
|
|
196
|
-
align-items: center;
|
|
197
|
-
padding: 0 2px;
|
|
198
|
-
}
|
|
199
|
-
.fx-supsub-stack {
|
|
200
|
-
display: inline-flex;
|
|
201
|
-
flex-direction: column;
|
|
202
|
-
align-items: flex-start;
|
|
203
|
-
font-size: 0.65em;
|
|
204
|
-
margin-left: 2px;
|
|
205
|
-
}
|
|
206
|
-
.fx-sup, .fx-sub {
|
|
207
|
-
display: flex;
|
|
208
|
-
align-items: center;
|
|
209
|
-
min-width: 16px;
|
|
210
|
-
min-height: 20px;
|
|
211
|
-
padding: 0 4px;
|
|
212
|
-
border-radius: 2px;
|
|
213
|
-
transition: all 0.15s ease;
|
|
214
|
-
}
|
|
215
|
-
.fx-sup {
|
|
216
|
-
vertical-align: super;
|
|
217
|
-
}
|
|
218
|
-
.fx-sub {
|
|
219
|
-
vertical-align: sub;
|
|
220
|
-
}
|
|
221
|
-
.fx-sup:hover, .fx-sub:hover {
|
|
222
|
-
background: rgba(122, 186, 89, 0.1);
|
|
223
|
-
}
|
|
224
|
-
.fx-sup.is-active, .fx-sub.is-active {
|
|
225
|
-
background: rgba(122, 186, 89, 0.16);
|
|
226
|
-
box-shadow: inset 0 0 0 1px rgba(83, 184, 86, 0.5);
|
|
227
|
-
}
|
|
228
|
-
.fx-sqrt {
|
|
229
|
-
display: inline-flex;
|
|
230
|
-
align-items: baseline;
|
|
231
|
-
}
|
|
232
|
-
.fx-sqrt-symbol {
|
|
233
|
-
font-size: 1.1em;
|
|
234
|
-
color: #2e2c29;
|
|
235
|
-
margin-right: 2px;
|
|
236
|
-
}
|
|
237
|
-
.fx-sqrt-body {
|
|
238
|
-
display: inline-flex;
|
|
239
|
-
align-items: center;
|
|
240
|
-
border-top: 2px solid #2e2c29;
|
|
241
|
-
padding: 4px 6px 0;
|
|
242
|
-
margin-left: 2px;
|
|
243
|
-
}
|
|
244
|
-
.fx-sqrt-body:hover {
|
|
245
|
-
background: rgba(122, 186, 89, 0.1);
|
|
246
|
-
}
|
|
247
|
-
.fx-sqrt-body.is-active {
|
|
248
|
-
background: rgba(122, 186, 89, 0.16);
|
|
249
|
-
}
|
|
250
|
-
.fx-fenced {
|
|
251
|
-
display: inline-flex;
|
|
252
|
-
align-items: center;
|
|
253
|
-
background: rgba(243, 241, 230, 0.78);
|
|
254
|
-
border-radius: 3px;
|
|
255
|
-
padding: 0 4px;
|
|
256
|
-
}
|
|
257
|
-
.fx-fence {
|
|
258
|
-
color: #59554d;
|
|
259
|
-
font-size: 1.2em;
|
|
260
|
-
padding: 0 2px;
|
|
261
|
-
}
|
|
262
|
-
.fx-fenced-body {
|
|
263
|
-
display: inline-flex;
|
|
264
|
-
align-items: center;
|
|
265
|
-
padding: 0 6px;
|
|
266
|
-
}
|
|
267
|
-
.fx-fenced-body:hover {
|
|
268
|
-
background: rgba(122, 186, 89, 0.1);
|
|
269
|
-
border-radius: 2px;
|
|
270
|
-
}
|
|
271
|
-
.fx-fenced-body.is-active {
|
|
272
|
-
background: rgba(122, 186, 89, 0.16);
|
|
273
|
-
border-radius: 2px;
|
|
43
|
+
// src/perf.ts
|
|
44
|
+
var import_kity_runtime = require("@formulaxjs/kity-runtime");
|
|
45
|
+
function getPerfHost() {
|
|
46
|
+
return globalThis;
|
|
47
|
+
}
|
|
48
|
+
function getPerfState() {
|
|
49
|
+
const host = getPerfHost();
|
|
50
|
+
host.__FORMULAX_PERF_STATE__ ??= {
|
|
51
|
+
reportedMeasureCount: 0,
|
|
52
|
+
reportScheduled: false
|
|
53
|
+
};
|
|
54
|
+
return host.__FORMULAX_PERF_STATE__;
|
|
274
55
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
height: 1.2em;
|
|
278
|
-
border: none;
|
|
279
|
-
background: #53b856;
|
|
280
|
-
padding: 0;
|
|
281
|
-
margin: 0 1px;
|
|
282
|
-
cursor: text;
|
|
283
|
-
border-radius: 1px;
|
|
284
|
-
vertical-align: middle;
|
|
56
|
+
function hasPerfSupport() {
|
|
57
|
+
return typeof performance !== "undefined" && typeof performance.mark === "function" && typeof performance.measure === "function" && typeof performance.getEntriesByType === "function";
|
|
285
58
|
}
|
|
286
|
-
|
|
287
|
-
|
|
59
|
+
function isPerfDebugEnabled() {
|
|
60
|
+
return getPerfHost().__FORMULAX_PERF__ === true;
|
|
288
61
|
}
|
|
289
|
-
|
|
290
|
-
|
|
62
|
+
function schedulePerfReport() {
|
|
63
|
+
if (!hasPerfSupport() || !isPerfDebugEnabled()) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const state = getPerfState();
|
|
67
|
+
if (state.reportScheduled) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
state.reportScheduled = true;
|
|
71
|
+
queueMicrotask(() => {
|
|
72
|
+
state.reportScheduled = false;
|
|
73
|
+
const entries = performance.getEntriesByType("measure").filter((entry) => entry.name.startsWith("fx:")).sort((left, right) => left.startTime - right.startTime);
|
|
74
|
+
const nextEntries = entries.slice(state.reportedMeasureCount);
|
|
75
|
+
state.reportedMeasureCount = entries.length;
|
|
76
|
+
if (!nextEntries.length) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
console.table(nextEntries.map((entry) => ({
|
|
80
|
+
name: entry.name,
|
|
81
|
+
duration: Number(entry.duration.toFixed(2)),
|
|
82
|
+
startTime: Number(entry.startTime.toFixed(2))
|
|
83
|
+
})));
|
|
84
|
+
});
|
|
291
85
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
var FormulaEditor = class {
|
|
296
|
-
state;
|
|
297
|
-
root;
|
|
298
|
-
onChange;
|
|
299
|
-
locale;
|
|
300
|
-
constructor(options) {
|
|
301
|
-
this.root = options.root;
|
|
302
|
-
this.state = options.initialState ?? (0, import_core.createEmptyState)();
|
|
303
|
-
this.onChange = options.onChange;
|
|
304
|
-
this.locale = options.locale ?? "en";
|
|
305
|
-
this.root.classList.add("fx-editor");
|
|
306
|
-
this.root.tabIndex = 0;
|
|
307
|
-
this.ensureStyles();
|
|
308
|
-
this.bindEvents();
|
|
309
|
-
this.render();
|
|
86
|
+
function markFormulaXPerf(name) {
|
|
87
|
+
if (!hasPerfSupport()) {
|
|
88
|
+
return null;
|
|
310
89
|
}
|
|
311
|
-
|
|
312
|
-
|
|
90
|
+
const markName = `${name}::${Date.now()}::${Math.random().toString(36).slice(2, 8)}`;
|
|
91
|
+
performance.mark(markName);
|
|
92
|
+
return markName;
|
|
93
|
+
}
|
|
94
|
+
function measureFormulaXPerf(name, startMark, endMark) {
|
|
95
|
+
if (!hasPerfSupport() || !startMark) {
|
|
96
|
+
return null;
|
|
313
97
|
}
|
|
314
|
-
|
|
315
|
-
|
|
98
|
+
const resolvedEndMark = endMark ?? markFormulaXPerf(`${name}:end`);
|
|
99
|
+
if (!resolvedEndMark) {
|
|
100
|
+
return null;
|
|
316
101
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
102
|
+
performance.measure(name, startMark, resolvedEndMark);
|
|
103
|
+
schedulePerfReport();
|
|
104
|
+
return resolvedEndMark;
|
|
105
|
+
}
|
|
106
|
+
function recordFormulaXPerfPoint(name) {
|
|
107
|
+
const markName = markFormulaXPerf(name);
|
|
108
|
+
if (!markName) {
|
|
109
|
+
return;
|
|
320
110
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
111
|
+
measureFormulaXPerf(name, markName, markName);
|
|
112
|
+
clearFormulaXPerfMarks(markName);
|
|
113
|
+
}
|
|
114
|
+
function clearFormulaXPerfMarks(...marks) {
|
|
115
|
+
if (!hasPerfSupport()) {
|
|
116
|
+
return;
|
|
325
117
|
}
|
|
326
|
-
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
document.head.appendChild(style);
|
|
118
|
+
for (const mark of marks) {
|
|
119
|
+
if (!mark) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
performance.clearMarks(mark);
|
|
332
123
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
});
|
|
341
|
-
this.root.addEventListener("keydown", (event) => {
|
|
342
|
-
if (event.key === "Backspace") {
|
|
343
|
-
event.preventDefault();
|
|
344
|
-
this.dispatch((0, import_core.backspace)());
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
if (event.key === "/") {
|
|
348
|
-
event.preventDefault();
|
|
349
|
-
this.dispatch((0, import_core.insertFraction)());
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
if (event.key === "^") {
|
|
353
|
-
event.preventDefault();
|
|
354
|
-
this.dispatch((0, import_core.insertSuperscript)());
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
if (event.key === "_") {
|
|
358
|
-
event.preventDefault();
|
|
359
|
-
this.dispatch((0, import_core.insertSubscript)());
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
if (event.key === "r" && event.ctrlKey) {
|
|
363
|
-
event.preventDefault();
|
|
364
|
-
this.dispatch((0, import_core.insertSqrt)());
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
if (event.key === "(") {
|
|
368
|
-
event.preventDefault();
|
|
369
|
-
this.dispatch((0, import_core.insertFenced)("(", ")"));
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
if (event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
|
|
373
|
-
event.preventDefault();
|
|
374
|
-
this.dispatch((0, import_core.insertText)(event.key));
|
|
375
|
-
}
|
|
376
|
-
});
|
|
124
|
+
}
|
|
125
|
+
async function preloadFormulaXEditor() {
|
|
126
|
+
await (0, import_kity_runtime.ensureKityRuntime)();
|
|
127
|
+
}
|
|
128
|
+
function scheduleFormulaXEditorPreload(mode, target) {
|
|
129
|
+
if (mode === false || typeof window === "undefined") {
|
|
130
|
+
return () => void 0;
|
|
377
131
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
132
|
+
let disposed = false;
|
|
133
|
+
let triggered = false;
|
|
134
|
+
const cleanupCallbacks = [];
|
|
135
|
+
const trigger = () => {
|
|
136
|
+
if (disposed || triggered) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
triggered = true;
|
|
140
|
+
while (cleanupCallbacks.length) {
|
|
141
|
+
cleanupCallbacks.pop()?.();
|
|
142
|
+
}
|
|
143
|
+
void preloadFormulaXEditor();
|
|
144
|
+
};
|
|
145
|
+
if (mode === "idle") {
|
|
146
|
+
const host = getPerfHost();
|
|
147
|
+
if (typeof host.requestIdleCallback === "function") {
|
|
148
|
+
const handle = host.requestIdleCallback(() => {
|
|
149
|
+
trigger();
|
|
150
|
+
});
|
|
151
|
+
cleanupCallbacks.push(() => {
|
|
152
|
+
host.cancelIdleCallback?.(handle);
|
|
153
|
+
});
|
|
154
|
+
} else {
|
|
155
|
+
const handle = window.setTimeout(() => {
|
|
156
|
+
trigger();
|
|
157
|
+
}, 1);
|
|
158
|
+
cleanupCallbacks.push(() => {
|
|
159
|
+
window.clearTimeout(handle);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return () => {
|
|
163
|
+
disposed = true;
|
|
164
|
+
while (cleanupCallbacks.length) {
|
|
165
|
+
cleanupCallbacks.pop()?.();
|
|
384
166
|
}
|
|
385
167
|
};
|
|
386
|
-
this.render();
|
|
387
|
-
this.onChange?.(this.getState());
|
|
388
168
|
}
|
|
389
|
-
|
|
390
|
-
|
|
169
|
+
if (target && "addEventListener" in target && "removeEventListener" in target) {
|
|
170
|
+
const eventTarget = target;
|
|
171
|
+
const onActivate = () => {
|
|
172
|
+
trigger();
|
|
173
|
+
};
|
|
174
|
+
eventTarget.addEventListener("pointerenter", onActivate, { once: true, passive: true });
|
|
175
|
+
eventTarget.addEventListener("focusin", onActivate, { once: true });
|
|
176
|
+
cleanupCallbacks.push(() => {
|
|
177
|
+
eventTarget.removeEventListener("pointerenter", onActivate);
|
|
178
|
+
eventTarget.removeEventListener("focusin", onActivate);
|
|
179
|
+
});
|
|
391
180
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
// src/formula-node.ts
|
|
399
|
-
var DEFAULT_FORMULA_ATTRIBUTE = "data-formulax-latex";
|
|
400
|
-
var FORMULA_FLAG_ATTRIBUTE = "data-formulax";
|
|
401
|
-
var DEFAULT_FORMULA_CLASS = "formulax-math";
|
|
402
|
-
function escapeAttribute(value) {
|
|
403
|
-
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
404
|
-
}
|
|
405
|
-
function escapeHtml(value) {
|
|
406
|
-
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
407
|
-
}
|
|
408
|
-
function createFormulaMarkup(latex, options = {}) {
|
|
409
|
-
const attributeName = options.attributeName ?? DEFAULT_FORMULA_ATTRIBUTE;
|
|
410
|
-
const className = options.className ?? DEFAULT_FORMULA_CLASS;
|
|
411
|
-
const displayClass = options.displayMode ? `${className} ${className}--block` : className;
|
|
412
|
-
const safeLatex = escapeAttribute(latex);
|
|
413
|
-
const cursorStyle = options.cursorStyle?.trim() || "pointer";
|
|
414
|
-
const extraAttributes = {
|
|
415
|
-
...options.extraAttributes ?? {},
|
|
416
|
-
style: mergeInlineStyles(
|
|
417
|
-
typeof options.extraAttributes?.style === "string" ? options.extraAttributes.style : "",
|
|
418
|
-
cursorStyle ? `cursor: ${cursorStyle}` : ""
|
|
419
|
-
)
|
|
181
|
+
return () => {
|
|
182
|
+
disposed = true;
|
|
183
|
+
while (cleanupCallbacks.length) {
|
|
184
|
+
cleanupCallbacks.pop()?.();
|
|
185
|
+
}
|
|
420
186
|
};
|
|
421
|
-
const serializedAttributes = Object.entries(extraAttributes).filter(([, value]) => value !== null && value !== void 0 && value !== false).map(([key, value]) => value === true ? key : `${key}="${escapeAttribute(String(value))}"`);
|
|
422
|
-
return [
|
|
423
|
-
"<span",
|
|
424
|
-
` class="${escapeAttribute(displayClass)}"`,
|
|
425
|
-
` ${FORMULA_FLAG_ATTRIBUTE}="true"`,
|
|
426
|
-
` ${attributeName}="${safeLatex}"`,
|
|
427
|
-
` data-latex="${safeLatex}"`,
|
|
428
|
-
' contenteditable="false"',
|
|
429
|
-
' role="button"',
|
|
430
|
-
' tabindex="0"',
|
|
431
|
-
serializedAttributes.length ? ` ${serializedAttributes.join(" ")}` : "",
|
|
432
|
-
">",
|
|
433
|
-
options.renderHtml ?? `<span class="${escapeAttribute(className)}__render">${escapeHtml(latex || "\\square")}</span>`,
|
|
434
|
-
"</span>"
|
|
435
|
-
].join("");
|
|
436
|
-
}
|
|
437
|
-
function mergeInlineStyles(existingStyle, nextStyle) {
|
|
438
|
-
const existing = existingStyle.trim().replace(/;+\s*$/, "");
|
|
439
|
-
const next = nextStyle.trim().replace(/;+\s*$/, "");
|
|
440
|
-
if (!existing) return next;
|
|
441
|
-
if (!next) return existing;
|
|
442
|
-
return `${existing}; ${next}`;
|
|
443
|
-
}
|
|
444
|
-
function createFormulaElement(ownerDocument, latex, options = {}) {
|
|
445
|
-
const wrapper = ownerDocument.createElement("span");
|
|
446
|
-
wrapper.innerHTML = createFormulaMarkup(latex, options);
|
|
447
|
-
return wrapper.firstElementChild;
|
|
448
|
-
}
|
|
449
|
-
function replaceFormulaElement(target, latex, options = {}) {
|
|
450
|
-
const next = createFormulaElement(target.ownerDocument ?? document, latex, options);
|
|
451
|
-
if (!next) return null;
|
|
452
|
-
target.replaceWith(next);
|
|
453
|
-
return next;
|
|
454
|
-
}
|
|
455
|
-
function getFormulaLatexFromElement(element, attributeName = DEFAULT_FORMULA_ATTRIBUTE) {
|
|
456
|
-
return element.getAttribute(attributeName) ?? element.getAttribute("data-latex") ?? "";
|
|
457
187
|
}
|
|
458
|
-
function
|
|
459
|
-
if (
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
const element = node.nodeType === 1 ? node : node.parentElement;
|
|
466
|
-
return element?.closest?.(`[${FORMULA_FLAG_ATTRIBUTE}="true"]`);
|
|
188
|
+
function waitForFormulaXAnimationFrame() {
|
|
189
|
+
if (typeof window === "undefined" || typeof window.requestAnimationFrame !== "function") {
|
|
190
|
+
return Promise.resolve();
|
|
191
|
+
}
|
|
192
|
+
return new Promise((resolve) => {
|
|
193
|
+
window.requestAnimationFrame(() => resolve());
|
|
194
|
+
});
|
|
467
195
|
}
|
|
468
196
|
|
|
469
197
|
// src/formula-modal.ts
|
|
@@ -604,8 +332,7 @@ var formulaXModalStyles = `
|
|
|
604
332
|
.fx-formula-kity-host .kf-editor svg text,
|
|
605
333
|
.fx-formula-kity-host .kf-editor-ui-area-item-text,
|
|
606
334
|
.fx-formula-kity-host .kf-editor-ui-box-item-text,
|
|
607
|
-
.fx-formula-kity-host .kf-editor-ui-box-item-val
|
|
608
|
-
.formulax-math__render {
|
|
335
|
+
.fx-formula-kity-host .kf-editor-ui-box-item-val {
|
|
609
336
|
font-family: "KF AMS MAIN", "Cambria Math", "Latin Modern Math", "Times New Roman", serif !important;
|
|
610
337
|
}
|
|
611
338
|
|
|
@@ -680,60 +407,35 @@ var formulaXModalStyles = `
|
|
|
680
407
|
background: #2563eb;
|
|
681
408
|
color: #fff;
|
|
682
409
|
}
|
|
683
|
-
|
|
684
|
-
.formulax-math {
|
|
685
|
-
display: inline-flex;
|
|
686
|
-
align-items: center;
|
|
687
|
-
vertical-align: middle;
|
|
688
|
-
line-height: 1;
|
|
689
|
-
padding: 0 2px;
|
|
690
|
-
margin: 0 1px;
|
|
691
|
-
border-radius: 3px;
|
|
692
|
-
background: transparent;
|
|
693
|
-
cursor: pointer;
|
|
694
|
-
user-select: none;
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
.formulax-math:hover {
|
|
698
|
-
outline: 1px solid rgba(37, 99, 235, 0.35);
|
|
699
|
-
background: rgba(37, 99, 235, 0.06);
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
.formulax-math__svg {
|
|
703
|
-
display: inline-block;
|
|
704
|
-
flex: 0 0 auto;
|
|
705
|
-
max-width: 100%;
|
|
706
|
-
vertical-align: -0.35em;
|
|
707
|
-
pointer-events: none;
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
.formulax-math__image {
|
|
711
|
-
display: inline-block;
|
|
712
|
-
max-width: 100%;
|
|
713
|
-
height: auto;
|
|
714
|
-
vertical-align: middle;
|
|
715
|
-
pointer-events: none;
|
|
716
|
-
}
|
|
717
410
|
`;
|
|
718
411
|
function ensureFormulaXModalStyles(doc = document) {
|
|
412
|
+
(0, import_renderer.ensureFormulaXBaseStyles)(doc);
|
|
719
413
|
if (doc.getElementById(STYLE_ID)) return;
|
|
720
414
|
const style = doc.createElement("style");
|
|
721
415
|
style.id = STYLE_ID;
|
|
722
416
|
style.textContent = formulaXModalStyles;
|
|
723
417
|
doc.head.appendChild(style);
|
|
724
418
|
}
|
|
725
|
-
function
|
|
726
|
-
let destroyed = false;
|
|
727
|
-
let latestLatex = options.initialLatex ?? "";
|
|
728
|
-
let handle = null;
|
|
729
|
-
const initialLatex = latestLatex.trim() ? latestLatex : EMPTY_FORMULA_PLACEHOLDER;
|
|
419
|
+
function renderFormulaXEditorLoadingState(root) {
|
|
730
420
|
root.classList.add("fx-formula-kity-host");
|
|
731
421
|
root.innerHTML = `
|
|
732
422
|
<div class="fx-formula-editor-loading" role="status" aria-live="polite">
|
|
733
423
|
Loading FormulaX editor...
|
|
734
424
|
</div>
|
|
735
425
|
`;
|
|
736
|
-
|
|
426
|
+
}
|
|
427
|
+
function mountFormulaXEditor(root, options = {}) {
|
|
428
|
+
recordFormulaXPerfPoint("fx:formula-editor:mount:start");
|
|
429
|
+
const mountStart = markFormulaXPerf("fx:formula-editor:mount:start:scope");
|
|
430
|
+
let destroyed = false;
|
|
431
|
+
let latestLatex = options.initialLatex ?? "";
|
|
432
|
+
let handle = null;
|
|
433
|
+
const initialLatex = latestLatex.trim() ? latestLatex : EMPTY_FORMULA_PLACEHOLDER;
|
|
434
|
+
renderFormulaXEditorLoadingState(root);
|
|
435
|
+
const loadingVisibleMark = markFormulaXPerf("fx:formula-editor:loading-visible");
|
|
436
|
+
measureFormulaXPerf("fx:formula-editor:loading-visible", mountStart, loadingVisibleMark);
|
|
437
|
+
clearFormulaXPerfMarks(loadingVisibleMark);
|
|
438
|
+
const readyPromise = (0, import_kity_runtime2.mountKityEditor)(root, {
|
|
737
439
|
initialLatex,
|
|
738
440
|
height: options.height ?? "100%",
|
|
739
441
|
autofocus: options.autofocus ?? true,
|
|
@@ -746,6 +448,9 @@ function mountFormulaXKityEditor(root, options = {}) {
|
|
|
746
448
|
nextHandle.destroy();
|
|
747
449
|
throw new Error("FormulaX editor mount cancelled");
|
|
748
450
|
}
|
|
451
|
+
const readyMark = markFormulaXPerf("fx:kity-editor:ready");
|
|
452
|
+
measureFormulaXPerf("fx:kity-editor:ready", mountStart, readyMark);
|
|
453
|
+
clearFormulaXPerfMarks(readyMark);
|
|
749
454
|
handle = nextHandle;
|
|
750
455
|
return nextHandle;
|
|
751
456
|
}).catch((error) => {
|
|
@@ -754,11 +459,13 @@ function mountFormulaXKityEditor(root, options = {}) {
|
|
|
754
459
|
root.innerHTML = `
|
|
755
460
|
<div class="fx-formula-editor-error">
|
|
756
461
|
Failed to load FormulaX editor.
|
|
757
|
-
<pre>${escapeHtml(error instanceof Error ? error.message : String(error))}</pre>
|
|
462
|
+
<pre>${(0, import_renderer.escapeHtml)(error instanceof Error ? error.message : String(error))}</pre>
|
|
758
463
|
</div>
|
|
759
464
|
`;
|
|
760
465
|
}
|
|
761
466
|
throw error;
|
|
467
|
+
}).finally(() => {
|
|
468
|
+
clearFormulaXPerfMarks(mountStart);
|
|
762
469
|
});
|
|
763
470
|
const getCurrentLatex = async () => {
|
|
764
471
|
const readyHandle = handle ?? await readyPromise;
|
|
@@ -775,17 +482,17 @@ function mountFormulaXKityEditor(root, options = {}) {
|
|
|
775
482
|
const latex = await getCurrentLatex();
|
|
776
483
|
try {
|
|
777
484
|
return {
|
|
778
|
-
...(0,
|
|
779
|
-
doc: (0,
|
|
485
|
+
...(0, import_core.createEmptyState)(),
|
|
486
|
+
doc: (0, import_core.parseLatex)(latex)
|
|
780
487
|
};
|
|
781
488
|
} catch {
|
|
782
|
-
return (0,
|
|
489
|
+
return (0, import_core.createEmptyState)();
|
|
783
490
|
}
|
|
784
491
|
},
|
|
785
492
|
async getRenderHtml() {
|
|
786
493
|
await readyPromise;
|
|
787
|
-
await
|
|
788
|
-
return
|
|
494
|
+
await (0, import_renderer_kity.waitForKityFormulaSvgLayout)(root);
|
|
495
|
+
return (0, import_renderer_kity.serializeKityFormulaFromRoot)(root);
|
|
789
496
|
},
|
|
790
497
|
destroy() {
|
|
791
498
|
if (destroyed) return;
|
|
@@ -835,400 +542,18 @@ async function tryReadLatexFromKityHandle(handle) {
|
|
|
835
542
|
}
|
|
836
543
|
return null;
|
|
837
544
|
}
|
|
838
|
-
function renderCurrentFormulaAsSvgHtml(root) {
|
|
839
|
-
const svg = findFormulaSvg(root);
|
|
840
|
-
if (!svg) {
|
|
841
|
-
return "";
|
|
842
|
-
}
|
|
843
|
-
return serializeSvgForInsertion(svg);
|
|
844
|
-
}
|
|
845
|
-
async function waitForFormulaSvgLayout(root) {
|
|
846
|
-
const doc = root.ownerDocument ?? document;
|
|
847
|
-
const view = doc.defaultView ?? window;
|
|
848
|
-
await waitForDocumentFonts(doc);
|
|
849
|
-
let previous = readRenderedFormulaBox(root);
|
|
850
|
-
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
851
|
-
await waitForAnimationFrame(view);
|
|
852
|
-
const current = readRenderedFormulaBox(root);
|
|
853
|
-
if (previous && current && areSvgBoxesClose(previous, current)) {
|
|
854
|
-
return;
|
|
855
|
-
}
|
|
856
|
-
previous = current;
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
function findFormulaSvg(root) {
|
|
860
|
-
return root.querySelector(
|
|
861
|
-
".kf-editor-edit-area svg, .kf-editor-canvas-container svg, svg"
|
|
862
|
-
);
|
|
863
|
-
}
|
|
864
|
-
function readRenderedFormulaBox(root) {
|
|
865
|
-
const svg = findFormulaSvg(root);
|
|
866
|
-
if (!svg) {
|
|
867
|
-
return null;
|
|
868
|
-
}
|
|
869
|
-
return getInlineSvgContent(svg)?.box ?? readSvgBox(svg);
|
|
870
|
-
}
|
|
871
|
-
function areSvgBoxesClose(left, right) {
|
|
872
|
-
return Math.abs(left.x - right.x) < 0.01 && Math.abs(left.y - right.y) < 0.01 && Math.abs(left.width - right.width) < 0.01 && Math.abs(left.height - right.height) < 0.01;
|
|
873
|
-
}
|
|
874
|
-
async function waitForDocumentFonts(doc) {
|
|
875
|
-
if (!doc.fonts?.ready) {
|
|
876
|
-
return;
|
|
877
|
-
}
|
|
878
|
-
try {
|
|
879
|
-
await doc.fonts.ready;
|
|
880
|
-
} catch {
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
function waitForAnimationFrame(view) {
|
|
884
|
-
return new Promise((resolve) => {
|
|
885
|
-
view.requestAnimationFrame(() => resolve());
|
|
886
|
-
});
|
|
887
|
-
}
|
|
888
|
-
function serializeSvgForInsertion(svg) {
|
|
889
|
-
const content = getInlineSvgContent(svg);
|
|
890
|
-
const inlineViewport = content ? createInlineSvgViewport(content.box) : null;
|
|
891
|
-
const clone = content && inlineViewport ? createInlineSvgClone(svg, content, inlineViewport) : svg.cloneNode(true);
|
|
892
|
-
uniquifySvgIds(clone);
|
|
893
|
-
sizeSvgForInlineDisplay(clone, svg, inlineViewport);
|
|
894
|
-
clone.removeAttribute("id");
|
|
895
|
-
clone.removeAttribute("xmlns");
|
|
896
|
-
clone.removeAttribute("xmlns:xlink");
|
|
897
|
-
clone.setAttribute("class", mergeClassNames(clone.getAttribute("class"), "formulax-math__svg"));
|
|
898
|
-
clone.setAttribute("focusable", "false");
|
|
899
|
-
clone.setAttribute("aria-hidden", "true");
|
|
900
|
-
clone.setAttribute("preserveAspectRatio", clone.getAttribute("preserveAspectRatio") || "xMinYMin meet");
|
|
901
|
-
return new XMLSerializer().serializeToString(clone);
|
|
902
|
-
}
|
|
903
|
-
function getInlineSvgContent(svg) {
|
|
904
|
-
const candidates = [
|
|
905
|
-
'[data-root="true"] > g[data-type="kf-editor-exp-content-box"]',
|
|
906
|
-
'g[data-type="kf-editor-exp-content-box"]',
|
|
907
|
-
'g[data-type="kf-container"]',
|
|
908
|
-
"svg > g, g"
|
|
909
|
-
];
|
|
910
|
-
for (const selector of candidates) {
|
|
911
|
-
const content = svg.querySelector(selector);
|
|
912
|
-
const rootSpace = content ? readSvgBoxInRootSpace(content) : null;
|
|
913
|
-
if (content && rootSpace) {
|
|
914
|
-
return {
|
|
915
|
-
root: content,
|
|
916
|
-
box: rootSpace.box,
|
|
917
|
-
matrix: rootSpace.matrix
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
return null;
|
|
922
|
-
}
|
|
923
|
-
function readSvgBoxInRootSpace(element) {
|
|
924
|
-
const box = readSvgBox(element);
|
|
925
|
-
const matrix = getSvgRootSpaceMatrix(element);
|
|
926
|
-
if (!box || !matrix) {
|
|
927
|
-
return null;
|
|
928
|
-
}
|
|
929
|
-
const points = [
|
|
930
|
-
{ x: box.x, y: box.y },
|
|
931
|
-
{ x: box.x + box.width, y: box.y },
|
|
932
|
-
{ x: box.x, y: box.y + box.height },
|
|
933
|
-
{ x: box.x + box.width, y: box.y + box.height }
|
|
934
|
-
].map((point) => ({
|
|
935
|
-
x: matrix.a * point.x + matrix.c * point.y + matrix.e,
|
|
936
|
-
y: matrix.b * point.x + matrix.d * point.y + matrix.f
|
|
937
|
-
}));
|
|
938
|
-
const xs = points.map((point) => point.x);
|
|
939
|
-
const ys = points.map((point) => point.y);
|
|
940
|
-
const x = Math.min(...xs);
|
|
941
|
-
const y = Math.min(...ys);
|
|
942
|
-
const width = Math.max(...xs) - x;
|
|
943
|
-
const height = Math.max(...ys) - y;
|
|
944
|
-
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
|
945
|
-
return null;
|
|
946
|
-
}
|
|
947
|
-
return {
|
|
948
|
-
box: { x, y, width, height },
|
|
949
|
-
matrix
|
|
950
|
-
};
|
|
951
|
-
}
|
|
952
|
-
function getSvgRootSpaceMatrix(element) {
|
|
953
|
-
const elementMatrix = typeof element.getCTM === "function" ? element.getCTM() : null;
|
|
954
|
-
const rootMatrix = typeof element.ownerSVGElement?.getCTM === "function" ? element.ownerSVGElement.getCTM() : null;
|
|
955
|
-
if (!elementMatrix) {
|
|
956
|
-
return null;
|
|
957
|
-
}
|
|
958
|
-
return rootMatrix ? multiplySvgMatrices(invertSvgMatrix(rootMatrix), elementMatrix) : toSvgMatrixLike(elementMatrix);
|
|
959
|
-
}
|
|
960
|
-
function invertSvgMatrix(matrix) {
|
|
961
|
-
const determinant = matrix.a * matrix.d - matrix.b * matrix.c;
|
|
962
|
-
if (!Number.isFinite(determinant) || determinant === 0) {
|
|
963
|
-
return {
|
|
964
|
-
a: 1,
|
|
965
|
-
b: 0,
|
|
966
|
-
c: 0,
|
|
967
|
-
d: 1,
|
|
968
|
-
e: 0,
|
|
969
|
-
f: 0
|
|
970
|
-
};
|
|
971
|
-
}
|
|
972
|
-
return {
|
|
973
|
-
a: matrix.d / determinant,
|
|
974
|
-
b: -matrix.b / determinant,
|
|
975
|
-
c: -matrix.c / determinant,
|
|
976
|
-
d: matrix.a / determinant,
|
|
977
|
-
e: (matrix.c * matrix.f - matrix.d * matrix.e) / determinant,
|
|
978
|
-
f: (matrix.b * matrix.e - matrix.a * matrix.f) / determinant
|
|
979
|
-
};
|
|
980
|
-
}
|
|
981
|
-
function multiplySvgMatrices(left, right) {
|
|
982
|
-
return {
|
|
983
|
-
a: left.a * right.a + left.c * right.b,
|
|
984
|
-
b: left.b * right.a + left.d * right.b,
|
|
985
|
-
c: left.a * right.c + left.c * right.d,
|
|
986
|
-
d: left.b * right.c + left.d * right.d,
|
|
987
|
-
e: left.a * right.e + left.c * right.f + left.e,
|
|
988
|
-
f: left.b * right.e + left.d * right.f + left.f
|
|
989
|
-
};
|
|
990
|
-
}
|
|
991
|
-
function toSvgMatrixLike(matrix) {
|
|
992
|
-
return {
|
|
993
|
-
a: matrix.a,
|
|
994
|
-
b: matrix.b,
|
|
995
|
-
c: matrix.c,
|
|
996
|
-
d: matrix.d,
|
|
997
|
-
e: matrix.e,
|
|
998
|
-
f: matrix.f
|
|
999
|
-
};
|
|
1000
|
-
}
|
|
1001
|
-
function readSvgBox(element) {
|
|
1002
|
-
if (typeof element.getBBox !== "function") {
|
|
1003
|
-
return null;
|
|
1004
|
-
}
|
|
1005
|
-
try {
|
|
1006
|
-
const box = element.getBBox();
|
|
1007
|
-
if (!Number.isFinite(box.width) || !Number.isFinite(box.height) || box.width <= 0 || box.height <= 0) {
|
|
1008
|
-
return null;
|
|
1009
|
-
}
|
|
1010
|
-
return {
|
|
1011
|
-
x: box.x,
|
|
1012
|
-
y: box.y,
|
|
1013
|
-
width: box.width,
|
|
1014
|
-
height: box.height
|
|
1015
|
-
};
|
|
1016
|
-
} catch {
|
|
1017
|
-
return null;
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
function createInlineSvgViewport(contentBox) {
|
|
1021
|
-
const edgePadding = Math.max(0.5, Math.min(contentBox.width, contentBox.height) * 6e-3);
|
|
1022
|
-
const inset = edgePadding / 2;
|
|
1023
|
-
return {
|
|
1024
|
-
x: contentBox.x - inset,
|
|
1025
|
-
y: contentBox.y - inset,
|
|
1026
|
-
width: contentBox.width + edgePadding,
|
|
1027
|
-
height: contentBox.height + edgePadding
|
|
1028
|
-
};
|
|
1029
|
-
}
|
|
1030
|
-
function createInlineSvgClone(source, content, viewport) {
|
|
1031
|
-
const clone = source.cloneNode(false);
|
|
1032
|
-
const ownerDocument = source.ownerDocument;
|
|
1033
|
-
copySvgRootAttributes(source, clone);
|
|
1034
|
-
clone.setAttribute(
|
|
1035
|
-
"viewBox",
|
|
1036
|
-
`0 0 ${roundLength(viewport.width)} ${roundLength(viewport.height)}`
|
|
1037
|
-
);
|
|
1038
|
-
Array.from(source.children).forEach((child) => {
|
|
1039
|
-
if (child.tagName.toLowerCase() === "defs") {
|
|
1040
|
-
clone.appendChild(child.cloneNode(true));
|
|
1041
|
-
}
|
|
1042
|
-
});
|
|
1043
|
-
const wrapper = ownerDocument.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
1044
|
-
wrapper.setAttribute(
|
|
1045
|
-
"transform",
|
|
1046
|
-
`translate(${roundLength(-viewport.x)} ${roundLength(-viewport.y)})`
|
|
1047
|
-
);
|
|
1048
|
-
const flattened = ownerDocument.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
1049
|
-
flattened.setAttribute(
|
|
1050
|
-
"transform",
|
|
1051
|
-
`matrix(${roundLength(content.matrix.a)} ${roundLength(content.matrix.b)} ${roundLength(content.matrix.c)} ${roundLength(content.matrix.d)} ${roundLength(content.matrix.e)} ${roundLength(content.matrix.f)})`
|
|
1052
|
-
);
|
|
1053
|
-
flattened.appendChild(content.root.cloneNode(true));
|
|
1054
|
-
wrapper.appendChild(flattened);
|
|
1055
|
-
clone.appendChild(wrapper);
|
|
1056
|
-
return clone;
|
|
1057
|
-
}
|
|
1058
|
-
function copySvgRootAttributes(source, target) {
|
|
1059
|
-
const excluded = /* @__PURE__ */ new Set([
|
|
1060
|
-
"id",
|
|
1061
|
-
"width",
|
|
1062
|
-
"height",
|
|
1063
|
-
"viewBox",
|
|
1064
|
-
"class",
|
|
1065
|
-
"focusable",
|
|
1066
|
-
"aria-hidden",
|
|
1067
|
-
"xmlns",
|
|
1068
|
-
"xmlns:xlink"
|
|
1069
|
-
]);
|
|
1070
|
-
Array.from(source.attributes).forEach((attribute) => {
|
|
1071
|
-
if (excluded.has(attribute.name)) return;
|
|
1072
|
-
target.setAttribute(attribute.name, attribute.value);
|
|
1073
|
-
});
|
|
1074
|
-
}
|
|
1075
|
-
function sizeSvgForInlineDisplay(clone, source, viewport) {
|
|
1076
|
-
const viewBox = clone.viewBox?.baseVal;
|
|
1077
|
-
const rect = source.getBoundingClientRect();
|
|
1078
|
-
const width = viewport?.width || viewBox?.width || rect.width || Number(clone.getAttribute("width")) || 1;
|
|
1079
|
-
const height = viewport?.height || viewBox?.height || rect.height || Number(clone.getAttribute("height")) || 1;
|
|
1080
|
-
const ratio = Math.max(0.1, width / Math.max(1, height));
|
|
1081
|
-
const inlineHeightEm = 0.875;
|
|
1082
|
-
const inlineWidthEm = Math.min(40, Math.max(0.75, ratio * inlineHeightEm));
|
|
1083
|
-
clone.setAttribute("width", roundLength(width));
|
|
1084
|
-
clone.setAttribute("height", roundLength(height));
|
|
1085
|
-
clone.setAttribute(
|
|
1086
|
-
"style",
|
|
1087
|
-
mergeInlineStyles2(
|
|
1088
|
-
clone.getAttribute("style"),
|
|
1089
|
-
`width:${roundLength(inlineWidthEm)}em`,
|
|
1090
|
-
`height:${inlineHeightEm}em`
|
|
1091
|
-
)
|
|
1092
|
-
);
|
|
1093
|
-
}
|
|
1094
|
-
function roundLength(value) {
|
|
1095
|
-
return String(Math.round(value * 1e3) / 1e3);
|
|
1096
|
-
}
|
|
1097
|
-
function uniquifySvgIds(svg) {
|
|
1098
|
-
const idMap = /* @__PURE__ */ new Map();
|
|
1099
|
-
const prefix = `fx-${randomIdPrefix()}-`;
|
|
1100
|
-
const elementsWithId = svg.querySelectorAll("[id]");
|
|
1101
|
-
elementsWithId.forEach((element) => {
|
|
1102
|
-
const id = element.getAttribute("id");
|
|
1103
|
-
if (!id) return;
|
|
1104
|
-
const nextId = `${prefix}${id}`;
|
|
1105
|
-
idMap.set(id, nextId);
|
|
1106
|
-
element.setAttribute("id", nextId);
|
|
1107
|
-
});
|
|
1108
|
-
if (!idMap.size) return;
|
|
1109
|
-
svg.querySelectorAll("*").forEach((element) => {
|
|
1110
|
-
Array.from(element.attributes).forEach((attribute) => {
|
|
1111
|
-
const nextValue = rewriteSvgReferences(attribute.value, idMap);
|
|
1112
|
-
if (nextValue !== attribute.value) {
|
|
1113
|
-
element.setAttribute(attribute.name, nextValue);
|
|
1114
|
-
}
|
|
1115
|
-
});
|
|
1116
|
-
});
|
|
1117
|
-
}
|
|
1118
|
-
function randomIdPrefix() {
|
|
1119
|
-
return Math.random().toString(36).slice(2, 5).padEnd(3, "0");
|
|
1120
|
-
}
|
|
1121
|
-
function rewriteSvgReferences(value, idMap) {
|
|
1122
|
-
let nextValue = value;
|
|
1123
|
-
idMap.forEach((nextId, id) => {
|
|
1124
|
-
nextValue = nextValue.replaceAll(`#${id}`, `#${nextId}`).replaceAll(`url(${id})`, `url(${nextId})`).replaceAll(`url(#${id})`, `url(#${nextId})`);
|
|
1125
|
-
});
|
|
1126
|
-
return nextValue;
|
|
1127
|
-
}
|
|
1128
|
-
function mergeClassNames(...values) {
|
|
1129
|
-
return values.flatMap((value) => value?.split(/\s+/) ?? []).filter(Boolean).filter((value, index, list) => list.indexOf(value) === index).join(" ");
|
|
1130
|
-
}
|
|
1131
|
-
function mergeInlineStyles2(...values) {
|
|
1132
|
-
return values.flatMap((value) => value?.split(";") ?? []).map((value) => value.trim()).filter(Boolean).join("; ");
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
// src/i18n.ts
|
|
1136
|
-
var translations = {
|
|
1137
|
-
en: {
|
|
1138
|
-
equation: "Equation",
|
|
1139
|
-
structures: "Structures",
|
|
1140
|
-
symbols: "Symbols",
|
|
1141
|
-
matrices: "Matrices",
|
|
1142
|
-
templates: "Templates",
|
|
1143
|
-
insert: "Insert",
|
|
1144
|
-
greek: "Greek",
|
|
1145
|
-
operators: "Operators",
|
|
1146
|
-
relations: "Relations",
|
|
1147
|
-
fraction: "Fraction",
|
|
1148
|
-
superscript: "Superscript",
|
|
1149
|
-
subscript: "Subscript",
|
|
1150
|
-
squareRoot: "Square Root",
|
|
1151
|
-
parentheses: "Parentheses",
|
|
1152
|
-
plusMinus: "Plus Minus",
|
|
1153
|
-
multiply: "Multiply",
|
|
1154
|
-
divide: "Divide",
|
|
1155
|
-
dot: "Dot",
|
|
1156
|
-
union: "Union",
|
|
1157
|
-
intersect: "Intersection",
|
|
1158
|
-
lessOrEqual: "Less or Equal",
|
|
1159
|
-
greaterOrEqual: "Greater or Equal",
|
|
1160
|
-
notEqual: "Not Equal",
|
|
1161
|
-
approximate: "Approximate",
|
|
1162
|
-
infinity: "Infinity",
|
|
1163
|
-
arrow: "Arrow",
|
|
1164
|
-
limit: "Limit",
|
|
1165
|
-
sine: "Sine",
|
|
1166
|
-
logarithm: "Logarithm",
|
|
1167
|
-
matrix: "Matrix",
|
|
1168
|
-
summation: "Summation",
|
|
1169
|
-
integral: "Integral",
|
|
1170
|
-
placeholder: "WPS-inspired ribbon layout. Some tiles are placeholders for future SDK features."
|
|
1171
|
-
},
|
|
1172
|
-
zh: {
|
|
1173
|
-
equation: "\u516C\u5F0F",
|
|
1174
|
-
structures: "\u7ED3\u6784",
|
|
1175
|
-
symbols: "\u7B26\u53F7",
|
|
1176
|
-
matrices: "\u77E9\u9635",
|
|
1177
|
-
templates: "\u6A21\u677F",
|
|
1178
|
-
insert: "\u63D2\u5165",
|
|
1179
|
-
greek: "\u5E0C\u814A\u5B57\u6BCD",
|
|
1180
|
-
operators: "\u8FD0\u7B97\u7B26",
|
|
1181
|
-
relations: "\u5173\u7CFB",
|
|
1182
|
-
fraction: "\u5206\u6570",
|
|
1183
|
-
superscript: "\u4E0A\u6807",
|
|
1184
|
-
subscript: "\u4E0B\u6807",
|
|
1185
|
-
squareRoot: "\u5E73\u65B9\u6839",
|
|
1186
|
-
parentheses: "\u62EC\u53F7",
|
|
1187
|
-
plusMinus: "\u52A0\u51CF",
|
|
1188
|
-
multiply: "\u4E58",
|
|
1189
|
-
divide: "\u9664",
|
|
1190
|
-
dot: "\u70B9\u4E58",
|
|
1191
|
-
union: "\u5E76\u96C6",
|
|
1192
|
-
intersect: "\u4EA4\u96C6",
|
|
1193
|
-
lessOrEqual: "\u5C0F\u4E8E\u7B49\u4E8E",
|
|
1194
|
-
greaterOrEqual: "\u5927\u4E8E\u7B49\u4E8E",
|
|
1195
|
-
notEqual: "\u4E0D\u7B49\u4E8E",
|
|
1196
|
-
approximate: "\u7EA6\u7B49\u4E8E",
|
|
1197
|
-
infinity: "\u65E0\u7A77",
|
|
1198
|
-
arrow: "\u7BAD\u5934",
|
|
1199
|
-
limit: "\u6781\u9650",
|
|
1200
|
-
sine: "\u6B63\u5F26",
|
|
1201
|
-
logarithm: "\u5BF9\u6570",
|
|
1202
|
-
matrix: "\u77E9\u9635",
|
|
1203
|
-
summation: "\u6C42\u548C",
|
|
1204
|
-
integral: "\u79EF\u5206",
|
|
1205
|
-
placeholder: "WPS \u98CE\u683C\u7684\u5DE5\u5177\u680F\u5E03\u5C40\u3002\u90E8\u5206\u6309\u94AE\u4ECD\u662F\u672A\u6765 SDK \u529F\u80FD\u7684\u5360\u4F4D\u9879\u3002"
|
|
1206
|
-
}
|
|
1207
|
-
};
|
|
1208
|
-
function t(locale, key) {
|
|
1209
|
-
return translations[locale][key] ?? translations.en[key];
|
|
1210
|
-
}
|
|
1211
545
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1212
546
|
0 && (module.exports = {
|
|
1213
|
-
|
|
1214
|
-
DEFAULT_FORMULA_CLASS,
|
|
1215
|
-
FORMULA_FLAG_ATTRIBUTE,
|
|
1216
|
-
FormulaEditor,
|
|
1217
|
-
createFormulaElement,
|
|
1218
|
-
createFormulaMarkup,
|
|
1219
|
-
editorStyles,
|
|
547
|
+
clearFormulaXPerfMarks,
|
|
1220
548
|
ensureFormulaXModalStyles,
|
|
1221
|
-
escapeAttribute,
|
|
1222
|
-
escapeHtml,
|
|
1223
|
-
findFormulaElement,
|
|
1224
549
|
formulaXModalStyles,
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
550
|
+
markFormulaXPerf,
|
|
551
|
+
measureFormulaXPerf,
|
|
552
|
+
mountFormulaXEditor,
|
|
553
|
+
preloadFormulaXEditor,
|
|
554
|
+
recordFormulaXPerfPoint,
|
|
555
|
+
renderFormulaXEditorLoadingState,
|
|
556
|
+
scheduleFormulaXEditorPreload,
|
|
557
|
+
waitForFormulaXAnimationFrame
|
|
1233
558
|
});
|
|
1234
559
|
//# sourceMappingURL=index.cjs.map
|