mdeval 1.2.0 → 1.3.1

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
@@ -7,6 +7,8 @@ Ever wanted dynamic values in your Markdown — package versions, star counts, c
7
7
 
8
8
  mdeval embeds JavaScript directly in your Markdown using HTML comments. The logic lives right next to the content it produces, and the file renders normally everywhere — GitHub, editors, any Markdown viewer — because HTML comments are invisible.
9
9
 
10
+ Any value that matters — a dependency count, a version string, a benchmark result — is computed, not typed. Whether written by a person or an AI agent, the expression shows the work and anyone can verify it. Re-run `mdeval` and every value updates.
11
+
10
12
  ## Install
11
13
 
12
14
  ```bash
@@ -51,7 +53,11 @@ The file is updated in-place. You can pass multiple files or glob patterns: `mde
51
53
  - Markers can be **self-contained** — no script block needed:
52
54
 
53
55
  ```markdown
54
- <!--mdeval (() => 2 + 2)()-->4<!--/mdeval-->
56
+ <!--mdeval (() => {
57
+ const n = 3;
58
+ if (n % 2 === 0) { return 'even' }
59
+ return 'odd'
60
+ })()-->odd<!--/mdeval-->
55
61
  ```
56
62
 
57
63
  In large documents, this IIFE pattern lets you keep logic next to the marker it serves instead of in a distant script block.
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- var g=Object.defineProperty;var l=(r,o)=>g(r,"name",{value:o,configurable:!0});import m from"node:fs/promises";import h from"node:path";import{cli as w}from"cleye";import{glob as E}from"tinyglobby";import{$ as y}from"zx";import{register as $}from"node:module";import{pathToFileURL as b}from"node:url";import{p as x,b as M,E as S,M as P,C as R,a as _}from"./parse-markdown-ChGEvmW3.mjs";import"md4x";const T=l(r=>{if(r==null)throw new Error(`Cannot interpolate ${r} \u2014 this is likely a bug in your script`);return typeof r=="string"?r:typeof r=="object"?Symbol.toPrimitive in r?String(r):JSON.stringify(r):String(r)},"coerceValue");$("#md-loader",import.meta.url);const k=l(async(r,o)=>{const{markers:t}=x(r);if(t.length===0)return r;const s=await import(b(o).href),p=M(t),u=await Promise.all(Array.from(p).map(async([e,c])=>{const n=T(await s[`${S}${c}`]);if(n.includes(P)||n.includes(`${R}
3
- `)||n.includes(_))throw new Error(`Expression "${e}" produced a value containing mdeval comment syntax, which would corrupt the document on re-parse`);return n})),i=[];let a=0;for(const e of t){const c=p.get(e.expression);i.push(r.slice(a,e.contentStart),u[c]),a=e.contentEnd}return i.push(r.slice(a)),i.join("")},"processSource");globalThis.block=r=>`
4
- ${String(r)}
5
- `,globalThis.$=y;const C=w({name:"mdeval",parameters:["<files...>"]}),d=C._.files,N=d.some(r=>r.includes("node_modules")),f=await E(d,{ignore:N?[]:["**/node_modules/**"]});f.length===0&&(console.error("No files matched the given patterns"),process.exit(1)),await Promise.all(f.map(async r=>{try{const o=h.resolve(r),t=await m.readFile(o,"utf8"),s=await k(t,o);s!==t&&(await m.writeFile(o,s,"utf8"),console.log(`Updated: ${r}`))}catch(o){console.error(`Error processing ${r}:`,o instanceof Error?o.message:o),process.exitCode=1}}));
2
+ var M=Object.defineProperty;var p=(o,r)=>M(o,"name",{value:r,configurable:!0});import m from"node:fs/promises";import $ from"node:path";import{cli as b}from"cleye";import{glob as x}from"tinyglobby";import{$ as S}from"zx";import{p as d,b as O,E as _,M as f,C as k,a as g,c as C,i as P}from"./parse-markdown-B18EMsYy.mjs";import{register as R}from"node:module";import{pathToFileURL as T}from"node:url";import"micromark";const N=p(o=>{if(o==null)throw new Error(`Cannot interpolate ${o} \u2014 this is likely a bug in your script`);return typeof o=="string"?o:typeof o=="object"?Symbol.toPrimitive in o?String(o):JSON.stringify(o):String(o)},"coerceValue");R("#md-loader",import.meta.url);const v=p(async(o,r)=>{const{markers:t}=d(o);if(t.length===0)return o;const i=await import(T(r).href),n=O(t),w=await Promise.all(Array.from(n).map(async([e,l])=>{const s=N(await i[`${_}${l}`]);if(s.includes(f)||s.includes(`${k}
3
+ `)||s.includes(g))throw new Error(`Expression "${e}" produced a value containing mdeval comment syntax, which would corrupt the document on re-parse`);return s})),a=[];let c=0;for(const e of t){const l=f.length+e.expression.length+C.length,s=e.start+l,E=e.end-g.length,y=n.get(e.expression);a.push(o.slice(c,s),w[y]),c=E}return a.push(o.slice(c)),a.join("")},"processSource");globalThis.block=o=>`
4
+ ${String(o)}
5
+ `,globalThis.$=S;const A=b({name:"mdeval",parameters:["<files...>"]}),u=A._.files,F=u.some(o=>o.includes("node_modules")),h=await x(u,{ignore:F?[]:["**/node_modules/**"]});h.length===0&&(console.error("No files matched the given patterns"),process.exit(1)),await Promise.all(h.map(async o=>{try{const r=$.resolve(o),t=await m.readFile(r,"utf8"),i=d(t);P(t,i)&&console.warn(`Warning: ${o} has no markdown content outside of mdeval blocks`);const n=await v(t,r);n!==t&&(await m.writeFile(r,n,"utf8"),console.log(`Updated: ${o}`))}catch(r){console.error(`Error processing ${o}:`,r instanceof Error?r.message:r),process.exitCode=1}}));
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- var p=Object.defineProperty;var i=(r,o)=>p(r,"name",{value:o,configurable:!0});import c from"node:fs/promises";import{fileURLToPath as m}from"node:url";import{p as f,b as u,E as d}from"./parse-markdown-ChGEvmW3.mjs";import"md4x";const l=i((r,o)=>{const t=r.join(`
3
- `),s=u(o);if(s.size===0)return t;const e=[...s].map(([n,a])=>`export const ${d}${a} = ${n};`);return`${t}
4
- ${e.join(`
5
- `)}`},"generateModule"),$=i(async(r,o,t)=>{if(!r.endsWith(".md"))return t(r,o);const s=await c.readFile(m(r),"utf8"),{scriptBlocks:e,markers:n}=f(s);return e.length===0&&n.length===0?t(r,o):{format:"module",source:l(e,n),shortCircuit:!0}},"load");export{$ as load};
2
+ var p=Object.defineProperty;var i=(r,o)=>p(r,"name",{value:o,configurable:!0});import c from"node:fs/promises";import{fileURLToPath as m}from"node:url";import{p as f,b as u,E as d}from"./parse-markdown-B18EMsYy.mjs";import"micromark";const l=i((r,o)=>{const e=r.map(t=>t.content).join(`
3
+ `),s=u(o);if(s.size===0)return e;const n=[...s].map(([t,a])=>`export const ${d}${a} = ${t};`);return`${e}
4
+ ${n.join(`
5
+ `)}`},"generateModule"),$=i(async(r,o,e)=>{if(!r.endsWith(".md"))return e(r,o);const s=await c.readFile(m(r),"utf8"),{scriptBlocks:n,markers:t}=f(s);return n.length===0&&t.length===0?e(r,o):{format:"module",source:l(n,t),shortCircuit:!0}},"load");export{$ as load};
@@ -0,0 +1,4 @@
1
+ var M=Object.defineProperty;var i=(t,n)=>M(t,"name",{value:n,configurable:!0});import{postprocess as O,parse as u,preprocess as C}from"micromark";const g="mdeval",d=`<!--${g}`,_=`${d} `,E=`<!--/${g}-->`,R=`__${g}_`,p="-->",S=i(t=>{const n=new Map;for(const{expression:s}of t)n.has(s)||n.set(s,n.size);return n},"buildExpressionMap"),k=i(t=>{const n=t.codePointAt(0)===65279?1:0,s=O(u().document().write(C()(t,void 0,!0))),r=[];for(const[o,e]of s)o==="enter"&&(e.type==="codeFenced"||e.type==="codeIndented"||e.type==="codeText")&&r.push([e.start.offset+n,e.end.offset+n]);return r},"findCodeRanges"),I=i(t=>{let n=null,s=0;return r=>{for(n===null&&(n=k(t));s<n.length&&n[s][1]<=r;)s+=1;return s<n.length&&r>=n[s][0]}},"createIsInCode"),T=i(t=>{if(!t.includes(d))return{scriptBlocks:[],markers:[]};const n=I(t),s=[],r=[];let o=0;for(;o<t.length;){const e=t.indexOf(d,o);if(e===-1)break;const c=e+d.length,h=t[c];if(h===`
2
+ `||h==="\r"&&t[c+1]===`
3
+ `){const f=h===`
4
+ `?c+1:c+2,a=t.indexOf(p,f);if(a===-1)break;const l=a+p.length;n(e)||s.push({content:t.slice(f,a),start:e,end:l}),o=l;continue}if(h===" "){const f=c+1,a=t.indexOf(p,f);if(a===-1)break;const l=a+p.length,x=t.indexOf(E,l);if(x===-1){o=l;continue}const m=x+E.length;n(e)||r.push({expression:t.slice(f,a),start:e,end:m}),o=m;continue}o=c}return{scriptBlocks:s,markers:r}},"parseMarkdown"),b=i((t,{scriptBlocks:n,markers:s})=>{if(n.length===0&&s.length===0)return!1;const r=[...n.map(e=>[e.start,e.end]),...s.map(e=>[e.start,e.end])].sort((e,c)=>e[0]-c[0]);let o=0;for(const[e,c]of r){if(t.slice(o,e).trim()!=="")return!1;o=c}return t.slice(o).trim()===""},"isOnlyMdeval");export{d as C,R as E,_ as M,E as a,S as b,p as c,b as i,T as p};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdeval",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "Evaluate JavaScript in markdown HTML comments and interpolate results in-place",
5
5
  "keywords": [
6
6
  "markdown",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "cleye": "^2.3.0",
32
- "md4x": "^0.0.25",
32
+ "micromark": "^4.0.2",
33
33
  "tinyglobby": "^0.2.15",
34
34
  "zx": "8.8.5-lite"
35
35
  }
@@ -5,6 +5,13 @@ description: Evaluates JavaScript in markdown HTML comments and interpolates res
5
5
 
6
6
  # mdeval
7
7
 
8
+ ## When to use
9
+
10
+ - Markdown contains values derived from code, files, APIs, or shell commands
11
+ - README stats, version numbers, dependency counts, or computed tables
12
+ - Any value where accuracy matters — counts, sizes, dates, calculations
13
+ - Auditable content — the expression proves the value is correct, not just asserted
14
+
8
15
  ## Syntax
9
16
 
10
17
  Two types of HTML comments — invisible when rendered:
@@ -1,3 +0,0 @@
1
- var _=Object.defineProperty;var d=(s,t)=>_(s,"name",{value:t,configurable:!0});import{parseAST as R}from"md4x";const x="mdeval",k=`<!--${x}`,O=`${k} `,M=`<!--/${x}-->`,C=`__${x}_`,A="-->",m=`${x}
2
- `,P=d(s=>{const t=new Map;for(const{expression:e}of s)t.has(e)||t.set(e,t.size);return t},"buildExpressionMap"),S=d((s,t)=>{const e=[],a=[];let l=0;const f=d(r=>{if(!Array.isArray(r))return;const[h,,...c]=r;if(h==="code"){const n=c[0];if(typeof n=="string"&&n.length>0){const o=t.indexOf(n,l);if(o!==-1){a.push([o,o+n.length]),l=o+n.length;return}const i=n.split(`
3
- `).filter(p=>p.length>0);if(i.length>0){const p=t.indexOf(i[0],l);if(p!==-1){let g=p+i[0].length;for(let E=1;E<i.length;E+=1){const u=t.indexOf(i[E],g);u!==-1&&(g=u+i[E].length)}a.push([p,g]),l=g}}}return}if(h===null&&typeof c[0]=="string"){const n=c[0];n.startsWith(m)&&e.push(n.slice(m.length));const o=`<!--${n}-->`,i=t.indexOf(o,l);i!==-1&&(l=i+o.length);return}for(const n of c)Array.isArray(n)&&f(n)},"walk");for(const r of s.nodes)f(r);return{scriptBlocks:e,codeRanges:a}},"walkAst"),w=d((s,t)=>{let e=0;const a=d(r=>{for(;e<t.length&&t[e][1]<=r;)e+=1;if(e>=t.length)return!1;const[h,c]=t[e];return r>=h&&r<c},"isInCode"),l=[];let f=0;for(;f<s.length;){const r=s.indexOf(O,f);if(r===-1)break;const h=r+O.length,c=s.indexOf(A,h);if(c===-1)break;const n=c+A.length,o=s.indexOf(M,n);if(o===-1){f=n;continue}const i=o+M.length;a(r)||l.push({expression:s.slice(h,c),contentStart:n,contentEnd:o}),f=i}return l},"findMarkers"),y=d(s=>{if(!s.includes(k))return{scriptBlocks:[],markers:[]};const t=R(s),{scriptBlocks:e,codeRanges:a}=S(t,s);return{scriptBlocks:e,markers:w(s,a)}},"parseMarkdown");export{k as C,C as E,O as M,M as a,P as b,y as p};