@formulaxjs/editor 0.2.0 → 0.3.1

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.
@@ -21,6 +21,105 @@ var FormulaX = (() => {
21
21
  };
22
22
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
23
23
 
24
+ // ../kity-runtime/public/assets/images/toolbar/btn.png
25
+ var btn_default;
26
+ var init_btn = __esm({
27
+ "../kity-runtime/public/assets/images/toolbar/btn.png"() {
28
+ btn_default = "./btn-5DANP6JY.png";
29
+ }
30
+ });
31
+
32
+ // ../kity-runtime/public/assets/images/toolbar/other.png
33
+ var other_default;
34
+ var init_other = __esm({
35
+ "../kity-runtime/public/assets/images/toolbar/other.png"() {
36
+ other_default = "./other-OMWJFGL5.png";
37
+ }
38
+ });
39
+
40
+ // ../kity-runtime/public/assets/styles/editor.css?url
41
+ var editor_default;
42
+ var init_editor = __esm({
43
+ "../kity-runtime/public/assets/styles/editor.css?url"() {
44
+ editor_default = "./editor-JT5KLVXX.css?url";
45
+ }
46
+ });
47
+
48
+ // ../kity-runtime/public/resource/KF_AMS_BB.woff
49
+ var KF_AMS_BB_default;
50
+ var init_KF_AMS_BB = __esm({
51
+ "../kity-runtime/public/resource/KF_AMS_BB.woff"() {
52
+ KF_AMS_BB_default = "./KF_AMS_BB-5QF7FUSO.woff";
53
+ }
54
+ });
55
+
56
+ // ../kity-runtime/public/resource/KF_AMS_CAL.woff
57
+ var KF_AMS_CAL_default;
58
+ var init_KF_AMS_CAL = __esm({
59
+ "../kity-runtime/public/resource/KF_AMS_CAL.woff"() {
60
+ KF_AMS_CAL_default = "./KF_AMS_CAL-NXRNLAZN.woff";
61
+ }
62
+ });
63
+
64
+ // ../kity-runtime/public/resource/KF_AMS_FRAK.woff
65
+ var KF_AMS_FRAK_default;
66
+ var init_KF_AMS_FRAK = __esm({
67
+ "../kity-runtime/public/resource/KF_AMS_FRAK.woff"() {
68
+ KF_AMS_FRAK_default = "./KF_AMS_FRAK-CO33WWN4.woff";
69
+ }
70
+ });
71
+
72
+ // ../kity-runtime/public/resource/KF_AMS_MAIN.woff
73
+ var KF_AMS_MAIN_default;
74
+ var init_KF_AMS_MAIN = __esm({
75
+ "../kity-runtime/public/resource/KF_AMS_MAIN.woff"() {
76
+ KF_AMS_MAIN_default = "./KF_AMS_MAIN-25QJVAWY.woff";
77
+ }
78
+ });
79
+
80
+ // ../kity-runtime/public/resource/KF_AMS_ROMAN.woff
81
+ var KF_AMS_ROMAN_default;
82
+ var init_KF_AMS_ROMAN = __esm({
83
+ "../kity-runtime/public/resource/KF_AMS_ROMAN.woff"() {
84
+ KF_AMS_ROMAN_default = "./KF_AMS_ROMAN-243BR7HH.woff";
85
+ }
86
+ });
87
+
88
+ // ../kity-runtime/src/asset-manifest.ts
89
+ var kityFontAssets, kityToolbarAssets, kityStyleAssets, kityAssetManifest;
90
+ var init_asset_manifest = __esm({
91
+ "../kity-runtime/src/asset-manifest.ts"() {
92
+ "use strict";
93
+ init_btn();
94
+ init_other();
95
+ init_editor();
96
+ init_KF_AMS_BB();
97
+ init_KF_AMS_CAL();
98
+ init_KF_AMS_FRAK();
99
+ init_KF_AMS_MAIN();
100
+ init_KF_AMS_ROMAN();
101
+ kityFontAssets = {
102
+ KF_AMS_BB: KF_AMS_BB_default,
103
+ KF_AMS_CAL: KF_AMS_CAL_default,
104
+ KF_AMS_FRAK: KF_AMS_FRAK_default,
105
+ KF_AMS_MAIN: KF_AMS_MAIN_default,
106
+ KF_AMS_ROMAN: KF_AMS_ROMAN_default
107
+ };
108
+ kityToolbarAssets = {
109
+ btn: btn_default,
110
+ other: other_default
111
+ };
112
+ kityStyleAssets = {
113
+ editor: editor_default
114
+ };
115
+ kityAssetManifest = {
116
+ fonts: kityFontAssets,
117
+ toolbar: kityToolbarAssets,
118
+ styles: kityStyleAssets
119
+ };
120
+ }
121
+ });
122
+
24
123
  // ../kity-runtime/src/vendor/legacy-box-type.ts
25
124
  var legacyBoxType;
26
125
  var init_legacy_box_type = __esm({
@@ -4965,7 +5064,26 @@ var FormulaX = (() => {
4965
5064
  var init_toolbar_assets = __esm({
4966
5065
  "../kity-runtime/src/toolbar-assets.ts"() {
4967
5066
  "use strict";
4968
- toolbarAssetFileMap = {};
5067
+ init_asset_manifest();
5068
+ toolbarAssetFileMap = {
5069
+ "btn.png": kityToolbarAssets.btn,
5070
+ "other.png": kityToolbarAssets.other
5071
+ };
5072
+ }
5073
+ });
5074
+
5075
+ // ../kity-runtime/src/i18n.ts
5076
+ function normalizeFormulaXLocale(locale) {
5077
+ if (locale === "zh_CN") {
5078
+ return "zh_CN";
5079
+ }
5080
+ return DEFAULT_FORMULAX_LOCALE;
5081
+ }
5082
+ var DEFAULT_FORMULAX_LOCALE;
5083
+ var init_i18n = __esm({
5084
+ "../kity-runtime/src/i18n.ts"() {
5085
+ "use strict";
5086
+ DEFAULT_FORMULAX_LOCALE = "en_US";
4969
5087
  }
4970
5088
  });
4971
5089
 
@@ -5854,14 +5972,11 @@ var FormulaX = (() => {
5854
5972
  count += 1;
5855
5973
  fontInfo.meta.src = resolveFontSource(this.fonts, this.resource, fontInfo.meta.src);
5856
5974
  this.createFontStyle(fontInfo);
5857
- preloadFont(this.doc, fontInfo).then(() => {
5858
- applyFonts(this.doc, fontInfo);
5859
- }).catch(() => void 0).finally(() => {
5860
- count -= 1;
5861
- if (count === 0) {
5862
- complete(this.doc, callback);
5863
- }
5864
- });
5975
+ applyFonts(this.doc, fontInfo);
5976
+ count -= 1;
5977
+ if (count === 0) {
5978
+ complete(this.doc, callback);
5979
+ }
5865
5980
  });
5866
5981
  },
5867
5982
  createFontStyle: function(fontInfo) {
@@ -5872,13 +5987,6 @@ var FormulaX = (() => {
5872
5987
  this.doc.head.appendChild(stylesheet);
5873
5988
  }
5874
5989
  });
5875
- function preloadFont(doc2, fontInfo) {
5876
- const view = doc2.defaultView ?? window;
5877
- if (view.fetch) {
5878
- return view.fetch(fontInfo.meta.src, { method: "GET" }).then(() => void 0);
5879
- }
5880
- return Promise.resolve();
5881
- }
5882
5990
  function resolveFontSource(fonts, resourceBase, originalSrc) {
5883
5991
  const directMatch = fonts[originalSrc];
5884
5992
  if (directMatch) {
@@ -6036,11 +6144,11 @@ var FormulaX = (() => {
6036
6144
  bg;
6037
6145
  exp;
6038
6146
  config;
6039
- constructor(kity26, exp, config2) {
6147
+ constructor(kity26, exp, config) {
6040
6148
  this.wrap = new kity26.Group();
6041
6149
  this.bg = new kity26.Rect(0, 0, 0, 0).fill("transparent");
6042
6150
  this.exp = exp;
6043
- this.config = config2;
6151
+ this.config = config;
6044
6152
  this.wrap.setAttr("data-type", "kf-exp-wrap");
6045
6153
  this.bg.setAttr("data-type", "kf-exp-wrap-bg");
6046
6154
  this.wrap.addShape(this.bg);
@@ -6069,14 +6177,14 @@ var FormulaX = (() => {
6069
6177
  static create(kity26, GTYPE2, FontManager, FontInstaller, FPaper, Output) {
6070
6178
  const Formula = kity26.createClass("Formula", {
6071
6179
  base: FPaper,
6072
- constructor: function(container, config2) {
6180
+ constructor: function(container, config) {
6073
6181
  if (this.__FORMULAX_PRESERVE_CALL_BASE__) {
6074
6182
  this.callBase(container);
6075
6183
  }
6076
6184
  FPaper.call(this, container);
6077
6185
  this.expressions = [];
6078
6186
  this.fontInstaller = new FontInstaller(this);
6079
- this.config = kity26.Utils.extend({}, DEFAULT_OPTIONS, config2);
6187
+ this.config = kity26.Utils.extend({}, DEFAULT_OPTIONS, config);
6080
6188
  this.initEnvironment();
6081
6189
  this.initInnerFont();
6082
6190
  },
@@ -13541,7 +13649,7 @@ var FormulaX = (() => {
13541
13649
  value: function() {
13542
13650
  const kf7 = window2.kf;
13543
13651
  const CONSTRUCT_MAPPING = {};
13544
- const CURSOR_CHAR3 = "\uF155";
13652
+ const CURSOR_CHAR4 = "\uF155";
13545
13653
  class Assembly {
13546
13654
  formula;
13547
13655
  constructor(formula) {
@@ -13578,7 +13686,7 @@ var FormulaX = (() => {
13578
13686
  if (tree.name.indexOf("text") === -1) {
13579
13687
  for (let i2 = 0, len = operand.length; i2 < len; i2 += 1) {
13580
13688
  currentOperand = operand[i2];
13581
- if (currentOperand === CURSOR_CHAR3) {
13689
+ if (currentOperand === CURSOR_CHAR4) {
13582
13690
  cursorLocation.push(i2);
13583
13691
  if (!Object.prototype.hasOwnProperty.call(selectInfo, "startOffset")) {
13584
13692
  selectInfo.startOffset = i2;
@@ -14873,7 +14981,7 @@ var FormulaX = (() => {
14873
14981
  return serviceObject;
14874
14982
  }
14875
14983
  var defaultOptions, components, kity2, kf, KFEditor, editor_default2;
14876
- var init_editor = __esm({
14984
+ var init_editor2 = __esm({
14877
14985
  "../kity-runtime/src/legacy/editor.ts"() {
14878
14986
  "use strict";
14879
14987
  init_legacy_utils();
@@ -14993,7 +15101,7 @@ var FormulaX = (() => {
14993
15101
  var init_factory = __esm({
14994
15102
  "../kity-runtime/src/legacy/factory.ts"() {
14995
15103
  "use strict";
14996
- init_editor();
15104
+ init_editor2();
14997
15105
  init_runtime_interop();
14998
15106
  EditorWrapper = class {
14999
15107
  callbacks = [];
@@ -16750,6 +16858,35 @@ var FormulaX = (() => {
16750
16858
  }
16751
16859
  Object.keys(list).forEach((key) => callback(list[key], key));
16752
16860
  }
16861
+ function translateToolbarText(value, locale) {
16862
+ if (locale === "zh_CN") {
16863
+ return value;
16864
+ }
16865
+ const normalizedValue = value.replace(/<br\s*\/?>/gi, "").trim();
16866
+ const translatedValue = zhCnToEnUsText.get(normalizedValue);
16867
+ if (!translatedValue) {
16868
+ return value;
16869
+ }
16870
+ const lineBreakMatch = value.match(/<br\s*\/?>/i);
16871
+ return lineBreakMatch ? `${translatedValue}${lineBreakMatch[0]}` : translatedValue;
16872
+ }
16873
+ function localizeToolbarConfig(value, locale) {
16874
+ if (Array.isArray(value)) {
16875
+ return value.map((item) => localizeToolbarConfig(item, locale));
16876
+ }
16877
+ if (!value || typeof value !== "object") {
16878
+ return value;
16879
+ }
16880
+ const result = {};
16881
+ for (const [key, currentValue] of Object.entries(value)) {
16882
+ if ((key === "label" || key === "title") && typeof currentValue === "string") {
16883
+ result[key] = translateToolbarText(currentValue, locale);
16884
+ continue;
16885
+ }
16886
+ result[key] = localizeToolbarConfig(currentValue, locale);
16887
+ }
16888
+ return result;
16889
+ }
16753
16890
  function getUnicodeContents(keySet) {
16754
16891
  let result = [];
16755
16892
  each(keySet, function(key) {
@@ -16769,7 +16906,13 @@ var FormulaX = (() => {
16769
16906
  });
16770
16907
  return result;
16771
16908
  }
16772
- var UI_ELE_TYPE, BOX_TYPE2, OTHER_POSITION, config, toolbar_config_default;
16909
+ function createToolbarConfig(locale = DEFAULT_FORMULAX_LOCALE) {
16910
+ return localizeToolbarConfig(
16911
+ baseToolbarConfig,
16912
+ normalizeFormulaXLocale(locale)
16913
+ );
16914
+ }
16915
+ var UI_ELE_TYPE, BOX_TYPE2, OTHER_POSITION, zhCnToEnUsText, baseToolbarConfig, toolbar_config_default;
16773
16916
  var init_toolbar_config = __esm({
16774
16917
  "../kity-runtime/src/legacy/toolbar-config.ts"() {
16775
16918
  "use strict";
@@ -16778,10 +16921,45 @@ var FormulaX = (() => {
16778
16921
  init_other_position();
16779
16922
  init_toolbar_assets();
16780
16923
  init_formula_symbols();
16924
+ init_i18n();
16781
16925
  UI_ELE_TYPE = legacyEleType;
16782
16926
  BOX_TYPE2 = legacyBoxType;
16783
16927
  OTHER_POSITION = legacyOtherPosition;
16784
- config = [{
16928
+ zhCnToEnUsText = /* @__PURE__ */ new Map([
16929
+ ["\u9884\u8BBE", "Presets"],
16930
+ ["\u9884\u8BBE\u516C\u5F0F", "Preset formulas"],
16931
+ ["\u4E8C\u6B21\u516C\u5F0F", "Quadratic formula"],
16932
+ ["\u4E8C\u9879\u5F0F\u5B9A\u7406", "Binomial theorem"],
16933
+ ["\u52FE\u80A1\u5B9A\u7406", "Pythagorean theorem"],
16934
+ ["\u57FA\u7840\u6570\u5B66", "Basic math"],
16935
+ ["\u5E0C\u814A\u5B57\u6BCD", "Greek letters"],
16936
+ ["\u6C42\u53CD\u5173\u7CFB\u8FD0\u7B97\u7B26", "Negated operators"],
16937
+ ["\u5B57\u6BCD\u7C7B\u7B26\u53F7", "Letter-like symbols"],
16938
+ ["\u7BAD\u5934", "Arrows"],
16939
+ ["\u624B\u5199\u4F53", "Script"],
16940
+ ["\u5206\u6570", "Fraction"],
16941
+ ["\u5E38\u7528\u5206\u6570", "Common fractions"],
16942
+ ["\u4E0A\u4E0B\u6807", "Scripts"],
16943
+ ["\u4E0A\u6807\u548C\u4E0B\u6807", "Superscripts and subscripts"],
16944
+ ["\u5E38\u7528\u7684\u4E0A\u6807\u548C\u4E0B\u6807", "Common superscripts and subscripts"],
16945
+ ["\u6839\u5F0F", "Radicals"],
16946
+ ["\u5E38\u7528\u6839\u5F0F", "Common radicals"],
16947
+ ["\u79EF\u5206", "Integrals"],
16948
+ ["\u5927\u578B\u8FD0\u7B97\u7B26", "Large operators"],
16949
+ ["\u6C42\u548C", "Summations"],
16950
+ ["\u62EC\u53F7", "Brackets"],
16951
+ ["\u65B9\u62EC\u53F7", "Brackets"],
16952
+ ["\u51FD\u6570", "Functions"],
16953
+ ["\u4E09\u89D2\u51FD\u6570", "Trigonometric functions"],
16954
+ ["\u5E38\u7528\u51FD\u6570", "Common functions"],
16955
+ ["\u5C0F\u5199", "Lowercase"],
16956
+ ["\u5927\u5199", "Uppercase"],
16957
+ ["\u53D8\u4F53", "Variants"],
16958
+ ["\u82B1\u4F53", "Fraktur"],
16959
+ ["\u53CC\u7EBF", "Double-struck"],
16960
+ ["\u7F57\u9A6C", "Roman"]
16961
+ ]);
16962
+ baseToolbarConfig = [{
16785
16963
  type: UI_ELE_TYPE.DRAPDOWN_BOX,
16786
16964
  options: {
16787
16965
  button: {
@@ -17187,7 +17365,7 @@ var FormulaX = (() => {
17187
17365
  }];
17188
17366
  (function() {
17189
17367
  let tmp = [], otherImageSrc = resolveToolbarAssetPath("other.png"), currentConf = [];
17190
- each(config, function(conf) {
17368
+ each(baseToolbarConfig, function(conf) {
17191
17369
  if (conf.type === UI_ELE_TYPE.DELIMITER) {
17192
17370
  return;
17193
17371
  }
@@ -17259,7 +17437,7 @@ var FormulaX = (() => {
17259
17437
  "aleph",
17260
17438
  "beth",
17261
17439
  "blacksquare"
17262
- ], configList = config[2].options.box.group[0].items;
17440
+ ], configList = baseToolbarConfig[2].options.box.group[0].items;
17263
17441
  configList.push({
17264
17442
  title: "\u57FA\u7840\u6570\u5B66",
17265
17443
  content: getUnicodeContents(list)
@@ -17275,7 +17453,7 @@ var FormulaX = (() => {
17275
17453
  }, {
17276
17454
  title: "\u53D8\u4F53",
17277
17455
  values: ["digamma", "varepsilon", "varkappa", "varphi", "varpi", "varrho", "varsigma", "vartheta"]
17278
- }], greekConfigList = config[2].options.box.group[1].items;
17456
+ }], greekConfigList = baseToolbarConfig[2].options.box.group[1].items;
17279
17457
  greekConfigList.push({
17280
17458
  title: greekList[0].title,
17281
17459
  content: getUnicodeContents(greekList[0].values)
@@ -17324,7 +17502,7 @@ var FormulaX = (() => {
17324
17502
  "nVDash",
17325
17503
  "nexists"
17326
17504
  ]
17327
- }], greekConfigList = config[2].options.box.group[2].items;
17505
+ }], greekConfigList = baseToolbarConfig[2].options.box.group[2].items;
17328
17506
  greekConfigList.push({
17329
17507
  title: greekList[0].title,
17330
17508
  content: getUnicodeContents(greekList[0].values)
@@ -17350,7 +17528,7 @@ var FormulaX = (() => {
17350
17528
  "Game",
17351
17529
  "Im",
17352
17530
  "Re"
17353
- ], configList = config[2].options.box.group[3].items;
17531
+ ], configList = baseToolbarConfig[2].options.box.group[3].items;
17354
17532
  configList.push({
17355
17533
  title: "\u5B57\u6BCD\u7C7B\u7B26\u53F7",
17356
17534
  content: getUnicodeContents(list)
@@ -17418,7 +17596,7 @@ var FormulaX = (() => {
17418
17596
  "twoheadleftarrow",
17419
17597
  "twoheadrightarrow",
17420
17598
  "rightsquigarrow"
17421
- ], configList = config[2].options.box.group[4].items;
17599
+ ], configList = baseToolbarConfig[2].options.box.group[4].items;
17422
17600
  configList.push({
17423
17601
  title: "\u7BAD\u5934",
17424
17602
  content: getUnicodeContents(list)
@@ -17597,7 +17775,7 @@ var FormulaX = (() => {
17597
17775
  "y",
17598
17776
  "z"
17599
17777
  ]
17600
- }], configList = config[2].options.box.group[5].items;
17778
+ }], configList = baseToolbarConfig[2].options.box.group[5].items;
17601
17779
  each(list[0].values, function(item, index) {
17602
17780
  list[0].values[index] = "mathcal{" + item + "}";
17603
17781
  });
@@ -17627,7 +17805,7 @@ var FormulaX = (() => {
17627
17805
  content: getUnicodeContents(list[3].values)
17628
17806
  });
17629
17807
  })();
17630
- toolbar_config_default = config;
17808
+ toolbar_config_default = createToolbarConfig;
17631
17809
  }
17632
17810
  });
17633
17811
 
@@ -17670,6 +17848,7 @@ var FormulaX = (() => {
17670
17848
  init_toolbar();
17671
17849
  init_scrollbar();
17672
17850
  init_toolbar_config();
17851
+ init_i18n();
17673
17852
  $$8 = createLegacyUiUtils();
17674
17853
  VIEW_STATE = legacyUiDef.VIEW_STATE;
17675
17854
  DEFAULT_EDIT_AREA_HEIGHT = 100;
@@ -17700,7 +17879,8 @@ var FormulaX = (() => {
17700
17879
  this.initScrollEvent();
17701
17880
  },
17702
17881
  initComponents() {
17703
- this.components.toolbar = new toolbar_default(this, this.kfEditor, toolbar_config_default);
17882
+ const toolbarConfig = toolbar_config_default(normalizeFormulaXLocale(this.options.locale));
17883
+ this.components.toolbar = new toolbar_default(this, this.kfEditor, toolbarConfig);
17704
17884
  this.components.scrollbar = new scrollbar_default(this, this.kfEditor);
17705
17885
  },
17706
17886
  updateContainerSize(container, toolbar, editArea) {
@@ -18967,6 +19147,21 @@ var FormulaX = (() => {
18967
19147
  });
18968
19148
 
18969
19149
  // ../kity-runtime/src/legacy/syntax.ts
19150
+ function clampOffset(offset, maxOffset) {
19151
+ return Math.max(0, Math.min(offset, maxOffset));
19152
+ }
19153
+ function normalizeCursorRecord(objTree, cursor) {
19154
+ const fallbackGroupId = objTree.mapping.root.strGroup.attr.id;
19155
+ const targetGroupId = cursor.groupId && objTree.mapping[cursor.groupId] ? cursor.groupId : fallbackGroupId;
19156
+ const operandCount = objTree.mapping[targetGroupId].strGroup.operand.length;
19157
+ const startOffset = clampOffset(cursor.startOffset, operandCount);
19158
+ const endOffset = clampOffset(cursor.endOffset, operandCount);
19159
+ return {
19160
+ groupId: targetGroupId,
19161
+ startOffset: Math.min(startOffset, endOffset),
19162
+ endOffset: Math.max(startOffset, endOffset)
19163
+ };
19164
+ }
18970
19165
  var CURSOR_CHAR2, kity19, SyntaxComponent, syntax_default;
18971
19166
  var init_syntax = __esm({
18972
19167
  "../kity-runtime/src/legacy/syntax.ts"() {
@@ -19027,10 +19222,14 @@ var FormulaX = (() => {
19027
19222
  },
19028
19223
  updateObjTree(objTree) {
19029
19224
  const selectInfo = objTree.select;
19225
+ this.objTree = objTree;
19030
19226
  if (selectInfo?.groupId) {
19031
19227
  this.updateCursor(selectInfo.groupId, selectInfo.startOffset, selectInfo.endOffset);
19228
+ return;
19229
+ }
19230
+ if (this.record.cursor.groupId !== null) {
19231
+ this.record.cursor = normalizeCursorRecord(objTree, this.record.cursor);
19032
19232
  }
19033
- this.objTree = objTree;
19034
19233
  },
19035
19234
  hasCursorInfo() {
19036
19235
  return this.record.cursor.groupId !== null;
@@ -19076,7 +19275,8 @@ var FormulaX = (() => {
19076
19275
  return this.objTree;
19077
19276
  },
19078
19277
  getGroupObject(id) {
19079
- return this.objTree.mapping[id].objGroup || null;
19278
+ const groupInfo = this.objTree.mapping[id];
19279
+ return groupInfo ? groupInfo.objGroup : null;
19080
19280
  },
19081
19281
  getCursorRecord() {
19082
19282
  return kity19.Utils.extend({}, this.record.cursor);
@@ -19152,7 +19352,7 @@ var FormulaX = (() => {
19152
19352
  return this.hasRootplaceholder();
19153
19353
  },
19154
19354
  serialization() {
19155
- const cursor = this.record.cursor;
19355
+ const cursor = normalizeCursorRecord(this.objTree, this.record.cursor);
19156
19356
  const objGroup = this.objTree.mapping[cursor.groupId];
19157
19357
  const curStrGroup = objGroup.strGroup;
19158
19358
  let strStartIndex = Math.min(cursor.endOffset, cursor.startOffset);
@@ -19188,11 +19388,12 @@ var FormulaX = (() => {
19188
19388
  endOffset = startOffset;
19189
19389
  startOffset = tmp;
19190
19390
  }
19191
- this.record.cursor = {
19391
+ const nextCursor = {
19192
19392
  groupId,
19193
19393
  startOffset,
19194
19394
  endOffset
19195
19395
  };
19396
+ this.record.cursor = this.objTree ? normalizeCursorRecord(this.objTree, nextCursor) : nextCursor;
19196
19397
  },
19197
19398
  leftMove() {
19198
19399
  this.components.move.leftMove();
@@ -19233,12 +19434,20 @@ var FormulaX = (() => {
19233
19434
  });
19234
19435
 
19235
19436
  // ../kity-runtime/src/legacy/input.ts
19236
- var KEY_CODE, kity20, InputComponent, input_default;
19437
+ function insertCursorMarkers(value, selectionStart, selectionEnd) {
19438
+ const normalizedStart = Math.max(0, Math.min(selectionStart ?? value.length, value.length));
19439
+ const normalizedEnd = Math.max(0, Math.min(selectionEnd ?? normalizedStart, value.length));
19440
+ const rangeStart = Math.min(normalizedStart, normalizedEnd);
19441
+ const rangeEnd = Math.max(normalizedStart, normalizedEnd);
19442
+ return value.slice(0, rangeStart) + CURSOR_CHAR3 + value.slice(rangeStart, rangeEnd) + CURSOR_CHAR3 + value.slice(rangeEnd);
19443
+ }
19444
+ var KEY_CODE, CURSOR_CHAR3, kity20, InputComponent, input_default;
19237
19445
  var init_input = __esm({
19238
19446
  "../kity-runtime/src/legacy/input.ts"() {
19239
19447
  "use strict";
19240
19448
  init_legacy_utils();
19241
19449
  init_legacy_input_filter();
19450
+ init_legacy_sysconf();
19242
19451
  init_runtime_interop();
19243
19452
  KEY_CODE = {
19244
19453
  LEFT: 37,
@@ -19246,6 +19455,7 @@ var FormulaX = (() => {
19246
19455
  DELETE: 8,
19247
19456
  INPUT: 229
19248
19457
  };
19458
+ CURSOR_CHAR3 = legacySysconf.cursorCharacter;
19249
19459
  kity20 = getLegacyKity();
19250
19460
  InputComponent = kity20.createClass("InputComponent", {
19251
19461
  constructor(parentComponent, kfEditor) {
@@ -19418,7 +19628,12 @@ var FormulaX = (() => {
19418
19628
  return `${e.shiftKey ? "s+" : ""}${e.keyCode}`;
19419
19629
  },
19420
19630
  processingInput() {
19421
- this.restruct(this.inputBox.value);
19631
+ const latexWithCursor = insertCursorMarkers(
19632
+ this.inputBox.value,
19633
+ this.inputBox.selectionStart,
19634
+ this.inputBox.selectionEnd
19635
+ );
19636
+ this.restruct(latexWithCursor);
19422
19637
  this.kfEditor.requestService("ui.update.canvas.view");
19423
19638
  },
19424
19639
  restruct(latexStr) {
@@ -19951,7 +20166,7 @@ var FormulaX = (() => {
19951
20166
  var init_start = __esm({
19952
20167
  "../kity-runtime/src/boot/start.ts"() {
19953
20168
  "use strict";
19954
- init_editor();
20169
+ init_editor2();
19955
20170
  init_factory();
19956
20171
  init_ui();
19957
20172
  init_parser();
@@ -19968,25 +20183,17 @@ var FormulaX = (() => {
19968
20183
  // src/index.ts
19969
20184
  var index_exports = {};
19970
20185
  __export(index_exports, {
19971
- DEFAULT_FORMULA_ATTRIBUTE: () => DEFAULT_FORMULA_ATTRIBUTE,
19972
- DEFAULT_FORMULA_CLASS: () => DEFAULT_FORMULA_CLASS,
19973
- FORMULA_FLAG_ATTRIBUTE: () => FORMULA_FLAG_ATTRIBUTE,
19974
- FormulaXEditor: () => FormulaXEditor,
19975
- createFormulaElement: () => createFormulaElement,
19976
- createFormulaMarkup: () => createFormulaMarkup,
19977
- createKityEditor: () => createKityEditor,
20186
+ clearFormulaXPerfMarks: () => clearFormulaXPerfMarks2,
19978
20187
  ensureFormulaXModalStyles: () => ensureFormulaXModalStyles,
19979
- ensureKityRuntime: () => ensureKityRuntime,
19980
- escapeAttribute: () => escapeAttribute,
19981
- escapeHtml: () => escapeHtml,
19982
- findFormulaElement: () => findFormulaElement,
19983
20188
  formulaXModalStyles: () => formulaXModalStyles,
19984
- getFormulaLatexFromElement: () => getFormulaLatexFromElement,
19985
- isFormulaElement: () => isFormulaElement,
20189
+ markFormulaXPerf: () => markFormulaXPerf2,
20190
+ measureFormulaXPerf: () => measureFormulaXPerf2,
19986
20191
  mountFormulaXEditor: () => mountFormulaXEditor,
19987
- mountKityEditor: () => mountKityEditor,
19988
- replaceFormulaElement: () => replaceFormulaElement,
19989
- serializeSvgForInsertion: () => serializeSvgForInsertion
20192
+ preloadFormulaXEditor: () => preloadFormulaXEditor,
20193
+ recordFormulaXPerfPoint: () => recordFormulaXPerfPoint,
20194
+ renderFormulaXEditorLoadingState: () => renderFormulaXEditorLoadingState,
20195
+ scheduleFormulaXEditorPreload: () => scheduleFormulaXEditorPreload,
20196
+ waitForFormulaXAnimationFrame: () => waitForFormulaXAnimationFrame
19990
20197
  });
19991
20198
 
19992
20199
  // ../core/src/ast.ts
@@ -20274,52 +20481,11 @@ var FormulaX = (() => {
20274
20481
  };
20275
20482
  var parseLatex = (input) => new LatexParser(input).parse();
20276
20483
 
20277
- // ../kity-runtime/public/assets/images/toolbar/btn.png
20278
- var btn_default = "./btn-5DANP6JY.png";
20279
-
20280
- // ../kity-runtime/public/assets/images/toolbar/other.png
20281
- var other_default = "./other-OMWJFGL5.png";
20282
-
20283
- // ../kity-runtime/public/assets/styles/editor.css?url
20284
- var editor_default = "./editor-JT5KLVXX.css?url";
20285
-
20286
- // ../kity-runtime/public/resource/KF_AMS_BB.woff
20287
- var KF_AMS_BB_default = "./KF_AMS_BB-5QF7FUSO.woff";
20288
-
20289
- // ../kity-runtime/public/resource/KF_AMS_CAL.woff
20290
- var KF_AMS_CAL_default = "./KF_AMS_CAL-NXRNLAZN.woff";
20291
-
20292
- // ../kity-runtime/public/resource/KF_AMS_FRAK.woff
20293
- var KF_AMS_FRAK_default = "./KF_AMS_FRAK-CO33WWN4.woff";
20294
-
20295
- // ../kity-runtime/public/resource/KF_AMS_MAIN.woff
20296
- var KF_AMS_MAIN_default = "./KF_AMS_MAIN-25QJVAWY.woff";
20297
-
20298
- // ../kity-runtime/public/resource/KF_AMS_ROMAN.woff
20299
- var KF_AMS_ROMAN_default = "./KF_AMS_ROMAN-243BR7HH.woff";
20300
-
20301
- // ../kity-runtime/src/asset-manifest.ts
20302
- var kityFontAssets = {
20303
- KF_AMS_BB: KF_AMS_BB_default,
20304
- KF_AMS_CAL: KF_AMS_CAL_default,
20305
- KF_AMS_FRAK: KF_AMS_FRAK_default,
20306
- KF_AMS_MAIN: KF_AMS_MAIN_default,
20307
- KF_AMS_ROMAN: KF_AMS_ROMAN_default
20308
- };
20309
- var kityToolbarAssets = {
20310
- btn: btn_default,
20311
- other: other_default
20312
- };
20313
- var kityStyleAssets = {
20314
- editor: editor_default
20315
- };
20316
- var kityAssetManifest = {
20317
- fonts: kityFontAssets,
20318
- toolbar: kityToolbarAssets,
20319
- styles: kityStyleAssets
20320
- };
20484
+ // ../kity-runtime/src/index.ts
20485
+ init_asset_manifest();
20321
20486
 
20322
20487
  // ../kity-runtime/src/create-editor.ts
20488
+ init_asset_manifest();
20323
20489
  init_legacy_box_type();
20324
20490
 
20325
20491
  // ../kity-runtime/src/vendor/char-position.ts
@@ -23722,8 +23888,83 @@ var FormulaX = (() => {
23722
23888
  targetWindow.kity = kity;
23723
23889
  }
23724
23890
 
23891
+ // ../kity-runtime/src/perf.ts
23892
+ function getPerfHost() {
23893
+ return globalThis;
23894
+ }
23895
+ function getPerfState() {
23896
+ const host = getPerfHost();
23897
+ host.__FORMULAX_PERF_STATE__ ??= {
23898
+ reportedMeasureCount: 0,
23899
+ reportScheduled: false
23900
+ };
23901
+ return host.__FORMULAX_PERF_STATE__;
23902
+ }
23903
+ function hasPerfSupport() {
23904
+ return typeof performance !== "undefined" && typeof performance.mark === "function" && typeof performance.measure === "function" && typeof performance.getEntriesByType === "function";
23905
+ }
23906
+ function isPerfDebugEnabled() {
23907
+ return getPerfHost().__FORMULAX_PERF__ === true;
23908
+ }
23909
+ function schedulePerfReport() {
23910
+ if (!hasPerfSupport() || !isPerfDebugEnabled()) {
23911
+ return;
23912
+ }
23913
+ const state = getPerfState();
23914
+ if (state.reportScheduled) {
23915
+ return;
23916
+ }
23917
+ state.reportScheduled = true;
23918
+ queueMicrotask(() => {
23919
+ state.reportScheduled = false;
23920
+ const entries = performance.getEntriesByType("measure").filter((entry) => entry.name.startsWith("fx:")).sort((left, right) => left.startTime - right.startTime);
23921
+ const nextEntries = entries.slice(state.reportedMeasureCount);
23922
+ state.reportedMeasureCount = entries.length;
23923
+ if (!nextEntries.length) {
23924
+ return;
23925
+ }
23926
+ console.table(nextEntries.map((entry) => ({
23927
+ name: entry.name,
23928
+ duration: Number(entry.duration.toFixed(2)),
23929
+ startTime: Number(entry.startTime.toFixed(2))
23930
+ })));
23931
+ });
23932
+ }
23933
+ function markFormulaXPerf(name) {
23934
+ if (!hasPerfSupport()) {
23935
+ return null;
23936
+ }
23937
+ const markName = `${name}::${Date.now()}::${Math.random().toString(36).slice(2, 8)}`;
23938
+ performance.mark(markName);
23939
+ return markName;
23940
+ }
23941
+ function measureFormulaXPerf(name, startMark, endMark) {
23942
+ if (!hasPerfSupport() || !startMark) {
23943
+ return null;
23944
+ }
23945
+ const resolvedEndMark = endMark ?? markFormulaXPerf(`${name}:end`);
23946
+ if (!resolvedEndMark) {
23947
+ return null;
23948
+ }
23949
+ performance.measure(name, startMark, resolvedEndMark);
23950
+ schedulePerfReport();
23951
+ return resolvedEndMark;
23952
+ }
23953
+ function clearFormulaXPerfMarks(...marks) {
23954
+ if (!hasPerfSupport()) {
23955
+ return;
23956
+ }
23957
+ for (const mark of marks) {
23958
+ if (!mark) {
23959
+ continue;
23960
+ }
23961
+ performance.clearMarks(mark);
23962
+ }
23963
+ }
23964
+
23725
23965
  // ../kity-runtime/src/create-editor.ts
23726
23966
  init_toolbar_assets();
23967
+ init_i18n();
23727
23968
  var DEFAULT_LATEX = "x=\\frac{-b\\pm\\sqrt{b^2-4ac}}{2a}";
23728
23969
  var DEFAULT_EDITOR_HEIGHT = "auto";
23729
23970
  var KITY_STYLE_ID = "formulax-kity-editor-styles";
@@ -23762,13 +24003,14 @@ var FormulaX = (() => {
23762
24003
  }
23763
24004
  function ensureKityStylesheet(doc2, href) {
23764
24005
  if (doc2.getElementById(KITY_STYLE_ID)) {
23765
- return;
24006
+ return false;
23766
24007
  }
23767
24008
  const link = doc2.createElement("link");
23768
24009
  link.id = KITY_STYLE_ID;
23769
24010
  link.rel = "stylesheet";
23770
24011
  link.href = href;
23771
24012
  doc2.head.appendChild(link);
24013
+ return true;
23772
24014
  }
23773
24015
  function hydrateLegacyKf(runtimeWindow) {
23774
24016
  const requireFormula = runtimeWindow.__kityFormulaRequire__;
@@ -23824,64 +24066,118 @@ var FormulaX = (() => {
23824
24066
  return runtimePromise;
23825
24067
  }
23826
24068
  runtimePromise = (async () => {
24069
+ const runtimeTotalStart = markFormulaXPerf("fx:kity-runtime:total");
23827
24070
  const runtimeWindow = window;
23828
24071
  runtimeWindow.kf = runtimeWindow.kf ?? {};
23829
24072
  installKityRuntime(runtimeWindow);
23830
- const { installLegacyKityFormulaRuntime: installLegacyKityFormulaRuntime2 } = await Promise.resolve().then(() => (init_install(), install_exports));
23831
- installLegacyKityFormulaRuntime2(runtimeWindow);
23832
- hydrateLegacyKf(runtimeWindow);
23833
- const { installLegacyParserRuntime: installLegacyParserRuntime2 } = await Promise.resolve().then(() => (init_install2(), install_exports2));
23834
- installLegacyParserRuntime2(runtimeWindow);
23835
- installLegacyRuntime(runtimeWindow);
23836
- const { installKityEditorStart: installKityEditorStart2 } = await Promise.resolve().then(() => (init_start(), start_exports));
23837
- installKityEditorStart2(runtimeWindow);
24073
+ try {
24074
+ const formulaImportStart = markFormulaXPerf("fx:kity-runtime:formula-import");
24075
+ const { installLegacyKityFormulaRuntime: installLegacyKityFormulaRuntime2 } = await Promise.resolve().then(() => (init_install(), install_exports));
24076
+ const formulaImportEnd = markFormulaXPerf("fx:kity-runtime:formula-import:end");
24077
+ measureFormulaXPerf("fx:kity-runtime:formula-import", formulaImportStart, formulaImportEnd);
24078
+ clearFormulaXPerfMarks(formulaImportStart, formulaImportEnd);
24079
+ const formulaInstallStart = markFormulaXPerf("fx:kity-runtime:formula-install");
24080
+ installLegacyKityFormulaRuntime2(runtimeWindow);
24081
+ hydrateLegacyKf(runtimeWindow);
24082
+ const formulaInstallEnd = markFormulaXPerf("fx:kity-runtime:formula-install:end");
24083
+ measureFormulaXPerf("fx:kity-runtime:formula-install", formulaInstallStart, formulaInstallEnd);
24084
+ clearFormulaXPerfMarks(formulaInstallStart, formulaInstallEnd);
24085
+ const parserImportStart = markFormulaXPerf("fx:kity-runtime:parser-import");
24086
+ const { installLegacyParserRuntime: installLegacyParserRuntime2 } = await Promise.resolve().then(() => (init_install2(), install_exports2));
24087
+ const parserImportEnd = markFormulaXPerf("fx:kity-runtime:parser-import:end");
24088
+ measureFormulaXPerf("fx:kity-runtime:parser-import", parserImportStart, parserImportEnd);
24089
+ clearFormulaXPerfMarks(parserImportStart, parserImportEnd);
24090
+ const parserInstallStart = markFormulaXPerf("fx:kity-runtime:parser-install");
24091
+ installLegacyParserRuntime2(runtimeWindow);
24092
+ const parserInstallEnd = markFormulaXPerf("fx:kity-runtime:parser-install:end");
24093
+ measureFormulaXPerf("fx:kity-runtime:parser-install", parserInstallStart, parserInstallEnd);
24094
+ clearFormulaXPerfMarks(parserInstallStart, parserInstallEnd);
24095
+ installLegacyRuntime(runtimeWindow);
24096
+ const bootImportStart = markFormulaXPerf("fx:kity-runtime:boot-import");
24097
+ const { installKityEditorStart: installKityEditorStart2 } = await Promise.resolve().then(() => (init_start(), start_exports));
24098
+ const bootImportEnd = markFormulaXPerf("fx:kity-runtime:boot-import:end");
24099
+ measureFormulaXPerf("fx:kity-runtime:boot-import", bootImportStart, bootImportEnd);
24100
+ clearFormulaXPerfMarks(bootImportStart, bootImportEnd);
24101
+ const bootInstallStart = markFormulaXPerf("fx:kity-runtime:boot-install");
24102
+ installKityEditorStart2(runtimeWindow);
24103
+ const bootInstallEnd = markFormulaXPerf("fx:kity-runtime:boot-install:end");
24104
+ measureFormulaXPerf("fx:kity-runtime:boot-install", bootInstallStart, bootInstallEnd);
24105
+ clearFormulaXPerfMarks(bootInstallStart, bootInstallEnd);
24106
+ } finally {
24107
+ const runtimeTotalEnd = markFormulaXPerf("fx:kity-runtime:total:end");
24108
+ measureFormulaXPerf("fx:kity-runtime:total", runtimeTotalStart, runtimeTotalEnd);
24109
+ clearFormulaXPerfMarks(runtimeTotalStart, runtimeTotalEnd);
24110
+ }
23838
24111
  })();
23839
24112
  return runtimePromise;
23840
24113
  }
23841
24114
  async function createKityEditor(container, options = {}) {
24115
+ const createEditorStart = markFormulaXPerf("fx:create-kity-editor:total");
23842
24116
  const fontsize = options.render?.fontsize ?? 40;
23843
24117
  const editorHeight = normalizeCssSize(options.height, DEFAULT_EDITOR_HEIGHT);
24118
+ const locale = normalizeFormulaXLocale(options.locale ?? DEFAULT_FORMULAX_LOCALE);
23844
24119
  const assets = resolveEditorAssets(options.assets);
23845
- ensureKityStylesheet(document, assets.styles.editor);
23846
- setToolbarAssetUrls(assets.toolbar);
23847
- await ensureKityRuntime();
23848
- const runtimeWindow = window;
23849
- if (!runtimeWindow.kf?.EditorFactory) {
23850
- throw new Error("Kity editor runtime did not initialize");
23851
- }
23852
- container.innerHTML = "";
23853
- const host = document.createElement("div");
23854
- host.className = "kf-editor";
23855
- host.style.width = "100%";
23856
- host.style.height = editorHeight;
23857
- container.appendChild(host);
23858
- const factory2 = runtimeWindow.kf.EditorFactory.create(host, {
23859
- render: {
23860
- fontsize
23861
- },
23862
- resource: {
23863
- path: "",
23864
- fonts: assets.fonts
24120
+ try {
24121
+ const stylesheetInserted = ensureKityStylesheet(document, assets.styles.editor);
24122
+ if (stylesheetInserted) {
24123
+ const stylesheetInsertedMark = markFormulaXPerf("fx:kity-css:link-inserted");
24124
+ measureFormulaXPerf("fx:kity-css:link-inserted", createEditorStart, stylesheetInsertedMark);
24125
+ clearFormulaXPerfMarks(stylesheetInsertedMark);
23865
24126
  }
23866
- });
23867
- return {
23868
- ready: factory2.ready.bind(factory2),
23869
- execCommand(name, value) {
23870
- factory2.ready(function execWhenReady() {
23871
- this.execCommand(name, value);
23872
- });
23873
- },
23874
- focus() {
23875
- factory2.ready(function focusWhenReady() {
23876
- this.execCommand("focus");
23877
- });
23878
- },
23879
- destroy() {
23880
- container.innerHTML = "";
23881
- },
23882
- host,
23883
- raw: factory2
23884
- };
24127
+ setToolbarAssetUrls(assets.toolbar);
24128
+ await ensureKityRuntime();
24129
+ const runtimeReadyMark = markFormulaXPerf("fx:kity-runtime:ready-for-editor");
24130
+ measureFormulaXPerf("fx:kity-runtime:ready-for-editor", createEditorStart, runtimeReadyMark);
24131
+ clearFormulaXPerfMarks(runtimeReadyMark);
24132
+ const runtimeWindow = window;
24133
+ if (!runtimeWindow.kf?.EditorFactory) {
24134
+ throw new Error("Kity editor runtime did not initialize");
24135
+ }
24136
+ container.innerHTML = "";
24137
+ const host = document.createElement("div");
24138
+ host.className = "kf-editor";
24139
+ host.style.width = "100%";
24140
+ host.style.height = editorHeight;
24141
+ container.appendChild(host);
24142
+ const factoryCreateStart = markFormulaXPerf("fx:kity-editor-factory:create");
24143
+ const factory2 = runtimeWindow.kf.EditorFactory.create(host, {
24144
+ render: {
24145
+ fontsize
24146
+ },
24147
+ ui: {
24148
+ locale
24149
+ },
24150
+ resource: {
24151
+ path: "",
24152
+ fonts: assets.fonts
24153
+ }
24154
+ });
24155
+ const factoryCreateEnd = markFormulaXPerf("fx:kity-editor-factory:create:end");
24156
+ measureFormulaXPerf("fx:kity-editor-factory:create", factoryCreateStart, factoryCreateEnd);
24157
+ clearFormulaXPerfMarks(factoryCreateStart, factoryCreateEnd);
24158
+ return {
24159
+ ready: factory2.ready.bind(factory2),
24160
+ execCommand(name, value) {
24161
+ factory2.ready(function execWhenReady() {
24162
+ this.execCommand(name, value);
24163
+ });
24164
+ },
24165
+ focus() {
24166
+ factory2.ready(function focusWhenReady() {
24167
+ this.execCommand("focus");
24168
+ });
24169
+ },
24170
+ destroy() {
24171
+ container.innerHTML = "";
24172
+ },
24173
+ host,
24174
+ raw: factory2
24175
+ };
24176
+ } finally {
24177
+ const createEditorEnd = markFormulaXPerf("fx:create-kity-editor:total:end");
24178
+ measureFormulaXPerf("fx:create-kity-editor:total", createEditorStart, createEditorEnd);
24179
+ clearFormulaXPerfMarks(createEditorStart, createEditorEnd);
24180
+ }
23885
24181
  }
23886
24182
  async function mountKityEditor(container, options = {}) {
23887
24183
  const editor = await createKityEditor(container, options);
@@ -23933,6 +24229,7 @@ var FormulaX = (() => {
23933
24229
 
23934
24230
  // ../kity-runtime/src/index.ts
23935
24231
  init_dom_utils();
24232
+ init_i18n();
23936
24233
  init_legacy_box_type();
23937
24234
  init_legacy_component();
23938
24235
  init_legacy_ele_type();
@@ -23952,495 +24249,71 @@ var FormulaX = (() => {
23952
24249
  init_legacy_ui_utils();
23953
24250
  init_legacy_utils();
23954
24251
 
23955
- // src/formula-node.ts
23956
- var DEFAULT_FORMULA_ATTRIBUTE = "data-formulax-latex";
23957
- var FORMULA_FLAG_ATTRIBUTE = "data-formulax";
23958
- var DEFAULT_FORMULA_CLASS = "formulax-math";
23959
- function escapeAttribute(value) {
23960
- return value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
23961
- }
24252
+ // ../renderer/src/markup.ts
23962
24253
  function escapeHtml(value) {
23963
24254
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
23964
24255
  }
23965
- function createFormulaMarkup(latex, options = {}) {
23966
- const attributeName = options.attributeName ?? DEFAULT_FORMULA_ATTRIBUTE;
23967
- const className = options.className ?? DEFAULT_FORMULA_CLASS;
23968
- const displayClass = options.displayMode ? `${className} ${className}--block` : className;
23969
- const safeLatex = escapeAttribute(latex);
23970
- const cursorStyle = options.cursorStyle?.trim() || "pointer";
23971
- const extraAttributes = {
23972
- ...options.extraAttributes ?? {},
23973
- style: mergeInlineStyles(
23974
- typeof options.extraAttributes?.style === "string" ? options.extraAttributes.style : "",
23975
- cursorStyle ? `cursor: ${cursorStyle}` : ""
23976
- )
23977
- };
23978
- const serializedAttributes = Object.entries(extraAttributes).filter(([, value]) => value !== null && value !== void 0 && value !== false).map(([key, value]) => value === true ? key : `${key}="${escapeAttribute(String(value))}"`);
23979
- return [
23980
- "<span",
23981
- ` class="${escapeAttribute(displayClass)}"`,
23982
- ` ${FORMULA_FLAG_ATTRIBUTE}="true"`,
23983
- ` ${attributeName}="${safeLatex}"`,
23984
- ` data-latex="${safeLatex}"`,
23985
- ' contenteditable="false"',
23986
- ' role="button"',
23987
- ' tabindex="0"',
23988
- serializedAttributes.length ? ` ${serializedAttributes.join(" ")}` : "",
23989
- ">",
23990
- options.renderHtml ?? `<span class="${escapeAttribute(className)}__render">${escapeHtml(latex || "\\square")}</span>`,
23991
- "</span>"
23992
- ].join("");
23993
- }
23994
- function mergeInlineStyles(existingStyle, nextStyle) {
23995
- const existing = existingStyle.trim().replace(/;+\s*$/, "");
23996
- const next = nextStyle.trim().replace(/;+\s*$/, "");
23997
- if (!existing) return next;
23998
- if (!next) return existing;
23999
- return `${existing}; ${next}`;
24000
- }
24001
- function createFormulaElement(ownerDocument, latex, options = {}) {
24002
- const wrapper = ownerDocument.createElement("span");
24003
- wrapper.innerHTML = createFormulaMarkup(latex, options);
24004
- return wrapper.firstElementChild;
24005
- }
24006
- function replaceFormulaElement(target, latex, options = {}) {
24007
- const next = createFormulaElement(target.ownerDocument ?? document, latex, options);
24008
- if (!next) return null;
24009
- target.replaceWith(next);
24010
- return next;
24011
- }
24012
- function getFormulaLatexFromElement(element, attributeName = DEFAULT_FORMULA_ATTRIBUTE) {
24013
- return element.getAttribute(attributeName) ?? element.getAttribute("data-latex") ?? "";
24014
- }
24015
- function isFormulaElement(node) {
24016
- if (!node || typeof node !== "object") return false;
24017
- const element = node;
24018
- return typeof element.getAttribute === "function" && element.getAttribute(FORMULA_FLAG_ATTRIBUTE) === "true";
24019
- }
24020
- function findFormulaElement(node) {
24021
- if (!node) return null;
24022
- const element = node.nodeType === 1 ? node : node.parentElement;
24023
- return element?.closest?.(`[${FORMULA_FLAG_ATTRIBUTE}="true"]`);
24024
- }
24025
-
24026
- // src/formula-modal.ts
24027
- var EMPTY_FORMULA_PLACEHOLDER = "\\placeholder ";
24028
- var STYLE_ID = "fx-formula-modal-styles";
24029
- var formulaXModalStyles = `
24030
- .fx-formula-modal-open {
24031
- overflow: hidden;
24032
- }
24033
24256
 
24034
- .fx-formula-modal-root {
24035
- position: fixed;
24036
- inset: 0;
24037
- z-index: 2147483000;
24038
- display: flex;
24257
+ // ../renderer/src/styles.ts
24258
+ var FORMULAX_BASE_STYLE_ID = "fx-formulax-base-styles";
24259
+ var formulaXBaseStyles = `
24260
+ .formulax-math {
24261
+ display: inline-flex;
24039
24262
  align-items: center;
24040
- justify-content: center;
24263
+ vertical-align: middle;
24264
+ line-height: 1;
24265
+ padding: 0 2px;
24266
+ margin: 0 1px;
24267
+ border-radius: 3px;
24268
+ background: transparent;
24269
+ cursor: pointer;
24270
+ user-select: none;
24041
24271
  }
24042
24272
 
24043
- .fx-formula-modal-backdrop {
24044
- position: absolute;
24045
- inset: 0;
24046
- background: rgba(15, 23, 42, 0.48);
24273
+ .formulax-math:hover {
24274
+ outline: 1px solid rgba(37, 99, 235, 0.35);
24275
+ background: rgba(37, 99, 235, 0.06);
24047
24276
  }
24048
24277
 
24049
- .fx-formula-modal {
24050
- --fx-formula-editor-body-height: 264px;
24051
- --fx-formula-workspace-height: 168px;
24052
- position: relative;
24053
- width: min(860px, calc(100vw - 32px));
24054
- height: auto;
24055
- max-height: calc(100vh - 32px);
24056
- background: #fff;
24057
- border-radius: 14px;
24058
- box-shadow: 0 24px 80px rgba(15, 23, 42, 0.28);
24059
- display: flex;
24060
- flex-direction: column;
24061
- overflow: visible;
24062
- isolation: isolate;
24278
+ .formulax-math__render,
24279
+ .formulax-math__svg,
24280
+ .formulax-math__image {
24281
+ display: inline-block;
24282
+ max-width: 100%;
24283
+ pointer-events: none;
24063
24284
  }
24064
24285
 
24065
- .fx-formula-modal__header,
24066
- .fx-formula-modal__footer,
24067
- .fx-formula-modal__title,
24068
- .fx-formula-modal__close,
24069
- .fx-formula-modal__button,
24070
- .fx-formula-editor-loading,
24071
- .fx-formula-editor-error {
24072
- font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
24286
+ .formulax-math__render {
24287
+ vertical-align: middle;
24288
+ font-family: "KF AMS MAIN", "Cambria Math", "Latin Modern Math", "Times New Roman", serif;
24073
24289
  }
24074
24290
 
24075
- .fx-formula-modal__header {
24076
- min-height: 56px;
24077
- padding: 0 20px;
24078
- border-bottom: 1px solid #e5e7eb;
24079
- display: flex;
24080
- align-items: center;
24081
- justify-content: space-between;
24082
- flex-shrink: 0;
24083
- position: relative;
24084
- z-index: 3;
24085
- background: #fff;
24086
- border-radius: 14px 14px 0 0;
24291
+ .formulax-math__svg {
24292
+ flex: 0 0 auto;
24293
+ vertical-align: -0.35em;
24087
24294
  }
24088
24295
 
24089
- .fx-formula-modal__title {
24090
- font-size: 16px;
24091
- font-weight: 650;
24092
- margin: 0;
24093
- color: #111827;
24296
+ .formulax-math__image {
24297
+ height: auto;
24298
+ vertical-align: middle;
24094
24299
  }
24095
-
24096
- .fx-formula-modal__close {
24097
- border: 0;
24098
- background: transparent;
24099
- font-size: 24px;
24100
- line-height: 1;
24101
- cursor: pointer;
24102
- color: #6b7280;
24103
- }
24104
-
24105
- .fx-formula-modal__body {
24106
- flex: 0 0 auto;
24107
- height: var(--fx-formula-editor-body-height);
24108
- padding: 0;
24109
- overflow: visible;
24110
- min-height: var(--fx-formula-editor-body-height);
24111
- position: relative;
24112
- z-index: 2;
24113
- }
24114
-
24115
- .fx-formula-editor-host {
24116
- width: 100%;
24117
- height: var(--fx-formula-editor-body-height);
24118
- min-height: var(--fx-formula-editor-body-height);
24119
- overflow: visible;
24120
- position: relative;
24121
- }
24122
-
24123
- .fx-formula-kity-host {
24124
- width: 100%;
24125
- height: var(--fx-formula-editor-body-height);
24126
- min-height: var(--fx-formula-editor-body-height);
24127
- overflow: visible;
24128
- position: relative;
24129
- }
24130
-
24131
- .fx-formula-kity-host .kf-editor {
24132
- height: var(--fx-formula-editor-body-height) !important;
24133
- overflow: visible !important;
24134
- }
24135
-
24136
- .fx-formula-kity-host .kf-editor-toolbar {
24137
- overflow: visible;
24138
- position: relative;
24139
- z-index: 20;
24140
- }
24141
-
24142
- .fx-formula-kity-host .kf-editor-ui-button-mount-point,
24143
- .fx-formula-kity-host .kf-editor-ui-area-mount,
24144
- .fx-formula-kity-host .kf-editor-ui-box,
24145
- .fx-formula-kity-host .kf-editor-ui-list {
24146
- z-index: 1000;
24147
- }
24148
-
24149
- .fx-formula-kity-host .kf-editor-edit-area,
24150
- .fx-formula-kity-host .kf-editor-canvas-container {
24151
- min-height: var(--fx-formula-workspace-height);
24152
- height: var(--fx-formula-workspace-height);
24153
- }
24154
-
24155
- .fx-formula-kity-host .kf-editor-edit-area {
24156
- flex: 0 0 auto;
24157
- overflow: hidden;
24158
- }
24159
-
24160
- .fx-formula-kity-host .kf-editor,
24161
- .fx-formula-kity-host .kf-editor svg text,
24162
- .fx-formula-kity-host .kf-editor-ui-area-item-text,
24163
- .fx-formula-kity-host .kf-editor-ui-box-item-text,
24164
- .fx-formula-kity-host .kf-editor-ui-box-item-val,
24165
- .formulax-math__render {
24166
- font-family: "KF AMS MAIN", "Cambria Math", "Latin Modern Math", "Times New Roman", serif !important;
24167
- }
24168
-
24169
- .fx-formula-kity-host .kf-editor-ui-box-item-content,
24170
- .fx-formula-kity-host .kf-editor-ui-box-item-val {
24171
- min-width: 32px;
24172
- min-height: 32px;
24173
- }
24174
-
24175
- .fx-formula-kity-host .kf-editor-ui-box-item-val svg,
24176
- .fx-formula-kity-host .kf-editor-ui-box-item-val img,
24177
- .fx-formula-kity-host .kf-editor-ui-area-item-img,
24178
- .fx-formula-kity-host .kf-editor-ui-area-item-text {
24179
- display: block;
24180
- }
24181
-
24182
- .fx-formula-editor-loading {
24183
- height: var(--fx-formula-editor-body-height);
24184
- padding: 24px;
24185
- color: #4b5563;
24186
- text-align: center;
24187
- display: flex;
24188
- align-items: center;
24189
- justify-content: center;
24190
- }
24191
-
24192
- .fx-formula-editor-error {
24193
- padding: 24px;
24194
- color: #dc2626;
24195
- font-size: 14px;
24196
- }
24197
-
24198
- .fx-formula-editor-error pre {
24199
- white-space: pre-wrap;
24200
- word-break: break-all;
24201
- color: #991b1b;
24202
- background: #fef2f2;
24203
- border: 1px solid #fecaca;
24204
- border-radius: 8px;
24205
- padding: 12px;
24206
- margin-top: 8px;
24207
- }
24208
-
24209
- .fx-formula-modal__footer {
24210
- min-height: 64px;
24211
- padding: 12px 20px;
24212
- border-top: 1px solid #e5e7eb;
24213
- display: flex;
24214
- align-items: center;
24215
- justify-content: flex-end;
24216
- gap: 12px;
24217
- flex-shrink: 0;
24218
- position: relative;
24219
- z-index: 1;
24220
- background: #fff;
24221
- border-radius: 0 0 14px 14px;
24222
- }
24223
-
24224
- .fx-formula-modal__button {
24225
- appearance: none;
24226
- border: 1px solid #d1d5db;
24227
- background: #fff;
24228
- color: #111827;
24229
- border-radius: 8px;
24230
- padding: 8px 14px;
24231
- font-size: 14px;
24232
- cursor: pointer;
24233
- }
24234
-
24235
- .fx-formula-modal__button--primary {
24236
- border-color: #2563eb;
24237
- background: #2563eb;
24238
- color: #fff;
24239
- }
24240
-
24241
- .formulax-math {
24242
- display: inline-flex;
24243
- align-items: center;
24244
- vertical-align: middle;
24245
- line-height: 1;
24246
- padding: 0 2px;
24247
- margin: 0 1px;
24248
- border-radius: 3px;
24249
- background: transparent;
24250
- cursor: pointer;
24251
- user-select: none;
24252
- }
24253
-
24254
- .formulax-math:hover {
24255
- outline: 1px solid rgba(37, 99, 235, 0.35);
24256
- background: rgba(37, 99, 235, 0.06);
24257
- }
24258
-
24259
- .formulax-math__svg {
24260
- display: inline-block;
24261
- flex: 0 0 auto;
24262
- max-width: 100%;
24263
- vertical-align: -0.35em;
24264
- pointer-events: none;
24265
- }
24266
-
24267
- .formulax-math__image {
24268
- display: inline-block;
24269
- max-width: 100%;
24270
- height: auto;
24271
- vertical-align: middle;
24272
- pointer-events: none;
24273
- }
24274
- `;
24275
- function ensureFormulaXModalStyles(doc2 = document) {
24276
- if (doc2.getElementById(STYLE_ID)) return;
24277
- const style = doc2.createElement("style");
24278
- style.id = STYLE_ID;
24279
- style.textContent = formulaXModalStyles;
24280
- doc2.head.appendChild(style);
24281
- }
24282
- function mountFormulaXEditor(root2, options = {}) {
24283
- let destroyed = false;
24284
- let latestLatex = options.initialLatex ?? "";
24285
- let handle = null;
24286
- const initialLatex = latestLatex.trim() ? latestLatex : EMPTY_FORMULA_PLACEHOLDER;
24287
- root2.classList.add("fx-formula-kity-host");
24288
- root2.innerHTML = `
24289
- <div class="fx-formula-editor-loading" role="status" aria-live="polite">
24290
- Loading FormulaX editor...
24291
- </div>
24292
- `;
24293
- const readyPromise = mountKityEditor(root2, {
24294
- initialLatex,
24295
- height: options.height ?? "100%",
24296
- autofocus: options.autofocus ?? true,
24297
- assets: options.assets,
24298
- render: {
24299
- fontsize: options.render?.fontsize ?? 40
24300
- }
24301
- }).then((nextHandle) => {
24302
- if (destroyed) {
24303
- nextHandle.destroy();
24304
- throw new Error("FormulaX editor mount cancelled");
24305
- }
24306
- handle = nextHandle;
24307
- return nextHandle;
24308
- }).catch((error) => {
24309
- console.error("[FormulaX] Failed to load FormulaX editor:", error);
24310
- if (!destroyed) {
24311
- root2.innerHTML = `
24312
- <div class="fx-formula-editor-error">
24313
- Failed to load FormulaX editor.
24314
- <pre>${escapeHtml(error instanceof Error ? error.message : String(error))}</pre>
24315
- </div>
24316
- `;
24317
- }
24318
- throw error;
24319
- });
24320
- const getCurrentLatex = async () => {
24321
- const readyHandle = handle ?? await readyPromise;
24322
- const latex = await tryReadLatexFromKityHandle(readyHandle);
24323
- if (latex !== null) {
24324
- latestLatex = latex;
24325
- }
24326
- return latestLatex;
24327
- };
24328
- return {
24329
- root: root2,
24330
- getLatex: getCurrentLatex,
24331
- async getState() {
24332
- const latex = await getCurrentLatex();
24333
- try {
24334
- return {
24335
- ...createEmptyState(),
24336
- doc: parseLatex(latex)
24337
- };
24338
- } catch {
24339
- return createEmptyState();
24340
- }
24341
- },
24342
- async getRenderHtml() {
24343
- await readyPromise;
24344
- await waitForFormulaSvgLayout(root2);
24345
- return renderCurrentFormulaAsSvgHtml(root2);
24346
- },
24347
- destroy() {
24348
- if (destroyed) return;
24349
- destroyed = true;
24350
- void readyPromise.then((readyHandle) => readyHandle.destroy()).catch(() => void 0);
24351
- root2.innerHTML = "";
24352
- }
24353
- };
24354
- }
24355
- async function tryReadLatexFromKityHandle(handle) {
24356
- try {
24357
- let isEmpty = false;
24358
- handle.ready(function ready() {
24359
- const result = this.execCommand("content.is.empty");
24360
- isEmpty = result === true;
24361
- });
24362
- if (isEmpty) {
24363
- return "";
24364
- }
24365
- } catch {
24366
- }
24367
- const candidates = [
24368
- "get.source",
24369
- "getSource",
24370
- "getLatex",
24371
- "get.latex",
24372
- "get.content",
24373
- "getContent"
24374
- ];
24375
- for (const command of candidates) {
24376
- try {
24377
- let value = null;
24378
- handle.ready(function ready() {
24379
- value = this.execCommand(command);
24380
- });
24381
- if (typeof value === "string" && value.trim()) {
24382
- return value;
24383
- }
24384
- if (value && typeof value === "object" && "latex" in value) {
24385
- const latex = value.latex;
24386
- if (typeof latex === "string" && latex.trim()) {
24387
- return latex;
24388
- }
24389
- }
24390
- } catch {
24391
- }
24392
- }
24393
- return null;
24394
- }
24395
- function renderCurrentFormulaAsSvgHtml(root2) {
24396
- const svg2 = findFormulaSvg(root2);
24397
- if (!svg2) {
24398
- return "";
24399
- }
24400
- return serializeSvgForInsertion(svg2);
24401
- }
24402
- async function waitForFormulaSvgLayout(root2) {
24403
- const doc2 = root2.ownerDocument ?? document;
24404
- const view = doc2.defaultView ?? window;
24405
- await waitForDocumentFonts(doc2);
24406
- let previous = readRenderedFormulaBox(root2);
24407
- for (let attempt = 0; attempt < 4; attempt += 1) {
24408
- await waitForAnimationFrame(view);
24409
- const current = readRenderedFormulaBox(root2);
24410
- if (previous && current && areSvgBoxesClose(previous, current)) {
24411
- return;
24412
- }
24413
- previous = current;
24414
- }
24415
- }
24416
- function findFormulaSvg(root2) {
24417
- return root2.querySelector(
24418
- ".kf-editor-edit-area svg, .kf-editor-canvas-container svg, svg"
24419
- );
24420
- }
24421
- function readRenderedFormulaBox(root2) {
24422
- const svg2 = findFormulaSvg(root2);
24423
- if (!svg2) {
24424
- return null;
24425
- }
24426
- return getInlineSvgContent(svg2)?.box ?? readSvgBox(svg2);
24427
- }
24428
- function areSvgBoxesClose(left, right) {
24429
- 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;
24430
- }
24431
- async function waitForDocumentFonts(doc2) {
24432
- if (!doc2.fonts?.ready) {
24433
- return;
24434
- }
24435
- try {
24436
- await doc2.fonts.ready;
24437
- } catch {
24438
- }
24300
+ `;
24301
+ function ensureFormulaXBaseStyles(doc2 = document) {
24302
+ if (doc2.getElementById(FORMULAX_BASE_STYLE_ID)) return;
24303
+ const style = doc2.createElement("style");
24304
+ style.id = FORMULAX_BASE_STYLE_ID;
24305
+ style.textContent = formulaXBaseStyles;
24306
+ doc2.head.appendChild(style);
24439
24307
  }
24440
- function waitForAnimationFrame(view) {
24441
- return new Promise((resolve) => {
24442
- view.requestAnimationFrame(() => resolve());
24443
- });
24308
+
24309
+ // ../renderer/src/svg.ts
24310
+ var SIMPLE_INLINE_HEIGHT_EM = 1.25;
24311
+ var BASE_FORMULA_HEIGHT = 40.5;
24312
+ var SIMPLE_FORMULA_HEIGHT_RATIO = 1.05;
24313
+ var MAX_INLINE_HEIGHT_EM = 1.65;
24314
+ var COMPLEX_FORMULA_SCALE = 0.825;
24315
+ function readRenderedFormulaSvgBox(svg2) {
24316
+ return getInlineSvgContent(svg2)?.box ?? readSvgBox(svg2);
24444
24317
  }
24445
24318
  function serializeSvgForInsertion(svg2) {
24446
24319
  const content = getInlineSvgContent(svg2);
@@ -24448,32 +24321,27 @@ var FormulaX = (() => {
24448
24321
  const clone = content && inlineViewport ? createInlineSvgClone(svg2, content, inlineViewport) : svg2.cloneNode(true);
24449
24322
  uniquifySvgIds(clone);
24450
24323
  sizeSvgForInlineDisplay(clone, svg2, inlineViewport);
24451
- clone.removeAttribute("id");
24452
- clone.removeAttribute("xmlns");
24453
- clone.removeAttribute("xmlns:xlink");
24454
- clone.setAttribute("class", mergeClassNames(clone.getAttribute("class"), "formulax-math__svg"));
24455
24324
  clone.setAttribute("focusable", "false");
24456
24325
  clone.setAttribute("aria-hidden", "true");
24457
- clone.setAttribute("preserveAspectRatio", clone.getAttribute("preserveAspectRatio") || "xMinYMin meet");
24458
- return new XMLSerializer().serializeToString(clone);
24326
+ clone.setAttribute("class", mergeClassNames(clone.getAttribute("class"), "formulax-math__svg"));
24327
+ return clone.outerHTML;
24459
24328
  }
24460
24329
  function getInlineSvgContent(svg2) {
24461
- const candidates = [
24462
- '[data-root="true"] > g[data-type="kf-editor-exp-content-box"]',
24463
- 'g[data-type="kf-editor-exp-content-box"]',
24464
- 'g[data-type="kf-container"]',
24465
- "svg > g, g"
24330
+ const selectorCandidates = [
24331
+ '[data-type="kf-editor-exp-content-box"]',
24332
+ '[data-root="true"] [data-type="kf-editor-exp-content-box"]',
24333
+ 'g[data-root="true"]'
24466
24334
  ];
24467
- for (const selector of candidates) {
24468
- const content = svg2.querySelector(selector);
24469
- const rootSpace = content ? readSvgBoxInRootSpace(content) : null;
24470
- if (content && rootSpace) {
24471
- return {
24472
- root: content,
24473
- box: rootSpace.box,
24474
- matrix: rootSpace.matrix
24475
- };
24476
- }
24335
+ for (const selector of selectorCandidates) {
24336
+ const element = svg2.querySelector(selector);
24337
+ if (!element) continue;
24338
+ const rootSpace = readSvgBoxInRootSpace(element);
24339
+ if (!rootSpace) continue;
24340
+ return {
24341
+ box: rootSpace.box,
24342
+ matrix: rootSpace.matrix,
24343
+ root: element
24344
+ };
24477
24345
  }
24478
24346
  return null;
24479
24347
  }
@@ -24512,181 +24380,750 @@ var FormulaX = (() => {
24512
24380
  if (!elementMatrix) {
24513
24381
  return null;
24514
24382
  }
24515
- return rootMatrix ? multiplySvgMatrices(invertSvgMatrix(rootMatrix), elementMatrix) : toSvgMatrixLike(elementMatrix);
24383
+ return rootMatrix ? multiplySvgMatrices(invertSvgMatrix(rootMatrix), elementMatrix) : toSvgMatrixLike(elementMatrix);
24384
+ }
24385
+ function invertSvgMatrix(matrix) {
24386
+ const determinant = matrix.a * matrix.d - matrix.b * matrix.c;
24387
+ if (!Number.isFinite(determinant) || determinant === 0) {
24388
+ return {
24389
+ a: 1,
24390
+ b: 0,
24391
+ c: 0,
24392
+ d: 1,
24393
+ e: 0,
24394
+ f: 0
24395
+ };
24396
+ }
24397
+ return {
24398
+ a: matrix.d / determinant,
24399
+ b: -matrix.b / determinant,
24400
+ c: -matrix.c / determinant,
24401
+ d: matrix.a / determinant,
24402
+ e: (matrix.c * matrix.f - matrix.d * matrix.e) / determinant,
24403
+ f: (matrix.b * matrix.e - matrix.a * matrix.f) / determinant
24404
+ };
24405
+ }
24406
+ function multiplySvgMatrices(left, right) {
24407
+ return {
24408
+ a: left.a * right.a + left.c * right.b,
24409
+ b: left.b * right.a + left.d * right.b,
24410
+ c: left.a * right.c + left.c * right.d,
24411
+ d: left.b * right.c + left.d * right.d,
24412
+ e: left.a * right.e + left.c * right.f + left.e,
24413
+ f: left.b * right.e + left.d * right.f + left.f
24414
+ };
24415
+ }
24416
+ function toSvgMatrixLike(matrix) {
24417
+ return {
24418
+ a: matrix.a,
24419
+ b: matrix.b,
24420
+ c: matrix.c,
24421
+ d: matrix.d,
24422
+ e: matrix.e,
24423
+ f: matrix.f
24424
+ };
24425
+ }
24426
+ function readSvgBox(element) {
24427
+ if (typeof element.getBBox !== "function") {
24428
+ return null;
24429
+ }
24430
+ try {
24431
+ const box = element.getBBox();
24432
+ if (!Number.isFinite(box.width) || !Number.isFinite(box.height) || box.width <= 0 || box.height <= 0) {
24433
+ return null;
24434
+ }
24435
+ return {
24436
+ x: box.x,
24437
+ y: box.y,
24438
+ width: box.width,
24439
+ height: box.height
24440
+ };
24441
+ } catch {
24442
+ return null;
24443
+ }
24444
+ }
24445
+ function createInlineSvgViewport(contentBox) {
24446
+ const edgePadding = Math.max(0.5, Math.min(contentBox.width, contentBox.height) * 6e-3);
24447
+ const inset = edgePadding / 2;
24448
+ return {
24449
+ x: contentBox.x - inset,
24450
+ y: contentBox.y - inset,
24451
+ width: contentBox.width + edgePadding,
24452
+ height: contentBox.height + edgePadding
24453
+ };
24454
+ }
24455
+ function createInlineSvgClone(source, content, viewport) {
24456
+ const clone = source.cloneNode(false);
24457
+ const ownerDocument = source.ownerDocument;
24458
+ copySvgRootAttributes(source, clone);
24459
+ clone.setAttribute(
24460
+ "viewBox",
24461
+ `0 0 ${roundLength(viewport.width)} ${roundLength(viewport.height)}`
24462
+ );
24463
+ Array.from(source.children).forEach((child) => {
24464
+ if (child.tagName.toLowerCase() === "defs") {
24465
+ clone.appendChild(child.cloneNode(true));
24466
+ }
24467
+ });
24468
+ const wrapper = ownerDocument.createElementNS("http://www.w3.org/2000/svg", "g");
24469
+ wrapper.setAttribute(
24470
+ "transform",
24471
+ `translate(${roundLength(-viewport.x)} ${roundLength(-viewport.y)})`
24472
+ );
24473
+ const flattened = ownerDocument.createElementNS("http://www.w3.org/2000/svg", "g");
24474
+ flattened.setAttribute(
24475
+ "transform",
24476
+ `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)})`
24477
+ );
24478
+ flattened.appendChild(content.root.cloneNode(true));
24479
+ wrapper.appendChild(flattened);
24480
+ clone.appendChild(wrapper);
24481
+ return clone;
24482
+ }
24483
+ function copySvgRootAttributes(source, target) {
24484
+ const excluded = /* @__PURE__ */ new Set([
24485
+ "id",
24486
+ "width",
24487
+ "height",
24488
+ "viewBox",
24489
+ "font-size",
24490
+ "class",
24491
+ "focusable",
24492
+ "aria-hidden",
24493
+ "xmlns",
24494
+ "xmlns:xlink"
24495
+ ]);
24496
+ Array.from(source.attributes).forEach((attribute) => {
24497
+ if (excluded.has(attribute.name)) return;
24498
+ target.setAttribute(attribute.name, attribute.value);
24499
+ });
24500
+ }
24501
+ function calculateInlineHeightEm(height2) {
24502
+ const heightRatio = height2 / BASE_FORMULA_HEIGHT;
24503
+ if (!Number.isFinite(heightRatio) || heightRatio <= SIMPLE_FORMULA_HEIGHT_RATIO) {
24504
+ return SIMPLE_INLINE_HEIGHT_EM;
24505
+ }
24506
+ return Math.min(
24507
+ MAX_INLINE_HEIGHT_EM,
24508
+ SIMPLE_INLINE_HEIGHT_EM * Math.pow(heightRatio, COMPLEX_FORMULA_SCALE)
24509
+ );
24510
+ }
24511
+ function sizeSvgForInlineDisplay(clone, source, viewport) {
24512
+ clone.removeAttribute("font-size");
24513
+ const viewBox = clone.viewBox?.baseVal;
24514
+ const rect = source.getBoundingClientRect();
24515
+ const width2 = viewport?.width || viewBox?.width || rect.width || Number(clone.getAttribute("width")) || 1;
24516
+ const height2 = viewport?.height || viewBox?.height || rect.height || Number(clone.getAttribute("height")) || 1;
24517
+ const ratio = Math.max(0.1, width2 / Math.max(1, height2));
24518
+ const inlineHeightEm = calculateInlineHeightEm(height2);
24519
+ const inlineWidthEm = Math.min(40, Math.max(0.75, ratio * inlineHeightEm));
24520
+ clone.setAttribute("width", roundLength(width2));
24521
+ clone.setAttribute("height", roundLength(height2));
24522
+ clone.setAttribute(
24523
+ "style",
24524
+ mergeInlineStyles(
24525
+ clone.getAttribute("style"),
24526
+ "font-size:inherit",
24527
+ `width:${roundLength(inlineWidthEm)}em`,
24528
+ `height:${roundLength(inlineHeightEm)}em`
24529
+ )
24530
+ );
24531
+ }
24532
+ function roundLength(value) {
24533
+ return String(Math.round(value * 1e3) / 1e3);
24534
+ }
24535
+ function uniquifySvgIds(svg2) {
24536
+ const idMap = /* @__PURE__ */ new Map();
24537
+ const prefix = `fx-${randomIdPrefix()}-`;
24538
+ const elementsWithId = svg2.querySelectorAll("[id]");
24539
+ elementsWithId.forEach((element) => {
24540
+ const id = element.getAttribute("id");
24541
+ if (!id) return;
24542
+ const nextId = `${prefix}${id}`;
24543
+ idMap.set(id, nextId);
24544
+ element.setAttribute("id", nextId);
24545
+ });
24546
+ if (!idMap.size) return;
24547
+ svg2.querySelectorAll("*").forEach((element) => {
24548
+ Array.from(element.attributes).forEach((attribute) => {
24549
+ const nextValue = rewriteSvgReferences(attribute.value, idMap);
24550
+ if (nextValue !== attribute.value) {
24551
+ element.setAttribute(attribute.name, nextValue);
24552
+ }
24553
+ });
24554
+ });
24555
+ }
24556
+ function randomIdPrefix() {
24557
+ return Math.random().toString(36).slice(2, 5).padEnd(3, "0");
24558
+ }
24559
+ function rewriteSvgReferences(value, idMap) {
24560
+ let nextValue = value;
24561
+ idMap.forEach((nextId, id) => {
24562
+ nextValue = nextValue.replaceAll(`#${id}`, `#${nextId}`).replaceAll(`url(${id})`, `url(${nextId})`).replaceAll(`url(#${id})`, `url(#${nextId})`);
24563
+ });
24564
+ return nextValue;
24565
+ }
24566
+ function mergeClassNames(...values) {
24567
+ return values.flatMap((value) => value?.split(/\s+/) ?? []).filter(Boolean).filter((value, index, list) => list.indexOf(value) === index).join(" ");
24568
+ }
24569
+ function mergeInlineStyles(...values) {
24570
+ return values.flatMap((value) => value?.split(";") ?? []).map((value) => value.trim()).filter(Boolean).join("; ");
24571
+ }
24572
+
24573
+ // ../renderer-kity/src/dom.ts
24574
+ async function waitForDocumentFonts(doc2) {
24575
+ if (!doc2.fonts?.ready) return;
24576
+ try {
24577
+ await doc2.fonts.ready;
24578
+ } catch {
24579
+ }
24580
+ }
24581
+ function waitForAnimationFrame(view) {
24582
+ return new Promise((resolve) => {
24583
+ view.requestAnimationFrame(() => resolve());
24584
+ });
24585
+ }
24586
+
24587
+ // ../renderer-kity/src/serialize.ts
24588
+ function findKityFormulaSvg(root2) {
24589
+ return root2.querySelector(
24590
+ ".kf-editor-edit-area svg, .kf-editor-canvas-container svg, svg"
24591
+ );
24592
+ }
24593
+ function serializeKityFormulaFromRoot(root2) {
24594
+ const svg2 = findKityFormulaSvg(root2);
24595
+ if (!svg2) {
24596
+ return "";
24597
+ }
24598
+ return serializeSvgForInsertion(svg2);
24599
+ }
24600
+ async function waitForKityFormulaSvgLayout(root2) {
24601
+ const doc2 = root2.ownerDocument ?? document;
24602
+ const view = doc2.defaultView ?? window;
24603
+ await waitForDocumentFonts(doc2);
24604
+ let previous = readRenderedFormulaBox(root2);
24605
+ for (let attempt = 0; attempt < 4; attempt += 1) {
24606
+ await waitForAnimationFrame(view);
24607
+ const current = readRenderedFormulaBox(root2);
24608
+ if (previous && current && areSvgBoxesClose(previous, current)) {
24609
+ return;
24610
+ }
24611
+ previous = current;
24612
+ }
24613
+ }
24614
+ function readRenderedFormulaBox(root2) {
24615
+ const svg2 = findKityFormulaSvg(root2);
24616
+ if (!svg2) {
24617
+ return null;
24618
+ }
24619
+ return readRenderedFormulaSvgBox(svg2);
24620
+ }
24621
+ function areSvgBoxesClose(left, right) {
24622
+ 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;
24623
+ }
24624
+
24625
+ // src/perf.ts
24626
+ function getPerfHost2() {
24627
+ return globalThis;
24628
+ }
24629
+ function getPerfState2() {
24630
+ const host = getPerfHost2();
24631
+ host.__FORMULAX_PERF_STATE__ ??= {
24632
+ reportedMeasureCount: 0,
24633
+ reportScheduled: false
24634
+ };
24635
+ return host.__FORMULAX_PERF_STATE__;
24636
+ }
24637
+ function hasPerfSupport2() {
24638
+ return typeof performance !== "undefined" && typeof performance.mark === "function" && typeof performance.measure === "function" && typeof performance.getEntriesByType === "function";
24639
+ }
24640
+ function isPerfDebugEnabled2() {
24641
+ return getPerfHost2().__FORMULAX_PERF__ === true;
24642
+ }
24643
+ function schedulePerfReport2() {
24644
+ if (!hasPerfSupport2() || !isPerfDebugEnabled2()) {
24645
+ return;
24646
+ }
24647
+ const state = getPerfState2();
24648
+ if (state.reportScheduled) {
24649
+ return;
24650
+ }
24651
+ state.reportScheduled = true;
24652
+ queueMicrotask(() => {
24653
+ state.reportScheduled = false;
24654
+ const entries = performance.getEntriesByType("measure").filter((entry) => entry.name.startsWith("fx:")).sort((left, right) => left.startTime - right.startTime);
24655
+ const nextEntries = entries.slice(state.reportedMeasureCount);
24656
+ state.reportedMeasureCount = entries.length;
24657
+ if (!nextEntries.length) {
24658
+ return;
24659
+ }
24660
+ console.table(nextEntries.map((entry) => ({
24661
+ name: entry.name,
24662
+ duration: Number(entry.duration.toFixed(2)),
24663
+ startTime: Number(entry.startTime.toFixed(2))
24664
+ })));
24665
+ });
24666
+ }
24667
+ function markFormulaXPerf2(name) {
24668
+ if (!hasPerfSupport2()) {
24669
+ return null;
24670
+ }
24671
+ const markName = `${name}::${Date.now()}::${Math.random().toString(36).slice(2, 8)}`;
24672
+ performance.mark(markName);
24673
+ return markName;
24674
+ }
24675
+ function measureFormulaXPerf2(name, startMark, endMark) {
24676
+ if (!hasPerfSupport2() || !startMark) {
24677
+ return null;
24678
+ }
24679
+ const resolvedEndMark = endMark ?? markFormulaXPerf2(`${name}:end`);
24680
+ if (!resolvedEndMark) {
24681
+ return null;
24682
+ }
24683
+ performance.measure(name, startMark, resolvedEndMark);
24684
+ schedulePerfReport2();
24685
+ return resolvedEndMark;
24516
24686
  }
24517
- function invertSvgMatrix(matrix) {
24518
- const determinant = matrix.a * matrix.d - matrix.b * matrix.c;
24519
- if (!Number.isFinite(determinant) || determinant === 0) {
24520
- return {
24521
- a: 1,
24522
- b: 0,
24523
- c: 0,
24524
- d: 1,
24525
- e: 0,
24526
- f: 0
24687
+ function recordFormulaXPerfPoint(name) {
24688
+ const markName = markFormulaXPerf2(name);
24689
+ if (!markName) {
24690
+ return;
24691
+ }
24692
+ measureFormulaXPerf2(name, markName, markName);
24693
+ clearFormulaXPerfMarks2(markName);
24694
+ }
24695
+ function clearFormulaXPerfMarks2(...marks) {
24696
+ if (!hasPerfSupport2()) {
24697
+ return;
24698
+ }
24699
+ for (const mark of marks) {
24700
+ if (!mark) {
24701
+ continue;
24702
+ }
24703
+ performance.clearMarks(mark);
24704
+ }
24705
+ }
24706
+ async function preloadFormulaXEditor() {
24707
+ await ensureKityRuntime();
24708
+ }
24709
+ function scheduleFormulaXEditorPreload(mode, target) {
24710
+ if (mode === false || typeof window === "undefined") {
24711
+ return () => void 0;
24712
+ }
24713
+ let disposed = false;
24714
+ let triggered = false;
24715
+ const cleanupCallbacks = [];
24716
+ const trigger = () => {
24717
+ if (disposed || triggered) {
24718
+ return;
24719
+ }
24720
+ triggered = true;
24721
+ while (cleanupCallbacks.length) {
24722
+ cleanupCallbacks.pop()?.();
24723
+ }
24724
+ void preloadFormulaXEditor();
24725
+ };
24726
+ if (mode === "idle") {
24727
+ const host = getPerfHost2();
24728
+ if (typeof host.requestIdleCallback === "function") {
24729
+ const handle = host.requestIdleCallback(() => {
24730
+ trigger();
24731
+ });
24732
+ cleanupCallbacks.push(() => {
24733
+ host.cancelIdleCallback?.(handle);
24734
+ });
24735
+ } else {
24736
+ const handle = window.setTimeout(() => {
24737
+ trigger();
24738
+ }, 1);
24739
+ cleanupCallbacks.push(() => {
24740
+ window.clearTimeout(handle);
24741
+ });
24742
+ }
24743
+ return () => {
24744
+ disposed = true;
24745
+ while (cleanupCallbacks.length) {
24746
+ cleanupCallbacks.pop()?.();
24747
+ }
24527
24748
  };
24528
24749
  }
24529
- return {
24530
- a: matrix.d / determinant,
24531
- b: -matrix.b / determinant,
24532
- c: -matrix.c / determinant,
24533
- d: matrix.a / determinant,
24534
- e: (matrix.c * matrix.f - matrix.d * matrix.e) / determinant,
24535
- f: (matrix.b * matrix.e - matrix.a * matrix.f) / determinant
24750
+ if (target && "addEventListener" in target && "removeEventListener" in target) {
24751
+ const eventTarget = target;
24752
+ const onActivate = () => {
24753
+ trigger();
24754
+ };
24755
+ eventTarget.addEventListener("pointerenter", onActivate, { once: true, passive: true });
24756
+ eventTarget.addEventListener("focusin", onActivate, { once: true });
24757
+ cleanupCallbacks.push(() => {
24758
+ eventTarget.removeEventListener("pointerenter", onActivate);
24759
+ eventTarget.removeEventListener("focusin", onActivate);
24760
+ });
24761
+ }
24762
+ return () => {
24763
+ disposed = true;
24764
+ while (cleanupCallbacks.length) {
24765
+ cleanupCallbacks.pop()?.();
24766
+ }
24536
24767
  };
24537
24768
  }
24538
- function multiplySvgMatrices(left, right) {
24539
- return {
24540
- a: left.a * right.a + left.c * right.b,
24541
- b: left.b * right.a + left.d * right.b,
24542
- c: left.a * right.c + left.c * right.d,
24543
- d: left.b * right.c + left.d * right.d,
24544
- e: left.a * right.e + left.c * right.f + left.e,
24545
- f: left.b * right.e + left.d * right.f + left.f
24546
- };
24769
+ function waitForFormulaXAnimationFrame() {
24770
+ if (typeof window === "undefined" || typeof window.requestAnimationFrame !== "function") {
24771
+ return Promise.resolve();
24772
+ }
24773
+ return new Promise((resolve) => {
24774
+ window.requestAnimationFrame(() => resolve());
24775
+ });
24776
+ }
24777
+
24778
+ // src/formula-modal.ts
24779
+ var EMPTY_FORMULA_PLACEHOLDER = "\\placeholder ";
24780
+ var STYLE_ID = "fx-formula-modal-styles";
24781
+ var formulaXModalStyles = `
24782
+ .fx-formula-modal-open {
24783
+ overflow: hidden;
24784
+ }
24785
+
24786
+ .fx-formula-modal-root {
24787
+ position: fixed;
24788
+ inset: 0;
24789
+ z-index: 2147483000;
24790
+ display: flex;
24791
+ align-items: center;
24792
+ justify-content: center;
24793
+ }
24794
+
24795
+ .fx-formula-modal-backdrop {
24796
+ position: absolute;
24797
+ inset: 0;
24798
+ background: rgba(15, 23, 42, 0.48);
24799
+ }
24800
+
24801
+ .fx-formula-modal {
24802
+ --fx-formula-editor-body-height: 264px;
24803
+ --fx-formula-workspace-height: 168px;
24804
+ position: relative;
24805
+ width: min(860px, calc(100vw - 32px));
24806
+ height: auto;
24807
+ max-height: calc(100vh - 32px);
24808
+ background: #fff;
24809
+ border-radius: 14px;
24810
+ box-shadow: 0 24px 80px rgba(15, 23, 42, 0.28);
24811
+ display: flex;
24812
+ flex-direction: column;
24813
+ overflow: visible;
24814
+ isolation: isolate;
24815
+ }
24816
+
24817
+ .fx-formula-modal__header,
24818
+ .fx-formula-modal__footer,
24819
+ .fx-formula-modal__title,
24820
+ .fx-formula-modal__close,
24821
+ .fx-formula-modal__button,
24822
+ .fx-formula-editor-loading,
24823
+ .fx-formula-editor-error {
24824
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
24825
+ }
24826
+
24827
+ .fx-formula-modal__header {
24828
+ min-height: 56px;
24829
+ padding: 0 20px;
24830
+ border-bottom: 1px solid #e5e7eb;
24831
+ display: flex;
24832
+ align-items: center;
24833
+ justify-content: space-between;
24834
+ flex-shrink: 0;
24835
+ position: relative;
24836
+ z-index: 3;
24837
+ background: #fff;
24838
+ border-radius: 14px 14px 0 0;
24839
+ }
24840
+
24841
+ .fx-formula-modal__title {
24842
+ font-size: 16px;
24843
+ font-weight: 650;
24844
+ margin: 0;
24845
+ color: #111827;
24846
+ }
24847
+
24848
+ .fx-formula-modal__close {
24849
+ border: 0;
24850
+ background: transparent;
24851
+ font-size: 24px;
24852
+ line-height: 1;
24853
+ cursor: pointer;
24854
+ color: #6b7280;
24855
+ }
24856
+
24857
+ .fx-formula-modal__body {
24858
+ flex: 0 0 auto;
24859
+ height: var(--fx-formula-editor-body-height);
24860
+ padding: 0;
24861
+ overflow: visible;
24862
+ min-height: var(--fx-formula-editor-body-height);
24863
+ position: relative;
24864
+ z-index: 2;
24865
+ }
24866
+
24867
+ .fx-formula-editor-host {
24868
+ width: 100%;
24869
+ height: var(--fx-formula-editor-body-height);
24870
+ min-height: var(--fx-formula-editor-body-height);
24871
+ overflow: visible;
24872
+ position: relative;
24873
+ }
24874
+
24875
+ .fx-formula-kity-host {
24876
+ width: 100%;
24877
+ height: var(--fx-formula-editor-body-height);
24878
+ min-height: var(--fx-formula-editor-body-height);
24879
+ overflow: visible;
24880
+ position: relative;
24881
+ }
24882
+
24883
+ .fx-formula-kity-host .kf-editor {
24884
+ box-sizing: border-box;
24885
+ width: 100%;
24886
+ height: var(--fx-formula-editor-body-height) !important;
24887
+ overflow: visible !important;
24888
+ }
24889
+
24890
+ .fx-formula-kity-host .kf-editor-toolbar {
24891
+ overflow: visible;
24892
+ position: relative;
24893
+ z-index: 20;
24894
+ }
24895
+
24896
+ .fx-formula-kity-host .kf-editor-ui-button-mount-point,
24897
+ .fx-formula-kity-host .kf-editor-ui-area-mount,
24898
+ .fx-formula-kity-host .kf-editor-ui-box,
24899
+ .fx-formula-kity-host .kf-editor-ui-list {
24900
+ z-index: 1000;
24901
+ }
24902
+
24903
+ .fx-formula-kity-host .kf-editor-edit-area,
24904
+ .fx-formula-kity-host .kf-editor-canvas-container {
24905
+ min-height: var(--fx-formula-workspace-height);
24906
+ height: var(--fx-formula-workspace-height);
24907
+ }
24908
+
24909
+ .fx-formula-kity-host .kf-editor-edit-area {
24910
+ flex: 0 0 auto;
24911
+ overflow: hidden;
24912
+ }
24913
+
24914
+ .fx-formula-kity-host .kf-editor,
24915
+ .fx-formula-kity-host .kf-editor svg text,
24916
+ .fx-formula-kity-host .kf-editor-ui-area-item-text,
24917
+ .fx-formula-kity-host .kf-editor-ui-box-item-text,
24918
+ .fx-formula-kity-host .kf-editor-ui-box-item-val {
24919
+ font-family: "KF AMS MAIN", "Cambria Math", "Latin Modern Math", "Times New Roman", serif !important;
24920
+ }
24921
+
24922
+ .fx-formula-kity-host .kf-editor-ui-box-item-content,
24923
+ .fx-formula-kity-host .kf-editor-ui-box-item-val {
24924
+ min-width: 32px;
24925
+ min-height: 32px;
24926
+ }
24927
+
24928
+ .fx-formula-kity-host .kf-editor-ui-box-item-val svg,
24929
+ .fx-formula-kity-host .kf-editor-ui-box-item-val img,
24930
+ .fx-formula-kity-host .kf-editor-ui-area-item-img,
24931
+ .fx-formula-kity-host .kf-editor-ui-area-item-text {
24932
+ display: block;
24933
+ }
24934
+
24935
+ .fx-formula-editor-loading {
24936
+ height: var(--fx-formula-editor-body-height);
24937
+ padding: 24px;
24938
+ color: #4b5563;
24939
+ text-align: center;
24940
+ display: flex;
24941
+ align-items: center;
24942
+ justify-content: center;
24943
+ }
24944
+
24945
+ .fx-formula-editor-error {
24946
+ padding: 24px;
24947
+ color: #dc2626;
24948
+ font-size: 14px;
24949
+ }
24950
+
24951
+ .fx-formula-editor-error pre {
24952
+ white-space: pre-wrap;
24953
+ word-break: break-all;
24954
+ color: #991b1b;
24955
+ background: #fef2f2;
24956
+ border: 1px solid #fecaca;
24957
+ border-radius: 8px;
24958
+ padding: 12px;
24959
+ margin-top: 8px;
24960
+ }
24961
+
24962
+ .fx-formula-modal__footer {
24963
+ min-height: 64px;
24964
+ padding: 12px 20px;
24965
+ border-top: 1px solid #e5e7eb;
24966
+ display: flex;
24967
+ align-items: center;
24968
+ justify-content: flex-end;
24969
+ gap: 12px;
24970
+ flex-shrink: 0;
24971
+ position: relative;
24972
+ z-index: 1;
24973
+ background: #fff;
24974
+ border-radius: 0 0 14px 14px;
24975
+ }
24976
+
24977
+ .fx-formula-modal__button {
24978
+ appearance: none;
24979
+ border: 1px solid #d1d5db;
24980
+ background: #fff;
24981
+ color: #111827;
24982
+ border-radius: 8px;
24983
+ padding: 8px 14px;
24984
+ font-size: 14px;
24985
+ cursor: pointer;
24986
+ }
24987
+
24988
+ .fx-formula-modal__button--primary {
24989
+ border-color: #2563eb;
24990
+ background: #2563eb;
24991
+ color: #fff;
24992
+ }
24993
+ `;
24994
+ function ensureFormulaXModalStyles(doc2 = document) {
24995
+ ensureFormulaXBaseStyles(doc2);
24996
+ if (doc2.getElementById(STYLE_ID)) return;
24997
+ const style = doc2.createElement("style");
24998
+ style.id = STYLE_ID;
24999
+ style.textContent = formulaXModalStyles;
25000
+ doc2.head.appendChild(style);
25001
+ }
25002
+ function renderFormulaXEditorLoadingState(root2) {
25003
+ root2.classList.add("fx-formula-kity-host");
25004
+ root2.innerHTML = `
25005
+ <div class="fx-formula-editor-loading" role="status" aria-live="polite">
25006
+ Loading FormulaX editor...
25007
+ </div>
25008
+ `;
24547
25009
  }
24548
- function toSvgMatrixLike(matrix) {
25010
+ function mountFormulaXEditor(root2, options = {}) {
25011
+ recordFormulaXPerfPoint("fx:formula-editor:mount:start");
25012
+ const mountStart = markFormulaXPerf2("fx:formula-editor:mount:start:scope");
25013
+ let destroyed = false;
25014
+ let latestLatex = options.initialLatex ?? "";
25015
+ let handle = null;
25016
+ const initialLatex = latestLatex.trim() ? latestLatex : EMPTY_FORMULA_PLACEHOLDER;
25017
+ renderFormulaXEditorLoadingState(root2);
25018
+ const loadingVisibleMark = markFormulaXPerf2("fx:formula-editor:loading-visible");
25019
+ measureFormulaXPerf2("fx:formula-editor:loading-visible", mountStart, loadingVisibleMark);
25020
+ clearFormulaXPerfMarks2(loadingVisibleMark);
25021
+ const readyPromise = mountKityEditor(root2, {
25022
+ initialLatex,
25023
+ height: options.height ?? "100%",
25024
+ autofocus: options.autofocus ?? true,
25025
+ assets: options.assets,
25026
+ render: {
25027
+ fontsize: options.render?.fontsize ?? 40
25028
+ }
25029
+ }).then((nextHandle) => {
25030
+ if (destroyed) {
25031
+ nextHandle.destroy();
25032
+ throw new Error("FormulaX editor mount cancelled");
25033
+ }
25034
+ const readyMark = markFormulaXPerf2("fx:kity-editor:ready");
25035
+ measureFormulaXPerf2("fx:kity-editor:ready", mountStart, readyMark);
25036
+ clearFormulaXPerfMarks2(readyMark);
25037
+ handle = nextHandle;
25038
+ return nextHandle;
25039
+ }).catch((error) => {
25040
+ console.error("[FormulaX] Failed to load FormulaX editor:", error);
25041
+ if (!destroyed) {
25042
+ root2.innerHTML = `
25043
+ <div class="fx-formula-editor-error">
25044
+ Failed to load FormulaX editor.
25045
+ <pre>${escapeHtml(error instanceof Error ? error.message : String(error))}</pre>
25046
+ </div>
25047
+ `;
25048
+ }
25049
+ throw error;
25050
+ }).finally(() => {
25051
+ clearFormulaXPerfMarks2(mountStart);
25052
+ });
25053
+ const getCurrentLatex = async () => {
25054
+ const readyHandle = handle ?? await readyPromise;
25055
+ const latex = await tryReadLatexFromKityHandle(readyHandle);
25056
+ if (latex !== null) {
25057
+ latestLatex = latex;
25058
+ }
25059
+ return latestLatex;
25060
+ };
24549
25061
  return {
24550
- a: matrix.a,
24551
- b: matrix.b,
24552
- c: matrix.c,
24553
- d: matrix.d,
24554
- e: matrix.e,
24555
- f: matrix.f
25062
+ root: root2,
25063
+ getLatex: getCurrentLatex,
25064
+ async getState() {
25065
+ const latex = await getCurrentLatex();
25066
+ try {
25067
+ return {
25068
+ ...createEmptyState(),
25069
+ doc: parseLatex(latex)
25070
+ };
25071
+ } catch {
25072
+ return createEmptyState();
25073
+ }
25074
+ },
25075
+ async getRenderHtml() {
25076
+ await readyPromise;
25077
+ await waitForKityFormulaSvgLayout(root2);
25078
+ return serializeKityFormulaFromRoot(root2);
25079
+ },
25080
+ destroy() {
25081
+ if (destroyed) return;
25082
+ destroyed = true;
25083
+ void readyPromise.then((readyHandle) => readyHandle.destroy()).catch(() => void 0);
25084
+ root2.innerHTML = "";
25085
+ }
24556
25086
  };
24557
25087
  }
24558
- function readSvgBox(element) {
24559
- if (typeof element.getBBox !== "function") {
24560
- return null;
24561
- }
25088
+ async function tryReadLatexFromKityHandle(handle) {
24562
25089
  try {
24563
- const box = element.getBBox();
24564
- if (!Number.isFinite(box.width) || !Number.isFinite(box.height) || box.width <= 0 || box.height <= 0) {
24565
- return null;
25090
+ let isEmpty = false;
25091
+ handle.ready(function ready() {
25092
+ const result = this.execCommand("content.is.empty");
25093
+ isEmpty = result === true;
25094
+ });
25095
+ if (isEmpty) {
25096
+ return "";
24566
25097
  }
24567
- return {
24568
- x: box.x,
24569
- y: box.y,
24570
- width: box.width,
24571
- height: box.height
24572
- };
24573
25098
  } catch {
24574
- return null;
24575
25099
  }
24576
- }
24577
- function createInlineSvgViewport(contentBox) {
24578
- const edgePadding = Math.max(0.5, Math.min(contentBox.width, contentBox.height) * 6e-3);
24579
- const inset = edgePadding / 2;
24580
- return {
24581
- x: contentBox.x - inset,
24582
- y: contentBox.y - inset,
24583
- width: contentBox.width + edgePadding,
24584
- height: contentBox.height + edgePadding
24585
- };
24586
- }
24587
- function createInlineSvgClone(source, content, viewport) {
24588
- const clone = source.cloneNode(false);
24589
- const ownerDocument = source.ownerDocument;
24590
- copySvgRootAttributes(source, clone);
24591
- clone.setAttribute(
24592
- "viewBox",
24593
- `0 0 ${roundLength(viewport.width)} ${roundLength(viewport.height)}`
24594
- );
24595
- Array.from(source.children).forEach((child) => {
24596
- if (child.tagName.toLowerCase() === "defs") {
24597
- clone.appendChild(child.cloneNode(true));
24598
- }
24599
- });
24600
- const wrapper = ownerDocument.createElementNS("http://www.w3.org/2000/svg", "g");
24601
- wrapper.setAttribute(
24602
- "transform",
24603
- `translate(${roundLength(-viewport.x)} ${roundLength(-viewport.y)})`
24604
- );
24605
- const flattened = ownerDocument.createElementNS("http://www.w3.org/2000/svg", "g");
24606
- flattened.setAttribute(
24607
- "transform",
24608
- `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)})`
24609
- );
24610
- flattened.appendChild(content.root.cloneNode(true));
24611
- wrapper.appendChild(flattened);
24612
- clone.appendChild(wrapper);
24613
- return clone;
24614
- }
24615
- function copySvgRootAttributes(source, target) {
24616
- const excluded = /* @__PURE__ */ new Set([
24617
- "id",
24618
- "width",
24619
- "height",
24620
- "viewBox",
24621
- "class",
24622
- "focusable",
24623
- "aria-hidden",
24624
- "xmlns",
24625
- "xmlns:xlink"
24626
- ]);
24627
- Array.from(source.attributes).forEach((attribute) => {
24628
- if (excluded.has(attribute.name)) return;
24629
- target.setAttribute(attribute.name, attribute.value);
24630
- });
24631
- }
24632
- function sizeSvgForInlineDisplay(clone, source, viewport) {
24633
- const viewBox = clone.viewBox?.baseVal;
24634
- const rect = source.getBoundingClientRect();
24635
- const width2 = viewport?.width || viewBox?.width || rect.width || Number(clone.getAttribute("width")) || 1;
24636
- const height2 = viewport?.height || viewBox?.height || rect.height || Number(clone.getAttribute("height")) || 1;
24637
- const ratio = Math.max(0.1, width2 / Math.max(1, height2));
24638
- const inlineHeightEm = 0.875;
24639
- const inlineWidthEm = Math.min(40, Math.max(0.75, ratio * inlineHeightEm));
24640
- clone.setAttribute("width", roundLength(width2));
24641
- clone.setAttribute("height", roundLength(height2));
24642
- clone.setAttribute(
24643
- "style",
24644
- mergeInlineStyles2(
24645
- clone.getAttribute("style"),
24646
- `width:${roundLength(inlineWidthEm)}em`,
24647
- `height:${inlineHeightEm}em`
24648
- )
24649
- );
24650
- }
24651
- function roundLength(value) {
24652
- return String(Math.round(value * 1e3) / 1e3);
24653
- }
24654
- function uniquifySvgIds(svg2) {
24655
- const idMap = /* @__PURE__ */ new Map();
24656
- const prefix = `fx-${randomIdPrefix()}-`;
24657
- const elementsWithId = svg2.querySelectorAll("[id]");
24658
- elementsWithId.forEach((element) => {
24659
- const id = element.getAttribute("id");
24660
- if (!id) return;
24661
- const nextId = `${prefix}${id}`;
24662
- idMap.set(id, nextId);
24663
- element.setAttribute("id", nextId);
24664
- });
24665
- if (!idMap.size) return;
24666
- svg2.querySelectorAll("*").forEach((element) => {
24667
- Array.from(element.attributes).forEach((attribute) => {
24668
- const nextValue = rewriteSvgReferences(attribute.value, idMap);
24669
- if (nextValue !== attribute.value) {
24670
- element.setAttribute(attribute.name, nextValue);
25100
+ const candidates = [
25101
+ "get.source",
25102
+ "getSource",
25103
+ "getLatex",
25104
+ "get.latex",
25105
+ "get.content",
25106
+ "getContent"
25107
+ ];
25108
+ for (const command of candidates) {
25109
+ try {
25110
+ let value = null;
25111
+ handle.ready(function ready() {
25112
+ value = this.execCommand(command);
25113
+ });
25114
+ if (typeof value === "string" && value.trim()) {
25115
+ return value;
24671
25116
  }
24672
- });
24673
- });
24674
- }
24675
- function randomIdPrefix() {
24676
- return Math.random().toString(36).slice(2, 5).padEnd(3, "0");
24677
- }
24678
- function rewriteSvgReferences(value, idMap) {
24679
- let nextValue = value;
24680
- idMap.forEach((nextId, id) => {
24681
- nextValue = nextValue.replaceAll(`#${id}`, `#${nextId}`).replaceAll(`url(${id})`, `url(${nextId})`).replaceAll(`url(#${id})`, `url(#${nextId})`);
24682
- });
24683
- return nextValue;
24684
- }
24685
- function mergeClassNames(...values) {
24686
- return values.flatMap((value) => value?.split(/\s+/) ?? []).filter(Boolean).filter((value, index, list) => list.indexOf(value) === index).join(" ");
24687
- }
24688
- function mergeInlineStyles2(...values) {
24689
- return values.flatMap((value) => value?.split(";") ?? []).map((value) => value.trim()).filter(Boolean).join("; ");
25117
+ if (value && typeof value === "object" && "latex" in value) {
25118
+ const latex = value.latex;
25119
+ if (typeof latex === "string" && latex.trim()) {
25120
+ return latex;
25121
+ }
25122
+ }
25123
+ } catch {
25124
+ }
25125
+ }
25126
+ return null;
24690
25127
  }
24691
25128
  return __toCommonJS(index_exports);
24692
25129
  })();