Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Changesets

Every PR that changes the published package needs a changeset, which becomes the release note in `CHANGELOG.md`.

CI only requires it when the PR changes the published code (`index.js`, `index.d.ts`, `configs/` or `lib/`, see `changedFilePatterns` in `config.json`).
It does not detect changes of `package.json`: add a changeset yourself when changing `dependencies`, `peerDependencies` or `engines`.
Add a changeset to a PR that should appear in the release notes in `CHANGELOG.md`. CI does not require it.

```sh
pnpm changeset # choose major / minor / patch and write the summary
Expand Down
20 changes: 0 additions & 20 deletions .github/workflows/lint-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,3 @@ jobs:
- run: pnpm pack --pack-destination "$RUNNER_TEMP"
- name: show the package contents
run: tar -tzf "$RUNNER_TEMP"/*.tgz

changeset:
# every PR changing the published code (`changedFilePatterns` in .changeset/config.json) needs a changeset
# (`pnpm changeset`, or `pnpm changeset --empty` for changes without a release note)
if: github.event_name == 'pull_request' && github.actor != 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# `changeset status --since` compares with the base branch
fetch-depth: 0
persist-credentials: false
show-progress: false
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 'lts/*'
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm changeset status --since="origin/${{ github.base_ref }}"
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The benchmarks are a separate package in [`bench/`](bench/README.md).

## Pull Requests

- Every PR needs a [changeset](.changeset/README.md), which becomes the release note in `CHANGELOG.md`. Use `pnpm changeset --empty` for changes that should not appear in the release notes (CI, docs, ...).
- Add a [changeset](.changeset/README.md) to a PR that should appear in the release notes in `CHANGELOG.md`. CI does not require it.
- On PRs, CI applies `pnpm lint:fix` and `pnpm update:eslint-docs` and commits the result, so formatting and generated docs do not need to be fixed by hand.
- CI also runs the tests on ESLint 9 and 10 and on Node.js 22, 24 and 26, checks the published types, and comments the coverage and the benchmark results on the PR.
- A PR fails when it makes the benchmarks more than 5% slower than the baseline. When a change is expected to change the performance (e.g. adding a rule), run the `Benchmark: update baseline` workflow on the branch.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ pnpm test # vitest with coverage

After changing a rule's docs or meta, run `pnpm update:eslint-docs` to regenerate the docs (CI also regenerates them on PRs).

Every PR needs a [changeset](.changeset/README.md), which becomes the release note in `CHANGELOG.md` (CI checks it):
Add a [changeset](.changeset/README.md) to a PR that should appear in the release notes in `CHANGELOG.md` (CI does not require it):

```sh
pnpm changeset # choose major / minor / patch and write the summary
Expand Down
6 changes: 5 additions & 1 deletion lib/rules/jsx-curly-brace-presence.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,11 @@ function renderJSXText(text) {
trimmedLine = trimmedLine.replace(/^[ ]+/, '');
}
if (i !== lines.length - 1) {
trimmedLine = trimmedLine.replace(/[ ]+$/, '');
let end = trimmedLine.length;
while (end > 0 && trimmedLine[end - 1] === ' ') {
end -= 1;
}
trimmedLine = trimmedLine.slice(0, end);
}
if (!trimmedLine) {
return rendered;
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/jsx-indent.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ module.exports = {
*/
function checkLiteralNodeIndent(node, indent) {
const value = node.value;
const regExp = indentType === 'space' ? /\n( *)[\t ]*\S/g : /\n(\t*)[\t ]*\S/g;
const regExp = indentType === 'space' ? /\n( *)(?:\t[\t ]*)?\S/g : /\n(\t*)(?: [\t ]*)?\S/g;
const nodeIndentsPerLine = Array.from(
String(value).matchAll(regExp),
(match) => (match[1] ? match[1].length : 0)
Expand Down
6 changes: 4 additions & 2 deletions lib/rules/jsx-one-expression-per-line.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,10 @@ module.exports = {
return;
}

countNewLinesBeforeContent = (child.raw.match(/^\s*\n/g) || []).length;
countNewLinesAfterContent = (child.raw.match(/\n\s*$/g) || []).length;
const leadingWhitespace = child.raw.slice(0, child.raw.length - child.raw.trimStart().length);
const trailingWhitespace = child.raw.slice(child.raw.trimEnd().length);
countNewLinesBeforeContent = leadingWhitespace.includes('\n') ? 1 : 0;
countNewLinesAfterContent = trailingWhitespace.includes('\n') ? 1 : 0;
}

const startLine = child.loc.start.line + countNewLinesBeforeContent;
Expand Down
20 changes: 19 additions & 1 deletion lib/rules/no-invalid-html-attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,24 @@ function splitIntoRangedParts(node, regex) {
});
}

/**
* Split a space-separated attribute value into parts made of each value and the value following it
* @param {ASTNode} node The literal node holding the attribute value
* @returns {{reportingValue: string}[]} One part per value, including the whitespace and the following value if any
*/
function splitIntoPairParts(node) {
const values = Array.from(node.value.matchAll(/\S+/g));

return values.map((value, i) => {
const next = values[i + 1];
const end = next ? next.index + next[0].length : value.index + value[0].length;

return {
reportingValue: node.value.slice(value.index, end),
};
});
}

function checkLiteralValueNode(context, attributeName, node, parentNode, parentNodeName) {
if (typeof node.value !== 'string') {
const data = { attributeName, reportingValue: node.value };
Expand Down Expand Up @@ -332,7 +350,7 @@ function checkLiteralValueNode(context, attributeName, node, parentNode, parentN

const allowedPairsForAttribute = VALID_PAIR_VALUES.get(attributeName);
if (allowedPairsForAttribute) {
const pairAttributeParts = splitIntoRangedParts(node, /(?=(\b\S+\s*\S+))/g);
const pairAttributeParts = splitIntoPairParts(node);
pairAttributeParts.forEach((pairPart) => {
allowedPairsForAttribute.forEach((siblings, pairing) => {
const attributes = pairPart.reportingValue.split('\u0020');
Expand Down
Loading