-
Notifications
You must be signed in to change notification settings - Fork 66.2k
Expand file tree
/
Copy pathfrontmatter-landing-recommended.js
More file actions
98 lines (82 loc) · 2.84 KB
/
frontmatter-landing-recommended.js
File metadata and controls
98 lines (82 loc) · 2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import fs from 'fs'
import path from 'path'
import { addError } from 'markdownlint-rule-helpers'
import { getFrontmatter } from '../helpers/utils'
function isValidArticlePath(articlePath, currentFilePath) {
const ROOT = process.env.ROOT || '.'
// Strategy 1: Always try as an absolute path from content root first
const contentDir = path.join(ROOT, 'content')
const normalizedPath = articlePath.startsWith('/') ? articlePath.substring(1) : articlePath
const absolutePath = path.join(contentDir, `${normalizedPath}.md`)
if (fs.existsSync(absolutePath) && fs.statSync(absolutePath).isFile()) {
return true
}
// Strategy 2: Fall back to relative path from current file's directory
const currentDir = path.dirname(currentFilePath)
const relativePath = path.join(currentDir, `${normalizedPath}.md`)
try {
return fs.existsSync(relativePath) && fs.statSync(relativePath).isFile()
} catch {
return false
}
}
export const frontmatterLandingRecommended = {
names: ['GHD056', 'frontmatter-landing-recommended'],
description:
'Only landing pages can have recommended articles, there should be no duplicate recommended articles, and all recommended articles must exist',
tags: ['frontmatter', 'landing', 'recommended'],
function: (params, onError) => {
const fm = getFrontmatter(params.lines)
if (!fm || !fm.recommended) return
const recommendedLine = params.lines.find((line) => line.startsWith('recommended:'))
if (!recommendedLine) return
const lineNumber = params.lines.indexOf(recommendedLine) + 1
if (!fm.layout || !fm.layout.includes('landing')) {
addError(
onError,
lineNumber,
'recommended frontmatter key is only valid for landing pages',
recommendedLine,
[1, recommendedLine.length],
null,
)
}
// Check for duplicate recommended items and invalid paths
if (Array.isArray(fm.recommended)) {
const seen = new Set()
const duplicates = []
const invalidPaths = []
fm.recommended.forEach((item) => {
if (seen.has(item)) {
duplicates.push(item)
} else {
seen.add(item)
}
// Validate that the article path exists
if (!isValidArticlePath(item, params.name)) {
invalidPaths.push(item)
}
})
if (duplicates.length > 0) {
addError(
onError,
lineNumber,
`Found duplicate recommended articles: ${duplicates.join(', ')}`,
recommendedLine,
[1, recommendedLine.length],
null,
)
}
if (invalidPaths.length > 0) {
addError(
onError,
lineNumber,
`Found invalid recommended article paths: ${invalidPaths.join(', ')}`,
recommendedLine,
[1, recommendedLine.length],
null,
)
}
}
},
}