Skip to content

Commit bf84320

Browse files
authored
Merge branch 'main' into fix-false-negatives-no-reversed-media-syntax
2 parents a467bdd + 614ef3e commit bf84320

13 files changed

+1296
-36
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "7.0.0"
2+
".": "7.1.0"
33
}

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Changelog
22

3+
## [7.1.0](https://github.com/eslint/markdown/compare/v7.0.0...v7.1.0) (2025-07-22)
4+
5+
6+
### Features
7+
8+
* add checkMissingCells option to table-column-count ([#434](https://github.com/eslint/markdown/issues/434)) ([bf3f39b](https://github.com/eslint/markdown/commit/bf3f39be366f6dec6ad6a8d26751c06d04988e3f))
9+
10+
11+
### Bug Fixes
12+
13+
* bump `plugin-kit` to latest to resolve security vulnerabilities ([#485](https://github.com/eslint/markdown/issues/485)) ([c5398ca](https://github.com/eslint/markdown/commit/c5398caac221daa147a2993cc945e42e374a6c5d))
14+
* case-insensitive attribute checks in `no-missing-link-fragment` ([#465](https://github.com/eslint/markdown/issues/465)) ([094a59d](https://github.com/eslint/markdown/commit/094a59d13b294f62c45693f41e921e08d15f0ccb))
15+
* case-insensitive checks for HTML attributes in `no-missing-link-fragment` ([094a59d](https://github.com/eslint/markdown/commit/094a59d13b294f62c45693f41e921e08d15f0ccb))
16+
* no-reversed-media-syntax add missing offset for code spans ([#460](https://github.com/eslint/markdown/issues/460)) ([af7736c](https://github.com/eslint/markdown/commit/af7736c51d2ad6d065d12b5b92ff01aff8d58a4a))
17+
* potential super-linear regular expressions ([#463](https://github.com/eslint/markdown/issues/463)) ([bc82567](https://github.com/eslint/markdown/commit/bc82567458f8fc41b36cbcb2c67aac746078e044))
18+
* remove unused types from `types.ts` ([#462](https://github.com/eslint/markdown/issues/462)) ([466f80e](https://github.com/eslint/markdown/commit/466f80e1b66e4894853ed26e7475fdab944a33ce))
19+
320
## [7.0.0](https://github.com/eslint/markdown/compare/v6.6.0...v7.0.0) (2025-07-11)
421

522

docs/rules/heading-increment.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,68 @@ Goodbye World!
2525
#EEE Goodbye World!
2626
```
2727

28+
## Options
29+
30+
The following options are available on this rule:
31+
32+
* `frontmatterTitle: string` - A regex pattern to match title fields in front matter. Front matter titles matching this pattern are treated as level 1 headings. The default pattern matches YAML (`title:`), TOML (`title =`), and JSON (`"title":`) formats. Set to an empty string to disable front matter title checking.
33+
34+
Examples of **incorrect** code for this rule:
35+
36+
```markdown
37+
<!-- eslint markdown/heading-increment: "error" -->
38+
39+
---
40+
title: My Title
41+
---
42+
43+
### Heading 3 with YAML front matter
44+
```
45+
46+
```markdown
47+
<!-- eslint markdown/heading-increment: "error" -->
48+
49+
+++
50+
title = "My Title"
51+
+++
52+
53+
### Heading 3 with TOML front matter
54+
```
55+
56+
```markdown
57+
<!-- eslint markdown/heading-increment: "error" -->
58+
59+
---
60+
{ "title": "My Title" }
61+
---
62+
63+
### Heading 3 with JSON front matter
64+
```
65+
66+
Examples of **incorrect** code when configured as `"heading-increment": ["error", { frontmatterTitle: "\\s*heading\\s*[:=]" }]`:
67+
68+
```markdown
69+
<!-- eslint markdown/heading-increment: ["error", { frontmatterTitle: "\\s*heading\\s*[:=]" }] -->
70+
71+
---
72+
heading: My Title
73+
---
74+
75+
### Heading 3
76+
```
77+
78+
Examples of **correct** code when configured as `"heading-increment": ["error", { frontmatterTitle: "" }]`:
79+
80+
```markdown
81+
<!-- eslint markdown/heading-increment: ["error", { frontmatterTitle: "" }] -->
82+
83+
---
84+
title: My Title
85+
---
86+
87+
### Heading 3
88+
```
89+
2890
## When Not to Use It
2991

3092
If you aren't concerned with enforcing heading levels increment by one, you can safely disable this rule.

jsr.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@eslint/markdown",
3-
"version": "7.0.0",
3+
"version": "7.1.0",
44
"exports": "./dist/esm/index.js",
55
"publish": {
66
"include": [

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@eslint/markdown",
3-
"version": "7.0.0",
3+
"version": "7.1.0",
44
"description": "The official ESLint language plugin for Markdown",
55
"license": "MIT",
66
"author": {
@@ -73,10 +73,10 @@
7373
"test:types": "tsc -p tests/types/tsconfig.json"
7474
},
7575
"devDependencies": {
76-
"@eslint/js": "^9.4.0",
76+
"@eslint/js": "^9.31.0",
7777
"c8": "^10.1.2",
7878
"dedent": "^1.5.3",
79-
"eslint": "^9.28.0",
79+
"eslint": "^9.31.0",
8080
"eslint-config-eslint": "^11.0.0",
8181
"eslint-plugin-eslint-plugin": "^6.3.2",
8282
"globals": "^15.1.0",
@@ -88,12 +88,12 @@
8888
"yorkie": "^2.0.0"
8989
},
9090
"dependencies": {
91-
"@eslint/core": "^0.15.0",
92-
"@eslint/plugin-kit": "^0.3.1",
91+
"@eslint/core": "^0.15.1",
92+
"@eslint/plugin-kit": "^0.3.4",
9393
"github-slugger": "^2.0.0",
9494
"mdast-util-from-markdown": "^2.0.2",
9595
"mdast-util-frontmatter": "^2.0.1",
96-
"mdast-util-gfm": "^3.0.0",
96+
"mdast-util-gfm": "^3.1.0",
9797
"micromark-extension-frontmatter": "^2.0.0",
9898
"micromark-extension-gfm": "^3.0.0"
9999
},

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ let recommendedPlugins, processorPlugins;
5454
const plugin = {
5555
meta: {
5656
name: "@eslint/markdown",
57-
version: "7.0.0", // x-release-please-version
57+
version: "7.1.0", // x-release-please-version
5858
},
5959
processors: {
6060
markdown: processor,

src/processor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ function postprocess(messages, filename) {
466466
export const processor = {
467467
meta: {
468468
name: "@eslint/markdown/markdown",
469-
version: "7.0.0", // x-release-please-version
469+
version: "7.1.0", // x-release-please-version
470470
},
471471
preprocess,
472472
postprocess,

src/rules/heading-increment.js

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,20 @@
33
* @author Nicholas C. Zakas
44
*/
55

6+
//-----------------------------------------------------------------------------
7+
// Imports
8+
//-----------------------------------------------------------------------------
9+
10+
import { frontmatterHasTitle } from "../util.js";
11+
612
//-----------------------------------------------------------------------------
713
// Type Definitions
814
//-----------------------------------------------------------------------------
915

1016
/**
1117
* @import { MarkdownRuleDefinition } from "../types.js";
1218
* @typedef {"skippedHeading"} HeadingIncrementMessageIds
13-
* @typedef {[]} HeadingIncrementOptions
19+
* @typedef {[{ frontmatterTitle?: string }]} HeadingIncrementOptions
1420
* @typedef {MarkdownRuleDefinition<{ RuleOptions: HeadingIncrementOptions, MessageIds: HeadingIncrementMessageIds }>} HeadingIncrementRuleDefinition
1521
*/
1622

@@ -33,12 +39,52 @@ export default {
3339
skippedHeading:
3440
"Heading level skipped from {{fromLevel}} to {{toLevel}}.",
3541
},
42+
43+
schema: [
44+
{
45+
type: "object",
46+
properties: {
47+
frontmatterTitle: {
48+
type: "string",
49+
},
50+
},
51+
additionalProperties: false,
52+
},
53+
],
54+
55+
defaultOptions: [
56+
{
57+
frontmatterTitle:
58+
"^(?!\\s*['\"]title[:=]['\"])\\s*\\{?\\s*['\"]?title['\"]?\\s*[:=]",
59+
},
60+
],
3661
},
3762

3863
create(context) {
64+
const [{ frontmatterTitle }] = context.options;
65+
const titlePattern =
66+
frontmatterTitle === "" ? null : new RegExp(frontmatterTitle, "iu");
3967
let lastHeadingDepth = 0;
4068

4169
return {
70+
yaml(node) {
71+
if (frontmatterHasTitle(node.value, titlePattern)) {
72+
lastHeadingDepth = 1;
73+
}
74+
},
75+
76+
toml(node) {
77+
if (frontmatterHasTitle(node.value, titlePattern)) {
78+
lastHeadingDepth = 1;
79+
}
80+
},
81+
82+
json(node) {
83+
if (frontmatterHasTitle(node.value, titlePattern)) {
84+
lastHeadingDepth = 1;
85+
}
86+
},
87+
4288
heading(node) {
4389
if (lastHeadingDepth > 0 && node.depth > lastHeadingDepth + 1) {
4490
context.report({

src/rules/no-multiple-h1.js

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// Imports
88
//-----------------------------------------------------------------------------
99

10-
import { findOffsets } from "../util.js";
10+
import { findOffsets, frontmatterHasTitle } from "../util.js";
1111

1212
//-----------------------------------------------------------------------------
1313
// Type Definitions
@@ -26,25 +26,6 @@ import { findOffsets } from "../util.js";
2626

2727
const h1TagPattern = /(?<!<!--[\s\S]*?)<h1[^>]*>[\s\S]*?<\/h1>/giu;
2828

29-
/**
30-
* Checks if a frontmatter block contains a title matching the given pattern
31-
* @param {string} value The frontmatter content
32-
* @param {RegExp|null} pattern The pattern to match against
33-
* @returns {boolean} Whether a title was found
34-
*/
35-
function frontmatterHasTitle(value, pattern) {
36-
if (!pattern) {
37-
return false;
38-
}
39-
const lines = value.split("\n");
40-
for (const line of lines) {
41-
if (pattern.test(line)) {
42-
return true;
43-
}
44-
}
45-
return false;
46-
}
47-
4829
//-----------------------------------------------------------------------------
4930
// Rule Definition
5031
//-----------------------------------------------------------------------------

src/util.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,22 @@ export function findOffsets(text, offset) {
3737
columnOffset,
3838
};
3939
}
40+
41+
/**
42+
* Checks if a frontmatter block contains a title matching the given pattern
43+
* @param {string} value The frontmatter content
44+
* @param {RegExp|null} pattern The pattern to match against
45+
* @returns {boolean} Whether a title was found
46+
*/
47+
export function frontmatterHasTitle(value, pattern) {
48+
if (!pattern) {
49+
return false;
50+
}
51+
const lines = value.split("\n");
52+
for (const line of lines) {
53+
if (pattern.test(line)) {
54+
return true;
55+
}
56+
}
57+
return false;
58+
}

0 commit comments

Comments
 (0)