@drghaliasri/butex 4.4.0 → 5.2.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.
@@ -6,6 +6,273 @@ function document2Id(prefix) {
6
6
  return id;
7
7
  }
8
8
 
9
+ // src/editor/digits.ts
10
+ var WESTERN = "0123456789";
11
+ var ARABIC_INDIC = "\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669";
12
+ var PERSIAN_INDIC = "\u06F0\u06F1\u06F2\u06F3\u06F4\u06F5\u06F6\u06F7\u06F8\u06F9";
13
+ var digitSets = {
14
+ western: WESTERN,
15
+ arabicIndic: ARABIC_INDIC,
16
+ persianIndic: PERSIAN_INDIC
17
+ };
18
+ function digitValue(char) {
19
+ const western = WESTERN.indexOf(char);
20
+ if (western >= 0) {
21
+ return western;
22
+ }
23
+ const arabicIndic = ARABIC_INDIC.indexOf(char);
24
+ if (arabicIndic >= 0) {
25
+ return arabicIndic;
26
+ }
27
+ return PERSIAN_INDIC.indexOf(char);
28
+ }
29
+ function formatDigits(value, digitForm = "western") {
30
+ const target = digitSets[digitForm];
31
+ return Array.from(value, (char) => {
32
+ const value2 = digitValue(char);
33
+ return value2 >= 0 ? target[value2] : char;
34
+ }).join("");
35
+ }
36
+
37
+ // src/document2/articleMeta.ts
38
+ var BUTEX_BASMALA = "\u0628\u0650\u0633\u0652\u0645\u0650 \u0627\u0644\u0644\u064E\u0651\u0647\u0650 \u0627\u0644\u0631\u064E\u0651\u062D\u0652\u0645\u064E\u0670\u0646\u0650 \u0627\u0644\u0631\u064E\u0651\u062D\u0650\u064A\u0645\u0650 \u0648\u064E\u0627\u0644\u0635\u064E\u0651\u0644\u064E\u0627\u0629\u064F \u0648\u064E\u0627\u0644\u0633\u064E\u0651\u0644\u064E\u0627\u0645\u064F \u0639\u064E\u0644\u064E\u0649\u0670 \u0631\u064E\u0633\u064F\u0648\u0644\u0650 \u0627\u0644\u0644\u064E\u0651\u0647\u0650 \uFDFA";
39
+ var BUTEX_CLOSING_HAMDALA = "\u0627\u0644\u0652\u062D\u064E\u0645\u0652\u062F\u064F \u0644\u0650\u0644\u064E\u0651\u0647\u0650 \u0646\u064E\u0641\u064E\u0639\u064E\u0646\u064E\u0627 \u0628\u0650\u0639\u0650\u0644\u0652\u0645\u0650\u0647\u0650";
40
+ function escapeButexTextArg(text) {
41
+ return text.replace(/\\/g, "\\textbackslash{}").replace(/[{}]/g, "\\$&");
42
+ }
43
+ function butexDiwaniDisplayTex(text) {
44
+ return `\\butexdiwani{${escapeButexTextArg(text)}}`;
45
+ }
46
+ function butexDiwaniDisplayLatex(text) {
47
+ return `\\[
48
+ ${butexDiwaniDisplayTex(text)}
49
+ \\]`;
50
+ }
51
+ var HIJRI_YEAR_MIN = 1400;
52
+ var HIJRI_YEAR_MAX = 1500;
53
+ var HIJRI_MONTH_IDS = [
54
+ "\u0645\u062D\u0631\u0645",
55
+ "\u0635\u0641\u0631",
56
+ "\u0631\u0628\u064A\u0639 \u0627\u0644\u0623\u0648\u0644",
57
+ "\u0631\u0628\u064A\u0639 \u0627\u0644\u0622\u062E\u0631",
58
+ "\u062C\u0645\u0627\u062F\u0649 \u0627\u0644\u0623\u0648\u0644\u0649",
59
+ "\u062C\u0645\u0627\u062F\u0649 \u0627\u0644\u0622\u062E\u0631\u0629",
60
+ "\u0631\u062C\u0628",
61
+ "\u0634\u0639\u0628\u0627\u0646",
62
+ "\u0631\u0645\u0636\u0627\u0646",
63
+ "\u0634\u0648\u0627\u0644",
64
+ "\u0630\u0648 \u0627\u0644\u0642\u0639\u062F\u0629",
65
+ "\u0630\u0648 \u0627\u0644\u062D\u062C\u0629"
66
+ ];
67
+ var HIJRI_MONTH_LABELS_EN = {
68
+ \u0645\u062D\u0631\u0645: "Muharram",
69
+ \u0635\u0641\u0631: "Safar",
70
+ "\u0631\u0628\u064A\u0639 \u0627\u0644\u0623\u0648\u0644": "Rabi\u02BB I",
71
+ "\u0631\u0628\u064A\u0639 \u0627\u0644\u0622\u062E\u0631": "Rabi\u02BB II",
72
+ "\u062C\u0645\u0627\u062F\u0649 \u0627\u0644\u0623\u0648\u0644\u0649": "Jumada I",
73
+ "\u062C\u0645\u0627\u062F\u0649 \u0627\u0644\u0622\u062E\u0631\u0629": "Jumada II",
74
+ \u0631\u062C\u0628: "Rajab",
75
+ \u0634\u0639\u0628\u0627\u0646: "Sha\u02BBban",
76
+ \u0631\u0645\u0636\u0627\u0646: "Ramadan",
77
+ \u0634\u0648\u0627\u0644: "Shawwal",
78
+ "\u0630\u0648 \u0627\u0644\u0642\u0639\u062F\u0629": "Dhul Qa\u02BBdah",
79
+ "\u0630\u0648 \u0627\u0644\u062D\u062C\u0629": "Dhul Hijjah"
80
+ };
81
+ var LEGACY_LATIN_MONTH = {
82
+ muharram: "\u0645\u062D\u0631\u0645",
83
+ safar: "\u0635\u0641\u0631",
84
+ rabiAwwal: "\u0631\u0628\u064A\u0639 \u0627\u0644\u0623\u0648\u0644",
85
+ rabiThani: "\u0631\u0628\u064A\u0639 \u0627\u0644\u0622\u062E\u0631",
86
+ jumadaAwwal: "\u062C\u0645\u0627\u062F\u0649 \u0627\u0644\u0623\u0648\u0644\u0649",
87
+ jumadaThani: "\u062C\u0645\u0627\u062F\u0649 \u0627\u0644\u0622\u062E\u0631\u0629",
88
+ rajab: "\u0631\u062C\u0628",
89
+ shaban: "\u0634\u0639\u0628\u0627\u0646",
90
+ ramadan: "\u0631\u0645\u0636\u0627\u0646",
91
+ shawwal: "\u0634\u0648\u0627\u0644",
92
+ dhulQadah: "\u0630\u0648 \u0627\u0644\u0642\u0639\u062F\u0629",
93
+ dhulHijjah: "\u0630\u0648 \u0627\u0644\u062D\u062C\u0629"
94
+ };
95
+ var DEFAULT_HIJRI_DATE = {
96
+ day: 1,
97
+ month: "\u0645\u062D\u0631\u0645",
98
+ year: 1448
99
+ };
100
+ function hijriMonthLabel(month, locale = "ar") {
101
+ return locale === "en" ? HIJRI_MONTH_LABELS_EN[month] : month;
102
+ }
103
+ function emptyDocument2Meta() {
104
+ return {
105
+ title: "",
106
+ authors: "",
107
+ date: { ...DEFAULT_HIJRI_DATE },
108
+ abstract: ""
109
+ };
110
+ }
111
+ function clampInt(value, min, max) {
112
+ if (!Number.isFinite(value)) {
113
+ return min;
114
+ }
115
+ return Math.min(max, Math.max(min, Math.trunc(value)));
116
+ }
117
+ function isHijriMonthId(value) {
118
+ return typeof value === "string" && HIJRI_MONTH_IDS.includes(value);
119
+ }
120
+ function resolveHijriMonthId(value) {
121
+ if (isHijriMonthId(value)) {
122
+ return value;
123
+ }
124
+ if (typeof value === "string" && value in LEGACY_LATIN_MONTH) {
125
+ return LEGACY_LATIN_MONTH[value];
126
+ }
127
+ return DEFAULT_HIJRI_DATE.month;
128
+ }
129
+ function normalizeDocument2HijriDate(value) {
130
+ if (typeof value !== "object" || value === null) {
131
+ return { ...DEFAULT_HIJRI_DATE };
132
+ }
133
+ const raw = value;
134
+ const day = clampInt(typeof raw.day === "number" ? raw.day : Number(raw.day), 1, 30);
135
+ const year = clampInt(typeof raw.year === "number" ? raw.year : Number(raw.year), HIJRI_YEAR_MIN, HIJRI_YEAR_MAX);
136
+ const month = resolveHijriMonthId(raw.month);
137
+ return { day, month, year };
138
+ }
139
+ function normalizeDocument2Meta(value) {
140
+ if (typeof value !== "object" || value === null) {
141
+ return emptyDocument2Meta();
142
+ }
143
+ const raw = value;
144
+ return {
145
+ title: typeof raw.title === "string" ? raw.title : "",
146
+ authors: typeof raw.authors === "string" ? raw.authors : "",
147
+ date: normalizeDocument2HijriDate(raw.date),
148
+ abstract: typeof raw.abstract === "string" ? raw.abstract : ""
149
+ };
150
+ }
151
+ function mergeDocument2Meta(fromJson, fromProp) {
152
+ const fromPropMeta = {
153
+ title: typeof fromProp?.title === "string" ? fromProp.title : "",
154
+ authors: typeof fromProp?.authors === "string" ? fromProp.authors : "",
155
+ abstract: typeof fromProp?.abstract === "string" ? fromProp.abstract : "",
156
+ date: fromProp?.date ? normalizeDocument2HijriDate({ ...DEFAULT_HIJRI_DATE, ...fromProp.date }) : { ...DEFAULT_HIJRI_DATE }
157
+ };
158
+ if (typeof fromJson !== "object" || fromJson === null) {
159
+ return fromPropMeta;
160
+ }
161
+ const json = fromJson;
162
+ return {
163
+ title: "title" in json && typeof json.title === "string" ? json.title : fromPropMeta.title,
164
+ authors: "authors" in json && typeof json.authors === "string" ? json.authors : fromPropMeta.authors,
165
+ abstract: "abstract" in json && typeof json.abstract === "string" ? json.abstract : fromPropMeta.abstract,
166
+ date: "date" in json ? normalizeDocument2HijriDate(json.date) : fromPropMeta.date
167
+ };
168
+ }
169
+ function fillDocument2MetaGaps(current, fromProp) {
170
+ if (!fromProp) {
171
+ return cloneDocument2Meta(current);
172
+ }
173
+ return {
174
+ title: current.title.trim().length > 0 ? current.title : typeof fromProp.title === "string" ? fromProp.title : current.title,
175
+ authors: current.authors.trim().length > 0 ? current.authors : typeof fromProp.authors === "string" ? fromProp.authors : current.authors,
176
+ abstract: current.abstract.trim().length > 0 ? current.abstract : typeof fromProp.abstract === "string" ? fromProp.abstract : current.abstract,
177
+ date: fromProp.date ? normalizeDocument2HijriDate({ ...current.date, ...fromProp.date }) : { ...current.date }
178
+ };
179
+ }
180
+ function document2HasMaketitle(meta) {
181
+ return meta.title.trim().length > 0 || meta.authors.trim().length > 0;
182
+ }
183
+ function document2HasAbstract(meta) {
184
+ return meta.abstract.trim().length > 0;
185
+ }
186
+ function document2HasTitleStack(meta) {
187
+ return document2HasMaketitle(meta) || document2HasAbstract(meta);
188
+ }
189
+ function formatHijriDate(date, options = "ar") {
190
+ const opts = typeof options === "string" ? { locale: options } : options;
191
+ const locale = opts.locale ?? "ar";
192
+ const digitForm = opts.digitForm ?? (locale === "en" ? "western" : "arabicIndic");
193
+ const month = hijriMonthLabel(date.month, locale);
194
+ const day = formatDigits(String(date.day), digitForm);
195
+ const year = formatDigits(String(date.year), digitForm);
196
+ if (locale === "en") {
197
+ return `${day} ${month} ${year} AH`;
198
+ }
199
+ return `${day} ${month} ${year}\u0647\u0640`;
200
+ }
201
+ function cloneDocument2Meta(meta) {
202
+ return {
203
+ title: meta.title,
204
+ authors: meta.authors,
205
+ date: { ...meta.date },
206
+ abstract: meta.abstract
207
+ };
208
+ }
209
+
210
+ // src/document2/citations.ts
211
+ function referenceNumberMap(references) {
212
+ const map = /* @__PURE__ */ new Map();
213
+ references.forEach((reference, index) => {
214
+ if (!map.has(reference.key)) {
215
+ map.set(reference.key, index + 1);
216
+ }
217
+ });
218
+ return map;
219
+ }
220
+ function resolveCiteNumbers(keys, references) {
221
+ const map = referenceNumberMap(references);
222
+ return keys.map((key) => map.get(key) ?? null);
223
+ }
224
+ function formatCiteLabel(keys, references, options = {}) {
225
+ const documentDirection = options.documentDirection ?? "rtl";
226
+ const digitForm = options.digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
227
+ const numbers = resolveCiteNumbers(keys, references).map((value) => value === null ? "?" : String(value));
228
+ const display = documentDirection === "rtl" ? [...numbers].reverse() : numbers;
229
+ const separator = documentDirection === "rtl" ? "\u060C" : ", ";
230
+ const body = display.map((part) => formatDigits(part, digitForm)).join(separator);
231
+ return `[${body}]`;
232
+ }
233
+ function formatBibliographyNumber(index, options = {}) {
234
+ const documentDirection = options.documentDirection ?? "rtl";
235
+ const digitForm = options.digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
236
+ return formatDigits(String(index), digitForm);
237
+ }
238
+ function parseCiteKeys(source) {
239
+ const match = /^\\cite\{([^}]*)\}$/.exec(source.trim());
240
+ if (!match) {
241
+ return [];
242
+ }
243
+ return (match[1] ?? "").split(",").map((key) => key.trim()).filter((key) => key.length > 0);
244
+ }
245
+ function citeTokenLatex(keys) {
246
+ return `\\cite{${keys.join(",")}}`;
247
+ }
248
+ function referenceFromJson(json) {
249
+ return {
250
+ id: document2Id("ref"),
251
+ key: json.key,
252
+ authors: typeof json.authors === "string" ? json.authors : "",
253
+ title: typeof json.title === "string" ? json.title : "",
254
+ year: typeof json.year === "string" ? json.year : "",
255
+ url: typeof json.url === "string" ? json.url : "",
256
+ venue: typeof json.venue === "string" ? json.venue : ""
257
+ };
258
+ }
259
+ function createEmptyReference2(partial = {}) {
260
+ return referenceFromJson({
261
+ key: partial.key ?? `ref${String(Date.now()).slice(-4)}`,
262
+ authors: partial.authors,
263
+ title: partial.title,
264
+ year: partial.year,
265
+ url: partial.url,
266
+ venue: partial.venue
267
+ });
268
+ }
269
+ function bibliographyEntryLatex(reference) {
270
+ const parts = [reference.authors, reference.title, reference.venue, reference.year].filter((part) => part.trim().length > 0);
271
+ const body = parts.join(", ");
272
+ const url = reference.url.trim().length > 0 ? ` \\url{${reference.url}}` : "";
273
+ return `\\bibitem{${reference.key}} ${body}${url}`.trim();
274
+ }
275
+
9
276
  // src/ast/commands/index.ts
10
277
  function renderCommandCore(context) {
11
278
  const optional = context.optionalArgs.map((arg) => `[${context.renderChain(arg)}]`).join("");
@@ -375,6 +642,168 @@ ${lines.map((line) => ` ${line}`).join(" \\\\\n")}
375
642
  ${math.closing}`;
376
643
  }
377
644
 
645
+ // src/document2/labels.ts
646
+ function defaultFloatMeta() {
647
+ return {
648
+ centered: true,
649
+ captionEnabled: false,
650
+ caption: "",
651
+ labelEnabled: false,
652
+ label: ""
653
+ };
654
+ }
655
+ function parseFloatMetaFromJson(json) {
656
+ const caption = typeof json.caption === "string" ? json.caption : "";
657
+ const label = typeof json.label === "string" ? json.label : "";
658
+ return {
659
+ centered: json.centered !== false,
660
+ captionEnabled: json.caption_enabled === true || typeof json.caption_enabled !== "boolean" && caption.length > 0,
661
+ caption,
662
+ labelEnabled: json.label_enabled === true || typeof json.label_enabled !== "boolean" && label.trim().length > 0,
663
+ label
664
+ };
665
+ }
666
+ function parseRefKeys(source) {
667
+ const eqref = /^\\eqref\{([^}]*)\}$/.exec(source.trim());
668
+ if (eqref) {
669
+ return {
670
+ refCommand: "eqref",
671
+ keys: (eqref[1] ?? "").split(",").map((key) => key.trim()).filter((key) => key.length > 0)
672
+ };
673
+ }
674
+ const ref = /^\\ref\{([^}]*)\}$/.exec(source.trim());
675
+ if (ref) {
676
+ return {
677
+ refCommand: "ref",
678
+ keys: (ref[1] ?? "").split(",").map((key) => key.trim()).filter((key) => key.length > 0)
679
+ };
680
+ }
681
+ return { keys: [], refCommand: "ref" };
682
+ }
683
+ function refTokenLatex(keys, refCommand) {
684
+ const command = refCommand === "eqref" ? "\\eqref" : "\\ref";
685
+ return `${command}{${keys.join(",")}}`;
686
+ }
687
+ function collectDocument2Labels(document2) {
688
+ const entries = [];
689
+ const counters = { fig: 0, tab: 0, eq: 0 };
690
+ function pushEqFromField(tokens) {
691
+ for (const token of tokens) {
692
+ if (token.kind !== "math") {
693
+ continue;
694
+ }
695
+ if (token.display && token.labelEnabled && token.label && token.label.trim().length > 0) {
696
+ counters.eq += 1;
697
+ entries.push({
698
+ key: token.label.trim(),
699
+ kind: "eq",
700
+ caption: "",
701
+ ownerId: token.id,
702
+ number: counters.eq
703
+ });
704
+ }
705
+ }
706
+ }
707
+ function walk(blocks) {
708
+ for (const block of blocks) {
709
+ if (block.kind === "image" && block.labelEnabled && block.label.trim().length > 0) {
710
+ counters.fig += 1;
711
+ entries.push({
712
+ key: block.label.trim(),
713
+ kind: "fig",
714
+ caption: block.captionEnabled ? block.caption : "",
715
+ ownerId: block.id,
716
+ number: counters.fig
717
+ });
718
+ }
719
+ if (block.kind === "table") {
720
+ if (block.labelEnabled && block.label.trim().length > 0) {
721
+ counters.tab += 1;
722
+ entries.push({
723
+ key: block.label.trim(),
724
+ kind: "tab",
725
+ caption: block.captionEnabled ? block.caption : "",
726
+ ownerId: block.id,
727
+ number: counters.tab
728
+ });
729
+ }
730
+ for (const row of block.rows) {
731
+ for (const cell of row) {
732
+ pushEqFromField(cell.tokens);
733
+ }
734
+ }
735
+ }
736
+ if (block.kind === "textBlock") {
737
+ pushEqFromField(block.field.tokens);
738
+ }
739
+ if (block.kind === "list") {
740
+ for (const item of block.items) {
741
+ pushEqFromField(item.field.tokens);
742
+ walk(item.blocks);
743
+ }
744
+ }
745
+ }
746
+ }
747
+ walk(document2.blocks);
748
+ return entries;
749
+ }
750
+ function labelNumberMap(document2) {
751
+ const map = /* @__PURE__ */ new Map();
752
+ for (const entry of collectDocument2Labels(document2)) {
753
+ if (!map.has(entry.key)) {
754
+ map.set(entry.key, { kind: entry.kind, number: entry.number });
755
+ }
756
+ }
757
+ return map;
758
+ }
759
+ function formatRefLabel(keys, document2, refCommand, options = {}) {
760
+ const documentDirection = options.documentDirection ?? "rtl";
761
+ const digitForm = options.digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
762
+ const map = labelNumberMap(document2);
763
+ const parts = keys.map((key) => {
764
+ const hit = map.get(key);
765
+ if (!hit) {
766
+ return "?";
767
+ }
768
+ return formatDigits(String(hit.number), digitForm);
769
+ });
770
+ const body = parts.join(documentDirection === "rtl" ? "\u060C" : ", ");
771
+ if (refCommand === "eqref") {
772
+ return `(${body})`;
773
+ }
774
+ return body;
775
+ }
776
+ function stripDisplayMathDelimiters(source) {
777
+ const trimmed = source.trim();
778
+ if (trimmed.startsWith("\\[") && trimmed.endsWith("\\]")) {
779
+ return trimmed.slice(2, -2).trim();
780
+ }
781
+ if (trimmed.startsWith("$$") && trimmed.endsWith("$$")) {
782
+ return trimmed.slice(2, -2).trim();
783
+ }
784
+ if (trimmed.startsWith("\\begin{equation}") && trimmed.endsWith("\\end{equation}")) {
785
+ return trimmed.slice("\\begin{equation}".length, -"\\end{equation}".length).trim();
786
+ }
787
+ return trimmed;
788
+ }
789
+ function applyFloatMetaPatch(block, patch) {
790
+ if (typeof patch.centered === "boolean") {
791
+ block.centered = patch.centered;
792
+ }
793
+ if (typeof patch.captionEnabled === "boolean") {
794
+ block.captionEnabled = patch.captionEnabled;
795
+ }
796
+ if (typeof patch.caption === "string") {
797
+ block.caption = patch.caption;
798
+ }
799
+ if (typeof patch.labelEnabled === "boolean") {
800
+ block.labelEnabled = patch.labelEnabled;
801
+ }
802
+ if (typeof patch.label === "string") {
803
+ block.label = patch.label;
804
+ }
805
+ }
806
+
378
807
  // src/document2/inlineScanner.ts
379
808
  var MATH_ENVIRONMENTS = /* @__PURE__ */ new Set([
380
809
  "equation",
@@ -424,53 +853,127 @@ function environmentSpan(value, start) {
424
853
  const end = closingStart + closing.length;
425
854
  return { start, end, source: value.slice(start, end), opening, closing, display: true };
426
855
  }
427
- function detectMathSpans2(value) {
428
- const spans = [];
429
- let i = 0;
430
- while (i < value.length) {
431
- if (value.startsWith("\\begin{", i)) {
432
- const span = environmentSpan(value, i);
433
- if (span) {
434
- spans.push(span);
435
- i = span.end;
436
- continue;
437
- }
856
+ function citeSpan(value, start) {
857
+ if (!value.startsWith("\\cite{", start) || isEscaped(value, start)) {
858
+ return null;
859
+ }
860
+ const openBrace = start + "\\cite".length;
861
+ if (value[openBrace] !== "{") {
862
+ return null;
863
+ }
864
+ let depth = 0;
865
+ for (let i = openBrace; i < value.length; i += 1) {
866
+ const char = value[i];
867
+ if (char === "{" && !isEscaped(value, i)) {
868
+ depth += 1;
869
+ continue;
438
870
  }
439
- if (value.startsWith("\\(", i)) {
440
- const close = value.indexOf("\\)", i + 2);
441
- if (close >= 0) {
442
- const end = close + 2;
443
- spans.push({ start: i, end, source: value.slice(i, end), opening: "\\(", closing: "\\)", display: false });
444
- i = end;
445
- continue;
871
+ if (char === "}" && !isEscaped(value, i)) {
872
+ depth -= 1;
873
+ if (depth === 0) {
874
+ const end = i + 1;
875
+ const source = value.slice(start, end);
876
+ return { kind: "cite", start, end, source, keys: parseCiteKeys(source) };
446
877
  }
447
878
  }
448
- if (value.startsWith("\\[", i)) {
449
- const close = value.indexOf("\\]", i + 2);
450
- if (close >= 0) {
451
- const end = close + 2;
452
- spans.push({ start: i, end, source: value.slice(i, end), opening: "\\[", closing: "\\]", display: true });
453
- i = end;
454
- continue;
455
- }
879
+ }
880
+ return null;
881
+ }
882
+ function refSpan(value, start) {
883
+ const eqrefPrefix = "\\eqref{";
884
+ const refPrefix = "\\ref{";
885
+ let refCommand = "ref";
886
+ let prefix = refPrefix;
887
+ if (value.startsWith(eqrefPrefix, start) && !isEscaped(value, start)) {
888
+ refCommand = "eqref";
889
+ prefix = eqrefPrefix;
890
+ } else if (value.startsWith(refPrefix, start) && !isEscaped(value, start)) {
891
+ refCommand = "ref";
892
+ prefix = refPrefix;
893
+ } else {
894
+ return null;
895
+ }
896
+ const openBrace = start + prefix.length - 1;
897
+ if (value[openBrace] !== "{") {
898
+ return null;
899
+ }
900
+ let depth = 0;
901
+ for (let i = openBrace; i < value.length; i += 1) {
902
+ const char = value[i];
903
+ if (char === "{" && !isEscaped(value, i)) {
904
+ depth += 1;
905
+ continue;
456
906
  }
457
- if (value.startsWith("$$", i) && !isEscaped(value, i)) {
458
- const close = value.indexOf("$$", i + 2);
459
- if (close >= 0) {
460
- const end = close + 2;
461
- spans.push({ start: i, end, source: value.slice(i, end), opening: "$$", closing: "$$", display: true });
462
- i = end;
463
- continue;
907
+ if (char === "}" && !isEscaped(value, i)) {
908
+ depth -= 1;
909
+ if (depth === 0) {
910
+ const end = i + 1;
911
+ const source = value.slice(start, end);
912
+ const parsed = parseRefKeys(source);
913
+ return { kind: "ref", start, end, source, keys: parsed.keys, refCommand };
464
914
  }
465
915
  }
466
- if (value[i] === "$" && !isEscaped(value, i)) {
467
- const close = findClosingDollar(value, i + 1);
468
- if (close >= 0) {
469
- const end = close + 1;
470
- spans.push({ start: i, end, source: value.slice(i, end), opening: "$", closing: "$", display: false });
471
- i = end;
472
- continue;
473
- }
916
+ }
917
+ return null;
918
+ }
919
+ function mathSpanAt(value, i) {
920
+ if (value.startsWith("\\begin{", i)) {
921
+ return environmentSpan(value, i);
922
+ }
923
+ if (value.startsWith("\\(", i)) {
924
+ const close = value.indexOf("\\)", i + 2);
925
+ if (close >= 0) {
926
+ const end = close + 2;
927
+ return { start: i, end, source: value.slice(i, end), opening: "\\(", closing: "\\)", display: false };
928
+ }
929
+ }
930
+ if (value.startsWith("\\[", i)) {
931
+ const close = value.indexOf("\\]", i + 2);
932
+ if (close >= 0) {
933
+ const end = close + 2;
934
+ return { start: i, end, source: value.slice(i, end), opening: "\\[", closing: "\\]", display: true };
935
+ }
936
+ }
937
+ if (value.startsWith("$$", i) && !isEscaped(value, i)) {
938
+ const close = value.indexOf("$$", i + 2);
939
+ if (close >= 0) {
940
+ const end = close + 2;
941
+ return { start: i, end, source: value.slice(i, end), opening: "$$", closing: "$$", display: true };
942
+ }
943
+ }
944
+ if (value[i] === "$" && !isEscaped(value, i)) {
945
+ const close = findClosingDollar(value, i + 1);
946
+ if (close >= 0) {
947
+ const end = close + 1;
948
+ return { start: i, end, source: value.slice(i, end), opening: "$", closing: "$", display: false };
949
+ }
950
+ }
951
+ return null;
952
+ }
953
+ function detectMathSpans2(value) {
954
+ return detectInlineSpans2(value).filter((span) => span.kind === "math").map(({ kind: _kind, ...span }) => span);
955
+ }
956
+ function detectInlineSpans2(value) {
957
+ const spans = [];
958
+ let i = 0;
959
+ while (i < value.length) {
960
+ const cite = citeSpan(value, i);
961
+ if (cite) {
962
+ spans.push(cite);
963
+ i = cite.end;
964
+ continue;
965
+ }
966
+ const ref = refSpan(value, i);
967
+ if (ref) {
968
+ spans.push(ref);
969
+ i = ref.end;
970
+ continue;
971
+ }
972
+ const math = mathSpanAt(value, i);
973
+ if (math) {
974
+ spans.push({ kind: "math", ...math });
975
+ i = math.end;
976
+ continue;
474
977
  }
475
978
  i += 1;
476
979
  }
@@ -507,19 +1010,63 @@ function pushDiagnostic(diagnostics, options, path, message) {
507
1010
  }
508
1011
  diagnostics.push({ code: "math_alignment", message, path });
509
1012
  }
1013
+ function parseReferences(json) {
1014
+ if (!Array.isArray(json)) {
1015
+ return [];
1016
+ }
1017
+ const references = [];
1018
+ for (const entry of json) {
1019
+ if (!isObject2(entry) || typeof entry.key !== "string" || entry.key.trim().length === 0) {
1020
+ continue;
1021
+ }
1022
+ references.push(
1023
+ referenceFromJson({
1024
+ key: entry.key.trim(),
1025
+ authors: typeof entry.authors === "string" ? entry.authors : void 0,
1026
+ title: typeof entry.title === "string" ? entry.title : void 0,
1027
+ year: typeof entry.year === "string" ? entry.year : void 0,
1028
+ url: typeof entry.url === "string" ? entry.url : void 0,
1029
+ venue: typeof entry.venue === "string" ? entry.venue : void 0
1030
+ })
1031
+ );
1032
+ }
1033
+ return references;
1034
+ }
510
1035
  function createInlineField2(value = "", mathObjects = [], options = {}, path = "$", diagnostics = []) {
511
1036
  const mode = options.mode ?? "english";
512
- const spans = detectMathSpans2(value);
1037
+ const spans = detectInlineSpans2(value);
1038
+ const mathSpans = spans.filter((span) => span.kind === "math");
513
1039
  const tokens = [];
514
1040
  let index = 0;
515
- if (mathObjects.length > 0 && mathObjects.length !== spans.length) {
516
- pushDiagnostic(diagnostics, options, path, `math_objects count mismatch: detected ${String(spans.length)}, got ${String(mathObjects.length)}`);
1041
+ let mathObjectIndex = 0;
1042
+ if (mathObjects.length > 0 && mathObjects.length !== mathSpans.length) {
1043
+ pushDiagnostic(diagnostics, options, path, `math_objects count mismatch: detected ${String(mathSpans.length)}, got ${String(mathObjects.length)}`);
517
1044
  }
518
- spans.forEach((span, spanIndex) => {
1045
+ for (const span of spans) {
519
1046
  if (span.start > index) {
520
1047
  tokens.push({ id: document2Id("text"), kind: "text", text: value.slice(index, span.start) });
521
1048
  }
522
- const mathJson = mathObjects[spanIndex];
1049
+ if (span.kind === "cite") {
1050
+ tokens.push({
1051
+ id: document2Id("cite"),
1052
+ kind: "cite",
1053
+ keys: span.keys.length > 0 ? span.keys : []
1054
+ });
1055
+ index = span.end;
1056
+ continue;
1057
+ }
1058
+ if (span.kind === "ref") {
1059
+ tokens.push({
1060
+ id: document2Id("ref"),
1061
+ kind: "ref",
1062
+ keys: span.keys.length > 0 ? span.keys : [],
1063
+ refCommand: span.refCommand
1064
+ });
1065
+ index = span.end;
1066
+ continue;
1067
+ }
1068
+ const mathJson = mathObjects[mathObjectIndex];
1069
+ mathObjectIndex += 1;
523
1070
  if (mathJson && (mathJson.math_mode !== span.opening || mathJson.closing !== span.closing)) {
524
1071
  pushDiagnostic(diagnostics, options, path, "math_objects order mismatch");
525
1072
  }
@@ -551,7 +1098,7 @@ function createInlineField2(value = "", mathObjects = [], options = {}, path = "
551
1098
  });
552
1099
  }
553
1100
  index = span.end;
554
- });
1101
+ }
555
1102
  if (index < value.length || tokens.length === 0) {
556
1103
  tokens.push({ id: document2Id("text"), kind: "text", text: value.slice(index) });
557
1104
  }
@@ -566,7 +1113,8 @@ function parseTextBlock(json, options, path, diagnostics) {
566
1113
  id: document2Id("block"),
567
1114
  kind: "textBlock",
568
1115
  command: json.command,
569
- field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics)
1116
+ field: createInlineField2(value, json.math_objects ?? [], options, `${path}.value`, diagnostics),
1117
+ ...json.centered === true ? { centered: true } : {}
570
1118
  };
571
1119
  }
572
1120
  function parseListItem(json, options, path, diagnostics) {
@@ -619,16 +1167,21 @@ function parseTableBlock(json, options, path, diagnostics) {
619
1167
  command: "\\begin{tabular}",
620
1168
  closing: "\\end{tabular}",
621
1169
  columns: typeof json.columns === "string" ? json.columns : "",
622
- rows
1170
+ rows,
1171
+ ...parseFloatMetaFromJson(json)
623
1172
  };
624
1173
  }
625
1174
  function parseImageBlock(json) {
1175
+ const assetId = typeof json.asset_id === "string" && json.asset_id.length > 0 ? json.asset_id : void 0;
1176
+ const value = assetId !== void 0 ? typeof json.value === "string" ? json.value : "" : requireString(json.value, "\\includegraphics requires string value");
626
1177
  return {
627
1178
  id: document2Id("block"),
628
1179
  kind: "image",
629
1180
  command: "\\includegraphics",
630
- value: requireString(json.value, "\\includegraphics requires string value"),
631
- options: isRecordOfStrings(json.options) ? json.options : {}
1181
+ value,
1182
+ ...assetId !== void 0 ? { assetId } : {},
1183
+ options: isRecordOfStrings(json.options) ? json.options : {},
1184
+ ...parseFloatMetaFromJson(json)
632
1185
  };
633
1186
  }
634
1187
  function parseRawBlock(json) {
@@ -639,6 +1192,14 @@ function parseRawBlock(json) {
639
1192
  value: typeof json.value === "string" ? json.value : ""
640
1193
  };
641
1194
  }
1195
+ function parseBibliographyBlock() {
1196
+ return {
1197
+ id: document2Id("block"),
1198
+ kind: "bibliography",
1199
+ command: "\\begin{thebibliography}",
1200
+ closing: "\\end{thebibliography}"
1201
+ };
1202
+ }
642
1203
  function parseBlock(json, options, path, diagnostics) {
643
1204
  if (TEXT_COMMANDS.has(json.command)) {
644
1205
  return parseTextBlock(json, options, path, diagnostics);
@@ -652,6 +1213,9 @@ function parseBlock(json, options, path, diagnostics) {
652
1213
  if (json.command === "\\includegraphics") {
653
1214
  return parseImageBlock(json);
654
1215
  }
1216
+ if (json.command === "\\begin{thebibliography}" || json.command === "\\bibliography") {
1217
+ return parseBibliographyBlock();
1218
+ }
655
1219
  if (json.command === "\\raw") {
656
1220
  return parseRawBlock(json);
657
1221
  }
@@ -672,12 +1236,20 @@ function fromDocumentJson2(json, options = {}) {
672
1236
  const diagnostics = [];
673
1237
  return {
674
1238
  nodeType: "DocumentObject",
1239
+ meta: normalizeDocument2Meta(json.meta),
1240
+ references: parseReferences(json.references),
675
1241
  blocks: json.blocks.map((block, index) => parseBlock(asBlockJson(block), options, `$.blocks[${String(index)}]`, diagnostics)),
676
1242
  diagnostics
677
1243
  };
678
1244
  }
679
1245
  function createEmptyDocument2() {
680
- return { nodeType: "DocumentObject", blocks: [], diagnostics: [] };
1246
+ return {
1247
+ nodeType: "DocumentObject",
1248
+ meta: emptyDocument2Meta(),
1249
+ references: [],
1250
+ blocks: [],
1251
+ diagnostics: []
1252
+ };
681
1253
  }
682
1254
 
683
1255
  // src/editor/atomicCommands.ts
@@ -1700,34 +2272,6 @@ function renderDivideOperatorLatex(side) {
1700
2272
  return side === "arabic" ? "\\backslash" : DIVIDE_OPERATOR_EN;
1701
2273
  }
1702
2274
 
1703
- // src/editor/digits.ts
1704
- var WESTERN = "0123456789";
1705
- var ARABIC_INDIC = "\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669";
1706
- var PERSIAN_INDIC = "\u06F0\u06F1\u06F2\u06F3\u06F4\u06F5\u06F6\u06F7\u06F8\u06F9";
1707
- var digitSets = {
1708
- western: WESTERN,
1709
- arabicIndic: ARABIC_INDIC,
1710
- persianIndic: PERSIAN_INDIC
1711
- };
1712
- function digitValue(char) {
1713
- const western = WESTERN.indexOf(char);
1714
- if (western >= 0) {
1715
- return western;
1716
- }
1717
- const arabicIndic = ARABIC_INDIC.indexOf(char);
1718
- if (arabicIndic >= 0) {
1719
- return arabicIndic;
1720
- }
1721
- return PERSIAN_INDIC.indexOf(char);
1722
- }
1723
- function formatDigits(value, digitForm = "western") {
1724
- const target = digitSets[digitForm];
1725
- return Array.from(value, (char) => {
1726
- const value2 = digitValue(char);
1727
- return value2 >= 0 ? target[value2] : char;
1728
- }).join("");
1729
- }
1730
-
1731
2275
  // src/editor/render.ts
1732
2276
  function selectedDigitForm(options) {
1733
2277
  return options?.digitForm ?? "western";
@@ -3060,6 +3604,8 @@ function cloneBlock(block) {
3060
3604
  function cloneDocument(document2) {
3061
3605
  return {
3062
3606
  nodeType: "DocumentObject",
3607
+ meta: cloneDocument2Meta(document2.meta ?? emptyDocument2Meta()),
3608
+ references: document2.references.map((reference) => ({ ...reference })),
3063
3609
  blocks: document2.blocks.map(cloneBlock),
3064
3610
  diagnostics: document2.diagnostics.map((diagnostic) => ({ ...diagnostic }))
3065
3611
  };
@@ -3169,6 +3715,29 @@ function moveDocument2BlockById(document2, blockId, direction) {
3169
3715
  next.blocks.splice(targetIndex, 0, block);
3170
3716
  return next;
3171
3717
  }
3718
+ function moveDocument2BlockRange(document2, from, to, direction) {
3719
+ const count = document2.blocks.length;
3720
+ if (from < 0 || to < 0 || from >= count || to >= count || from > to) {
3721
+ return document2;
3722
+ }
3723
+ const insertAt = from + direction;
3724
+ if (insertAt < 0 || to + direction >= count) {
3725
+ return document2;
3726
+ }
3727
+ const next = cloneDocument(document2);
3728
+ const slice = next.blocks.splice(from, to - from + 1);
3729
+ next.blocks.splice(insertAt, 0, ...slice);
3730
+ return next;
3731
+ }
3732
+ function removeDocument2BlockRange(document2, from, to) {
3733
+ const count = document2.blocks.length;
3734
+ if (from < 0 || to < 0 || from >= count || to >= count || from > to) {
3735
+ return document2;
3736
+ }
3737
+ const next = cloneDocument(document2);
3738
+ next.blocks = [...next.blocks.slice(0, from), ...next.blocks.slice(to + 1)];
3739
+ return next;
3740
+ }
3172
3741
  function normalizeFieldTokens(tokens) {
3173
3742
  if (tokens.length === 0) {
3174
3743
  return [{ id: document2Id("text"), kind: "text", text: "" }];
@@ -3263,16 +3832,50 @@ function replaceMathTokenFromSession(document2, tokenId, session, opening, closi
3263
3832
  const current = field.tokens[index];
3264
3833
  const open = opening ?? current.opening;
3265
3834
  const close = closing ?? current.closing;
3266
- field.tokens[index] = mathTokenFromSession(session, open, close, side);
3267
- field.tokens[index].id = current.id;
3268
- return true;
3835
+ const replaced = mathTokenFromSession(session, open, close, side);
3836
+ replaced.id = current.id;
3837
+ if (current.labelEnabled !== void 0) {
3838
+ replaced.labelEnabled = current.labelEnabled;
3839
+ }
3840
+ if (current.label !== void 0) {
3841
+ replaced.label = current.label;
3842
+ }
3843
+ field.tokens[index] = replaced;
3844
+ return true;
3269
3845
  });
3270
3846
  return next;
3271
3847
  }
3272
3848
  function addDocument2TextBlock(document2, command = "\\paragraph", afterBlockId) {
3273
- const block = { id: document2Id("block"), kind: "textBlock", command, field: createInlineField2("") };
3849
+ const block = {
3850
+ id: document2Id("block"),
3851
+ kind: "textBlock",
3852
+ command,
3853
+ field: createInlineField2(""),
3854
+ ...command === "\\paragraph" ? { centered: false } : {}
3855
+ };
3274
3856
  return insertDocument2BlockAfter(document2, afterBlockId, block);
3275
3857
  }
3858
+ function updateDocument2TextBlockCentered(document2, blockId, centered) {
3859
+ const next = cloneDocument(document2);
3860
+ function visit(blocks) {
3861
+ for (const block of blocks) {
3862
+ if (block.id === blockId && block.kind === "textBlock" && block.command === "\\paragraph") {
3863
+ block.centered = centered;
3864
+ return true;
3865
+ }
3866
+ if (block.kind === "list") {
3867
+ for (const item of block.items) {
3868
+ if (visit(item.blocks)) {
3869
+ return true;
3870
+ }
3871
+ }
3872
+ }
3873
+ }
3874
+ return false;
3875
+ }
3876
+ visit(next.blocks);
3877
+ return next;
3878
+ }
3276
3879
  function removeDocument2BlockById(document2, blockId) {
3277
3880
  const next = cloneDocument(document2);
3278
3881
  next.blocks = next.blocks.filter((block) => block.id !== blockId);
@@ -3309,7 +3912,8 @@ function addDocument2TableBlock(document2, columns = "lll", rowCount = 3, colCou
3309
3912
  command: "\\begin{tabular}",
3310
3913
  closing: "\\end{tabular}",
3311
3914
  columns: columns || "l".repeat(cols),
3312
- rows: tableRows
3915
+ rows: tableRows,
3916
+ ...defaultFloatMeta()
3313
3917
  };
3314
3918
  return insertDocument2BlockAfter(document2, afterBlockId, block);
3315
3919
  }
@@ -3319,7 +3923,8 @@ function addDocument2ImageBlock(document2, src = "", afterBlockId) {
3319
3923
  kind: "image",
3320
3924
  command: "\\includegraphics",
3321
3925
  value: src,
3322
- options: {}
3926
+ options: { width: "0.8\\textwidth" },
3927
+ ...defaultFloatMeta()
3323
3928
  };
3324
3929
  return insertDocument2BlockAfter(document2, afterBlockId, block);
3325
3930
  }
@@ -3344,6 +3949,128 @@ function updateDocument2ImageValue(document2, blockId, value) {
3344
3949
  visit(next.blocks);
3345
3950
  return next;
3346
3951
  }
3952
+ function updateDocument2ImageMeta(document2, blockId, patch) {
3953
+ const next = cloneDocument(document2);
3954
+ function visit(blocks) {
3955
+ for (const block of blocks) {
3956
+ if (block.id === blockId && block.kind === "image") {
3957
+ applyFloatMetaPatch(block, patch);
3958
+ return true;
3959
+ }
3960
+ if (block.kind === "list") {
3961
+ for (const item of block.items) {
3962
+ if (visit(item.blocks)) {
3963
+ return true;
3964
+ }
3965
+ }
3966
+ }
3967
+ }
3968
+ return false;
3969
+ }
3970
+ visit(next.blocks);
3971
+ return next;
3972
+ }
3973
+ function updateDocument2TableMeta(document2, blockId, patch) {
3974
+ const next = cloneDocument(document2);
3975
+ function visit(blocks) {
3976
+ for (const block of blocks) {
3977
+ if (block.id === blockId && block.kind === "table") {
3978
+ applyFloatMetaPatch(block, patch);
3979
+ return true;
3980
+ }
3981
+ if (block.kind === "list") {
3982
+ for (const item of block.items) {
3983
+ if (visit(item.blocks)) {
3984
+ return true;
3985
+ }
3986
+ }
3987
+ }
3988
+ }
3989
+ return false;
3990
+ }
3991
+ visit(next.blocks);
3992
+ return next;
3993
+ }
3994
+ function updateMathTokenLabel(document2, tokenId, patch) {
3995
+ const next = cloneDocument(document2);
3996
+ visitFields(next.blocks, (field) => {
3997
+ const token = field.tokens.find((entry) => entry.id === tokenId && entry.kind === "math");
3998
+ if (!token) {
3999
+ return false;
4000
+ }
4001
+ if (typeof patch.labelEnabled === "boolean") {
4002
+ token.labelEnabled = patch.labelEnabled;
4003
+ }
4004
+ if (typeof patch.label === "string") {
4005
+ token.label = patch.label;
4006
+ }
4007
+ return true;
4008
+ });
4009
+ return next;
4010
+ }
4011
+ function refTokenFromKeys(keys, refCommand) {
4012
+ return { id: document2Id("ref"), kind: "ref", keys: [...keys], refCommand };
4013
+ }
4014
+ function insertRefTokenAtCaret(document2, fieldId, textTokenId, caretOffset, keys, refCommand = "ref") {
4015
+ if (keys.length === 0) {
4016
+ return document2;
4017
+ }
4018
+ const next = cloneDocument(document2);
4019
+ const refToken = refTokenFromKeys(keys, refCommand);
4020
+ visitFields(next.blocks, (field) => {
4021
+ if (field.id !== fieldId) {
4022
+ return false;
4023
+ }
4024
+ const textIndex = textTokenId ? field.tokens.findIndex((token) => token.id === textTokenId && token.kind === "text") : field.tokens.findIndex((token) => token.kind === "text");
4025
+ if (textIndex < 0) {
4026
+ field.tokens.push(refToken);
4027
+ field.tokens.push({ id: document2Id("text"), kind: "text", text: "" });
4028
+ return true;
4029
+ }
4030
+ const current = field.tokens[textIndex];
4031
+ const [before, after] = splitTextTokenAt(current, caretOffset);
4032
+ const parts = [...field.tokens.slice(0, textIndex)];
4033
+ if (before.text.length > 0) {
4034
+ parts.push(before);
4035
+ }
4036
+ parts.push(refToken);
4037
+ parts.push(after);
4038
+ parts.push(...field.tokens.slice(textIndex + 1));
4039
+ field.tokens = normalizeFieldTokens(parts);
4040
+ return true;
4041
+ });
4042
+ return next;
4043
+ }
4044
+ function updateRefTokenKeys(document2, tokenId, keys, refCommand) {
4045
+ if (keys.length === 0) {
4046
+ return document2;
4047
+ }
4048
+ const next = cloneDocument(document2);
4049
+ visitFields(next.blocks, (field) => {
4050
+ const token = field.tokens.find((entry) => entry.id === tokenId && entry.kind === "ref");
4051
+ if (!token) {
4052
+ return false;
4053
+ }
4054
+ token.keys = [...keys];
4055
+ if (refCommand) {
4056
+ token.refCommand = refCommand;
4057
+ }
4058
+ return true;
4059
+ });
4060
+ return next;
4061
+ }
4062
+ function removeRefTokenById(document2, tokenId) {
4063
+ const next = cloneDocument(document2);
4064
+ visitFields(next.blocks, (field) => {
4065
+ const index = field.tokens.findIndex((token) => token.id === tokenId && token.kind === "ref");
4066
+ if (index < 0) {
4067
+ return false;
4068
+ }
4069
+ field.tokens = normalizeFieldTokens(stitchTextAroundRemovedToken(field.tokens, index));
4070
+ return true;
4071
+ });
4072
+ return next;
4073
+ }
3347
4074
  function mutateListBlockById(blocks, listBlockId, mutator) {
3348
4075
  for (const block of blocks) {
3349
4076
  if (block.id === listBlockId && block.kind === "list") {
@@ -3380,12 +4107,372 @@ function removeDocument2ListItem(document2, listBlockId, itemId) {
3380
4107
  });
3381
4108
  return next;
3382
4109
  }
4110
+ function citeTokenFromKeys(keys) {
4111
+ return { id: document2Id("cite"), kind: "cite", keys: [...keys] };
4112
+ }
4113
+ function insertCiteTokenAtCaret(document2, fieldId, textTokenId, caretOffset, keys) {
4114
+ if (keys.length === 0) {
4115
+ return document2;
4116
+ }
4117
+ const next = cloneDocument(document2);
4118
+ const citeToken = citeTokenFromKeys(keys);
4119
+ visitFields(next.blocks, (field) => {
4120
+ if (field.id !== fieldId) {
4121
+ return false;
4122
+ }
4123
+ const textIndex = textTokenId ? field.tokens.findIndex((token) => token.id === textTokenId && token.kind === "text") : field.tokens.findIndex((token) => token.kind === "text");
4124
+ if (textIndex < 0) {
4125
+ field.tokens.push(citeToken);
4126
+ field.tokens.push({ id: document2Id("text"), kind: "text", text: "" });
4127
+ return true;
4128
+ }
4129
+ const current = field.tokens[textIndex];
4130
+ const [before, after] = splitTextTokenAt(current, caretOffset);
4131
+ const parts = [...field.tokens.slice(0, textIndex)];
4132
+ if (before.text.length > 0) {
4133
+ parts.push(before);
4134
+ }
4135
+ parts.push(citeToken);
4136
+ parts.push(after);
4137
+ parts.push(...field.tokens.slice(textIndex + 1));
4138
+ field.tokens = normalizeFieldTokens(parts);
4139
+ return true;
4140
+ });
4141
+ return next;
4142
+ }
4143
+ function updateCiteTokenKeys(document2, tokenId, keys) {
4144
+ if (keys.length === 0) {
4145
+ return document2;
4146
+ }
4147
+ const next = cloneDocument(document2);
4148
+ visitFields(next.blocks, (field) => {
4149
+ const token = field.tokens.find((entry) => entry.id === tokenId && entry.kind === "cite");
4150
+ if (!token) {
4151
+ return false;
4152
+ }
4153
+ token.keys = [...keys];
4154
+ return true;
4155
+ });
4156
+ return next;
4157
+ }
4158
+ function removeCiteTokenById(document2, tokenId) {
4159
+ const next = cloneDocument(document2);
4160
+ visitFields(next.blocks, (field) => {
4161
+ const index = field.tokens.findIndex((token) => token.id === tokenId && token.kind === "cite");
4162
+ if (index < 0) {
4163
+ return false;
4164
+ }
4165
+ field.tokens = normalizeFieldTokens(stitchTextAroundRemovedToken(field.tokens, index));
4166
+ return true;
4167
+ });
4168
+ return next;
4169
+ }
4170
+ function ensureDocument2BibliographyBlock(document2, afterBlockId) {
4171
+ if (document2.blocks.some((block2) => block2.kind === "bibliography")) {
4172
+ return document2;
4173
+ }
4174
+ const block = {
4175
+ id: document2Id("block"),
4176
+ kind: "bibliography",
4177
+ command: "\\begin{thebibliography}",
4178
+ closing: "\\end{thebibliography}"
4179
+ };
4180
+ return insertDocument2BlockAfter(document2, afterBlockId ?? null, block);
4181
+ }
4182
+ function addDocument2Reference(document2, partial = {}) {
4183
+ const next = cloneDocument(document2);
4184
+ next.references.push(createEmptyReference2(partial));
4185
+ return next;
4186
+ }
4187
+ function updateDocument2Reference(document2, referenceId, patch) {
4188
+ const next = cloneDocument(document2);
4189
+ const reference = next.references.find((entry) => entry.id === referenceId);
4190
+ if (!reference) {
4191
+ return document2;
4192
+ }
4193
+ if (typeof patch.key === "string" && patch.key.trim().length > 0) {
4194
+ reference.key = patch.key.trim();
4195
+ }
4196
+ if (typeof patch.authors === "string") {
4197
+ reference.authors = patch.authors;
4198
+ }
4199
+ if (typeof patch.title === "string") {
4200
+ reference.title = patch.title;
4201
+ }
4202
+ if (typeof patch.year === "string") {
4203
+ reference.year = patch.year;
4204
+ }
4205
+ if (typeof patch.url === "string") {
4206
+ reference.url = patch.url;
4207
+ }
4208
+ if (typeof patch.venue === "string") {
4209
+ reference.venue = patch.venue;
4210
+ }
4211
+ return next;
4212
+ }
4213
+ function removeDocument2Reference(document2, referenceId) {
4214
+ const next = cloneDocument(document2);
4215
+ next.references = next.references.filter((reference) => reference.id !== referenceId);
4216
+ return next;
4217
+ }
4218
+ function moveDocument2Reference(document2, referenceId, direction) {
4219
+ const next = cloneDocument(document2);
4220
+ const index = next.references.findIndex((reference2) => reference2.id === referenceId);
4221
+ const targetIndex = index + direction;
4222
+ if (index < 0 || targetIndex < 0 || targetIndex >= next.references.length) {
4223
+ return document2;
4224
+ }
4225
+ const [reference] = next.references.splice(index, 1);
4226
+ if (!reference) {
4227
+ return document2;
4228
+ }
4229
+ next.references.splice(targetIndex, 0, reference);
4230
+ return next;
4231
+ }
4232
+ function setDocument2References(document2, references) {
4233
+ const next = cloneDocument(document2);
4234
+ next.references = references.map((reference) => ({ ...reference }));
4235
+ return next;
4236
+ }
4237
+ function updateDocument2Meta(document2, patch) {
4238
+ const next = cloneDocument(document2);
4239
+ const current = next.meta ?? emptyDocument2Meta();
4240
+ next.meta = {
4241
+ title: typeof patch.title === "string" ? patch.title : current.title,
4242
+ authors: typeof patch.authors === "string" ? patch.authors : current.authors,
4243
+ abstract: typeof patch.abstract === "string" ? patch.abstract : current.abstract,
4244
+ date: patch.date ? normalizeDocument2HijriDate({ ...current.date, ...patch.date }) : { ...current.date }
4245
+ };
4246
+ return next;
4247
+ }
4248
+
4249
+ // src/document2/arabicPreamble.ts
4250
+ function arabicXeLatexPreamblePkg(twocolumn = false) {
4251
+ const classOptions = twocolumn ? "12pt,a4paper,twocolumn" : "12pt,a4paper";
4252
+ return `
4253
+ \\documentclass[${classOptions}]{article}
4254
+ ` + String.raw`\usepackage{amsmath,amsfonts,amssymb,mathrsfs,tikz,fancyhdr, mathtools}
4255
+ \usepackage{fontspec} % For loading OpenType fonts
4256
+ \usepackage{unicode-math} % For setting the math font
4257
+ \usepackage{polyglossia} % For Arabic support
4258
+ \usepackage{array}
4259
+ \usepackage{cancel}
4260
+ \usepackage{bidi} % For bidirectional text handling
4261
+ \usepackage{multirow}
4262
+ \usepackage{booktabs}
4263
+ \usepackage{graphicx} % For \reflectbox
4264
+ \usepackage{xcolor}
4265
+ \usepackage{tikz}
4266
+ \usepackage{tcolorbox} % For tcolorbox environment
4267
+ \usepackage{textcomp} % For \textrightarrow command
4268
+
4269
+
4270
+ % visit : https://www.symbolcopy.com/punctuation-symbol.html
4271
+ % for inversed punctuation
4272
+
4273
+ % save inverted comma for use - copy paste -> ،
4274
+ % save back tick for use - copy paste -> ` + "`";
4275
+ }
4276
+ function arabicXeLatexPreambleFont(digitsMapping = "arabicdigits") {
4277
+ return `
4278
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4279
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4280
+ % Toggle between eastern and western digits by changing the Mapping in the below fonts (inside math font as well) between "arabicdigits" and "digits"
4281
+ \\setdefaultlanguage[calendar=gregorian]{arabic} % from polyglossia
4282
+ \\setmainfont[Script=Arabic , Mapping=${digitsMapping}]{Amiri}
4283
+ \\newfontfamily\\diwani[Script=Arabic,Mapping=${digitsMapping}]{Diwani Letter}
4284
+ \\newfontfamily\\diwanioutlineshaded[Script=Arabic,Mapping=${digitsMapping}]{Diwani Outline Shaded}
4285
+ \\newfontfamily\\takween[Script=Arabic,Mapping=${digitsMapping}]{Takween}
4286
+ \\newfontfamily\\boldarabic[Script=Arabic,Mapping=${digitsMapping}]{Amiri Bold}
4287
+ \\newfontfamily\\italicarabic[Script=Arabic,Mapping=${digitsMapping}]{Amiri Italic}
4288
+
4289
+ % Explicitly set math font to XITS Math
4290
+ % Remove "Script=Arabic" to cancel reflected symbols and other RTL symbols
4291
+ \\setmathfont[Script=Arabic , Mapping=${digitsMapping}]{XITS Math} % Ensure XITS Math is correctly installed and available
4292
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4293
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4294
+ `;
4295
+ }
4296
+ function arabicXeLatexPreambleCmd() {
4297
+ return String.raw`
4298
+ % Run with XeLaTeX compiler
4299
+ \newcommand{\butextakween}[1]{\text{\takween{#1}}}
4300
+ \newcommand{\butexdiwani}[1]{\text{\diwani{#1}}}
4301
+ \newcommand{\butexdiwanioutline}[1]{\text{\diwanioutlineshaded{#1}}}
4302
+
4303
+ \newcommand{\arabN}{\text{\diwanioutlineshaded{ط}}}
4304
+ \newcommand{\arabZ}{\text{\diwanioutlineshaded{ص}}}
4305
+ \newcommand{\arabQ}{\text{\diwanioutlineshaded{ن}}}
4306
+ \newcommand{\arabR}{\text{\diwanioutlineshaded{ح}}}
4307
+ \newcommand{\arabC}{\text{\diwanioutlineshaded{ع}}}
4308
+ \newcommand{\arabH}{\text{\diwanioutlineshaded{ر}}}
4309
+
4310
+
4311
+ \newcommand{\lowerscript}[1]{\raisebox{-4pt}{\scriptsize #1}}
4312
+ \newcommand{\llowerscript}[1]{\raisebox{-8pt}{\scriptsize #1}}
4313
+ \newcommand{\lllowerscript}[2]{\raisebox{#2pt}{\scriptsize #1}}
4314
+
4315
+ \newcommand{\arabdsub}[3]{\prescript{}{#1}{\prescript{}{#2}{#3}}} % arabic double subscript
4316
+ \newcommand{\arabsub}[2]{\prescript{}{#1}{#2}} % arabic single subscript
4317
+
4318
+
4319
+
4320
+ \newcommand{\upperscript}[1]{\raisebox{8pt}{\scriptsize #1}}
4321
+ \newcommand{\uupperscript}[2]{\raisebox{#2pt}{\scriptsize #1}}
4322
+ \newcommand{\vertbar}{\rule[-1ex]{0.5pt}{2.5ex}}
4323
+ \newcommand{\horzbar}{\rule[.5ex]{2.5ex}{0.5pt}}
4324
+
4325
+ \newcommand{\arabsqrt}[2]{\reflectbox{\(\sqrt[\reflectbox{\(#1\)}]{\reflectbox{\(#2\)}}\)}}
4326
+ \newcommand{\arabvec}[1]{\reflectbox{$\vec{\reflectbox{$#1$}}$}}
4327
+
4328
+ \newcommand{\arabexp}[1]{{}^{#1}\!\raisebox{-4.5pt}{\text{\diwani{ه}}}}
4329
+ \newcommand{\arablog}[2]{\left(\text{#2}\right)\!\prescript{}{\text{#1}}{\text{\diwani{لو}}}}
4330
+ \newcommand{\arabnlog}[1]{\left(\text{#1}\right)\!\prescript{}{\text{\diwani{ه}}}{\text{\diwani{لو}}}}
4331
+
4332
+ \newcommand{\arabcos}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{جتا}}}}
4333
+ \newcommand{\arabsin}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{جا}}}}
4334
+ \newcommand{\arabtan}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{ظا}}}}
4335
+ \newcommand{\arabcot}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{ظتا}}}}
4336
+ \newcommand{\arabsec}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قا}}}}
4337
+ \newcommand{\arabcsc}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قتا}}}}
4338
+
4339
+ \newcommand{\arabacos}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قجتا}}}}
4340
+ \newcommand{\arabasin}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قجا}}}}
4341
+ \newcommand{\arabatan}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قظا}}}}
4342
+ \newcommand{\arabacot}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قظتا}}}}
4343
+ \newcommand{\arabasec}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{ققا}}}}
4344
+ \newcommand{\arabacsc}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{ققتا}}}}
4345
+
4346
+
4347
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4348
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4349
+ % summation
4350
+ \newcommand{\arablim}[2]{\underset{#2 \leftarrow #1}{\text{نـــــها}}}
4351
+ \newcommand{\arabsum}[2]{\underset{#1}{\overset{#2}{\text{مجـــ}}}}
4352
+ \newcommand{\arabprod}[2]{\underset{#1}{\overset{#2}{\text{جـــذ}}}}
4353
+ \newcommand{\arabint}[2]{\prescript{#2}{#1\!\!\!}\int}
4354
+
4355
+
4356
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4357
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4358
+ % we define this command to make it ease for change of notation later
4359
+ \newcommand{\ad}[0]{\text{ء}} % "ad" for arabic differentiation or derivative (ء" لإشتقاق")
4360
+ \newcommand{\arpi}[0]{\!\text{\diwani{ط}}}
4361
+
4362
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4363
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4364
+ % differentials
4365
+
4366
+ \newcommand{\arabdiff}[2]{\frac{#1\ad}{#2\ad}} % arabic differential
4367
+ \newcommand{\arabddiff}[2]{\frac{#1{}^{2}\ad}{{}^{2}#2\ad}} % arabic second differential
4368
+
4369
+ \newcommand{\arabode}[2][-5pt]{\stackrel{\raisebox{#1}{$\cdot$}}{\text{#2}}}
4370
+ \newcommand{\arabodde}[2][-5pt]{\stackrel{\raisebox{#1}{$\vcenter{\hbox{$\cdot\!\cdot$}}$}}{\text{#2}}}
4371
+ \newcommand{\araboddde}[2][-5pt]{\stackrel{\raisebox{#1}{$\vcenter{\hbox{$\cdot\!\cdot\!\cdot$}}$}}{\text{#2}}}
4372
+ \newcommand{\arabpde}[1]{\prescript{}{#1\!\!}{\nabla}} % arabic partial differential equation (PDE)
4373
+
4374
+ \newcommand{\arabprime}[0]{\reflectbox{$\prime$}\!} % arabic prime notation
4375
+ \newcommand{\arabpprime}[0]{\reflectbox{$\prime$}\reflectbox{$\prime$}\!} % arabic prime notation
4376
+ \newcommand{\arabppprime}[0]{\reflectbox{$\prime$}\reflectbox{$\prime$}\reflectbox{$\prime$}\!} % arabic prime notation
4377
+
4378
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4379
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4380
+ % probability
4381
+ \newcommand{\ap}[0]{\!\text{\diwani{حـ}}} % arabic Probability - used a lot so short form
4382
+ \newcommand{\arabExpct}[0]{\text{\diwani{توقـ}}} % arabic Expectation
4383
+ \newcommand{\arabVar}[0]{\!\text{\diwani{با}}} % arabic Variance
4384
+ \newcommand{\arabCov}[0]{\!\text{\diwani{ت}}} % arabic Covariance
4385
+
4386
+
4387
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4388
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4389
+ % custom commands specific to lesson
4390
+ \newcommand{\lagrange}[2]{\left(#2\right)\!\prescript{}{#1}{\text{\diwani{لا}}}}
4391
+ \newcommand{\xii}[0]{\left(\prescript{}{\text{يـ}}{\text{س}}\right)\!}
4392
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4393
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4394
+
4395
+
4396
+ \newcommand{\arsqrt}[2][]{\reflectbox{\(\sqrt[\reflectbox{\(#1\)}]{\reflectbox{\(#2\)}}\)}}
4397
+ \newcommand{\arexp}[0]{\!\raisebox{-4.5pt}{\text{\diwani{ه}}}}
4398
+ \newcommand{\arlog}[0]{\!\!\text{\diwani{لو}}}
4399
+ \newcommand{\arln}[0]{\!\!\prescript{}{\text{\diwani{ه}}}{\text{\diwani{لو}}}}
4400
+ \newcommand{\ardet}[0]{\!\!\text{\diwani{محدد}}}
4401
+
4402
+ \newcommand{\arsum}[0]{\text{مجـــ}}
4403
+ \newcommand{\arprod}[0]{\text{جـــذ}}
4404
+
4405
+ \newcommand{\arlim}[0]{\text{نـــــها}}
4406
+ \newcommand{\armax}[0]{\text{أكبر}}
4407
+ \newcommand{\armin}[0]{\text{أصغر}}
4408
+ \newcommand{\arsup}[0]{\text{أعلى}}
4409
+ \newcommand{\arinf}[0]{\text{أدنى}}
4410
+
4411
+ \newcommand{\arsin}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{جا}}}}
4412
+ \newcommand{\arcos}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{جتا}}}}
4413
+ \newcommand{\artan}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ظا}}}}
4414
+ \newcommand{\arcot}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ظتا}}}}
4415
+ \newcommand{\arsec}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قا}}}}
4416
+ \newcommand{\arcsc}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قتا}}}}
4417
+
4418
+ \newcommand{\arasin}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قجا}}}}
4419
+ \newcommand{\aracos}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قجتا}}}}
4420
+ \newcommand{\aratan}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قظا}}}}
4421
+ \newcommand{\aracot}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قظتا}}}}
4422
+ \newcommand{\arasec}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ققا}}}}
4423
+ \newcommand{\aracsc}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ققتا}}}}
4424
+
4425
+ \newcommand{\arsinh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{جزا}}}}
4426
+ \newcommand{\arcosh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{جتزا}}}}
4427
+ \newcommand{\artanh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ظزا}}}}
4428
+ \newcommand{\arcoth}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ظتزا}}}}
4429
+ \newcommand{\arsech}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قزا}}}}
4430
+ \newcommand{\arcsch}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قتزا}}}}
4431
+
4432
+ \newcommand{\arasinh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قجزا}}}}
4433
+ \newcommand{\aracosh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قجتزا}}}}
4434
+ \newcommand{\aratanh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قظزا}}}}
4435
+ \newcommand{\aracoth}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قظتزا}}}}
4436
+ \newcommand{\arasech}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ققزا}}}}
4437
+ \newcommand{\aracsch}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ققتزا}}}}
4438
+
4439
+ \newcommand{\unit}[1]{\text{#1}}
4440
+ \newcommand{\idx}[1]{#1}
4441
+ \newcommand{\arbinom}[2]{\left(\begin{array}{c} #1 \\ #2 \end{array} \right)}
4442
+ `;
4443
+ }
4444
+ function getArabicXeLatexPreamble(digitsMappingOrOptions = "arabicdigits") {
4445
+ const options = typeof digitsMappingOrOptions === "string" ? { digitsMapping: digitsMappingOrOptions } : digitsMappingOrOptions;
4446
+ const digitsMapping = options.digitsMapping ?? "arabicdigits";
4447
+ const twocolumn = options.twocolumn === true;
4448
+ return arabicXeLatexPreamblePkg(twocolumn) + arabicXeLatexPreambleFont(digitsMapping) + arabicXeLatexPreambleCmd();
4449
+ }
3383
4450
 
3384
4451
  // src/document2/exportLatex.ts
4452
+ function mathBodyLatex(token) {
4453
+ if (!token.math || token.sourceOwner === "raw" || token.sourceOwner === "editor") {
4454
+ return stripDisplayMathDelimiters(token.source);
4455
+ }
4456
+ const rendered = renderMathNodeLatex(token.math);
4457
+ return stripDisplayMathDelimiters(rendered);
4458
+ }
3385
4459
  function tokenLatex(token) {
3386
4460
  if (token.kind === "text") {
3387
4461
  return token.text;
3388
4462
  }
4463
+ if (token.kind === "cite") {
4464
+ return citeTokenLatex(token.keys);
4465
+ }
4466
+ if (token.kind === "ref") {
4467
+ return refTokenLatex(token.keys, token.refCommand);
4468
+ }
4469
+ if (token.display && token.labelEnabled && token.label && token.label.trim().length > 0) {
4470
+ const body = mathBodyLatex(token);
4471
+ return `\\begin{equation}
4472
+ ${body}
4473
+ \\label{${token.label.trim()}}
4474
+ \\end{equation}`;
4475
+ }
3389
4476
  if (!token.math || token.sourceOwner === "raw" || token.sourceOwner === "editor") {
3390
4477
  return token.source;
3391
4478
  }
@@ -3395,26 +4482,52 @@ function inlineFieldLatex(field) {
3395
4482
  return field.tokens.map((token) => tokenLatex(token)).join("");
3396
4483
  }
3397
4484
  function textBlockLatex(block) {
3398
- return `${block.command}{${inlineFieldLatex(block.field)}}`;
4485
+ const body = `${block.command}{${inlineFieldLatex(block.field)}}`;
4486
+ if (block.command === "\\paragraph" && block.centered) {
4487
+ return `\\begin{center}
4488
+ ${body}
4489
+ \\end{center}`;
4490
+ }
4491
+ return body;
3399
4492
  }
3400
4493
  function indent(value) {
3401
4494
  return value.split("\n").map((line) => ` ${line}`).join("\n");
3402
4495
  }
3403
- function listBlockLatex(block) {
4496
+ function listBlockLatex(block, references) {
3404
4497
  const items = block.items.map((item) => {
3405
- const nested = item.blocks.map((child) => "\n" + indent(blockLatex(child))).join("");
4498
+ const nested = item.blocks.map((child) => "\n" + indent(blockLatex(child, references))).join("");
3406
4499
  return ` \\item ${inlineFieldLatex(item.field)}${nested}`;
3407
4500
  }).join("\n");
3408
4501
  return `${block.command}
3409
4502
  ${items}
3410
4503
  ${block.closing}`;
3411
4504
  }
3412
- function tableBlockLatex(block) {
4505
+ function tabularInnerLatex(block) {
3413
4506
  const rows = block.rows.map((row) => ` ${row.map((cell) => inlineFieldLatex(cell)).join(" & ")}`).join(" \\\\\n");
3414
4507
  return `${block.command}{${block.columns}}
3415
4508
  ${rows}
3416
4509
  ${block.closing}`;
3417
4510
  }
4511
+ function floatCaptionLabelLines(block) {
4512
+ const lines = [];
4513
+ if (block.captionEnabled && block.caption.trim().length > 0) {
4514
+ lines.push(` \\caption{${block.caption.trim()}}`);
4515
+ }
4516
+ if (block.labelEnabled && block.label.trim().length > 0) {
4517
+ lines.push(` \\label{${block.label.trim()}}`);
4518
+ }
4519
+ return lines;
4520
+ }
4521
+ function tableBlockLatex(block) {
4522
+ const lines = ["\\begin{table}[htbp]"];
4523
+ if (block.centered) {
4524
+ lines.push(" \\centering");
4525
+ }
4526
+ lines.push(...floatCaptionLabelLines(block));
4527
+ lines.push(indent(tabularInnerLatex(block)));
4528
+ lines.push("\\end{table}");
4529
+ return lines.join("\n");
4530
+ }
3418
4531
  function imageOptionsLatex(block) {
3419
4532
  const entries = Object.entries(block.options);
3420
4533
  if (entries.length === 0) {
@@ -3422,23 +4535,81 @@ function imageOptionsLatex(block) {
3422
4535
  }
3423
4536
  return `[${entries.map(([key, value]) => `${key}=${value}`).join(",")}]`;
3424
4537
  }
3425
- function blockLatex(block) {
4538
+ function imageBlockLatex(block) {
4539
+ const lines = ["\\begin{figure}[htbp]"];
4540
+ if (block.centered) {
4541
+ lines.push(" \\centering");
4542
+ }
4543
+ lines.push(` ${block.command}${imageOptionsLatex(block)}{${block.value}}`);
4544
+ lines.push(...floatCaptionLabelLines(block));
4545
+ lines.push("\\end{figure}");
4546
+ return lines.join("\n");
4547
+ }
4548
+ function blockLatex(block, references) {
3426
4549
  if (block.kind === "textBlock") {
3427
4550
  return textBlockLatex(block);
3428
4551
  }
3429
4552
  if (block.kind === "list") {
3430
- return listBlockLatex(block);
4553
+ return listBlockLatex(block, references);
3431
4554
  }
3432
4555
  if (block.kind === "table") {
3433
4556
  return tableBlockLatex(block);
3434
4557
  }
3435
4558
  if (block.kind === "image") {
3436
- return `${block.command}${imageOptionsLatex(block)}{${block.value}}`;
4559
+ return imageBlockLatex(block);
4560
+ }
4561
+ if (block.kind === "bibliography") {
4562
+ const width = String(Math.max(references.length, 9));
4563
+ const items = references.map((reference) => ` ${bibliographyEntryLatex(reference)}`).join("\n");
4564
+ return `${block.command}{${width}}
4565
+ ${items}
4566
+ ${block.closing}`;
3437
4567
  }
3438
4568
  return block.value;
3439
4569
  }
3440
- function document2Latex(document2) {
3441
- return document2.blocks.map((block) => blockLatex(block)).join("\n\n");
4570
+ function authorLatex(authors) {
4571
+ return authors.split(/\n+/).map((line) => line.trim()).filter((line) => line.length > 0).join(" \\\\ ");
4572
+ }
4573
+ function articleFrontMatterLatex(meta) {
4574
+ const parts = [butexDiwaniDisplayLatex(BUTEX_BASMALA)];
4575
+ if (document2HasMaketitle(meta)) {
4576
+ if (meta.title.trim().length > 0) {
4577
+ parts.push(`\\title{${meta.title.trim()}}`);
4578
+ }
4579
+ if (meta.authors.trim().length > 0) {
4580
+ parts.push(`\\author{${authorLatex(meta.authors)}}`);
4581
+ }
4582
+ parts.push(`\\date{${formatHijriDate(meta.date, { locale: "ar", digitForm: "arabicIndic" })}}`);
4583
+ parts.push("\\maketitle");
4584
+ }
4585
+ if (document2HasAbstract(meta)) {
4586
+ parts.push(`\\begin{abstract}
4587
+ ${meta.abstract.trim()}
4588
+ \\end{abstract}`);
4589
+ }
4590
+ return parts;
4591
+ }
4592
+ function document2Latex(document2, options = {}) {
4593
+ const meta = document2.meta ?? emptyDocument2Meta();
4594
+ const front = articleFrontMatterLatex(meta);
4595
+ const bodyBlocks = document2.blocks.map((block) => blockLatex(block, document2.references));
4596
+ const closing = butexDiwaniDisplayLatex(BUTEX_CLOSING_HAMDALA);
4597
+ const body = [...front, ...bodyBlocks, closing].filter((part) => part.length > 0).join("\n\n");
4598
+ const wrapDocument = options.wrapDocument !== false;
4599
+ if (!wrapDocument) {
4600
+ return body;
4601
+ }
4602
+ const preamble = getArabicXeLatexPreamble({
4603
+ digitsMapping: options.digitsMapping ?? "arabicdigits",
4604
+ twocolumn: options.twocolumn === true
4605
+ });
4606
+ return `${preamble}
4607
+ \\begin{document}
4608
+
4609
+ ${body}
4610
+
4611
+ \\end{document}
4612
+ `;
3442
4613
  }
3443
4614
 
3444
4615
  // src/document2/history.ts
@@ -3474,18 +4645,99 @@ function document2HistoryCanRedo(stacks) {
3474
4645
  return stacks.future.length > 0;
3475
4646
  }
3476
4647
 
4648
+ // src/document2/blockSelection.ts
4649
+ function emptyBlockSelection() {
4650
+ return { selection: null, anchor: null };
4651
+ }
4652
+ function normalizeBlockSelection(selection, blockCount) {
4653
+ if (!selection) {
4654
+ return null;
4655
+ }
4656
+ const { from, to } = selection;
4657
+ if (blockCount <= 0 || from < 0 || to < 0 || from >= blockCount || to >= blockCount || from > to) {
4658
+ return null;
4659
+ }
4660
+ return { from, to };
4661
+ }
4662
+ function inRange(selection, index) {
4663
+ return index >= selection.from && index <= selection.to;
4664
+ }
4665
+ function toggleBlockInSelection(state, index, blockCount) {
4666
+ if (index < 0 || index >= blockCount) {
4667
+ return state;
4668
+ }
4669
+ const selection = normalizeBlockSelection(state.selection, blockCount);
4670
+ if (!selection) {
4671
+ return { selection: { from: index, to: index }, anchor: index };
4672
+ }
4673
+ if (inRange(selection, index)) {
4674
+ if (selection.from === selection.to) {
4675
+ return emptyBlockSelection();
4676
+ }
4677
+ if (index === selection.from) {
4678
+ return { selection: { from: selection.from + 1, to: selection.to }, anchor: state.anchor };
4679
+ }
4680
+ if (index === selection.to) {
4681
+ return { selection: { from: selection.from, to: selection.to - 1 }, anchor: state.anchor };
4682
+ }
4683
+ return emptyBlockSelection();
4684
+ }
4685
+ if (index === selection.from - 1) {
4686
+ return { selection: { from: index, to: selection.to }, anchor: state.anchor ?? index };
4687
+ }
4688
+ if (index === selection.to + 1) {
4689
+ return { selection: { from: selection.from, to: index }, anchor: state.anchor ?? index };
4690
+ }
4691
+ return { selection: { from: index, to: index }, anchor: index };
4692
+ }
4693
+ function extendBlockSelectionFromAnchor(state, index, blockCount) {
4694
+ if (index < 0 || index >= blockCount) {
4695
+ return state;
4696
+ }
4697
+ const anchor = state.anchor ?? index;
4698
+ const from = Math.min(anchor, index);
4699
+ const to = Math.max(anchor, index);
4700
+ return {
4701
+ selection: { from, to },
4702
+ anchor: state.anchor ?? index
4703
+ };
4704
+ }
4705
+ function remapSelectionAfterRangeMove(selection, direction) {
4706
+ return { from: selection.from + direction, to: selection.to + direction };
4707
+ }
4708
+
3477
4709
  // src/document2/previewModel.ts
3478
4710
  function mathTex(token, equationSide) {
3479
- if (token.kind === "text") {
3480
- return token.text;
3481
- }
3482
4711
  return mathTokenSourceForSide(token, equationSide);
3483
4712
  }
3484
- function previewInlines(field, islands, output, equationSide) {
4713
+ function previewInlines(field, islands, output, equationSide, document2, previewOptions) {
3485
4714
  return field.tokens.map((token) => {
3486
4715
  if (token.kind === "text") {
3487
4716
  return { kind: "text", text: token.text };
3488
4717
  }
4718
+ if (token.kind === "cite") {
4719
+ return {
4720
+ kind: "cite",
4721
+ id: token.id,
4722
+ keys: [...token.keys],
4723
+ label: formatCiteLabel(token.keys, document2.references, {
4724
+ documentDirection: previewOptions.documentDirection,
4725
+ digitForm: previewOptions.digitForm
4726
+ })
4727
+ };
4728
+ }
4729
+ if (token.kind === "ref") {
4730
+ return {
4731
+ kind: "ref",
4732
+ id: token.id,
4733
+ keys: [...token.keys],
4734
+ refCommand: token.refCommand,
4735
+ label: formatRefLabel(token.keys, document2, token.refCommand, {
4736
+ documentDirection: previewOptions.documentDirection,
4737
+ digitForm: previewOptions.digitForm
4738
+ })
4739
+ };
4740
+ }
3489
4741
  const island = {
3490
4742
  id: token.id,
3491
4743
  tex: mathTex(token, equationSide),
@@ -3497,21 +4749,43 @@ function previewInlines(field, islands, output, equationSide) {
3497
4749
  return { kind: "math", ...island };
3498
4750
  });
3499
4751
  }
3500
- function textBlockPreview(block, islands, output, equationSide) {
4752
+ function textBlockPreview(block, islands, output, equationSide, document2, previewOptions) {
4753
+ const inlines = previewInlines(block.field, islands, output, equationSide, document2, previewOptions);
3501
4754
  if (block.command === "\\section") {
3502
- return { kind: "heading", id: block.id, level: 1, inlines: previewInlines(block.field, islands, output, equationSide) };
4755
+ return { kind: "heading", id: block.id, level: 1, inlines };
3503
4756
  }
3504
4757
  if (block.command === "\\subsection") {
3505
- return { kind: "heading", id: block.id, level: 2, inlines: previewInlines(block.field, islands, output, equationSide) };
4758
+ return { kind: "heading", id: block.id, level: 2, inlines };
3506
4759
  }
3507
4760
  if (block.command === "\\subsubsection") {
3508
- return { kind: "heading", id: block.id, level: 3, inlines: previewInlines(block.field, islands, output, equationSide) };
4761
+ return { kind: "heading", id: block.id, level: 3, inlines };
4762
+ }
4763
+ return {
4764
+ kind: "paragraph",
4765
+ id: block.id,
4766
+ inlines,
4767
+ ...block.centered ? { centered: true } : {}
4768
+ };
4769
+ }
4770
+ function floatNumberLabel(document2, key, previewOptions) {
4771
+ if (!key || key.trim().length === 0) {
4772
+ return void 0;
4773
+ }
4774
+ const hit = labelNumberMap(document2).get(key.trim());
4775
+ if (!hit || hit.kind !== "fig" && hit.kind !== "tab") {
4776
+ return void 0;
3509
4777
  }
3510
- return { kind: "paragraph", id: block.id, inlines: previewInlines(block.field, islands, output, equationSide) };
4778
+ const locale = previewOptions.uiLocale ?? "ar";
4779
+ const kindWord = hit.kind === "fig" ? locale === "ar" ? "\u0627\u0644\u0634\u0643\u0644" : "Figure" : locale === "ar" ? "\u0627\u0644\u062C\u062F\u0648\u0644" : "Table";
4780
+ const digits = formatBibliographyNumber(hit.number, {
4781
+ documentDirection: previewOptions.documentDirection,
4782
+ digitForm: previewOptions.digitForm
4783
+ });
4784
+ return `${kindWord} ${digits}`;
3511
4785
  }
3512
- function blockPreview(block, islands, output, equationSide) {
4786
+ function blockPreview(block, islands, output, equationSide, document2, previewOptions) {
3513
4787
  if (block.kind === "textBlock") {
3514
- return textBlockPreview(block, islands, output, equationSide);
4788
+ return textBlockPreview(block, islands, output, equationSide, document2, previewOptions);
3515
4789
  }
3516
4790
  if (block.kind === "list") {
3517
4791
  return {
@@ -3520,50 +4794,154 @@ function blockPreview(block, islands, output, equationSide) {
3520
4794
  ordered: block.command === "\\begin{enumerate}",
3521
4795
  items: block.items.map((item) => ({
3522
4796
  id: item.id,
3523
- inlines: previewInlines(item.field, islands, output, equationSide),
3524
- blocks: item.blocks.map((child) => blockPreview(child, islands, output, equationSide))
4797
+ inlines: previewInlines(item.field, islands, output, equationSide, document2, previewOptions),
4798
+ blocks: item.blocks.map((child) => blockPreview(child, islands, output, equationSide, document2, previewOptions))
3525
4799
  }))
3526
4800
  };
3527
4801
  }
3528
4802
  if (block.kind === "table") {
3529
- return { kind: "table", id: block.id, rows: block.rows.map((row) => row.map((cell) => previewInlines(cell, islands, output, equationSide))) };
4803
+ const label = block.labelEnabled ? block.label.trim() : "";
4804
+ return {
4805
+ kind: "table",
4806
+ id: block.id,
4807
+ rows: block.rows.map((row) => row.map((cell) => previewInlines(cell, islands, output, equationSide, document2, previewOptions))),
4808
+ ...block.captionEnabled && block.caption.trim().length > 0 ? { caption: block.caption.trim() } : {},
4809
+ ...label.length > 0 ? { label, numberLabel: floatNumberLabel(document2, label, previewOptions) } : {}
4810
+ };
3530
4811
  }
3531
4812
  if (block.kind === "image") {
3532
- return { kind: "image", id: block.id, src: block.value, options: block.options };
4813
+ const label = block.labelEnabled ? block.label.trim() : "";
4814
+ return {
4815
+ kind: "image",
4816
+ id: block.id,
4817
+ src: block.value,
4818
+ ...block.assetId !== void 0 ? { assetId: block.assetId } : {},
4819
+ options: block.options,
4820
+ ...block.captionEnabled && block.caption.trim().length > 0 ? { caption: block.caption.trim() } : {},
4821
+ ...label.length > 0 ? { label, numberLabel: floatNumberLabel(document2, label, previewOptions) } : {}
4822
+ };
4823
+ }
4824
+ if (block.kind === "bibliography") {
4825
+ return {
4826
+ kind: "bibliography",
4827
+ id: block.id,
4828
+ items: document2.references.map((reference, index) => ({
4829
+ id: reference.id,
4830
+ numberLabel: formatBibliographyNumber(index + 1, {
4831
+ documentDirection: previewOptions.documentDirection,
4832
+ digitForm: previewOptions.digitForm
4833
+ }),
4834
+ key: reference.key,
4835
+ authors: reference.authors,
4836
+ title: reference.title,
4837
+ year: reference.year,
4838
+ url: reference.url,
4839
+ venue: reference.venue
4840
+ }))
4841
+ };
3533
4842
  }
3534
4843
  return { kind: "omit", id: block.id };
3535
4844
  }
3536
- function document2Preview(document2, output = "svg", equationSide = "arabic") {
4845
+ function articleChromePreview(document2, uiLocale, previewOptions) {
4846
+ const meta = document2.meta ?? emptyDocument2Meta();
4847
+ const blocks = [
4848
+ { kind: "basmala", id: "article-basmala", text: BUTEX_BASMALA, tex: butexDiwaniDisplayTex(BUTEX_BASMALA) }
4849
+ ];
4850
+ if (document2HasMaketitle(meta)) {
4851
+ blocks.push({
4852
+ kind: "titleBlock",
4853
+ id: "article-title",
4854
+ ...meta.title.trim().length > 0 ? { title: meta.title.trim() } : {},
4855
+ ...meta.authors.trim().length > 0 ? { authors: meta.authors.trim() } : {},
4856
+ date: formatHijriDate(meta.date, {
4857
+ locale: uiLocale,
4858
+ digitForm: previewOptions.digitForm
4859
+ })
4860
+ });
4861
+ }
4862
+ if (document2HasAbstract(meta)) {
4863
+ blocks.push({ kind: "abstract", id: "article-abstract", text: meta.abstract.trim() });
4864
+ }
4865
+ return blocks;
4866
+ }
4867
+ function document2Preview(document2, output = "svg", equationSide = "arabic", previewOptions = {}) {
3537
4868
  const mathIslands = [];
4869
+ const options = {
4870
+ documentDirection: previewOptions.documentDirection ?? "rtl",
4871
+ digitForm: previewOptions.digitForm ?? (previewOptions.documentDirection === "ltr" ? "western" : "arabicIndic"),
4872
+ uiLocale: previewOptions.uiLocale ?? "ar"
4873
+ };
4874
+ const body = document2.blocks.map((block) => blockPreview(block, mathIslands, output, equationSide, document2, options));
3538
4875
  return {
3539
- blocks: document2.blocks.map((block) => blockPreview(block, mathIslands, output, equationSide)),
4876
+ blocks: [
4877
+ ...articleChromePreview(document2, options.uiLocale ?? "ar", options),
4878
+ ...body,
4879
+ { kind: "closing", id: "article-closing", text: BUTEX_CLOSING_HAMDALA, tex: butexDiwaniDisplayTex(BUTEX_CLOSING_HAMDALA) }
4880
+ ],
3540
4881
  mathIslands
3541
4882
  };
3542
4883
  }
3543
4884
  export {
4885
+ BUTEX_BASMALA,
4886
+ BUTEX_CLOSING_HAMDALA,
3544
4887
  DEFAULT_DOCUMENT2_HISTORY_MAX_DEPTH,
4888
+ DEFAULT_HIJRI_DATE,
4889
+ HIJRI_MONTH_IDS,
4890
+ HIJRI_YEAR_MAX,
4891
+ HIJRI_YEAR_MIN,
3545
4892
  addDocument2ImageBlock,
3546
4893
  addDocument2ListBlock,
3547
4894
  addDocument2ListItem,
4895
+ addDocument2Reference,
3548
4896
  addDocument2TableBlock,
3549
4897
  addDocument2TextBlock,
4898
+ applyFloatMetaPatch,
4899
+ arabicXeLatexPreambleCmd,
4900
+ arabicXeLatexPreambleFont,
4901
+ arabicXeLatexPreamblePkg,
4902
+ bibliographyEntryLatex,
4903
+ butexDiwaniDisplayLatex,
4904
+ butexDiwaniDisplayTex,
4905
+ citeTokenLatex,
4906
+ cloneDocument2Meta,
3550
4907
  cloneDocument2Node,
4908
+ collectDocument2Labels,
3551
4909
  createDocument2History,
3552
4910
  createEmptyArabicEquationSession,
3553
4911
  createEmptyDocument2,
3554
4912
  createEmptyEquationSession,
4913
+ createEmptyReference2,
3555
4914
  createInlineField2,
4915
+ defaultFloatMeta,
4916
+ detectInlineSpans2,
3556
4917
  detectMathSpans2,
4918
+ document2HasAbstract,
4919
+ document2HasMaketitle,
4920
+ document2HasTitleStack,
3557
4921
  document2HistoryCanRedo,
3558
4922
  document2HistoryCanUndo,
3559
4923
  document2Latex,
3560
4924
  document2Preview,
4925
+ emptyBlockSelection,
4926
+ emptyDocument2Meta,
4927
+ ensureDocument2BibliographyBlock,
4928
+ extendBlockSelectionFromAnchor,
4929
+ fillDocument2MetaGaps,
3561
4930
  findFirstInlineField,
4931
+ formatBibliographyNumber,
4932
+ formatCiteLabel,
4933
+ formatHijriDate,
4934
+ formatRefLabel,
3562
4935
  fromDocumentJson2,
4936
+ getArabicXeLatexPreamble,
4937
+ hijriMonthLabel,
3563
4938
  inlineFieldLatex,
4939
+ insertCiteTokenAtCaret,
3564
4940
  insertDocument2BlockAfter,
3565
4941
  insertMathToken,
3566
4942
  insertMathTokenAtCaret,
4943
+ insertRefTokenAtCaret,
4944
+ labelNumberMap,
3567
4945
  mathNodeFromArabicSession,
3568
4946
  mathNodeFromSession,
3569
4947
  mathSourceFromArabicSession,
@@ -3571,15 +4949,44 @@ export {
3571
4949
  mathTokenSourceForSide,
3572
4950
  mathTokenToArabicEditorSession,
3573
4951
  mathTokenToEditorSession,
4952
+ mergeDocument2Meta,
3574
4953
  moveDocument2BlockById,
4954
+ moveDocument2BlockRange,
4955
+ moveDocument2Reference,
4956
+ normalizeBlockSelection,
4957
+ normalizeDocument2HijriDate,
4958
+ normalizeDocument2Meta,
4959
+ parseCiteKeys,
4960
+ parseFloatMetaFromJson,
4961
+ parseRefKeys,
3575
4962
  pushDocument2Snapshot,
4963
+ refTokenLatex,
4964
+ referenceFromJson,
4965
+ referenceNumberMap,
4966
+ remapSelectionAfterRangeMove,
4967
+ removeCiteTokenById,
3576
4968
  removeDocument2BlockById,
4969
+ removeDocument2BlockRange,
3577
4970
  removeDocument2ListItem,
4971
+ removeDocument2Reference,
3578
4972
  removeMathTokenById,
4973
+ removeRefTokenById,
3579
4974
  replaceMathTokenFromSession,
4975
+ resolveCiteNumbers,
3580
4976
  restoreDocument2Redo,
3581
4977
  restoreDocument2Undo,
4978
+ setDocument2References,
4979
+ stripDisplayMathDelimiters,
4980
+ toggleBlockInSelection,
4981
+ updateCiteTokenKeys,
4982
+ updateDocument2ImageMeta,
3582
4983
  updateDocument2ImageValue,
4984
+ updateDocument2Meta,
4985
+ updateDocument2Reference,
4986
+ updateDocument2TableMeta,
4987
+ updateDocument2TextBlockCentered,
4988
+ updateMathTokenLabel,
4989
+ updateRefTokenKeys,
3583
4990
  updateTextToken
3584
4991
  };
3585
4992
  //# sourceMappingURL=document2.mjs.map