Files
fox/src/.vitepress/plugins/utils/file-processor.ts
T

136 lines
4.2 KiB
TypeScript
Raw Normal View History

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[],
newLinks: SectionLinkListItem[]
) => {
const existingLinksSet = new Set(
existingLinks
.map(link => link.link)
.filter((link): link is string => Boolean(link))
.map(normalizeLink)
)
const hasNewLinks = newLinks.some(
link => link.link && !existingLinksSet.has(normalizeLink(link.link))
)
if (hasNewLinks) return true
const sidebarLinksSet = new Set(
newLinks
.map(link => link.link)
.filter((link): link is string => Boolean(link))
.map(normalizeLink)
)
const existingSidebarLinks = existingLinks
.filter(link => link.link && sidebarLinksSet.has(normalizeLink(link.link)))
.map(link => normalizeLink(link.link!))
.join('|')
const mergedSidebarLinks = mergedLinks
.slice(0, newLinks.length)
.filter(link => link.link && sidebarLinksSet.has(normalizeLink(link.link)))
.map(link => normalizeLink(link.link!))
.join('|')
return existingSidebarLinks !== mergedSidebarLinks && mergedLinks.length === existingLinks.length
}
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 rawExistingLinks: SectionLinkListItem[] = Array.isArray(frontmatter.section_links)
? [...frontmatter.section_links]
: []
const existingLinks = removeDuplicates(rawExistingLinks)
const newLinks = extractTopLevelLinks(sidebarItems, normalizedPath, srcDir)
if (!newLinks.length) return false
const mergedLinks = removeDuplicates(mergeSectionLinks(existingLinks, newLinks))
if (!hasChanges(existingLinks, mergedLinks, newLinks)) return false
frontmatter.section_links = mergedLinks
const updatedContent = stringifyFrontmatter(frontmatter, content)
writeFileSync(filePath, updatedContent, '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 rawExistingLinks: SectionLinkListItem[] = Array.isArray(frontmatter.section_links)
? [...frontmatter.section_links]
: []
const existingLinks = removeDuplicates(rawExistingLinks)
const newLinks = extractItemsForPage(sidebarItems, normalizedPath, srcDir)
if (!newLinks.length) return false
const mergedLinks = removeDuplicates(mergeSectionLinks(existingLinks, newLinks))
if (!hasChanges(existingLinks, mergedLinks, newLinks)) return false
frontmatter.section_links = mergedLinks
const updatedContent = stringifyFrontmatter(frontmatter, content)
writeFileSync(filePath, updatedContent, 'utf-8')
return true
} catch {
return false
}
}