katex4arabic 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +303 -0
  3. package/dist/cdn/katex-arabic.min.cjs +258 -0
  4. package/dist/cdn/katex-arabic.min.css +9 -0
  5. package/dist/cdn/katex-arabic.min.js +258 -0
  6. package/dist/cdn/katex-arabic.min.mjs +11878 -0
  7. package/dist/lib/arabicFunctions.d.ts +87 -0
  8. package/dist/lib/arabicFunctions.d.ts.map +1 -0
  9. package/dist/lib/arabicNumerals.d.ts +50 -0
  10. package/dist/lib/arabicNumerals.d.ts.map +1 -0
  11. package/dist/lib/arabicSymbols.d.ts +52 -0
  12. package/dist/lib/arabicSymbols.d.ts.map +1 -0
  13. package/dist/lib/cdn.d.ts +18 -0
  14. package/dist/lib/cdn.d.ts.map +1 -0
  15. package/dist/lib/hooks.cjs +41 -0
  16. package/dist/lib/hooks.cjs.map +1 -0
  17. package/dist/lib/hooks.d.cts +61 -0
  18. package/dist/lib/hooks.d.ts +61 -0
  19. package/dist/lib/hooks.d.ts.map +1 -0
  20. package/dist/lib/hooks.mjs +41 -0
  21. package/dist/lib/hooks.mjs.map +1 -0
  22. package/dist/lib/index.cjs +71 -0
  23. package/dist/lib/index.cjs.map +1 -0
  24. package/dist/lib/index.d.cts +53 -0
  25. package/dist/lib/index.d.ts +53 -0
  26. package/dist/lib/index.d.ts.map +1 -0
  27. package/dist/lib/index.mjs +72 -0
  28. package/dist/lib/index.mjs.map +1 -0
  29. package/dist/lib/katex-arabic.css +458 -0
  30. package/dist/lib/protectedRegions.d.ts +26 -0
  31. package/dist/lib/protectedRegions.d.ts.map +1 -0
  32. package/dist/lib/render.cjs +811 -0
  33. package/dist/lib/render.cjs.map +1 -0
  34. package/dist/lib/render.d.ts +65 -0
  35. package/dist/lib/render.d.ts.map +1 -0
  36. package/dist/lib/render.mjs +812 -0
  37. package/dist/lib/render.mjs.map +1 -0
  38. package/dist/lib/rtlRenderer.d.ts +100 -0
  39. package/dist/lib/rtlRenderer.d.ts.map +1 -0
  40. package/dist/lib/types.d.ts +98 -0
  41. package/dist/lib/types.d.ts.map +1 -0
  42. package/docs/INSTALL.md +314 -0
  43. package/package.json +119 -0
@@ -0,0 +1,53 @@
1
+ /**
2
+ * ════════════════════════════════════════════════════════════════
3
+ * index.ts
4
+ * Public entry point for the KaTeX Arabic library.
5
+ *
6
+ * This module is the *only* file the application should import
7
+ * from when consuming the library. All internal modules are
8
+ * re-exported below for advanced use cases.
9
+ *
10
+ * The render functions themselves live in `render.ts` so that
11
+ * `hooks.ts` can import them without a circular dependency
12
+ * through this barrel.
13
+ * ════════════════════════════════════════════════════════════════
14
+ */
15
+ import { renderArabic, renderArabicToString, renderArabicWithMeta, renderArabicBatch, processLatex, validateLatex } from './render';
16
+ import { clearRenderCache, resolveOptions, buildCssClasses, getArabicMacros } from './rtlRenderer';
17
+ import { toArabicNumerals, fromArabicNumerals, formatArabicNumber, convertNumbersInText, isArabicDigit } from './arabicNumerals';
18
+ import { translateFunctions, translateVariables, translateDifferentials, translateSpecialPatterns, translateAll } from './arabicFunctions';
19
+ import { applyMirroredSymbols } from './arabicSymbols';
20
+ export { DEFAULT_OPTIONS, resolveOptions, buildCssClasses, getArabicMacros, clearRenderCache, MAX_INPUT_LENGTH, } from './rtlRenderer';
21
+ export type { ArabicKatexOptions, PartialArabicOptions, RenderResult } from './types';
22
+ export { renderArabicToString, renderArabicWithMeta, renderArabic, renderArabicBatch, processLatex, validateLatex, } from './render';
23
+ export { toArabicNumerals, fromArabicNumerals, formatArabicNumber, convertNumbersInText, isArabicDigit, } from './arabicNumerals';
24
+ export { translateFunctions, translateVariables, translateDifferentials, translateSpecialPatterns, translateAll, FUNCTION_MAP, VARIABLE_MAP, GREEK_MAP, DIFFERENTIAL_PATTERNS, } from './arabicFunctions';
25
+ export { applyMirroredSymbols, MIRRORED_SYMBOLS, COMPARISON_SYMBOLS, ARROW_SYMBOLS, BRACKET_SYMBOLS, ARABIC_MATH_UNICODE, SPECIAL_ARABIC_SYMBOLS, } from './arabicSymbols';
26
+ export declare const VERSION = "1.1.1";
27
+ declare const KaTeXArabic: {
28
+ render: typeof renderArabic;
29
+ renderToString: typeof renderArabicToString;
30
+ renderWithMeta: typeof renderArabicWithMeta;
31
+ renderBatch: typeof renderArabicBatch;
32
+ process: typeof processLatex;
33
+ validate: typeof validateLatex;
34
+ toArabicNumerals: typeof toArabicNumerals;
35
+ fromArabicNumerals: typeof fromArabicNumerals;
36
+ formatArabicNumber: typeof formatArabicNumber;
37
+ convertNumbersInText: typeof convertNumbersInText;
38
+ isArabicDigit: typeof isArabicDigit;
39
+ translateFunctions: typeof translateFunctions;
40
+ translateVariables: typeof translateVariables;
41
+ translateDifferentials: typeof translateDifferentials;
42
+ translateSpecialPatterns: typeof translateSpecialPatterns;
43
+ translateAll: typeof translateAll;
44
+ applyMirroredSymbols: typeof applyMirroredSymbols;
45
+ resolveOptions: typeof resolveOptions;
46
+ buildCssClasses: typeof buildCssClasses;
47
+ getArabicMacros: typeof getArabicMacros;
48
+ clearCache: typeof clearRenderCache;
49
+ DEFAULT_OPTIONS: import("./types").ArabicKatexOptions;
50
+ VERSION: string;
51
+ };
52
+ export default KaTeXArabic;
53
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/katex-arabic/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACd,MAAM,UAAU,CAAC;AAClB,OAAO,EAEL,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,wBAAwB,EACxB,YAAY,EACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAGvD,OAAO,EACL,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGtF,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,aAAa,GACd,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,wBAAwB,EACxB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAKzB,eAAO,MAAM,OAAO,UAAU,CAAC;AAW/B,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;CAmChB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { D as DEFAULT_OPTIONS, c as clearRenderCache, g as getArabicMacros, b as buildCssClasses, d as resolveOptions, e as applyMirroredSymbols, t as translateAll, f as translateSpecialPatterns, h as translateDifferentials, i as translateVariables, j as translateFunctions, k as isArabicDigit, l as convertNumbersInText, m as formatArabicNumber, n as fromArabicNumerals, o as toArabicNumerals, v as validateLatex, q as processLatex, a as renderArabicBatch, r as renderArabicWithMeta, s as renderArabicToString, u as renderArabic } from "./render.mjs";
2
+ import { A, w, B, C, x, F, G, M, y, S, V } from "./render.mjs";
3
+ const VERSION = "1.1.1";
4
+ const KaTeXArabic = {
5
+ // ─── Rendering ───────────────────────────────────────────
6
+ render: renderArabic,
7
+ renderToString: renderArabicToString,
8
+ renderWithMeta: renderArabicWithMeta,
9
+ renderBatch: renderArabicBatch,
10
+ // ─── Text processing ─────────────────────────────────────
11
+ process: processLatex,
12
+ validate: validateLatex,
13
+ // ─── Numerals ────────────────────────────────────────────
14
+ toArabicNumerals,
15
+ fromArabicNumerals,
16
+ formatArabicNumber,
17
+ convertNumbersInText,
18
+ isArabicDigit,
19
+ // ─── Translation ─────────────────────────────────────────
20
+ translateFunctions,
21
+ translateVariables,
22
+ translateDifferentials,
23
+ translateSpecialPatterns,
24
+ translateAll,
25
+ // ─── Mirroring ───────────────────────────────────────────
26
+ applyMirroredSymbols,
27
+ // ─── Options / cache ─────────────────────────────────────
28
+ resolveOptions,
29
+ buildCssClasses,
30
+ getArabicMacros,
31
+ clearCache: clearRenderCache,
32
+ DEFAULT_OPTIONS,
33
+ VERSION
34
+ };
35
+ export {
36
+ A as ARABIC_MATH_UNICODE,
37
+ w as ARROW_SYMBOLS,
38
+ B as BRACKET_SYMBOLS,
39
+ C as COMPARISON_SYMBOLS,
40
+ DEFAULT_OPTIONS,
41
+ x as DIFFERENTIAL_PATTERNS,
42
+ F as FUNCTION_MAP,
43
+ G as GREEK_MAP,
44
+ M as MAX_INPUT_LENGTH,
45
+ y as MIRRORED_SYMBOLS,
46
+ S as SPECIAL_ARABIC_SYMBOLS,
47
+ V as VARIABLE_MAP,
48
+ VERSION,
49
+ applyMirroredSymbols,
50
+ buildCssClasses,
51
+ clearRenderCache,
52
+ convertNumbersInText,
53
+ KaTeXArabic as default,
54
+ formatArabicNumber,
55
+ fromArabicNumerals,
56
+ getArabicMacros,
57
+ isArabicDigit,
58
+ processLatex,
59
+ renderArabic,
60
+ renderArabicBatch,
61
+ renderArabicToString,
62
+ renderArabicWithMeta,
63
+ resolveOptions,
64
+ toArabicNumerals,
65
+ translateAll,
66
+ translateDifferentials,
67
+ translateFunctions,
68
+ translateSpecialPatterns,
69
+ translateVariables,
70
+ validateLatex
71
+ };
72
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/lib/katex-arabic/index.ts"],"sourcesContent":["/**\n * ════════════════════════════════════════════════════════════════\n * index.ts\n * Public entry point for the KaTeX Arabic library.\n *\n * This module is the *only* file the application should import\n * from when consuming the library. All internal modules are\n * re-exported below for advanced use cases.\n *\n * The render functions themselves live in `render.ts` so that\n * `hooks.ts` can import them without a circular dependency\n * through this barrel.\n * ════════════════════════════════════════════════════════════════\n */\n\nimport {\n renderArabic,\n renderArabicToString,\n renderArabicWithMeta,\n renderArabicBatch,\n processLatex,\n validateLatex,\n} from './render';\nimport {\n DEFAULT_OPTIONS,\n clearRenderCache,\n resolveOptions,\n buildCssClasses,\n getArabicMacros,\n} from './rtlRenderer';\nimport {\n toArabicNumerals,\n fromArabicNumerals,\n formatArabicNumber,\n convertNumbersInText,\n isArabicDigit,\n} from './arabicNumerals';\nimport {\n translateFunctions,\n translateVariables,\n translateDifferentials,\n translateSpecialPatterns,\n translateAll,\n} from './arabicFunctions';\nimport { applyMirroredSymbols } from './arabicSymbols';\n\n// ─── Re-exports: configuration ─────────────────────────────\nexport {\n DEFAULT_OPTIONS,\n resolveOptions,\n buildCssClasses,\n getArabicMacros,\n clearRenderCache,\n MAX_INPUT_LENGTH,\n} from './rtlRenderer';\nexport type { ArabicKatexOptions, PartialArabicOptions, RenderResult } from './types';\n\n// ─── Re-exports: render functions ────────────────────────────\nexport {\n renderArabicToString,\n renderArabicWithMeta,\n renderArabic,\n renderArabicBatch,\n processLatex,\n validateLatex,\n} from './render';\n\n// ─── Re-exports: numerals ──────────────────────────────────\nexport {\n toArabicNumerals,\n fromArabicNumerals,\n formatArabicNumber,\n convertNumbersInText,\n isArabicDigit,\n} from './arabicNumerals';\n\n// ─── Re-exports: function translation ──────────────────────\nexport {\n translateFunctions,\n translateVariables,\n translateDifferentials,\n translateSpecialPatterns,\n translateAll,\n FUNCTION_MAP,\n VARIABLE_MAP,\n GREEK_MAP,\n DIFFERENTIAL_PATTERNS,\n} from './arabicFunctions';\n\n// ─── Re-exports: symbol mirroring ──────────────────────────\nexport {\n applyMirroredSymbols,\n MIRRORED_SYMBOLS,\n COMPARISON_SYMBOLS,\n ARROW_SYMBOLS,\n BRACKET_SYMBOLS,\n ARABIC_MATH_UNICODE,\n SPECIAL_ARABIC_SYMBOLS,\n} from './arabicSymbols';\n\n// ─── Version constant ──────────────────────────────────────\n// Kept in sync with package.json by scripts/build-cdn.mjs\n// (the CDN build fails if these ever drift apart).\nexport const VERSION = '1.1.1';\n\n// ═══════════════════════════════════════════════════════════════\n// Default export — the \"KaTeXArabic\" namespace\n//\n// This object is what a CDN <script> tag exposes as `window.KaTeXArabic`,\n// and what `import KaTeXArabic from 'katex-arabic'` returns. It mirrors\n// `katex`'s own API shape (render / renderToString / …) plus every\n// Arabic helper, so it works as a full drop-in namespace.\n// ═══════════════════════════════════════════════════════════════\n\nconst KaTeXArabic = {\n // ─── Rendering ───────────────────────────────────────────\n render: renderArabic,\n renderToString: renderArabicToString,\n renderWithMeta: renderArabicWithMeta,\n renderBatch: renderArabicBatch,\n\n // ─── Text processing ─────────────────────────────────────\n process: processLatex,\n validate: validateLatex,\n\n // ─── Numerals ────────────────────────────────────────────\n toArabicNumerals,\n fromArabicNumerals,\n formatArabicNumber,\n convertNumbersInText,\n isArabicDigit,\n\n // ─── Translation ─────────────────────────────────────────\n translateFunctions,\n translateVariables,\n translateDifferentials,\n translateSpecialPatterns,\n translateAll,\n\n // ─── Mirroring ───────────────────────────────────────────\n applyMirroredSymbols,\n\n // ─── Options / cache ─────────────────────────────────────\n resolveOptions,\n buildCssClasses,\n getArabicMacros,\n clearCache: clearRenderCache,\n DEFAULT_OPTIONS,\n VERSION,\n};\n\nexport default KaTeXArabic;"],"names":[],"mappings":";;AAuGO,MAAM,UAAU;AAWvB,MAAM,cAAc;AAAA;AAAA,EAElB,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA;AAAA,EAGb,SAAS;AAAA,EACT,UAAU;AAAA;AAAA,EAGV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AACF;"}
@@ -0,0 +1,458 @@
1
+ /* ════════════════════════════════════════════════════════════════
2
+ katex-arabic.css
3
+ KaTeX Arabic — Core rendering styles.
4
+
5
+ Goals:
6
+ • Make Arabic equations visually match their Latin counterparts
7
+ in size, baseline, alignment, and weight.
8
+ • Provide a small, well-named API of classes (katex-arabic, is-display,
9
+ is-inline, mirror-sqrt, mirror-big-ops, mirror-brackets, mirror-symbols,
10
+ full-rtl-mode) so callers can opt into behaviours.
11
+ • Use CSS variables for theming; never hardcode colors in the
12
+ main selectors.
13
+
14
+ Conventions:
15
+ • The root wrapper has class `katex-arabic` and is set to `inline-block`
16
+ in inline mode and `block` (via `.is-display`) in display mode.
17
+ • The inner `.katex` element is left untouched by KaTeX; we only
18
+ adjust sizes, alignment, and mirroring around it.
19
+ ════════════════════════════════════════════════════════════════ */
20
+
21
+ /* ─── Design tokens ──────────────────────────────────────── */
22
+ .katex-arabic {
23
+ /* Sizes mirror KaTeX's own scale so Arabic and Latin match. */
24
+ --ka-size-multiplier: 1;
25
+ /* Robust Arabic-first fallback chain. If the preferred font (Amiri)
26
+ is not loaded, the browser walks down to other high-quality Arabic
27
+ math/text faces before falling back to KaTeX_Main and a generic
28
+ serif. This keeps Arabic operator names and \text{} content legible
29
+ and correctly shaped in every environment. */
30
+ --ka-font-family: 'Amiri', 'Scheherazade New', 'Noto Naskh Arabic',
31
+ 'Cairo', 'Tajawal', 'KaTeX_Main', 'Latin Modern Math', serif;
32
+ --ka-color: inherit;
33
+ --ka-line-height: 1.6;
34
+
35
+ /* Mirror transforms — only used when the corresponding class is on. */
36
+ --ka-mirror-transform: scaleX(-1);
37
+
38
+ /* The default display */
39
+ display: inline-block;
40
+ direction: rtl;
41
+ font-family: var(--ka-font-family);
42
+ color: var(--ka-color);
43
+ line-height: var(--ka-line-height);
44
+ font-size: calc(1em * var(--ka-size-multiplier));
45
+ text-align: center;
46
+ unicode-bidi: isolate;
47
+ vertical-align: middle;
48
+ }
49
+
50
+ /* ─── Display vs inline ──────────────────────────────────── */
51
+ .katex-arabic.is-display {
52
+ display: block;
53
+ text-align: center;
54
+ margin: 0.75em 0;
55
+ }
56
+
57
+ .katex-arabic.is-inline {
58
+ display: inline-block;
59
+ text-align: center;
60
+ white-space: nowrap;
61
+ }
62
+
63
+ /* ─── The inner .katex element ───────────────────────────── */
64
+ .katex-arabic .katex {
65
+ font-family: var(--ka-font-family);
66
+ direction: rtl;
67
+ text-align: center;
68
+ display: inline-block;
69
+ /* The horizontal layout of math expressions is LTR (operators
70
+ have direction), but the surrounding text is RTL. Keep this
71
+ to "ltr" to avoid mirrored placement of signs. */
72
+ unicode-bidi: isolate;
73
+ }
74
+
75
+ .katex-arabic .katex-display {
76
+ margin: 0;
77
+ text-align: center;
78
+ }
79
+
80
+ .katex-arabic .katex .base {
81
+ display: inline-block;
82
+ vertical-align: baseline;
83
+ }
84
+
85
+ /* ─── operator-name (operatorname) ───────────────────────── */
86
+ /* Scope the Arabic font override to Arabic operator names only
87
+ (نها, جا, …). We MUST NOT match `.mop.op-symbol.large-op` —
88
+ KaTeX relies on `.op-symbol.large-op { font-family: KaTeX_Size2 }`
89
+ to render big-operator glyphs (∫ Σ ∏ ∮) in the tall Size2 math
90
+ font. This selector has higher CSS specificity (three classes) than
91
+ KaTeX's two-class rule, so applying it bare would override the
92
+ Size2 font and re-render the integral in Amiri / KaTeX_Main — the
93
+ glyph would then be the wrong size, the strut/limits KaTeX computed
94
+ would be matched to a glyph that no longer fills them, and the
95
+ bounds would drift away from the two tips of the symbol. Excluding
96
+ `.op-symbol` (the integral/sum glyph itself) and `.op-limits` (the
97
+ outer wrapper that stacks limits above/below) restores KaTeX's
98
+ specialised fonts for big operators while keeping Arabic names. */
99
+ .katex-arabic .katex .mop:not(.op-symbol):not(.op-limits) {
100
+ font-family: var(--ka-font-family);
101
+ font-weight: 400;
102
+ }
103
+
104
+ /* ─── mathnormal / mathit — keep upright so Arabic doesn't italicise */
105
+ .katex-arabic .katex .mathnormal,
106
+ .katex-arabic .katex .mathit {
107
+ font-style: normal;
108
+ }
109
+
110
+ /* ─── Text inside math (e.g. \text{د}) ───────────────────── */
111
+ .katex-arabic .katex .mord.text,
112
+ .katex-arabic .katex .text {
113
+ font-family: var(--ka-font-family);
114
+ direction: rtl;
115
+ unicode-bidi: isolate;
116
+ }
117
+
118
+ /* ─── Fractions: vertical center with the rest of the line ─ */
119
+ .katex-arabic .katex .mfrac {
120
+ vertical-align: middle;
121
+ }
122
+
123
+ .katex-arabic .katex .frac-line {
124
+ min-width: 100%;
125
+ }
126
+
127
+ /* ─── Matrices: keep columns aligned ─────────────────────── */
128
+ .katex-arabic .katex .mtable {
129
+ vertical-align: middle;
130
+ direction: ltr; /* math layout is direction-agnostic */
131
+ }
132
+
133
+ .katex-arabic .katex .minner {
134
+ vertical-align: middle;
135
+ }
136
+
137
+ /* ─── Delimiters: ensure proper baseline ─────────────────── */
138
+ .katex-arabic .katex .delimsizing,
139
+ .katex-arabic .katex .mopen,
140
+ .katex-arabic .katex .mclose {
141
+ vertical-align: middle;
142
+ }
143
+
144
+ /* ─── Superscript / subscript ───────────────────────────────
145
+ KaTeX positions the bounds of ∫, Σ, ∏, lim and sub-/super-scripts
146
+ with great precision via the `.vlist-t` inline-table and computed
147
+ `top:-Xem` offsets on its row spans. The exact offsets were
148
+ calculated by KaTeX assuming the inherited line-height (1.2 on
149
+ `.katex`). We deliberately do NOT touch `.msupsub`, `.vlist-t`, or
150
+ `.vlist` here — any vertical-align / line-height override on them
151
+ would shift the computed baselines and misalign the limits. */
152
+
153
+ /* ═══════════════════════════════════════════════════════════════
154
+ Limits & big operators (lim, max, min, ∫, Σ, ∏)
155
+ We let KaTeX render these natively. KaTeX positions the bounds with
156
+ `top:-Xem` offsets computed against the inherited line-height (1.2 on
157
+ `.katex`) and against the metric of the big-operator glyph in
158
+ `KaTeX_Size2`. Forcing a different line-height here, or overriding
159
+ the font-family of the `.op-symbol` glyph, would invalidate those
160
+ computed offsets and drift the bounds away from the two tips of the
161
+ symbol — so we deliberately add NO rules in this section. Cf. the
162
+ `.mop:not(.op-symbol):not(.op-limits)` exclusions above for the same
163
+ reason.
164
+ ═══════════════════════════════════════════════════════════════ */
165
+
166
+ /* Big operators (∫ Σ ∏) — keep the glyph + its sub/sup limits as ONE
167
+ atomic LTR unit. Under direction:rtl the bidi algorithm would
168
+ otherwise reorder the integral glyph against its .msupsub limits and
169
+ scatter the bounds away from the two tips of the symbol. Isolating
170
+ the .mop keeps the limits anchored at the correct tips while the
171
+ integral still participates in the RTL equation as a single atom. */
172
+ .katex-arabic .katex .mop:has(> .op-symbol) {
173
+ direction: ltr;
174
+ unicode-bidi: isolate;
175
+ }
176
+ /* ═══════════════════════════════════════════════════════════════
177
+ Mirroring
178
+ ═══════════════════════════════════════════════════════════════ */
179
+
180
+ /* ─── Big operators (∫ Σ ∏ ∮) ────────────────────────────── */
181
+ /* Mirror the large-operator glyphs for RTL. The transform is
182
+ GPU-composited (translateZ(0)) to avoid sub-pixel flicker on the
183
+ mirrored glyph, and backface-visibility is hidden so the flipped
184
+ glyph never shows its reverse face during compositing. The glyph's
185
+ sub/sup limits stay anchored because the parent .mop is isolated as
186
+ an atomic LTR unit (see the :has(> .op-symbol) rule above). */
187
+ .katex-arabic.mirror-big-ops .katex .mop-int,
188
+ .katex-arabic.mirror-big-ops .katex .op-symbol.large-op {
189
+ display: inline-block;
190
+ transform: var(--ka-mirror-transform) translateZ(0);
191
+ -webkit-transform: var(--ka-mirror-transform) translateZ(0);
192
+ -moz-transform: var(--ka-mirror-transform) translateZ(0);
193
+ -ms-transform: var(--ka-mirror-transform) translateZ(0);
194
+ -o-transform: var(--ka-mirror-transform) translateZ(0);
195
+ backface-visibility: hidden;
196
+ -webkit-backface-visibility: hidden;
197
+ }
198
+
199
+ /* ─── Square root sign ───────────────────────────────────── */
200
+ /* Mirror the radical sign for RTL: flip the whole .sqrt container
201
+ (this moves the vertical bar to the reading-start side and places
202
+ the radicand under the overline), then counter-flip ONLY the
203
+ readable content — the radicand cell and any n-th root — so the
204
+ text itself stays upright. Without the container flip the bar
205
+ stays on the wrong (left) side; without the counter-flip the
206
+ radicand would be mirrored. */
207
+ .katex-arabic.mirror-sqrt .katex .sqrt {
208
+ display: inline-block;
209
+ transform: var(--ka-mirror-transform) translateZ(0);
210
+ transform-origin: center;
211
+ backface-visibility: hidden;
212
+ -webkit-backface-visibility: hidden;
213
+ /* A CSS transform does not change layout, so the mirrored radical
214
+ (bar now on the reading-start side) can collide with the symbol
215
+ that precedes it. Reserve small horizontal margins on both
216
+ reading sides so the flipped sign never touches its neighbours. */
217
+ margin-inline: 0.15em;
218
+ }
219
+
220
+ /* Counter-flip the readable content so the radicand and any n-th root
221
+ index stay upright after the container flip. These selectors target
222
+ the exact KaTeX internal nodes that hold readable glyphs; the GPU
223
+ compositing hints (translateZ(0) + backface-visibility) prevent
224
+ sub-pixel flicker on the flipped content. */
225
+ .katex-arabic.mirror-sqrt .katex .sqrt > .vlist-t > .vlist-r > .vlist > span:first-child,
226
+ .katex-arabic.mirror-sqrt .katex .sqrt .katex-root,
227
+ .katex-arabic.mirror-sqrt .katex .sqrt .root {
228
+ transform: var(--ka-mirror-transform) translateZ(0);
229
+ transform-origin: center;
230
+ backface-visibility: hidden;
231
+ -webkit-backface-visibility: hidden;
232
+ }
233
+
234
+ /* ─── Brackets: swap opening and closing pairs visually ──── */
235
+ .katex-arabic.mirror-brackets .katex .mopen + .minner + .mclose,
236
+ .katex-arabic.mirror-brackets .katex .delimsizing:first-of-type {
237
+ /* Hook for future per-glyph mirroring */
238
+ }
239
+
240
+ /* ─── Comparison symbols: use KaTeX command mirroring which
241
+ is already applied at the LaTeX level, so no DOM mirror needed. */
242
+ .katex-arabic.mirror-symbols .katex {
243
+ /* No additional transforms — mirroring happens in processArabicLatex */
244
+ }
245
+
246
+ /* ═══════════════════════════════════════════════════════════════
247
+ Full RTL mode (toggle)
248
+ When enabled, the whole .katex element flips to RTL direction.
249
+ This is the "Arabic-first" mode for users who want the entire
250
+ equation to read right-to-left (powers on left, subscripts on right).
251
+ ═══════════════════════════════════════════════════════════════ */
252
+
253
+ .katex-arabic.full-rtl-mode .katex {
254
+ direction: rtl;
255
+ }
256
+
257
+ .katex-arabic.full-rtl-mode .katex-display {
258
+ direction: rtl;
259
+ text-align: center;
260
+ }
261
+
262
+ .katex-arabic.full-rtl-mode .katex .base {
263
+ direction: rtl;
264
+ }
265
+
266
+ /* ═══════════════════════════════════════════════════════════════
267
+ Size variants
268
+ Sizes are *multipliers* — they stack on top of the inherited
269
+ font-size so they compose nicely with Tailwind's text-* classes.
270
+ ═══════════════════════════════════════════════════════════════ */
271
+
272
+ .katex-arabic.size-sm { --ka-size-multiplier: 0.85; }
273
+ .katex-arabic.size-md { --ka-size-multiplier: 1; }
274
+ .katex-arabic.size-lg { --ka-size-multiplier: 1.15; }
275
+ .katex-arabic.size-xl { --ka-size-multiplier: 1.35; }
276
+ .katex-arabic.size-2xl { --ka-size-multiplier: 1.6; }
277
+
278
+ /* ═══════════════════════════════════════════════════════════════
279
+ Error state
280
+ ═══════════════════════════════════════════════════════════════ */
281
+
282
+ .katex-arabic--error {
283
+ padding: 0.5em 0.75em;
284
+ background: rgba(220, 38, 38, 0.08);
285
+ border: 1px solid rgba(220, 38, 38, 0.3);
286
+ border-radius: 6px;
287
+ display: inline-block;
288
+ }
289
+
290
+ .katex-arabic__error-icon {
291
+ margin-inline-end: 0.25em;
292
+ font-weight: 700;
293
+ }
294
+
295
+ .katex-arabic__error-text {
296
+ font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
297
+ font-size: 0.95em;
298
+ word-break: break-all;
299
+ }
300
+
301
+ /* ═══════════════════════════════════════════════════════════════
302
+ Print styles
303
+ ═══════════════════════════════════════════════════════════════ */
304
+
305
+ @media print {
306
+ .katex-arabic {
307
+ color: #000 !important;
308
+ background: transparent !important;
309
+ }
310
+ .katex-arabic--error {
311
+ border-color: #999;
312
+ background: transparent;
313
+ }
314
+ }
315
+
316
+ /* ═══════════════════════════════════════════════════════════════
317
+ Latin visual parity
318
+ The goal of this block is to make Arabic glyphs (operator names,
319
+ \text{…} content, differentials) behave exactly like their Latin
320
+ KaTeX counterparts: same line metrics, same baseline, no clipping,
321
+ and — opt-in — an optical size factor for fonts whose x-height
322
+ differs from KaTeX_Main.
323
+
324
+ Everything here defaults to "no visual change" (factor = 1) so the
325
+ rules are safe to ship out of the box; they only activate when the
326
+ caller needs them (e.g. the operatorScale option).
327
+ ═══════════════════════════════════════════════════════════════ */
328
+
329
+ /* 1. Arabic ascenders / descenders / diacritics must never be clipped. */
330
+ .katex-arabic .katex {
331
+ overflow: visible;
332
+ }
333
+
334
+ /* 2. Operator names and math text get a tight, stable line box so the
335
+ Arabic font metrics cannot inflate the formula height. */
336
+ .katex-arabic .katex .mop:not(.op-symbol):not(.op-limits),
337
+ .katex-arabic .katex .mord.text,
338
+ .katex-arabic .katex .textord.text {
339
+ line-height: 1;
340
+ vertical-align: baseline;
341
+ }
342
+
343
+ /* 3. Arabic math text stays upright and regular — same weight and
344
+ posture as Latin \operatorname names. */
345
+ .katex-arabic .katex .mord.text,
346
+ .katex-arabic .katex .textord.text {
347
+ font-style: normal;
348
+ font-weight: 400;
349
+ letter-spacing: 0;
350
+ text-rendering: optimizeLegibility;
351
+ }
352
+
353
+ /* 4. Opt-in optical scale (default 1 → no change). Expose the knob as a
354
+ CSS variable so themers can tune it from anywhere:
355
+ .math-equation { --ka-op-scale: 1.08; }
356
+ The wrapper also receives it inline from the operatorScale option. */
357
+ .katex-arabic .katex .mop .mord.text,
358
+ .katex-arabic .katex .mop .text,
359
+ .katex-arabic .katex .mord.text,
360
+ .katex-arabic .katex .textord.text {
361
+ font-size: calc(1em * var(--ka-op-scale, 1));
362
+ }
363
+
364
+ /* 5. We do NOT override line-height on fractions, roots, or
365
+ super/sub-script vlists. KaTeX positions every row inside these
366
+ vlists with top:-Xem offsets that were calculated assuming
367
+ the inherited line-height (1.2 on .katex). Forcing
368
+ line-height: 1 here would change the line-box baseline within
369
+ each row and shift the radicand of a root, the bar of a fraction,
370
+ and crucially the upper/lower limits of \int_a^b away from
371
+ the two tips of the operator glyph. Keeping the default inheritance
372
+ leaves every offset exactly where KaTeX computed it, which also
373
+ matches the Latin reference. */
374
+
375
+ /* 6. Matrices: every column centers on the math axis, like Latin arrays. */
376
+ .katex-arabic .katex .mtable .col-align-c {
377
+ vertical-align: middle;
378
+ }
379
+
380
+ /* 7. Inline mode: match KaTeX's own compact line box so an Arabic inline
381
+ equation sits on the text line at the same height as a Latin one. */
382
+ .katex-arabic.is-inline {
383
+ line-height: 1.2;
384
+ }
385
+
386
+ /* ═══════════════════════════════════════════════════════════════
387
+ Arabic character metrics compensation
388
+ ─────────────────────────────────────────────────────────────
389
+ KaTeX's font-metrics tables only cover Latin math glyphs. When an
390
+ Arabic character (digit ٠-٩, letter س, operator جا, …) is rendered,
391
+ KaTeX creates a SymbolNode with height=0, depth=0, width=0 because
392
+ the character is not in its metrics tables. The browser still draws
393
+ the glyph at its natural font size, but KaTeX's layout engine
394
+ (vlists, struts, fraction bars, sqrt signs, super/sub positions)
395
+ was computed against the zero metrics — so Arabic text can appear
396
+ misaligned, clipped, or colliding with adjacent symbols.
397
+
398
+ The rules below compensate at the CSS level WITHOUT overriding the
399
+ carefully-tuned line-height / display / vertical-align values set
400
+ earlier in this file. They are purely additive:
401
+ 1. Enable OpenType features for correct Arabic shaping.
402
+ 2. Prevent clipping of tall Arabic ascenders / descenders.
403
+ 3. Add minimal spacing to prevent symbol collision.
404
+ ═══════════════════════════════════════════════════════════════ */
405
+
406
+ /* 1. OpenType features for correct Arabic shaping. These are essential
407
+ for fonts like Amiri, Noto Naskh Arabic, and Scheherazade New to
408
+ render contextual letter forms, ligatures (لا, لله), and proper
409
+ mark (harakat) positioning. This is purely additive and does not
410
+ affect layout metrics. */
411
+ .katex-arabic .katex .mord.text,
412
+ .katex-arabic .katex .mop:not(.op-symbol):not(.op-limits),
413
+ .katex-arabic .katex .text {
414
+ font-feature-settings:
415
+ 'liga' 1, /* standard ligatures (لا, etc.) */
416
+ 'calt' 1, /* contextual alternates (letter forms) */
417
+ 'kern' 1, /* kerning */
418
+ 'mark' 1, /* mark positioning (harakat) */
419
+ 'mkmk' 1; /* mark-to-mark positioning */
420
+ font-variant-ligatures: common-ligatures contextual;
421
+ text-rendering: optimizeLegibility;
422
+ }
423
+
424
+ /* 2. Arabic characters must never be clipped by overflow:hidden on
425
+ parent vlist rows. KaTeX's vlist-t uses overflow:visible by
426
+ default, but some nested containers can clip tall Arabic
427
+ ascenders (ا, ل, ك) or descenders (ي, ج, ع). */
428
+ .katex-arabic .katex .vlist-t,
429
+ .katex-arabic .katex .vlist-r,
430
+ .katex-arabic .katex .vlist {
431
+ overflow: visible;
432
+ }
433
+
434
+ /* 3. Operator names (جا, جتا, نها, …) rendered via \operatorname{}.
435
+ These are the most visible Arabic elements. A small horizontal
436
+ padding prevents collision with adjacent symbols without changing
437
+ the display mode or line-height (which are deliberately tuned
438
+ above). */
439
+ .katex-arabic .katex .mop:not(.op-symbol):not(.op-limits) {
440
+ padding-inline: 0.04em;
441
+ }
442
+
443
+ /* 4. Ensure the radical sign (√) and its Arabic radicand don't collide.
444
+ The mirrored sqrt (bar on the right) needs extra clearance for
445
+ Arabic text which tends to be wider than Latin. */
446
+ .katex-arabic.mirror-sqrt .katex .sqrt .mord.text,
447
+ .katex-arabic.mirror-sqrt .katex .sqrt .mop:not(.op-symbol) {
448
+ padding-inline-start: 0.08em;
449
+ }
450
+
451
+ /* 5. Matrix cells with Arabic content. Centre-align horizontally,
452
+ matching Latin matrix behaviour. */
453
+ .katex-arabic .katex .mtable .mord.text,
454
+ .katex-arabic .katex .mtable .mop:not(.op-symbol) {
455
+ text-align: center;
456
+ }
457
+
458
+
@@ -0,0 +1,26 @@
1
+ /**
2
+ * ════════════════════════════════════════════════════════════════
3
+ * protectedRegions.ts
4
+ * Shared helpers for tracking spans of a LaTeX string that text
5
+ * transforms must never touch (the bodies of \text{…},
6
+ * \operatorname{…}, …). Used by the function translator and the
7
+ * symbol-mirroring engine so user-written prose inside math stays
8
+ * byte-for-byte identical.
9
+ * ════════════════════════════════════════════════════════════════
10
+ */
11
+ export interface TextRegion {
12
+ start: number;
13
+ end: number;
14
+ }
15
+ /**
16
+ * Collect the indices of every verbatim span in `latex`.
17
+ * Regions are sorted by start; overlapping spans are merged so a
18
+ * single `isInsideRegions` walk stays correct.
19
+ */
20
+ export declare function collectProtectedRegions(latex: string): TextRegion[];
21
+ /**
22
+ * Returns true when `pos` (a match offset in the original string) lies
23
+ * inside any protected region. Regions must be sorted (see above).
24
+ */
25
+ export declare function isInsideRegions(pos: number, regions: TextRegion[]): boolean;
26
+ //# sourceMappingURL=protectedRegions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protectedRegions.d.ts","sourceRoot":"","sources":["../../src/lib/katex-arabic/protectedRegions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAkCD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAqBnE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAM3E"}