@dogsbay/render 0.2.0-beta.129 → 0.2.0-beta.131

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/README.md CHANGED
@@ -39,7 +39,10 @@ Every run writes a JSON report to stderr:
39
39
  ```json
40
40
  {
41
41
  "schemaVersion": 1,
42
- "warnings": [{ "code": "link-unresolvable", "message": "\"guide.md\": a single page has no other pages; …" }],
42
+ "warnings": [
43
+ { "code": "syntax-unclosed-container", "message": ":::note is never closed — …", "line": 12 },
44
+ { "code": "link-unresolvable", "message": "\"guide.md\": a single page has no other pages; …" }
45
+ ],
43
46
  "sizes": { "total": 35826, "css": 25829, "js": 0, "body": 7702 },
44
47
  "elements": []
45
48
  }
@@ -54,10 +57,10 @@ unreadable input; 2 means a usage error.
54
57
  |---|---|---|
55
58
  | `link-unresolvable` | a relative link; a single page has no other pages | use an absolute `https://` URL, or an `#anchor` |
56
59
  | `anchor-missing` | `#id` points to nothing on the page | correct the anchor or the heading |
57
- | `image-missing` | a local image was not found, or is outside the document's folder | put it next to the document |
60
+ | `image-missing` | a local image was not found, or is outside the document's folder; left out of the page (its alt text stays) | put it next to the document |
58
61
  | `image-remote` | an `http(s)` image; the page fetches nothing | download it next to the document |
59
62
  | `image-large` | an embedded image over 1.5 MB | resize it |
60
- | `image-type` | not an image type the page can embed (png, jpg, gif, webp, svg, avif) | convert it |
63
+ | `image-type` | not an image type the page can embed (png, jpg, gif, webp, svg, avif); left out of the page | convert it |
61
64
  | `node-unsupported` | a component this renderer does not know | use a supported directive |
62
65
  | `icon-unknown` | an icon name with no built-in glyph | use a built-in icon |
63
66
  | `math-raw` / `diagram-raw` | math or a diagram left as source | pass `--math mathml`; diagrams are not rendered yet |
@@ -65,6 +68,24 @@ unreadable input; 2 means a usage error.
65
68
  | `tokens-external` | a `url()` in the token file | inline it, or drop it |
66
69
  | `html-sanitized`, `attribute-dropped`, `unsafe-url` | raw HTML, an attribute or a URL removed by `--sanitize` | expected for untrusted input |
67
70
 
71
+ **Syntax warnings carry a `line`** (1-based, front matter counted). They are Markdown
72
+ the parser recovered from without failing, and they come first in the list, in line
73
+ order, because they often cause the warnings after them:
74
+
75
+ | Code | Meaning | Fix |
76
+ |---|---|---|
77
+ | `syntax-unclosed-container` | a `:::block` is never closed: it takes in what follows, or is shown as text | add its own `:::` closer |
78
+ | `syntax-stray-closer` | a `:::` that closes nothing, shown as text | delete it |
79
+ | `syntax-closer-mismatch` | a closer labelled for a different block | check which block it should end |
80
+ | `syntax-unknown-container` | `:::name` is not a directive; shown as a plain box (reported instead of `node-unsupported`; an unclosed one is shown as text and reported as `syntax-unclosed-container`) | correct the name |
81
+ | `syntax-unknown-inline` | `:name[…]` is not an inline directive; shown as text | correct the name |
82
+ | `syntax-block-directive-inline` | a block directive inside a line of text; shown as text | put it on a line of its own |
83
+ | `syntax-leaf-as-block` | `:::youtube` written as a block; it has no body | write `::youtube{…}` on one line |
84
+ | `syntax-bad-attributes` | an attribute block the parser cannot read; ignored | fix the quoting |
85
+ | `syntax-dropped-attributes` | an attribute block on something that takes none | move or delete it |
86
+ | `syntax-missing-label` | an inline directive with no `[label]`, such as `:badge{…}` or `:button{…}`; shown as text | write `:badge[label]{…}` |
87
+ | `syntax-nesting-unchecked` | the parser stopped re-checking nested blocks; where a block ends may be wrong | give each nested block its own closer, or split the page |
88
+
68
89
  ## For agents
69
90
 
70
91
  - **Skill:** the package ships the `dogsbay-documents` skill in
@@ -96,6 +117,11 @@ written in the document. That can include a query string or percent-encoding
96
117
  (`my%20pic.png?v=2`), so strip and decode it as your storage needs. The CLI provides
97
118
  one that does, and reads images only from inside the document's folder.
98
119
 
120
+ A page's scripts are the theme boot plus one `<script>` per element it uses, each allowed by its
121
+ hash in the page's CSP. If you serve pages under a fixed CSP of your own, such as a browser
122
+ extension's sandbox page, `await scriptHashes()` returns the hash of every script a page can
123
+ carry. List those hashes instead of allowing `'unsafe-inline'`.
124
+
99
125
  ## Security
100
126
 
101
127
  - **Sanitizing** is on by default, in the library and the CLI, for files and stdin
package/dist/bin.mjs CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{b as e}from"./chunks/chunk-4WDV4LZ6.mjs";import"./chunks/chunk-YC7BAVNG.mjs";import"./chunks/chunk-2WIDSLTD.mjs";import"./chunks/chunk-2V77MTNA.mjs";e(process.argv.slice(2)).then(r=>{process.exitCode=r});
2
+ import{b as e}from"./chunks/chunk-CKEJATK5.mjs";import"./chunks/chunk-TEQIWHVG.mjs";import"./chunks/chunk-PISZYHIF.mjs";import"./chunks/chunk-2V77MTNA.mjs";e(process.argv.slice(2)).then(r=>{process.exitCode=r});
@@ -1,4 +1,4 @@
1
- import{a as c,b as g,c as v}from"./chunk-YC7BAVNG.mjs";import{lstatSync as L,readFileSync as h,realpathSync as k,writeFileSync as b}from"node:fs";import{dirname as M,extname as $,isAbsolute as x,resolve as j,sep as R}from"node:path";var p=`dogsbay-render ${g}: render one Dogsbay Markdown file to one self-contained HTML file
1
+ import{a as c,b as g,d as v}from"./chunk-TEQIWHVG.mjs";import{lstatSync as L,readFileSync as h,realpathSync as k,writeFileSync as b}from"node:fs";import{dirname as M,extname as $,isAbsolute as x,resolve as j,sep as R}from"node:path";var p=`dogsbay-render ${g}: render one Dogsbay Markdown file to one self-contained HTML file
2
2
 
3
3
  Usage: dogsbay-render <in.md | -> [-o out.html] [options]
4
4
 
@@ -14,7 +14,7 @@ Usage: dogsbay-render <in.md | -> [-o out.html] [options]
14
14
  -h, --help this text
15
15
  -v, --version the version
16
16
 
17
- The report is JSON: { schemaVersion, warnings: [{ code, message }], sizes, elements }.`,S={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".avif":"image/avif"};function T(a){let t=k(a);return i=>{let n;try{n=decodeURIComponent(i.split(/[?#]/)[0])}catch{return}if(!n||x(n)||/^[a-z]+:/i.test(n))return;let l=S[$(n).toLowerCase()];if(!l)return;let d=j(t,n),s=r=>r===t||r.startsWith(t+R);if(s(d))try{let r=k(d),u=L(r);return!s(r)||!u.isFile()||u.nlink>1||S[$(r).toLowerCase()]!==l?void 0:{bytes:new Uint8Array(h(r)),mime:l}}catch{return}}}var m=class extends Error{constructor(i,n){super(i);this.code=n}};function o(a,t=1){throw new m(a,t)}async function F(a){try{return await A(a),0}catch(t){let i=t instanceof m?t.code:1,n=t instanceof Error?t.message:String(t);return process.stderr.write(n.startsWith("dogsbay-render ")?`${n}
17
+ The report is JSON: { schemaVersion, warnings: [{ code, message, line? }], sizes, elements }.`,S={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".avif":"image/avif"};function T(a){let t=k(a);return i=>{let n;try{n=decodeURIComponent(i.split(/[?#]/)[0])}catch{return}if(!n||x(n)||/^[a-z]+:/i.test(n))return;let l=S[$(n).toLowerCase()];if(!l)return;let d=j(t,n),s=r=>r===t||r.startsWith(t+R);if(s(d))try{let r=k(d),u=L(r);return!s(r)||!u.isFile()||u.nlink>1||S[$(r).toLowerCase()]!==l?void 0:{bytes:new Uint8Array(h(r)),mime:l}}catch{return}}}var m=class extends Error{constructor(i,n){super(i);this.code=n}};function o(a,t=1){throw new m(a,t)}async function F(a){try{return await A(a),0}catch(t){let i=t instanceof m?t.code:1,n=t instanceof Error?t.message:String(t);return process.stderr.write(n.startsWith("dogsbay-render ")?`${n}
18
18
  `:`dogsbay-render: ${n}
19
19
  `),i}}async function A(a){let t=[...a],i,n,l,d,s={},r=e=>t.shift()??o(`${e} needs a value`,2);for(;t.length;){let e=t.shift();if(e==="-h"||e==="--help")return void process.stdout.write(p+`
20
20
  `);if(e==="-v"||e==="--version")return void process.stdout.write(g+`
@@ -0,0 +1,10 @@
1
+ var b={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};function d(t){return String(t??"").replace(/[&<>"']/g,n=>b[n])}function j(t){let n="";for(let[s,e]of Object.entries(t))e==null||e===!1||e===""&&s!=="alt"||(n+=e===!0?` ${s}`:` ${s}="${d(e)}"`);return n}function w(t,n){let s={},e=[n,t?.class].filter(Boolean).join(" ");if(e&&(s.class=e),!t)return s;for(let[o,r]of Object.entries(t))(o==="id"||o==="style"||o.startsWith("data-")||o.startsWith("aria-"))&&(s[o]=r);return s}function A(t){return t.toLowerCase().normalize("NFKD").replace(/[̀-ͯ]/g,"").replace(/<[^>]*>/g,"").replace(/[^\p{L}\p{N}\s_-]/gu,"").trim().replace(/[\s_]+/g,"-").replace(/-+/g,"-")||"section"}function O(t){return t.replace(/&(amp|lt|gt|quot|#39|#x27|apos);/g,(n,s)=>({amp:"&",lt:"<",gt:">",quot:'"',"#39":"'","#x27":"'",apos:"'"})[s])}var E="<!--db-foreign-->",L="<!--/db-foreign-->";var g=/[ \t]*(?:\/\/|#|--|<!--|\/\*|;)[ \t]*\[!code[^\]]*\](?:[ \t]*(?:-->|\*\/))?/g,h=/[ \t]*\[!code[^\]]*\]/g;function m(t,n){return t.includes("[!code")?t.split(`
2
+ `).map(s=>{if(n)return s.replace(g,"").replace(h,"");let e="",o=0;for(let r of s.matchAll(g)){let c=r.index+r[0].length;if(s.slice(c).trim()==="")break;e+=s.slice(o,r.index),o=c}return e+s.slice(o)}).join(`
3
+ `):t}function _(t){return t.replace(g,"").replace(h,"").replace(/\s*\/\/\s*![a-z]+.*$/gm,"").trim()}var $=new Set(["","text","txt","plain","plaintext","none","output","log","code","codeblock"]);function B(t){if(t==null)return[];let n=[];for(let s of String(t).replace(/[{}]/g,"").split(/[,\s]+/)){let e=/^(\d+)(?:-(\d+))?$/.exec(s);if(!e)continue;let o=Number(e[1]),r=e[2]?Number(e[2]):o;for(let c=o;c<=Math.min(r,o+5e3);c++)n.push(c)}return n}function S(t){let n=[...new Set(t)].filter(e=>e>0).sort((e,o)=>e-o),s=[];for(let e of n){let o=s[s.length-1];o&&e===o[1]+1?o[1]=e:s.push([e,e])}return s}function C(t,n,s){let e=t.indexOf("<code>"),o=t.lastIndexOf("</code>");if(e<0||o<e||!n.length)return t;let r=t.slice(e+6,o).split(`
4
+ `);for(let[c,p]of S(n).reverse()){if(c>r.length)continue;let l=Math.min(p,r.length),i=`<span class="code-collapse"><label class="code-collapse-label" data-pagefind-ignore><input type="checkbox" class="code-collapse-toggle">${s(l-c+1)}</label><span class="code-collapse-lines">${r.slice(c-1,l).join(`
5
+ `)}</span></span>`;r.splice(c-1,l-c+1,i)}return t.slice(0,e+6)+r.join(`
6
+ `)+t.slice(o)}function k(t,n,s,e){if(!s&&!e)return"";let o=[];return s&&o.push(String(t).padStart(3)),e&&o.push(n==="add"?"+":n==="remove"?"\u2212":" "),`<span class="gutter${n?` ${n}`:""}" data-pagefind-ignore>${o.join(" ")}</span>`}function N(t,n={}){let s=new Set(n.highlights??[]),e=new Set(n.diffAdd??[]),o=new Set(n.diffRemove??[]),r=n.lineNumbers?" line-numbers":"",c=e.size>0||o.size>0,p=t.split(`
7
+ `).map((l,i)=>{let a=i+1,f=e.has(a)?"add":o.has(a)?"remove":"";return`<span class="${["line",s.has(a)&&"highlighted",f&&`diff ${f}`].filter(Boolean).join(" ")}">${k(a,f,!!n.lineNumbers,c)}${d(l)}</span>`});return`<pre class="shiki shiki-plain${r}" tabindex="0"><code>${p.join(`
8
+ `)}</code></pre>`}var x=/[ \t]*(?:(?:\/\/|#|--|<!--|\/\*|;)[ \t]*)?\[!code (\+\+|--|highlight|hl)(?::(\d+))?\](?:[ \t]*(?:-->|\*\/))?/;function R(t,n={}){if(!t.includes("[!code"))return{code:t,opts:n};let s=new Set(n.highlights??[]),e=new Set(n.diffAdd??[]),o=new Set(n.diffRemove??[]),r=[],c,p=(l,i)=>(i==="++"?e:i==="--"?o:s).add(l);for(let l of t.split(`
9
+ `)){let i=x.exec(l),a=i?l.replace(x,""):l;if(i&&a.trim()===""){c={kind:i[1],left:Number(i[2]??1)};continue}r.push(a);let f=r.length;if(c&&c.left>0&&(p(f,c.kind),--c.left===0&&(c=void 0)),i){let u=Number(i[2]??1);p(f,i[1]),u>1&&(c={kind:i[1],left:u-1})}}return{code:r.join(`
10
+ `),opts:{...n,highlights:[...s].sort((l,i)=>l-i),diffAdd:[...e].sort((l,i)=>l-i),diffRemove:[...o].sort((l,i)=>l-i)}}}function v(){let t=s=>{let e=(s??"").toLowerCase().trim();return $.has(e)?"text":e},n=(s,e,o={})=>{let r=R(s.replace(/\n$/,""),o);return N(m(r.code,!0),r.opts)};return{resolve:t,render:n,code:n,has:()=>!1,prime:()=>{},cacheStats:()=>({entries:0,chars:0,hits:0,misses:0})}}var F=v();export{d as a,j as b,w as c,A as d,O as e,E as f,L as g,m as h,_ as i,$ as j,B as k,C as l,N as m,F as n};