Skip to content

Commit c5ddef5

Browse files
committed
feat: add JSON frontmatter support to no-multiple-h1 rule
1 parent 7392f0f commit c5ddef5

File tree

3 files changed

+229
-2
lines changed

3 files changed

+229
-2
lines changed

docs/rules/no-multiple-h1.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This rule warns when it finds more than one H1 heading in a Markdown document. I
1212

1313
- ATX-style headings (`# Heading`)
1414
- Setext-style headings (`Heading\n=========`)
15-
- Front matter title fields (YAML and TOML)
15+
- Front matter title fields (YAML, TOML, and JSON)
1616
- HTML h1 tags (`<h1>Heading</h1>`)
1717

1818
Examples of **incorrect** code for this rule:
@@ -46,7 +46,7 @@ Another H1 heading
4646

4747
The following options are available on this rule:
4848

49-
* `frontmatterTitle: string` - A regex pattern to match title fields in front matter. The default pattern matches both YAML (`title:`) and TOML (`title =`) formats. Set to an empty string to disable front matter title checking.
49+
* `frontmatterTitle: string` - A regex pattern to match title fields in front matter. The default pattern matches YAML (`title:`), TOML (`title =`), and JSON (`"title":`) formats. Set to an empty string to disable front matter title checking.
5050

5151
Examples of **incorrect** code for this rule:
5252

src/rules/no-multiple-h1.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ export default {
9898
}
9999
},
100100

101+
json(node) {
102+
if (frontmatterHasTitle(node.value, titlePattern)) {
103+
h1Count++;
104+
}
105+
},
106+
101107
html(node) {
102108
let match;
103109
while ((match = h1TagPattern.exec(node.value)) !== null) {

tests/rules/no-multiple-h1.test.js

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,19 @@ ruleTester.run("no-multiple-h1", rule, {
8282
frontmatter: "toml",
8383
},
8484
},
85+
{
86+
code: dedent`
87+
---
88+
{
89+
"title": "My Title"
90+
}
91+
---
92+
## Heading 2
93+
`,
94+
languageOptions: {
95+
frontmatter: "json",
96+
},
97+
},
8598
{
8699
code: dedent`
87100
---
@@ -150,6 +163,20 @@ ruleTester.run("no-multiple-h1", rule, {
150163
frontmatter: "toml",
151164
},
152165
},
166+
{
167+
code: dedent`
168+
---
169+
{
170+
"heading": "My Title"
171+
}
172+
---
173+
## Heading 2
174+
`,
175+
options: [{ frontmatterTitle: '^\\s*"heading"\\s*:' }],
176+
languageOptions: {
177+
frontmatter: "json",
178+
},
179+
},
153180
{
154181
code: dedent`
155182
---
@@ -172,6 +199,19 @@ ruleTester.run("no-multiple-h1", rule, {
172199
frontmatter: "toml",
173200
},
174201
},
202+
{
203+
code: dedent`
204+
---
205+
{
206+
"author": "Pixel998"
207+
}
208+
---
209+
# Heading 1
210+
`,
211+
languageOptions: {
212+
frontmatter: "json",
213+
},
214+
},
175215
{
176216
code: dedent`
177217
---
@@ -196,6 +236,20 @@ ruleTester.run("no-multiple-h1", rule, {
196236
frontmatter: "toml",
197237
},
198238
},
239+
{
240+
code: dedent`
241+
---
242+
{
243+
"title": "My Title"
244+
}
245+
---
246+
# Heading 1
247+
`,
248+
options: [{ frontmatterTitle: "" }],
249+
languageOptions: {
250+
frontmatter: "json",
251+
},
252+
},
199253
'<h1 class="title">Heading</h1>',
200254
dedent`
201255
# Heading 1
@@ -422,6 +476,28 @@ ruleTester.run("no-multiple-h1", rule, {
422476
},
423477
],
424478
},
479+
{
480+
code: dedent`
481+
---
482+
{
483+
"title": "My Title"
484+
}
485+
---
486+
# Heading 1
487+
`,
488+
languageOptions: {
489+
frontmatter: "json",
490+
},
491+
errors: [
492+
{
493+
messageId: "multipleH1",
494+
line: 6,
495+
column: 1,
496+
endLine: 6,
497+
endColumn: 12,
498+
},
499+
],
500+
},
425501
{
426502
code: dedent`
427503
---
@@ -462,6 +538,28 @@ ruleTester.run("no-multiple-h1", rule, {
462538
},
463539
],
464540
},
541+
{
542+
code: dedent`
543+
---
544+
{
545+
'title': 'My Title'
546+
}
547+
---
548+
# Heading 1
549+
`,
550+
languageOptions: {
551+
frontmatter: "json",
552+
},
553+
errors: [
554+
{
555+
messageId: "multipleH1",
556+
line: 6,
557+
column: 1,
558+
endLine: 6,
559+
endColumn: 12,
560+
},
561+
],
562+
},
465563
{
466564
code: dedent`
467565
---
@@ -504,6 +602,29 @@ ruleTester.run("no-multiple-h1", rule, {
504602
},
505603
],
506604
},
605+
{
606+
code: dedent`
607+
---
608+
{
609+
"author": "Pixel998"
610+
"title": "My Title"
611+
}
612+
---
613+
# Heading 1
614+
`,
615+
languageOptions: {
616+
frontmatter: "json",
617+
},
618+
errors: [
619+
{
620+
messageId: "multipleH1",
621+
line: 7,
622+
column: 1,
623+
endLine: 7,
624+
endColumn: 12,
625+
},
626+
],
627+
},
507628
{
508629
code: dedent`
509630
---
@@ -544,6 +665,28 @@ ruleTester.run("no-multiple-h1", rule, {
544665
},
545666
],
546667
},
668+
{
669+
code: dedent`
670+
---
671+
{
672+
"TITLE": "My Title"
673+
}
674+
---
675+
# Heading 1
676+
`,
677+
languageOptions: {
678+
frontmatter: "json",
679+
},
680+
errors: [
681+
{
682+
messageId: "multipleH1",
683+
line: 6,
684+
column: 1,
685+
endLine: 6,
686+
endColumn: 12,
687+
},
688+
],
689+
},
547690
{
548691
code: dedent`
549692
---
@@ -586,6 +729,29 @@ ruleTester.run("no-multiple-h1", rule, {
586729
},
587730
],
588731
},
732+
{
733+
code: dedent`
734+
---
735+
{
736+
"heading": "My Title"
737+
}
738+
---
739+
# Heading 1
740+
`,
741+
options: [{ frontmatterTitle: '^\\s*"heading"\\s*:' }],
742+
languageOptions: {
743+
frontmatter: "json",
744+
},
745+
errors: [
746+
{
747+
messageId: "multipleH1",
748+
line: 6,
749+
column: 1,
750+
endLine: 6,
751+
endColumn: 12,
752+
},
753+
],
754+
},
589755
{
590756
code: dedent`
591757
---
@@ -630,6 +796,30 @@ ruleTester.run("no-multiple-h1", rule, {
630796
},
631797
],
632798
},
799+
{
800+
code: dedent`
801+
---
802+
{
803+
"title": "My Title"
804+
}
805+
---
806+
# Heading 1
807+
# Another H1
808+
`,
809+
options: [{ frontmatterTitle: "" }],
810+
languageOptions: {
811+
frontmatter: "json",
812+
},
813+
errors: [
814+
{
815+
messageId: "multipleH1",
816+
line: 7,
817+
column: 1,
818+
endLine: 7,
819+
endColumn: 13,
820+
},
821+
],
822+
},
633823
{
634824
code: dedent`
635825
<h1>Heading</h1>
@@ -769,5 +959,36 @@ ruleTester.run("no-multiple-h1", rule, {
769959
},
770960
],
771961
},
962+
{
963+
code: dedent`
964+
---
965+
{
966+
"title": "My Title"
967+
}
968+
---
969+
# Heading 1
970+
971+
<h1>Another H1</h1>
972+
`,
973+
languageOptions: {
974+
frontmatter: "json",
975+
},
976+
errors: [
977+
{
978+
messageId: "multipleH1",
979+
line: 6,
980+
column: 1,
981+
endLine: 6,
982+
endColumn: 12,
983+
},
984+
{
985+
messageId: "multipleH1",
986+
line: 8,
987+
column: 1,
988+
endLine: 8,
989+
endColumn: 20,
990+
},
991+
],
992+
},
772993
],
773994
});

0 commit comments

Comments
 (0)