Skip to content

Commit bcbaa25

Browse files
committed
feat: add install transform for generating installation instructions
1 parent cedf851 commit bcbaa25

6 files changed

Lines changed: 126 additions & 8 deletions

File tree

src/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const tocTransform = require('./transforms/toc')
99
const sectionTocTransform = require('./transforms/sectionToc')
1010
const wordCountTransform = require('./transforms/wordCount')
1111
const remoteTransform = require('./transforms/remote')
12+
const installTransform = require('./transforms/install')
1213
const { getSyntaxInfo } = require('./utils/syntax')
1314
const { onlyUnique, getCodeLocation, pluralize } = require('./utils')
1415
const { readFile, resolveOutputPath, resolveFlatPath } = require('./utils/fs')
@@ -34,7 +35,8 @@ const defaultTransforms = {
3435
TOC: tocTransform,
3536
sectionToc: sectionTocTransform,
3637
wordCount: wordCountTransform,
37-
remote: remoteTransform
38+
remote: remoteTransform,
39+
install: installTransform,
3840
}
3941

4042
const defaultOptions = {

src/transforms/code/index.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ const path = require('path')
33
const { remoteRequest } = require('../../utils/remoteRequest')
44
const { isLocalPath } = require('../../utils/fs')
55
const { deepLog } = require('../../utils/logs')
6-
const { getLineCount, getTextBetweenLines, stripMultiLineDoubleDashComments, stripHTMLComments } = require('../../utils/text')
6+
const {
7+
getLineCount,
8+
getTextBetweenLines,
9+
stripMultiLineDoubleSlashComments,
10+
stripSingleLineDoubleSlashComments,
11+
stripHTMLComments
12+
} = require('../../utils/text')
713
const { resolveGithubContents, isGithubLink } = require('./resolve-github-file')
814

915
const GITHUB_LINK = /https:\/\/github\.com\/([^/\s]*)\/([^/\s]*)\/blob\//
@@ -158,7 +164,7 @@ module.exports = async function CODE(api) {
158164
const endLineIndex = lines.findIndex(line => line.includes(`CODE_SECTION:${id}:END`));
159165
const endLine = endLineIndex !== -1 ? endLineIndex : lines.length - 1;
160166
// console.log('startLine', startLine)
161-
// console.log('endLineendLine', endLine)
167+
// console.log('endLine', endLine)
162168
if (startLine === -1 && endLine === -1) {
163169
throw new Error(`Missing ${id} code section from ${codeFilePath}`)
164170
}
@@ -179,10 +185,16 @@ module.exports = async function CODE(api) {
179185
if (options.header) {
180186
header = `\n${options.header}`
181187
}
188+
189+
if (options.trimSingleLineComments) {
190+
if (syntax === 'js' || syntax === 'ts' || syntax === 'javascript' || syntax === 'typescript') {
191+
code = stripSingleLineDoubleSlashComments(code)
192+
}
193+
}
182194

183195
if (options.trimDeadCode) {
184196
if (syntax === 'js' || syntax === 'ts' || syntax === 'javascript' || syntax === 'typescript') {
185-
code = stripMultiLineDoubleDashComments(code)
197+
code = stripMultiLineDoubleSlashComments(code)
186198
} else if (syntax === 'html') {
187199
code = stripHTMLComments(code, { multilineOnly: true })
188200
}

src/transforms/index.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const file = require('./file')
33
const remoteContent = require('./remote')
44
const toc = require('./toc')
55
const sectionToc = require('./sectionToc')
6+
const install = require('./install')
67

78
const transforms = {
89
/**
@@ -111,6 +112,32 @@ const transforms = {
111112
* @return {string} Updated content to place in the content block
112113
*/
113114
REMOTE: remoteContent,
115+
/**
116+
* ### > install
117+
*
118+
* Generate installation instructions in a markdown table format
119+
*
120+
* **Options:**
121+
* - `packageName` (optional): The name of the package to install. If not provided, will try to read from package.json
122+
* - `isDev` (optional): Whether to install the package as a dev dependency. Default `false`
123+
* - `header` (optional): The header to use for the installation instructions. Default `# Installation`
124+
* - `body` (optional): The body to use for the installation instructions. Default `Install the \`${packageName}\` cli using your favorite package manager.`
125+
*
126+
* **Example:**
127+
* ```md
128+
* <!-- doc-gen install -->
129+
* Installation instructions will be generated here
130+
* <!-- end-doc-gen -->
131+
* ```
132+
*
133+
* Default `matchWord` is `doc-gen`
134+
*
135+
* ---
136+
* @param {string} content The current content of the comment block
137+
* @param {object} options The options passed in from the comment declaration
138+
* @return {string} Updated content to place in the content block
139+
*/
140+
install: install,
114141
}
115142

116143
module.exports = transforms

src/transforms/install.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
const fs = require('fs')
2+
const path = require('path')
3+
4+
/**
5+
* ### > INSTALL
6+
*
7+
* Generate installation instructions in a markdown table format
8+
*
9+
* **Options:**
10+
* - `packageName` (optional): The name of the package to install. If not provided, will try to read from package.json
11+
*
12+
* **Example:**
13+
* ```md
14+
* <!-- doc-gen INSTALL packageName=my-package -->
15+
* Installation instructions will be generated here
16+
* <!-- end-doc-gen -->
17+
* ```
18+
*
19+
* Default `matchWord` is `doc-gen`
20+
*
21+
* ---
22+
* @param {string} content The current content of the comment block
23+
* @param {object} options The options passed in from the comment declaration
24+
* @return {string} Updated content to place in the content block
25+
*/
26+
function install(api) {
27+
console.log('INSTALL API', api)
28+
const { options } = api
29+
const { isDev = false } = options
30+
let packageName = options.packageName
31+
32+
// If no package name provided, try to read from package.json
33+
if (!packageName) {
34+
try {
35+
const packageJsonPath = path.join(process.cwd(), 'package.json')
36+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
37+
packageName = packageJson.name
38+
} catch (error) {
39+
console.log('Could not read package.json:', error.message)
40+
return 'Error: No package name provided and could not read from package.json'
41+
}
42+
}
43+
44+
let header = '# Installation'
45+
if (options.header) {
46+
header = (options.header.startsWith('#')) ? options.header : `# ${options.header}`
47+
}
48+
header = `${header}\n\n`
49+
50+
let body = `Install the \`${packageName}\` cli using your favorite package manager.`
51+
if (options.body) {
52+
body = (options.body.startsWith('\n')) ? options.body : `\n${options.body}`
53+
}
54+
body = `${body}\n`
55+
56+
if (!packageName) {
57+
return 'Error: No package name provided'
58+
}
59+
60+
const flag = isDev ? ' -D' : ' '
61+
const space = isDev ? ' ' : ''
62+
63+
return `${header}${body}
64+
| package manager | command |
65+
| --------------- | ------- |
66+
| npm | \`npm install ${packageName}${flag}\` |
67+
| pnpm | \`pnpm add ${packageName}${flag}\` |
68+
| yarn | \`yarn add ${packageName}${flag}\` |
69+
| bun | \`bun install ${packageName}\`${space} |`
70+
}
71+
72+
module.exports = install

src/utils/format-md.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ const { removeLeadingH1 } = require('@davidwells/md-utils/string-utils')
33

44
function formatMd(content, options = {}) {
55
let fileContents = content
6-
if (options.removeLeadingH1) {
6+
if (options.removeLeadingH1 || options.stripFirstH1) {
77
fileContents = removeLeadingH1(fileContents)
88
}
99

1010
// Shift headers up or down by the specified number of levels if shiftHeaders is enabled and file is markdown
1111
if (options.shiftHeaders) {
1212
fileContents = fileContents.replace(/^(#{1,6})\s/gm, (match, hashes) => {
1313
const currentLevel = hashes.length;
14-
const shiftAmount = options.shiftHeaders;
14+
const shiftAmount = Number(options.shiftHeaders);
1515
const newLevel = Math.max(1, Math.min(6, currentLevel + shiftAmount));
1616
return '#'.repeat(newLevel) + ' ';
1717
})

src/utils/text.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,14 @@ function stripComments(str, syntax = 'md') {
197197

198198

199199
// https://regex101.com/r/nCnt2J/1
200-
function stripMultiLineDoubleDashComments(str = '') {
200+
function stripMultiLineDoubleSlashComments(str = '') {
201201
return str.replace(/(?:\n\s*\/\/.*){2,}/g, '')
202202
}
203203

204+
function stripSingleLineDoubleSlashComments(str = '') {
205+
return str.replace(/\/\/.*$/gm, '')
206+
}
207+
204208
// https://regex101.com/r/plpXmr/1
205209
function stripOutMultilineJsComments(str = '') {
206210
return str.replace(/\/\*[\s\S]+?\*\/\s*\n?/g, (match) => {
@@ -351,7 +355,8 @@ module.exports = {
351355
dedentString,
352356
stripComments,
353357
convertCommentSyntax,
354-
stripMultiLineDoubleDashComments,
358+
stripSingleLineDoubleSlashComments,
359+
stripMultiLineDoubleSlashComments,
355360
stripHTMLComments,
356361
// stripCommentBlockJS,
357362
trimString,

0 commit comments

Comments
 (0)