rapier-markdown-kit 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 (55) hide show
  1. package/LICENSE +40 -0
  2. package/README.md +102 -0
  3. package/dist/agent/vendor/pretext/LICENSE +21 -0
  4. package/dist/agent/vendor/pretext/NOTICE +15 -0
  5. package/dist/agent/vendor/pretext/SOURCE.json +85 -0
  6. package/dist/agent/vendor/pretext/analysis.js +1234 -0
  7. package/dist/agent/vendor/pretext/bidi.js +151 -0
  8. package/dist/agent/vendor/pretext/generated/bidi-data.js +3831 -0
  9. package/dist/agent/vendor/pretext/layout.js +308 -0
  10. package/dist/agent/vendor/pretext/line-break.js +636 -0
  11. package/dist/agent/vendor/pretext/line-text.js +44 -0
  12. package/dist/agent/vendor/pretext/measurement.js +189 -0
  13. package/dist/agent/vendor/pretext/package.json +3 -0
  14. package/dist/agent/vendor/pretext/rich-inline.js +291 -0
  15. package/dist/agent/will.mjs +167 -0
  16. package/dist/kit/assets.mjs +3 -0
  17. package/dist/kit/conformance/01-inline.expected.json +82 -0
  18. package/dist/kit/conformance/01-inline.md +10 -0
  19. package/dist/kit/conformance/02-width-x-align.expected.json +83 -0
  20. package/dist/kit/conformance/02-width-x-align.md +12 -0
  21. package/dist/kit/conformance/03-wrap-around-silhouette.expected.json +177 -0
  22. package/dist/kit/conformance/03-wrap-around-silhouette.md +12 -0
  23. package/dist/kit/conformance/04-wrap-box.expected.json +173 -0
  24. package/dist/kit/conformance/04-wrap-box.md +12 -0
  25. package/dist/kit/conformance/05-behind.expected.json +122 -0
  26. package/dist/kit/conformance/05-behind.md +12 -0
  27. package/dist/kit/conformance/06-front.expected.json +122 -0
  28. package/dist/kit/conformance/06-front.md +12 -0
  29. package/dist/kit/conformance/07-rotate-raster.expected.json +179 -0
  30. package/dist/kit/conformance/07-rotate-raster.md +12 -0
  31. package/dist/kit/conformance/08-drawing-rotation.expected.json +188 -0
  32. package/dist/kit/conformance/08-drawing-rotation.md +12 -0
  33. package/dist/kit/conformance/09-drawing-ring-interior.expected.json +229 -0
  34. package/dist/kit/conformance/09-drawing-ring-interior.md +12 -0
  35. package/dist/kit/conformance/10-both-sides.expected.json +221 -0
  36. package/dist/kit/conformance/10-both-sides.md +10 -0
  37. package/dist/kit/conformance/11-neighbour-skips-image.expected.json +160 -0
  38. package/dist/kit/conformance/11-neighbour-skips-image.md +13 -0
  39. package/dist/kit/conformance/12-heading-barrier.expected.json +164 -0
  40. package/dist/kit/conformance/12-heading-barrier.md +12 -0
  41. package/dist/kit/conformance/13-rtl-text.expected.json +179 -0
  42. package/dist/kit/conformance/13-rtl-text.md +8 -0
  43. package/dist/kit/conformance/README.md +99 -0
  44. package/dist/kit/conformance/measurer.mjs +0 -0
  45. package/dist/kit/conformance/run.mjs +123 -0
  46. package/dist/kit/index.mjs +6 -0
  47. package/dist/kit/layout.mjs +2 -0
  48. package/dist/kit/marks.mjs +2 -0
  49. package/dist/kit/model.mjs +3 -0
  50. package/dist/kit/will.mjs +2 -0
  51. package/dist/layout/model.mjs +364 -0
  52. package/dist/spec/md-assets.mjs +323 -0
  53. package/dist/spec/md-layout.mjs +117 -0
  54. package/dist/spec/md-marks.mjs +78 -0
  55. package/package.json +33 -0
package/LICENSE ADDED
@@ -0,0 +1,40 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jack Skipworth
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ Files under this licence carry `SPDX-License-Identifier: MIT` in their first lines: the standard's
24
+ grammar and marks (`spec/md-layout.mjs`, `spec/md-marks.mjs`), the layout model and line planner
25
+ (`layout/model.mjs`), the Will grammar (`agent/will.mjs`), the picture appendix reader and writer
26
+ (`spec/md-assets.mjs`), the two shared-page reference readers (`tools/read-shared-page.mjs`,
27
+ `tools/read-shared-page.py`), and the host helper `packages/rapier-embed/embed.mjs`. The vendored Pretext (`agent/vendor/pretext`) and micromark carry their
28
+ own MIT notices. Everything else in Rapier is AGPL-3.0-only (see `LICENSE`).
29
+
30
+ The picture appendix reader and writer used to be part of `images/assets.mjs`, a file that also
31
+ holds JPEG XL/raster header inspection and SVG sanitizing -- both of which reach the editor's own
32
+ AGPL-3.0-only decoders (`images/raster.mjs`, `draw/font.mjs`), so the whole file could not honestly
33
+ sit in this list. The appendix logic (`parseAssets`, `documentAssets`, `imageEnvironment`,
34
+ `mayRetireImageDefinitions`, `retireDeletedImageDefinitions`, `assetOmissions`, `isAssetBlock`,
35
+ `serializeAsset`, `appendAssetText`, `appendAsset`, and the small markdown-it plumbing they share)
36
+ depends on nothing but a markdown-it factory, so it lives in `spec/md-assets.mjs`; `images/assets.mjs`
37
+ re-imports and re-exports that surface unchanged (one owner, no copy) and keeps everything that
38
+ needs the AGPL decoders, so it is AGPL-3.0-only like the rest of the editor. The `rapier-markdown-kit`
39
+ package re-exports `spec/md-assets.mjs` directly, never `images/assets.mjs`, so its import graph
40
+ never touches AGPL code.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # rapier-markdown-kit
2
+
3
+ Read and write the Rapier Markdown standard -- picture layout, text marks, Will intent markers and
4
+ the picture appendix -- and lay text out around pictures exactly as Rapier does, without taking the
5
+ Rapier editor.
6
+
7
+ **MIT. No Rapier required. No npm dependencies.** The text layout engine it uses, Pretext, is
8
+ vendored inside the package with its own MIT licence. Nothing from the editor, Draw, the image
9
+ decoders or the apps is in here.
10
+
11
+ ## Install
12
+
13
+ Node 22 or newer:
14
+
15
+ ```sh
16
+ npm install rapier-markdown-kit
17
+ ```
18
+
19
+ ## What it gives you
20
+
21
+ | Import | What it is |
22
+ | --- | --- |
23
+ | `rapier-markdown-kit/layout` | The `md-layout:v1` comment a picture carries: parse it, validate it, write it back. |
24
+ | `rapier-markdown-kit/marks` | Text colour and page-break markers. |
25
+ | `rapier-markdown-kit/model` | Occupancy profiles and the line planner: the wrapping itself. |
26
+ | `rapier-markdown-kit/will` | The Will/1 grammar (a separate, optional standard): the markers around an agent's intent regions. |
27
+ | `rapier-markdown-kit/assets` | The picture appendix: the reference definitions a document's pictures live in. It never decodes a picture. |
28
+ | `rapier-markdown-kit` | All five in one import. |
29
+
30
+ Every convention here is plain Markdown or an HTML comment that other readers ignore. Laying lines
31
+ out exactly as Rapier does also takes the same font metrics, which the host supplies (below).
32
+
33
+ ## Example
34
+
35
+ Save this as `example.mjs` in the folder you installed into and run `node example.mjs`. It prints
36
+ `lines: 4 height: 80`.
37
+
38
+ ```js
39
+ import {parseLayout} from 'rapier-markdown-kit/layout';
40
+ import {parseProfile, pictureSlices, prepareRun, flowLines, prepareRichInline} from 'rapier-markdown-kit/model';
41
+ const {loadDocuments, installMeasurer} = await import(new URL(
42
+ './dist/kit/conformance/measurer.mjs', import.meta.resolve('rapier-markdown-kit/package.json')));
43
+
44
+ // Text metrics: the widths the conformance documents recorded in Rapier's own browser, standing in
45
+ // for a font shaper so the example runs anywhere (see "What the host supplies").
46
+ installMeasurer(loadDocuments());
47
+
48
+ // 1. Parse the layout comment a picture carries.
49
+ const layout = parseLayout('<!--md-layout:v1 width=40% wrap=around x=25%-->');
50
+ // => {width: 40, wrap: 'around', x: 25}
51
+
52
+ // 2. The picture's shape: the occupancy descriptor Rapier's exports carry beside a picture
53
+ // (`data-rapier-occupancy`, one left-right pair per horizontal band), placed as obstacles.
54
+ const profile = parseProfile('0.1-0.9|0.2-0.8|0.3-0.7');
55
+ const obstacles = pictureSlices(profile, /* x */ 0, /* y */ 0, /* width */ 120, /* height */ 90);
56
+
57
+ // 3. Plan the lines of a paragraph around those obstacles.
58
+ const text = 'This anchor paragraph carries enough ordinary prose', font = 'normal 400 17.6px Geist, system-ui, sans-serif';
59
+ const run = prepareRun(text, font);
60
+ const flow = prepareRichInline([{text: run.raw, font, letterSpacing: 0}]);
61
+ const plan = flowLines(flow, /* column width */ 300, /* top */ 0, obstacles, /* line height */ 20, /* min slot */ 40);
62
+ // Each line carries its own x, y and width, and the text fragments laid into it.
63
+ console.log('lines:', plan.lines.length, 'height:', plan.height); // lines: 4 height: 80
64
+ ```
65
+
66
+ ## What the host supplies
67
+
68
+ `prepareRun` and `prepareRichInline` measure text the way a browser does: they need a global
69
+ `OffscreenCanvas` (or a DOM `document`) whose `getContext('2d')` has a settable `font` and a
70
+ `measureText(text)` returning `{width}`. A browser has one already; in Node, put those two members
71
+ in front of whatever shaper you have. The example replays recorded measurements instead, and a
72
+ query they never recorded falls back to summing single characters, without kerning or shaping.
73
+
74
+ `alphaProfile(image)` samples a decoded `<img>` through a canvas, so it needs a browser. Without
75
+ one, read the saved descriptor with `parseProfile`, or sample the picture with your own image
76
+ library. `polygonProfile` and `rasterTiltProfile` are plain geometry.
77
+
78
+ The appendix parser takes a markdown-it-compatible parser factory from the caller
79
+ (`parseAssets(source, factory)`, or once through `configureParser`); no parser is bundled.
80
+
81
+ ## Conformance
82
+
83
+ ```sh
84
+ node node_modules/rapier-markdown-kit/dist/kit/conformance/run.mjs
85
+ ```
86
+
87
+ Thirteen small documents, each with the line boxes Rapier's own export produced for it. The runner
88
+ reports two things separately. **Preservation**: every layout comment round-trips exactly (12 of
89
+ the 12 documents that carry one). **Presentation**: how closely the planned lines match (4 agree
90
+ within 2px, 9 are close, none differ); each close row has a named cause, given in the runner's
91
+ output and in `dist/kit/conformance/README.md`. `--impl path/to/module.mjs` runs another
92
+ implementation against the same documents; `--tolerance 2` sets the pixel tolerance.
93
+
94
+ ## Licence
95
+
96
+ MIT, the full text in `LICENSE`; every module keeps its own MIT line. Pretext's licence, notice and
97
+ pinned source inventory are in `dist/agent/vendor/pretext/`. The Rapier editor is AGPL-3.0-only and
98
+ none of it is in this package. The kit's version is its own and does not follow the editor's.
99
+
100
+ ## Where the modules live
101
+
102
+ Each module of the standard has one home in the Rapier source (`spec/`, `layout/`, `agent/`), where Rapier itself reads it; `dist/` is that closure copied byte for byte, so an installed copy needs nothing beside it.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pretext contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,15 @@
1
+ Pretext 0.0.9
2
+ Copyright (c) 2026 Pretext contributors
3
+ https://github.com/chenglou/pretext
4
+ MIT license: see LICENSE.
5
+
6
+ Vendored from the user-supplied pretext-main source snapshot.
7
+ SOURCE.json records every original and generated module hash.
8
+ Node's built-in TypeScript transform generated these ESM modules;
9
+ the upstream runtime implementation is unchanged.
10
+
11
+ Upstream README credits Sebastian Markbage's text-layout research:
12
+ canvas measureText for shaping, bidi from pdf.js, and streaming line breaking.
13
+ Upstream src/bidi.ts identifies its simplified bidi metadata helper as
14
+ forked from pdf.js through Sebastian's text-layout. This provenance applies
15
+ to the generated bidi.js module as well.
@@ -0,0 +1,85 @@
1
+ {
2
+ "package": "@chenglou/pretext",
3
+ "version": "0.0.9",
4
+ "releaseDate": "2026-09-07",
5
+ "repository": "https://github.com/chenglou/pretext",
6
+ "sourceSnapshot": "User-supplied pretext-main archive; no commit identifier included",
7
+ "license": "MIT",
8
+ "licenseSha256": "e9355cb16457e81acd97dac2e50f2f8bbf2a9a464025f9c46db3680cf9598846",
9
+ "exports": {
10
+ ".": "./layout.js",
11
+ "./rich-inline": "./rich-inline.js"
12
+ },
13
+ "compiler": {
14
+ "runtime": "v24.19.0",
15
+ "api": "node:module.stripTypeScriptTypes",
16
+ "mode": "transform"
17
+ },
18
+ "changes": "TypeScript erased by the Node built-in transform; attribution header added. Runtime semantics and module imports preserved.",
19
+ "files": [
20
+ {
21
+ "source": "src/analysis.ts",
22
+ "sourceBytes": 47015,
23
+ "sourceSha256": "45d06ff67f5e7c8334fd3188bc6e3d13c582c36714cbf584aca5c4280587f571",
24
+ "output": "analysis.js",
25
+ "outputBytes": 44912,
26
+ "outputSha256": "68f7c705892b03c6b2e93b5f86ec4216231246607aac11c2dab98ed06f0f602b"
27
+ },
28
+ {
29
+ "source": "src/bidi.ts",
30
+ "sourceBytes": 6034,
31
+ "sourceSha256": "70f7f01dcd866076b68dbf2a3c398364aceaba2ccf98037e77e0b3b8bcfbeaa5",
32
+ "output": "bidi.js",
33
+ "outputBytes": 5176,
34
+ "outputSha256": "f69a132df81d5ad666bd35a295e10bf2549f8f0bc6470ab37fe361eafd0162b5"
35
+ },
36
+ {
37
+ "source": "src/generated/bidi-data.ts",
38
+ "sourceBytes": 21681,
39
+ "sourceSha256": "745211b804d907af78afb6c1ed87eff6d7454a5e85152a6129eb7b3bf0f6f262",
40
+ "output": "generated/bidi-data.js",
41
+ "outputBytes": 44541,
42
+ "outputSha256": "2f3fd15a0dbc1df87fefc53e23d261419b392feab32e1288a3d7d568cd368fea"
43
+ },
44
+ {
45
+ "source": "src/layout.ts",
46
+ "sourceBytes": 22096,
47
+ "sourceSha256": "2b44bcc39ecf287de621d40dbc443815cf2faa8c976a98de8a02f1639b782b9d",
48
+ "output": "layout.js",
49
+ "outputBytes": 13886,
50
+ "outputSha256": "ed52968b68a8d7fb3726333ff522f41f10a779d2c072ba05eb9aa841a6daf469"
51
+ },
52
+ {
53
+ "source": "src/line-break.ts",
54
+ "sourceBytes": 30545,
55
+ "sourceSha256": "f226213c179d65adea48b849040719349c8c3928519348d03d38b7b41f344796",
56
+ "output": "line-break.js",
57
+ "outputBytes": 29515,
58
+ "outputSha256": "30d83886d6e681fec3da72073749d14f7d01e5371cc907554596782df9c3de7c"
59
+ },
60
+ {
61
+ "source": "src/line-text.ts",
62
+ "sourceBytes": 2234,
63
+ "sourceSha256": "5e21684d995df8c30324c03a14b8a0bc3a579ce169a0e10b6d579b6aeee577dc",
64
+ "output": "line-text.js",
65
+ "outputBytes": 1994,
66
+ "outputSha256": "d7485c43086420e37418b68a49bf42acc45c13a6045d170eecbf37df4738a03c"
67
+ },
68
+ {
69
+ "source": "src/measurement.ts",
70
+ "sourceBytes": 8430,
71
+ "sourceSha256": "7768e0452c9dcc027182a3ed8131ed4a26d1d6099c9642ed93389a1c52342b01",
72
+ "output": "measurement.js",
73
+ "outputBytes": 7468,
74
+ "outputSha256": "58d8827d10367319d667c54056ef1200b0850a4ef6d298eaad486217cc84277e"
75
+ },
76
+ {
77
+ "source": "src/rich-inline.ts",
78
+ "sourceBytes": 15398,
79
+ "sourceSha256": "5a7e5d339e1f703d52928913e3b7d6a5f5df04bdfdd365f47c1890dde3b61964",
80
+ "output": "rich-inline.js",
81
+ "outputBytes": 11352,
82
+ "outputSha256": "60b7d96428236a8f12f7d6fdbd7d402c8c3b39e4da9cd4bf83b1d3dee27a7418"
83
+ }
84
+ ]
85
+ }