mdat 1.3.3 → 1.3.5
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/bin/cli.js +278 -0
- package/dist/lib/index.d.ts +156 -0
- package/dist/lib/index.js +7 -0
- package/license.txt +1 -1
- package/package.json +46 -34
- package/readme.md +17 -14
- package/bin/cli.js +0 -29421
- package/dist/api.d.ts +0 -31
- package/dist/config.d.ts +0 -74
- package/dist/index.d.ts +0 -5
- package/dist/index.js +0 -24796
- package/dist/mdat-json-loader.d.ts +0 -7
- package/dist/processors.d.ts +0 -12
- package/dist/readme/api.d.ts +0 -46
- package/dist/readme/config.d.ts +0 -14
- package/dist/readme/init.d.ts +0 -18
- package/dist/readme/rules/badges.d.ts +0 -7
- package/dist/readme/rules/banner.d.ts +0 -7
- package/dist/readme/rules/code.d.ts +0 -6
- package/dist/readme/rules/contributing.d.ts +0 -7
- package/dist/readme/rules/description.d.ts +0 -10
- package/dist/readme/rules/footer.d.ts +0 -10
- package/dist/readme/rules/header.d.ts +0 -11
- package/dist/readme/rules/index.d.ts +0 -66
- package/dist/readme/rules/license.d.ts +0 -7
- package/dist/readme/rules/short-description.d.ts +0 -12
- package/dist/readme/rules/size-table.d.ts +0 -6
- package/dist/readme/rules/size.d.ts +0 -6
- package/dist/readme/rules/table-of-contents.d.ts +0 -9
- package/dist/readme/rules/title.d.ts +0 -8
- package/dist/readme/rules/toc.d.ts +0 -11
- package/dist/readme/rules/utilities/size/size-report.d.ts +0 -19
- package/dist/readme/templates/index.d.ts +0 -27
- package/dist/readme/utilities.d.ts +0 -15
- package/dist/utilities.d.ts +0 -10
package/dist/bin/cli.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import e from"picocolors";import t from"pretty-ms";import{deepMergeDefined as n,getMdatReports as r,getSoleRule as i,log as a,mdatCheck as o,mdatClean as s,mdatExpand as c,mdatSplit as l,optionsSchema as u,reporterMdat as d,rulesSchema as f}from"remark-mdat";import{read as p,write as m}from"to-vfile";import ee from"yargs";import{hideBin as h}from"yargs/helpers";import{cosmiconfig as g,defaultLoaders as te}from"cosmiconfig";import{TypeScriptLoader as ne}from"cosmiconfig-typescript-loader";import _ from"node:fs/promises";import v from"node:path";import re from"plur";import{readPackage as ie}from"read-pkg";import{z as y}from"zod";import{packageUp as ae}from"package-up";import{isFile as oe,isFileSync as b}from"path-type";import{Configuration as se}from"unified-engine";import ce from"untildify";import{remark as x}from"remark";import S from"remark-gfm";import"vfile";import{globby as le}from"globby";import{promisify as ue}from"node:util";import{brotliCompress as de,gzip as fe}from"node:zlib";import pe from"pretty-bytes";import{toc as me}from"mdast-util-toc";import{findUp as he}from"find-up";import{packageDirectory as ge}from"package-directory";import{confirm as _e,group as ve,intro as ye,note as be,outro as xe,select as C}from"@clack/prompts";var Se=`1.3.5`;function Ce(e,t){let n=te[`.json`];return we(n(e,t))}function we(e,t=``,n={}){for(let[r,i]of Object.entries(e)){let e=t?`${t}.${r}`:r;typeof i==`object`&&i&&!Array.isArray(i)?we(i,e,n):i===null?n[e]=`null`:n[e]=i.toString()}return n}function Te(e,t){let n=t===0?1:Math.floor(Math.log10(Math.abs(t))+1);return e.toString().padStart(n,`0`)}async function Ee(e,t,n,r){let i=[];for(let[a,o]of e.entries()){let s=await De(o,t,n,r,n&&e.length>1?`-${Te(a+1,e.length)}`:``);i.push(s)}return i}async function De(e,t,n,r,i=``){let a=w(e),o=t?w(t):void 0;if(!b(a))throw Error(`Input file not found: "${a}"`);if(o){if(b(o))throw Error(`Output path must be a directory, received a file path: "${o}"`);await _.mkdir(o,{recursive:!0})}return{input:a,name:`${n?v.basename(n,v.extname(n)):v.basename(a,v.extname(a))}${i}${`.${r??(n&&v.extname(n)!==``?v.extname(n):v.extname(e)===``?``:v.extname(e))}`}`,output:o??v.dirname(a)}}function w(e){return ce(e)}async function T(){return ae()}function E(e){return e==null?[]:Array.isArray(e)?e:[e]}async function Oe(){let e=new se({cwd:process.cwd(),detectConfig:!0,packageField:`remarkConfig`,rcName:`.remarkrc`}),t=await new Promise(t=>{e.load(``,(e,n)=>{if(e){a.error(String(e)),t(void 0);return}t(n)})});if(t){let{filePath:e}=t;return e===void 0?a.info(`No ambient Remark configuration file found`):a.info(`Found and loaded ambient Remark configuration from "${e}"`),t}return a.info(`No ambient Remark configuration found`),{filePath:void 0,plugins:[],settings:{}}}const D=u.merge(y.object({assetsPath:y.string().optional(),packageFile:y.string().optional()})).describe(`Config Extension`);async function O(t){let{additionalConfig:r,additionalRules:i,readmeDefaults:o,searchFrom:s}=t??{};A=void 0,M=void 0;let c={addMetaComment:!1,assetsPath:`./assets`,closingPrefix:`/`,keywordPrefix:``,metaCommentIdentifier:`+`,packageFile:await T(),rules:{mdat:`Powered by the Markdown Autophagic Template system: [mdat](https://github.com/kitschpatrol/mdat).`}};o&&(c=n(c,o));let l=g(`mdat`,{loaders:{".ts":ne()}}),u=await l.search(s);if(u){let{config:e,filepath:t}=u,r=e;if(a.info(`Using config from "${t}"`),t.endsWith(`package.json`)&&typeof e==`string`){a.info(`Detected shared config string: "${e}"`);let{default:t}=await import(e);r=t}let i=k(r,D);i&&(c=n(c,i))}if(r!==void 0){let e=Array.isArray(r)?r:[r];for(let t of e){let e;if(typeof t==`string`){let n=await l.load(t);if(n==null)continue;let{config:r,filepath:i}=n;a.info(`Loaded additional config from "${i}"`),e=r}else e=t;if(e===void 0)continue;a.info(`Merging configuration object`);let r=k(e,D);r!==void 0&&(c=n(c,r))}}if(i!==void 0){let e=Array.isArray(i)?i:[i],t=g(`mdat`,{loaders:{".json":Ce,".ts":ne()}});for(let r of e){let e;if(typeof r==`string`){let n;if(n=v.basename(r).endsWith(`package.json`)?{config:Ce(r,await _.readFile(r,`utf8`)),filepath:r}:await t.load(r),n==null)continue;let{config:i,filepath:o}=n;a.info(`Loaded additional config from "${o}"`),e=i}else e=r;if(e===void 0)continue;a.info(`Merging rules into configuration object`);let i=ke(e,f);i!==void 0&&(c=n(c,i))}}if(c.rules){let t=Object.keys(c.rules).toSorted().map(t=>`"${e.green(e.bold(t))}"`);a.info(`Loaded ${e.bold(t.length)} mdat comment expansion ${re(`rule`,t.length)}:`);for(let e of t)a.info(`\t${e}`)}else a.error(`No rules loaded from additional configurations or rules, using default.`);return A=c,c}function ke(e,t){if(t.safeParse(e).success)return{rules:e};a.error(`Rules object has the wrong shape. Ignoring and using default configuration:\n${JSON.stringify(e,void 0,2)}`)}function k(e,t){if(t.safeParse(e).success)return e;a.error(`Config object has the wrong shape. Ignoring and using default configuration:\n${JSON.stringify(e,void 0,2)}`)}let A;async function j(){return A===void 0&&(a.warn(`getConfig(): config was undefined`),A??=await O()),A}let M;async function N(){let{packageFile:e}=await j();if(e===void 0)throw Error(`No packageFile found or set in config`);if(M??=await ie({cwd:v.dirname(e)}),M===void 0)throw Error(`No package.json found`);return M}async function P(e,t,n,r,i,a,o){let s=await t({additionalConfig:a,additionalRules:o}),c=await Oe(),l=await Ee(E(e),i,r,`md`),u=[],d=n(s,c);for(let{input:e,name:t,output:n}of l){let r=await p(e),i=await d.process(r);i.dirname=n,i.basename=t,u.push(i)}return u}function Ae(e,t){return x().use({settings:{bullet:`-`,emphasis:`_`}}).use(S).use(t).use(()=>async function(t,n){l(t,n),s(t,n,e),await c(t,n,e)})}function je(e,t){return x().use({settings:{bullet:`-`,emphasis:`_`}}).use(S).use(t).use(()=>function(t,n){l(t,n),s(t,n,e)})}function Me(e,t){return x().use({settings:{bullet:`-`,emphasis:`_`}}).use(S).use(t).use(()=>async function(t,n){await o(t,n,{...e,paranoid:!1})})}async function Ne(e,t,n,r,i){return P(e,O,Ae,t,n,r,i)}async function Pe(e,t,n,r,i){return P(e,O,Me,t,n,r,i)}async function Fe(e,t,n,r,i){return P(e,O,je,t,n,r,i)}var Ie={badges:{async content(e){let t=y.object({custom:y.record(y.object({image:y.string(),link:y.string()})).optional(),npm:y.array(y.string()).optional()}).optional().parse(e),n=await N(),{name:r}=n,i=[];if(t?.npm===void 0)(!n.name.startsWith(`@`)||n.publishConfig?.access===`public`)&&i.push(`[](https://npmjs.com/package/${r})`);else for(let e of t.npm)i.push(`[](https://npmjs.com/package/${e})`);let{license:a}=n;if(a!==void 0&&i.push(`[}-yellow.svg)](https://opensource.org/licenses/${a})`),t?.custom!==void 0)for(let[e,{image:n,link:r}]of Object.entries(t.custom))i.push(`[](${r})`);return i.join(`
|
|
3
|
+
`)},order:3}},Le={banner:{async content(e){let t=y.object({alt:y.string().optional(),src:y.string().optional()}).optional().parse(e),{assetsPath:n,packageFile:r}=await j();if(r===void 0)throw Error(`No package.json found`);let i=t?.src??await Re(n)??await Re();if(i===void 0)throw Error(`Banner image not found at any typical location, consider adding something at ./assets/banner.webp`);if(!ze(i)&&!await oe(i))throw Error(`Banner image not found at "${i}"`);let a=t?.alt;if(a===void 0){let e=(await ie({cwd:v.dirname(r)})).name;if(e===void 0)throw Error(`Banner image alt text not available`);a=`${e} banner`}return``},order:2}};async function Re(e){let{packageFile:t}=await j();if(t===void 0)throw Error(`No package.json found`);let n=v.dirname(t),r=await le((e===void 0?[`.`,`assets`,`media`,`readme-assets`,`readme-media`,`readme`,`images`,`.github/assets`]:[e]).map(e=>v.join(n,e)),{deep:1,expandDirectories:{extensions:[`png`,`gif`,`jpg`,`jpeg`,`svg`,`webp`],files:[`banner`,`cover`,`demo`,`header`,`hero`,`image`,`logo`,`overview`,`readme`,`screenshot`,`screenshots`,`splash`]}});if(r.length>0)return v.relative(process.cwd(),r[0])}function ze(e,t=!0){if(typeof e!=`string`)throw TypeError(`Expected a string`);if(e=e.trim(),e.includes(` `))return!1;try{return new URL(e),!0}catch{return t?ze(`https://${e}`,!1):!1}}var Be={code:{async content(e){let t=y.object({file:y.string(),language:y.string().optional()}).parse(e);return`\`\`\`${(v.extname(t.file)??``).replace(/^\./,``)}\n${await _.readFile(v.join(process.cwd(),t.file),`utf8`)}\n\`\`\``}}},Ve={contributing:{async content(){let e=(await N()).bugs?.url;if(e===void 0)throw Error(`Could not find "bugs.url" entry in package.json`);return`## Contributing\n[Issues](${e}) and pull requests are welcome.`},order:15}},He={description:{async content(){let e=await N();if(e.description===void 0)throw Error(`Could not find "description" entry in package.json`);return`**${e.description}**`},order:4}},Ue={license:{async content(){let{author:e,license:t}=await N();if(e?.name===void 0)throw Error(`Could not find "author.name" entry in package.json`);if(t===void 0)throw Error(`Could not find "license" entry in package.json`);return`## License\n[${t}](license.txt) © ${e.name}`},order:16}},We={footer:{content:[i(Ve),i(Ue)],order:17}},F={"short-description":i(He)},Ge={title:{applicationOrder:2,async content(e){let{postfix:t,prefix:n,titleCase:r}=y.object({postfix:y.string().optional().default(``),prefix:y.string().optional().default(``),titleCase:y.boolean().optional().default(!1)}).parse(e??{}),{name:i}=await N();return`# ${n}${r?Ke(i):i}${t}`},order:1}};function Ke(e){return e.split(/[ _-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}var qe={header:{applicationOrder:2,content:[i(Ge),i(Le),i(Ie),i(F)],order:1}};const Je=ue(de),Ye=ue(fe);function I(e,t){let n=t===0?0:(t-e)/t*100;return{bytes:e,bytesPretty:pe(e,{maximumFractionDigits:1}),percent:n,percentPretty:`${Math.round(n)}%`}}async function Xe(e){try{let t=await _.readFile(e),n=t.length,[r,i]=await Promise.all([Je(t),Ye(t)]);return{brotli:I(r.length,n),gzip:I(i.length,n),original:I(n,n)}}catch(e){throw Error(`Failed to analyze file: ${e instanceof Error?e.message:`Unknown error`}`)}}const Ze=y.object({compression:y.enum([`none`,`brotli`,`gzip`]).optional().default(`none`),file:y.string()});function Qe(e,t){switch(t){case`brotli`:return e.brotli.bytesPretty;case`gzip`:return e.gzip.bytesPretty;case`none`:return e.original.bytesPretty}}var $e={size:{async content(e){let t=Ze.parse(e);return Qe(await Xe(v.join(process.cwd(),t.file)),t.compression)}}};const et=y.union([y.string(),y.array(y.string())]).transform(e=>Array.isArray(e)?e:[e]),tt=y.union([y.object({brotli:y.boolean().optional().default(!0),file:et,gzip:y.boolean().optional().default(!0),original:y.boolean().optional().default(!0),showPercentage:y.boolean().optional().default(!1)}),y.object({brotli:y.boolean().optional().default(!0),files:et,gzip:y.boolean().optional().default(!0),original:y.boolean().optional().default(!0),showPercentage:y.boolean().optional().default(!1)})]).transform(e=>{if(`file`in e){let{file:t,...n}=e;return{files:t,...n}}return e});function nt(e,t){let n=[`File`];t.original&&n.push(`Original`),t.gzip&&n.push(`Gzip`),t.brotli&&n.push(`Brotli`);let r=n.map(()=>`---`),i=e.map(([e,n])=>{let r=[v.basename(e)];return t.original&&r.push(n.original.bytesPretty),t.gzip&&r.push(t.showPercentage?`${n.gzip.bytesPretty} (${n.gzip.percentPretty})`:n.gzip.bytesPretty),t.brotli&&r.push(t.showPercentage?`${n.brotli.bytesPretty} (${n.brotli.percentPretty})`:n.brotli.bytesPretty),r});return[`| ${n.join(` | `)} |`,`| ${r.join(` | `)} |`,...i.map(e=>`| ${e.join(` | `)} |`)].join(`
|
|
4
|
+
`)}var rt={"size-table":{async content(e){let t=tt.parse(e);return nt(await Promise.all(t.files.map(async e=>[e,await Xe(v.join(process.cwd(),e))])),{brotli:t.brotli,gzip:t.gzip,original:t.original,showPercentage:t.showPercentage})}}},it={"table-of-contents":{applicationOrder:1,async content(e,t){let n=me(t,{heading:null,maxDepth:y.object({depth:y.union([y.literal(1),y.literal(2),y.literal(3),y.literal(4),y.literal(5),y.literal(6)]).optional()}).optional().parse(e)?.depth??3,tight:!0});if(n.map===void 0)throw Error(`Could not generate table of contents`);let r={children:n.map.children,type:`root`};return[`## Table of contents`,x().use(S).stringify(r).replaceAll(`
|
|
5
|
+
|
|
6
|
+
`,`
|
|
7
|
+
`)].join(`
|
|
8
|
+
`)},order:6}},at={toc:i(it)},ot={...Ie,...Le,...Be,...Ve,...He,...We,...qe,...Ue,...F,...$e,...rt,...it,...Ge,...at};async function L(e){let t={addMetaComment:!0,rules:ot},{additionalConfig:n=[],readmeDefaults:r=t,...i}=e??{},a=await O({additionalConfig:Array.isArray(n)?n:[n],readmeDefaults:r,...i});if(a.packageFile===void 0)throw Error("Package file path is required in `mdat readme` config");return a}async function st(){a.info(`Searching for package directory...`);let e=await he(`readme.md`,{stopAt:await ge()??process.cwd(),type:`file`});if(e!==void 0)return a.info(`Found closest readme at "${e}"`),e}async function R(){let e=await st();if(e===void 0)throw Error(`No readme found`);return e}async function ct(e,t,n,r,i){return e??=await R(),P(e,L,Ae,t,n,r,i)}async function lt(e,t,n,r,i){return e??=await R(),P(e,L,Me,t,n,r,i)}async function ut(e,t,n,r,i){return e??=await R(),P(e,L,je,t,n,r,i)}var dt=`<!-- header -->
|
|
9
|
+
|
|
10
|
+
<!-- table-of-contents -->
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
## Getting started
|
|
15
|
+
|
|
16
|
+
### Dependencies
|
|
17
|
+
|
|
18
|
+
### Installation
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Library
|
|
23
|
+
|
|
24
|
+
#### API
|
|
25
|
+
|
|
26
|
+
#### Examples
|
|
27
|
+
|
|
28
|
+
### CLI
|
|
29
|
+
|
|
30
|
+
#### Commands
|
|
31
|
+
|
|
32
|
+
#### Examples
|
|
33
|
+
|
|
34
|
+
## Background
|
|
35
|
+
|
|
36
|
+
### Motivation
|
|
37
|
+
|
|
38
|
+
### Implementation notes
|
|
39
|
+
|
|
40
|
+
### Similar projects
|
|
41
|
+
|
|
42
|
+
## The future
|
|
43
|
+
|
|
44
|
+
## Maintainers
|
|
45
|
+
|
|
46
|
+
_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._
|
|
47
|
+
|
|
48
|
+
## Acknowledgments
|
|
49
|
+
|
|
50
|
+
_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._
|
|
51
|
+
|
|
52
|
+
<!-- footer -->
|
|
53
|
+
`,ft=`<!-- title -->
|
|
54
|
+
|
|
55
|
+
<!-- banner -->
|
|
56
|
+
|
|
57
|
+
<!-- badges -->
|
|
58
|
+
|
|
59
|
+
<!-- short-description -->
|
|
60
|
+
|
|
61
|
+
<!-- table-of-contents -->
|
|
62
|
+
|
|
63
|
+
## Overview
|
|
64
|
+
|
|
65
|
+
## Getting started
|
|
66
|
+
|
|
67
|
+
### Dependencies
|
|
68
|
+
|
|
69
|
+
### Installation
|
|
70
|
+
|
|
71
|
+
## Usage
|
|
72
|
+
|
|
73
|
+
### Library
|
|
74
|
+
|
|
75
|
+
#### API
|
|
76
|
+
|
|
77
|
+
#### Examples
|
|
78
|
+
|
|
79
|
+
### CLI
|
|
80
|
+
|
|
81
|
+
#### Commands
|
|
82
|
+
|
|
83
|
+
#### Examples
|
|
84
|
+
|
|
85
|
+
## Background
|
|
86
|
+
|
|
87
|
+
### Motivation
|
|
88
|
+
|
|
89
|
+
### Implementation notes
|
|
90
|
+
|
|
91
|
+
### Similar projects
|
|
92
|
+
|
|
93
|
+
## The future
|
|
94
|
+
|
|
95
|
+
## Maintainers
|
|
96
|
+
|
|
97
|
+
_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._
|
|
98
|
+
|
|
99
|
+
## Acknowledgments
|
|
100
|
+
|
|
101
|
+
_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._
|
|
102
|
+
|
|
103
|
+
<!-- contributing -->
|
|
104
|
+
|
|
105
|
+
<!-- license -->
|
|
106
|
+
`,pt=`<!-- header -->
|
|
107
|
+
|
|
108
|
+
## Install
|
|
109
|
+
|
|
110
|
+
\`\`\`sh
|
|
111
|
+
# Code block illustrating how to install.
|
|
112
|
+
\`\`\`
|
|
113
|
+
|
|
114
|
+
## Usage
|
|
115
|
+
|
|
116
|
+
\`\`\`ts
|
|
117
|
+
// Code block illustrating common usage.
|
|
118
|
+
// Consider using the <!-- code { src: "path/to/example.ts" } --> comment as well.
|
|
119
|
+
\`\`\`
|
|
120
|
+
|
|
121
|
+
<!-- footer -->
|
|
122
|
+
`,mt=`<!-- title -->
|
|
123
|
+
|
|
124
|
+
<!-- short-description -->
|
|
125
|
+
|
|
126
|
+
<!-- table-of-contents -->
|
|
127
|
+
|
|
128
|
+
## Install
|
|
129
|
+
|
|
130
|
+
\`\`\`sh
|
|
131
|
+
# Code block illustrating how to install.
|
|
132
|
+
\`\`\`
|
|
133
|
+
|
|
134
|
+
## Usage
|
|
135
|
+
|
|
136
|
+
\`\`\`ts
|
|
137
|
+
// Code block illustrating common usage.
|
|
138
|
+
// Consider using the <!-- code { src: "path/to/example.ts" } --> comment as well.
|
|
139
|
+
\`\`\`
|
|
140
|
+
|
|
141
|
+
<!-- contributing -->
|
|
142
|
+
|
|
143
|
+
<!-- license -->
|
|
144
|
+
`,ht=`<!-- header -->
|
|
145
|
+
|
|
146
|
+
_Long description goes here._
|
|
147
|
+
|
|
148
|
+
_No heading. Cover the main reasons for building the repository. This should describe your module in broad terms, generally in just a few paragraphs; more detail of the module's routines or methods, lengthy code examples, or other in-depth material should be given in subsequent sections._
|
|
149
|
+
|
|
150
|
+
<!-- table-of-contents -->
|
|
151
|
+
|
|
152
|
+
## Background
|
|
153
|
+
|
|
154
|
+
_Cover motivation. Cover abstract dependencies. Cover intellectual provenance: A See Also section is also fitting._
|
|
155
|
+
|
|
156
|
+
### See also
|
|
157
|
+
|
|
158
|
+
## Install
|
|
159
|
+
|
|
160
|
+
\`\`\`sh
|
|
161
|
+
# Code block illustrating how to install.
|
|
162
|
+
\`\`\`
|
|
163
|
+
|
|
164
|
+
### Dependencies
|
|
165
|
+
|
|
166
|
+
_Required if there are unusual dependencies or dependencies that must be manually installed._
|
|
167
|
+
|
|
168
|
+
## Usage
|
|
169
|
+
|
|
170
|
+
\`\`\`ts
|
|
171
|
+
// Code block illustrating common usage.
|
|
172
|
+
// Consider using the <!-- code { src: "path/to/example.ts" } --> comment as well.
|
|
173
|
+
\`\`\`
|
|
174
|
+
|
|
175
|
+
\`\`\`ts
|
|
176
|
+
// If importable, code block indicating both import functionality and usage.
|
|
177
|
+
\`\`\`
|
|
178
|
+
|
|
179
|
+
### CLI
|
|
180
|
+
|
|
181
|
+
\`\`\`ts
|
|
182
|
+
// If CLI compatible, code block indicating common usage.
|
|
183
|
+
\`\`\`
|
|
184
|
+
|
|
185
|
+
## _Extra Sections (Rename)_
|
|
186
|
+
|
|
187
|
+
## Security
|
|
188
|
+
|
|
189
|
+
## API
|
|
190
|
+
|
|
191
|
+
_Describe exported functions and objects._
|
|
192
|
+
|
|
193
|
+
- _Describe signatures, return types, callbacks, and events._
|
|
194
|
+
- _Cover types covered where not obvious._
|
|
195
|
+
- _Describe caveats._
|
|
196
|
+
- _If using an external API generator (like go-doc, js-doc, or so on), point to an external API.md file. This can be the only item in the section, if present._
|
|
197
|
+
|
|
198
|
+
## Maintainers
|
|
199
|
+
|
|
200
|
+
_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._
|
|
201
|
+
|
|
202
|
+
## Thanks
|
|
203
|
+
|
|
204
|
+
_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._
|
|
205
|
+
|
|
206
|
+
<!-- footer -->
|
|
207
|
+
`,gt=`<!-- title -->
|
|
208
|
+
|
|
209
|
+
<!-- banner -->
|
|
210
|
+
|
|
211
|
+
<!-- badges -->
|
|
212
|
+
|
|
213
|
+
<!-- short-description -->
|
|
214
|
+
|
|
215
|
+
_Long description goes here._
|
|
216
|
+
|
|
217
|
+
_No heading. Cover the main reasons for building the repository. This should describe your module in broad terms, generally in just a few paragraphs; more detail of the module's routines or methods, lengthy code examples, or other in-depth material should be given in subsequent sections._
|
|
218
|
+
|
|
219
|
+
<!-- table-of-contents -->
|
|
220
|
+
|
|
221
|
+
## Background
|
|
222
|
+
|
|
223
|
+
_Cover motivation. Cover abstract dependencies. Cover intellectual provenance: A See Also section is also fitting._
|
|
224
|
+
|
|
225
|
+
### See also
|
|
226
|
+
|
|
227
|
+
## Install
|
|
228
|
+
|
|
229
|
+
\`\`\`sh
|
|
230
|
+
# Code block illustrating how to install.
|
|
231
|
+
\`\`\`
|
|
232
|
+
|
|
233
|
+
### Dependencies
|
|
234
|
+
|
|
235
|
+
_Required if there are unusual dependencies or dependencies that must be manually installed._
|
|
236
|
+
|
|
237
|
+
## Usage
|
|
238
|
+
|
|
239
|
+
\`\`\`ts
|
|
240
|
+
// Code block illustrating common usage.
|
|
241
|
+
// Consider using the <!-- code { src: "path/to/example.ts" } --> comment as well.
|
|
242
|
+
\`\`\`
|
|
243
|
+
|
|
244
|
+
\`\`\`ts
|
|
245
|
+
// If importable, code block indicating both import functionality and usage.
|
|
246
|
+
\`\`\`
|
|
247
|
+
|
|
248
|
+
### CLI
|
|
249
|
+
|
|
250
|
+
\`\`\`ts
|
|
251
|
+
// If CLI compatible, code block indicating common usage.
|
|
252
|
+
\`\`\`
|
|
253
|
+
|
|
254
|
+
## _Extra Sections (Rename)_
|
|
255
|
+
|
|
256
|
+
## Security
|
|
257
|
+
|
|
258
|
+
## API
|
|
259
|
+
|
|
260
|
+
_Describe exported functions and objects._
|
|
261
|
+
|
|
262
|
+
- _Describe signatures, return types, callbacks, and events._
|
|
263
|
+
- _Cover types covered where not obvious._
|
|
264
|
+
- _Describe caveats._
|
|
265
|
+
- _If using an external API generator (like go-doc, js-doc, or so on), point to an external API.md file. This can be the only item in the section, if present._
|
|
266
|
+
|
|
267
|
+
## Maintainers
|
|
268
|
+
|
|
269
|
+
_List maintainer(s) for a repository, along with one way of contacting them (e.g. GitHub link or email)._
|
|
270
|
+
|
|
271
|
+
## Thanks
|
|
272
|
+
|
|
273
|
+
_State anyone or anything that significantly helped with the development of your project. State public contact hyper-links if applicable._
|
|
274
|
+
|
|
275
|
+
<!-- contributing -->
|
|
276
|
+
|
|
277
|
+
<!-- license -->
|
|
278
|
+
`,z={"MDAT Readme":{content:{compound:dt,explicit:ft},description:`The house style. An expansive starting point. Prune to your context and taste.`,exampleLink:`https://github.com/kitschpatrol/mdat/blob/main/readme.md`},"Standard Readme Basic":{content:{compound:pt,explicit:mt},description:`Includes only the "required" sections from the Standard Readme specification.`,exampleLink:`https://github.com/RichardLitt/standard-readme/blob/main/example-readmes/minimal-readme.md`},"Standard Readme Full":{content:{compound:ht,explicit:gt},description:`Includes all sections from the Standard Readme specification.`,exampleLink:`https://github.com/RichardLitt/standard-readme/blob/main/example-readmes/maximal-readme.md`}};async function _t(){let e=await st(),t=await T();return{packageDirectory:t===void 0?void 0:v.dirname(v.resolve(t)),readmePath:e}}async function vt(){let{packageDirectory:t,readmePath:n}=await _t(),r=v.resolve(process.cwd());ye(`Running ${e.bold(`mdat readme init`)} interactively`);let i=await yt(await ve({overwrite:async()=>n===void 0||await _e({message:`Found an existing readme at "${e.blue(n)}". Do you want to overwrite it?`,active:`Overwrite`,inactive:`Exit`})?!0:(()=>{throw Error("`mdat readme init` was cancelled to avoid an overwrite - no changes were made")})(),output:async()=>t!==void 0&&t!==r?C({initialValue:t,message:`There's a root package directory nearby, do you want to create the readme there instead of the current directory?`,options:[{label:`Create in the current package root: "${e.blue(t)}"`,value:t},{label:`Create in current working directory: "${e.blue(r)}"`,value:r}]}):r,template:async()=>C({message:`Which template would you like to use?`,options:xt()}),compound:async()=>C({message:`Do you want to use "compound comments" where possible, which combine several expansions into a single comment block?`,options:[{label:`Yes: Combine things like ${e.green(`<!-- title -->`)} and ${e.green(`<!-- badges -->`)} in a single ${e.green(`<!-- header -->`)} comment.`,value:!0},{label:`No: Use individual MDAT expansion comments for each section.`,value:!1}]}),expand:async()=>t===void 0?!1:_e({initialValue:!0,message:"Do you want to run `mdat readme` now to expand the template with content from your package.json?"})},{onCancel(){throw Error("`mdat readme init` was cancelled - no changes were made")}}));return t===void 0&&be("No package.json was found. Once you've created one, you can run `mdat readme` to expand the template with content from your package.json."),be(`Readme created: "${e.blue(e.bold(i))}"`),xe(`Done!`),i}async function yt(e){let{packageDirectory:t}=await _t(),r=n({compound:!0,output:t??process.cwd(),overwrite:!0,expand:t!==void 0,template:Object.keys(z)[0]},e??{}),i=bt(r.template,r.compound),a=v.join(r.output,`readme.md`);if(!r.overwrite&&await _.access(a).then(()=>!0,()=>!1))throw Error(`Readme already exists at "${a}". Use the overwrite option to replace it.`);if(await _.writeFile(a,i,`utf8`),r.expand){let[e]=await ct(a);await m(e)}return a}function bt(e,t){let n=z[e].content[t?`compound`:`explicit`];if(n===void 0||n===``)throw Error(`No template found for "${e}"`);return n}function xt(){return Object.entries(z).map(([e,t])=>({label:e,hint:t.description,value:e}))}const B={config:{defaultDescription:`Configuration is loaded if found from the usual places, or defaults are used.`,description:`Path(s) to files containing MDAT configuration.`,string:!0,type:`array`}},V={meta:{alias:`m`,coerce(e){return typeof e==`string`?e.toLowerCase()===`false`||e===`0`?!1:e.toLowerCase()===`true`||e===`1`?!0:e:e},description:"Embed an extra comment at the top of the generated Markdown warning editors that certain sections of the document have been generated dynamically. Can be a `boolean` to enable/disable the default message, or a `string` to provide a custom message. Defaults to `false` for `mdat` commands and `true` for `mdat readme` commands."}},H={name:{alias:`n`,defaultDescription:`Same name as input file. Overwrites the input file.`,description:`Output file name.`,type:`string`}},U={output:{alias:`o`,defaultDescription:`Same directory as input file.`,description:`Output file directory.`,type:`string`}},W={prefix:{description:`Require a string prefix before all comments to be considered for expansion. Useful if you have a bunch of non-MDAT comments in your Markdown file, or if you're willing to trade some verbosity for safety.`,type:`string`}},G={print:{description:"Print the expanded Markdown to stdout instead of saving to a file. Ignores `--output` and `--name` options.",type:`boolean`}},K={rules:{alias:`r`,description:`Path(s) to files containing MDAT comment expansion rules.`,string:!0,type:`array`}},q={verbose:{describe:`Enable verbose logging. All verbose logs are prefixed with their log level and are printed to stderr for ease of redirection.`,type:`boolean`}},J=[`files`,{array:!0,demandOption:!0,describe:`Markdown file(s) with MDAT placeholder comments.`,type:`string`}],St={package:{defaultDescription:`The closest package.json file is used by default.`,description:`Path to the package.json file to use to populate the readme.`,string:!0}},Ct={assets:{defaultDescription:`./assets`,description:`Path to find and save readme-related assets.`,string:!0}},wt={interactive:{alias:`i`,default:!0,description:"Run the guided interactive `init` process. Set explicitly to `false` to use default values and skip the prompt.",type:`boolean`}},Tt={overwrite:{default:!1,defaultDescription:"`false`, if an existing readme is found, don't touch it.",description:`Replace an existing readme file if one is found.`,type:`boolean`}},Et={expand:{alias:`e`,default:!0,description:"Automatically run `mdat readme` immediately after creating the readme template.",type:`boolean`}},Dt={template:{alias:`t`,choices:Object.keys(z),default:Object.keys(z)[0],description:`Specify a template to use for the new readme.`,type:`string`}},Ot={compound:{alias:`c`,default:!0,description:"Use compound comment version of the template to replace several individual comment placeholders where possible. This combines things like `<!-- title -->`, `<!-- badges -->`, etc. in a single `<!-- header -->` comment. It's less clutter when you're editing, but it's also less explicit. The final readme.md output is identical.",type:`boolean`}},Y=[`files`,{array:!0,demandOption:!1,describe:`Readme file(s) with MDAT placeholder comments. If not provided, the closest readme.md file is used.`,type:`string`}],X=performance.now(),kt=ee(h(process.argv));try{await kt.scriptName(`mdat`).usage(`$0 [command]`,`Work with MDAT placeholder comments in any Markdown file.`).command([`$0 <files..> [options]`,`expand <files..> [options]`],`Expand MDAT placeholder comments.`,e=>e.positional(...J).option(B).option(K).option(U).option(H).option(V).option(W).option(G).option(q),async({config:e,files:n,meta:r,name:i,output:o,prefix:s,print:c,rules:l,verbose:u})=>{a.verbose=u??!1,Z({name:i,output:o,print:c});let f=await Ne(n,i,o,Q(e,{addMetaComment:r,keywordPrefix:s}),l);for(let e of f)c?process.stdout.write(e.toString()):await m(e);d(f),a.info(`Expanded comments in ${t(performance.now()-X)}.`),process.exitCode=$(f)}).command(`check <files..> [options]`,`Validate a Markdown file containing MDAT placeholder comments.`,e=>e.positional(...J).option(B).option(K).option(V).option(W).option(q),async({config:e,files:n,meta:r,prefix:i,rules:o,verbose:s})=>{a.verbose=s??!1;let c=await Pe(n,void 0,void 0,Q(e,{addMetaComment:r,keywordPrefix:i}),o);d(c),a.info(`Checked comments in ${t(performance.now()-X)}.`),process.exitCode=$(c)}).command(`collapse <files..> [options]`,`Collapse MDAT placeholder comments.`,e=>e.positional(...J).option(B).option(U).option(H).option(W).option(G).option(q),async({config:e,files:n,name:r,output:i,prefix:o,print:s,verbose:c})=>{a.verbose=c??!1,Z({name:r,output:i,print:s});let l=await Fe(n,r,i,Q(e,{keywordPrefix:o}));for(let e of l)s?process.stdout.write(e.toString()):await m(e);d(l),a.info(`Cleaned comments in ${t(performance.now()-X)}.`),process.exitCode=$(l)}).command(`readme [command]`,`Work with MDAT comments in your readme.md.`,n=>n.command([`$0 [files..] [options]`,`expand [files..] [options]`],`Expand MDAT comment placeholders in your readme.md using a collection of helpful built-in expansion rules.`,e=>e.positional(...Y).option(B).option(K).option(U).option(H).option(St).option(Ct).option(W).option(V).option(G).option(q),async({assets:n,config:r,files:i,meta:o,name:s,output:c,package:l,prefix:u,print:f,rules:p,verbose:ee})=>{a.verbose=ee??!1,Z({name:s,output:c,print:f});let h=await ct(i,s,c,Q(r,{addMetaComment:o,assetsPath:n,keywordPrefix:u,packageFile:l}),p);for(let e of h)f?process.stdout.write(e.toString()):await m(e);d(h);let{packageFile:g}=await j();g!==void 0&&a.info(`Pulled package metadata from: ${e.blue(e.bold(g))}`),a.info(`Expanded readme(s) in ${t(performance.now()-X)}.`),process.exitCode=$(h)}).command(`check [files..] [options]`,`Validate MDAT placeholder comments in your readme.md.`,e=>e.positional(...Y).option(B).option(K).option(St).option(Ct).option(W).option(V).option(q),async({assets:n,config:r,files:i,meta:o,package:s,prefix:c,rules:l,verbose:u})=>{a.verbose=u??!1;let f=await lt(i,void 0,void 0,Q(r,{addMetaComment:o,assetsPath:n,keywordPrefix:c,packageFile:s}),l);d(f);let{packageFile:p}=await j();p!==void 0&&a.info(`Pulled package metadata from: ${e.blue(e.bold(p))}`),a.info(`Checked readme(s) in ${t(performance.now()-X)}.`),process.exitCode=$(f)}).command(`collapse [files..] [options]`,`Collapse MDAT placeholder comments in your readme.md.`,e=>e.positional(...Y).option(U).option(H).option(G).option(B).option(W).option(q),async({config:e,files:n,name:r,output:i,prefix:o,print:s,verbose:c})=>{a.verbose=c??!1,Z({name:r,output:i,print:s});let l=await ut(n,r,i,Q(e,{keywordPrefix:o}));for(let e of l)s?process.stdout.write(e.toString()):await m(e);d(l),a.info(`Cleaned readme(s) in ${t(performance.now()-X)}.`),process.exitCode=$(l)}).command(`init [options]`,`Interactively create a new readme.md file with sensible default MDAT comment placeholders.`,e=>e.option(wt).option(Tt).option(U).option(Et).option(Dt).option(Ot).option(q),async({compound:n,expand:r,interactive:i,output:o,overwrite:s,template:c,verbose:l})=>{if(a.verbose=l??!1,i)await vt();else{let i=await yt({compound:n,expand:r,output:o,overwrite:s,template:c});a.info(`Created readme at "${e.blue(i)}" in ${t(performance.now()-X)}.`)}process.exitCode=0}),()=>{a.error(`Root MDAT readme command should be unreachable.`)}).help().alias(`h`,`help`).version(Se).alias(`v`,`version`).wrap(process.stdout.isTTY?Math.min(120,kt.terminalWidth()):0).fail(!1).parse()}catch(e){e instanceof Error&&a.error(e.message),process.exitCode=1}function Z(e){e.print&&e.output&&a.warn(`Ignoring --output option because --print is set`),e.print&&e.name&&a.warn(`Ignoring --name option because --print is set`)}function Q(e,t){return[...E(e),t]}function $(e){return r(e).reduce((e,t)=>e+t.errors.length,0)>0?1:0}export{};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import "read-pkg";
|
|
2
|
+
import { Options, Rules } from "remark-mdat";
|
|
3
|
+
import { VFile } from "vfile";
|
|
4
|
+
import { Simplify } from "type-fest";
|
|
5
|
+
|
|
6
|
+
//#region src/lib/config.d.ts
|
|
7
|
+
type Config = Simplify<Options & {
|
|
8
|
+
assetsPath?: string;
|
|
9
|
+
packageFile?: string;
|
|
10
|
+
}>;
|
|
11
|
+
type ConfigLoaded = {
|
|
12
|
+
addMetaComment: boolean | string;
|
|
13
|
+
assetsPath: string;
|
|
14
|
+
closingPrefix: string;
|
|
15
|
+
keywordPrefix: string;
|
|
16
|
+
metaCommentIdentifier: string;
|
|
17
|
+
packageFile: string | undefined;
|
|
18
|
+
rules: Rules;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Generously accept either string paths to .ts, .js, or .json files with
|
|
22
|
+
* `Config` type default exports. Takes a single value, or an array of values which
|
|
23
|
+
* will be merged right to left.
|
|
24
|
+
*/
|
|
25
|
+
type ConfigToLoad = Array<Config | string> | Config | string;
|
|
26
|
+
/**
|
|
27
|
+
* Generously accept either string paths to .ts, .js, or .json files with
|
|
28
|
+
* `Rules` type default exports.
|
|
29
|
+
*/
|
|
30
|
+
type RulesToLoad = Array<Rules | string> | Rules | string;
|
|
31
|
+
/**
|
|
32
|
+
* Load and validate mdat configuration / rule sets
|
|
33
|
+
* Uses cosmiconfig to search in the usual places.
|
|
34
|
+
* Merge precedence: Base Defaults < Readme Defaults < Searched Config < Additional Config Paths
|
|
35
|
+
*
|
|
36
|
+
* Generic to accommodate additional Config options, so set T to your custom config type if needed. You must provide a matching configExtensionSchema as well.
|
|
37
|
+
*/
|
|
38
|
+
declare function loadConfig(options?: {
|
|
39
|
+
/**
|
|
40
|
+
* Additional Config objects to merge.
|
|
41
|
+
*
|
|
42
|
+
* Strings are treated as paths to `ts`, `js`, or `json` files with `Config` type default exports. These will be dynamically loaded by Cosmiconfig.
|
|
43
|
+
* Accepts an individual item, or an array. Objects in the array will be merged right to left.
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
additionalConfig?: ConfigToLoad;
|
|
47
|
+
/**
|
|
48
|
+
* Additional Rules objects to merge.
|
|
49
|
+
*
|
|
50
|
+
* Strings are treated as paths to `ts`, `js`, or `json` files with `Rules` type default exports. These will be dynamically loaded by Cosmiconfig.
|
|
51
|
+
* Accepts an individual item, or an array. Objects in the array will be merged right to left, and take precedence over any rules in previously loaded Config objects as well.
|
|
52
|
+
*/
|
|
53
|
+
additionalRules?: RulesToLoad;
|
|
54
|
+
/**
|
|
55
|
+
* Readme-specific defaults that have higher priority than base defaults but lower than searched config.
|
|
56
|
+
* Used internally by loadConfigReadme.
|
|
57
|
+
*/
|
|
58
|
+
readmeDefaults?: Config; /** Search for config in specific directories, mainly useful for testing. Cosmiconfig default search paths used if unset. */
|
|
59
|
+
searchFrom?: string;
|
|
60
|
+
}): Promise<ConfigLoaded>;
|
|
61
|
+
/**
|
|
62
|
+
* Convenience function for merging configs
|
|
63
|
+
* Performs a deep merge, with the rightmost object taking precedence
|
|
64
|
+
*/
|
|
65
|
+
declare function mergeConfigs(a: Config, b: Config): Config;
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/lib/api.d.ts
|
|
68
|
+
/**
|
|
69
|
+
* Expand MDAT comments in one or more Markdown files
|
|
70
|
+
* Writing is the responsibility of the caller (e.g. via `await write(result)`)
|
|
71
|
+
* @returns an array of VFiles (Even if you only pass a single file path!)
|
|
72
|
+
*/
|
|
73
|
+
declare function expandFiles(files: string | string[], name?: string, output?: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Expand MDAT comments in a Markdown string
|
|
76
|
+
*/
|
|
77
|
+
declare function expandString(markdown: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile>;
|
|
78
|
+
/**
|
|
79
|
+
* Check and validate MDAT comments in one or more Markdown files
|
|
80
|
+
* @returns an array of VFiles (Even if you only pass a single file path!)
|
|
81
|
+
*/
|
|
82
|
+
declare function checkFiles(files: string | string[], name?: string, output?: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile[]>;
|
|
83
|
+
/**
|
|
84
|
+
* Check and validate MDAT comments in a Markdown string
|
|
85
|
+
*/
|
|
86
|
+
declare function checkString(markdown: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile>;
|
|
87
|
+
/**
|
|
88
|
+
* Collapse MDAT comments in one or more Markdown files
|
|
89
|
+
* Writing is the responsibility of the caller (e.g. via `await write(result)`)
|
|
90
|
+
* @returns an array of VFiles (Even if you only pass a single file path!)
|
|
91
|
+
*/
|
|
92
|
+
declare function collapseFiles(files: string | string[], name?: string, output?: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile[]>;
|
|
93
|
+
/**
|
|
94
|
+
* Collapse MDAT comments in a Markdown string
|
|
95
|
+
*/
|
|
96
|
+
declare function collapseString(markdown: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile>;
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/lib/readme/api.d.ts
|
|
99
|
+
/**
|
|
100
|
+
* Expands MDAT readme comments in the closest readme.md file
|
|
101
|
+
* Basically an alias to `expandReadmeFiles()` with certain arguments elided.
|
|
102
|
+
* @see `findReadme()` for more details on the search process.
|
|
103
|
+
*/
|
|
104
|
+
declare function expandReadme(config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile[]>;
|
|
105
|
+
/**
|
|
106
|
+
* Expands MDAT readme comments in one or more Markdown files
|
|
107
|
+
* Searches up for a readme.md file if none is provided.
|
|
108
|
+
* @see `findReadme()` for more details on the search process.
|
|
109
|
+
*/
|
|
110
|
+
declare function expandReadmeFiles(files?: string | string[], name?: string, output?: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile[]>;
|
|
111
|
+
/**
|
|
112
|
+
* Expands MDAT readme comments in a Markdown string
|
|
113
|
+
*/
|
|
114
|
+
declare function expandReadmeString(markdown: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile>;
|
|
115
|
+
/**
|
|
116
|
+
* Checks and validates MDAT readme comments in the closest readme.md file
|
|
117
|
+
* Basically an alias to `checkReadmeFiles()` with certain arguments elided.
|
|
118
|
+
* @see `findReadme()` for more details on the search process.
|
|
119
|
+
*/
|
|
120
|
+
declare function checkReadme(config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile[]>;
|
|
121
|
+
/**
|
|
122
|
+
* Checks and validates MDAT readme comments in one or more Markdown files
|
|
123
|
+
* Searches up for a readme.md file if none is provided.
|
|
124
|
+
* @see `findReadme()` for more details on the search process.
|
|
125
|
+
*/
|
|
126
|
+
declare function checkReadmeFiles(files?: string | string[], name?: string, output?: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile[]>;
|
|
127
|
+
/**
|
|
128
|
+
* Checks and validates MDAT readme comments in a Markdown string
|
|
129
|
+
*/
|
|
130
|
+
declare function checkReadmeString(markdown: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile>;
|
|
131
|
+
/**
|
|
132
|
+
* Collapses MDAT readme comments in the closest readme.md file
|
|
133
|
+
* Basically an alias to `collapseReadmeFiles()` with certain arguments elided.
|
|
134
|
+
* @see `findReadme()` for more details on the search process.
|
|
135
|
+
*/
|
|
136
|
+
declare function collapseReadme(config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile[]>;
|
|
137
|
+
/**
|
|
138
|
+
* Collapses MDAT readme comments in one or more Markdown files
|
|
139
|
+
* Searches up for a readme.md file if none is provided.
|
|
140
|
+
* @see `findReadme()` for more details on the search process.
|
|
141
|
+
*/
|
|
142
|
+
declare function collapseReadmeFiles(files?: string | string[], name?: string, output?: string, config?: ConfigToLoad, rules?: RulesToLoad): Promise<VFile[]>;
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/lib/readme/config.d.ts
|
|
145
|
+
type ReadmeConfigLoaded = Simplify<ConfigLoaded & {
|
|
146
|
+
packageFile: string;
|
|
147
|
+
}>;
|
|
148
|
+
type LoadConfigOptions = Parameters<typeof loadConfig>[0];
|
|
149
|
+
/**
|
|
150
|
+
* Convenience loader to always include the default readme config.
|
|
151
|
+
* The readme defaults should have lower priority than searched/user config,
|
|
152
|
+
* but higher priority than base mdat defaults.
|
|
153
|
+
*/
|
|
154
|
+
declare function loadConfigReadme(options?: LoadConfigOptions): Promise<ReadmeConfigLoaded>;
|
|
155
|
+
//#endregion
|
|
156
|
+
export { type Config, type Rules, checkFiles, checkReadme, checkReadmeFiles, checkReadmeString, checkString, collapseFiles, collapseReadme, collapseReadmeFiles, collapseString, expandFiles, expandReadme, expandReadmeFiles, expandReadmeString, expandString, loadConfig, loadConfigReadme, mergeConfigs };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{cosmiconfig as e,defaultLoaders as t}from"cosmiconfig";import{TypeScriptLoader as n}from"cosmiconfig-typescript-loader";import r from"node:fs/promises";import i from"node:path";import a from"picocolors";import o from"plur";import{readPackage as s}from"read-pkg";import{deepMergeDefined as c,getSoleRule as l,log as u,mdatCheck as d,mdatClean as f,mdatExpand as p,mdatSplit as m,optionsSchema as h,rulesSchema as ee}from"remark-mdat";import{z as g}from"zod";import{packageUp as te}from"package-up";import{isFile as ne,isFileSync as _}from"path-type";import{Configuration as re}from"unified-engine";import ie from"untildify";import{remark as v}from"remark";import y from"remark-gfm";import{read as ae}from"to-vfile";import{VFile as oe}from"vfile";import{globby as se}from"globby";import{promisify as b}from"node:util";import{brotliCompress as ce,gzip as le}from"node:zlib";import ue from"pretty-bytes";import{toc as de}from"mdast-util-toc";import{findUp as fe}from"find-up";import{packageDirectory as pe}from"package-directory";function x(e,n){let r=t[`.json`];return S(r(e,n))}function S(e,t=``,n={}){for(let[r,i]of Object.entries(e)){let e=t?`${t}.${r}`:r;typeof i==`object`&&i&&!Array.isArray(i)?S(i,e,n):i===null?n[e]=`null`:n[e]=i.toString()}return n}function me(e,t){let n=t===0?1:Math.floor(Math.log10(Math.abs(t))+1);return e.toString().padStart(n,`0`)}async function he(e,t,n,r){let i=[];for(let[a,o]of e.entries()){let s=await ge(o,t,n,r,n&&e.length>1?`-${me(a+1,e.length)}`:``);i.push(s)}return i}async function ge(e,t,n,a,o=``){let s=C(e),c=t?C(t):void 0;if(!_(s))throw Error(`Input file not found: "${s}"`);if(c){if(_(c))throw Error(`Output path must be a directory, received a file path: "${c}"`);await r.mkdir(c,{recursive:!0})}return{input:s,name:`${n?i.basename(n,i.extname(n)):i.basename(s,i.extname(s))}${o}${`.${a??(n&&i.extname(n)!==``?i.extname(n):i.extname(e)===``?``:i.extname(e))}`}`,output:c??i.dirname(s)}}function C(e){return ie(e)}async function _e(){return te()}function ve(e){return e==null?[]:Array.isArray(e)?e:[e]}async function w(){let e=new re({cwd:process.cwd(),detectConfig:!0,packageField:`remarkConfig`,rcName:`.remarkrc`}),t=await new Promise(t=>{e.load(``,(e,n)=>{if(e){u.error(String(e)),t(void 0);return}t(n)})});if(t){let{filePath:e}=t;return e===void 0?u.info(`No ambient Remark configuration file found`):u.info(`Found and loaded ambient Remark configuration from "${e}"`),t}return u.info(`No ambient Remark configuration found`),{filePath:void 0,plugins:[],settings:{}}}const T=h.merge(g.object({assetsPath:g.string().optional(),packageFile:g.string().optional()})).describe(`Config Extension`);async function E(t){let{additionalConfig:s,additionalRules:l,readmeDefaults:d,searchFrom:f}=t??{};O=void 0,A=void 0;let p={addMetaComment:!1,assetsPath:`./assets`,closingPrefix:`/`,keywordPrefix:``,metaCommentIdentifier:`+`,packageFile:await _e(),rules:{mdat:`Powered by the Markdown Autophagic Template system: [mdat](https://github.com/kitschpatrol/mdat).`}};d&&(p=c(p,d));let m=e(`mdat`,{loaders:{".ts":n()}}),h=await m.search(f);if(h){let{config:e,filepath:t}=h,n=e;if(u.info(`Using config from "${t}"`),t.endsWith(`package.json`)&&typeof e==`string`){u.info(`Detected shared config string: "${e}"`);let{default:t}=await import(e);n=t}let r=D(n,T);r&&(p=c(p,r))}if(s!==void 0){let e=Array.isArray(s)?s:[s];for(let t of e){let e;if(typeof t==`string`){let n=await m.load(t);if(n==null)continue;let{config:r,filepath:i}=n;u.info(`Loaded additional config from "${i}"`),e=r}else e=t;if(e===void 0)continue;u.info(`Merging configuration object`);let n=D(e,T);n!==void 0&&(p=c(p,n))}}if(l!==void 0){let t=Array.isArray(l)?l:[l],a=e(`mdat`,{loaders:{".json":x,".ts":n()}});for(let e of t){let t;if(typeof e==`string`){let n;if(n=i.basename(e).endsWith(`package.json`)?{config:x(e,await r.readFile(e,`utf8`)),filepath:e}:await a.load(e),n==null)continue;let{config:o,filepath:s}=n;u.info(`Loaded additional config from "${s}"`),t=o}else t=e;if(t===void 0)continue;u.info(`Merging rules into configuration object`);let n=ye(t,ee);n!==void 0&&(p=c(p,n))}}if(p.rules){let e=Object.keys(p.rules).toSorted().map(e=>`"${a.green(a.bold(e))}"`);u.info(`Loaded ${a.bold(e.length)} mdat comment expansion ${o(`rule`,e.length)}:`);for(let t of e)u.info(`\t${t}`)}else u.error(`No rules loaded from additional configurations or rules, using default.`);return O=p,p}function ye(e,t){if(t.safeParse(e).success)return{rules:e};u.error(`Rules object has the wrong shape. Ignoring and using default configuration:\n${JSON.stringify(e,void 0,2)}`)}function D(e,t){if(t.safeParse(e).success)return e;u.error(`Config object has the wrong shape. Ignoring and using default configuration:\n${JSON.stringify(e,void 0,2)}`)}let O;async function k(){return O===void 0&&(u.warn(`getConfig(): config was undefined`),O??=await E()),O}let A;async function j(){let{packageFile:e}=await k();if(e===void 0)throw Error(`No packageFile found or set in config`);if(A??=await s({cwd:i.dirname(e)}),A===void 0)throw Error(`No package.json found`);return A}function be(e,t){return c(e,t)}async function M(e,t,n,r,i,a,o){let s=await t({additionalConfig:a,additionalRules:o}),c=await w(),l=await he(ve(e),i,r,`md`),u=[],d=n(s,c);for(let{input:e,name:t,output:n}of l){let r=await ae(e),i=await d.process(r);i.dirname=n,i.basename=t,u.push(i)}return u}async function N(e,t,n,r,i){return n(await t({additionalConfig:r,additionalRules:i}),await w()).process(new oe(e))}function P(e,t){return v().use({settings:{bullet:`-`,emphasis:`_`}}).use(y).use(t).use(()=>async function(t,n){m(t,n),f(t,n,e),await p(t,n,e)})}function F(e,t){return v().use({settings:{bullet:`-`,emphasis:`_`}}).use(y).use(t).use(()=>function(t,n){m(t,n),f(t,n,e)})}function I(e,t){return v().use({settings:{bullet:`-`,emphasis:`_`}}).use(y).use(t).use(()=>async function(t,n){await d(t,n,{...e,paranoid:!1})})}async function xe(e,t,n,r,i){return M(e,E,P,t,n,r,i)}async function Se(e,t,n){return N(e,E,P,t,n)}async function Ce(e,t,n,r,i){return M(e,E,I,t,n,r,i)}async function we(e,t,n){return N(e,E,I,t,n)}async function Te(e,t,n,r,i){return M(e,E,F,t,n,r,i)}async function Ee(e,t,n){return N(e,E,F,t,n)}var L={badges:{async content(e){let t=g.object({custom:g.record(g.object({image:g.string(),link:g.string()})).optional(),npm:g.array(g.string()).optional()}).optional().parse(e),n=await j(),{name:r}=n,i=[];if(t?.npm===void 0)(!n.name.startsWith(`@`)||n.publishConfig?.access===`public`)&&i.push(`[](https://npmjs.com/package/${r})`);else for(let e of t.npm)i.push(`[](https://npmjs.com/package/${e})`);let{license:a}=n;if(a!==void 0&&i.push(`[}-yellow.svg)](https://opensource.org/licenses/${a})`),t?.custom!==void 0)for(let[e,{image:n,link:r}]of Object.entries(t.custom))i.push(`[](${r})`);return i.join(`
|
|
2
|
+
`)},order:3}},R={banner:{async content(e){let t=g.object({alt:g.string().optional(),src:g.string().optional()}).optional().parse(e),{assetsPath:n,packageFile:r}=await k();if(r===void 0)throw Error(`No package.json found`);let a=t?.src??await z(n)??await z();if(a===void 0)throw Error(`Banner image not found at any typical location, consider adding something at ./assets/banner.webp`);if(!B(a)&&!await ne(a))throw Error(`Banner image not found at "${a}"`);let o=t?.alt;if(o===void 0){let e=(await s({cwd:i.dirname(r)})).name;if(e===void 0)throw Error(`Banner image alt text not available`);o=`${e} banner`}return``},order:2}};async function z(e){let{packageFile:t}=await k();if(t===void 0)throw Error(`No package.json found`);let n=i.dirname(t),r=await se((e===void 0?[`.`,`assets`,`media`,`readme-assets`,`readme-media`,`readme`,`images`,`.github/assets`]:[e]).map(e=>i.join(n,e)),{deep:1,expandDirectories:{extensions:[`png`,`gif`,`jpg`,`jpeg`,`svg`,`webp`],files:[`banner`,`cover`,`demo`,`header`,`hero`,`image`,`logo`,`overview`,`readme`,`screenshot`,`screenshots`,`splash`]}});if(r.length>0)return i.relative(process.cwd(),r[0])}function B(e,t=!0){if(typeof e!=`string`)throw TypeError(`Expected a string`);if(e=e.trim(),e.includes(` `))return!1;try{return new URL(e),!0}catch{return t?B(`https://${e}`,!1):!1}}var De={code:{async content(e){let t=g.object({file:g.string(),language:g.string().optional()}).parse(e);return`\`\`\`${(i.extname(t.file)??``).replace(/^\./,``)}\n${await r.readFile(i.join(process.cwd(),t.file),`utf8`)}\n\`\`\``}}},V={contributing:{async content(){let e=(await j()).bugs?.url;if(e===void 0)throw Error(`Could not find "bugs.url" entry in package.json`);return`## Contributing\n[Issues](${e}) and pull requests are welcome.`},order:15}},H={description:{async content(){let e=await j();if(e.description===void 0)throw Error(`Could not find "description" entry in package.json`);return`**${e.description}**`},order:4}},U={license:{async content(){let{author:e,license:t}=await j();if(e?.name===void 0)throw Error(`Could not find "author.name" entry in package.json`);if(t===void 0)throw Error(`Could not find "license" entry in package.json`);return`## License\n[${t}](license.txt) © ${e.name}`},order:16}},Oe={footer:{content:[l(V),l(U)],order:17}},W={"short-description":l(H)},G={title:{applicationOrder:2,async content(e){let{postfix:t,prefix:n,titleCase:r}=g.object({postfix:g.string().optional().default(``),prefix:g.string().optional().default(``),titleCase:g.boolean().optional().default(!1)}).parse(e??{}),{name:i}=await j();return`# ${n}${r?ke(i):i}${t}`},order:1}};function ke(e){return e.split(/[ _-]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}var Ae={header:{applicationOrder:2,content:[l(G),l(R),l(L),l(W)],order:1}};const je=b(ce),Me=b(le);function K(e,t){let n=t===0?0:(t-e)/t*100;return{bytes:e,bytesPretty:ue(e,{maximumFractionDigits:1}),percent:n,percentPretty:`${Math.round(n)}%`}}async function q(e){try{let t=await r.readFile(e),n=t.length,[i,a]=await Promise.all([je(t),Me(t)]);return{brotli:K(i.length,n),gzip:K(a.length,n),original:K(n,n)}}catch(e){throw Error(`Failed to analyze file: ${e instanceof Error?e.message:`Unknown error`}`)}}const Ne=g.object({compression:g.enum([`none`,`brotli`,`gzip`]).optional().default(`none`),file:g.string()});function Pe(e,t){switch(t){case`brotli`:return e.brotli.bytesPretty;case`gzip`:return e.gzip.bytesPretty;case`none`:return e.original.bytesPretty}}var Fe={size:{async content(e){let t=Ne.parse(e);return Pe(await q(i.join(process.cwd(),t.file)),t.compression)}}};const J=g.union([g.string(),g.array(g.string())]).transform(e=>Array.isArray(e)?e:[e]),Ie=g.union([g.object({brotli:g.boolean().optional().default(!0),file:J,gzip:g.boolean().optional().default(!0),original:g.boolean().optional().default(!0),showPercentage:g.boolean().optional().default(!1)}),g.object({brotli:g.boolean().optional().default(!0),files:J,gzip:g.boolean().optional().default(!0),original:g.boolean().optional().default(!0),showPercentage:g.boolean().optional().default(!1)})]).transform(e=>{if(`file`in e){let{file:t,...n}=e;return{files:t,...n}}return e});function Le(e,t){let n=[`File`];t.original&&n.push(`Original`),t.gzip&&n.push(`Gzip`),t.brotli&&n.push(`Brotli`);let r=n.map(()=>`---`),a=e.map(([e,n])=>{let r=[i.basename(e)];return t.original&&r.push(n.original.bytesPretty),t.gzip&&r.push(t.showPercentage?`${n.gzip.bytesPretty} (${n.gzip.percentPretty})`:n.gzip.bytesPretty),t.brotli&&r.push(t.showPercentage?`${n.brotli.bytesPretty} (${n.brotli.percentPretty})`:n.brotli.bytesPretty),r});return[`| ${n.join(` | `)} |`,`| ${r.join(` | `)} |`,...a.map(e=>`| ${e.join(` | `)} |`)].join(`
|
|
3
|
+
`)}var Re={"size-table":{async content(e){let t=Ie.parse(e);return Le(await Promise.all(t.files.map(async e=>[e,await q(i.join(process.cwd(),e))])),{brotli:t.brotli,gzip:t.gzip,original:t.original,showPercentage:t.showPercentage})}}},Y={"table-of-contents":{applicationOrder:1,async content(e,t){let n=de(t,{heading:null,maxDepth:g.object({depth:g.union([g.literal(1),g.literal(2),g.literal(3),g.literal(4),g.literal(5),g.literal(6)]).optional()}).optional().parse(e)?.depth??3,tight:!0});if(n.map===void 0)throw Error(`Could not generate table of contents`);let r={children:n.map.children,type:`root`};return[`## Table of contents`,v().use(y).stringify(r).replaceAll(`
|
|
4
|
+
|
|
5
|
+
`,`
|
|
6
|
+
`)].join(`
|
|
7
|
+
`)},order:6}},ze={toc:l(Y)},Be={...L,...R,...De,...V,...H,...Oe,...Ae,...U,...W,...Fe,...Re,...Y,...G,...ze};async function X(e){let t={addMetaComment:!0,rules:Be},{additionalConfig:n=[],readmeDefaults:r=t,...i}=e??{},a=await E({additionalConfig:Array.isArray(n)?n:[n],readmeDefaults:r,...i});if(a.packageFile===void 0)throw Error("Package file path is required in `mdat readme` config");return a}async function Ve(){u.info(`Searching for package directory...`);let e=await fe(`readme.md`,{stopAt:await pe()??process.cwd(),type:`file`});if(e!==void 0)return u.info(`Found closest readme at "${e}"`),e}async function Z(){let e=await Ve();if(e===void 0)throw Error(`No readme found`);return e}async function He(e,t){return Q(void 0,void 0,void 0,e,t)}async function Q(e,t,n,r,i){return e??=await Z(),M(e,X,P,t,n,r,i)}async function Ue(e,t,n){return N(e,X,P,t,n)}async function We(e,t){return Ge(void 0,void 0,void 0,e,t)}async function Ge(e,t,n,r,i){return e??=await Z(),M(e,X,I,t,n,r,i)}async function Ke(e,t,n){return N(e,X,I,t,n)}async function qe(e,t){return $(void 0,void 0,void 0,e,t)}async function $(e,t,n,r,i){return e??=await Z(),M(e,X,F,t,n,r,i)}export{Ce as checkFiles,We as checkReadme,Ge as checkReadmeFiles,Ke as checkReadmeString,we as checkString,Te as collapseFiles,qe as collapseReadme,$ as collapseReadmeFiles,Ee as collapseString,xe as expandFiles,He as expandReadme,Q as expandReadmeFiles,Ue as expandReadmeString,Se as expandString,E as loadConfig,X as loadConfigReadme,be as mergeConfigs};
|
package/license.txt
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdat",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"description": "CLI tool and TypeScript library implementing the Markdown Autophagic Template (MDAT) system. MDAT lets you use comments as dynamic content templates in Markdown files, making it easy to generate and update readme boilerplate.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mdat",
|
|
@@ -26,66 +26,78 @@
|
|
|
26
26
|
"url": "https://ericmika.com"
|
|
27
27
|
},
|
|
28
28
|
"type": "module",
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/lib/index.d.ts",
|
|
32
|
+
"import": "./dist/lib/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"main": "./dist/lib/index.js",
|
|
36
|
+
"module": "./dist/lib/index.js",
|
|
37
|
+
"types": "./dist/lib/index.d.ts",
|
|
32
38
|
"bin": {
|
|
33
|
-
"mdat": "bin/cli.js"
|
|
39
|
+
"mdat": "dist/bin/cli.js"
|
|
34
40
|
},
|
|
35
41
|
"files": [
|
|
36
|
-
"bin/*",
|
|
37
42
|
"dist/*"
|
|
38
43
|
],
|
|
39
44
|
"dependencies": {
|
|
40
|
-
"@clack/prompts": "^0.
|
|
41
|
-
"@types/mdast": "^4.0.4",
|
|
42
|
-
"@types/node": "^22.19.1",
|
|
43
|
-
"@types/unist": "^3.0.3",
|
|
44
|
-
"@types/yargs": "^17.0.35",
|
|
45
|
+
"@clack/prompts": "^1.0.1",
|
|
45
46
|
"cosmiconfig": "^9.0.0",
|
|
46
47
|
"cosmiconfig-typescript-loader": "^6.2.0",
|
|
47
|
-
"globby": "^14.1.0",
|
|
48
|
-
"read-pkg": "^10.0.0",
|
|
49
|
-
"remark-mdat": "^1.2.1",
|
|
50
|
-
"type-fest": "^5.3.1",
|
|
51
|
-
"unified-engine": "^11.2.2",
|
|
52
|
-
"vfile": "^6.0.3"
|
|
53
|
-
},
|
|
54
|
-
"devDependencies": {
|
|
55
|
-
"@kitschpatrol/shared-config": "^5.10.0",
|
|
56
|
-
"bumpp": "^10.3.2",
|
|
57
|
-
"execa": "^9.6.1",
|
|
58
48
|
"find-up": "^8.0.0",
|
|
49
|
+
"globby": "^16.1.1",
|
|
59
50
|
"mdast-util-toc": "^7.1.0",
|
|
60
|
-
"
|
|
61
|
-
"mdat-plugin-example": "^1.0.1",
|
|
62
|
-
"mdat-plugin-tldraw": "^1.0.2",
|
|
63
|
-
"nanoid": "^5.1.6",
|
|
64
|
-
"package-directory": "^8.1.0",
|
|
51
|
+
"package-directory": "^8.2.0",
|
|
65
52
|
"package-up": "^5.0.0",
|
|
66
53
|
"path-type": "^6.0.0",
|
|
67
54
|
"picocolors": "^1.1.1",
|
|
68
55
|
"plur": "^6.0.0",
|
|
69
56
|
"pretty-bytes": "^7.1.0",
|
|
70
57
|
"pretty-ms": "^9.3.0",
|
|
58
|
+
"read-pkg": "^10.1.0",
|
|
71
59
|
"remark": "^15.0.1",
|
|
72
60
|
"remark-gfm": "^4.0.1",
|
|
61
|
+
"remark-mdat": "^1.2.3",
|
|
73
62
|
"to-vfile": "^8.0.0",
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"unplugin-raw": "^0.6.3",
|
|
63
|
+
"type-fest": "^5.4.4",
|
|
64
|
+
"unified-engine": "^11.2.2",
|
|
77
65
|
"untildify": "^6.0.0",
|
|
78
|
-
"
|
|
79
|
-
"yargs": "^
|
|
66
|
+
"vfile": "^6.0.3",
|
|
67
|
+
"yargs": "^18.0.0",
|
|
80
68
|
"zod": "^3.25.76"
|
|
81
69
|
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@arethetypeswrong/core": "^0.18.2",
|
|
72
|
+
"@kitschpatrol/shared-config": "^6.0.0",
|
|
73
|
+
"@types/mdast": "^4.0.4",
|
|
74
|
+
"@types/node": "~20.19.33",
|
|
75
|
+
"@types/unist": "^3.0.3",
|
|
76
|
+
"@types/yargs": "^17.0.35",
|
|
77
|
+
"bumpp": "^10.4.1",
|
|
78
|
+
"execa": "^9.6.1",
|
|
79
|
+
"mdat-plugin-cli-help": "^1.0.6",
|
|
80
|
+
"mdat-plugin-example": "^1.0.4",
|
|
81
|
+
"mdat-plugin-tldraw": "^1.0.6",
|
|
82
|
+
"nanoid": "^5.1.6",
|
|
83
|
+
"publint": "^0.3.17",
|
|
84
|
+
"tsdown": "^0.20.3",
|
|
85
|
+
"typescript": "~5.9.3",
|
|
86
|
+
"unplugin-raw": "^0.6.4",
|
|
87
|
+
"vitest": "^4.0.18"
|
|
88
|
+
},
|
|
82
89
|
"engines": {
|
|
83
90
|
"node": ">=20.19.0"
|
|
84
91
|
},
|
|
92
|
+
"devEngines": {
|
|
93
|
+
"runtime": {
|
|
94
|
+
"name": "node",
|
|
95
|
+
"version": ">=22.21.0"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
85
98
|
"scripts": {
|
|
86
|
-
"build": "tsdown
|
|
99
|
+
"build": "tsdown",
|
|
87
100
|
"clean": "git rm -f pnpm-lock.yaml ; git clean -fdX",
|
|
88
|
-
"dev": "pnpm run test",
|
|
89
101
|
"fix": "ksc fix",
|
|
90
102
|
"lint": "ksc lint",
|
|
91
103
|
"release": "bumpp --commit 'Release: %s' && pnpm run build && NPM_AUTH_TOKEN=$(op read 'op://Personal/npm/token') && pnpm publish",
|