rapier-html 1.2.46 → 1.2.48
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/BUILD.json +4 -4
- package/README.md +12 -11
- package/dist/ledger/carried.mjs +17 -8
- package/dist/ledger/diff/concerns.mjs +2 -2
- package/dist/ledger/document-fonts.mjs +60 -6
- package/dist/ledger/source.mjs +31 -2
- package/dist/ledger/vendor/SOURCES.json +253 -0
- package/dist/ledger/vendor/entities/decode-codepoint.mjs +27 -0
- package/dist/ledger/vendor/entities.mjs +499 -0
- package/dist/ledger/vendor/linkify-it.mjs +427 -0
- package/dist/ledger/vendor/markdown-it.mjs +4027 -0
- package/dist/ledger/vendor/markdown-plugins.mjs +1328 -11
- package/dist/ledger/vendor/markdown-runtime.mjs +3 -11
- package/dist/ledger/vendor/mdurl/index.mjs +11 -0
- package/dist/ledger/vendor/mdurl/lib/decode.mjs +107 -0
- package/dist/ledger/vendor/mdurl/lib/encode.mjs +77 -0
- package/dist/ledger/vendor/mdurl/lib/format.mjs +20 -0
- package/dist/ledger/vendor/mdurl/lib/parse.mjs +231 -0
- package/dist/ledger/vendor/punycode.mjs +282 -0
- package/dist/ledger/vendor/uc.micro.mjs +49 -0
- package/dist/page.mjs +11 -3
- package/dist/rapier.html +97 -51
- package/dist/wrap.mjs +10 -5
- package/package.json +1 -1
- package/dist/ledger/vendor/BROWSER-ENTITIES.json +0 -36
- package/dist/ledger/vendor/MARKDOWN-RUNTIME.json +0 -136
- package/dist/ledger/vendor/MARKDOWNIT.json +0 -582
- package/dist/ledger/vendor/markdown-plugins.json +0 -46
package/BUILD.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "rapier-html",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.48",
|
|
4
4
|
"path": "dist/rapier.html",
|
|
5
|
-
"bytes":
|
|
6
|
-
"sha256": "
|
|
7
|
-
"builtAt": "2026-10-
|
|
5
|
+
"bytes": 5967960,
|
|
6
|
+
"sha256": "be629bc50b6a201e8889ce4c2768ee350015e8dfbafe7cfe880a6a6113865595",
|
|
7
|
+
"builtAt": "2026-10-28T02:28:38.799Z",
|
|
8
8
|
"node": "v22.23.4",
|
|
9
9
|
"canonical": true,
|
|
10
10
|
"packing": "zopfli",
|
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@ Turn Markdown into one offline HTML file that contains the full Rapier editor.
|
|
|
7
7
|
<img src="https://raw.githubusercontent.com/jackskip22/rapier-plugins/main/assets/write-390-light.png" alt="The Rapier editor on a phone: a launch plan with an agent's change marked" width="320">
|
|
8
8
|
</picture>
|
|
9
9
|
|
|
10
|
-
Try it: `npx rapier-html@1.2.
|
|
11
|
-
Install: `npm install rapier-html@1.2.
|
|
10
|
+
Try it: `npx rapier-html@1.2.48 notes.md`, then open `notes.rapier.html` in any browser.
|
|
11
|
+
Install: `npm install rapier-html@1.2.48`.
|
|
12
12
|
|
|
13
13
|
It opens on a phone or computer, with no account. People read, edit, draw and paint; agents hand over documents, show
|
|
14
14
|
what changed and get the edited copy back.
|
|
@@ -21,19 +21,20 @@ The file needs no hosted workspace.
|
|
|
21
21
|
- Where scripts don't run (a mail preview, a strict viewer), the file shows the document's words.
|
|
22
22
|
- `--return` adds a one-use Send back address from the agent door.
|
|
23
23
|
- `--view draw` opens on Draw. `--compare original.md` opens the edit with its diff; `--by <name>` attributes it.
|
|
24
|
+
- `--editor page.html` uses another Rapier page as the editor, such as one the agent door exported.
|
|
24
25
|
- `writePage(text, name)` makes the page in one call; `unwrap` gives the document back, exactly.
|
|
25
26
|
|
|
26
27
|
Needs Node 22 or newer.
|
|
27
28
|
|
|
28
29
|
```sh
|
|
29
|
-
npx -- rapier-html@1.2.
|
|
30
|
-
npx -- rapier-html@1.2.
|
|
31
|
-
npx -- rapier-html@1.2.
|
|
32
|
-
npx -- rapier-html@1.2.
|
|
33
|
-
npx -- rapier-html@1.2.
|
|
34
|
-
npx -- rapier-html@1.2.
|
|
35
|
-
npx -- rapier-html@1.2.
|
|
36
|
-
npm install rapier-html@1.2.
|
|
30
|
+
npx -- rapier-html@1.2.48 notes.md # the editor, notes.md inside it, written beside the file
|
|
31
|
+
npx -- rapier-html@1.2.48 notes.md --view draw # opens on Draw: sketch and paint, the document behind it
|
|
32
|
+
npx -- rapier-html@1.2.48 notes.md --include draw,math # carries Draw and Math (default: what the document needs)
|
|
33
|
+
npx -- rapier-html@1.2.48 notes.md --drawing sketch.svg # carries a drawing, opened on Draw over the document
|
|
34
|
+
npx -- rapier-html@1.2.48 revised.md --compare original.md # opens showing what changed
|
|
35
|
+
npx -- rapier-html@1.2.48 notes.md --return <return_url> --return-expires-at <return_expires_at> # Send back
|
|
36
|
+
npx -- rapier-html@1.2.48 notes.md out.html # a named output
|
|
37
|
+
npm install rapier-html@1.2.48 # as a library: writePage, unwrap
|
|
37
38
|
```
|
|
38
39
|
|
|
39
40
|
The first `--` is for npm, so `--help` reaches the command. It never overwrites a file.
|
|
@@ -52,7 +53,7 @@ Will markers in the Markdown (`keep`, `append`, `edit`) control what agents may
|
|
|
52
53
|
## Send an edited document back
|
|
53
54
|
|
|
54
55
|
1. Call `show {target:"return"}` on the Rapier agent door for the document's workspace.
|
|
55
|
-
2. Pass its `return_url` and `return_expires_at` as `--return
|
|
56
|
+
2. Pass its `return_url` and `return_expires_at` as `--return <return_url> --return-expires-at <return_expires_at>`,
|
|
56
57
|
or `wrap(..., {return: return_url, return_expires_at})`. Only `https://mcp.rapier.website/return/…` is accepted.
|
|
57
58
|
Share then shows Send back; a page without an address doesn't.
|
|
58
59
|
3. The person edits offline and taps Send back. The source and filename go once; the page shows acceptance or
|
package/dist/ledger/carried.mjs
CHANGED
|
@@ -56,11 +56,19 @@ export function documentTrailer(text, options) {
|
|
|
56
56
|
export function writeDocument(text, options) {
|
|
57
57
|
return text + documentTrailer(text, options);
|
|
58
58
|
}
|
|
59
|
+
function trailerOpening(source) {
|
|
60
|
+
const marker = '<!-- rapier-carried/1', at = source.lastIndexOf(marker);
|
|
61
|
+
if (at < 0) return null;
|
|
62
|
+
if (source.slice(at - 2, at + marker.length + 1) === OPEN) return {start: at - 2, body: at + marker.length + 1};
|
|
63
|
+
const before = /(?:\r\n|\r|\n){2}$/.exec(source.slice(Math.max(0, at - 4), at));
|
|
64
|
+
const after = /^(?:\r\n|\r|\n)/.exec(source.slice(at + marker.length, at + marker.length + 2));
|
|
65
|
+
return before && after ? {start: at - before[0].length, body: at + marker.length + after[0].length} : null;
|
|
66
|
+
}
|
|
59
67
|
function unfinishedTrailer(source) {
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
const opening = trailerOpening(source);
|
|
69
|
+
if (!opening) return false;
|
|
62
70
|
let fence = null;
|
|
63
|
-
for (const line of source.slice(0,
|
|
71
|
+
for (const line of source.slice(0, opening.start).split(/\r\n?|\n/)) {
|
|
64
72
|
const found = /^ {0,3}(`{3,}|~{3,})/.exec(line);
|
|
65
73
|
if (!found) continue;
|
|
66
74
|
if (!fence) fence = found[1];
|
|
@@ -69,17 +77,18 @@ function unfinishedTrailer(source) {
|
|
|
69
77
|
return !fence;
|
|
70
78
|
}
|
|
71
79
|
export function readDocument(source) {
|
|
72
|
-
|
|
80
|
+
const closing = /(?:\r\n|\r|\n)-->(?:\r\n|\r|\n)$/.exec(source.slice(-7));
|
|
81
|
+
if (!closing) {
|
|
73
82
|
if (unfinishedTrailer(source)) throw fault('unfinished document metadata');
|
|
74
83
|
return {text: source, ledger: null, authorship: null};
|
|
75
84
|
}
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
85
|
+
const opening = trailerOpening(source);
|
|
86
|
+
if (!opening) return {text: source, ledger: null, authorship: null};
|
|
78
87
|
let parts;
|
|
79
|
-
try { parts = JSON.parse(source.slice(
|
|
88
|
+
try { parts = JSON.parse(source.slice(opening.body, -closing[0].length)); }
|
|
80
89
|
catch (_) { throw fault('invalid document metadata'); }
|
|
81
90
|
if (!parts || Object.keys(parts).length !== 2 || !Object.hasOwn(parts, 'ledger') || !Object.hasOwn(parts, 'authorship')) throw fault('invalid document parts');
|
|
82
|
-
const text = source.slice(0,
|
|
91
|
+
const text = source.slice(0, opening.start);
|
|
83
92
|
return {text, ...validateParts(text, parts)};
|
|
84
93
|
}
|
|
85
94
|
|
|
@@ -5,7 +5,7 @@ export function separate(c, endA = c.before.length, endB = c.after.length) {
|
|
|
5
5
|
const {before, after, safe, raw, spend} = c;
|
|
6
6
|
if (!raw) for (let i = c.result.length - 1; i > 0; i--) {
|
|
7
7
|
const p = c.result[i - 1], q = c.result[i], side = p[0][0] === p[0][1] ? 1 : p[1][0] === p[1][1] ? 0 : -1, text = side ? after : before;
|
|
8
|
-
if (side >= 0 && !/\S/.test(text.slice(...p[side]))) {
|
|
8
|
+
if (!c.evidence && side >= 0 && !/\S/.test(text.slice(...p[side]))) {
|
|
9
9
|
let n = 0;
|
|
10
10
|
while (p[0][1] + n < q[0][0] && text[p[side][0] + n] === text[p[side][1] + n] && spend()) n++;
|
|
11
11
|
if (p[0][1] + n === q[0][0] && p.slice(0, 2).every((span, k) => safe(k ? after : before, span[0] + n) && safe(k ? after : before, span[1] + n)))
|
|
@@ -20,7 +20,7 @@ export function separate(c, endA = c.before.length, endB = c.after.length) {
|
|
|
20
20
|
keep[3][0] = x[0] === x[1] ? 2 : y[0] === y[1] ? 0 : 1;
|
|
21
21
|
c.result.splice(i - 1, 2, [x, y, false, keep[3]]);
|
|
22
22
|
}
|
|
23
|
-
if (!raw) for (let i = 0; i < c.result.length; i++) {
|
|
23
|
+
if (!raw && !c.evidence) for (let i = 0; i < c.result.length; i++) {
|
|
24
24
|
const p = c.result[i], q = c.result[i + 1], side = p[0][0] === p[0][1] ? 1 : p[1][0] === p[1][1] ? 0 : -1;
|
|
25
25
|
if (side < 0 || p[2]) continue;
|
|
26
26
|
const text = side ? after : before;
|
|
@@ -18,12 +18,19 @@ function parserFor(parser) {
|
|
|
18
18
|
return md;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
const sourceMetadataFields = ['license', 'origin'];
|
|
22
|
+
function sourceMetadata(value) {
|
|
23
|
+
return Object.fromEntries(sourceMetadataFields.filter(field => value[field] != null).map(field => [field, value[field]]));
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
function faceOf(value) {
|
|
22
27
|
const family = normalizeFontFamily(value?.family), style = value?.style || 'normal';
|
|
23
28
|
const weight = value?.weight ?? 400, stretch = value?.stretch ?? 100;
|
|
24
29
|
if (!family || !['normal', 'italic', 'oblique'].includes(style) || !Number.isFinite(weight) || weight < 1 || weight > 1000 ||
|
|
25
30
|
!Number.isFinite(stretch) || stretch <= 0 || stretch > 1000) return null;
|
|
26
31
|
const result = {family, style, weight, stretch};
|
|
32
|
+
if (value.subsetted != null && typeof value.subsetted !== 'boolean') return null;
|
|
33
|
+
if (value.subsetted === true || value.subset?.subset === true) result.subsetted = true;
|
|
27
34
|
if (value.weightRange != null) {
|
|
28
35
|
const range = value.weightRange;
|
|
29
36
|
if (!Array.isArray(range) || range.length !== 2 || range.some(number => !Number.isFinite(number) || number < 1 || number > 1000) || range[0] > range[1]) return null;
|
|
@@ -44,6 +51,25 @@ function faceOf(value) {
|
|
|
44
51
|
if (!/^f[0-9a-f]{24}$/.test(value.sourceId)) return null;
|
|
45
52
|
result.sourceId = value.sourceId;
|
|
46
53
|
}
|
|
54
|
+
if (value.license != null) {
|
|
55
|
+
const license = value.license;
|
|
56
|
+
if (!license || !['OFL-1.0', 'OFL-1.1', 'Apache-2.0', 'Ubuntu-font-1.0'].includes(license.id) ||
|
|
57
|
+
typeof license.text !== 'string' || !license.text.trim() || new TextEncoder().encode(license.text).length > 128 * 1024 ||
|
|
58
|
+
typeof license.url !== 'string' || typeof license.sri !== 'string' || !/^sha384-[A-Za-z0-9+/]{64}$/.test(license.sri)) return null;
|
|
59
|
+
let url;
|
|
60
|
+
try { url = new URL(license.url); } catch (_) { return null; }
|
|
61
|
+
if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash) return null;
|
|
62
|
+
result.license = {id: license.id, text: license.text, url: license.url, sri: license.sri};
|
|
63
|
+
}
|
|
64
|
+
if (value.origin != null) {
|
|
65
|
+
const origin = value.origin;
|
|
66
|
+
if (!result.license || result.subsetted || !origin || origin.catalog !== 'google-fonts' ||
|
|
67
|
+
typeof origin.family !== 'string' || !/^[a-z0-9][a-z0-9-]{0,95}$/.test(origin.family) ||
|
|
68
|
+
typeof origin.version !== 'string' || !origin.version || origin.version.length > 128 || /[\u0000-\u001f\u007f]/u.test(origin.version) ||
|
|
69
|
+
typeof origin.file !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}\.woff2$/.test(origin.file) ||
|
|
70
|
+
typeof origin.sri !== 'string' || !/^sha384-[A-Za-z0-9+/]{64}$/.test(origin.sri)) return null;
|
|
71
|
+
result.origin = {catalog: origin.catalog, family: origin.family, version: origin.version, file: origin.file, sri: origin.sri};
|
|
72
|
+
}
|
|
47
73
|
return result;
|
|
48
74
|
}
|
|
49
75
|
|
|
@@ -63,7 +89,7 @@ export function readFontAssets(markdown, parser) {
|
|
|
63
89
|
else if (source[at] === '\n') starts.push(at + 1);
|
|
64
90
|
}
|
|
65
91
|
md.block.parse(frame.body.replace(/\r\n?/g, '\n').replace(/\0/g, '\ufffd'), md, env, tokens);
|
|
66
|
-
const labels = new Set(), faces = new Set();
|
|
92
|
+
const labels = new Set(), faces = new Set(), metadata = new Map(), faceMetadata = new Map(), subsetUrls = new Set();
|
|
67
93
|
for (const token of tokens) {
|
|
68
94
|
if (token.type !== 'reference_definition' || !token.map) continue;
|
|
69
95
|
const id = token.meta.label, first = !labels.has(id);
|
|
@@ -79,18 +105,33 @@ export function readFontAssets(markdown, parser) {
|
|
|
79
105
|
if (!match) continue;
|
|
80
106
|
const label = md.utils.unescapeAll(match[1]);
|
|
81
107
|
if (!data) { refused.push({name: label, reason: 'The font reference must contain an embedded font.'}); continue; }
|
|
82
|
-
let
|
|
108
|
+
let definitionMetadata = {family: label.slice(5)};
|
|
83
109
|
if (definition.title) {
|
|
84
|
-
try {
|
|
110
|
+
try { definitionMetadata = JSON.parse(definition.title); }
|
|
85
111
|
catch (_) { refused.push({name: label, reason: 'The font reference has invalid metadata.'}); continue; }
|
|
86
112
|
}
|
|
87
|
-
const face = faceOf(
|
|
113
|
+
const face = faceOf(definitionMetadata);
|
|
88
114
|
if (!face) { refused.push({name: label, reason: 'The font reference has invalid metadata.'}); continue; }
|
|
89
115
|
const key = fontAssetKey(face), active = first && !faces.has(key);
|
|
116
|
+
const conflict = sourceMetadataFields.find(field => face[field] && [metadata.get(url)?.[field], faceMetadata.get(key)?.[field]]
|
|
117
|
+
.some(prior => prior && JSON.stringify(prior) !== JSON.stringify(face[field])));
|
|
118
|
+
if (conflict) { refused.push({name: label, reason: 'The font references have conflicting ' + conflict + ' metadata.'}); continue; }
|
|
119
|
+
if (face.subsetted && metadata.get(url)?.origin || face.origin && subsetUrls.has(url)) {
|
|
120
|
+
refused.push({name: label, reason: 'A font subset cannot claim an original catalog file.'}); continue;
|
|
121
|
+
}
|
|
122
|
+
metadata.set(url, {...metadata.get(url), ...sourceMetadata(face)});
|
|
123
|
+
faceMetadata.set(key, {...faceMetadata.get(key), ...sourceMetadata(face)});
|
|
124
|
+
if (face.subsetted) subsetUrls.add(url);
|
|
90
125
|
const row = {...face, ...data, url, label, id, key, source: raw, start, end, next, active, topLevel: token.level === 0};
|
|
91
126
|
blocks.push(row);
|
|
92
127
|
if (active) { assets.push(row); faces.add(key); }
|
|
93
128
|
}
|
|
129
|
+
for (let index = 0; index < assets.length; index++) {
|
|
130
|
+
const asset = assets[index], declared = metadata.get(asset.url);
|
|
131
|
+
for (const field of sourceMetadataFields) if (!asset[field] && declared?.[field])
|
|
132
|
+
assets[index] = {...assets[index], [field]: declared[field]};
|
|
133
|
+
if (subsetUrls.has(asset.url) && !asset.subsetted) assets[index] = {...assets[index], subsetted: true};
|
|
134
|
+
}
|
|
94
135
|
return {assets, blocks, refused, references: env.references || Object.create(null)};
|
|
95
136
|
}
|
|
96
137
|
|
|
@@ -113,13 +154,26 @@ function escapeFontLabel(label) {
|
|
|
113
154
|
}
|
|
114
155
|
|
|
115
156
|
export function writeFontAssets(markdown, assets, parser) {
|
|
116
|
-
const source = String(markdown ?? ''), md = parserFor(parser), index = readFontAssets(source, md), wanted = new Map();
|
|
157
|
+
const source = String(markdown ?? ''), md = parserFor(parser), index = readFontAssets(source, md), wanted = new Map(), metadata = new Map(), subsetUrls = new Set();
|
|
117
158
|
for (const asset of assets || []) {
|
|
118
|
-
const key = fontAssetKey(asset);
|
|
159
|
+
const key = fontAssetKey(asset), face = faceOf(asset);
|
|
119
160
|
if (!key || !fontDataUrl(asset?.url)) throw new TypeError('font: invalid embedded asset');
|
|
120
161
|
if (wanted.has(key) && wanted.get(key).url !== asset.url) throw new TypeError('font: one file owns each family face');
|
|
162
|
+
const conflict = sourceMetadataFields.find(field => face[field] && metadata.get(asset.url)?.[field] &&
|
|
163
|
+
JSON.stringify(metadata.get(asset.url)[field]) !== JSON.stringify(face[field]));
|
|
164
|
+
if (conflict) throw new TypeError('font: conflicting ' + conflict + ' metadata');
|
|
165
|
+
if (face.subsetted && metadata.get(asset.url)?.origin || face.origin && subsetUrls.has(asset.url))
|
|
166
|
+
throw new TypeError('font: a subset cannot claim an original catalog file');
|
|
167
|
+
metadata.set(asset.url, {...metadata.get(asset.url), ...sourceMetadata(face)});
|
|
168
|
+
if (face.subsetted) subsetUrls.add(asset.url);
|
|
121
169
|
wanted.set(key, asset);
|
|
122
170
|
}
|
|
171
|
+
for (const [key, asset] of wanted) {
|
|
172
|
+
const declared = metadata.get(asset.url);
|
|
173
|
+
for (const field of sourceMetadataFields) if (!asset[field] && declared?.[field])
|
|
174
|
+
wanted.set(key, {...wanted.get(key), [field]: declared[field]});
|
|
175
|
+
if (subsetUrls.has(asset.url) && !asset.subsetted) wanted.set(key, {...wanted.get(key), subsetted: true});
|
|
176
|
+
}
|
|
123
177
|
const edits = [], consumed = new Set(), labels = new Set(Object.keys(index.references));
|
|
124
178
|
const retired = index.assets.filter(row => !wanted.has(row.key));
|
|
125
179
|
for (const row of index.blocks) {
|
package/dist/ledger/source.mjs
CHANGED
|
@@ -70,13 +70,42 @@ function sourceString(node) {
|
|
|
70
70
|
}
|
|
71
71
|
const replacements = new WeakMap(), texts = new WeakMap(), edits = new WeakMap();
|
|
72
72
|
export const sourceEdit = source => edits.get(source) || null;
|
|
73
|
+
const INITIAL_LEAF_CHARS = 16384;
|
|
73
74
|
export class HistorySource {
|
|
74
75
|
#root;
|
|
75
|
-
constructor(text) {
|
|
76
|
+
constructor(text) {
|
|
77
|
+
if (typeof text === 'string' && text.length > INITIAL_LEAF_CHARS) {
|
|
78
|
+
const leaves = [];
|
|
79
|
+
for (let from = 0; from < text.length;) {
|
|
80
|
+
let to = Math.min(text.length, from + INITIAL_LEAF_CHARS);
|
|
81
|
+
if (to < text.length && (text.charCodeAt(to - 1) & 0xfc00) === 0xd800 && (text.charCodeAt(to) & 0xfc00) === 0xdc00) to++;
|
|
82
|
+
leaves.push(sourceLeaf(text, from, to));
|
|
83
|
+
from = to;
|
|
84
|
+
}
|
|
85
|
+
const build = (from, to) => from === to ? null : to - from === 1 ? leaves[from]
|
|
86
|
+
: sourceNode(build(from, (from + to) >> 1), build((from + to) >> 1, to));
|
|
87
|
+
this.#root = build(0, leaves.length);
|
|
88
|
+
} else this.#root = sourceLeaf(text);
|
|
89
|
+
Object.freeze(this);
|
|
90
|
+
}
|
|
76
91
|
static owns(value) { return value !== null && typeof value === 'object' && #root in value; }
|
|
77
92
|
static #fromRoot(root) { const source = new HistorySource(''); source.#root = root; return source; }
|
|
78
93
|
static fromParts(parts) {
|
|
79
|
-
const leaves =
|
|
94
|
+
const leaves = [];
|
|
95
|
+
for (const text of parts) {
|
|
96
|
+
if (typeof text !== 'string') throw new TypeError('source string required');
|
|
97
|
+
if (text.length <= INITIAL_LEAF_CHARS) {
|
|
98
|
+
const leaf = sourceLeaf(text);
|
|
99
|
+
if (leaf) leaves.push(leaf);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
for (let from = 0; from < text.length;) {
|
|
103
|
+
let to = Math.min(text.length, from + INITIAL_LEAF_CHARS);
|
|
104
|
+
if (to < text.length && (text.charCodeAt(to - 1) & 0xfc00) === 0xd800 && (text.charCodeAt(to) & 0xfc00) === 0xdc00) to++;
|
|
105
|
+
leaves.push(sourceLeaf(text, from, to));
|
|
106
|
+
from = to;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
80
109
|
const build = (from, to) => from === to ? null : to - from === 1 ? leaves[from]
|
|
81
110
|
: sourceNode(build(from, Math.floor((from + to) / 2)), build(Math.floor((from + to) / 2), to));
|
|
82
111
|
return HistorySource.#fromRoot(build(0, leaves.length));
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "rapier-markdown-readable/1",
|
|
3
|
+
"description": "The pinned markdown-it 15.0.3 compiled unminified from its published sources, as the page's copy is, with its runtime dependencies and plugins as published, for the installed helpers. Written by tools/markdown-readable-vendor.mjs; licences in agent/vendor/NOTICE.txt and agent/vendor/markdown-licenses/.",
|
|
4
|
+
"packages": [
|
|
5
|
+
{
|
|
6
|
+
"name": "markdown-it",
|
|
7
|
+
"version": "15.0.3",
|
|
8
|
+
"tarball": "https://registry.npmjs.org/markdown-it/-/markdown-it-15.0.3.tgz",
|
|
9
|
+
"integrity": "sha512-+Az7Ojz3iRGu8KYMvJ6xVhvrxP3eE+vEtJX75Ow88XBpcQNV/0lGX5ZynIIBftREo4DC2jsveAMDaeltmm8QvQ=="
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "entities",
|
|
13
|
+
"version": "8.1.0",
|
|
14
|
+
"tarball": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz",
|
|
15
|
+
"integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA=="
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "linkify-it",
|
|
19
|
+
"version": "6.1.0",
|
|
20
|
+
"tarball": "https://registry.npmjs.org/linkify-it/-/linkify-it-6.1.0.tgz",
|
|
21
|
+
"integrity": "sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw=="
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "mdurl",
|
|
25
|
+
"version": "2.1.0",
|
|
26
|
+
"tarball": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz",
|
|
27
|
+
"integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg=="
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "uc.micro",
|
|
31
|
+
"version": "3.0.0",
|
|
32
|
+
"tarball": "https://registry.npmjs.org/uc.micro/-/uc.micro-3.0.0.tgz",
|
|
33
|
+
"integrity": "sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw=="
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "punycode.js",
|
|
37
|
+
"version": "2.3.1",
|
|
38
|
+
"tarball": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
|
|
39
|
+
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "markdown-it-task-lists",
|
|
43
|
+
"version": "2.1.1",
|
|
44
|
+
"tarball": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz",
|
|
45
|
+
"integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA=="
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "markdown-it-footnote",
|
|
49
|
+
"version": "4.0.0",
|
|
50
|
+
"tarball": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-4.0.0.tgz",
|
|
51
|
+
"integrity": "sha512-WYJ7urf+khJYl3DqofQpYfEYkZKbmXmwxQV8c8mO/hGIhgZ1wOe7R4HLFNwqx7TjILbnC98fuyeSsin19JdFcQ=="
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "markdown-it-mark",
|
|
55
|
+
"version": "4.0.0",
|
|
56
|
+
"tarball": "https://registry.npmjs.org/markdown-it-mark/-/markdown-it-mark-4.0.0.tgz",
|
|
57
|
+
"integrity": "sha512-YLhzaOsU9THO/cal0lUjfMjrqSMPjjyjChYM7oyj4DnyaXEzA8gnW6cVJeyCrCVeyesrY2PlEdUYJSPFYL4Nkg=="
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "markdown-it-sup",
|
|
61
|
+
"version": "2.0.0",
|
|
62
|
+
"tarball": "https://registry.npmjs.org/markdown-it-sup/-/markdown-it-sup-2.0.0.tgz",
|
|
63
|
+
"integrity": "sha512-5VgmdKlkBd8sgXuoDoxMpiU+BiEt3I49GItBzzw7Mxq9CxvnhE/k09HFli09zgfFDRixDQDfDxi0mgBCXtaTvA=="
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"name": "markdown-it-emoji",
|
|
67
|
+
"version": "3.1.0",
|
|
68
|
+
"tarball": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-3.1.0.tgz",
|
|
69
|
+
"integrity": "sha512-NhmMEH2ywduD4Nty1E8uB5NqfLhAT1VR0dyvoJyStKOqCzbZmVdn/+8wj7zpDsb/fLBikpCPsWwxqKlvMmbz4g=="
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "markdown-it-abbr",
|
|
73
|
+
"version": "2.0.0",
|
|
74
|
+
"tarball": "https://registry.npmjs.org/markdown-it-abbr/-/markdown-it-abbr-2.0.0.tgz",
|
|
75
|
+
"integrity": "sha512-of7C8pXSjXjDojW4neNP+jD7inUYH/DO0Ca+K/4FUEccg0oHAEX/nfscw0jfz66PJbYWOAT9U8mjO21X5p6aAw=="
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "markdown-it-ins",
|
|
79
|
+
"version": "4.0.0",
|
|
80
|
+
"tarball": "https://registry.npmjs.org/markdown-it-ins/-/markdown-it-ins-4.0.0.tgz",
|
|
81
|
+
"integrity": "sha512-sWbjK2DprrkINE4oYDhHdCijGT+MIDhEupjSHLXe5UXeVr5qmVxs/nTUVtgi0Oh/qtF+QKV0tNWDhQBEPxiMew=="
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "markdown-it-deflist",
|
|
85
|
+
"version": "4.0.0",
|
|
86
|
+
"tarball": "https://registry.npmjs.org/markdown-it-deflist/-/markdown-it-deflist-4.0.0.tgz",
|
|
87
|
+
"integrity": "sha512-06186ZWDwNLg638THD70MxBeFrDMF0+nL7IWU/qwCGHGOcUIm4MTYXbfjpv0ooWnVjkSnAjW8msKaOQmNRfY6Q=="
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
"build": {
|
|
91
|
+
"path": "markdown-it.mjs",
|
|
92
|
+
"package": "markdown-it",
|
|
93
|
+
"map": "dist/markdown-it.mjs.map",
|
|
94
|
+
"imports": {
|
|
95
|
+
"mdurl": "./mdurl/index.mjs",
|
|
96
|
+
"uc.micro": "./uc.micro.mjs",
|
|
97
|
+
"entities": "./entities.mjs",
|
|
98
|
+
"linkify-it": "./linkify-it.mjs",
|
|
99
|
+
"punycode.js": "./punycode.mjs"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"copies": [
|
|
103
|
+
{
|
|
104
|
+
"path": "linkify-it.mjs",
|
|
105
|
+
"package": "linkify-it",
|
|
106
|
+
"from": "build/index.mjs",
|
|
107
|
+
"imports": {
|
|
108
|
+
"uc.micro": "./uc.micro.mjs"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"path": "uc.micro.mjs",
|
|
113
|
+
"package": "uc.micro",
|
|
114
|
+
"from": "build/index.mjs"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"path": "punycode.mjs",
|
|
118
|
+
"package": "punycode.js",
|
|
119
|
+
"from": "punycode.es6.js"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"path": "entities/decode-codepoint.mjs",
|
|
123
|
+
"package": "entities",
|
|
124
|
+
"from": "dist/decode-codepoint.js"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"path": "mdurl/index.mjs",
|
|
128
|
+
"package": "mdurl",
|
|
129
|
+
"from": "index.mjs"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"path": "mdurl/lib/decode.mjs",
|
|
133
|
+
"package": "mdurl",
|
|
134
|
+
"from": "lib/decode.mjs"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"path": "mdurl/lib/encode.mjs",
|
|
138
|
+
"package": "mdurl",
|
|
139
|
+
"from": "lib/encode.mjs"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"path": "mdurl/lib/format.mjs",
|
|
143
|
+
"package": "mdurl",
|
|
144
|
+
"from": "lib/format.mjs"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"path": "mdurl/lib/parse.mjs",
|
|
148
|
+
"package": "mdurl",
|
|
149
|
+
"from": "lib/parse.mjs"
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"plugins": [
|
|
153
|
+
{
|
|
154
|
+
"package": "markdown-it-task-lists",
|
|
155
|
+
"from": "dist/markdown-it-task-lists.js"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"package": "markdown-it-footnote",
|
|
159
|
+
"from": "dist/markdown-it-footnote.js"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"package": "markdown-it-mark",
|
|
163
|
+
"from": "dist/markdown-it-mark.js"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"package": "markdown-it-sup",
|
|
167
|
+
"from": "dist/markdown-it-sup.js"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"package": "markdown-it-emoji",
|
|
171
|
+
"from": "dist/markdown-it-emoji-light.js"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"package": "markdown-it-abbr",
|
|
175
|
+
"from": "dist/markdown-it-abbr.js"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"package": "markdown-it-ins",
|
|
179
|
+
"from": "dist/markdown-it-ins.js"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"package": "markdown-it-deflist",
|
|
183
|
+
"from": "dist/markdown-it-deflist.js"
|
|
184
|
+
}
|
|
185
|
+
],
|
|
186
|
+
"files": [
|
|
187
|
+
{
|
|
188
|
+
"path": "entities.mjs",
|
|
189
|
+
"bytes": 50594,
|
|
190
|
+
"sha256": "7914d95849325717065db7db37b8fcd6f8ffaaa3aa481f1bde687209f844da38"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"path": "entities/decode-codepoint.mjs",
|
|
194
|
+
"bytes": 948,
|
|
195
|
+
"sha256": "d80628653e792234aca25c5b431523753af5c827339140d38e265d726a136579"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"path": "linkify-it.mjs",
|
|
199
|
+
"bytes": 16516,
|
|
200
|
+
"sha256": "9e2b21808450980d055f1cc159293c32eb0eecc205fe19b67ded4d7fee08aca6"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"path": "markdown-it.mjs",
|
|
204
|
+
"bytes": 111298,
|
|
205
|
+
"sha256": "73c4a1041d82dddb670375e9889bc91492c0c1c150c2c8f33267cfb3790c5d05"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"path": "markdown-plugins.mjs",
|
|
209
|
+
"bytes": 45734,
|
|
210
|
+
"sha256": "0a935c55fb20f684271d32f37819d0811ca0772c2e9cd4b1822aab2507525555"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"path": "markdown-runtime.mjs",
|
|
214
|
+
"bytes": 110,
|
|
215
|
+
"sha256": "8ce7c709299538e10b844b7f051dd784b67f0515efdd4bd167be13e0deb97f5b"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"path": "mdurl/index.mjs",
|
|
219
|
+
"bytes": 200,
|
|
220
|
+
"sha256": "8ea430f1f8a107f529e2dac519d2f18e71ec9befe6f23f78bf6510cf86d3f9a0"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"path": "mdurl/lib/decode.mjs",
|
|
224
|
+
"bytes": 2692,
|
|
225
|
+
"sha256": "6a854a029a7211a14575cbb43922734fa8a11be28a00e184463848582a349d6a"
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"path": "mdurl/lib/encode.mjs",
|
|
229
|
+
"bytes": 1697,
|
|
230
|
+
"sha256": "65aa62a0e96659b9bb53ab0b4e64d5917be86e964e2f121dfce21e30a88448cb"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"path": "mdurl/lib/format.mjs",
|
|
234
|
+
"bytes": 465,
|
|
235
|
+
"sha256": "ac3695720223d7e38b1a8c061c8615b8a74b2dd56f383d3029db073430322ea6"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"path": "mdurl/lib/parse.mjs",
|
|
239
|
+
"bytes": 6205,
|
|
240
|
+
"sha256": "ac8f5a5a4a68f2c03f4624f672a5c28b425e0ddd52b8483d6c2b9a60056dcc81"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"path": "punycode.mjs",
|
|
244
|
+
"bytes": 5921,
|
|
245
|
+
"sha256": "ad32ca11244584756cc645b69679cb0df608428443f081f20bbad269afd15ff1"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"path": "uc.micro.mjs",
|
|
249
|
+
"bytes": 6384,
|
|
250
|
+
"sha256": "17ece0a12a868a21119fd68dad490664cc5f7e116102ec939f586bf203a977cb"
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const c1 = [
|
|
2
|
+
8364, 0, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 0,
|
|
3
|
+
381, 0, 0, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250,
|
|
4
|
+
339, 0, 382, 376,
|
|
5
|
+
];
|
|
6
|
+
function isInvalidCodePoint(codePoint) {
|
|
7
|
+
return (codePoint === 0 ||
|
|
8
|
+
(codePoint >= 0xd8_00 && codePoint <= 0xdf_ff) ||
|
|
9
|
+
codePoint > 0x10_ff_ff);
|
|
10
|
+
}
|
|
11
|
+
export function replaceCodePoint(codePoint) {
|
|
12
|
+
if (isInvalidCodePoint(codePoint)) {
|
|
13
|
+
return 0xff_fd;
|
|
14
|
+
}
|
|
15
|
+
if (codePoint >= 128 && codePoint <= 159) {
|
|
16
|
+
return c1[codePoint - 128] || codePoint;
|
|
17
|
+
}
|
|
18
|
+
return codePoint;
|
|
19
|
+
}
|
|
20
|
+
export function replaceCodePointXML(codePoint) {
|
|
21
|
+
return isInvalidCodePoint(codePoint) ? 0xff_fd : codePoint;
|
|
22
|
+
}
|
|
23
|
+
export function codePointToString(codePoint) {
|
|
24
|
+
return (codePoint - 1) >>> 0 < 0x7f || (codePoint - 0xa0) >>> 0 < 0xd7_60
|
|
25
|
+
? String.fromCharCode(codePoint)
|
|
26
|
+
: String.fromCodePoint(replaceCodePoint(codePoint));
|
|
27
|
+
}
|