@drghaliasri/butex 4.4.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/document2.js CHANGED
@@ -24,22 +24,35 @@ __export(document2_exports, {
24
24
  addDocument2ImageBlock: () => addDocument2ImageBlock,
25
25
  addDocument2ListBlock: () => addDocument2ListBlock,
26
26
  addDocument2ListItem: () => addDocument2ListItem,
27
+ addDocument2Reference: () => addDocument2Reference,
27
28
  addDocument2TableBlock: () => addDocument2TableBlock,
28
29
  addDocument2TextBlock: () => addDocument2TextBlock,
30
+ arabicXeLatexPreambleCmd: () => arabicXeLatexPreambleCmd,
31
+ arabicXeLatexPreambleFont: () => arabicXeLatexPreambleFont,
32
+ arabicXeLatexPreamblePkg: () => arabicXeLatexPreamblePkg,
33
+ bibliographyEntryLatex: () => bibliographyEntryLatex,
34
+ citeTokenLatex: () => citeTokenLatex,
29
35
  cloneDocument2Node: () => cloneDocument2Node,
30
36
  createDocument2History: () => createDocument2History,
31
37
  createEmptyArabicEquationSession: () => createEmptyArabicEquationSession,
32
38
  createEmptyDocument2: () => createEmptyDocument2,
33
39
  createEmptyEquationSession: () => createEmptyEquationSession,
40
+ createEmptyReference2: () => createEmptyReference2,
34
41
  createInlineField2: () => createInlineField2,
42
+ detectInlineSpans2: () => detectInlineSpans2,
35
43
  detectMathSpans2: () => detectMathSpans2,
36
44
  document2HistoryCanRedo: () => document2HistoryCanRedo,
37
45
  document2HistoryCanUndo: () => document2HistoryCanUndo,
38
46
  document2Latex: () => document2Latex,
39
47
  document2Preview: () => document2Preview,
48
+ ensureDocument2BibliographyBlock: () => ensureDocument2BibliographyBlock,
40
49
  findFirstInlineField: () => findFirstInlineField,
50
+ formatBibliographyNumber: () => formatBibliographyNumber,
51
+ formatCiteLabel: () => formatCiteLabel,
41
52
  fromDocumentJson2: () => fromDocumentJson2,
53
+ getArabicXeLatexPreamble: () => getArabicXeLatexPreamble,
42
54
  inlineFieldLatex: () => inlineFieldLatex,
55
+ insertCiteTokenAtCaret: () => insertCiteTokenAtCaret,
43
56
  insertDocument2BlockAfter: () => insertDocument2BlockAfter,
44
57
  insertMathToken: () => insertMathToken,
45
58
  insertMathTokenAtCaret: () => insertMathTokenAtCaret,
@@ -51,14 +64,24 @@ __export(document2_exports, {
51
64
  mathTokenToArabicEditorSession: () => mathTokenToArabicEditorSession,
52
65
  mathTokenToEditorSession: () => mathTokenToEditorSession,
53
66
  moveDocument2BlockById: () => moveDocument2BlockById,
67
+ moveDocument2Reference: () => moveDocument2Reference,
68
+ parseCiteKeys: () => parseCiteKeys,
54
69
  pushDocument2Snapshot: () => pushDocument2Snapshot,
70
+ referenceFromJson: () => referenceFromJson,
71
+ referenceNumberMap: () => referenceNumberMap,
72
+ removeCiteTokenById: () => removeCiteTokenById,
55
73
  removeDocument2BlockById: () => removeDocument2BlockById,
56
74
  removeDocument2ListItem: () => removeDocument2ListItem,
75
+ removeDocument2Reference: () => removeDocument2Reference,
57
76
  removeMathTokenById: () => removeMathTokenById,
58
77
  replaceMathTokenFromSession: () => replaceMathTokenFromSession,
78
+ resolveCiteNumbers: () => resolveCiteNumbers,
59
79
  restoreDocument2Redo: () => restoreDocument2Redo,
60
80
  restoreDocument2Undo: () => restoreDocument2Undo,
81
+ setDocument2References: () => setDocument2References,
82
+ updateCiteTokenKeys: () => updateCiteTokenKeys,
61
83
  updateDocument2ImageValue: () => updateDocument2ImageValue,
84
+ updateDocument2Reference: () => updateDocument2Reference,
62
85
  updateTextToken: () => updateTextToken
63
86
  });
64
87
  module.exports = __toCommonJS(document2_exports);
@@ -71,6 +94,100 @@ function document2Id(prefix) {
71
94
  return id;
72
95
  }
73
96
 
97
+ // src/editor/digits.ts
98
+ var WESTERN = "0123456789";
99
+ var ARABIC_INDIC = "\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669";
100
+ var PERSIAN_INDIC = "\u06F0\u06F1\u06F2\u06F3\u06F4\u06F5\u06F6\u06F7\u06F8\u06F9";
101
+ var digitSets = {
102
+ western: WESTERN,
103
+ arabicIndic: ARABIC_INDIC,
104
+ persianIndic: PERSIAN_INDIC
105
+ };
106
+ function digitValue(char) {
107
+ const western = WESTERN.indexOf(char);
108
+ if (western >= 0) {
109
+ return western;
110
+ }
111
+ const arabicIndic = ARABIC_INDIC.indexOf(char);
112
+ if (arabicIndic >= 0) {
113
+ return arabicIndic;
114
+ }
115
+ return PERSIAN_INDIC.indexOf(char);
116
+ }
117
+ function formatDigits(value, digitForm = "western") {
118
+ const target = digitSets[digitForm];
119
+ return Array.from(value, (char) => {
120
+ const value2 = digitValue(char);
121
+ return value2 >= 0 ? target[value2] : char;
122
+ }).join("");
123
+ }
124
+
125
+ // src/document2/citations.ts
126
+ function referenceNumberMap(references) {
127
+ const map = /* @__PURE__ */ new Map();
128
+ references.forEach((reference, index) => {
129
+ if (!map.has(reference.key)) {
130
+ map.set(reference.key, index + 1);
131
+ }
132
+ });
133
+ return map;
134
+ }
135
+ function resolveCiteNumbers(keys, references) {
136
+ const map = referenceNumberMap(references);
137
+ return keys.map((key) => map.get(key) ?? null);
138
+ }
139
+ function formatCiteLabel(keys, references, options = {}) {
140
+ const documentDirection = options.documentDirection ?? "rtl";
141
+ const digitForm = options.digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
142
+ const numbers = resolveCiteNumbers(keys, references).map((value) => value === null ? "?" : String(value));
143
+ const display = documentDirection === "rtl" ? [...numbers].reverse() : numbers;
144
+ const separator = documentDirection === "rtl" ? "\u060C" : ", ";
145
+ const body = display.map((part) => formatDigits(part, digitForm)).join(separator);
146
+ return `[${body}]`;
147
+ }
148
+ function formatBibliographyNumber(index, options = {}) {
149
+ const documentDirection = options.documentDirection ?? "rtl";
150
+ const digitForm = options.digitForm ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
151
+ return formatDigits(String(index), digitForm);
152
+ }
153
+ function parseCiteKeys(source) {
154
+ const match = /^\\cite\{([^}]*)\}$/.exec(source.trim());
155
+ if (!match) {
156
+ return [];
157
+ }
158
+ return (match[1] ?? "").split(",").map((key) => key.trim()).filter((key) => key.length > 0);
159
+ }
160
+ function citeTokenLatex(keys) {
161
+ return `\\cite{${keys.join(",")}}`;
162
+ }
163
+ function referenceFromJson(json) {
164
+ return {
165
+ id: document2Id("ref"),
166
+ key: json.key,
167
+ authors: typeof json.authors === "string" ? json.authors : "",
168
+ title: typeof json.title === "string" ? json.title : "",
169
+ year: typeof json.year === "string" ? json.year : "",
170
+ url: typeof json.url === "string" ? json.url : "",
171
+ venue: typeof json.venue === "string" ? json.venue : ""
172
+ };
173
+ }
174
+ function createEmptyReference2(partial = {}) {
175
+ return referenceFromJson({
176
+ key: partial.key ?? `ref${String(Date.now()).slice(-4)}`,
177
+ authors: partial.authors,
178
+ title: partial.title,
179
+ year: partial.year,
180
+ url: partial.url,
181
+ venue: partial.venue
182
+ });
183
+ }
184
+ function bibliographyEntryLatex(reference) {
185
+ const parts = [reference.authors, reference.title, reference.venue, reference.year].filter((part) => part.trim().length > 0);
186
+ const body = parts.join(", ");
187
+ const url = reference.url.trim().length > 0 ? ` \\url{${reference.url}}` : "";
188
+ return `\\bibitem{${reference.key}} ${body}${url}`.trim();
189
+ }
190
+
74
191
  // src/ast/commands/index.ts
75
192
  function renderCommandCore(context) {
76
193
  const optional = context.optionalArgs.map((arg) => `[${context.renderChain(arg)}]`).join("");
@@ -489,53 +606,84 @@ function environmentSpan(value, start) {
489
606
  const end = closingStart + closing.length;
490
607
  return { start, end, source: value.slice(start, end), opening, closing, display: true };
491
608
  }
492
- function detectMathSpans2(value) {
493
- const spans = [];
494
- let i = 0;
495
- while (i < value.length) {
496
- if (value.startsWith("\\begin{", i)) {
497
- const span = environmentSpan(value, i);
498
- if (span) {
499
- spans.push(span);
500
- i = span.end;
501
- continue;
502
- }
609
+ function citeSpan(value, start) {
610
+ if (!value.startsWith("\\cite{", start) || isEscaped(value, start)) {
611
+ return null;
612
+ }
613
+ const openBrace = start + "\\cite".length;
614
+ if (value[openBrace] !== "{") {
615
+ return null;
616
+ }
617
+ let depth = 0;
618
+ for (let i = openBrace; i < value.length; i += 1) {
619
+ const char = value[i];
620
+ if (char === "{" && !isEscaped(value, i)) {
621
+ depth += 1;
622
+ continue;
503
623
  }
504
- if (value.startsWith("\\(", i)) {
505
- const close = value.indexOf("\\)", i + 2);
506
- if (close >= 0) {
507
- const end = close + 2;
508
- spans.push({ start: i, end, source: value.slice(i, end), opening: "\\(", closing: "\\)", display: false });
509
- i = end;
510
- continue;
624
+ if (char === "}" && !isEscaped(value, i)) {
625
+ depth -= 1;
626
+ if (depth === 0) {
627
+ const end = i + 1;
628
+ const source = value.slice(start, end);
629
+ return { kind: "cite", start, end, source, keys: parseCiteKeys(source) };
511
630
  }
512
631
  }
513
- if (value.startsWith("\\[", i)) {
514
- const close = value.indexOf("\\]", i + 2);
515
- if (close >= 0) {
516
- const end = close + 2;
517
- spans.push({ start: i, end, source: value.slice(i, end), opening: "\\[", closing: "\\]", display: true });
518
- i = end;
519
- continue;
520
- }
632
+ }
633
+ return null;
634
+ }
635
+ function mathSpanAt(value, i) {
636
+ if (value.startsWith("\\begin{", i)) {
637
+ return environmentSpan(value, i);
638
+ }
639
+ if (value.startsWith("\\(", i)) {
640
+ const close = value.indexOf("\\)", i + 2);
641
+ if (close >= 0) {
642
+ const end = close + 2;
643
+ return { start: i, end, source: value.slice(i, end), opening: "\\(", closing: "\\)", display: false };
521
644
  }
522
- if (value.startsWith("$$", i) && !isEscaped(value, i)) {
523
- const close = value.indexOf("$$", i + 2);
524
- if (close >= 0) {
525
- const end = close + 2;
526
- spans.push({ start: i, end, source: value.slice(i, end), opening: "$$", closing: "$$", display: true });
527
- i = end;
528
- continue;
529
- }
645
+ }
646
+ if (value.startsWith("\\[", i)) {
647
+ const close = value.indexOf("\\]", i + 2);
648
+ if (close >= 0) {
649
+ const end = close + 2;
650
+ return { start: i, end, source: value.slice(i, end), opening: "\\[", closing: "\\]", display: true };
530
651
  }
531
- if (value[i] === "$" && !isEscaped(value, i)) {
532
- const close = findClosingDollar(value, i + 1);
533
- if (close >= 0) {
534
- const end = close + 1;
535
- spans.push({ start: i, end, source: value.slice(i, end), opening: "$", closing: "$", display: false });
536
- i = end;
537
- continue;
538
- }
652
+ }
653
+ if (value.startsWith("$$", i) && !isEscaped(value, i)) {
654
+ const close = value.indexOf("$$", i + 2);
655
+ if (close >= 0) {
656
+ const end = close + 2;
657
+ return { start: i, end, source: value.slice(i, end), opening: "$$", closing: "$$", display: true };
658
+ }
659
+ }
660
+ if (value[i] === "$" && !isEscaped(value, i)) {
661
+ const close = findClosingDollar(value, i + 1);
662
+ if (close >= 0) {
663
+ const end = close + 1;
664
+ return { start: i, end, source: value.slice(i, end), opening: "$", closing: "$", display: false };
665
+ }
666
+ }
667
+ return null;
668
+ }
669
+ function detectMathSpans2(value) {
670
+ return detectInlineSpans2(value).filter((span) => span.kind === "math").map(({ kind: _kind, ...span }) => span);
671
+ }
672
+ function detectInlineSpans2(value) {
673
+ const spans = [];
674
+ let i = 0;
675
+ while (i < value.length) {
676
+ const cite = citeSpan(value, i);
677
+ if (cite) {
678
+ spans.push(cite);
679
+ i = cite.end;
680
+ continue;
681
+ }
682
+ const math = mathSpanAt(value, i);
683
+ if (math) {
684
+ spans.push({ kind: "math", ...math });
685
+ i = math.end;
686
+ continue;
539
687
  }
540
688
  i += 1;
541
689
  }
@@ -572,19 +720,53 @@ function pushDiagnostic(diagnostics, options, path, message) {
572
720
  }
573
721
  diagnostics.push({ code: "math_alignment", message, path });
574
722
  }
723
+ function parseReferences(json) {
724
+ if (!Array.isArray(json)) {
725
+ return [];
726
+ }
727
+ const references = [];
728
+ for (const entry of json) {
729
+ if (!isObject2(entry) || typeof entry.key !== "string" || entry.key.trim().length === 0) {
730
+ continue;
731
+ }
732
+ references.push(
733
+ referenceFromJson({
734
+ key: entry.key.trim(),
735
+ authors: typeof entry.authors === "string" ? entry.authors : void 0,
736
+ title: typeof entry.title === "string" ? entry.title : void 0,
737
+ year: typeof entry.year === "string" ? entry.year : void 0,
738
+ url: typeof entry.url === "string" ? entry.url : void 0,
739
+ venue: typeof entry.venue === "string" ? entry.venue : void 0
740
+ })
741
+ );
742
+ }
743
+ return references;
744
+ }
575
745
  function createInlineField2(value = "", mathObjects = [], options = {}, path = "$", diagnostics = []) {
576
746
  const mode = options.mode ?? "english";
577
- const spans = detectMathSpans2(value);
747
+ const spans = detectInlineSpans2(value);
748
+ const mathSpans = spans.filter((span) => span.kind === "math");
578
749
  const tokens = [];
579
750
  let index = 0;
580
- if (mathObjects.length > 0 && mathObjects.length !== spans.length) {
581
- pushDiagnostic(diagnostics, options, path, `math_objects count mismatch: detected ${String(spans.length)}, got ${String(mathObjects.length)}`);
751
+ let mathObjectIndex = 0;
752
+ if (mathObjects.length > 0 && mathObjects.length !== mathSpans.length) {
753
+ pushDiagnostic(diagnostics, options, path, `math_objects count mismatch: detected ${String(mathSpans.length)}, got ${String(mathObjects.length)}`);
582
754
  }
583
- spans.forEach((span, spanIndex) => {
755
+ for (const span of spans) {
584
756
  if (span.start > index) {
585
757
  tokens.push({ id: document2Id("text"), kind: "text", text: value.slice(index, span.start) });
586
758
  }
587
- const mathJson = mathObjects[spanIndex];
759
+ if (span.kind === "cite") {
760
+ tokens.push({
761
+ id: document2Id("cite"),
762
+ kind: "cite",
763
+ keys: span.keys.length > 0 ? span.keys : []
764
+ });
765
+ index = span.end;
766
+ continue;
767
+ }
768
+ const mathJson = mathObjects[mathObjectIndex];
769
+ mathObjectIndex += 1;
588
770
  if (mathJson && (mathJson.math_mode !== span.opening || mathJson.closing !== span.closing)) {
589
771
  pushDiagnostic(diagnostics, options, path, "math_objects order mismatch");
590
772
  }
@@ -616,7 +798,7 @@ function createInlineField2(value = "", mathObjects = [], options = {}, path = "
616
798
  });
617
799
  }
618
800
  index = span.end;
619
- });
801
+ }
620
802
  if (index < value.length || tokens.length === 0) {
621
803
  tokens.push({ id: document2Id("text"), kind: "text", text: value.slice(index) });
622
804
  }
@@ -688,11 +870,14 @@ function parseTableBlock(json, options, path, diagnostics) {
688
870
  };
689
871
  }
690
872
  function parseImageBlock(json) {
873
+ const assetId = typeof json.asset_id === "string" && json.asset_id.length > 0 ? json.asset_id : void 0;
874
+ const value = assetId !== void 0 ? typeof json.value === "string" ? json.value : "" : requireString(json.value, "\\includegraphics requires string value");
691
875
  return {
692
876
  id: document2Id("block"),
693
877
  kind: "image",
694
878
  command: "\\includegraphics",
695
- value: requireString(json.value, "\\includegraphics requires string value"),
879
+ value,
880
+ ...assetId !== void 0 ? { assetId } : {},
696
881
  options: isRecordOfStrings(json.options) ? json.options : {}
697
882
  };
698
883
  }
@@ -704,6 +889,14 @@ function parseRawBlock(json) {
704
889
  value: typeof json.value === "string" ? json.value : ""
705
890
  };
706
891
  }
892
+ function parseBibliographyBlock() {
893
+ return {
894
+ id: document2Id("block"),
895
+ kind: "bibliography",
896
+ command: "\\begin{thebibliography}",
897
+ closing: "\\end{thebibliography}"
898
+ };
899
+ }
707
900
  function parseBlock(json, options, path, diagnostics) {
708
901
  if (TEXT_COMMANDS.has(json.command)) {
709
902
  return parseTextBlock(json, options, path, diagnostics);
@@ -717,6 +910,9 @@ function parseBlock(json, options, path, diagnostics) {
717
910
  if (json.command === "\\includegraphics") {
718
911
  return parseImageBlock(json);
719
912
  }
913
+ if (json.command === "\\begin{thebibliography}" || json.command === "\\bibliography") {
914
+ return parseBibliographyBlock();
915
+ }
720
916
  if (json.command === "\\raw") {
721
917
  return parseRawBlock(json);
722
918
  }
@@ -737,12 +933,13 @@ function fromDocumentJson2(json, options = {}) {
737
933
  const diagnostics = [];
738
934
  return {
739
935
  nodeType: "DocumentObject",
936
+ references: parseReferences(json.references),
740
937
  blocks: json.blocks.map((block, index) => parseBlock(asBlockJson(block), options, `$.blocks[${String(index)}]`, diagnostics)),
741
938
  diagnostics
742
939
  };
743
940
  }
744
941
  function createEmptyDocument2() {
745
- return { nodeType: "DocumentObject", blocks: [], diagnostics: [] };
942
+ return { nodeType: "DocumentObject", references: [], blocks: [], diagnostics: [] };
746
943
  }
747
944
 
748
945
  // src/editor/atomicCommands.ts
@@ -1765,34 +1962,6 @@ function renderDivideOperatorLatex(side) {
1765
1962
  return side === "arabic" ? "\\backslash" : DIVIDE_OPERATOR_EN;
1766
1963
  }
1767
1964
 
1768
- // src/editor/digits.ts
1769
- var WESTERN = "0123456789";
1770
- var ARABIC_INDIC = "\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669";
1771
- var PERSIAN_INDIC = "\u06F0\u06F1\u06F2\u06F3\u06F4\u06F5\u06F6\u06F7\u06F8\u06F9";
1772
- var digitSets = {
1773
- western: WESTERN,
1774
- arabicIndic: ARABIC_INDIC,
1775
- persianIndic: PERSIAN_INDIC
1776
- };
1777
- function digitValue(char) {
1778
- const western = WESTERN.indexOf(char);
1779
- if (western >= 0) {
1780
- return western;
1781
- }
1782
- const arabicIndic = ARABIC_INDIC.indexOf(char);
1783
- if (arabicIndic >= 0) {
1784
- return arabicIndic;
1785
- }
1786
- return PERSIAN_INDIC.indexOf(char);
1787
- }
1788
- function formatDigits(value, digitForm = "western") {
1789
- const target = digitSets[digitForm];
1790
- return Array.from(value, (char) => {
1791
- const value2 = digitValue(char);
1792
- return value2 >= 0 ? target[value2] : char;
1793
- }).join("");
1794
- }
1795
-
1796
1965
  // src/editor/render.ts
1797
1966
  function selectedDigitForm(options) {
1798
1967
  return options?.digitForm ?? "western";
@@ -3125,6 +3294,7 @@ function cloneBlock(block) {
3125
3294
  function cloneDocument(document2) {
3126
3295
  return {
3127
3296
  nodeType: "DocumentObject",
3297
+ references: document2.references.map((reference) => ({ ...reference })),
3128
3298
  blocks: document2.blocks.map(cloneBlock),
3129
3299
  diagnostics: document2.diagnostics.map((diagnostic) => ({ ...diagnostic }))
3130
3300
  };
@@ -3445,12 +3615,340 @@ function removeDocument2ListItem(document2, listBlockId, itemId) {
3445
3615
  });
3446
3616
  return next;
3447
3617
  }
3618
+ function citeTokenFromKeys(keys) {
3619
+ return { id: document2Id("cite"), kind: "cite", keys: [...keys] };
3620
+ }
3621
+ function insertCiteTokenAtCaret(document2, fieldId, textTokenId, caretOffset, keys) {
3622
+ if (keys.length === 0) {
3623
+ return document2;
3624
+ }
3625
+ const next = cloneDocument(document2);
3626
+ const citeToken = citeTokenFromKeys(keys);
3627
+ visitFields(next.blocks, (field) => {
3628
+ if (field.id !== fieldId) {
3629
+ return false;
3630
+ }
3631
+ const textIndex = textTokenId ? field.tokens.findIndex((token) => token.id === textTokenId && token.kind === "text") : field.tokens.findIndex((token) => token.kind === "text");
3632
+ if (textIndex < 0) {
3633
+ field.tokens.push(citeToken);
3634
+ field.tokens.push({ id: document2Id("text"), kind: "text", text: "" });
3635
+ return true;
3636
+ }
3637
+ const current = field.tokens[textIndex];
3638
+ const [before, after] = splitTextTokenAt(current, caretOffset);
3639
+ const parts = [...field.tokens.slice(0, textIndex)];
3640
+ if (before.text.length > 0) {
3641
+ parts.push(before);
3642
+ }
3643
+ parts.push(citeToken);
3644
+ parts.push(after);
3645
+ parts.push(...field.tokens.slice(textIndex + 1));
3646
+ field.tokens = normalizeFieldTokens(parts);
3647
+ return true;
3648
+ });
3649
+ return next;
3650
+ }
3651
+ function updateCiteTokenKeys(document2, tokenId, keys) {
3652
+ if (keys.length === 0) {
3653
+ return document2;
3654
+ }
3655
+ const next = cloneDocument(document2);
3656
+ visitFields(next.blocks, (field) => {
3657
+ const token = field.tokens.find((entry) => entry.id === tokenId && entry.kind === "cite");
3658
+ if (!token) {
3659
+ return false;
3660
+ }
3661
+ token.keys = [...keys];
3662
+ return true;
3663
+ });
3664
+ return next;
3665
+ }
3666
+ function removeCiteTokenById(document2, tokenId) {
3667
+ const next = cloneDocument(document2);
3668
+ visitFields(next.blocks, (field) => {
3669
+ const index = field.tokens.findIndex((token) => token.id === tokenId && token.kind === "cite");
3670
+ if (index < 0) {
3671
+ return false;
3672
+ }
3673
+ field.tokens = normalizeFieldTokens(stitchTextAroundRemovedToken(field.tokens, index));
3674
+ return true;
3675
+ });
3676
+ return next;
3677
+ }
3678
+ function ensureDocument2BibliographyBlock(document2, afterBlockId) {
3679
+ if (document2.blocks.some((block2) => block2.kind === "bibliography")) {
3680
+ return document2;
3681
+ }
3682
+ const block = {
3683
+ id: document2Id("block"),
3684
+ kind: "bibliography",
3685
+ command: "\\begin{thebibliography}",
3686
+ closing: "\\end{thebibliography}"
3687
+ };
3688
+ return insertDocument2BlockAfter(document2, afterBlockId ?? null, block);
3689
+ }
3690
+ function addDocument2Reference(document2, partial = {}) {
3691
+ const next = cloneDocument(document2);
3692
+ next.references.push(createEmptyReference2(partial));
3693
+ return next;
3694
+ }
3695
+ function updateDocument2Reference(document2, referenceId, patch) {
3696
+ const next = cloneDocument(document2);
3697
+ const reference = next.references.find((entry) => entry.id === referenceId);
3698
+ if (!reference) {
3699
+ return document2;
3700
+ }
3701
+ if (typeof patch.key === "string" && patch.key.trim().length > 0) {
3702
+ reference.key = patch.key.trim();
3703
+ }
3704
+ if (typeof patch.authors === "string") {
3705
+ reference.authors = patch.authors;
3706
+ }
3707
+ if (typeof patch.title === "string") {
3708
+ reference.title = patch.title;
3709
+ }
3710
+ if (typeof patch.year === "string") {
3711
+ reference.year = patch.year;
3712
+ }
3713
+ if (typeof patch.url === "string") {
3714
+ reference.url = patch.url;
3715
+ }
3716
+ if (typeof patch.venue === "string") {
3717
+ reference.venue = patch.venue;
3718
+ }
3719
+ return next;
3720
+ }
3721
+ function removeDocument2Reference(document2, referenceId) {
3722
+ const next = cloneDocument(document2);
3723
+ next.references = next.references.filter((reference) => reference.id !== referenceId);
3724
+ return next;
3725
+ }
3726
+ function moveDocument2Reference(document2, referenceId, direction) {
3727
+ const next = cloneDocument(document2);
3728
+ const index = next.references.findIndex((reference2) => reference2.id === referenceId);
3729
+ const targetIndex = index + direction;
3730
+ if (index < 0 || targetIndex < 0 || targetIndex >= next.references.length) {
3731
+ return document2;
3732
+ }
3733
+ const [reference] = next.references.splice(index, 1);
3734
+ if (!reference) {
3735
+ return document2;
3736
+ }
3737
+ next.references.splice(targetIndex, 0, reference);
3738
+ return next;
3739
+ }
3740
+ function setDocument2References(document2, references) {
3741
+ const next = cloneDocument(document2);
3742
+ next.references = references.map((reference) => ({ ...reference }));
3743
+ return next;
3744
+ }
3745
+
3746
+ // src/document2/arabicPreamble.ts
3747
+ function arabicXeLatexPreamblePkg() {
3748
+ return String.raw`
3749
+ \documentclass[12pt,a4paper]{article}
3750
+ \usepackage{amsmath,amsfonts,amssymb,mathrsfs,tikz,fancyhdr, mathtools}
3751
+ \usepackage{fontspec} % For loading OpenType fonts
3752
+ \usepackage{unicode-math} % For setting the math font
3753
+ \usepackage{polyglossia} % For Arabic support
3754
+ \usepackage{array}
3755
+ \usepackage{cancel}
3756
+ \usepackage{bidi} % For bidirectional text handling
3757
+ \usepackage{multirow}
3758
+ \usepackage{booktabs}
3759
+ \usepackage{graphicx} % For \reflectbox
3760
+ \usepackage{xcolor}
3761
+ \usepackage{tikz}
3762
+ \usepackage{tcolorbox} % For tcolorbox environment
3763
+ \usepackage{textcomp} % For \textrightarrow command
3764
+
3765
+
3766
+ % visit : https://www.symbolcopy.com/punctuation-symbol.html
3767
+ % for inversed punctuation
3768
+
3769
+ % save inverted comma for use - copy paste -> ،
3770
+ % save back tick for use - copy paste -> ` + "`";
3771
+ }
3772
+ function arabicXeLatexPreambleFont(digitsMapping = "arabicdigits") {
3773
+ return `
3774
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3775
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3776
+ % Toggle between eastern and western digits by changing the Mapping in the below fonts (inside math font as well) between "arabicdigits" and "digits"
3777
+ \\setdefaultlanguage[calendar=gregorian]{arabic} % from polyglossia
3778
+ \\setmainfont[Script=Arabic , Mapping=${digitsMapping}]{Amiri}
3779
+ \\newfontfamily\\diwani[Script=Arabic,Mapping=${digitsMapping}]{Diwani Letter}
3780
+ \\newfontfamily\\diwanioutlineshaded[Script=Arabic,Mapping=${digitsMapping}]{Diwani Outline Shaded}
3781
+ \\newfontfamily\\takween[Script=Arabic,Mapping=${digitsMapping}]{Takween}
3782
+ \\newfontfamily\\boldarabic[Script=Arabic,Mapping=${digitsMapping}]{Amiri Bold}
3783
+ \\newfontfamily\\italicarabic[Script=Arabic,Mapping=${digitsMapping}]{Amiri Italic}
3784
+
3785
+ % Explicitly set math font to XITS Math
3786
+ % Remove "Script=Arabic" to cancel reflected symbols and other RTL symbols
3787
+ \\setmathfont[Script=Arabic , Mapping=${digitsMapping}]{XITS Math} % Ensure XITS Math is correctly installed and available
3788
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3789
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3790
+ `;
3791
+ }
3792
+ function arabicXeLatexPreambleCmd() {
3793
+ return String.raw`
3794
+ % Run with XeLaTeX compiler
3795
+ \newcommand{\butextakween}[1]{\text{\takween{#1}}}
3796
+ \newcommand{\butexdiwani}[1]{\text{\diwani{#1}}}
3797
+ \newcommand{\butexdiwanioutline}[1]{\text{\diwanioutlineshaded{#1}}}
3798
+
3799
+ \newcommand{\arabN}{\text{\diwanioutlineshaded{ط}}}
3800
+ \newcommand{\arabZ}{\text{\diwanioutlineshaded{ص}}}
3801
+ \newcommand{\arabQ}{\text{\diwanioutlineshaded{ن}}}
3802
+ \newcommand{\arabR}{\text{\diwanioutlineshaded{ح}}}
3803
+ \newcommand{\arabC}{\text{\diwanioutlineshaded{ع}}}
3804
+ \newcommand{\arabH}{\text{\diwanioutlineshaded{ر}}}
3805
+
3806
+
3807
+ \newcommand{\lowerscript}[1]{\raisebox{-4pt}{\scriptsize #1}}
3808
+ \newcommand{\llowerscript}[1]{\raisebox{-8pt}{\scriptsize #1}}
3809
+ \newcommand{\lllowerscript}[2]{\raisebox{#2pt}{\scriptsize #1}}
3810
+
3811
+ \newcommand{\arabdsub}[3]{\prescript{}{#1}{\prescript{}{#2}{#3}}} % arabic double subscript
3812
+ \newcommand{\arabsub}[2]{\prescript{}{#1}{#2}} % arabic single subscript
3813
+
3814
+
3815
+
3816
+ \newcommand{\upperscript}[1]{\raisebox{8pt}{\scriptsize #1}}
3817
+ \newcommand{\uupperscript}[2]{\raisebox{#2pt}{\scriptsize #1}}
3818
+ \newcommand{\vertbar}{\rule[-1ex]{0.5pt}{2.5ex}}
3819
+ \newcommand{\horzbar}{\rule[.5ex]{2.5ex}{0.5pt}}
3820
+
3821
+ \newcommand{\arabsqrt}[2]{\reflectbox{\(\sqrt[\reflectbox{\(#1\)}]{\reflectbox{\(#2\)}}\)}}
3822
+ \newcommand{\arabvec}[1]{\reflectbox{$\vec{\reflectbox{$#1$}}$}}
3823
+
3824
+ \newcommand{\arabexp}[1]{{}^{#1}\!\raisebox{-4.5pt}{\text{\diwani{ه}}}}
3825
+ \newcommand{\arablog}[2]{\left(\text{#2}\right)\!\prescript{}{\text{#1}}{\text{\diwani{لو}}}}
3826
+ \newcommand{\arabnlog}[1]{\left(\text{#1}\right)\!\prescript{}{\text{\diwani{ه}}}{\text{\diwani{لو}}}}
3827
+
3828
+ \newcommand{\arabcos}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{جتا}}}}
3829
+ \newcommand{\arabsin}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{جا}}}}
3830
+ \newcommand{\arabtan}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{ظا}}}}
3831
+ \newcommand{\arabcot}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{ظتا}}}}
3832
+ \newcommand{\arabsec}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قا}}}}
3833
+ \newcommand{\arabcsc}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قتا}}}}
3834
+
3835
+ \newcommand{\arabacos}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قجتا}}}}
3836
+ \newcommand{\arabasin}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قجا}}}}
3837
+ \newcommand{\arabatan}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قظا}}}}
3838
+ \newcommand{\arabacot}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{قظتا}}}}
3839
+ \newcommand{\arabasec}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{ققا}}}}
3840
+ \newcommand{\arabacsc}[1]{\left(#1\right)\!\!\raisebox{-2.5pt}{\text{\diwani{ققتا}}}}
3841
+
3842
+
3843
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3844
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3845
+ % summation
3846
+ \newcommand{\arablim}[2]{\underset{#2 \leftarrow #1}{\text{نـــــها}}}
3847
+ \newcommand{\arabsum}[2]{\underset{#1}{\overset{#2}{\text{مجـــ}}}}
3848
+ \newcommand{\arabprod}[2]{\underset{#1}{\overset{#2}{\text{جـــذ}}}}
3849
+ \newcommand{\arabint}[2]{\prescript{#2}{#1\!\!\!}\int}
3850
+
3851
+
3852
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3853
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3854
+ % we define this command to make it ease for change of notation later
3855
+ \newcommand{\ad}[0]{\text{ء}} % "ad" for arabic differentiation or derivative (ء" لإشتقاق")
3856
+ \newcommand{\arpi}[0]{\!\text{\diwani{ط}}}
3857
+
3858
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3859
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3860
+ % differentials
3861
+
3862
+ \newcommand{\arabdiff}[2]{\frac{#1\ad}{#2\ad}} % arabic differential
3863
+ \newcommand{\arabddiff}[2]{\frac{#1{}^{2}\ad}{{}^{2}#2\ad}} % arabic second differential
3864
+
3865
+ \newcommand{\arabode}[2][-5pt]{\stackrel{\raisebox{#1}{$\cdot$}}{\text{#2}}}
3866
+ \newcommand{\arabodde}[2][-5pt]{\stackrel{\raisebox{#1}{$\vcenter{\hbox{$\cdot\!\cdot$}}$}}{\text{#2}}}
3867
+ \newcommand{\araboddde}[2][-5pt]{\stackrel{\raisebox{#1}{$\vcenter{\hbox{$\cdot\!\cdot\!\cdot$}}$}}{\text{#2}}}
3868
+ \newcommand{\arabpde}[1]{\prescript{}{#1\!\!}{\nabla}} % arabic partial differential equation (PDE)
3869
+
3870
+ \newcommand{\arabprime}[0]{\reflectbox{$\prime$}\!} % arabic prime notation
3871
+ \newcommand{\arabpprime}[0]{\reflectbox{$\prime$}\reflectbox{$\prime$}\!} % arabic prime notation
3872
+ \newcommand{\arabppprime}[0]{\reflectbox{$\prime$}\reflectbox{$\prime$}\reflectbox{$\prime$}\!} % arabic prime notation
3873
+
3874
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3875
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3876
+ % probability
3877
+ \newcommand{\ap}[0]{\!\text{\diwani{حـ}}} % arabic Probability - used a lot so short form
3878
+ \newcommand{\arabExpct}[0]{\text{\diwani{توقـ}}} % arabic Expectation
3879
+ \newcommand{\arabVar}[0]{\!\text{\diwani{با}}} % arabic Variance
3880
+ \newcommand{\arabCov}[0]{\!\text{\diwani{ت}}} % arabic Covariance
3881
+
3882
+
3883
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3884
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3885
+ % custom commands specific to lesson
3886
+ \newcommand{\lagrange}[2]{\left(#2\right)\!\prescript{}{#1}{\text{\diwani{لا}}}}
3887
+ \newcommand{\xii}[0]{\left(\prescript{}{\text{يـ}}{\text{س}}\right)\!}
3888
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3889
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3890
+
3891
+
3892
+ \newcommand{\arsqrt}[2][]{\reflectbox{\(\sqrt[\reflectbox{\(#1\)}]{\reflectbox{\(#2\)}}\)}}
3893
+ \newcommand{\arexp}[0]{\!\raisebox{-4.5pt}{\text{\diwani{ه}}}}
3894
+ \newcommand{\arlog}[0]{\!\!\text{\diwani{لو}}}
3895
+ \newcommand{\arln}[0]{\!\!\prescript{}{\text{\diwani{ه}}}{\text{\diwani{لو}}}}
3896
+ \newcommand{\ardet}[0]{\!\!\text{\diwani{محدد}}}
3897
+
3898
+ \newcommand{\arsum}[0]{\text{مجـــ}}
3899
+ \newcommand{\arprod}[0]{\text{جـــذ}}
3900
+
3901
+ \newcommand{\arlim}[0]{\text{نـــــها}}
3902
+ \newcommand{\armax}[0]{\text{أكبر}}
3903
+ \newcommand{\armin}[0]{\text{أصغر}}
3904
+ \newcommand{\arsup}[0]{\text{أعلى}}
3905
+ \newcommand{\arinf}[0]{\text{أدنى}}
3906
+
3907
+ \newcommand{\arsin}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{جا}}}}
3908
+ \newcommand{\arcos}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{جتا}}}}
3909
+ \newcommand{\artan}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ظا}}}}
3910
+ \newcommand{\arcot}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ظتا}}}}
3911
+ \newcommand{\arsec}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قا}}}}
3912
+ \newcommand{\arcsc}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قتا}}}}
3913
+
3914
+ \newcommand{\arasin}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قجا}}}}
3915
+ \newcommand{\aracos}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قجتا}}}}
3916
+ \newcommand{\aratan}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قظا}}}}
3917
+ \newcommand{\aracot}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قظتا}}}}
3918
+ \newcommand{\arasec}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ققا}}}}
3919
+ \newcommand{\aracsc}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ققتا}}}}
3920
+
3921
+ \newcommand{\arsinh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{جزا}}}}
3922
+ \newcommand{\arcosh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{جتزا}}}}
3923
+ \newcommand{\artanh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ظزا}}}}
3924
+ \newcommand{\arcoth}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ظتزا}}}}
3925
+ \newcommand{\arsech}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قزا}}}}
3926
+ \newcommand{\arcsch}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قتزا}}}}
3927
+
3928
+ \newcommand{\arasinh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قجزا}}}}
3929
+ \newcommand{\aracosh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قجتزا}}}}
3930
+ \newcommand{\aratanh}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قظزا}}}}
3931
+ \newcommand{\aracoth}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{قظتزا}}}}
3932
+ \newcommand{\arasech}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ققزا}}}}
3933
+ \newcommand{\aracsch}[0]{\!\!\raisebox{-2.5pt}{\text{\diwani{ققتزا}}}}
3934
+
3935
+ \newcommand{\unit}[1]{\text{#1}}
3936
+ \newcommand{\idx}[1]{#1}
3937
+ \newcommand{\arbinom}[2]{\left(\begin{array}{c} #1 \\ #2 \end{array} \right)}
3938
+ `;
3939
+ }
3940
+ function getArabicXeLatexPreamble(digitsMapping = "arabicdigits") {
3941
+ return arabicXeLatexPreamblePkg() + arabicXeLatexPreambleFont(digitsMapping) + arabicXeLatexPreambleCmd();
3942
+ }
3448
3943
 
3449
3944
  // src/document2/exportLatex.ts
3450
3945
  function tokenLatex(token) {
3451
3946
  if (token.kind === "text") {
3452
3947
  return token.text;
3453
3948
  }
3949
+ if (token.kind === "cite") {
3950
+ return citeTokenLatex(token.keys);
3951
+ }
3454
3952
  if (!token.math || token.sourceOwner === "raw" || token.sourceOwner === "editor") {
3455
3953
  return token.source;
3456
3954
  }
@@ -3465,9 +3963,9 @@ function textBlockLatex(block) {
3465
3963
  function indent(value) {
3466
3964
  return value.split("\n").map((line) => ` ${line}`).join("\n");
3467
3965
  }
3468
- function listBlockLatex(block) {
3966
+ function listBlockLatex(block, references) {
3469
3967
  const items = block.items.map((item) => {
3470
- const nested = item.blocks.map((child) => "\n" + indent(blockLatex(child))).join("");
3968
+ const nested = item.blocks.map((child) => "\n" + indent(blockLatex(child, references))).join("");
3471
3969
  return ` \\item ${inlineFieldLatex(item.field)}${nested}`;
3472
3970
  }).join("\n");
3473
3971
  return `${block.command}
@@ -3487,12 +3985,12 @@ function imageOptionsLatex(block) {
3487
3985
  }
3488
3986
  return `[${entries.map(([key, value]) => `${key}=${value}`).join(",")}]`;
3489
3987
  }
3490
- function blockLatex(block) {
3988
+ function blockLatex(block, references) {
3491
3989
  if (block.kind === "textBlock") {
3492
3990
  return textBlockLatex(block);
3493
3991
  }
3494
3992
  if (block.kind === "list") {
3495
- return listBlockLatex(block);
3993
+ return listBlockLatex(block, references);
3496
3994
  }
3497
3995
  if (block.kind === "table") {
3498
3996
  return tableBlockLatex(block);
@@ -3500,10 +3998,29 @@ function blockLatex(block) {
3500
3998
  if (block.kind === "image") {
3501
3999
  return `${block.command}${imageOptionsLatex(block)}{${block.value}}`;
3502
4000
  }
4001
+ if (block.kind === "bibliography") {
4002
+ const width = String(Math.max(references.length, 9));
4003
+ const items = references.map((reference) => ` ${bibliographyEntryLatex(reference)}`).join("\n");
4004
+ return `${block.command}{${width}}
4005
+ ${items}
4006
+ ${block.closing}`;
4007
+ }
3503
4008
  return block.value;
3504
4009
  }
3505
- function document2Latex(document2) {
3506
- return document2.blocks.map((block) => blockLatex(block)).join("\n\n");
4010
+ function document2Latex(document2, options = {}) {
4011
+ const body = document2.blocks.map((block) => blockLatex(block, document2.references)).join("\n\n");
4012
+ const wrapDocument = options.wrapDocument !== false;
4013
+ if (!wrapDocument) {
4014
+ return body;
4015
+ }
4016
+ const preamble = getArabicXeLatexPreamble(options.digitsMapping ?? "arabicdigits");
4017
+ return `${preamble}
4018
+ \\begin{document}
4019
+
4020
+ ${body}
4021
+
4022
+ \\end{document}
4023
+ `;
3507
4024
  }
3508
4025
 
3509
4026
  // src/document2/history.ts
@@ -3541,16 +4058,24 @@ function document2HistoryCanRedo(stacks) {
3541
4058
 
3542
4059
  // src/document2/previewModel.ts
3543
4060
  function mathTex(token, equationSide) {
3544
- if (token.kind === "text") {
3545
- return token.text;
3546
- }
3547
4061
  return mathTokenSourceForSide(token, equationSide);
3548
4062
  }
3549
- function previewInlines(field, islands, output, equationSide) {
4063
+ function previewInlines(field, islands, output, equationSide, document2, previewOptions) {
3550
4064
  return field.tokens.map((token) => {
3551
4065
  if (token.kind === "text") {
3552
4066
  return { kind: "text", text: token.text };
3553
4067
  }
4068
+ if (token.kind === "cite") {
4069
+ return {
4070
+ kind: "cite",
4071
+ id: token.id,
4072
+ keys: [...token.keys],
4073
+ label: formatCiteLabel(token.keys, document2.references, {
4074
+ documentDirection: previewOptions.documentDirection,
4075
+ digitForm: previewOptions.digitForm
4076
+ })
4077
+ };
4078
+ }
3554
4079
  const island = {
3555
4080
  id: token.id,
3556
4081
  tex: mathTex(token, equationSide),
@@ -3562,21 +4087,22 @@ function previewInlines(field, islands, output, equationSide) {
3562
4087
  return { kind: "math", ...island };
3563
4088
  });
3564
4089
  }
3565
- function textBlockPreview(block, islands, output, equationSide) {
4090
+ function textBlockPreview(block, islands, output, equationSide, document2, previewOptions) {
4091
+ const inlines = previewInlines(block.field, islands, output, equationSide, document2, previewOptions);
3566
4092
  if (block.command === "\\section") {
3567
- return { kind: "heading", id: block.id, level: 1, inlines: previewInlines(block.field, islands, output, equationSide) };
4093
+ return { kind: "heading", id: block.id, level: 1, inlines };
3568
4094
  }
3569
4095
  if (block.command === "\\subsection") {
3570
- return { kind: "heading", id: block.id, level: 2, inlines: previewInlines(block.field, islands, output, equationSide) };
4096
+ return { kind: "heading", id: block.id, level: 2, inlines };
3571
4097
  }
3572
4098
  if (block.command === "\\subsubsection") {
3573
- return { kind: "heading", id: block.id, level: 3, inlines: previewInlines(block.field, islands, output, equationSide) };
4099
+ return { kind: "heading", id: block.id, level: 3, inlines };
3574
4100
  }
3575
- return { kind: "paragraph", id: block.id, inlines: previewInlines(block.field, islands, output, equationSide) };
4101
+ return { kind: "paragraph", id: block.id, inlines };
3576
4102
  }
3577
- function blockPreview(block, islands, output, equationSide) {
4103
+ function blockPreview(block, islands, output, equationSide, document2, previewOptions) {
3578
4104
  if (block.kind === "textBlock") {
3579
- return textBlockPreview(block, islands, output, equationSide);
4105
+ return textBlockPreview(block, islands, output, equationSide, document2, previewOptions);
3580
4106
  }
3581
4107
  if (block.kind === "list") {
3582
4108
  return {
@@ -3585,23 +4111,56 @@ function blockPreview(block, islands, output, equationSide) {
3585
4111
  ordered: block.command === "\\begin{enumerate}",
3586
4112
  items: block.items.map((item) => ({
3587
4113
  id: item.id,
3588
- inlines: previewInlines(item.field, islands, output, equationSide),
3589
- blocks: item.blocks.map((child) => blockPreview(child, islands, output, equationSide))
4114
+ inlines: previewInlines(item.field, islands, output, equationSide, document2, previewOptions),
4115
+ blocks: item.blocks.map((child) => blockPreview(child, islands, output, equationSide, document2, previewOptions))
3590
4116
  }))
3591
4117
  };
3592
4118
  }
3593
4119
  if (block.kind === "table") {
3594
- return { kind: "table", id: block.id, rows: block.rows.map((row) => row.map((cell) => previewInlines(cell, islands, output, equationSide))) };
4120
+ return {
4121
+ kind: "table",
4122
+ id: block.id,
4123
+ rows: block.rows.map((row) => row.map((cell) => previewInlines(cell, islands, output, equationSide, document2, previewOptions)))
4124
+ };
3595
4125
  }
3596
4126
  if (block.kind === "image") {
3597
- return { kind: "image", id: block.id, src: block.value, options: block.options };
4127
+ return {
4128
+ kind: "image",
4129
+ id: block.id,
4130
+ src: block.value,
4131
+ ...block.assetId !== void 0 ? { assetId: block.assetId } : {},
4132
+ options: block.options
4133
+ };
4134
+ }
4135
+ if (block.kind === "bibliography") {
4136
+ return {
4137
+ kind: "bibliography",
4138
+ id: block.id,
4139
+ items: document2.references.map((reference, index) => ({
4140
+ id: reference.id,
4141
+ numberLabel: formatBibliographyNumber(index + 1, {
4142
+ documentDirection: previewOptions.documentDirection,
4143
+ digitForm: previewOptions.digitForm
4144
+ }),
4145
+ key: reference.key,
4146
+ authors: reference.authors,
4147
+ title: reference.title,
4148
+ year: reference.year,
4149
+ url: reference.url,
4150
+ venue: reference.venue
4151
+ }))
4152
+ };
3598
4153
  }
3599
4154
  return { kind: "omit", id: block.id };
3600
4155
  }
3601
- function document2Preview(document2, output = "svg", equationSide = "arabic") {
4156
+ function document2Preview(document2, output = "svg", equationSide = "arabic", previewOptions = {}) {
3602
4157
  const mathIslands = [];
4158
+ const options = {
4159
+ documentDirection: previewOptions.documentDirection ?? "rtl",
4160
+ digitForm: previewOptions.digitForm ?? (previewOptions.documentDirection === "ltr" ? "western" : "arabicIndic")
4161
+ };
3603
4162
  return {
3604
- blocks: document2.blocks.map((block) => blockPreview(block, mathIslands, output, equationSide)),
4163
+ blocks: document2.blocks.map((block) => blockPreview(block, mathIslands, output, equationSide, document2, options)),
3605
4164
  mathIslands
3606
4165
  };
3607
4166
  }
@@ -3611,22 +4170,35 @@ function document2Preview(document2, output = "svg", equationSide = "arabic") {
3611
4170
  addDocument2ImageBlock,
3612
4171
  addDocument2ListBlock,
3613
4172
  addDocument2ListItem,
4173
+ addDocument2Reference,
3614
4174
  addDocument2TableBlock,
3615
4175
  addDocument2TextBlock,
4176
+ arabicXeLatexPreambleCmd,
4177
+ arabicXeLatexPreambleFont,
4178
+ arabicXeLatexPreamblePkg,
4179
+ bibliographyEntryLatex,
4180
+ citeTokenLatex,
3616
4181
  cloneDocument2Node,
3617
4182
  createDocument2History,
3618
4183
  createEmptyArabicEquationSession,
3619
4184
  createEmptyDocument2,
3620
4185
  createEmptyEquationSession,
4186
+ createEmptyReference2,
3621
4187
  createInlineField2,
4188
+ detectInlineSpans2,
3622
4189
  detectMathSpans2,
3623
4190
  document2HistoryCanRedo,
3624
4191
  document2HistoryCanUndo,
3625
4192
  document2Latex,
3626
4193
  document2Preview,
4194
+ ensureDocument2BibliographyBlock,
3627
4195
  findFirstInlineField,
4196
+ formatBibliographyNumber,
4197
+ formatCiteLabel,
3628
4198
  fromDocumentJson2,
4199
+ getArabicXeLatexPreamble,
3629
4200
  inlineFieldLatex,
4201
+ insertCiteTokenAtCaret,
3630
4202
  insertDocument2BlockAfter,
3631
4203
  insertMathToken,
3632
4204
  insertMathTokenAtCaret,
@@ -3638,14 +4210,24 @@ function document2Preview(document2, output = "svg", equationSide = "arabic") {
3638
4210
  mathTokenToArabicEditorSession,
3639
4211
  mathTokenToEditorSession,
3640
4212
  moveDocument2BlockById,
4213
+ moveDocument2Reference,
4214
+ parseCiteKeys,
3641
4215
  pushDocument2Snapshot,
4216
+ referenceFromJson,
4217
+ referenceNumberMap,
4218
+ removeCiteTokenById,
3642
4219
  removeDocument2BlockById,
3643
4220
  removeDocument2ListItem,
4221
+ removeDocument2Reference,
3644
4222
  removeMathTokenById,
3645
4223
  replaceMathTokenFromSession,
4224
+ resolveCiteNumbers,
3646
4225
  restoreDocument2Redo,
3647
4226
  restoreDocument2Undo,
4227
+ setDocument2References,
4228
+ updateCiteTokenKeys,
3648
4229
  updateDocument2ImageValue,
4230
+ updateDocument2Reference,
3649
4231
  updateTextToken
3650
4232
  });
3651
4233
  //# sourceMappingURL=document2.js.map