diff --git a/packages/remark-tight-comments/LICENSE b/packages/remark-tight-comments/LICENSE new file mode 100644 index 0000000..9580002 --- /dev/null +++ b/packages/remark-tight-comments/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Bernard Dickens + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/remark-tight-comments/README.md b/packages/remark-tight-comments/README.md new file mode 100644 index 0000000..71d4374 --- /dev/null +++ b/packages/remark-tight-comments/README.md @@ -0,0 +1,221 @@ + + + +[![Black Lives Matter!][badge-blm]][link-blm] +[![Maintenance status][badge-maintenance]][link-repo] +[![Last commit timestamp][badge-last-commit]][link-repo] +[![Open issues][badge-issues]][link-issues] +[![Pull requests][badge-pulls]][link-pulls] +[![Codecov][badge-codecov]][link-codecov] +[![Source license][badge-license]][link-license] +[![NPM version][badge-npm]][link-npm] +[![Uses Semantic Release!][badge-semantic-release]][link-semantic-release] + + + + +# remark-tight-comments + +This is a [unified][23] ([remark][24]) plugin that allows you to selectively +remove unnecessary newlines around Markdown comments. + +This plugin is useful for preserving the structure of auto-generated content, +e.g. [all-contributors][12], [doctoc][1], etc. You might also be interested in +[remark-ignore][26], which lets you instruct remark not to transform parts of +your Markdown documents. For a live example of these two plugins in action, +check the source of [this very README.md file][25]. ✨ + +--- + + + + + + +- [Install][3] +- [Usage][4] + - [Via API][13] + - [Via remark-cli][14] + - [Via unified configuration][15] +- [API][5] +- [Related][7] +- [Contributing and Support][8] + - [Contributors][9] + + + + + +## Install + +> Due to the nature of the unified ecosystem, this package is ESM only and +> cannot be `require`'d. + +```bash +npm install --save-dev remark-tight-comments +``` + +## Usage + +### Via API + +> See [mdast-util-tight-comments][27] for more details. + +```typescript +import { read } from 'to-vfile'; +import { remark } from 'remark'; +import remarkTightComments from 'remark-tight-comments'; + +const file = await remark() + .use(remarkTightComments) + .process(await read('example.md')); + +console.log(String(file)); +``` + + + +### Via [remark-cli](https://github.com/remarkjs/remark/tree/main/packages/remark-cli) + +```shell +remark -o --use tight-comments README.md +``` + + + +### Via [unified configuration](https://github.com/unifiedjs/unified-engine/blob/main/doc/configure.md) + +In `package.json`: + +```json + /* … */ + "remarkConfig": { + "plugins": [ + "remark-tight-comments" + /* … */ + ] + }, + /* … */ +``` + +In `.remarkrc.js`: + +```javascript +module.exports = { + plugins: [ + // … + 'tight-comments' + ] +}; +``` + +In `.remarkrc.mjs`: + +```javascript +import remarkTightComments from 'remark-tight-comments'; + +export default { + plugins: [ + // … + remarkTightComments + ] +}; +``` + +## API + +Detailed interface information can be found under [`docs/`][docs]. + +## Related + +- [remark-ignore][26] — use comments to exclude one or more nodes from + [transformation][28] +- [mdast-util-tight-comments][29] — selectively remove newlines around comment + nodes during serialization + +## Contributing and Support + +**[New issues][choose-new-issue] and [pull requests][pr-compare] are always +welcome and greatly appreciated! 🤩** Just as well, you can [star 🌟 this +project][link-repo] to let me know you found it useful! ✊🏿 Thank you! + +See [CONTRIBUTING.md][contributing] and [SUPPORT.md][support] for more +information. + +### Contributors + + + +[badge-blm]: https://xunn.at/badge-blm 'Join the movement!' +[link-blm]: https://xunn.at/donate-blm +[badge-maintenance]: + https://img.shields.io/maintenance/active/2022 + 'Is this package maintained?' +[link-repo]: + https://github.com/xunnamius/unified-utils/blob/main/packages/remark-tight-comments +[badge-last-commit]: + https://img.shields.io/github/last-commit/xunnamius/unified-utils + 'Latest commit timestamp' +[badge-issues]: + https://img.shields.io/github/issues/Xunnamius/unified-utils + 'Open issues' +[link-issues]: https://github.com/Xunnamius/unified-utils/issues?q= +[badge-pulls]: + https://img.shields.io/github/issues-pr/xunnamius/unified-utils + 'Open pull requests' +[link-pulls]: https://github.com/xunnamius/unified-utils/pulls +[badge-codecov]: + https://codecov.io/gh/Xunnamius/unified-utils/branch/main/graph/badge.svg?token=HWRIOBAAPW + 'Is this package well-tested?' +[link-codecov]: https://codecov.io/gh/Xunnamius/unified-utils +[badge-license]: + https://img.shields.io/npm/l/remark-tight-comments + "This package's source license" +[link-license]: + https://github.com/Xunnamius/unified-utils/blob/main/packages/remark-tight-comments/LICENSE +[badge-npm]: + https://api.ergodark.com/badges/npm-pkg-version/remark-tight-comments + 'Install this package using npm or yarn!' +[link-npm]: https://www.npmjs.com/package/remark-tight-comments +[badge-semantic-release]: + https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg + 'This repo practices continuous integration and deployment!' +[link-semantic-release]: https://github.com/semantic-release/semantic-release +[package-json]: package.json +[docs]: docs +[choose-new-issue]: https://github.com/xunnamius/unified-utils/issues/new/choose +[pr-compare]: https://github.com/xunnamius/unified-utils/compare +[contributing]: /CONTRIBUTING.md +[support]: /.github/SUPPORT.md +[1]: https://github.com/thlorenz/doctoc +[2]: #remark-tight-comments +[3]: #install +[4]: #usage +[5]: #api +[6]: #examples +[7]: #related +[8]: #contributing-and-support +[9]: #contributors +[10]: https://prettier.io/docs/en/ignore.html#javascript +[11]: https://github.com/unifiedjs/unified#processoruseplugin-options +[12]: https://github.com/all-contributors/all-contributors +[13]: #via-api +[14]: #via-remark-cli +[15]: #via-unified-configuration +[16]: https://github.com/remarkjs/remark/tree/main/packages/remark-cli +[17]: https://github.com/unifiedjs/unified-engine/blob/main/doc/configure.md +[18]: + https://github.com/zestedesavoir/zmarkdown/tree/HEAD/packages/remark-comments#readme +[19]: + https://github.com/zestedesavoir/zmarkdown/tree/HEAD/packages/remark-disable-tokenizers#readme +[20]: https://github.com/remarkjs/remark-message-control +[21]: https://github.com/syntax-tree/mdast-comment-marker +[22]: https://github.com/syntax-tree/mdast-zone +[23]: https://github.com/unifiedjs/unified +[24]: https://github.com/remarkjs/remark +[25]: + https://raw.githubusercontent.com/Xunnamius/unified-utils/main/packages/remark-tight-comments/README.md +[26]: /packages/remark-ignore +[27]: /packages/mdast-util-tight-comments/README.md#usage +[28]: https://github.com/unifiedjs/unified#overview +[29]: /packages/mdast-util-tight-comments diff --git a/packages/remark-tight-comments/package.json b/packages/remark-tight-comments/package.json new file mode 100644 index 0000000..15b2789 --- /dev/null +++ b/packages/remark-tight-comments/package.json @@ -0,0 +1,97 @@ +{ + "name": "remark-tight-comments", + "version": "0.0.0-semantic", + "description": "remark plugin to selectively remove newlines around comments", + "keywords": [ + "unified", + "mdast", + "remark", + "remark-plugin", + "plugin", + "markdown", + "comment", + "space", + "node", + "newline", + "remove", + "selective" + ], + "homepage": "https://github.com/Xunnamius/unified-utils/blob/main/packages/remark-tight-comments", + "repository": { + "type": "git", + "url": "https://github.com/Xunnamius/unified-utils" + }, + "license": "MIT", + "author": "Xunnamius", + "sideEffects": false, + "type": "commonjs", + "exports": { + "./start": { + "types": "./dist/start.d.ts", + "node": "./dist/start.mjs", + "default": "./dist/start.mjs" + }, + "./end": { + "types": "./dist/end.d.ts", + "node": "./dist/end.mjs", + "default": "./dist/end.mjs" + }, + ".": { + "types": "./dist/index.d.ts", + "node": "./dist/index.mjs", + "default": "./dist/index.mjs" + }, + "./package": "./package.json", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "start": [ + "./dist/start.d.ts" + ], + "end": [ + "./dist/end.d.ts" + ], + "*": [ + "./dist/index.d.ts" + ] + } + }, + "files": [ + "/dist", + "/LICENSE", + "/package.json", + "/README.md" + ], + "scripts": { + "build": "npm run build:dist --", + "build:changelog": "conventional-changelog --outfile CHANGELOG.md --config ../../conventional.config.js --release-count 0 --skip-unstable && (if [ \"$CHANGELOG_SKIP_TITLE\" != 'true' ]; then { node -e 'console.log(require(\"../../conventional.config.js\").changelogTitle)'; cat CHANGELOG.md; } > CHANGELOG.md.ignore && mv CHANGELOG.md.ignore CHANGELOG.md; fi) && NODE_ENV=format remark --output --frail CHANGELOG.md && prettier --write CHANGELOG.md", + "build:dist": "NODE_ENV=production tsc --project tsconfig.types.json --incremental false && tsconfig-replace-paths --project tsconfig.types.json && NODE_ENV=production-esm babel src --extensions .ts --out-dir dist --out-file-extension .mjs --root-mode upward", + "build:docs": "if [ -r ./next.config.js ]; then typedoc --plugin typedoc-plugin-markdown --tsconfig tsconfig.docs.json --out docs --readme none lib src test types external-scripts --exclude '**/*.test.*' --exclude external-scripts/bin; else ENTRY=`node -e 'const entry = require(\"./package.json\").config?.[\"plugin-build\"]?.docs?.entry; if(!entry) throw new Error(\"\\\"config['\"'\"'plugin-build'\"'\"'].docs.entry\\\" field is not defined in package.json\"); console.log(entry)'` && echo 'Entry file:' \"$ENTRY\" && typedoc --plugin typedoc-plugin-markdown --tsconfig tsconfig.docs.json --out docs --readme none $(echo $ENTRY) && find docs -name '*.md' -exec sed -i -e 's/Project: //g' {} + && sed -i -e 1,4d docs/README.md; fi && find docs -name '*.md' -exec sed -i -e 's/`__namedParameters`/`\\(destructured\\)`/g' {} + && find docs -name '*.md' -exec sed -i -E 's/`__namedParameters\\.([^`]+)`/`\\({ \\1 }\\)`/g' {} +", + "clean": "git ls-files --exclude-standard --ignored --others --directory | grep -vE '^((\\.(env|vscode|husky))|next-env\\.d\\.ts|node_modules)($|\\/)' | xargs -p rm -rf", + "format": "cd ../.. && npm run format", + "lint": "echo 'IMPLEMENT ME'", + "list-tasks": "node -e 'console.log(Object.keys(require(\"./package.json\").scripts).join(\"\\n\"))'", + "test": "npm run test:unit --", + "test:integration": "echo 'IMPLEMENT ME'", + "test:unit": "echo 'IMPLEMENT ME'" + }, + "config": { + "plugin-build": { + "docs": { + "entry": "./src/*" + } + } + }, + "dependencies": { + "mdast-comment-marker": "^2.1.0", + "mdast-util-hidden": "^1.0.0", + "unist-util-visit": "^4.1.1" + }, + "engines": { + "node": "^14.19.0 || ^16.13.0 || >=17.4.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/remark-tight-comments/src/index.ts b/packages/remark-tight-comments/src/index.ts new file mode 100644 index 0000000..608c618 --- /dev/null +++ b/packages/remark-tight-comments/src/index.ts @@ -0,0 +1,23 @@ +import { joinTightComments } from 'mdast-util-tight-comments'; + +import type { Plugin } from 'unified'; +import type { Root } from 'mdast'; + +/** + * A remark plugin that ensures tight spacing between HTML comments and select + * other mdast nodes under certain conditions. + */ +const remarkTightComments: Plugin = function () { + const data = this.data(); + + add('toMarkdownExtensions', joinTightComments()); + + function add(field: string, value: unknown) { + const list = // ? Be cognizant of other extensions + (data[field] ? data[field] : (data[field] = [])) as unknown[]; + + list.push(value); + } +}; + +export default remarkTightComments; diff --git a/packages/remark-tight-comments/test/fixtures/clean-transformed.md b/packages/remark-tight-comments/test/fixtures/clean-transformed.md new file mode 100644 index 0000000..280fdee --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/clean-transformed.md @@ -0,0 +1,15 @@ +# Some project + + + +[![Build][2]][1] + +## Section + +[A link][3] + +[Another link][3] + +[1]: https://github.com/remarkjs/remark-defsplit/actions +[2]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg +[3]: https://example.com diff --git a/packages/remark-tight-comments/test/fixtures/clean.md b/packages/remark-tight-comments/test/fixtures/clean.md new file mode 100644 index 0000000..280fdee --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/clean.md @@ -0,0 +1,15 @@ +# Some project + + + +[![Build][2]][1] + +## Section + +[A link][3] + +[Another link][3] + +[1]: https://github.com/remarkjs/remark-defsplit/actions +[2]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg +[3]: https://example.com diff --git a/packages/remark-tight-comments/test/fixtures/ignore-next-transformed.md b/packages/remark-tight-comments/test/fixtures/ignore-next-transformed.md new file mode 100644 index 0000000..eaf4cd5 --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/ignore-next-transformed.md @@ -0,0 +1,15 @@ +# Some project + + + +[![Build][3]][2] + +## Section + +[A link][1] + +[Another link][1] + +[1]: https://example.com +[2]: https://github.com/remarkjs/remark-defsplit/actions +[3]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg diff --git a/packages/remark-tight-comments/test/fixtures/ignore-next.md b/packages/remark-tight-comments/test/fixtures/ignore-next.md new file mode 100644 index 0000000..eaf4cd5 --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/ignore-next.md @@ -0,0 +1,15 @@ +# Some project + + + +[![Build][3]][2] + +## Section + +[A link][1] + +[Another link][1] + +[1]: https://example.com +[2]: https://github.com/remarkjs/remark-defsplit/actions +[3]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg diff --git a/packages/remark-tight-comments/test/fixtures/ignore-range-2-transformed.md b/packages/remark-tight-comments/test/fixtures/ignore-range-2-transformed.md new file mode 100644 index 0000000..046e442 --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/ignore-range-2-transformed.md @@ -0,0 +1,13 @@ +# Some project + +[![Build][3]][2] + +## Section + +[A link][1] + +[Another link][1] + +[1]: https://example.com +[2]: https://github.com/remarkjs/remark-defsplit/actions +[3]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg diff --git a/packages/remark-tight-comments/test/fixtures/ignore-range-2.md b/packages/remark-tight-comments/test/fixtures/ignore-range-2.md new file mode 100644 index 0000000..98d9baf --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/ignore-range-2.md @@ -0,0 +1,20 @@ + + +# Some project + +[![Build][3]][2] + + + +## Section + +[A link][1] + + + + +[Another link][1] + +[1]: https://example.com +[2]: https://github.com/remarkjs/remark-defsplit/actions +[3]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg diff --git a/packages/remark-tight-comments/test/fixtures/ignore-range-transformed.md b/packages/remark-tight-comments/test/fixtures/ignore-range-transformed.md new file mode 100644 index 0000000..65d9cd3 --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/ignore-range-transformed.md @@ -0,0 +1,17 @@ + + +# Some project + +[![Build][3]][2] + +## Section + +[A link][1] + + + +[Another link][1] + +[1]: https://example.com +[2]: https://github.com/remarkjs/remark-defsplit/actions +[3]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg diff --git a/packages/remark-tight-comments/test/fixtures/ignore-range.md b/packages/remark-tight-comments/test/fixtures/ignore-range.md new file mode 100644 index 0000000..65d9cd3 --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/ignore-range.md @@ -0,0 +1,17 @@ + + +# Some project + +[![Build][3]][2] + +## Section + +[A link][1] + + + +[Another link][1] + +[1]: https://example.com +[2]: https://github.com/remarkjs/remark-defsplit/actions +[3]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg diff --git a/packages/remark-tight-comments/test/fixtures/orphan-transformed.md b/packages/remark-tight-comments/test/fixtures/orphan-transformed.md new file mode 100644 index 0000000..05db5c7 --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/orphan-transformed.md @@ -0,0 +1,15 @@ +# Some project + +[![Build][2]][1] + +## Section + + + +[A link][3] + +[Another link][3] + +[1]: https://github.com/remarkjs/remark-defsplit/actions +[2]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg +[3]: https://example.com diff --git a/packages/remark-tight-comments/test/fixtures/orphan.md b/packages/remark-tight-comments/test/fixtures/orphan.md new file mode 100644 index 0000000..05db5c7 --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/orphan.md @@ -0,0 +1,15 @@ +# Some project + +[![Build][2]][1] + +## Section + + + +[A link][3] + +[Another link][3] + +[1]: https://github.com/remarkjs/remark-defsplit/actions +[2]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg +[3]: https://example.com diff --git a/packages/remark-tight-comments/test/fixtures/redundant-transformed.md b/packages/remark-tight-comments/test/fixtures/redundant-transformed.md new file mode 100644 index 0000000..32a3ef2 --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/redundant-transformed.md @@ -0,0 +1,21 @@ +# Some project + + + + +[![Build][3]][2] + +## Section + + + + +[A link][1] + + + +[Another link][1] + +[1]: https://example.com +[2]: https://github.com/remarkjs/remark-defsplit/actions +[3]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg diff --git a/packages/remark-tight-comments/test/fixtures/redundant.md b/packages/remark-tight-comments/test/fixtures/redundant.md new file mode 100644 index 0000000..32a3ef2 --- /dev/null +++ b/packages/remark-tight-comments/test/fixtures/redundant.md @@ -0,0 +1,21 @@ +# Some project + + + + +[![Build][3]][2] + +## Section + + + + +[A link][1] + + + +[Another link][1] + +[1]: https://example.com +[2]: https://github.com/remarkjs/remark-defsplit/actions +[3]: https://github.com/remarkjs/remark-defsplit/workflows/main/badge.svg diff --git a/packages/remark-tight-comments/test/helpers.ts b/packages/remark-tight-comments/test/helpers.ts new file mode 100644 index 0000000..5a70829 --- /dev/null +++ b/packages/remark-tight-comments/test/helpers.ts @@ -0,0 +1,12 @@ +import { readFileSync as readToString } from 'fs'; +import { read as readToVFile } from 'to-vfile'; + +export function getFixtureVFile(fixture: string) { + return readToVFile(`${__dirname}/fixtures/${fixture}.md`); +} + +export function getFixtureString(fixture: string, { trim = true } = {}) { + return readToString(`${__dirname}/fixtures/${fixture}.md`, 'utf8')[ + trim ? 'trim' : 'toString' + ](); +} diff --git a/packages/remark-tight-comments/test/integration-node.test.ts b/packages/remark-tight-comments/test/integration-node.test.ts new file mode 100644 index 0000000..7e98dd7 --- /dev/null +++ b/packages/remark-tight-comments/test/integration-node.test.ts @@ -0,0 +1,348 @@ +import { debugFactory } from 'multiverse/debug-extended'; +import { run } from 'multiverse/run'; +import { getFixtureString } from 'pkgverse/remark-tight-comments/test/helpers'; + +import { + mockFixtureFactory, + dummyFilesFixture, + dummyNpmPackageFixture, + npmCopySelfFixture, + nodeImportTestFixture, + MockFixture +} from 'testverse/setup'; + +import { name as pkgName, exports as pkgExports } from '../package.json'; + +import type { FixtureOptions } from 'testverse/setup'; + +const TEST_IDENTIFIER = 'integration-node'; +const debug = debugFactory(`${pkgName}:${TEST_IDENTIFIER}`); +const nodeVersion = process.env.MATRIX_NODE_VERSION || process.version; + +const pkgMainPaths = Object.values(pkgExports) + .map((xport) => (typeof xport == 'string' ? null : `${__dirname}/../${xport.node}`)) + .filter(Boolean) as string[]; + +// eslint-disable-next-line jest/require-hook +debug('pkgMainPaths: %O', pkgMainPaths); +// eslint-disable-next-line jest/require-hook +debug(`nodeVersion: "${nodeVersion}"`); + +const fixtureOptions = { + performCleanup: true, + pkgRoot: `${__dirname}/..`, + pkgName, + initialFileContents: {} as FixtureOptions['initialFileContents'], + use: [ + dummyNpmPackageFixture(), + dummyFilesFixture(), + npmCopySelfFixture(), + runTestFixture() + ], + npmInstall: ['remark', 'remark-cli', 'remark-remove-comments', 'remark-reference-links'] +} as Partial & { + initialFileContents: FixtureOptions['initialFileContents']; +}; + +const withMockedFixture = mockFixtureFactory(TEST_IDENTIFIER, fixtureOptions); + +// TODO: note that we've made some modifications to the setup.ts file that +// TODO: should be propagated! +function runTestFixture(): MockFixture { + return { + name: 'run-test', + description: 'running CLI command for jest integration test', + setup: async (ctx) => { + const bin = ctx.options.runWith?.binary; + + if (!bin) throw new Error('could not find runWith binary (required)'); + + const args = ctx.options.runWith?.args || []; + const opts = ctx.options.runWith?.opts || {}; + + const { code, stdout, stderr } = await run(bin, args, { + cwd: ctx.root, + ...opts + }); + + ctx.testResult = { + code, + stdout, + stderr + }; + } + }; +} + +beforeAll(async () => { + await Promise.all( + pkgMainPaths.map(async (pkgMainPath) => { + if ((await run('test', ['-e', pkgMainPath])).code != 0) { + debug(`unable to find main distributable: ${pkgMainPath}`); + throw new Error('must build distributables first (try `npm run build:dist`)'); + } + }) + ); +}); + +describe('via api', () => { + it('works as an ESM import', async () => { + expect.hasAssertions(); + + const initialFileContents = ` + import { deepStrictEqual } from 'assert'; + import { remark } from 'remark'; + import remarkReferenceLinks from 'remark-reference-links'; + import remarkIgnore, { ignoreStart, ignoreEnd } from 'remark-tight-comments'; + import defaultIgnoreStart from 'remark-tight-comments/start'; + import defaultIgnoreEnd from 'remark-tight-comments/end'; + + const mdIgnoreNext = ${JSON.stringify( + getFixtureString('ignore-next', { trim: false }) + )}; + + const mdIgnoreNextTransformed = ${JSON.stringify( + getFixtureString('ignore-next-transformed', { trim: false }) + )}; + + const result1 = await remark() + .use(remarkIgnore) + .use(remarkReferenceLinks) + .process(mdIgnoreNext); + + const result2 = await remark() + .use(ignoreStart) + .use(remarkReferenceLinks) + .use(ignoreEnd) + .process(mdIgnoreNext); + + const result3 = await remark() + .use(defaultIgnoreStart) + .use(remarkReferenceLinks) + .use(defaultIgnoreEnd) + .process(mdIgnoreNext); + + deepStrictEqual(result1.toString(), mdIgnoreNextTransformed); + deepStrictEqual(result2.toString(), mdIgnoreNextTransformed); + deepStrictEqual(result3.toString(), mdIgnoreNextTransformed); + + console.log('success'); + `; + + await withMockedFixture( + async (ctx) => { + if (!ctx.testResult) throw new Error('must use node-import-test fixture'); + expect(ctx.testResult?.stderr).toBeEmpty(); + expect(ctx.testResult?.stdout).toBe('success'); + expect(ctx.testResult?.code).toBe(0); + }, + { + initialFileContents: { 'src/index.mjs': initialFileContents }, + use: [ + dummyNpmPackageFixture(), + dummyFilesFixture(), + npmCopySelfFixture(), + nodeImportTestFixture() + ] + } + ); + }); +}); + +describe('via remark-cli inline configuration', () => { + it('works with --use option using default syntax', async () => { + expect.hasAssertions(); + + await withMockedFixture( + async (ctx) => { + if (!ctx.testResult) throw new Error('must use run-test-test fixture'); + expect(ctx.testResult?.stderr).toMatch(/^.*README\.md.*: no issues found$/); + expect(ctx.testResult?.stdout).toBe(getFixtureString('ignore-range-transformed')); + expect(ctx.testResult?.code).toBe(0); + }, + { + initialFileContents: { 'README.md': getFixtureString('ignore-range') }, + runWith: { + binary: 'npx', + args: [ + '--no-install', + 'remark', + '--use', + 'remark-tight-comments', + '--use', + 'remark-reference-links', + 'README.md' + ] + } + } + ); + }); + + it('works with --use option using alternative syntax', async () => { + expect.hasAssertions(); + + await withMockedFixture( + async (ctx) => { + if (!ctx.testResult) throw new Error('must use run-test-test fixture'); + expect(ctx.testResult?.stderr).toMatch(/^.*README\.md.*: no issues found$/); + expect(ctx.testResult?.stdout).toBe( + getFixtureString('ignore-range-2-transformed') + ); + expect(ctx.testResult?.code).toBe(0); + }, + { + initialFileContents: { 'README.md': getFixtureString('ignore-range-2') }, + runWith: { + binary: 'npx', + args: [ + '--no-install', + 'remark', + '--use', + 'ignore/start', + '--use', + 'reference-links', + '--use', + 'ignore/end', + '--use', + 'remove-comments', + 'README.md' + ] + } + } + ); + }); +}); + +describe('via remark-cli unified configuration', () => { + it('works with package.json using default syntax (short-string)', async () => { + expect.hasAssertions(); + + await withMockedFixture( + async (ctx) => { + if (!ctx.testResult) throw new Error('must use run-test-test fixture'); + expect(ctx.testResult?.stderr).toMatch(/^.*README\.md.*: no issues found$/); + expect(ctx.testResult?.stdout).toBe(getFixtureString('ignore-range-transformed')); + expect(ctx.testResult?.code).toBe(0); + }, + { + initialFileContents: { + 'README.md': getFixtureString('ignore-range'), + 'package.json': JSON.stringify({ + name: 'dummy-pkg', + remarkConfig: { plugins: ['ignore', 'reference-links'] } + }) + }, + runWith: { + binary: 'npx', + args: ['--no-install', 'remark', 'README.md'] + } + } + ); + }); + + it('works with package.json using default syntax (string)', async () => { + expect.hasAssertions(); + + await withMockedFixture( + async (ctx) => { + if (!ctx.testResult) throw new Error('must use run-test-test fixture'); + expect(ctx.testResult?.stderr).toMatch(/^.*README\.md.*: no issues found$/); + expect(ctx.testResult?.stdout).toBe(getFixtureString('ignore-range-transformed')); + expect(ctx.testResult?.code).toBe(0); + }, + { + initialFileContents: { + 'README.md': getFixtureString('ignore-range'), + 'package.json': JSON.stringify({ + name: 'dummy-pkg', + remarkConfig: { plugins: ['remark-tight-comments', 'remark-reference-links'] } + }) + }, + runWith: { + binary: 'npx', + args: ['--no-install', 'remark', 'README.md'] + } + } + ); + }); + + it('works with .remarkrc.js using alternative syntax (strings)', async () => { + expect.hasAssertions(); + + await withMockedFixture( + async (ctx) => { + if (!ctx.testResult) throw new Error('must use run-test-test fixture'); + expect(ctx.testResult?.stderr).toMatch(/^.*README\.md.*: no issues found$/); + expect(ctx.testResult?.stdout).toBe( + getFixtureString('ignore-range-2-transformed') + ); + expect(ctx.testResult?.code).toBe(0); + }, + { + initialFileContents: { + 'README.md': getFixtureString('ignore-range-2'), + '.remarkrc.js': ` + module.exports = { + plugins: [ + 'remark-tight-comments/start', + 'remark-reference-links', + 'remark-tight-comments/end', + 'remark-remove-comments' + ] + }; + ` + }, + runWith: { + binary: 'npx', + args: ['--no-install', 'remark', 'README.md'] + } + } + ); + }); + + it('works with .remarkrc.mjs using alternative syntax (short-string, function)', async () => { + expect.hasAssertions(); + + await withMockedFixture( + async (ctx) => { + if (!ctx.testResult) throw new Error('must use run-test-test fixture'); + expect(ctx.testResult?.stderr).toMatch(/^.*README\.md.*: no issues found$/); + expect(ctx.testResult?.stdout).toBe( + getFixtureString('ignore-range-2-transformed') + ); + expect(ctx.testResult?.code).toBe(0); + }, + { + initialFileContents: { + 'README.md': getFixtureString('ignore-range-2'), + '.remarkrc.mjs': ` + import { ignoreStart } from 'remark-tight-comments'; + export default { + plugins: [ + ignoreStart, + 'reference-links', + 'ignore/end', + 'remove-comments' + ] + }; + ` + }, + runWith: { + binary: 'npx', + args: ['--no-install', 'remark', 'README.md'] + } + } + ); + }); +}); + +// ? There is no CJS distributable for this package +// eslint-disable-next-line jest/no-commented-out-tests +/* it('works as a CJS require(...)', async () => { + expect.hasAssertions(); + await runTest(false, async (ctx) => { + expect(ctx.testResult?.stderr).toMatch(/^.*README\.md.*: no issues found$/); + expect(ctx.testResult?.stdout).toBe('success'); + expect(ctx.testResult?.code).toBe(0); + }); +}); */ diff --git a/packages/remark-tight-comments/test/unit-index.test.ts b/packages/remark-tight-comments/test/unit-index.test.ts new file mode 100644 index 0000000..4bf355d --- /dev/null +++ b/packages/remark-tight-comments/test/unit-index.test.ts @@ -0,0 +1,99 @@ +import { remark } from 'remark'; +import remarkReferenceLinks from 'remark-reference-links'; +import remarkRemoveComments from 'remark-remove-comments'; + +import remarkIgnore, { + ignoreStart, + ignoreEnd +} from 'pkgverse/remark-tight-comments/src/index'; +import defaultIgnoreStart from 'pkgverse/remark-tight-comments/src/start'; +import defaultIgnoreEnd from 'pkgverse/remark-tight-comments/src/end'; +import { + getFixtureString, + getFixtureVFile +} from 'pkgverse/remark-tight-comments/test/helpers'; + +describe('::default', () => { + it('is no-op without ignore commands', async () => { + expect.hasAssertions(); + + const result = await remark() + .use(remarkIgnore) + .use(remarkReferenceLinks) + .process(await getFixtureVFile('clean')); + + expect(result.toString()).toStrictEqual(getFixtureString('clean-transformed')); + }); + + it('ignores the next node via remark-tight-comments', async () => { + expect.hasAssertions(); + + const result = await remark() + .use(remarkIgnore) + .use(remarkReferenceLinks) + .process(await getFixtureVFile('ignore-next')); + + expect(result.toString()).toStrictEqual(getFixtureString('ignore-next-transformed')); + }); + + it('ignores a range of nodes via remark-tight-comments-start/end', async () => { + expect.hasAssertions(); + + const result = await remark() + .use(remarkIgnore) + .use(remarkReferenceLinks) + .process(await getFixtureVFile('ignore-range')); + + expect(result.toString()).toStrictEqual(getFixtureString('ignore-range-transformed')); + }); + + it('does not malfunction on orphan remark-tight-comments-end', async () => { + expect.hasAssertions(); + + const result = await remark() + .use(remarkIgnore) + .use(remarkReferenceLinks) + .process(await getFixtureVFile('orphan')); + + expect(result.toString()).toStrictEqual(getFixtureString('orphan-transformed')); + }); + + it('does not malfunction on redundant remark-tight-comments', async () => { + expect.hasAssertions(); + + const result = await remark() + .use(remarkIgnore) + .use(remarkReferenceLinks) + .process(await getFixtureVFile('redundant')); + + expect(result.toString()).toStrictEqual(getFixtureString('redundant-transformed')); + }); +}); + +describe('::ignoreStart & ::ignoreEnd', () => { + it('only disables transforms that occur between ignoreStart and ignoreEnd', async () => { + expect.hasAssertions(); + + const result = await remark() + .use(ignoreStart) + .use(remarkReferenceLinks) + .use(ignoreEnd) + .use(remarkRemoveComments) + .process(await getFixtureVFile('ignore-range-2')); + + expect(result.toString()).toStrictEqual( + getFixtureString('ignore-range-2-transformed') + ); + + const result2 = await remark() + .use(defaultIgnoreStart) + .use(remarkReferenceLinks) + .use(defaultIgnoreEnd) + .use(remarkRemoveComments) + .process(await getFixtureVFile('ignore-range-2')); + + expect(result2.toString()).toStrictEqual( + getFixtureString('ignore-range-2-transformed') + ); + }); +}); diff --git a/packages/remark-tight-comments/tsconfig.docs.json b/packages/remark-tight-comments/tsconfig.docs.json new file mode 100644 index 0000000..07dd331 --- /dev/null +++ b/packages/remark-tight-comments/tsconfig.docs.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["../../types/**/*", "src/**/*"] +} diff --git a/packages/remark-tight-comments/tsconfig.lint.json b/packages/remark-tight-comments/tsconfig.lint.json new file mode 100644 index 0000000..07dd331 --- /dev/null +++ b/packages/remark-tight-comments/tsconfig.lint.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["../../types/**/*", "src/**/*"] +} diff --git a/packages/remark-tight-comments/tsconfig.types.json b/packages/remark-tight-comments/tsconfig.types.json new file mode 100644 index 0000000..c5793eb --- /dev/null +++ b/packages/remark-tight-comments/tsconfig.types.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "allowJs": false, + "declaration": true, + "emitDeclarationOnly": true, + "isolatedModules": false, + "noEmit": false, + "outDir": "dist", + "rootDir": "./src" + }, + "extends": "../../tsconfig.json", + "include": ["../../types/**/*", "src/**/*"] +}