Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcdecbb4

Browse files
authored
Add frontmatter validation linter rule (GHD055) (#56150)
1 parent6164dc2 commitcdecbb4

File tree

5 files changed

+678
-0
lines changed

5 files changed

+678
-0
lines changed

‎data/reusables/contributing/content-linter-rules.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
| GHD051| frontmatter-versions-whitespace| Versions frontmatter should not contain unnecessary whitespace| warning| frontmatter, versions|
7171
| GHD053| header-content-requirement| Headers must have content between them, such as an introduction| warning| headers, structure, content|
7272
| GHD054| third-party-actions-reusable| Code examples with third-party actions must include disclaimer reusable| warning| actions, reusable, third-party|
73+
| GHD055| frontmatter-validation| Frontmatter properties must meet character limits and required property requirements| warning| frontmatter, character-limits, required-properties|
7374
|[search-replace](https://github.com/OnkarRuikar/markdownlint-rule-search-replace)| deprecated liquid syntax: octicon-<icon-name>| The octicon liquid syntax used is deprecated. Use this format instead`octicon "<octicon-name>" aria-label="<Octicon aria label>"`| error||
7475
|[search-replace](https://github.com/OnkarRuikar/markdownlint-rule-search-replace)| deprecated liquid syntax: site.data| Catch occurrences of deprecated liquid data syntax.| error||
7576
|[search-replace](https://github.com/OnkarRuikar/markdownlint-rule-search-replace)| developer-domain| Catch occurrences of developer.github.com domain.| error||
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import{addError}from'markdownlint-rule-helpers'
2+
import{getFrontmatter}from'@/content-linter/lib/helpers/utils'
3+
4+
exportconstfrontmatterValidation={
5+
names:['GHD055','frontmatter-validation'],
6+
description:
7+
'Frontmatter properties must meet character limits and required property requirements',
8+
tags:['frontmatter','character-limits','required-properties'],
9+
function:(params,onError)=>{
10+
constfm=getFrontmatter(params.lines)
11+
if(!fm)return
12+
13+
// Detect content type based on frontmatter properties and file path
14+
constcontentType=detectContentType(fm,params.name)
15+
16+
// Define character limits and requirements for different content types
17+
constcontentRules={
18+
category:{
19+
title:{max:70,recommended:67},
20+
shortTitle:{max:30,recommended:27},
21+
intro:{required:true,recommended:280,max:362},
22+
requiredProperties:['intro'],
23+
},
24+
mapTopic:{
25+
title:{max:70,recommended:63},
26+
shortTitle:{max:35,recommended:30},
27+
intro:{required:true,recommended:280,max:362},
28+
requiredProperties:['intro'],
29+
},
30+
article:{
31+
title:{max:80,recommended:60},
32+
shortTitle:{max:30,recommended:25},
33+
intro:{required:false,recommended:251,max:354},
34+
requiredProperties:['topics'],
35+
},
36+
}
37+
38+
construles=contentRules[contentType]
39+
if(!rules)return
40+
41+
// Check required properties
42+
for(constpropertyofrules.requiredProperties){
43+
if(!fm[property]){
44+
addError(
45+
onError,
46+
1,
47+
`Missing required property '${property}' for${contentType} content type`,
48+
null,
49+
null,
50+
null,
51+
)
52+
}
53+
}
54+
55+
// Check title length
56+
if(fm.title){
57+
validatePropertyLength(onError,params.lines,'title',fm.title,rules.title,'Title')
58+
}
59+
60+
// Check shortTitle length
61+
if(fm.shortTitle){
62+
validatePropertyLength(
63+
onError,
64+
params.lines,
65+
'shortTitle',
66+
fm.shortTitle,
67+
rules.shortTitle,
68+
'ShortTitle',
69+
)
70+
}
71+
72+
// Check intro length if it exists
73+
if(fm.intro&&rules.intro){
74+
validatePropertyLength(onError,params.lines,'intro',fm.intro,rules.intro,'Intro')
75+
}
76+
77+
// Cross-property validation: if title is longer than shortTitle limit, shortTitle must exist
78+
if(fm.title&&fm.title.length>rules.shortTitle.max&&!fm.shortTitle){
79+
consttitleLine=findPropertyLine(params.lines,'title')
80+
addError(
81+
onError,
82+
titleLine,
83+
`Title is${fm.title.length} characters, which exceeds the shortTitle limit of${rules.shortTitle.max} characters. A shortTitle must be provided.`,
84+
fm.title,
85+
null,
86+
null,
87+
)
88+
}
89+
90+
// Special validation for articles: should have at least one topic
91+
if(contentType==='article'&&fm.topics){
92+
if(!Array.isArray(fm.topics)){
93+
consttopicsLine=findPropertyLine(params.lines,'topics')
94+
addError(onError,topicsLine,'Topics must be an array',String(fm.topics),null,null)
95+
}elseif(fm.topics.length===0){
96+
consttopicsLine=findPropertyLine(params.lines,'topics')
97+
addError(
98+
onError,
99+
topicsLine,
100+
'Articles should have at least one topic',
101+
'topics: []',
102+
null,
103+
null,
104+
)
105+
}
106+
}
107+
},
108+
}
109+
110+
functionvalidatePropertyLength(onError,lines,propertyName,propertyValue,limits,displayName){
111+
constpropertyLength=propertyValue.length
112+
constpropertyLine=findPropertyLine(lines,propertyName)
113+
114+
// Only report the most severe error - maximum takes precedence over recommended
115+
if(propertyLength>limits.max){
116+
addError(
117+
onError,
118+
propertyLine,
119+
`${displayName} exceeds maximum length of${limits.max} characters (current:${propertyLength})`,
120+
propertyValue,
121+
null,
122+
null,
123+
)
124+
}elseif(propertyLength>limits.recommended){
125+
addError(
126+
onError,
127+
propertyLine,
128+
`${displayName} exceeds recommended length of${limits.recommended} characters (current:${propertyLength})`,
129+
propertyValue,
130+
null,
131+
null,
132+
)
133+
}
134+
}
135+
136+
functiondetectContentType(frontmatter,filePath){
137+
// Only apply validation to markdown files
138+
if(!filePath||!filePath.endsWith('.md')){
139+
returnnull
140+
}
141+
142+
// Map topics have mapTopic: true
143+
if(frontmatter.mapTopic===true){
144+
return'mapTopic'
145+
}
146+
147+
// Categories are index.md files that contain children but no mapTopic
148+
// Only check files that look like they're in the content directory structure
149+
if(
150+
filePath.includes('/index.md')&&
151+
frontmatter.children&&
152+
Array.isArray(frontmatter.children)&&
153+
!frontmatter.mapTopic
154+
){
155+
return'category'
156+
}
157+
158+
// Everything else is an article
159+
return'article'
160+
}
161+
162+
functionfindPropertyLine(lines,property){
163+
constline=lines.find((line)=>line.trim().startsWith(`${property}:`))
164+
returnline ?lines.indexOf(line)+1 :1
165+
}

‎src/content-linter/lib/linting-rules/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import { britishEnglishQuotes } from '@/content-linter/lib/linting-rules/british
5151
import{multipleEmphasisPatterns}from'@/content-linter/lib/linting-rules/multiple-emphasis-patterns'
5252
import{noteWarningFormatting}from'@/content-linter/lib/linting-rules/note-warning-formatting'
5353
import{frontmatterVersionsWhitespace}from'@/content-linter/lib/linting-rules/frontmatter-versions-whitespace'
54+
import{frontmatterValidation}from'@/content-linter/lib/linting-rules/frontmatter-validation'
5455
import{headerContentRequirement}from'@/content-linter/lib/linting-rules/header-content-requirement'
5556
import{thirdPartyActionsReusable}from'@/content-linter/lib/linting-rules/third-party-actions-reusable'
5657

@@ -113,6 +114,7 @@ export const gitHubDocsMarkdownlint = {
113114
frontmatterVersionsWhitespace,// GHD051
114115
headerContentRequirement,// GHD053
115116
thirdPartyActionsReusable,// GHD054
117+
frontmatterValidation,// GHD055
116118

117119
// Search-replace rules
118120
searchReplace,// Open-source plugin

‎src/content-linter/style/github-docs.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,12 @@ export const githubDocsFrontmatterConfig = {
304304
'partial-markdown-files':false,
305305
'yml-files':false,
306306
},
307+
'frontmatter-validation':{
308+
// GHD055
309+
severity:'warning',
310+
'partial-markdown-files':false,
311+
'yml-files':false,
312+
},
307313
}
308314

309315
// Configures rules from the `github/markdownlint-github` repo

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp