118 lines
3.4 KiB
TypeScript
118 lines
3.4 KiB
TypeScript
import { readFileSync, writeFileSync, existsSync } from 'fs'
|
|
import { relative, resolve } from 'path'
|
|
import type { SidebarItem } from './types'
|
|
import { parseFrontmatter, stringifyFrontmatter } from './frontmatter'
|
|
import { mergeSectionLinks, extractTopLevelLinks, extractItemsForPage } from './links'
|
|
import { normalizeLink } from './path-utils'
|
|
import { SectionLinkListItem } from '../../theme/components/SectionLinkList/SectionLinkList.types'
|
|
|
|
const removeDuplicates = (links: SectionLinkListItem[]) => {
|
|
const result: SectionLinkListItem[] = []
|
|
const seenLinks = new Set<string>()
|
|
|
|
for (const link of links) {
|
|
if (link.link) {
|
|
const normalized = normalizeLink(link.link)
|
|
if (!seenLinks.has(normalized)) {
|
|
seenLinks.add(normalized)
|
|
result.push(link)
|
|
}
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
const hasChanges = (
|
|
existingLinks: SectionLinkListItem[],
|
|
mergedLinks: SectionLinkListItem[]
|
|
) => {
|
|
if (existingLinks.length !== mergedLinks.length) return true
|
|
|
|
const existingSet = new Set(
|
|
existingLinks
|
|
.filter(link => link.link)
|
|
.map(link => `${normalizeLink(link.link!)}|${link.title}`)
|
|
)
|
|
|
|
const mergedSet = new Set(
|
|
mergedLinks
|
|
.filter(link => link.link)
|
|
.map(link => `${normalizeLink(link.link!)}|${link.title}`)
|
|
)
|
|
|
|
if (existingSet.size !== mergedSet.size) return true
|
|
|
|
for (const item of existingSet) {
|
|
if (!mergedSet.has(item)) return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
export const processIndexFile = (
|
|
filePath: string,
|
|
sidebarItems: SidebarItem[],
|
|
srcDir: string
|
|
) => {
|
|
if (!existsSync(filePath)) return false
|
|
|
|
try {
|
|
const fileContent = readFileSync(filePath, 'utf-8')
|
|
const { frontmatter, content } = parseFrontmatter(fileContent)
|
|
|
|
const relativePath = relative(srcDir, filePath).replace(/\\/g, '/')
|
|
const normalizedPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`
|
|
|
|
const existingLinks = removeDuplicates(
|
|
Array.isArray(frontmatter.section_links) ? [...frontmatter.section_links] : []
|
|
)
|
|
const newLinks = extractTopLevelLinks(sidebarItems, normalizedPath, srcDir)
|
|
|
|
if (!newLinks.length) return false
|
|
|
|
const mergedLinks = removeDuplicates(mergeSectionLinks(existingLinks, newLinks))
|
|
|
|
if (!hasChanges(existingLinks, mergedLinks)) return false
|
|
|
|
frontmatter.section_links = mergedLinks
|
|
writeFileSync(filePath, stringifyFrontmatter(frontmatter, content), 'utf-8')
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export const processPageWithItems = (
|
|
filePath: string,
|
|
sidebarItems: SidebarItem[],
|
|
srcDir: string
|
|
) => {
|
|
if (!existsSync(filePath)) return false
|
|
|
|
try {
|
|
const fileContent = readFileSync(filePath, 'utf-8')
|
|
const { frontmatter, content } = parseFrontmatter(fileContent)
|
|
|
|
const relativePath = relative(srcDir, filePath).replace(/\\/g, '/')
|
|
const normalizedPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`
|
|
|
|
const existingLinks = removeDuplicates(
|
|
Array.isArray(frontmatter.section_links) ? [...frontmatter.section_links] : []
|
|
)
|
|
const newLinks = extractItemsForPage(sidebarItems, normalizedPath, srcDir)
|
|
|
|
const mergedLinks = newLinks.length > 0
|
|
? removeDuplicates(mergeSectionLinks(existingLinks, newLinks))
|
|
: []
|
|
|
|
if (!hasChanges(existingLinks, mergedLinks)) return false
|
|
|
|
frontmatter.section_links = mergedLinks
|
|
writeFileSync(filePath, stringifyFrontmatter(frontmatter, content), 'utf-8')
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|