mdat 0.2.0 → 0.3.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.
package/dist/index.js CHANGED
@@ -1,3 +1,33 @@
1
- import{defaultLoaders as v}from"cosmiconfig";function P(n,e){let t=v[".json"],i=t(n,e);return M(i)}function M(n,e="",t={}){for(let[i,s]of Object.entries(n)){let o=e?`${e}.${i}`:i;typeof s=="object"&&s!==null&&!Array.isArray(s)?M(s,o,t):s===null?t[o]="null":t[o]=s.toString()}return t}import S from"chalk";import{cosmiconfig as j}from"cosmiconfig";import L from"node:fs/promises";import N from"node:path";import z from"plur";import{deepMergeDefined as w,log as g,optionsSchema as Z,rulesSchema as _}from"remark-mdat";async function x(n){let{additionalConfig:e,additionalRules:t,configExtensionSchema:i,searchFrom:s}=n??{},o={},r=Z;i!==void 0&&(r=r.merge(i));let u=j("mdat"),l=await u.search(s);if(l){let{config:a,filepath:d}=l;g.info(`Using config from "${d}"`);let f=T(a,r);f&&(o=w(o,f))}if(e!==void 0){let a=Array.isArray(e)?e:[e];for(let d of a){let f;if(typeof d=="string"){let c=await u.load(d);if(c==null)continue;let{config:m,filepath:h}=c;g.info(`Loaded additional config from "${h}"`),f=m}else f=d;if(f===void 0)continue;g.info("Merging configuration object");let p=T(f,r);p!==void 0&&(o=w(o,p))}}if(t!==void 0){let a=Array.isArray(t)?t:[t],d=j("mdat",{loaders:{".json":P}});for(let f of a){let p;if(typeof f=="string"){let m;if(N.basename(f).endsWith("package.json")){let I=await L.readFile(f,"utf8");m={config:P(f,I),filepath:f}}else m=await d.load(f);if(m==null)continue;let{config:h,filepath:V}=m;g.info(`Loaded additional config from "${V}"`),p=h}else p=f;if(p===void 0)continue;g.info("Merging rules into configuration object");let c=D(p,_);c!==void 0&&(o=w(o,c))}}if(o.rules){let a=Object.keys(o.rules).sort().map(d=>`"${S.bold.green(d)}"`);g.info(`Loaded ${S.bold(a.length)} mdat comment expansion ${z("rule",a.length)}:`);for(let d of a)g.info(` ${d}`)}else g.error("No rules loaded from additional configurations or rules, using default.");return o}function D(n,e){if(e.safeParse(n).success)return{rules:n};g.error(`Rules object has the wrong shape. Ignoring and using default configuration:
2
- ${JSON.stringify(n,void 0,2)}`)}function T(n,e){if(e.safeParse(n).success)return n;g.error(`Config object has the wrong shape. Ignoring and using default configuration:
3
- ${JSON.stringify(n,void 0,2)}`)}import G from"node:fs";import y from"node:path";import{isFileSync as $}from"path-type";import U from"untildify";function W(n,e){let t=e===0?1:Math.floor(Math.log10(Math.abs(e))+1);return n.toString().padStart(t,"0")}function b(n,e,t,i){let s=[];for(let[o,r]of n.entries()){let u=t&&n.length>1?`-${W(o+1,n.length+1)}`:"",l=C(r,e,t,i,u);s.push(l)}return s}function C(n,e,t,i,s=""){let o=k(n),r=e?k(e):void 0;if(!$(o))throw new Error(`Input file not found: "${o}"`);if(r){if($(r))throw new Error(`Output path must be a directory, received a file path: "${r}"`);G.mkdirSync(r,{recursive:!0})}let u=t?y.basename(t,y.extname(t)):y.basename(o,y.extname(o)),l=`.${i??(t&&y.extname(t)!==""?y.extname(t):y.extname(n)===""?"":y.extname(n))}`,a=`${u}${s}${l}`,d=r??y.dirname(o);return{input:o,name:a,output:d}}function k(n){return U(n)}import{remark as J}from"remark";import A from"remark-gfm";import{mdatClean as q,mdatSplit as B,default as H}from"remark-mdat";import{read as O}from"to-vfile";import{VFile as E}from"vfile";async function Q(n,e,t,i,s){let o=await x({additionalConfig:i,additionalRules:s}),r=b(n,t,e,"md"),u=[],l=F(o);for(let{input:a,name:d,output:f}of r){let p=await O(a),c=await l.process(p);c.dirname=f,c.basename=d,u.push(c)}return u}async function X(n,e,t,i,s){let o=await x({additionalConfig:i,additionalRules:s}),r=C(n,t,e,"md"),u=await O(r.input),l=await F(o).process(u);return l.dirname=r.output,l.basename=r.name,l}async function Y(n,e,t){let i=await x({additionalConfig:e,additionalRules:t});return F(i).process(new E(n))}function F(n){return J().use({settings:{bullet:"-",emphasis:"_"}}).use(A).use(H,n??{})}async function K(n,e,t,i){let s=await x({additionalConfig:i});console.log("----------------------------------"),console.log(`config: ${JSON.stringify(i,void 0,2)}`),console.log(`resolvedOptions: ${JSON.stringify(s,void 0,2)}`);let{closingPrefix:o,keywordPrefix:r,metaCommentIdentifier:u}=s,l=b(n,t,e,"md"),a=[],d=R({closingPrefix:o,keywordPrefix:r,metaCommentIdentifier:u});for(let{input:f,name:p,output:c}of l){let m=await O(f),h=await d.process(m);h.dirname=c,h.basename=p,a.push(h)}return a}async function nn(n,e,t,i){let{closingPrefix:s,keywordPrefix:o,metaCommentIdentifier:r}=await x({additionalConfig:i}),u=C(n,t,e,"md"),l=await O(u.input),a=await R({closingPrefix:s,keywordPrefix:o,metaCommentIdentifier:r}).process(l);return a.dirname=u.output,a.basename=u.name,a}async function tn(n,e){let{closingPrefix:t,keywordPrefix:i,metaCommentIdentifier:s}=await x({additionalConfig:e});return R({closingPrefix:t,keywordPrefix:i,metaCommentIdentifier:s}).process(new E(n))}function R(n){let{closingPrefix:e="/",keywordPrefix:t="",metaCommentIdentifier:i="+"}=n;return J().use({settings:{bullet:"-",emphasis:"_"}}).use(A).use(()=>function(o,r){B(o,r),q(o,r,{closingPrefix:e,keywordPrefix:t,metaCommentIdentifier:i})})}export{nn as cleanFile,K as cleanFiles,tn as cleanString,X as expandFile,Q as expandFiles,Y as expandString,x as loadConfig};
1
+ import{defaultLoaders as st}from"cosmiconfig";function H(t,e){let n=st[".json"],i=n(t,e);return Re(i)}function Re(t,e="",n={}){for(let[i,o]of Object.entries(t)){let a=e?`${e}.${i}`:i;typeof o=="object"&&o!==null&&!Array.isArray(o)?Re(o,a,n):o===null?n[a]="null":n[a]=o.toString()}return n}import{findUp as mt}from"find-up";import dt from"node:fs";import C from"node:path";import{packageUp as ct}from"package-up";import{isFileSync as Se}from"path-type";import{packageDirectory as ut}from"pkg-dir";import{log as ke}from"remark-mdat";import ft from"untildify";function pt(t,e){let n=e===0?1:Math.floor(Math.log10(Math.abs(e))+1);return t.toString().padStart(n,"0")}function z(t,e,n,i){let o=[];for(let[a,r]of t.entries()){let s=n&&t.length>1?`-${pt(a+1,t.length+1)}`:"",m=O(r,e,n,i,s);o.push(m)}return o}function O(t,e,n,i,o=""){let a=$e(t),r=e?$e(e):void 0;if(!Se(a))throw new Error(`Input file not found: "${a}"`);if(r){if(Se(r))throw new Error(`Output path must be a directory, received a file path: "${r}"`);dt.mkdirSync(r,{recursive:!0})}let s=n?C.basename(n,C.extname(n)):C.basename(a,C.extname(a)),m=`.${i??(n&&C.extname(n)!==""?C.extname(n):C.extname(t)===""?"":C.extname(t))}`,d=`${s}${o}${m}`,u=r??C.dirname(a);return{input:a,name:d,output:u}}function $e(t){return ft(t)}async function Ee(){ke.info("Searching for package directory...");let t=await ut()??process.cwd(),e=await mt("readme.md",{stopAt:t,type:"file"});if(e!==void 0)return ke.info(`Found closest readme at "${e}"`),e}async function xe(){return ct()}import Ne from"chalk";import{cosmiconfig as Oe}from"cosmiconfig";import lt from"node:fs/promises";import Te from"node:path";import gt from"plur";import{readPackage as ht}from"read-pkg";import{deepMergeDefined as q,log as g,optionsSchema as yt,rulesSchema as wt}from"remark-mdat";import{z as L}from"zod";var Le=yt.merge(L.object({assetsPath:L.string().optional(),packageFile:L.string().optional(),readmeFile:L.string().optional()})).describe("Config Extension");async function h(t){let{additionalConfig:e,additionalRules:n,searchFrom:i}=t??{},o={addMetaComment:!1,assetsPath:"./assets",closingPrefix:"/",keywordPrefix:"",metaCommentIdentifier:"+",packageFile:await xe(),readmeFile:await Ee(),rules:{mdat:"Powered by the Markdown Autophagic Template system: [mdat](https://github.com/kitschpatrol/mdat)."}},a=Oe("mdat"),r=await a.search(i);if(r){let{config:s,filepath:m}=r;g.info(`Using config from "${m}"`);let d=Fe(s,Le);d&&(o=q(o,d))}if(e!==void 0){let s=Array.isArray(e)?e:[e];for(let m of s){let d;if(typeof m=="string"){let f=await a.load(m);if(f==null)continue;let{config:p,filepath:w}=f;g.info(`Loaded additional config from "${w}"`),d=p}else d=m;if(d===void 0)continue;g.info("Merging configuration object");let u=Fe(d,Le);u!==void 0&&(o=q(o,u))}}if(n!==void 0){let s=Array.isArray(n)?n:[n],m=Oe("mdat",{loaders:{".json":H}});for(let d of s){let u;if(typeof d=="string"){let p;if(Te.basename(d).endsWith("package.json")){let at=await lt.readFile(d,"utf8");p={config:H(d,at),filepath:d}}else p=await m.load(d);if(p==null)continue;let{config:w,filepath:b}=p;g.info(`Loaded additional config from "${b}"`),u=w}else u=d;if(u===void 0)continue;g.info("Merging rules into configuration object");let f=Ct(u,wt);f!==void 0&&(o=q(o,f))}}if(o.rules){let s=Object.keys(o.rules).sort().map(m=>`"${Ne.bold.green(m)}"`);g.info(`Loaded ${Ne.bold(s.length)} mdat comment expansion ${gt("rule",s.length)}:`);for(let m of s)g.info(` ${m}`)}else g.error("No rules loaded from additional configurations or rules, using default.");return F=o,o}function Ct(t,e){if(e.safeParse(t).success)return{rules:t};g.error(`Rules object has the wrong shape. Ignoring and using default configuration:
2
+ ${JSON.stringify(t,void 0,2)}`)}function Fe(t,e){if(e.safeParse(t).success)return t;g.error(`Config object has the wrong shape. Ignoring and using default configuration:
3
+ ${JSON.stringify(t,void 0,2)}`)}var F;async function R(){return F===void 0&&(g.warn("getConfig(): config was undefined"),F??=await h()),F}var W;async function l(){let{packageFile:t}=await R();if(t===void 0)throw new Error("No packageFile found or set in config");if(W??=await ht({cwd:Te.dirname(t)}),W===void 0)throw new Error("No package.json found");return W}import{remark as Ae}from"remark";import je from"remark-gfm";import{mdatClean as Pt,mdatSplit as bt,default as Rt}from"remark-mdat";import{read as T}from"to-vfile";import{VFile as Me}from"vfile";async function St(t,e,n,i,o){let a=await h({additionalConfig:i,additionalRules:o});i=a;let r=z(t,n,e,"md"),s=[],m=Z(a);for(let{input:d,name:u,output:f}of r){let p=await T(d),w=await m.process(p);w.dirname=f,w.basename=u,s.push(w)}return s}async function Y(t,e,n,i,o){let a=await h({additionalConfig:i,additionalRules:o});i=a;let r=O(t,n,e,"md"),s=await T(r.input),m=await Z(a).process(s);return m.dirname=r.output,m.basename=r.name,m}async function K(t,e,n){let i=await h({additionalConfig:e,additionalRules:n});return e=i,Z(i).process(new Me(t))}async function kt(t,e,n,i){let o=await h({additionalConfig:i});i=o;let a=z(t,n,e,"md"),r=[],s=Q(o);for(let{input:m,name:d,output:u}of a){let f=await T(m),p=await s.process(f);p.dirname=u,p.basename=d,r.push(p)}return r}async function G(t,e,n,i){let o=await h({additionalConfig:i});i=o;let a=O(t,n,e,"md"),r=await T(a.input),s=await Q(o).process(r);return s.dirname=a.output,s.basename=a.name,s}async function $t(t,e){let n=await h({additionalConfig:e});return e=n,Q(n).process(new Me(t))}function Z(t){return Ae().use({settings:{bullet:"-",emphasis:"_"}}).use(je).use(Rt,t??{})}function Q(t){let{closingPrefix:e,keywordPrefix:n,metaCommentIdentifier:i}=t;return Ae().use({settings:{bullet:"-",emphasis:"_"}}).use(je).use(()=>function(a,r){bt(a,r),Pt(a,r,{closingPrefix:e,keywordPrefix:n,metaCommentIdentifier:i})})}import{z as x}from"zod";var A={badges:{async content(t){var r;let e=x.object({custom:x.record(x.object({image:x.string(),link:x.string()})).optional()}).optional().parse(t),n=await l(),{name:i}=n,o=[];!n.private&&((r=n.publishConfig)==null?void 0:r.access)==="public"&&o.push(`[![NPM Package](https://img.shields.io/npm/v/${i}.svg)](https://npmjs.com/package/${i})`);let{license:a}=n;if(a!==void 0&&o.push(`[![License: ${a}](https://img.shields.io/badge/License-${a}-yellow.svg)](https://opensource.org/licenses/${a})`),(e==null?void 0:e.custom)!==void 0)for(let[s,{image:m,link:d}]of Object.entries(e.custom))o.push(`[![${s}](${m})](${d})`);return o.join(`
4
+ `)},order:3,required:!1}};import{globby as Et}from"globby";import j from"node:path";import{isFile as xt}from"path-type";import{readPackage as Nt}from"read-pkg";import{z as X}from"zod";async function Ot(t){let{packageFile:e}=await R();if(e===void 0)throw new Error("No package.json found");let n=j.dirname(e),i=t===void 0?[".","assets","media","readme-assets","readme-media","readme","images"]:[t],o=["banner","header","logo","readme","cover","screenshot","screenshots","demo","overview","image","hero"],a=["png","gif","jpg","jpeg","svg","webp"],r=await Et(i.map(s=>j.join(n,s)),{expandDirectories:{extensions:a,files:o}});if(r.length>0)return j.relative(process.cwd(),r[0])}var M={banner:{async content(t){let e=X.object({alt:X.string().optional(),src:X.string().optional()}).optional().parse(t),{assetsPath:n,packageFile:i}=await R();if(i===void 0)throw new Error("No package.json found");let o=(e==null?void 0:e.src)??await Ot(n);if(o===void 0||!await xt(o))throw new Error(`Banner image not found at ${o===void 0?"any typical location, consider adding something at ./assets/banner.webp":`"${o}"`}`);let a=(e==null?void 0:e.alt)??`${(await Nt({cwd:j.dirname(i)})).name} banner`;if(a===void 0||a==="undefined banner")throw new Error("Banner image alt text not available");return`![${a}](${o})`},order:2}};import{CstParser as Lt,Lexer as S,createToken as c}from"chevrotain";var ne=c({name:"flag",pattern:/--[\w-_]+/}),oe=c({name:"alias",pattern:/-[A-Za-z]/}),ve=c({group:S.SKIPPED,name:"comma",pattern:/,/}),$=c({name:"word",pattern:/\S+/}),N=c({name:"argument",pattern:/<\S+>|\[\S+]/}),ie=c({name:"type",pattern:/\[(boolean|string|array)]/}),re=c({name:"defaultInfo",pattern:/\[default]/}),ae=c({name:"required",pattern:/\[required]/}),se=c({name:"defaultInfoDescription",pattern:/\[default:\s.+?]/}),me=c({name:"choices",pattern:/\[choices:\s.+?]/}),ee=c({group:S.SKIPPED,name:"whiteSpace",pattern:/\s/}),De=c({group:S.SKIPPED,name:"startProgramDescription",pattern:/\n\n/,push_mode:"PROGRAM_DESCRIPTION_MODE"}),de=c({name:"programDescription",pattern:/.+/}),Ue=c({group:S.SKIPPED,name:"endProgramDescription",pattern:/\n\n/,pop_mode:!0}),ce=c({name:"startOptionsSection",pattern:/Options:\n/,push_mode:"SECTION_MODE"}),ue=c({name:"startPositionalsSection",pattern:/Positionals:\n/,push_mode:"SECTION_MODE"}),fe=c({name:"startCommandsSection",pattern:/Commands:\n/,push_mode:"SECTION_MODE"}),pe=c({name:"startRow",pattern:/ {2,}/,push_mode:"ROW_MODE"}),le=c({name:"rowDescription",pattern:/ {2}\w.+ {2}/}),ge=c({name:"rowDescriptionTerminal",pattern:/ {2}\w.+/}),_e=c({group:S.SKIPPED,name:"endRow",pattern:/\n/,pop_mode:!0}),Ie=c({group:S.SKIPPED,name:"endSection",pattern:/\n+/,pop_mode:!0}),Ft=new S({defaultMode:"DEFAULT_MODE",modes:{DEFAULT_MODE:[ce,ue,fe,De,N,$,ee],PROGRAM_DESCRIPTION_MODE:[Ue,de],ROW_MODE:[_e,ve,ie,le,ge,se,re,ae,me,ne,oe,N,$,ee],SECTION_MODE:[pe,Ie]}}),Tt=[ne,oe,ve,$,N,ie,re,ae,se,me,ee,De,de,Ue,ce,ue,fe,pe,le,ge,_e,Ie];function At(t){return Ft.tokenize(t.trim())}var te=class extends Lt{programHelp=this.RULE("programHelp",()=>{this.AT_LEAST_ONE(()=>{this.CONSUME($,{LABEL:"commandName"})}),this.MANY1(()=>{this.CONSUME(N)}),this.OPTION(()=>{this.CONSUME(de,{LABEL:"description"})}),this.OPTION1(()=>{this.SUBRULE(this.commandsSection)}),this.OPTION2(()=>{this.SUBRULE(this.positionalsSection)}),this.OPTION3(()=>{this.SUBRULE(this.optionsSection)})});positionalsSection=this.RULE("positionalsSection",()=>{this.CONSUME(ue),this.MANY(()=>{this.SUBRULE(this.sectionRow)})});commandsSection=this.RULE("commandsSection",()=>{this.CONSUME(fe),this.MANY1(()=>{this.SUBRULE1(this.sectionRow)})});optionsSection=this.RULE("optionsSection",()=>{this.CONSUME(ce),this.MANY2(()=>{this.SUBRULE2(this.sectionRow)})});sectionRow=this.RULE("sectionRow",()=>{this.CONSUME(pe),this.OPTION(()=>{this.CONSUME($,{LABEL:"parentCommandName"})}),this.MANY(()=>{this.CONSUME1($,{LABEL:"commandName"})}),this.MANY1(()=>{this.OR([{ALT:()=>this.CONSUME(N)},{ALT:()=>this.CONSUME(oe)},{ALT:()=>this.CONSUME(ne)},{ALT:()=>this.CONSUME(le,{LABEL:"description"})},{ALT:()=>this.CONSUME(ge,{LABEL:"description"})},{ALT:()=>this.CONSUME(ie)},{ALT:()=>this.CONSUME(ae)},{ALT:()=>this.CONSUME(se)},{ALT:()=>this.CONSUME(re)},{ALT:()=>this.CONSUME(me)}])})});constructor(){super(Tt),this.performSelfAnalysis()}},k=new te;function Ve(t){let e=At(t);k.input=e.tokens;let n=k.programHelp();if(k.errors.length>0)throw new Error(`Errors parsing CLI command help text output: ${JSON.stringify(k.errors,void 0,2)}`);return n}var he=class extends k.getBaseCstVisitorConstructor(){constructor(){super(),this.validateVisitor()}programHelp(e){let{command:n,subcommand:i}=Mt(this.getString(e.commandName));return{arguments:this.getArray(e.argument),commandName:n,commands:e.commandsSection?this.visit(e.commandsSection):void 0,description:this.getString(e.description),options:e.optionsSection?this.visit(e.optionsSection):void 0,positionals:e.positionalsSection?this.visit(e.positionalsSection):void 0,subcommandName:i}}positionalsSection(e){return e.sectionRow.map(n=>this.positionalParentCommandToArguments(this.visit(n)))}commandsSection(e){return e.sectionRow.map(n=>this.visit(n))}optionsSection(e){return e.sectionRow.map(n=>this.visit(n))}sectionRow(e){return{aliases:this.getArray(e.alias),arguments:this.getArray(e.argument),choices:this.splitChoices(this.getString(e.choices)),commandName:this.getString(e.commandName),default:e.defaultInfo?!0:void 0,defaultValue:this.getString(e.defaultInfoDescription,!0),description:this.getString(e.description,!0),flags:this.getArray(e.flag),parentCommandName:this.getString(e.parentCommandName),required:e.required?!0:void 0,type:this.getString(e.type,!0)}}positionalParentCommandToArguments(e){let{arguments:n,parentCommandName:i,...o}=e;return i===void 0?e:{arguments:[i,...n??[]],...o}}getString(e,n=!1){if(e!==void 0)return e.map(i=>n?this.clean(i.image):i.image).join(" ")}getArray(e){if(e!==void 0)return e.map(n=>n.image)}clean(e){return e.replaceAll(/^[\s[]*(default:)?\s*|[\s\]]*$/g,"")}splitChoices(e){if(e!==void 0)return this.clean(e.replaceAll(/^\[choices:\s/g,"")).split(", ")}},jt=new he;function Je(t){return jt.visit(t)}function Mt(t){if(t===void 0)throw new Error('Could not find "commandName" entry in help');let e=t.split(" ");if(e.length===0&&t===void 0)throw new Error('Could not find "commandName" entry in help');if(e.length===1)return{command:e[0],subcommand:void 0};let n=e.at(-1);return{command:e.slice(0,-1).join(" "),subcommand:n}}function Be(t,e=!1){var i,o,a;let n=[];if(e){let r=(i=t.commands)==null?void 0:i.find(d=>d.default),s=(o=t.commands)==null?void 0:o.find(d=>d.commandName===void 0),m=`${t.commandName}${t.subcommandName?` ${t.subcommandName}`:""}`;n.push(`#### Command: \`${m}\``),s!=null&&s.description&&n.push(s==null?void 0:s.description),n.push(`This section lists top-level commands for \`${m}\`.`),r&&n.push(`If no command is provided, \`${r.parentCommandName} ${r.commandName}\` is run by default.`),n.push("Usage:"),s&&n.push(`\`\`\`txt
5
+ ${s.parentCommandName}${s.arguments?` ${s.arguments.join(" ")}`:""}
6
+ \`\`\``),t.commands=(a=t.commands)==null?void 0:a.filter(d=>d!==s)}else n.push(`#### Subcommand: \`${t.commandName} ${t.subcommandName}\``),n.push(t.description),n.push("Usage:"),n.push(`\`\`\`txt
7
+ ${t.commandName} ${t.subcommandName}${t.arguments?` ${t.arguments.join(" ")}`:""}
8
+ \`\`\``);return t.positionals&&!e&&n.push(ye(["Positional Argument","Description","Type","Default"],t.positionals.map(r=>[r.arguments?[r.arguments.map(s=>`\`${s}\``)].join(" "):"",`${r.description??""}${r.required?" _(Required.)_":" _(Optional.)_"}`,r.type?`\`${r.type}\``:"",r.defaultValue?r.defaultValue.includes(" ")?r.defaultValue:`\`${r.defaultValue}\``:""]))),t.commands&&n.push(ye(["Command","Argument","Description"],t.commands.map(r=>{var s;return[`\`${r.commandName??(r.default?"[default]":"")}\``,r.arguments?(s=r.arguments)==null?void 0:s.map(m=>`\`${m}\``).join(" "):"",`${r.description??""}${r.default?" _(Default command.)_":""}`]}))),t.options&&!e&&n.push(ye(["Option","Alias","Argument","Description","Type","Default"],t.options.map(r=>[r.flags?r.flags.map(s=>`\`${s}\``).join(" "):"",r.aliases?r.aliases.map(s=>`\`${s}\``).join(" "):"",r.arguments?r.arguments.map(s=>`\`${s}\``).join(" "):"",r.description??"",r.type?`\`${r.type}\``:"",r.defaultValue?r.defaultValue.includes(" ")?r.defaultValue:`\`${r.defaultValue}\``:""]))),e&&n.push("_See the sections below for more information on each subcommand._"),n.join(`
9
+
10
+ `)}function ye(t,e){let n=vt(e);t=t.filter((o,a)=>!n.includes(a)),e=e.map(o=>o.filter((a,r)=>!n.includes(r)));let i="";i+=`| ${t.join(" | ")} |
11
+ `,i+=`| ${t.map(()=>"---").join(" | ")} |
12
+ `;for(let o of e)i+=`| ${o.join(" | ")} |
13
+ `;return i}function vt(t){var i;let e=[],n=((i=t[0])==null?void 0:i.length)||0;for(let o=0;o<n;o++){let a=!0;for(let r of t)if(r[o]!==""){a=!1;break}a&&e.push(o)}return e}import{execaCommand as Dt}from"execa";import{log as He}from"remark-mdat";async function we(t){let e=`${t} --help`,n;try{let{stderr:o,stdout:a}=await Dt(e);n=a,(n===void 0||n==="")&&(n=o)}catch(o){if(o instanceof Error)throw new TypeError(`Error running CLI help command: ${e}
14
+ ${o.message}
15
+ `)}if(n===void 0||n==="")throw new Error(`No result from running CLI help command: ${e}
16
+ `);let i;try{let o=Ve(n);i=Je(o)}catch(o){o instanceof Error&&(i=void 0,He.warn(`Error parsing help output for command: ${t}
17
+ ${o.message}`),He.warn("Falling back to basic cli help text output."))}return i===void 0?_t(n):Ut(t,i)}async function Ut(t,e){let n=(e.commands&&e.commands.some(a=>a.default))??!1,i=Be(e,n),o=t.split(" ")[0];if(e.commands)for(let a of e.commands){if(!a.parentCommandName||!a.commandName)continue;let r=await we(`${o} ${a.commandName}`);i+=`
18
+
19
+ ${r}`}return i}function _t(t){return`\`\`\`txt
20
+ ${t}
21
+ \`\`\``}import{isExecutable as It}from"is-executable";import Vt from"node:path";import{log as Jt}from"remark-mdat";import Bt from"which";async function ze(t){return t??=await Ht(),qt(t)}async function Ht(){let t=await l();if(t!=null&&t.bin){let e=typeof t.bin=="string"?t.bin:String(Object.values(t.bin).at(0));if(zt(e))return Jt.info(`Inferred <!-- cli-help --> command to run from package.json: ${e}`),e}throw new Error(`Could not infer which command to run for the <!-- cli-help --> rule. Please pass a "cliCommand" option to the expansion comment, e.g. <!-- cli-help {cliCommend: './dist/bin.js'} -->`)}function zt(t){let e=Vt.parse(t);return e.root!==""||e.dir!==""}async function qt(t){let e=await Bt(t,{nothrow:!0});if(e===null&&(e=await Wt(t)??void 0),e!==void 0&&await It(e))return e;throw new Error(`The cli-help rule noticed that "${e}" is not executable.`)}async function Wt(t){var n;let e=await l();return((n=e==null?void 0:e.bin)==null?void 0:n[t])??void 0}import{z as qe}from"zod";var We={"cli-help":{async content(t){let e=qe.object({cliCommand:qe.string().optional()}).optional().parse(t),n=await ze(e==null?void 0:e.cliCommand);return we(n)}}};import Yt from"node:fs/promises";import Ye from"node:path";import{z as Ce}from"zod";var Ke={code:{async content(t){let e=Ce.object({file:Ce.string(),language:Ce.string().optional()}).parse(t),n=Ye.extname(e.file)??"",i=await Yt.readFile(Ye.join(process.cwd(),e.file),"utf8");return`\`\`\`${n}
22
+ ${i}
23
+ \`\`\``}}};var v={contributing:{async content(){var n;let t=await l(),e=(n=t==null?void 0:t.bugs)==null?void 0:n.url;if(e===void 0)throw new Error('Could not find "bugs.url" entry in package.json');return`## Contributing
24
+ [Issues](${e}) and pull requests are welcome.`},order:15,required:!0}};var D={license:{async content(){let t=await l(),{author:e,license:n}=t;if((e==null?void 0:e.name)===void 0)throw new Error('Could not find "author.name" entry in package.json');if(n===void 0)throw new Error('Could not find "license" entry in package.json');return`## License
25
+ [${n}](license.txt) \xA9 ${e.name}`},order:16,required:!0}};import{getSoleRule as Ge}from"remark-mdat";var Ze={footer:{content:[Ge(v),Ge(D)],order:17}};var U={"short-description":{async content(){let t=await l();if(t.description===void 0)throw new Error('Could not find "description" entry in package.json');return`**${t.description}**`},order:4,required:!0}};import{z as _}from"zod";var I={title:{applicationOrder:2,async content(t){let{postfix:e,prefix:n,titleCase:i}=_.object({postfix:_.string().optional().default(""),prefix:_.string().optional().default(""),titleCase:_.boolean().optional().default(!1)}).parse(t??{}),{name:o}=await l();return`# ${n}${i?Kt(o):o}${e}`},order:1,required:!0}};function Kt(t){return t.split(/[ _-]/).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}import{getSoleRule as V}from"remark-mdat";var Qe={header:{applicationOrder:2,content:[V(I),V(M),V(A),V(U)],order:1}};import{toc as Gt}from"mdast-util-toc";import{remark as Zt}from"remark";import Qt from"remark-gfm";import{z as P}from"zod";var J={"table-of-contents":{applicationOrder:1,async content(t,e){let n=P.object({maxDepth:P.union([P.literal(1),P.literal(2),P.literal(3),P.literal(4),P.literal(5),P.literal(6)]).optional()}).optional().parse(t),i=Gt(e,{heading:null,maxDepth:(n==null?void 0:n.maxDepth)??3,tight:!0}),o="## Table of contents";if(i.map===void 0)throw new Error("Could not generate table of contents");let a={children:i.map.children,type:"root"},r=Zt().use(Qt).stringify(a).replaceAll(`
26
+
27
+ `,`
28
+ `);return[o,r].join(`
29
+ `)},order:6}};import{tldrawToImage as Xe}from"@kitschpatrol/tldraw-cli";import Xt from"node:crypto";import E from"node:fs/promises";import y from"node:path";import{isFile as Pe}from"path-type";import{z as be}from"zod";var ot={tldraw:{async content(t){let{alt:e="tldraw diagram",src:n}=be.object({alt:be.string().optional(),src:be.string()}).parse(t),{assetsPath:i}=await R();if(i===void 0)throw new Error("No assets path found");await E.mkdir(i,{recursive:!0});let o=await Pe(n)?await tt(n):void 0;if(o!==void 0){let d=y.basename(n,y.extname(n)),u=y.join(i,`${d}-${o}-light.svg`),f=y.join(i,`${d}-${o}-dark.svg`);if(await Pe(u)&&await Pe(f))return et(u,f,e)}let[a]=await Xe(n,{dark:!1,format:"svg",output:i,transparent:!0});o??=await tt(a);let r=`${nt(a)}-${o}-light.svg`;await E.rename(a,r);let[s]=await Xe(n,{dark:!0,format:"svg",output:i,transparent:!0}),m=`${nt(s)}-${o}-dark.svg`;if(await E.rename(s,m),o!==void 0){let d=y.basename(m),u=y.basename(r),f=u.replace(`${o}-light.svg`,""),p=await E.readdir(i);for(let w of p){let b=y.basename(w);b!==d&&b!==u&&b.startsWith(f)&&b.endsWith(".svg")&&await E.rm(y.join(i,b))}}return et(r,m,e)}}};async function et(t,e,n){let{readmeFile:i}=await R();if(i===void 0)throw new Error("No readme file found");let o=y.dirname(i),a=y.relative(o,t);return`<picture>
30
+ <source media="(prefers-color-scheme: dark)" srcset="${y.relative(o,e)}">
31
+ <source media="(prefers-color-scheme: light)" srcset="${a}">
32
+ <img alt="${n}" src="${a}">
33
+ </picture>`}async function tt(t){let e=await E.readFile(t),n=Xt.createHash("sha1");return n.update(e),n.digest("hex").slice(0,8)}function nt(t){return t.replace(/\.[^./]+$/,"")}import{getSoleRule as en}from"remark-mdat";var it={toc:{applicationOrder:1,content:[en(J)]}};var rt={...A,...M,...We,...Ke,...v,...Ze,...Qe,...D,...U,...J,...ot,...it,...I};async function tn(t,e,n,i){let o=await B({additionalConfig:n,additionalRules:i});return Y(o.readmeFile,t,e,o)}async function nn(t,e,n){let i=await B({additionalConfig:e,additionalRules:n});return K(t,i)}async function on(t){let e=await B({additionalConfig:t});return G(e.readmeFile,void 0,void 0,e)}async function B(t){let e={addMetaComment:!0,rules:rt},{additionalConfig:n=[],...i}=t??{},o=Array.isArray(n)?n:[n],a=await h({additionalConfig:[e,...o],...i});if(a.packageFile===void 0||a.readmeFile===void 0)throw new Error("Package and readme files are required in `mdat readme` config");return a}export{G as cleanFile,kt as cleanFiles,on as cleanReadme,$t as cleanString,Y as expandFile,St as expandFiles,tn as expandReadme,nn as expandReadmeString,K as expandString,h as loadConfig,B as loadConfigReadme};
@@ -0,0 +1,13 @@
1
+ import { type ConfigLoaded, type ConfigToLoad, type RulesToLoad, loadConfig } from '../config';
2
+ import { type Simplify } from 'type-fest';
3
+ import { type VFile } from 'vfile';
4
+ type ReadmeConfigLoaded = Simplify<{
5
+ packageFile: string;
6
+ readmeFile: string;
7
+ } & ConfigLoaded>;
8
+ export declare function expandReadme(name?: string, output?: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile>;
9
+ export declare function expandReadmeString(markdown: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile>;
10
+ export declare function cleanReadme(config?: ConfigToLoad): Promise<VFile>;
11
+ type LoadConfigOptions = Parameters<typeof loadConfig>[0];
12
+ export declare function loadConfigReadme(options?: LoadConfigOptions): Promise<ReadmeConfigLoaded>;
13
+ export {};
@@ -0,0 +1,8 @@
1
+ declare const _default: {
2
+ badges: {
3
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
4
+ order: number;
5
+ required: false;
6
+ };
7
+ };
8
+ export default _default;
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ banner: {
3
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
4
+ order: number;
5
+ };
6
+ };
7
+ export default _default;
@@ -0,0 +1,6 @@
1
+ declare const _default: {
2
+ 'cli-help': {
3
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
4
+ };
5
+ };
6
+ export default _default;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Get help output from a CLI command and return it as markdown
3
+ */
4
+ export declare function getHelpMarkdown(cliCommand: string): Promise<string>;
@@ -0,0 +1,35 @@
1
+ import { type CstNode } from 'chevrotain';
2
+ type Command = {
3
+ arguments?: string[];
4
+ commandName?: string;
5
+ default?: boolean;
6
+ description?: string;
7
+ parentCommandName?: string;
8
+ };
9
+ type Positional = {
10
+ arguments?: string[];
11
+ defaultValue?: string;
12
+ description?: string;
13
+ required?: boolean;
14
+ type?: string;
15
+ };
16
+ type Option = {
17
+ aliases?: string[];
18
+ arguments?: string[];
19
+ choices?: string[];
20
+ defaultValue?: string;
21
+ description?: string;
22
+ flags?: string[];
23
+ type?: string;
24
+ };
25
+ export type ProgramInfo = {
26
+ arguments?: string[];
27
+ commandName: string;
28
+ commands?: Command[];
29
+ description?: string;
30
+ options?: Option[];
31
+ positionals?: Positional[];
32
+ subcommandName?: string;
33
+ };
34
+ export declare function helpCstToObject(cst: CstNode): ProgramInfo;
35
+ export {};
@@ -0,0 +1,7 @@
1
+ import { type ProgramInfo } from './help-cst-to-object';
2
+ /**
3
+ * Simple case without subcommands
4
+ * @param programInfo - a ProgramInfo object, likely output from helpCstToObject()
5
+ * @returns - markdown string with help in table form, ready to be rendered
6
+ */
7
+ export declare function helpObjectToMarkdown(programInfo: ProgramInfo, commandsOnly?: boolean): string;
@@ -0,0 +1,13 @@
1
+ import { type CstNode, CstParser, type ILexingResult } from 'chevrotain';
2
+ export declare function tokenizeHelp(text: string): ILexingResult;
3
+ declare class CliParser extends CstParser {
4
+ programHelp: import("chevrotain").ParserMethod<[], CstNode>;
5
+ private readonly positionalsSection;
6
+ private readonly commandsSection;
7
+ private readonly optionsSection;
8
+ private readonly sectionRow;
9
+ constructor();
10
+ }
11
+ export declare const parser: CliParser;
12
+ export declare function helpStringToCst(text: string): CstNode;
13
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Accommodate missing or sloppy cli help command input
3
+ * @param cliCommand - Can be nothing, a command name on the path like `git`, or a path to an executable like `./bin/cli.js`
4
+ * @returns The path to a verified executable
5
+ * @throws If nothing can be inferred or resolved
6
+ */
7
+ export declare function inferCommand(cliCommand: string | undefined): Promise<string>;
@@ -0,0 +1,6 @@
1
+ declare const _default: {
2
+ code: {
3
+ content(options: import("type-fest").JsonValue): Promise<string>;
4
+ };
5
+ };
6
+ export default _default;
@@ -0,0 +1,8 @@
1
+ declare const _default: {
2
+ contributing: {
3
+ content(): Promise<string>;
4
+ order: number;
5
+ required: true;
6
+ };
7
+ };
8
+ export default _default;
@@ -0,0 +1,11 @@
1
+ declare const _default: {
2
+ footer: {
3
+ content: {
4
+ content(): Promise<string>;
5
+ order: number;
6
+ required: true;
7
+ }[];
8
+ order: number;
9
+ };
10
+ };
11
+ export default _default;
@@ -0,0 +1,11 @@
1
+ declare const _default: {
2
+ header: {
3
+ applicationOrder: number;
4
+ content: {
5
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
6
+ order: number;
7
+ }[];
8
+ order: number;
9
+ };
10
+ };
11
+ export default _default;
@@ -0,0 +1,71 @@
1
+ declare const _default: {
2
+ title: {
3
+ applicationOrder: number;
4
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
5
+ order: number;
6
+ required: true;
7
+ };
8
+ toc: {
9
+ applicationOrder: number;
10
+ content: {
11
+ applicationOrder: number;
12
+ content(options: import("type-fest").JsonValue, tree: import("mdast").Root): Promise<string>;
13
+ order: number;
14
+ }[];
15
+ };
16
+ tldraw: {
17
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
18
+ };
19
+ 'table-of-contents': {
20
+ applicationOrder: number;
21
+ content(options: import("type-fest").JsonValue, tree: import("mdast").Root): Promise<string>;
22
+ order: number;
23
+ };
24
+ 'short-description': {
25
+ content(): Promise<string>;
26
+ order: number;
27
+ required: true;
28
+ };
29
+ license: {
30
+ content(): Promise<string>;
31
+ order: number;
32
+ required: true;
33
+ };
34
+ header: {
35
+ applicationOrder: number;
36
+ content: {
37
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
38
+ order: number;
39
+ }[];
40
+ order: number;
41
+ };
42
+ footer: {
43
+ content: {
44
+ content(): Promise<string>;
45
+ order: number;
46
+ required: true;
47
+ }[];
48
+ order: number;
49
+ };
50
+ contributing: {
51
+ content(): Promise<string>;
52
+ order: number;
53
+ required: true;
54
+ };
55
+ code: {
56
+ content(options: import("type-fest").JsonValue): Promise<string>;
57
+ };
58
+ 'cli-help': {
59
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
60
+ };
61
+ banner: {
62
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
63
+ order: number;
64
+ };
65
+ badges: {
66
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
67
+ order: number;
68
+ required: false;
69
+ };
70
+ };
71
+ export default _default;
@@ -0,0 +1,8 @@
1
+ declare const _default: {
2
+ license: {
3
+ content(): Promise<string>;
4
+ order: number;
5
+ required: true;
6
+ };
7
+ };
8
+ export default _default;
@@ -0,0 +1,8 @@
1
+ declare const _default: {
2
+ 'short-description': {
3
+ content(): Promise<string>;
4
+ order: number;
5
+ required: true;
6
+ };
7
+ };
8
+ export default _default;
@@ -0,0 +1,9 @@
1
+ import { type Root } from 'mdast';
2
+ declare const _default: {
3
+ 'table-of-contents': {
4
+ applicationOrder: number;
5
+ content(options: import("type-fest").JsonValue, tree: Root): Promise<string>;
6
+ order: number;
7
+ };
8
+ };
9
+ export default _default;
@@ -0,0 +1,9 @@
1
+ declare const _default: {
2
+ title: {
3
+ applicationOrder: number;
4
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
5
+ order: number;
6
+ required: true;
7
+ };
8
+ };
9
+ export default _default;
@@ -0,0 +1,6 @@
1
+ declare const _default: {
2
+ tldraw: {
3
+ content(options?: import("type-fest").JsonValue | undefined): Promise<string>;
4
+ };
5
+ };
6
+ export default _default;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Simple alias for table-of-contents
3
+ */
4
+ declare const _default: {
5
+ toc: {
6
+ applicationOrder: number;
7
+ content: {
8
+ applicationOrder: number;
9
+ content(options: import("type-fest").JsonValue, tree: import("mdast").Root): Promise<string>;
10
+ order: number;
11
+ }[];
12
+ };
13
+ };
14
+ export default _default;
@@ -9,3 +9,14 @@ export declare function getInputOutputPath(input: string, output: string | undef
9
9
  output: string;
10
10
  };
11
11
  export declare function expandPath(file: string): string;
12
+ /**
13
+ * Searches for a readme file in the following order:
14
+ * 1. Searches the current working directly for readme.md
15
+ * 2. If there's no readme.md in the current directory, search up to the closest package directory
16
+ * 3. Give up and return undefined if no readme is found
17
+ *
18
+ * @returns The path to the readme file
19
+ * @throws If no readme is found
20
+ */
21
+ export declare function findReadme(): Promise<string | undefined>;
22
+ export declare function findPackage(): Promise<string | undefined>;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "mdat",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
- "description": "CLI tool and library for using comments as content templates in Markdown files.",
5
+ "description": "CLI tool and library for using comments as content templates in Markdown files, with helpful presets for readmes.",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git@github.com:kitschpatrol/mdat.git",
@@ -42,28 +42,40 @@
42
42
  "cli"
43
43
  ],
44
44
  "dependencies": {
45
+ "@clack/prompts": "^0.7.0",
46
+ "@kitschpatrol/tldraw-cli": "^4.0.0",
45
47
  "@types/mdast": "^4.0.3",
46
48
  "@types/unist": "^3.0.2",
47
49
  "chalk": "^5.3.0",
50
+ "chevrotain": "^11.0.3",
48
51
  "cosmiconfig": "^9.0.0",
52
+ "execa": "^8.0.1",
53
+ "find-up": "^7.0.0",
54
+ "globby": "^14.0.0",
55
+ "is-executable": "^2.0.1",
56
+ "mdast-util-toc": "^7.0.0",
57
+ "nanoid": "^5.0.5",
58
+ "package-up": "^5.0.0",
49
59
  "path-type": "^5.0.0",
60
+ "pkg-dir": "^8.0.0",
50
61
  "plur": "^5.1.0",
51
62
  "pretty-ms": "^9.0.0",
63
+ "read-pkg": "^9.0.1",
52
64
  "remark": "^15.0.1",
53
65
  "remark-gfm": "^4.0.0",
54
66
  "to-vfile": "^8.0.0",
55
67
  "type-fest": "^4.10.2",
56
68
  "untildify": "^5.0.0",
57
69
  "vfile": "^6.0.1",
70
+ "which": "^4.0.0",
58
71
  "yargs": "^17.7.2",
59
72
  "zod": "^3.22.4",
60
- "remark-mdat": "0.2.0"
73
+ "remark-mdat": "0.3.0"
61
74
  },
62
75
  "devDependencies": {
63
- "@types/node": "^20.11.16",
76
+ "@types/node": "^20.11.17",
77
+ "@types/which": "^3.0.3",
64
78
  "@types/yargs": "^17.0.32",
65
- "execa": "^8.0.1",
66
- "nanoid": "^5.0.5",
67
79
  "tsup": "^8.0.1",
68
80
  "typescript": "^5.3.3",
69
81
  "vitest": "^1.2.2"
@@ -74,8 +86,8 @@
74
86
  "scripts": {
75
87
  "build": "tsup && tsc -p tsconfig.build.json",
76
88
  "dev": "pnpm run test",
77
- "mdat": "../mdat-readme/bin/cli.js --config ../../mdat.config.ts",
89
+ "mdat": "./bin/cli.js readme --config ../../mdat.config.ts",
78
90
  "pretest": "pnpm run build",
79
- "test": "vitest"
91
+ "test": "vitest -no-file-parallelism"
80
92
  }
81
93
  }