@drghaliasri/butex 5.0.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.
package/README.md CHANGED
@@ -253,7 +253,9 @@ const latex = document2Latex(documentNode);
253
253
  const preview = document2Preview(documentNode, 'svg');
254
254
  ```
255
255
 
256
- `document2Latex(doc)` emits a **complete Arabic XeLaTeX document** by default (preamble + `\begin{document}` + body + `\end{document}`). Pass `{ wrapDocument: false }` for body-only blocks. Optional `digitsMapping: 'arabicdigits' | 'digits'` controls eastern vs western digit font mapping in the preamble (default `'arabicdigits'`). See [`examples/example-latex-export.tex`](examples/example-latex-export.tex) for a full sample (regenerated by the wrap vitest). Hosts can also call `getArabicXeLatexPreamble()` alone.
256
+ `document2Latex(doc)` emits a **complete Arabic XeLaTeX document** by default (preamble + `\begin{document}` + body + `\end{document}`). Pass `{ wrapDocument: false }` for body-only blocks. Optional `digitsMapping: 'arabicdigits' | 'digits'` controls eastern vs western digit font mapping in the preamble (default `'arabicdigits'`). Pass `{ twocolumn: true }` for `\documentclass[12pt,a4paper,twocolumn]{article}`. See [`examples/example-latex-export.tex`](examples/example-latex-export.tex) for a full sample (regenerated by the wrap vitest). Hosts can also call `getArabicXeLatexPreamble()` alone.
257
+
258
+ Figures and tables always export as centered `figure` / `table` floats. Optional caption/label fields (checkbox-driven in the editor) emit `\caption` / `\label`. Display math stays `\[…\]` unless an equation label is enabled, then export uses `\begin{equation}…\label{…}\end{equation}`. Internal cross-refs use `\ref` / `\eqref` tokens (separate from bibliography `\cite`).
257
259
 
258
260
  V2 exports Arabic TeX by default for equations saved from the embedded editor. Imported raw-only math is preserved as raw source and marked non-editable until a structured equation object is attached.
259
261
 
@@ -334,7 +336,7 @@ export default function Page() {
334
336
  }
335
337
  ```
336
338
 
337
- Host apps still register BuTeX with MathJax before preview rendering. `uiLocale` selects Arabic (`"ar"`, the default) or English (`"en"`) document-editor chrome and is passed to the embedded equation editor. `documentDirection` independently controls prose inputs and preview flow without creating a second document tree. `equationSide` independently controls whether structured equations open, render, and save from the `"english"` or `"arabic"` side. Set `editableEquations={false}` to show math islands without equation insertion, deletion, or editor access. Set `previewOnly={true}` to render only the read-only document preview with no toolbar, editor panel, or equation drawer. Optional `\includegraphics` `asset_id` is preserved on import; pass `resolveImageUrl={({ assetId, value }) => …})` so preview can load S3/CDN/local assets while plain `value` URLs keep working without a resolver. Document JSON may include a root `references` catalog (`key`, `authors`, `title`, `year`, `url`, `venue`) and `\cite{key1,key2}` spans in text values; the editor shows numeric cite chips and a bibliography block. RTL preview/chips render reversed labels such as `[٣،٢،١]` (Arabic comma); LTR stays `[1, 2, 3]`. Pass `digitForm` (`western` / `arabicIndic` / `persianIndic`, defaulting from `documentDirection`) or use the toolbar digit control. LaTeX export keeps logical `\cite{…}` key order for XeLaTeX; digit shaping and bidi display in PDF belong in the host preamble (`bidi`/polyglossia + font `Mapping`, see `references/commands.py`). Range compression (`[3–7]`) is not implemented yet. Raw-only equations keep their original source because the browser does not parse raw LaTeX into equation ASTs. Document editor v2 defaults to **`tex-svg.js`**; use `tex-chtml.js` only if you pass `mathOutput="chtml"`.
339
+ Host apps still register BuTeX with MathJax before preview rendering. `uiLocale` selects Arabic (`"ar"`, the default) or English (`"en"`) document-editor chrome and is passed to the embedded equation editor. `documentDirection` independently controls prose inputs and preview flow without creating a second document tree. `equationSide` independently controls whether structured equations open, render, and save from the `"english"` or `"arabic"` side. Set `editableEquations={false}` to show math islands without equation insertion, deletion, or editor access. Set `previewOnly={true}` to render only the read-only document preview with no toolbar, editor panel, or equation drawer. Optional `\includegraphics` `asset_id` is preserved on import; pass `resolveImageUrl={({ assetId, value }) => …})` so preview can load S3/CDN/local assets while plain `value` URLs keep working without a resolver. Document JSON may include root `meta` (`title`, `authors`, structured Hijri `date` `{ day, month, year }` with Arabic month names such as `"محرم"`, `abstract`) plus a `references` catalog (`key`, `authors`, `title`, `year`, `url`, `venue`) and `\cite{key1,key2}` spans in text values. Pass `documentMeta` to seed missing meta fields from the host; JSON keys win when present. The editor always centers a fixed basmala line before the title block and a closing ḥamdala after the body (preview + LaTeX). Hijri date uses day/month/year dropdowns (no calendar conversion; default year 1448). The editor shows numeric cite chips and a bibliography block. RTL preview/chips render reversed labels such as `[٣،٢،١]` (Arabic comma); LTR stays `[1, 2, 3]`. Pass `digitForm` (`western` / `arabicIndic` / `persianIndic`, defaulting from `documentDirection`) or use the toolbar digit control. LaTeX export keeps logical `\cite{…}` key order for XeLaTeX; digit shaping and bidi display in PDF belong in the host preamble (`bidi`/polyglossia + font `Mapping`, see `references/commands.py`). Range compression (`[3–7]`) is not implemented yet. Raw-only equations keep their original source because the browser does not parse raw LaTeX into equation ASTs. Document editor v2 defaults to **`tex-svg.js`**; use `tex-chtml.js` only if you pass `mathOutput="chtml"`.
338
340
 
339
341
  ### Styling/theming contract
340
342
 
@@ -146,8 +146,21 @@ type Reference2Json = {
146
146
  url?: string;
147
147
  venue?: string;
148
148
  };
149
+ type HijriMonthId = 'محرم' | 'صفر' | 'ربيع الأول' | 'ربيع الآخر' | 'جمادى الأولى' | 'جمادى الآخرة' | 'رجب' | 'شعبان' | 'رمضان' | 'شوال' | 'ذو القعدة' | 'ذو الحجة';
150
+ type Document2HijriDate = {
151
+ day: number;
152
+ month: HijriMonthId;
153
+ year: number;
154
+ };
155
+ type Document2Meta = {
156
+ title: string;
157
+ authors: string;
158
+ date: Document2HijriDate;
159
+ abstract: string;
160
+ };
149
161
  type Document2Json = {
150
162
  node_type: 'DocumentObject';
163
+ meta?: Document2Meta;
151
164
  references?: Reference2Json[];
152
165
  blocks: Document2BlockJson[];
153
166
  };
@@ -162,6 +175,11 @@ type Document2BlockJson = {
162
175
  items?: Document2ListItemJson[];
163
176
  rows?: string[][];
164
177
  columns?: string;
178
+ caption?: string;
179
+ label?: string;
180
+ caption_enabled?: boolean;
181
+ label_enabled?: boolean;
182
+ centered?: boolean;
165
183
  };
166
184
  type Document2ListItemJson = {
167
185
  value: string;
@@ -199,13 +217,22 @@ type MathToken2 = {
199
217
  editable: boolean;
200
218
  reason?: string;
201
219
  sourceOwner: 'imported-structured' | 'raw' | 'editor';
220
+ /** When true on display math, export as equation env with \\label. */
221
+ labelEnabled?: boolean;
222
+ label?: string;
202
223
  };
203
224
  type CiteToken2 = {
204
225
  id: string;
205
226
  kind: 'cite';
206
227
  keys: string[];
207
228
  };
208
- type InlineToken2 = TextToken2 | MathToken2 | CiteToken2;
229
+ type RefToken2 = {
230
+ id: string;
231
+ kind: 'ref';
232
+ keys: string[];
233
+ refCommand: 'ref' | 'eqref';
234
+ };
235
+ type InlineToken2 = TextToken2 | MathToken2 | CiteToken2 | RefToken2;
209
236
  type InlineField2 = {
210
237
  id: string;
211
238
  tokens: InlineToken2[];
@@ -215,6 +242,8 @@ type TextBlock2 = {
215
242
  kind: 'textBlock';
216
243
  command: '\\section' | '\\subsection' | '\\subsubsection' | '\\paragraph';
217
244
  field: InlineField2;
245
+ /** When true on \\paragraph, center in preview and LaTeX export. */
246
+ centered?: boolean;
218
247
  };
219
248
  type ListItem2 = {
220
249
  id: string;
@@ -228,6 +257,13 @@ type ListBlock2 = {
228
257
  closing: '\\end{itemize}' | '\\end{enumerate}';
229
258
  items: ListItem2[];
230
259
  };
260
+ type FloatMeta2 = {
261
+ centered: boolean;
262
+ captionEnabled: boolean;
263
+ caption: string;
264
+ labelEnabled: boolean;
265
+ label: string;
266
+ };
231
267
  type TableBlock2 = {
232
268
  id: string;
233
269
  kind: 'table';
@@ -235,7 +271,7 @@ type TableBlock2 = {
235
271
  closing: '\\end{tabular}';
236
272
  columns: string;
237
273
  rows: InlineField2[][];
238
- };
274
+ } & FloatMeta2;
239
275
  type ImageBlock2 = {
240
276
  id: string;
241
277
  kind: 'image';
@@ -244,7 +280,7 @@ type ImageBlock2 = {
244
280
  /** Host asset identity from wire `asset_id`; preserved across value edits. */
245
281
  assetId?: string;
246
282
  options: Record<string, string>;
247
- };
283
+ } & FloatMeta2;
248
284
  type BibliographyBlock2 = {
249
285
  id: string;
250
286
  kind: 'bibliography';
@@ -260,6 +296,7 @@ type RawBlock2 = {
260
296
  type Document2Block = TextBlock2 | ListBlock2 | TableBlock2 | ImageBlock2 | BibliographyBlock2 | RawBlock2;
261
297
  type Document2Node = {
262
298
  nodeType: 'DocumentObject';
299
+ meta: Document2Meta;
263
300
  references: Reference2[];
264
301
  blocks: Document2Block[];
265
302
  diagnostics: Document2Diagnostic[];
@@ -283,9 +320,17 @@ type DetectedCiteSpan2 = {
283
320
  source: string;
284
321
  keys: string[];
285
322
  };
323
+ type DetectedRefSpan2 = {
324
+ kind: 'ref';
325
+ start: number;
326
+ end: number;
327
+ source: string;
328
+ keys: string[];
329
+ refCommand: 'ref' | 'eqref';
330
+ };
286
331
  type DetectedInlineSpan2 = ({
287
332
  kind: 'math';
288
- } & DetectedMathSpan2) | DetectedCiteSpan2;
333
+ } & DetectedMathSpan2) | DetectedCiteSpan2 | DetectedRefSpan2;
289
334
  type PreviewInline2 = {
290
335
  kind: 'text';
291
336
  text: string;
@@ -301,8 +346,34 @@ type PreviewInline2 = {
301
346
  id: string;
302
347
  keys: string[];
303
348
  label: string;
349
+ } | {
350
+ kind: 'ref';
351
+ id: string;
352
+ keys: string[];
353
+ refCommand: 'ref' | 'eqref';
354
+ label: string;
304
355
  };
305
356
  type PreviewBlock2 = {
357
+ kind: 'basmala';
358
+ id: string;
359
+ text: string;
360
+ tex: string;
361
+ } | {
362
+ kind: 'titleBlock';
363
+ id: string;
364
+ title?: string;
365
+ authors?: string;
366
+ date?: string;
367
+ } | {
368
+ kind: 'abstract';
369
+ id: string;
370
+ text: string;
371
+ } | {
372
+ kind: 'closing';
373
+ id: string;
374
+ text: string;
375
+ tex: string;
376
+ } | {
306
377
  kind: 'heading';
307
378
  id: string;
308
379
  level: 1 | 2 | 3;
@@ -311,6 +382,7 @@ type PreviewBlock2 = {
311
382
  kind: 'paragraph';
312
383
  id: string;
313
384
  inlines: PreviewInline2[];
385
+ centered?: boolean;
314
386
  } | {
315
387
  kind: 'list';
316
388
  id: string;
@@ -324,12 +396,18 @@ type PreviewBlock2 = {
324
396
  kind: 'table';
325
397
  id: string;
326
398
  rows: PreviewInline2[][][];
399
+ caption?: string;
400
+ label?: string;
401
+ numberLabel?: string;
327
402
  } | {
328
403
  kind: 'image';
329
404
  id: string;
330
405
  src: string;
331
406
  assetId?: string;
332
407
  options: Record<string, string>;
408
+ caption?: string;
409
+ label?: string;
410
+ numberLabel?: string;
333
411
  } | {
334
412
  kind: 'bibliography';
335
413
  id: string;
@@ -365,21 +443,117 @@ type FormatCiteLabelOptions = {
365
443
  digitForm?: DigitFormId;
366
444
  };
367
445
 
446
+ type Document2LabelKind = 'fig' | 'tab' | 'eq';
447
+ type Document2LabelEntry = {
448
+ key: string;
449
+ kind: Document2LabelKind;
450
+ caption: string;
451
+ /** Block id for fig/tab, or math token id for eq. */
452
+ ownerId: string;
453
+ number: number;
454
+ };
455
+ type FloatMetaPatch = {
456
+ centered?: boolean;
457
+ captionEnabled?: boolean;
458
+ caption?: string;
459
+ labelEnabled?: boolean;
460
+ label?: string;
461
+ };
462
+ declare function defaultFloatMeta(): {
463
+ centered: true;
464
+ captionEnabled: false;
465
+ caption: '';
466
+ labelEnabled: false;
467
+ label: '';
468
+ };
469
+ declare function parseFloatMetaFromJson(json: {
470
+ caption?: string;
471
+ label?: string;
472
+ caption_enabled?: boolean;
473
+ label_enabled?: boolean;
474
+ centered?: boolean;
475
+ }): {
476
+ centered: boolean;
477
+ captionEnabled: boolean;
478
+ caption: string;
479
+ labelEnabled: boolean;
480
+ label: string;
481
+ };
482
+ declare function parseRefKeys(source: string): {
483
+ keys: string[];
484
+ refCommand: 'ref' | 'eqref';
485
+ };
486
+ declare function refTokenLatex(keys: string[], refCommand: 'ref' | 'eqref'): string;
487
+ /** Collect enabled labels in document order, numbering per kind. */
488
+ declare function collectDocument2Labels(document: Document2Node): Document2LabelEntry[];
489
+ declare function labelNumberMap(document: Document2Node): Map<string, {
490
+ kind: Document2LabelKind;
491
+ number: number;
492
+ }>;
493
+ declare function formatRefLabel(keys: string[], document: Document2Node, refCommand: 'ref' | 'eqref', options?: FormatCiteLabelOptions): string;
494
+ declare function stripDisplayMathDelimiters(source: string): string;
495
+ declare function applyFloatMetaPatch<T extends ImageBlock2 | TableBlock2>(block: T, patch: FloatMetaPatch): void;
496
+
497
+ type ButexUiLocale = 'ar' | 'en';
498
+
499
+ declare const 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";
500
+ declare const 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";
501
+ /** Display-math body using BuTeX Diwani (for MathJax preview islands). */
502
+ declare function butexDiwaniDisplayTex(text: string): string;
503
+ /** Full display equation for XeLaTeX export. */
504
+ declare function butexDiwaniDisplayLatex(text: string): string;
505
+ declare const HIJRI_YEAR_MIN = 1400;
506
+ declare const HIJRI_YEAR_MAX = 1500;
507
+ declare const HIJRI_MONTH_IDS: HijriMonthId[];
508
+ declare const DEFAULT_HIJRI_DATE: Document2HijriDate;
509
+ declare function hijriMonthLabel(month: HijriMonthId, locale?: ButexUiLocale): string;
510
+ declare function emptyDocument2Meta(): Document2Meta;
511
+ declare function normalizeDocument2HijriDate(value: unknown): Document2HijriDate;
512
+ declare function normalizeDocument2Meta(value: unknown): Document2Meta;
513
+ type Document2MetaProp = Partial<Omit<Document2Meta, 'date'>> & {
514
+ date?: Partial<Document2HijriDate>;
515
+ };
516
+ /** Prop fills gaps; JSON wins only when the key is present on the JSON object. */
517
+ declare function mergeDocument2Meta(fromJson: unknown, fromProp?: Document2MetaProp): Document2Meta;
518
+ /** For live Document2Node meta: prop fills empty title/authors/abstract; date patch merges. */
519
+ declare function fillDocument2MetaGaps(current: Document2Meta, fromProp?: Document2MetaProp): Document2Meta;
520
+ declare function document2HasMaketitle(meta: Document2Meta): boolean;
521
+ declare function document2HasAbstract(meta: Document2Meta): boolean;
522
+ declare function document2HasTitleStack(meta: Document2Meta): boolean;
523
+ type FormatHijriDateOptions = {
524
+ locale?: ButexUiLocale;
525
+ digitForm?: DigitFormId;
526
+ };
527
+ declare function formatHijriDate(date: Document2HijriDate, options?: FormatHijriDateOptions | ButexUiLocale): string;
528
+ declare function cloneDocument2Meta(meta: Document2Meta): Document2Meta;
529
+
368
530
  declare function findFirstInlineField(document: Document2Node): InlineField2 | null;
369
531
  declare function updateTextToken(document: Document2Node, fieldId: string, tokenId: string, text: string): Document2Node;
370
532
  declare function cloneDocument2Node(document: Document2Node): Document2Node;
371
533
  declare function insertDocument2BlockAfter(document: Document2Node, afterBlockId: string | null | undefined, block: Document2Block): Document2Node;
372
534
  declare function moveDocument2BlockById(document: Document2Node, blockId: string, direction: -1 | 1): Document2Node;
535
+ declare function moveDocument2BlockRange(document: Document2Node, from: number, to: number, direction: -1 | 1): Document2Node;
536
+ declare function removeDocument2BlockRange(document: Document2Node, from: number, to: number): Document2Node;
373
537
  declare function removeMathTokenById(document: Document2Node, tokenId: string): Document2Node;
374
538
  declare function insertMathTokenAtCaret(document: Document2Node, fieldId: string, textTokenId: string | null, caretOffset: number, session: EditorSession, opening?: string, closing?: string, side?: EditorSide): Document2Node;
375
539
  declare function insertMathToken(document: Document2Node, fieldId: string, insertIndex: number, session: EditorSession, opening?: string, closing?: string, side?: EditorSide): Document2Node;
376
540
  declare function replaceMathTokenFromSession(document: Document2Node, tokenId: string, session: EditorSession, opening?: string, closing?: string, side?: EditorSide): Document2Node;
377
541
  declare function addDocument2TextBlock(document: Document2Node, command?: '\\section' | '\\subsection' | '\\subsubsection' | '\\paragraph', afterBlockId?: string | null): Document2Node;
542
+ declare function updateDocument2TextBlockCentered(document: Document2Node, blockId: string, centered: boolean): Document2Node;
378
543
  declare function removeDocument2BlockById(document: Document2Node, blockId: string): Document2Node;
379
544
  declare function addDocument2ListBlock(document: Document2Node, ordered: boolean, afterBlockId?: string | null): Document2Node;
380
545
  declare function addDocument2TableBlock(document: Document2Node, columns?: string, rowCount?: number, colCount?: number, afterBlockId?: string | null): Document2Node;
381
546
  declare function addDocument2ImageBlock(document: Document2Node, src?: string, afterBlockId?: string | null): Document2Node;
382
547
  declare function updateDocument2ImageValue(document: Document2Node, blockId: string, value: string): Document2Node;
548
+ declare function updateDocument2ImageMeta(document: Document2Node, blockId: string, patch: FloatMetaPatch): Document2Node;
549
+ declare function updateDocument2TableMeta(document: Document2Node, blockId: string, patch: FloatMetaPatch): Document2Node;
550
+ declare function updateMathTokenLabel(document: Document2Node, tokenId: string, patch: {
551
+ labelEnabled?: boolean;
552
+ label?: string;
553
+ }): Document2Node;
554
+ declare function insertRefTokenAtCaret(document: Document2Node, fieldId: string, textTokenId: string | null, caretOffset: number, keys: string[], refCommand?: 'ref' | 'eqref'): Document2Node;
555
+ declare function updateRefTokenKeys(document: Document2Node, tokenId: string, keys: string[], refCommand?: 'ref' | 'eqref'): Document2Node;
556
+ declare function removeRefTokenById(document: Document2Node, tokenId: string): Document2Node;
383
557
  declare function addDocument2ListItem(document: Document2Node, listBlockId: string): Document2Node;
384
558
  declare function removeDocument2ListItem(document: Document2Node, listBlockId: string, itemId: string): Document2Node;
385
559
  declare function insertCiteTokenAtCaret(document: Document2Node, fieldId: string, textTokenId: string | null, caretOffset: number, keys: string[]): Document2Node;
@@ -391,6 +565,7 @@ declare function updateDocument2Reference(document: Document2Node, referenceId:
391
565
  declare function removeDocument2Reference(document: Document2Node, referenceId: string): Document2Node;
392
566
  declare function moveDocument2Reference(document: Document2Node, referenceId: string, direction: -1 | 1): Document2Node;
393
567
  declare function setDocument2References(document: Document2Node, references: Reference2[]): Document2Node;
568
+ declare function updateDocument2Meta(document: Document2Node, patch: Document2MetaProp): Document2Node;
394
569
 
395
570
  declare function referenceNumberMap(references: Array<Pick<Reference2, 'key'>>): Map<string, number>;
396
571
  declare function resolveCiteNumbers(keys: string[], references: Array<Pick<Reference2, 'key'>>): Array<number | null>;
@@ -404,10 +579,15 @@ declare function bibliographyEntryLatex(reference: Reference2): string;
404
579
 
405
580
  /** Arabic XeLaTeX preamble fragments for full-document export. */
406
581
  type ArabicDigitsMapping = 'arabicdigits' | 'digits';
407
- declare function arabicXeLatexPreamblePkg(): string;
582
+ type ArabicXeLatexPreambleOptions = {
583
+ digitsMapping?: ArabicDigitsMapping;
584
+ /** When true, add the article class twocolumn option. Default false. */
585
+ twocolumn?: boolean;
586
+ };
587
+ declare function arabicXeLatexPreamblePkg(twocolumn?: boolean): string;
408
588
  declare function arabicXeLatexPreambleFont(digitsMapping?: ArabicDigitsMapping): string;
409
589
  declare function arabicXeLatexPreambleCmd(): string;
410
- declare function getArabicXeLatexPreamble(digitsMapping?: ArabicDigitsMapping): string;
590
+ declare function getArabicXeLatexPreamble(digitsMappingOrOptions?: ArabicDigitsMapping | ArabicXeLatexPreambleOptions): string;
411
591
 
412
592
  type Document2LatexOptions = {
413
593
  /**
@@ -418,6 +598,8 @@ type Document2LatexOptions = {
418
598
  wrapDocument?: boolean;
419
599
  /** Font digit Mapping when wrapping. Default 'arabicdigits'. */
420
600
  digitsMapping?: ArabicDigitsMapping;
601
+ /** When true, use article class option twocolumn. Default false. */
602
+ twocolumn?: boolean;
421
603
  };
422
604
  declare function inlineFieldLatex(field: InlineField2): string;
423
605
  declare function document2Latex(document: Document2Node, options?: Document2LatexOptions): string;
@@ -435,13 +617,29 @@ declare function restoreDocument2Redo(stacks: Document2HistoryStacks, documentNo
435
617
  declare function document2HistoryCanUndo(stacks: Document2HistoryStacks): boolean;
436
618
  declare function document2HistoryCanRedo(stacks: Document2HistoryStacks): boolean;
437
619
 
620
+ type BlockSelectionRange = {
621
+ from: number;
622
+ to: number;
623
+ };
624
+ type BlockSelectionState = {
625
+ selection: BlockSelectionRange | null;
626
+ anchor: number | null;
627
+ };
628
+ declare function emptyBlockSelection(): BlockSelectionState;
629
+ declare function normalizeBlockSelection(selection: BlockSelectionRange | null, blockCount: number): BlockSelectionRange | null;
630
+ /** Checkbox click without Shift */
631
+ declare function toggleBlockInSelection(state: BlockSelectionState, index: number, blockCount: number): BlockSelectionState;
632
+ /** Shift+click on checkbox or header label */
633
+ declare function extendBlockSelectionFromAnchor(state: BlockSelectionState, index: number, blockCount: number): BlockSelectionState;
634
+ declare function remapSelectionAfterRangeMove(selection: BlockSelectionRange, direction: -1 | 1): BlockSelectionRange;
635
+
438
636
  declare function createInlineField2(value?: string, mathObjects?: MathObject2Json[], options?: ImportDocument2Options, path?: string, diagnostics?: Document2Diagnostic[]): InlineField2;
439
637
  declare function fromDocumentJson2(json: unknown, options?: ImportDocument2Options): Document2Node;
440
638
  declare function createEmptyDocument2(): Document2Node;
441
639
 
442
640
  /** Math-only spans (used for math_objects alignment counts). */
443
641
  declare function detectMathSpans2(value: string): DetectedMathSpan2[];
444
- /** Left-to-right math + \\cite spans without overlap. */
642
+ /** Left-to-right math + \\cite + \\ref/\\eqref spans without overlap. */
445
643
  declare function detectInlineSpans2(value: string): DetectedInlineSpan2[];
446
644
 
447
645
  type Document2MathBridgeResult = {
@@ -464,7 +662,8 @@ declare function mathTokenSourceForSide(token: MathToken2, side: EditorSide): st
464
662
  type Document2PreviewOptions = {
465
663
  documentDirection?: Document2Direction;
466
664
  digitForm?: DigitFormId;
665
+ uiLocale?: ButexUiLocale;
467
666
  };
468
667
  declare function document2Preview(document: Document2Node, output?: Document2MathOutput, equationSide?: EditorSide, previewOptions?: Document2PreviewOptions): Document2Preview;
469
668
 
470
- export { type ArabicDigitsMapping, type BibliographyBlock2, type CiteToken2, DEFAULT_DOCUMENT2_HISTORY_MAX_DEPTH, type Document2Block, type Document2BlockJson, type Document2Diagnostic, type Document2Direction, type Document2HistoryStacks, type Document2Json, type Document2LatexOptions, type Document2MathOutput, type Document2Node, type Document2PreviewOptions, type FormatCiteLabelOptions, type ImageBlock2, type ImportDocument2Options, type InlineField2, type InlineToken2, type ListBlock2, type MathIsland2, type MathObject2Json, type MathToken2, type PreviewBlock2, type PreviewInline2, type RawBlock2, type Reference2, type Reference2Json, type TableBlock2, type TextBlock2, type TextToken2, addDocument2ImageBlock, addDocument2ListBlock, addDocument2ListItem, addDocument2Reference, addDocument2TableBlock, addDocument2TextBlock, arabicXeLatexPreambleCmd, arabicXeLatexPreambleFont, arabicXeLatexPreamblePkg, bibliographyEntryLatex, citeTokenLatex, cloneDocument2Node, createDocument2History, createEmptyArabicEquationSession, createEmptyDocument2, createEmptyEquationSession, createEmptyReference2, createInlineField2, detectInlineSpans2, detectMathSpans2, document2HistoryCanRedo, document2HistoryCanUndo, document2Latex, document2Preview, ensureDocument2BibliographyBlock, findFirstInlineField, formatBibliographyNumber, formatCiteLabel, fromDocumentJson2, getArabicXeLatexPreamble, inlineFieldLatex, insertCiteTokenAtCaret, insertDocument2BlockAfter, insertMathToken, insertMathTokenAtCaret, mathNodeFromArabicSession, mathNodeFromSession, mathSourceFromArabicSession, mathSourceFromSession, mathTokenSourceForSide, mathTokenToArabicEditorSession, mathTokenToEditorSession, moveDocument2BlockById, moveDocument2Reference, parseCiteKeys, pushDocument2Snapshot, referenceFromJson, referenceNumberMap, removeCiteTokenById, removeDocument2BlockById, removeDocument2ListItem, removeDocument2Reference, removeMathTokenById, replaceMathTokenFromSession, resolveCiteNumbers, restoreDocument2Redo, restoreDocument2Undo, setDocument2References, updateCiteTokenKeys, updateDocument2ImageValue, updateDocument2Reference, updateTextToken };
669
+ export { type ArabicDigitsMapping, type ArabicXeLatexPreambleOptions, BUTEX_BASMALA, BUTEX_CLOSING_HAMDALA, type BibliographyBlock2, type BlockSelectionRange, type BlockSelectionState, type CiteToken2, DEFAULT_DOCUMENT2_HISTORY_MAX_DEPTH, DEFAULT_HIJRI_DATE, type Document2Block, type Document2BlockJson, type Document2Diagnostic, type Document2Direction, type Document2HijriDate, type Document2HistoryStacks, type Document2Json, type Document2LabelEntry, type Document2LabelKind, type Document2LatexOptions, type Document2MathOutput, type Document2Meta, type Document2MetaProp, type Document2Node, type Document2Preview, type Document2PreviewOptions, type FloatMeta2, type FloatMetaPatch, type FormatCiteLabelOptions, HIJRI_MONTH_IDS, HIJRI_YEAR_MAX, HIJRI_YEAR_MIN, type HijriMonthId, type ImageBlock2, type ImportDocument2Options, type InlineField2, type InlineToken2, type ListBlock2, type MathIsland2, type MathObject2Json, type MathToken2, type PreviewBlock2, type PreviewInline2, type RawBlock2, type RefToken2, type Reference2, type Reference2Json, type TableBlock2, type TextBlock2, type TextToken2, addDocument2ImageBlock, addDocument2ListBlock, addDocument2ListItem, addDocument2Reference, addDocument2TableBlock, addDocument2TextBlock, applyFloatMetaPatch, arabicXeLatexPreambleCmd, arabicXeLatexPreambleFont, arabicXeLatexPreamblePkg, bibliographyEntryLatex, butexDiwaniDisplayLatex, butexDiwaniDisplayTex, citeTokenLatex, cloneDocument2Meta, cloneDocument2Node, collectDocument2Labels, createDocument2History, createEmptyArabicEquationSession, createEmptyDocument2, createEmptyEquationSession, createEmptyReference2, createInlineField2, defaultFloatMeta, detectInlineSpans2, detectMathSpans2, document2HasAbstract, document2HasMaketitle, document2HasTitleStack, document2HistoryCanRedo, document2HistoryCanUndo, document2Latex, document2Preview, emptyBlockSelection, emptyDocument2Meta, ensureDocument2BibliographyBlock, extendBlockSelectionFromAnchor, fillDocument2MetaGaps, findFirstInlineField, formatBibliographyNumber, formatCiteLabel, formatHijriDate, formatRefLabel, fromDocumentJson2, getArabicXeLatexPreamble, hijriMonthLabel, inlineFieldLatex, insertCiteTokenAtCaret, insertDocument2BlockAfter, insertMathToken, insertMathTokenAtCaret, insertRefTokenAtCaret, labelNumberMap, mathNodeFromArabicSession, mathNodeFromSession, mathSourceFromArabicSession, mathSourceFromSession, mathTokenSourceForSide, mathTokenToArabicEditorSession, mathTokenToEditorSession, mergeDocument2Meta, moveDocument2BlockById, moveDocument2BlockRange, moveDocument2Reference, normalizeBlockSelection, normalizeDocument2HijriDate, normalizeDocument2Meta, parseCiteKeys, parseFloatMetaFromJson, parseRefKeys, pushDocument2Snapshot, refTokenLatex, referenceFromJson, referenceNumberMap, remapSelectionAfterRangeMove, removeCiteTokenById, removeDocument2BlockById, removeDocument2BlockRange, removeDocument2ListItem, removeDocument2Reference, removeMathTokenById, removeRefTokenById, replaceMathTokenFromSession, resolveCiteNumbers, restoreDocument2Redo, restoreDocument2Undo, setDocument2References, stripDisplayMathDelimiters, toggleBlockInSelection, updateCiteTokenKeys, updateDocument2ImageMeta, updateDocument2ImageValue, updateDocument2Meta, updateDocument2Reference, updateDocument2TableMeta, updateDocument2TextBlockCentered, updateMathTokenLabel, updateRefTokenKeys, updateTextToken };