@drghaliasri/butex 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -231,6 +231,60 @@ const preview = document2Preview(documentNode, 'svg');
231
231
 
232
232
  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.
233
233
 
234
+ ### Document JSON contract (`value` + `math_objects`)
235
+
236
+ Both document layers import the same shape. A text field holds `value` (the full string, **with math delimiters kept in place**) and an optional parallel `math_objects` array that supplies the structured equation AST for each math span found in that string.
237
+
238
+ Rules:
239
+
240
+ - **Detect, then align.** The importer scans `value` for delimiters (`$…$`, `\(…\)`, `\[…\]`, `$$…$$`, and math environments) and binds each detected span to `math_objects` **in reading order (left-to-right)**.
241
+ - **Count and order must match.** Extra or missing entries produce a diagnostic; the browser never silently remaps. `math_mode`/`closing` on each `MathObject` must match the delimiter in `value`.
242
+ - **Per field, not per document.** Each paragraph, heading, and list `item` carries its own `math_objects`.
243
+ - **Tables are the exception:** one flat `math_objects` array lives on the `\begin{tabular}` block and is consumed **row-major** across all cells (each cell takes as many entries as it has spans).
244
+ - **Missing `math_objects`** → the span renders as a non-editable raw math chip from its delimited source.
245
+ - The browser **does not** parse equation LaTeX bodies into `ChainClass`; structured chains come from `math_objects` (import) or the equation editor (GUI).
246
+
247
+ Paragraph with one inline span:
248
+
249
+ ```json
250
+ {
251
+ "command": "\\paragraph",
252
+ "value": "لدينا $x^2$ ثابت.",
253
+ "math_objects": [
254
+ { "node_type": "MathObject", "math_mode": "$",
255
+ "lines": [{ "node_type": "ChainClass", "chain": [] }], "closing": "$" }
256
+ ]
257
+ }
258
+ ```
259
+
260
+ List item with a display span (`math_mode`/`closing` match the delimiter in `value`):
261
+
262
+ ```json
263
+ {
264
+ "value": "الحل \\[a+b\\]",
265
+ "math_objects": [
266
+ { "node_type": "MathObject", "math_mode": "\\[",
267
+ "lines": [{ "node_type": "ChainClass", "chain": [] }], "closing": "\\]" }
268
+ ]
269
+ }
270
+ ```
271
+
272
+ Table: one flat array, consumed row-major (here `$x$`, then `$y$`):
273
+
274
+ ```json
275
+ {
276
+ "command": "\\begin{tabular}",
277
+ "columns": "cc",
278
+ "rows": [["الرمز $x$", "القيمة"], ["الرمز $y$", "القيمة"]],
279
+ "math_objects": [
280
+ { "node_type": "MathObject", "math_mode": "$",
281
+ "lines": [{ "node_type": "ChainClass", "chain": [] }], "closing": "$" },
282
+ { "node_type": "MathObject", "math_mode": "$",
283
+ "lines": [{ "node_type": "ChainClass", "chain": [] }], "closing": "$" }
284
+ ]
285
+ }
286
+ ```
287
+
234
288
  ### Document React widget v2 (`butex/react-document2`)
235
289
 
236
290
  Use this entry for the new document editor integration. It opens embedded `<ButexEditor />` sessions in Arabic/RTL mode by default and renders document preview math islands with MathJax **SVG** by default (`mathOutput` defaults to `'svg'`; pass `mathOutput="chtml"` only if the host loads `tex-chtml.js`).
@@ -254,7 +308,7 @@ export default function Page() {
254
308
  }
255
309
  ```
256
310
 
257
- 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. 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"`.
311
+ 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. 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"`.
258
312
 
259
313
  ### Styling/theming contract
260
314
 
@@ -285,6 +285,8 @@ type ButexDocumentEditor2Props = {
285
285
  documentDirection?: 'rtl' | 'ltr';
286
286
  equationSide?: EditorSide;
287
287
  editableEquations?: boolean;
288
+ /** When true, render only the read-only document preview (no toolbar, editor panel, or equation drawer). */
289
+ previewOnly?: boolean;
288
290
  uiLocale?: ButexUiLocale;
289
291
  mathOutput?: Document2MathOutput;
290
292
  onDocumentChange?: (document: Document2Node) => void;
@@ -295,7 +297,7 @@ type Document2InitialState = {
295
297
  error: string | null;
296
298
  };
297
299
  declare function resolveInitialDocument2(initialDocument: Document2Json | Document2Node | undefined, uiLocale?: ButexUiLocale): Document2InitialState;
298
- declare function ButexDocumentEditor2({ initialDocument, className, debug, documentDirection, equationSide, editableEquations, uiLocale, mathOutput, onDocumentChange, onLatexChange, }: ButexDocumentEditor2Props): react_jsx_runtime.JSX.Element;
300
+ declare function ButexDocumentEditor2({ initialDocument, className, debug, documentDirection, equationSide, editableEquations, previewOnly, uiLocale, mathOutput, onDocumentChange, onLatexChange, }: ButexDocumentEditor2Props): react_jsx_runtime.JSX.Element;
299
301
 
300
302
  type DocumentInsertToolbarProps = {
301
303
  canUndo: boolean;
@@ -285,6 +285,8 @@ type ButexDocumentEditor2Props = {
285
285
  documentDirection?: 'rtl' | 'ltr';
286
286
  equationSide?: EditorSide;
287
287
  editableEquations?: boolean;
288
+ /** When true, render only the read-only document preview (no toolbar, editor panel, or equation drawer). */
289
+ previewOnly?: boolean;
288
290
  uiLocale?: ButexUiLocale;
289
291
  mathOutput?: Document2MathOutput;
290
292
  onDocumentChange?: (document: Document2Node) => void;
@@ -295,7 +297,7 @@ type Document2InitialState = {
295
297
  error: string | null;
296
298
  };
297
299
  declare function resolveInitialDocument2(initialDocument: Document2Json | Document2Node | undefined, uiLocale?: ButexUiLocale): Document2InitialState;
298
- declare function ButexDocumentEditor2({ initialDocument, className, debug, documentDirection, equationSide, editableEquations, uiLocale, mathOutput, onDocumentChange, onLatexChange, }: ButexDocumentEditor2Props): react_jsx_runtime.JSX.Element;
300
+ declare function ButexDocumentEditor2({ initialDocument, className, debug, documentDirection, equationSide, editableEquations, previewOnly, uiLocale, mathOutput, onDocumentChange, onLatexChange, }: ButexDocumentEditor2Props): react_jsx_runtime.JSX.Element;
299
301
 
300
302
  type DocumentInsertToolbarProps = {
301
303
  canUndo: boolean;
@@ -11556,6 +11556,7 @@ function ButexDocumentEditor2({
11556
11556
  documentDirection = "rtl",
11557
11557
  equationSide = "arabic",
11558
11558
  editableEquations = true,
11559
+ previewOnly = false,
11559
11560
  uiLocale = "ar",
11560
11561
  mathOutput = "svg",
11561
11562
  onDocumentChange,
@@ -11598,10 +11599,10 @@ function ButexDocumentEditor2({
11598
11599
  injectBuTeXDocument2Styles();
11599
11600
  }, []);
11600
11601
  (0, import_react6.useEffect)(() => {
11601
- if (!editableEquations) {
11602
+ if (!editableEquations || previewOnly) {
11602
11603
  setSelectedMath(null);
11603
11604
  }
11604
- }, [editableEquations]);
11605
+ }, [editableEquations, previewOnly]);
11605
11606
  (0, import_react6.useEffect)(() => {
11606
11607
  const next = resolveInitialDocument2(initialDocument, uiLocale);
11607
11608
  setDocumentNode(next.document);
@@ -11890,6 +11891,8 @@ function ButexDocumentEditor2({
11890
11891
  pendingFocusRef.current = focusAfterDeletedMath(current, next, tokenId);
11891
11892
  applyDocument(next, "immediate");
11892
11893
  }
11894
+ const showEditorPanel = !previewOnly && editorOpen;
11895
+ const showPreviewPanel = previewOnly || previewOpen;
11893
11896
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
11894
11897
  "div",
11895
11898
  {
@@ -11898,7 +11901,7 @@ function ButexDocumentEditor2({
11898
11901
  dir: uiLocaleDirection(uiLocale),
11899
11902
  lang: uiLocale,
11900
11903
  children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "butex-document2-widget__shell", children: [
11901
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "butex-document2-widget__toolbar", children: [
11904
+ !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "butex-document2-widget__toolbar", children: [
11902
11905
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
11903
11906
  DocumentInsertToolbar,
11904
11907
  {
@@ -11928,19 +11931,19 @@ function ButexDocumentEditor2({
11928
11931
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", onClick: collapseAllBlocks, children: messages.collapseAll }),
11929
11932
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", onClick: openAllBlocks, children: messages.openAll })
11930
11933
  ] })
11931
- ] }),
11934
+ ] }) : null,
11932
11935
  error ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "butex-document2-widget__error", children: error }) : null,
11933
11936
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
11934
11937
  "div",
11935
11938
  {
11936
- className: `butex-document2-widget__layout butex-document2-widget__layout--editor-${editorOpen ? "open" : "closed"} butex-document2-widget__layout--preview-${previewOpen ? "open" : "closed"}`,
11939
+ className: `butex-document2-widget__layout butex-document2-widget__layout--editor-${showEditorPanel ? "open" : "closed"} butex-document2-widget__layout--preview-${showPreviewPanel ? "open" : "closed"}`,
11937
11940
  children: [
11938
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
11941
+ !previewOnly ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
11939
11942
  "section",
11940
11943
  {
11941
11944
  className: "butex-document2-widget__panel butex-document2-widget__editor-panel",
11942
11945
  "aria-label": messages.documentEditor,
11943
- "aria-hidden": !editorOpen,
11946
+ "aria-hidden": !showEditorPanel,
11944
11947
  children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "butex-document2-widget__blocks", children: documentNode.blocks.map((block, blockIndex) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
11945
11948
  BlockEditor,
11946
11949
  {
@@ -11970,13 +11973,13 @@ function ButexDocumentEditor2({
11970
11973
  block.id
11971
11974
  )) })
11972
11975
  }
11973
- ),
11976
+ ) : null,
11974
11977
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
11975
11978
  "section",
11976
11979
  {
11977
11980
  className: "butex-document2-widget__panel butex-document2-widget__preview-panel",
11978
11981
  "aria-label": messages.documentPreview,
11979
- "aria-hidden": !previewOpen,
11982
+ "aria-hidden": !showPreviewPanel,
11980
11983
  children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DocumentPreview, { blocks: preview.blocks, output: mathOutput, documentDirection, uiLocale })
11981
11984
  }
11982
11985
  )
@@ -11993,7 +11996,7 @@ function ButexDocumentEditor2({
11993
11996
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: "AST" }),
11994
11997
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("pre", { children: JSON.stringify(documentNode, null, 2) })
11995
11998
  ] }) : null,
11996
- selectedMath ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
11999
+ !previewOnly && selectedMath ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
11997
12000
  EquationDrawer,
11998
12001
  {
11999
12002
  session: selectedMath.session,