From 537668f18ba7dd534cc191f70e4859faeac55c2c Mon Sep 17 00:00:00 2001 From: Trey Cucco Date: Thu, 7 Sep 2023 11:47:32 -0600 Subject: [PATCH 1/3] Recognize jsx-style comments in .mdx files --- README.md | 8 +++-- src/utils/replace.test.ts | 74 ++++++++++++++++++++++++++++++--------- src/utils/replace.ts | 25 ++++++++++--- 3 files changed, 84 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index b44c002..67c62bf 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,7 @@ You can install this package via npm: ## Tagging your Code as a Best Practice -You can tag blocks of code as best practices with specially formatted -comments: +You can tag blocks of code as best practices with specially formatted comments: ```tsx // @BestPractice React Components @@ -108,6 +107,11 @@ like to insert a best practice: +If your file is a `.mdx` Markdown file, use `JSX` style comments instead: + + {/* @BestPractice.insert insertIntoStaticDocs */} + {/* @BestPractice.end */} + It's important to have both the start and end lines, as these will be used as boundaries of the program to know where to replace the code. diff --git a/src/utils/replace.test.ts b/src/utils/replace.test.ts index b69bd73..45de539 100644 --- a/src/utils/replace.test.ts +++ b/src/utils/replace.test.ts @@ -4,24 +4,24 @@ import BestPractice from '../BestPractice'; import { replaceBestPractices } from './replace'; describe(replaceBestPractices, () => { - test('replaces best practices correctly', () => { - const getBestPracticeLines = (bestPractice: BestPractice) => { - return [ - `\`\`\`${bestPractice.getFileType()}`, - ...bestPractice.codeLines, - '```', - ]; - }; - - const bestPractices = [ - mockBestPractice({ meta: { id: ['sample_id_1'] } }), - mockBestPractice({ - codeLines: ['const c = a + b'], - meta: { id: ['sample_id_2'] }, - }), + const getBestPracticeLines = (bestPractice: BestPractice) => { + return [ + `\`\`\`${bestPractice.getFileType()}`, + ...bestPractice.codeLines, + '```', ]; - const index = new Map(bestPractices.map((bp) => [bp.getMeta('id'), bp])); + }; + + const bestPractices = [ + mockBestPractice({ meta: { id: ['sample_id_1'] } }), + mockBestPractice({ + codeLines: ['const c = a + b'], + meta: { id: ['sample_id_2'] }, + }), + ]; + const index = new Map(bestPractices.map((bp) => [bp.getMeta('id'), bp])); + test('replaces .md best practices correctly', () => { const oldLines = [ '## A Title', '', @@ -62,4 +62,46 @@ describe(replaceBestPractices, () => { expect(insertedIds).toEqual(new Set(['sample_id_1'])); }); + + test('replaces .mdx best practices correctly', () => { + const oldLines = [ + '## A Title', + '', + "Hello and here's the thing.", + '', + '{/* @BestPractice.insert sample_id_1 */}', + 'this is', + 'lines that were', + 'inserted before', + '{/* @BestPractice.end */}', + '', + "And here's some stuff after", + ]; + + const [newLines, insertedIds] = replaceBestPractices( + 'someDocumentation.mdx', + oldLines, + index, + getBestPracticeLines, + ); + + expect(newLines).toEqual([ + '## A Title', + '', + "Hello and here's the thing.", + '', + '{/* @BestPractice.insert sample_id_1 */}', + '```ts', + ' const add = (a: number) => (b: number) => {', + ' return a + b;', + ' };', + ' return add(5);', + '```', + '{/* @BestPractice.end */}', + '', + "And here's some stuff after", + ]); + + expect(insertedIds).toEqual(new Set(['sample_id_1'])); + }); }); diff --git a/src/utils/replace.ts b/src/utils/replace.ts index b1f9a9f..beaa0c5 100644 --- a/src/utils/replace.ts +++ b/src/utils/replace.ts @@ -63,6 +63,7 @@ export const replaceBestPractices = ( index: Map, getBestPracticeLines: (bestPractices: BestPractice) => string[], ): [newLines: string[], insertedIds: Set] => { + const [startRe, endRe] = getInsertREs(filename); let inBestPractice = false; let lineNumber = 0; @@ -73,7 +74,7 @@ export const replaceBestPractices = ( lineNumber += 1; if (inBestPractice) { - if (INSERT_END_RE.test(line)) { + if (endRe.test(line)) { inBestPractice = false; // Do not continue, we want to write out the end line } else { @@ -83,10 +84,10 @@ export const replaceBestPractices = ( newLines.push(line); - if (INSERT_START_RE.test(line)) { + if (startRe.test(line)) { inBestPractice = true; - const [, bestPracticeId] = INSERT_START_RE.exec(line)!; + const [, bestPracticeId] = startRe.exec(line)!; if (!index.has(bestPracticeId)) { throw new Error( @@ -102,5 +103,19 @@ export const replaceBestPractices = ( return [newLines, new Set(insertedIds)]; }; -const INSERT_START_RE = /^\s*$/; -const INSERT_END_RE = /^\s*$/; +/** + * Get the regexp to match insertion comments in a documentation file. + * + * .mdx files use jsx comments rather than html comments. + */ +const getInsertREs = (filename: string): [start: RegExp, end: RegExp] => { + if (/\.mdx$/.test(filename)) { + return [MDX_INSERT_START_RE, MDX_INSERT_END_RE]; + } + return [MD_INSERT_START_RE, MD_INSERT_END_RE]; +}; + +const MD_INSERT_START_RE = /^\s*$/; +const MD_INSERT_END_RE = /^\s*$/; +const MDX_INSERT_START_RE = /^\s*{\/\* @BestPractice.insert (\S+) \*\/}$/; +const MDX_INSERT_END_RE = /^\s*{\/\* @BestPractice.end \*\/}$/; From f99c22e2222a09abebdf6957074fd4cc339f4630 Mon Sep 17 00:00:00 2001 From: Trey Cucco Date: Thu, 7 Sep 2023 11:49:07 -0600 Subject: [PATCH 2/3] Build lib --- lib/cjs/types/utils/replace.d.ts.map | 2 +- lib/cjs/utils/replace.js | 24 +++++++++++++++++++----- lib/esm/types/utils/replace.d.ts.map | 2 +- lib/esm/utils/replace.js | 24 +++++++++++++++++++----- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/lib/cjs/types/utils/replace.d.ts.map b/lib/cjs/types/utils/replace.d.ts.map index 8e22c03..d5e7c56 100644 --- a/lib/cjs/types/utils/replace.d.ts.map +++ b/lib/cjs/types/utils/replace.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"replace.d.ts","sourceRoot":"","sources":["../../../../src/utils/replace.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,iBAAiB,CAAC;AAG3C;;GAEG;AACH,eAAO,MAAM,6BAA6B,aAC9B,MAAM,iBACD,YAAY,EAAE,uCACQ,YAAY,KAAK,MAAM,EAAE,KAC7D,QAAQ,IAAI,MAAM,CAAC,CAwBrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,aAC3B,MAAM,SACT,IAAI,MAAM,EAAE,YAAY,CAAC,uCACK,YAAY,KAAK,MAAM,EAAE,KAC7D,QAAQ,IAAI,MAAM,CAAC,CAUrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,aACrB,MAAM,SACT,MAAM,EAAE,SACR,IAAI,MAAM,EAAE,YAAY,CAAC,wCACM,YAAY,KAAK,MAAM,EAAE,mDAuChE,CAAC"} \ No newline at end of file +{"version":3,"file":"replace.d.ts","sourceRoot":"","sources":["../../../../src/utils/replace.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,iBAAiB,CAAC;AAG3C;;GAEG;AACH,eAAO,MAAM,6BAA6B,aAC9B,MAAM,iBACD,YAAY,EAAE,uCACQ,YAAY,KAAK,MAAM,EAAE,KAC7D,QAAQ,IAAI,MAAM,CAAC,CAwBrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,aAC3B,MAAM,SACT,IAAI,MAAM,EAAE,YAAY,CAAC,uCACK,YAAY,KAAK,MAAM,EAAE,KAC7D,QAAQ,IAAI,MAAM,CAAC,CAUrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,aACrB,MAAM,SACT,MAAM,EAAE,SACR,IAAI,MAAM,EAAE,YAAY,CAAC,wCACM,YAAY,KAAK,MAAM,EAAE,mDAwChE,CAAC"} \ No newline at end of file diff --git a/lib/cjs/utils/replace.js b/lib/cjs/utils/replace.js index 46ca962..13344b5 100644 --- a/lib/cjs/utils/replace.js +++ b/lib/cjs/utils/replace.js @@ -69,6 +69,7 @@ exports.insertBestPracticesIntoDoc = insertBestPracticesIntoDoc; * Given lines from a file, return new lines with best practices inserted. */ const replaceBestPractices = (filename, lines, index, getBestPracticeLines) => { + const [startRe, endRe] = getInsertREs(filename); let inBestPractice = false; let lineNumber = 0; const newLines = []; @@ -76,7 +77,7 @@ const replaceBestPractices = (filename, lines, index, getBestPracticeLines) => { for (const line of lines) { lineNumber += 1; if (inBestPractice) { - if (INSERT_END_RE.test(line)) { + if (endRe.test(line)) { inBestPractice = false; // Do not continue, we want to write out the end line } @@ -85,9 +86,9 @@ const replaceBestPractices = (filename, lines, index, getBestPracticeLines) => { } } newLines.push(line); - if (INSERT_START_RE.test(line)) { + if (startRe.test(line)) { inBestPractice = true; - const [, bestPracticeId] = INSERT_START_RE.exec(line); + const [, bestPracticeId] = startRe.exec(line); if (!index.has(bestPracticeId)) { throw new Error(`Missing best practice: file ${filename} at line ${lineNumber} expects best practice ID: ${bestPracticeId}. No best practice with this ID was found.`); } @@ -98,5 +99,18 @@ const replaceBestPractices = (filename, lines, index, getBestPracticeLines) => { return [newLines, new Set(insertedIds)]; }; exports.replaceBestPractices = replaceBestPractices; -const INSERT_START_RE = /^\s*$/; -const INSERT_END_RE = /^\s*$/; +/** + * Get the regexp to match insertion comments in a documentation file. + * + * .mdx files use jsx comments rather than html comments. + */ +const getInsertREs = (filename) => { + if (/\.mdx$/.test(filename)) { + return [MDX_INSERT_START_RE, MDX_INSERT_END_RE]; + } + return [MD_INSERT_START_RE, MD_INSERT_END_RE]; +}; +const MD_INSERT_START_RE = /^\s*$/; +const MD_INSERT_END_RE = /^\s*$/; +const MDX_INSERT_START_RE = /^\s*{\/\* @BestPractice.insert (\S+) \*\/}$/; +const MDX_INSERT_END_RE = /^\s*{\/\* @BestPractice.end \*\/}$/; diff --git a/lib/esm/types/utils/replace.d.ts.map b/lib/esm/types/utils/replace.d.ts.map index 8e22c03..d5e7c56 100644 --- a/lib/esm/types/utils/replace.d.ts.map +++ b/lib/esm/types/utils/replace.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"replace.d.ts","sourceRoot":"","sources":["../../../../src/utils/replace.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,iBAAiB,CAAC;AAG3C;;GAEG;AACH,eAAO,MAAM,6BAA6B,aAC9B,MAAM,iBACD,YAAY,EAAE,uCACQ,YAAY,KAAK,MAAM,EAAE,KAC7D,QAAQ,IAAI,MAAM,CAAC,CAwBrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,aAC3B,MAAM,SACT,IAAI,MAAM,EAAE,YAAY,CAAC,uCACK,YAAY,KAAK,MAAM,EAAE,KAC7D,QAAQ,IAAI,MAAM,CAAC,CAUrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,aACrB,MAAM,SACT,MAAM,EAAE,SACR,IAAI,MAAM,EAAE,YAAY,CAAC,wCACM,YAAY,KAAK,MAAM,EAAE,mDAuChE,CAAC"} \ No newline at end of file +{"version":3,"file":"replace.d.ts","sourceRoot":"","sources":["../../../../src/utils/replace.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,iBAAiB,CAAC;AAG3C;;GAEG;AACH,eAAO,MAAM,6BAA6B,aAC9B,MAAM,iBACD,YAAY,EAAE,uCACQ,YAAY,KAAK,MAAM,EAAE,KAC7D,QAAQ,IAAI,MAAM,CAAC,CAwBrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,aAC3B,MAAM,SACT,IAAI,MAAM,EAAE,YAAY,CAAC,uCACK,YAAY,KAAK,MAAM,EAAE,KAC7D,QAAQ,IAAI,MAAM,CAAC,CAUrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,aACrB,MAAM,SACT,MAAM,EAAE,SACR,IAAI,MAAM,EAAE,YAAY,CAAC,wCACM,YAAY,KAAK,MAAM,EAAE,mDAwChE,CAAC"} \ No newline at end of file diff --git a/lib/esm/utils/replace.js b/lib/esm/utils/replace.js index 5a8f06d..e7e334e 100644 --- a/lib/esm/utils/replace.js +++ b/lib/esm/utils/replace.js @@ -40,6 +40,7 @@ exports.insertBestPracticesIntoDoc = insertBestPracticesIntoDoc; * Given lines from a file, return new lines with best practices inserted. */ const replaceBestPractices = (filename, lines, index, getBestPracticeLines) => { + const [startRe, endRe] = getInsertREs(filename); let inBestPractice = false; let lineNumber = 0; const newLines = []; @@ -47,7 +48,7 @@ const replaceBestPractices = (filename, lines, index, getBestPracticeLines) => { for (const line of lines) { lineNumber += 1; if (inBestPractice) { - if (INSERT_END_RE.test(line)) { + if (endRe.test(line)) { inBestPractice = false; // Do not continue, we want to write out the end line } @@ -56,9 +57,9 @@ const replaceBestPractices = (filename, lines, index, getBestPracticeLines) => { } } newLines.push(line); - if (INSERT_START_RE.test(line)) { + if (startRe.test(line)) { inBestPractice = true; - const [, bestPracticeId] = INSERT_START_RE.exec(line); + const [, bestPracticeId] = startRe.exec(line); if (!index.has(bestPracticeId)) { throw new Error(`Missing best practice: file ${filename} at line ${lineNumber} expects best practice ID: ${bestPracticeId}. No best practice with this ID was found.`); } @@ -69,5 +70,18 @@ const replaceBestPractices = (filename, lines, index, getBestPracticeLines) => { return [newLines, new Set(insertedIds)]; }; exports.replaceBestPractices = replaceBestPractices; -const INSERT_START_RE = /^\s*$/; -const INSERT_END_RE = /^\s*$/; +/** + * Get the regexp to match insertion comments in a documentation file. + * + * .mdx files use jsx comments rather than html comments. + */ +const getInsertREs = (filename) => { + if (/\.mdx$/.test(filename)) { + return [MDX_INSERT_START_RE, MDX_INSERT_END_RE]; + } + return [MD_INSERT_START_RE, MD_INSERT_END_RE]; +}; +const MD_INSERT_START_RE = /^\s*$/; +const MD_INSERT_END_RE = /^\s*$/; +const MDX_INSERT_START_RE = /^\s*{\/\* @BestPractice.insert (\S+) \*\/}$/; +const MDX_INSERT_END_RE = /^\s*{\/\* @BestPractice.end \*\/}$/; From de7cd8e208a6158a236ca5ca0e9628e655478b2d Mon Sep 17 00:00:00 2001 From: Trey Cucco Date: Thu, 7 Sep 2023 11:49:13 -0600 Subject: [PATCH 3/3] 0.4.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 41c24b6..124f573 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@closeio/best-practices-documentation", - "version": "0.4.1", + "version": "0.4.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@closeio/best-practices-documentation", - "version": "0.4.1", + "version": "0.4.2", "license": "ISC", "dependencies": { "crypto-js": "^4.1.1" diff --git a/package.json b/package.json index 4516759..aee6818 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@closeio/best-practices-documentation", - "version": "0.4.1", + "version": "0.4.2", "description": "Tooling to document best practices in your code base.", "author": "Trey Cucco", "main": "index.js",