rapier-math 1.0.1 → 1.1.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.
Files changed (69) hide show
  1. package/README.md +187 -85
  2. package/adoption-check.mjs +149 -0
  3. package/check.mjs +21 -0
  4. package/classic.d.ts +4 -0
  5. package/delimiters.d.ts +8 -0
  6. package/delimiters.mjs +39 -0
  7. package/examples/README.md +25 -0
  8. package/examples/browser.html +10 -0
  9. package/examples/browser.mjs +24 -0
  10. package/examples/formula.mjs +12 -0
  11. package/examples/markdown.mjs +9 -0
  12. package/examples/react.tsx +19 -0
  13. package/examples/stream.mjs +19 -0
  14. package/examples/unified.mjs +26 -0
  15. package/examples/worker.mjs +7 -0
  16. package/index.d.ts +43 -0
  17. package/index.mjs +205 -108
  18. package/integration.d.ts +9 -0
  19. package/integration.mjs +28 -0
  20. package/markdown-it.d.ts +6 -0
  21. package/markdown-it.mjs +45 -0
  22. package/markdown-rules.mjs +65 -0
  23. package/math-components.json +6 -6
  24. package/package.json +78 -5
  25. package/rapier-math-1.1.0.js +2980 -0
  26. package/rehype.d.ts +6 -0
  27. package/rehype.mjs +37 -0
  28. package/src/math/FONT-SOURCE.md +32 -6
  29. package/src/math/README.md +210 -0
  30. package/src/math/adoption-verify.mjs +149 -0
  31. package/src/math/api.js +37 -14
  32. package/src/math/browser.js +67 -30
  33. package/src/math/build-font.py +237 -95
  34. package/src/math/classic.d.ts +4 -0
  35. package/src/math/delimiters.d.ts +8 -0
  36. package/src/math/delimiters.mjs +39 -0
  37. package/src/math/examples/README.md +25 -0
  38. package/src/math/examples/browser.html +10 -0
  39. package/src/math/examples/browser.mjs +24 -0
  40. package/src/math/examples/formula.mjs +12 -0
  41. package/src/math/examples/markdown.mjs +9 -0
  42. package/src/math/examples/react.tsx +19 -0
  43. package/src/math/examples/stream.mjs +19 -0
  44. package/src/math/examples/unified.mjs +26 -0
  45. package/src/math/examples/worker.mjs +7 -0
  46. package/src/math/fallbacks.js +5 -5
  47. package/src/math/font.js +59 -26
  48. package/src/math/index.d.ts +43 -0
  49. package/src/math/integration.d.ts +9 -0
  50. package/src/math/integration.mjs +28 -0
  51. package/src/math/layout.js +37 -33
  52. package/src/math/markdown-it.d.ts +6 -0
  53. package/src/math/markdown-it.mjs +45 -0
  54. package/src/math/markdown-rules.mjs +65 -0
  55. package/src/math/package-build.mjs +4 -4
  56. package/src/math/package-check.mjs +118 -0
  57. package/src/math/package-readme.mjs +8 -0
  58. package/src/math/package-verify.mjs +7 -2
  59. package/src/math/rehype.d.ts +6 -0
  60. package/src/math/rehype.mjs +37 -0
  61. package/src/math/stream.d.ts +14 -0
  62. package/src/math/stream.mjs +46 -0
  63. package/src/package.json +1 -1
  64. package/src/shell/math-resources.json +184 -25
  65. package/src/tools/build-math.mjs +23 -4
  66. package/stream.d.ts +14 -0
  67. package/stream.mjs +46 -0
  68. package/verify.mjs +7 -2
  69. package/rapier-math-1.0.1.js +0 -2883
@@ -0,0 +1,9 @@
1
+ // SPDX-License-Identifier: MIT
2
+ import MarkdownIt from 'markdown-it';
3
+ import rapierMath from 'rapier-math/markdown-it';
4
+
5
+ export const md = new MarkdownIt({html: false}).use(rapierMath);
6
+ const source = 'It costs $5 and $10. Code: `$$x$$`. Math: \\(x^2\\).\n\n$$\\frac{1}{2}$$\n';
7
+ const env = {};
8
+ console.log(md.render(source, env));
9
+ console.error(env.rapierMathErrors || []);
@@ -0,0 +1,19 @@
1
+ // SPDX-License-Identifier: MIT
2
+ import {useEffect, useMemo, useRef} from 'react';
3
+ import {render, observe} from 'rapier-math';
4
+
5
+ export function Equation({source, displayMode = false}: {source: string; displayMode?: boolean}) {
6
+ const ref = useRef<HTMLSpanElement>(null);
7
+ const result = useMemo(() => {
8
+ try { return render(source, {displayMode}); }
9
+ catch { return null; }
10
+ }, [source, displayMode]);
11
+ const svg = result && result.errors.length === 0 ? result.svg : null;
12
+ useEffect(() => {
13
+ if (ref.current && svg) return observe(ref.current);
14
+ }, [svg]); // Cleanup runs before replacement setup and on unmount.
15
+ if (!svg) return <code>{source}</code>;
16
+ // The server and initial client render use identical source/options. Fit only
17
+ // after hydration; never pass authored HTML to dangerouslySetInnerHTML.
18
+ return <span ref={ref} dangerouslySetInnerHTML={{__html: svg}} />;
19
+ }
@@ -0,0 +1,19 @@
1
+ // SPDX-License-Identifier: MIT
2
+ import MarkdownIt from 'markdown-it';
3
+ import rapierMath from 'rapier-math/markdown-it';
4
+ import {createMarkdownStream} from 'rapier-math/stream';
5
+
6
+ const md = new MarkdownIt({html: false}).use(rapierMath);
7
+ const stream = createMarkdownStream(source => md.render(source, {}), {previewEvery: 16});
8
+ for (const chunk of ['The answer is \\(', '\\frac{1}', '{2}', '\\)', '. Code: `$$x$$`.']) {
9
+ const preview = stream.write(chunk);
10
+ if (preview) console.log({phase: 'preview', ...preview});
11
+ }
12
+ const final = stream.finish();
13
+ console.log({phase: 'complete', ...final});
14
+ if (final.html !== md.render(final.source, {})) throw new Error('Batch mismatch');
15
+
16
+ // One stream per message. On replacement: cancel its transport, reset, write.
17
+ stream.reset();
18
+ stream.write('Replacement \\(y\\).');
19
+ console.log(stream.finish());
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: MIT
2
+ import {unified} from 'unified';
3
+ import remarkParse from 'remark-parse';
4
+ import remarkMath from 'remark-math';
5
+ import remarkRehype from 'remark-rehype';
6
+ import rehypeSanitize, {defaultSchema} from 'rehype-sanitize';
7
+ import rehypeRapierMath from 'rapier-math/rehype';
8
+ import rehypeStringify from 'rehype-stringify';
9
+ import {pathToFileURL} from 'node:url';
10
+
11
+ export const processor = unified().use(remarkParse)
12
+ .use(remarkMath, {singleDollarTextMath: false}).use(remarkRehype)
13
+ .use(rehypeSanitize, {
14
+ ...defaultSchema,
15
+ attributes: {...defaultSchema.attributes, code: [
16
+ ...(defaultSchema.attributes.code || []).filter(rule => !(Array.isArray(rule) && rule[0] === 'className')),
17
+ ['className', 'language-math', 'math-inline', 'math-display'],
18
+ ]},
19
+ })
20
+ .use(rehypeRapierMath).use(rehypeStringify);
21
+
22
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
23
+ const file = await processor.process('Price $5. Code `$$x$$`. Math $$x^2$$.\n\n$$\n\\frac{1}{2}\n$$');
24
+ console.log(String(file));
25
+ console.error(file.messages);
26
+ }
@@ -0,0 +1,7 @@
1
+ // SPDX-License-Identifier: MIT
2
+ import {render} from '../index.mjs';
3
+ self.onmessage = ({data: {id, source}}) => {
4
+ try { self.postMessage({id, source, result: render(source)}); }
5
+ catch (error) { self.postMessage({id, source, error: {code: error.code, message: error.message}}); }
6
+ };
7
+ // Keep a request id per message; install a reply only if it is still current.
package/index.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ // SPDX-License-Identifier: MIT
2
+ export interface MathError {
3
+ code: string;
4
+ message: string;
5
+ /** Zero-based UTF-16 offset in the formula. */
6
+ offset: number;
7
+ command?: string;
8
+ messageTruncated?: boolean;
9
+ commandTruncated?: boolean;
10
+ /** True only when refused oversized source is not embedded in diagnostic SVG. */
11
+ sourceOmitted?: boolean;
12
+ }
13
+ export interface RenderOptions {
14
+ displayMode?: boolean;
15
+ maxWidth?: number;
16
+ screen?: {fontSize: number; pixelRatio: number; dark: boolean};
17
+ }
18
+ export interface RenderResult {
19
+ svg: string;
20
+ width: number;
21
+ height: number;
22
+ depth: number;
23
+ lines: number;
24
+ fitted: boolean;
25
+ errors: MathError[];
26
+ }
27
+ /** Parser nodes are inspectable; the internal node vocabulary can grow. */
28
+ export interface MathNode {type: string; [field: string]: unknown}
29
+ /** Browser nodes (including Element, Document and DocumentFragment) satisfy this
30
+ * structural type without requiring the DOM type library in server projects. */
31
+ export interface MathContainer {readonly nodeType: number}
32
+ export const version: string;
33
+ /** Oversized source returns a bounded resource-limit diagnostic with sourceOmitted. */
34
+ export function render(source: unknown, options?: RenderOptions): RenderResult;
35
+ export function renderToString(source: unknown, options?: RenderOptions): string;
36
+ export function parse(source: string): MathNode;
37
+ export function fit(container: MathContainer): number;
38
+ export function observe(container: MathContainer): () => void;
39
+ declare const RapierMath: Readonly<{
40
+ version: typeof version; render: typeof render; renderToString: typeof renderToString;
41
+ parse: typeof parse; fit: typeof fit; observe: typeof observe;
42
+ }>;
43
+ export default RapierMath;