@simonklee/opentui-tex 0.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/LICENSE +21 -0
- package/README.md +238 -0
- package/dist/backend.d.ts +23 -0
- package/dist/binding-tex-renderable.d.ts +24 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1379 -0
- package/dist/math-layout.d.ts +3 -0
- package/dist/math-parser.d.ts +4 -0
- package/dist/math-symbols.d.ts +11 -0
- package/dist/math-types.d.ts +59 -0
- package/dist/native/ffi.d.ts +18 -0
- package/dist/native/native-renderer.d.ts +15 -0
- package/dist/native/native-tex-backend.d.ts +8 -0
- package/dist/native/platform.d.ts +1 -0
- package/dist/native.bun.js +273 -0
- package/dist/native.d.ts +2 -0
- package/dist/native.js +273 -0
- package/dist/react.d.ts +8 -0
- package/dist/react.js +1501 -0
- package/dist/solid.d.ts +8 -0
- package/dist/solid.js +1501 -0
- package/dist/tex-renderable.d.ts +67 -0
- package/dist/unicode-tex-backend.d.ts +11 -0
- package/docs/native.md +32 -0
- package/docs/releasing.md +130 -0
- package/package.json +103 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { BoxRenderable, type BoxOptions, type ImageRenderableOptions, type RenderContext } from "@opentui/core";
|
|
2
|
+
import type { TexBackend } from "./backend.js";
|
|
3
|
+
export type { TexBackend, TexRenderOutput, TexRenderRequest } from "./backend.js";
|
|
4
|
+
export type TexFallback = "message" | "throw" | "retain" | "unicode";
|
|
5
|
+
export interface TexRenderableOptions extends BoxOptions {
|
|
6
|
+
formula: string;
|
|
7
|
+
display?: boolean;
|
|
8
|
+
foreground: string;
|
|
9
|
+
background: string;
|
|
10
|
+
widthMax?: number;
|
|
11
|
+
heightMax?: number;
|
|
12
|
+
backend: TexBackend;
|
|
13
|
+
fallback?: TexFallback;
|
|
14
|
+
imageOptions?: Omit<ImageRenderableOptions, "source" | "width" | "height">;
|
|
15
|
+
onError?: (error: unknown) => void;
|
|
16
|
+
streaming?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface TexDimensions {
|
|
19
|
+
columns: number;
|
|
20
|
+
rows: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function measureTex(width: number, height: number, display: boolean, widthMax: number, heightMax: number): TexDimensions;
|
|
23
|
+
export declare function fitImageToPlacement(imageWidth: number, imageHeight: number, columns: number, rows: number, cellPxWidth: number, cellPxHeight: number): {
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
} | null;
|
|
27
|
+
export declare class TexRenderable extends BoxRenderable {
|
|
28
|
+
ready: Promise<void>;
|
|
29
|
+
private readonly backend;
|
|
30
|
+
private readonly fallback;
|
|
31
|
+
private readonly widthMax;
|
|
32
|
+
private readonly heightMax;
|
|
33
|
+
private autoWidth;
|
|
34
|
+
private autoHeight;
|
|
35
|
+
private trackExplicitDimensions;
|
|
36
|
+
private currentDimensions;
|
|
37
|
+
private readonly imageOptions?;
|
|
38
|
+
private readonly onError?;
|
|
39
|
+
private _formula;
|
|
40
|
+
private _foreground;
|
|
41
|
+
private _background;
|
|
42
|
+
private _display;
|
|
43
|
+
private _streaming;
|
|
44
|
+
private controller;
|
|
45
|
+
private committedOutput;
|
|
46
|
+
constructor(context: RenderContext, options: TexRenderableOptions);
|
|
47
|
+
get formula(): string;
|
|
48
|
+
set formula(value: string);
|
|
49
|
+
get display(): boolean;
|
|
50
|
+
set display(value: boolean);
|
|
51
|
+
get width(): number;
|
|
52
|
+
set width(value: number | "auto" | `${number}%`);
|
|
53
|
+
get height(): number;
|
|
54
|
+
set height(value: number | "auto" | `${number}%`);
|
|
55
|
+
get streaming(): boolean;
|
|
56
|
+
set streaming(value: boolean);
|
|
57
|
+
setColors(foreground: string, background: string): void;
|
|
58
|
+
protected setSnapshot(formula: string, foreground: string, background: string, display?: boolean): void;
|
|
59
|
+
whenReady(): Promise<void>;
|
|
60
|
+
private update;
|
|
61
|
+
private previewOutput;
|
|
62
|
+
private clearOutput;
|
|
63
|
+
private applyOutput;
|
|
64
|
+
private createImageChild;
|
|
65
|
+
private resizeToPlacement;
|
|
66
|
+
protected destroySelf(): void;
|
|
67
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TexBackend, TexRenderOutput, TexRenderRequest } from "./backend.js";
|
|
2
|
+
export declare const UNICODE_TEX_SOURCE_LENGTH_MAX = 4096;
|
|
3
|
+
type UnicodeTexRenderOutput = Extract<TexRenderOutput, {
|
|
4
|
+
kind: "unicode";
|
|
5
|
+
}>;
|
|
6
|
+
export declare class UnicodeTexBackend implements TexBackend {
|
|
7
|
+
renderSync(request: TexRenderRequest): UnicodeTexRenderOutput;
|
|
8
|
+
render(request: TexRenderRequest): Promise<TexRenderOutput>;
|
|
9
|
+
}
|
|
10
|
+
export declare function renderIncompleteUnicode(request: TexRenderRequest): UnicodeTexRenderOutput;
|
|
11
|
+
export {};
|
package/docs/native.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Native rendering
|
|
2
|
+
|
|
3
|
+
The native TeX backend is part of `@simonklee/opentui-tex`.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { NativeTexBackend } from "@simonklee/opentui-tex/native"
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
`NativeTexRenderer.renderAsync()` returns an owned OpenTUI `NativeImage`. The
|
|
10
|
+
caller must dispose every returned image. Cached images use independent retained
|
|
11
|
+
references, so callers can dispose results without invalidating the cache or
|
|
12
|
+
other results. `TexRenderable` manages images returned through `NativeTexBackend`.
|
|
13
|
+
|
|
14
|
+
The native renderer returns borrowed RGBA pixels to JavaScript, which copies
|
|
15
|
+
them synchronously into OpenTUI native-image ownership. The rendering path is
|
|
16
|
+
free of image encoding and decoding, but it is not zero-copy because the TeX and
|
|
17
|
+
OpenTUI native libraries are separate.
|
|
18
|
+
|
|
19
|
+
`NativeImage.takeRaw()` requires exclusive ownership. Destroy the renderer and
|
|
20
|
+
dispose all other retained references before transferring its pixels.
|
|
21
|
+
|
|
22
|
+
The package loads a prebuilt library for the current operating system,
|
|
23
|
+
architecture, and Linux libc. Set `OPENTUI_LIBC=glibc` or `OPENTUI_LIBC=musl`
|
|
24
|
+
to override Linux selection.
|
|
25
|
+
|
|
26
|
+
Standalone executables can extract the selected shared library and set
|
|
27
|
+
`OPENTUI_LATEX_NATIVE_PATH` to its absolute path.
|
|
28
|
+
|
|
29
|
+
The native context is process-owned. `destroy()` releases renderer-instance
|
|
30
|
+
queues and caches. Node 26.4 can retain its experimental FFI handle during
|
|
31
|
+
shutdown, so short-lived Node programs may need to call `process.exit()` after
|
|
32
|
+
application cleanup. Re-test this restriction when upgrading Node's FFI.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
Users install `@simonklee/opentui-tex`. Each release publishes ten npm packages:
|
|
4
|
+
the JavaScript package, eight optional native packages, and the corresponding
|
|
5
|
+
native source package. All ten have the same version.
|
|
6
|
+
|
|
7
|
+
The native packages use the same target matrix and Bun/Node library-path exports
|
|
8
|
+
as OpenTUI. npm and Bun select a binary through `os`, `cpu`, and Linux `libc`
|
|
9
|
+
constraints. The JavaScript package keeps `@opentui/core` external and declares
|
|
10
|
+
it as a required peer. React and Solid are optional peers.
|
|
11
|
+
|
|
12
|
+
## First publication
|
|
13
|
+
|
|
14
|
+
npm requires a package to exist before you can configure its trusted publisher.
|
|
15
|
+
Publish all ten packages locally with an interactive npm login and two-factor
|
|
16
|
+
authentication first. Do not create an `NPM_TOKEN` secret.
|
|
17
|
+
|
|
18
|
+
1. Commit and push the release changes to `main`.
|
|
19
|
+
2. Create and push the matching `v0.2.0` tag. Do not publish the GitHub release yet.
|
|
20
|
+
3. Run `Release` manually with `tag` set to `v0.2.0` and `dry-run` enabled.
|
|
21
|
+
4. After the run succeeds, download its `npm-packages` artifact into a clean
|
|
22
|
+
`release/` directory. Keep only the ten tarballs from that run.
|
|
23
|
+
5. From the repository root at the tagged commit, run:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npm login
|
|
27
|
+
RELEASE_TAG=v0.2.0 bun run publish:packages
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Complete npm's browser or terminal authentication prompts. The publisher uses
|
|
31
|
+
your local npm login and publishes the tested tarballs in dependency order. If
|
|
32
|
+
the process stops partway through, rerun the same command without rebuilding.
|
|
33
|
+
The publisher checks npm before skipping an already-published version.
|
|
34
|
+
|
|
35
|
+
You can instead build and test the tarballs locally with `bun run release:check`
|
|
36
|
+
at the tagged commit before running these publication commands.
|
|
37
|
+
|
|
38
|
+
After the packages exist, configure a trusted publisher for **each of the ten
|
|
39
|
+
packages**. With npm 11.19.0, the command for the main package is:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
npm trust github @simonklee/opentui-tex \
|
|
43
|
+
--repo simonklee/opentui-tex \
|
|
44
|
+
--file release.yml \
|
|
45
|
+
--env npm \
|
|
46
|
+
--allow-publish
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Repeat it for `@simonklee/opentui-tex-native-source` and each of the eight names
|
|
50
|
+
in `package.json`'s `optionalDependencies`, with the same options. The npm
|
|
51
|
+
website offers the same fields under **Settings > Trusted Publisher**:
|
|
52
|
+
|
|
53
|
+
| Field | Value |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| Provider | GitHub Actions |
|
|
56
|
+
| Organization or user | `simonklee` |
|
|
57
|
+
| Repository | `opentui-tex` |
|
|
58
|
+
| Workflow filename | `release.yml` |
|
|
59
|
+
| Environment | `npm` |
|
|
60
|
+
| Allowed action | `npm publish` |
|
|
61
|
+
|
|
62
|
+
Create the GitHub environment `npm` in `simonklee/opentui-tex` and restrict it to
|
|
63
|
+
tags named `v*`. You can also require approval before publication. Only the
|
|
64
|
+
publish job uses this environment and receives `id-token: write`; build and
|
|
65
|
+
dry-run jobs need neither. No npm token secret is needed.
|
|
66
|
+
|
|
67
|
+
Later releases use OIDC authentication and receive npm provenance automatically
|
|
68
|
+
from this public repository. After a successful trusted release, select
|
|
69
|
+
**Require two-factor authentication and disallow tokens** in each package's
|
|
70
|
+
publishing settings. Local interactive publication remains available.
|
|
71
|
+
|
|
72
|
+
See [npm's trusted publishing guide](https://docs.npmjs.com/trusted-publishers/)
|
|
73
|
+
and [`npm trust`](https://docs.npmjs.com/cli/v11/commands/npm-trust) for the
|
|
74
|
+
account-side settings. Repository files alone cannot grant npm access.
|
|
75
|
+
|
|
76
|
+
## Validate a release
|
|
77
|
+
|
|
78
|
+
Use Bun 1.3.14, Zig 0.16.0, Node 26.4 or newer, npm 11.19.0 or newer, `curl`, and
|
|
79
|
+
`tar`. Run:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
bun install --frozen-lockfile
|
|
83
|
+
bun run release:check
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The check runs type checking, JavaScript and Zig tests, all native builds, and
|
|
87
|
+
package builds. It writes ten tarballs to `release/`. A local scoped registry
|
|
88
|
+
serves those tarballs to clean npm and Bun installs. The smoke tests verify
|
|
89
|
+
platform selection, Unicode output, native rendering, and shared OpenTUI class
|
|
90
|
+
identity on both Bun and Node. They also check that imports still work without
|
|
91
|
+
the TeX binary. The publisher then validates the tarballs and prints the publish
|
|
92
|
+
order without uploading packages.
|
|
93
|
+
|
|
94
|
+
The release runner tests native execution on Linux x64. Cross-compilation does
|
|
95
|
+
not establish runtime coverage on the other seven targets.
|
|
96
|
+
|
|
97
|
+
## Publish
|
|
98
|
+
|
|
99
|
+
Version 0.2.0 is the first single-install release. It replaces the separate
|
|
100
|
+
native JavaScript package from the 0.1.0 GitHub release. Keep the existing 0.1.0
|
|
101
|
+
tags and tarballs unchanged.
|
|
102
|
+
|
|
103
|
+
For later versions, update the root version and all native dependency versions
|
|
104
|
+
together:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
npm version 0.2.1 --no-git-tag-version
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The `version` script also updates `bun.lock`. Commit the version change and the
|
|
111
|
+
release code, then create and push the matching `v<version>` tag. Publish a
|
|
112
|
+
GitHub release for that tag to run the workflow. The tag must match
|
|
113
|
+
`package.json` exactly.
|
|
114
|
+
|
|
115
|
+
You can also run `Release` manually. Leave `dry-run` enabled to validate a branch
|
|
116
|
+
or tag without publishing. To publish manually, supply the existing release tag
|
|
117
|
+
and disable `dry-run`. Select that tag as the workflow ref too, so the run can
|
|
118
|
+
deploy to the tag-restricted `npm` environment.
|
|
119
|
+
|
|
120
|
+
The workflow publishes the tested tarballs, not rebuilt copies. It publishes
|
|
121
|
+
corresponding source first, native packages next, and the JavaScript package
|
|
122
|
+
last. Stable versions use the npm `latest` tag; prereleases use `next`.
|
|
123
|
+
Publication is not atomic. If publication stops partway through, rerun the failed
|
|
124
|
+
publish job to reuse the tarballs from the successful build job. The publisher
|
|
125
|
+
checks npm before skipping an already-published version.
|
|
126
|
+
|
|
127
|
+
Do not use plain `npm publish` from the repository root for a release: that
|
|
128
|
+
would omit the native packages. The coordinated command is
|
|
129
|
+
`RELEASE_TAG=v<version> bun run publish:packages`, after
|
|
130
|
+
`bun run release:check` succeeds. The named tag must point to `HEAD`.
|
package/package.json
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@simonklee/opentui-tex",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "TeX renderable with Unicode and native image backends for OpenTUI",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"packageManager": "bun@1.3.14",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/simonklee/opentui-tex.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/simonklee/opentui-tex/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/simonklee/opentui-tex#readme",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"module": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"docs",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./native": {
|
|
31
|
+
"types": "./dist/native.d.ts",
|
|
32
|
+
"bun": "./dist/native.bun.js",
|
|
33
|
+
"import": "./dist/native.js"
|
|
34
|
+
},
|
|
35
|
+
"./react": {
|
|
36
|
+
"types": "./dist/react.d.ts",
|
|
37
|
+
"import": "./dist/react.js"
|
|
38
|
+
},
|
|
39
|
+
"./solid": {
|
|
40
|
+
"types": "./dist/solid.d.ts",
|
|
41
|
+
"import": "./dist/solid.js"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "bun run build:native && bun run build:package",
|
|
46
|
+
"build:package": "bun scripts/build-package.ts",
|
|
47
|
+
"build:demo": "bun build demo/app.ts --outdir dist --target bun --packages external",
|
|
48
|
+
"build:demo:node": "bun build demo/app.ts --outfile dist/app.node.js --target node --packages external",
|
|
49
|
+
"build:native": "bash scripts/build-native",
|
|
50
|
+
"build:native:all": "bash scripts/build-native --all",
|
|
51
|
+
"build:release": "bun run build:package && bun run build:native:all && bun scripts/package-release.ts",
|
|
52
|
+
"dev": "bun demo/app.ts",
|
|
53
|
+
"start": "bun demo/app.ts",
|
|
54
|
+
"start:node": "bun run build:demo:node && node --permission --allow-fs-read=.. --allow-child-process --allow-worker --allow-ffi --experimental-ffi dist/app.node.js",
|
|
55
|
+
"test": "bun test src/document.test.ts src/tex-renderable.test.ts src/unicode-tex-backend.test.ts",
|
|
56
|
+
"test:native": "bun run build:native && bun run test:native:zig && bun test src/native",
|
|
57
|
+
"test:native:zig": "bash scripts/bootstrap-native && zig build test",
|
|
58
|
+
"test:release": "bun scripts/test-release.ts",
|
|
59
|
+
"test:all": "bun run test && bun run test:native",
|
|
60
|
+
"release:check": "bun run typecheck && bun run test:all && bun run build:release && bun run test:release && bun scripts/publish-packages.ts --dry-run",
|
|
61
|
+
"publish:packages": "bun scripts/publish-packages.ts",
|
|
62
|
+
"typecheck": "tsc --noEmit",
|
|
63
|
+
"version": "bun scripts/version.ts && bun install --lockfile-only"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"string-width": "7.2.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"@opentui/core": "0.0.0-20260812-1d34234c",
|
|
70
|
+
"@opentui/react": "0.0.0-20260812-1d34234c",
|
|
71
|
+
"@opentui/solid": "0.0.0-20260812-1d34234c"
|
|
72
|
+
},
|
|
73
|
+
"peerDependenciesMeta": {
|
|
74
|
+
"@opentui/react": { "optional": true },
|
|
75
|
+
"@opentui/solid": { "optional": true }
|
|
76
|
+
},
|
|
77
|
+
"devDependencies": {
|
|
78
|
+
"@opentui/core": "0.0.0-20260812-1d34234c",
|
|
79
|
+
"@opentui/react": "0.0.0-20260812-1d34234c",
|
|
80
|
+
"@opentui/solid": "0.0.0-20260812-1d34234c",
|
|
81
|
+
"@types/bun": "latest",
|
|
82
|
+
"@types/node": "^24.0.0",
|
|
83
|
+
"typescript": "^5"
|
|
84
|
+
},
|
|
85
|
+
"optionalDependencies": {
|
|
86
|
+
"@simonklee/opentui-tex-native-darwin-arm64": "0.2.0",
|
|
87
|
+
"@simonklee/opentui-tex-native-darwin-x64": "0.2.0",
|
|
88
|
+
"@simonklee/opentui-tex-native-linux-arm64": "0.2.0",
|
|
89
|
+
"@simonklee/opentui-tex-native-linux-arm64-musl": "0.2.0",
|
|
90
|
+
"@simonklee/opentui-tex-native-linux-x64": "0.2.0",
|
|
91
|
+
"@simonklee/opentui-tex-native-linux-x64-musl": "0.2.0",
|
|
92
|
+
"@simonklee/opentui-tex-native-win32-arm64": "0.2.0",
|
|
93
|
+
"@simonklee/opentui-tex-native-win32-x64": "0.2.0"
|
|
94
|
+
},
|
|
95
|
+
"publishConfig": {
|
|
96
|
+
"access": "public",
|
|
97
|
+
"registry": "https://registry.npmjs.org/"
|
|
98
|
+
},
|
|
99
|
+
"engines": {
|
|
100
|
+
"bun": ">=1.3.0",
|
|
101
|
+
"node": ">=26.4.0"
|
|
102
|
+
}
|
|
103
|
+
}
|