rapier-html 1.2.6 → 1.2.8
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 +10 -10
- package/README.md +20 -18
- package/dist/cli.mjs +1 -0
- package/dist/page.d.mts +59 -0
- package/dist/page.mjs +30 -9
- package/dist/rapier.html +258 -70
- package/dist/wrap.mjs +51 -0
- package/package.json +6 -2
package/dist/wrap.mjs
CHANGED
|
@@ -41,6 +41,57 @@ export function offlineTemplate(pageHtml, address = null) {
|
|
|
41
41
|
head.slice(at) + pageHtml.slice(end);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
// What a carried page may hold beyond the base editor: Draw (its part and its letter sets) and the plug-ins a document
|
|
45
|
+
// displays with. Notes and the font subsetter never travel; without the subsetter a page keeps its fonts whole.
|
|
46
|
+
export const CHOICES = Object.freeze(['drawing', 'math', 'mermaid']);
|
|
47
|
+
const INVENTORY = '<script type="application/json" id="rapier-builtin-plugins">';
|
|
48
|
+
const element = (html, id) => {
|
|
49
|
+
const start = html.indexOf('<script type="application/rapier-runtime" id="' + id + '">');
|
|
50
|
+
if (start < 0) return null;
|
|
51
|
+
const end = html.indexOf(END, start) + END.length;
|
|
52
|
+
return {start, end: html[end] === '\n' ? end + 1 : end};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// The full carried editor cut to the base editor and `include` (ids from CHOICES). Only whole inert elements and the
|
|
56
|
+
// inventory rows naming them are removed; every kept byte is unchanged.
|
|
57
|
+
export function carry(pageHtml, include = []) {
|
|
58
|
+
const kept = new Set(include);
|
|
59
|
+
for (const id of kept) if (!CHOICES.includes(id)) throw new Error('a carried page includes ' + CHOICES.join(', ') + '; not ' + id);
|
|
60
|
+
if (kept.has('drawing')) kept.add('letters');
|
|
61
|
+
let html = pageHtml;
|
|
62
|
+
const cut = id => { const at = element(html, id); if (at) html = html.slice(0, at.start) + html.slice(at.end); };
|
|
63
|
+
// Parts beyond the base editor (Notes, page layout) never travel, as in the person's HTML editor file; Draw when chosen.
|
|
64
|
+
for (const id of [...new Set([...html.matchAll(/<script type="application\/rapier-runtime" id="(rapier-part-[a-z-]+)">/g)].map(match => match[1]))])
|
|
65
|
+
if (id !== 'rapier-part-drawing' || !kept.has('drawing')) cut(id);
|
|
66
|
+
const start = html.indexOf(INVENTORY);
|
|
67
|
+
if (start < 0) return html;
|
|
68
|
+
const close = html.indexOf(END, start), end = html[close + END.length] === '\n' ? close + END.length + 1 : close + END.length;
|
|
69
|
+
const groups = JSON.parse(html.slice(start + INVENTORY.length, close)), carried = groups.filter(group => kept.has(group.id));
|
|
70
|
+
html = html.slice(0, start) + (carried.length ? INVENTORY + JSON.stringify(carried).replace(/</g, '\\u003c') + END + '\n' : '') + html.slice(end);
|
|
71
|
+
for (const group of groups) if (!kept.has(group.id)) cut(group.element);
|
|
72
|
+
return html;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The plug-ins a Markdown text displays with, read without a Markdown parser, so it leans toward carrying: math for a `$`
|
|
76
|
+
// or `$$` span outside code, Mermaid for a mermaid fence (`flowchart(fence)` true marks one Rapier draws natively).
|
|
77
|
+
export function portableNeeds(text, {base, flowchart} = {}) {
|
|
78
|
+
const needs = new Set();
|
|
79
|
+
for (const source of [text, base]) {
|
|
80
|
+
if (typeof source !== 'string') continue;
|
|
81
|
+
let prose = '';
|
|
82
|
+
const lines = source.split(/\r\n|\r|\n/);
|
|
83
|
+
for (let at = 0; at < lines.length; at++) {
|
|
84
|
+
const open = /^ {0,3}(`{3,}|~{3,})\s*([^\s`]*)/.exec(lines[at]);
|
|
85
|
+
if (!open) { prose += lines[at] + '\n'; continue; }
|
|
86
|
+
const body = [];
|
|
87
|
+
for (at++; at < lines.length && !new RegExp('^ {0,3}' + open[1][0] + '{' + open[1].length + ',}\\s*$').test(lines[at]); at++) body.push(lines[at]);
|
|
88
|
+
if (open[2].toLowerCase() === 'mermaid' && flowchart?.(body.join('\n')) !== true) needs.add('mermaid');
|
|
89
|
+
}
|
|
90
|
+
if (/\$\$[\s\S]+?\$\$|(?:^|[^\\$])\$(?![\s$])[^$\n]*[^\s\\$]\$(?!\d)/.test(prose.split(/\n[ \t]*\n/).map(paragraph => paragraph.replace(/(`+)[\s\S]*?\1/g, '')).join('\n\n'))) needs.add('math');
|
|
91
|
+
}
|
|
92
|
+
return CHOICES.filter(id => needs.has(id));
|
|
93
|
+
}
|
|
94
|
+
|
|
44
95
|
export function wrap(pageHtml, text, name, options) {
|
|
45
96
|
if (typeof pageHtml !== 'string' || !pageHtml.includes('</body>')) throw new Error('not a Rapier page: no </body>');
|
|
46
97
|
if (typeof text !== 'string') throw new Error('the document must be text');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rapier-html",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"description": "One command turns a Markdown file into one offline HTML file: the whole Rapier editor with the document inside. Opens in any browser, phone or desktop, with no install or account. Write, draw and paint watercolor, then Send back the edits to your AI agent.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -40,8 +40,12 @@
|
|
|
40
40
|
"bin": {
|
|
41
41
|
"rapier-html": "dist/cli.mjs"
|
|
42
42
|
},
|
|
43
|
+
"types": "./dist/page.d.mts",
|
|
43
44
|
"exports": {
|
|
44
|
-
".":
|
|
45
|
+
".": {
|
|
46
|
+
"types": "./dist/page.d.mts",
|
|
47
|
+
"default": "./dist/page.mjs"
|
|
48
|
+
}
|
|
45
49
|
},
|
|
46
50
|
"files": [
|
|
47
51
|
"dist",
|