VEGA-6128 Генерация ссылок для index старниц
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user