Skip to content

Commit 56ab0ff

Browse files
committed
feat(remark-lint): add
1 parent 23cb0b1 commit 56ab0ff

30 files changed

+1321
-137
lines changed

.github/workflows/publish-packages.yml

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,25 @@ jobs:
7272
# If a specific package is requested via workflow_dispatch, just publish that one
7373
echo "matrix={\"package\":[\"$PACKAGE\"]}" >> $GITHUB_OUTPUT
7474
else
75-
# Otherwise, identify all packages with changes since the last commit
7675
CHANGED_PACKAGES=()
7776
for pkg in $(ls -d packages/*); do
7877
PKG_NAME=$(basename "$pkg")
79-
# For manual runs, include all packages. For automatic runs, only include packages with changes
78+
PKG_JSON="$pkg/package.json"
79+
80+
# Determine if the package has changed (or include all on manual trigger)
8081
if [ "$EVENT_NAME" == "workflow_dispatch" ] || ! git diff --quiet $COMMIT_SHA~1 $COMMIT_SHA -- "$pkg/"; then
81-
CHANGED_PACKAGES+=("$PKG_NAME")
82+
HAS_VERSION=$(jq 'has("version")' "$PKG_JSON")
83+
if [ "$HAS_VERSION" == "false" ]; then
84+
# Include packages without version field
85+
CHANGED_PACKAGES+=("$PKG_NAME")
86+
else
87+
# For packages with version field, include only if version changed
88+
OLD_VERSION=$(git show $COMMIT_SHA~1:$PKG_JSON | jq -r '.version')
89+
NEW_VERSION=$(jq -r '.version' "$PKG_JSON")
90+
if [ "$OLD_VERSION" != "$NEW_VERSION" ]; then
91+
CHANGED_PACKAGES+=("$PKG_NAME")
92+
fi
93+
fi
8294
fi
8395
done
8496
@@ -120,8 +132,12 @@ jobs:
120132
run: |
121133
# Install deps
122134
pnpm install --frozen-lockfile
123-
# Create a unique version using the commit SHA as a prerelease identifier
124-
npm version --no-git-tag-version 1.0.1-$COMMIT_SHA
135+
136+
HAS_VERSION=$(jq 'has("version")' package.json)
137+
if [ "$HAS_VERSION" == "false" ]; then
138+
# Only bump version if package has no version field
139+
npm version --no-git-tag-version 1.0.1-$COMMIT_SHA
140+
fi
125141
126142
# Check if a custom publish script exists in package.json
127143
if jq -e '.scripts.publish' package.json > /dev/null; then

apps/site/.remarkrc.json

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,3 @@
11
{
2-
"settings": {
3-
"bullet": "-",
4-
"resourceLink": true
5-
},
6-
"plugins": [
7-
"remark-frontmatter",
8-
"remark-preset-lint-node",
9-
["remark-gfm", false],
10-
["remark-lint-fenced-code-flag", false],
11-
["remark-lint-first-heading-level", false],
12-
["remark-lint-maximum-line-length", false],
13-
["remark-lint-no-file-name-articles", false],
14-
["remark-lint-no-literal-urls", false],
15-
["remark-lint-no-unused-definitions", false],
16-
["remark-lint-no-undefined-references", false],
17-
["remark-lint-prohibited-strings", false],
18-
["remark-lint-unordered-list-marker-style", "-"],
19-
["remark-preset-lint-node/remark-lint-nodejs-links.js", false]
20-
]
2+
"plugins": ["remark-frontmatter", "@node-core/remark-lint"]
213
}

apps/site/package.json

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"@eslint/eslintrc": "~3.3.1",
8383
"@flarelabs-net/wrangler-build-time-fs-assets-polyfilling": "^0.0.1",
8484
"@next/eslint-plugin-next": "15.4.4",
85+
"@node-core/remark-lint": "workspace:*",
8586
"@opennextjs/cloudflare": "^1.6.2",
8687
"@playwright/test": "^1.54.1",
8788
"@testing-library/user-event": "~14.6.1",
@@ -95,17 +96,7 @@
9596
"global-jsdom": "^26.0.0",
9697
"handlebars": "4.7.8",
9798
"jsdom": "^26.0.0",
98-
"remark-frontmatter": "5.0.0",
99-
"remark-lint-fenced-code-flag": "^4.2.0",
100-
"remark-lint-first-heading-level": "^4.0.1",
101-
"remark-lint-maximum-line-length": "^4.1.1",
102-
"remark-lint-no-file-name-articles": "^3.0.1",
103-
"remark-lint-no-literal-urls": "^4.0.1",
104-
"remark-lint-no-undefined-references": "^5.0.2",
105-
"remark-lint-no-unused-definitions": "^4.0.2",
106-
"remark-lint-prohibited-strings": "^4.0.0",
107-
"remark-lint-unordered-list-marker-style": "^4.0.1",
108-
"remark-preset-lint-node": "5.1.2",
99+
"remark-frontmatter": "^5.0.0",
109100
"stylelint": "16.23.0",
110101
"stylelint-config-standard": "39.0.0",
111102
"stylelint-order": "7.0.0",

apps/site/pages/en/learn/modules/publishing-a-package.mdx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ authors: JakobJingleheimer
66

77
# Publishing a package
88

9-
All the provided `package.json` configurations (not specifically marked “does not work”) work in Node.js 12.22.x (v12 latest, the oldest supported line) and 17.2.0 (current latest at the time)[^1], and for grins, with webpack 5.53.0 and 5.63.0 respectively. These are available: [JakobJingleheimer/nodejs-module-config-examples](https://github.com/JakobJingleheimer/nodejs-module-config-examples).
9+
All the provided `package.json` configurations (not specifically marked “does not work”) work in Node.js 12.22.x (v12 latest, the oldest supported line) and 17.2.0 (current latest at the time)\[^1], and for grins, with webpack 5.53.0 and 5.63.0 respectively. These are available: [JakobJingleheimer/nodejs-module-config-examples](https://github.com/JakobJingleheimer/nodejs-module-config-examples).
1010

1111
For curious cats, [How did we get here](#how-did-we-get-here) and [Down the rabbit-hole](#down-the-rabbit-hole) provide background and deeper explanations.
1212

@@ -36,19 +36,23 @@ There are other options available, mostly for historical purposes.
3636
<td>ESM: consumers <code>import</code> your package</td>
3737
<td><a href="#cjs-source-and-only-esm-distribution">CJS source and only ESM distribution</a></td>
3838
</tr>
39+
3940
<tr>
4041
<td>CJS & ESM: consumers either <code>require()</code> or <code>import</code> your package</td>
4142
<td><a href="#cjs-source-and-both-cjs-amp-esm-distribution">CJS source and both CJS & ESM distribution</a></td>
4243
</tr>
44+
4345
<tr>
4446
<td rowSpan="2">ESM source code using <code>import</code></td>
4547
<td>CJS: consumers <code>require()</code> your package (and you use top-level <code>await</code>)</td>
4648
<td><a href="#esm-source-with-only-cjs-distribution">ESM source with only CJS distribution</a></td>
4749
</tr>
50+
4851
<tr>
4952
<td>CJS & ESM: consumers either <code>require()</code> or <code>import</code> your package</td>
5053
<td><a href="#esm-source-and-both-cjs-amp-esm-distribution">ESM source and both CJS & ESM distribution</a></td>
5154
</tr>
55+
5256
</tbody>
5357
</table>
5458

@@ -333,7 +337,7 @@ We're not in Kansas anymore, Toto.
333337

334338
The configurations (there are 2 options) are nearly the same as [ESM source and both CJS & ESM distribution](#esm-source-and-both-cjs-amp-esm-distribution), just exclude `packageJson.exports.import`.
335339

336-
💡 Using `"type": "module"`[^2] paired with the `.cjs` file extension (for commonjs files) yields best results. For more information on why, see [Down the rabbit-hole](#down-the-rabbit-hole) and [Gotchas](#gotchas) below.
340+
💡 Using `"type": "module"`\[^2] paired with the `.cjs` file extension (for commonjs files) yields best results. For more information on why, see [Down the rabbit-hole](#down-the-rabbit-hole) and [Gotchas](#gotchas) below.
337341

338342
**Working example**: [esm-with-cjs-distro](https://github.com/JakobJingleheimer/nodejs-module-config-examples/tree/main/packages/esm/cjs-distro)
339343

@@ -382,7 +386,7 @@ If your files explicitly _all_ use `.cjs` and/or `.mjs` file extensions (none us
382386
}
383387
```
384388

385-
💡 Using `"type": "module"`[^2] paired with the `.cjs` file extension (for commonjs files) yields best results. For more information on why, see [Down the rabbit-hole](#down-the-rabbit-hole) and [Gotchas](#gotchas) below.
389+
💡 Using `"type": "module"`\[^2] paired with the `.cjs` file extension (for commonjs files) yields best results. For more information on why, see [Down the rabbit-hole](#down-the-rabbit-hole) and [Gotchas](#gotchas) below.
386390

387391
#### Publish a CJS distribution with an ESM wrapper
388392

@@ -422,7 +426,7 @@ This is also almost identical to the [CJS source and dual distribution using an
422426
}
423427
```
424428

425-
💡 Using `"type": "module"`[^2] paired with the `.cjs` file extension (for commonjs files) yields best results. For more information on why, see [Down the rabbit-hole](#down-the-rabbit-hole) and [Gotchas](#gotchas) below.
429+
💡 Using `"type": "module"`\[^2] paired with the `.cjs` file extension (for commonjs files) yields best results. For more information on why, see [Down the rabbit-hole](#down-the-rabbit-hole) and [Gotchas](#gotchas) below.
426430

427431
#### Publish both full CJS & ESM distributions
428432

@@ -494,7 +498,7 @@ Alternatively, you can use `"default"` and `"node"` keys, which are less counter
494498
}
495499
```
496500

497-
💡 Using `"type": "module"`[^2] paired with the `.cjs` file extension (for commonjs files) yields best results. For more information on why, see [Down the rabbit-hole](#down-the-rabbit-hole) and [Gotchas](#gotchas) below.
501+
💡 Using `"type": "module"`\[^2] paired with the `.cjs` file extension (for commonjs files) yields best results. For more information on why, see [Down the rabbit-hole](#down-the-rabbit-hole) and [Gotchas](#gotchas) below.
498502

499503
##### Use the `.mjs` (or equivalent) file extension for all source code files
500504

@@ -523,9 +527,11 @@ The `"engines"` field provides both a human-friendly and a machine-friendly indi
523527
Specifically in relation to Node.js, there are 4 problems to solve:
524528

525529
- Determining format of source code files (author running their own code)
530+
526531
- Determining format of distribution files (code consumers will receive)
527532

528533
- Publicising distribution code for when it is `require()`’d (consumer expects CJS)
534+
529535
- Publicising distribution code for when it is `import`’d (consumer probably wants ESM)
530536

531537
⚠️ The first 2 are **independent** of the last 2.
@@ -592,6 +598,6 @@ Excluding `"type": "module"` produces the opposite problem:
592598

593599
This does not work because `packageJson.exports["."].import` will get interpreted as CJS (but it’s actually ESM).
594600

595-
[^1]: There was a bug in Node.js v13.0–13.6 where `packageJson.exports["."]` had to be an array with verbose config options as the first item (as an object) and the “default” as the second item (as a string). See [nodejs/modules#446](https://github.com/nodejs/modules/issues/446).
601+
\[^1]: There was a bug in Node.js v13.0–13.6 where `packageJson.exports["."]` had to be an array with verbose config options as the first item (as an object) and the “default” as the second item (as a string). See [nodejs/modules#446](https://github.com/nodejs/modules/issues/446).
596602

597-
[^2]: The `"type"` field in package.json changes what the `.js` file extension means, similar to to an [HTML script element’s type attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type).
603+
\[^2]: The `"type"` field in package.json changes what the `.js` file extension means, similar to to an [HTML script element’s type attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type).

apps/site/pages/fr/about/security-reporting.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,4 @@ Si vous avez des suggestions sur la façon dont ce processus pourrait être amé
8585
/>
8686
</a>
8787

88-
Le [badge des meilleures pratiques] de l'Open Source Security Foundation (OpenSSF) (https://github.com/coreinfrastructure/best-practices-badge) est un moyen pour les projets de logiciels libres et open source (FLOSS) de montrer qu'ils suivent les meilleures pratiques. Les projets peuvent volontairement auto-certifier la manière dont ils suivent chaque meilleure pratique. Les utilisateurs du badge peuvent rapidement déterminer quels sont les projets FLOSS qui suivent les meilleures pratiques et qui sont donc plus susceptibles de produire des logiciels sécurisés de meilleure qualité.
88+
Le \[badge des meilleures pratiques] de l'Open Source Security Foundation (OpenSSF) (https://github.com/coreinfrastructure/best-practices-badge) est un moyen pour les projets de logiciels libres et open source (FLOSS) de montrer qu'ils suivent les meilleures pratiques. Les projets peuvent volontairement auto-certifier la manière dont ils suivent chaque meilleure pratique. Les utilisateurs du badge peuvent rapidement déterminer quels sont les projets FLOSS qui suivent les meilleures pratiques et qui sont donc plus susceptibles de produire des logiciels sécurisés de meilleure qualité.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"**/*.{js,mjs,ts,tsx,md,mdx}": ["prettier --check --write", "eslint --fix"],
3+
"**/*.{json,yml}": ["prettier --check --write"]
4+
}

packages/remark-lint/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# `@node-core/remark-lint`
2+
3+
A [`remark-lint`](https://github.com/remarkjs/remark-lint) plugin with configurations tailored to the documentation and contribution standards of the [Node.js GitHub Organization](https://github.com/nodejs).
4+
5+
## Installation
6+
7+
```bash
8+
npm install --save-dev @node-core/remark-lint
9+
```
10+
11+
## Usage
12+
13+
Add the plugin to your `.remarkrc` or `remark.config.js`:
14+
15+
```json
16+
{
17+
"plugins": ["@node-core/remark-lint"]
18+
}
19+
```
20+
21+
You can then run `remark` over your markdown files:
22+
23+
```bash
24+
npx remark . --frail
25+
```
26+
27+
## Settings
28+
29+
### `NODE_RELEASED_VERSIONS`
30+
31+
Some lint rules (such as `node-core:yaml-comments`) require knowledge of released Node.js versions to validate version references.
32+
33+
You can provide these using the `NODE_RELEASED_VERSIONS` environment variable:
34+
35+
```bash
36+
NODE_RELEASED_VERSIONS=20.12.0,18.19.1,16.20.2 npx remark .
37+
```
38+
39+
If not set, version-related rules will accept any valid SemVer.

packages/remark-lint/eslint.config.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import globals from 'globals';
2+
3+
import baseConfig from '../../eslint.config.js';
4+
5+
export default [
6+
...baseConfig,
7+
{
8+
languageOptions: {
9+
globals: globals.nodeBuiltin,
10+
parserOptions: {
11+
// Allow nullish syntax (i.e. "?." or "??"),
12+
// and top-level await
13+
ecmaVersion: 'latest',
14+
},
15+
},
16+
},
17+
];

packages/remark-lint/package.json

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"name": "@node-core/remark-lint",
3+
"type": "module",
4+
"version": "1.0.0",
5+
"exports": {
6+
".": "./src/index.mjs",
7+
"./api": "./src/api.mjs"
8+
},
9+
"scripts": {
10+
"lint": "node --run lint:js",
11+
"lint:fix": "node --run lint:js:fix",
12+
"lint:js": "eslint \"**/*.mjs\"",
13+
"lint:js:fix": "node --run lint:js -- --fix",
14+
"test": "node --run test:unit",
15+
"test:unit": "cross-env NODE_NO_WARNINGS=1 node --experimental-test-coverage --test \"**/*.test.mjs\""
16+
},
17+
"dependencies": {
18+
"remark-gfm": "~4.0.1",
19+
"remark-lint-blockquote-indentation": "^4.0.1",
20+
"remark-lint-checkbox-character-style": "^5.0.1",
21+
"remark-lint-checkbox-content-indent": "^5.0.1",
22+
"remark-lint-code-block-style": "^4.0.1",
23+
"remark-lint-definition-spacing": "^4.0.1",
24+
"remark-lint-fenced-code-flag": "^4.2.0",
25+
"remark-lint-fenced-code-marker": "^4.0.1",
26+
"remark-lint-file-extension": "^3.0.1",
27+
"remark-lint-final-definition": "^4.0.2",
28+
"remark-lint-heading-style": "^4.0.1",
29+
"remark-lint-maximum-line-length": "^4.1.1",
30+
"remark-lint-no-consecutive-blank-lines": "^5.0.1",
31+
"remark-lint-no-file-name-consecutive-dashes": "^3.0.1",
32+
"remark-lint-no-file-name-outer-dashes": "^3.0.1",
33+
"remark-lint-no-heading-indent": "^5.0.1",
34+
"remark-lint-no-literal-urls": "^4.0.1",
35+
"remark-lint-no-multiple-toplevel-headings": "^4.0.1",
36+
"remark-lint-no-shell-dollars": "^4.0.1",
37+
"remark-lint-no-table-indentation": "^5.0.1",
38+
"remark-lint-no-tabs": "^4.0.1",
39+
"remark-lint-no-trailing-spaces": "^3.0.2",
40+
"remark-lint-no-unused-definitions": "^4.0.2",
41+
"remark-lint-prohibited-strings": "^4.0.0",
42+
"remark-lint-rule-style": "^4.0.1",
43+
"remark-lint-strong-marker": "^4.0.1",
44+
"remark-lint-table-cell-padding": "^5.1.1",
45+
"remark-lint-table-pipes": "^5.0.1",
46+
"remark-lint-unordered-list-marker-style": "^4.0.1",
47+
"remark-preset-lint-recommended": "^7.0.1",
48+
"semver": "~7.7.2",
49+
"unified-lint-rule": "^3.0.1",
50+
"unist-util-visit": "^5.0.0",
51+
"yaml": "^2.8.0"
52+
},
53+
"devDependencies": {
54+
"cross-env": "catalog:",
55+
"dedent": "^1.6.0",
56+
"globals": "^16.3.0",
57+
"remark-parse": "^11.0.0",
58+
"unified": "^11.0.5"
59+
}
60+
}

packages/remark-lint/src/api.mjs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import remarkGfm from 'remark-gfm';
2+
import remarkLintFencedCodeFlag from 'remark-lint-fenced-code-flag';
3+
import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length';
4+
import remarkLintNoUnusedDefinitions from 'remark-lint-no-unused-definitions';
5+
import remarkLintProhibitedStrings from 'remark-lint-prohibited-strings';
6+
import remarkLintUnorderedListMarkerStyle from 'remark-lint-unordered-list-marker-style';
7+
8+
import basePreset from './index.mjs';
9+
import duplicateStabilityNodes from './rules/duplicate-stability-nodes.mjs';
10+
import hashedSelfReference from './rules/hashed-self-reference.mjs';
11+
import orderedReferences from './rules/ordered-references.mjs';
12+
import requiredMetadata from './rules/required-metadata.mjs';
13+
import yamlComments from './rules/yaml/index.mjs';
14+
15+
export default {
16+
settings: {
17+
...basePreset.settings,
18+
bullet: '*',
19+
},
20+
plugins: [
21+
remarkGfm,
22+
...basePreset.plugins,
23+
duplicateStabilityNodes,
24+
yamlComments,
25+
hashedSelfReference,
26+
orderedReferences,
27+
requiredMetadata,
28+
remarkLintNoUnusedDefinitions,
29+
[remarkLintFencedCodeFlag, { allowEmpty: false }],
30+
[remarkLintMaximumLineLength, 120],
31+
[remarkLintUnorderedListMarkerStyle, '*'],
32+
[
33+
remarkLintProhibitedStrings,
34+
[
35+
{ yes: 'End-of-Life' },
36+
{ no: 'filesystem', yes: 'file system' },
37+
{ yes: 'GitHub' },
38+
{ no: 'hostname', yes: 'host name' },
39+
{ yes: 'JavaScript' },
40+
{ no: '[Ll]ong[ -][Tt]erm [Ss]upport', yes: 'Long Term Support' },
41+
{ no: 'Node', yes: 'Node.js', ignoreNextTo: '-API' },
42+
{ yes: 'Node.js' },
43+
{ no: 'Node[Jj][Ss]', yes: 'Node.js' },
44+
{ no: "Node\\.js's?", yes: 'the Node.js' },
45+
{ no: '[Nn]ote that', yes: '<nothing>' },
46+
{ yes: 'RFC' },
47+
{ no: '[Rr][Ff][Cc]\\d+', yes: 'RFC <number>' },
48+
{ yes: 'TypeScript' },
49+
{ yes: 'Unix' },
50+
{ yes: 'Valgrind' },
51+
{ yes: 'V8' },
52+
],
53+
],
54+
],
55+
};

0 commit comments

Comments
 (0)