Skip to content

Commit a405709

Browse files
committed
Update parsing to work with the more generic project-felt markdown repo
1 parent 10aeffc commit a405709

8 files changed

Lines changed: 94 additions & 28 deletions

File tree

cli/cli.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { buildPropsData } from './buildPropsData.js'
1313
import { hasFile } from './hasFile.js'
1414
import { convertToMDX } from './convertToMDX.js'
1515
import { mkdir, copyFile } from 'fs/promises'
16+
import { fileURLToPath } from 'url'
1617
import { fileExists } from './fileExists.js'
1718

1819
const currentDir = process.cwd()
@@ -34,8 +35,11 @@ try {
3435
.replace('file://', '')
3536
} catch (e: any) {
3637
if (e.code === 'ERR_MODULE_NOT_FOUND') {
37-
console.log('@patternfly/patternfly-doc-core not found, using current directory as astroRoot')
38-
astroRoot = process.cwd()
38+
// When running from the doc-core package itself (e.g. via portal: link),
39+
// derive astroRoot from the CLI's own location (dist/cli/cli.js)
40+
const cliDir = dirname(fileURLToPath(import.meta.url))
41+
astroRoot = resolve(cliDir, '..', '..')
42+
console.log('Resolved astroRoot from CLI location:', astroRoot)
3943
} else {
4044
console.error('Error resolving astroRoot', e)
4145
}

cli/getConfig.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export interface CollectionDefinition {
55
version?: string
66
pattern: string
77
name: string
8+
frontmatterDefaults?: Record<string, string>
9+
frontmatterMapping?: Record<string, string>
810
}
911

1012
export interface PropsGlobs {

src/components/NavEntry.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface TextContentEntry {
88
section: string
99
tab?: string
1010
sortValue?: number
11+
subsection?: string
1112
}
1213
}
1314

src/components/NavSection.tsx

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,20 @@ export const NavSection = ({
1616
const isExpanded = window.location.pathname.includes(kebabCase(sectionId))
1717
const isActive = entries.some((entry) => entry.id === activeItem)
1818

19-
const items = entries.map((entry) => (
19+
// Group entries by subsection
20+
const topLevelEntries = entries.filter((entry) => !entry.data.subsection)
21+
const subsections = new Map<string, TextContentEntry[]>()
22+
entries.forEach((entry) => {
23+
if (entry.data.subsection) {
24+
const sub = entry.data.subsection
25+
if (!subsections.has(sub)) {
26+
subsections.set(sub, [])
27+
}
28+
subsections.get(sub)!.push(entry)
29+
}
30+
})
31+
32+
const renderEntry = (entry: TextContentEntry) => (
2033
<NavEntry
2134
key={entry.id}
2235
entry={entry}
@@ -25,7 +38,7 @@ export const NavSection = ({
2538
window.location.pathname.includes(kebabCase(entry.data.id))
2639
}
2740
/>
28-
))
41+
)
2942

3043
return (
3144
<NavExpandable
@@ -34,7 +47,23 @@ export const NavSection = ({
3447
isExpanded={isExpanded}
3548
id={`nav-section-${sectionId}`}
3649
>
37-
{items}
50+
{topLevelEntries.map(renderEntry)}
51+
{Array.from(subsections.entries()).map(([subsection, subEntries]) => {
52+
const subIsExpanded = subEntries.some(
53+
(entry) => activeItem === entry.id || window.location.pathname.includes(kebabCase(entry.data.id))
54+
)
55+
return (
56+
<NavExpandable
57+
key={subsection}
58+
title={sentenceCase(subsection)}
59+
isActive={subIsExpanded}
60+
isExpanded={subIsExpanded || isExpanded}
61+
id={`nav-subsection-${sectionId}-${subsection}`}
62+
>
63+
{subEntries.map(renderEntry)}
64+
</NavExpandable>
65+
)
66+
})}
3867
</NavExpandable>
3968
)
4069
}

src/components/Navigation.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const sortedSections = [...orderedSections, ...unorderedSections.sort()]
3939
const navData = sortedSections.map((section) => {
4040
const entries = navDataRaw
4141
.filter((entry) => entry.data.section === section)
42-
.map(entry => ({ id: entry.id, data: { id: entry.data.id, section, sortValue: entry.data.sortValue }} as TextContentEntry))
42+
.map(entry => ({ id: entry.id, data: { id: entry.data.id, section, sortValue: entry.data.sortValue, subsection: entry.data.subsection }} as TextContentEntry))
4343
4444
const uniqueEntries = [
4545
...entries

src/content.config.ts

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import type { CollectionDefinition } from '../cli/getConfig'
66
import { convertToMDX } from '../cli/convertToMDX'
77

88
function defineContent(contentObj: CollectionDefinition) {
9-
const { base, packageName, pattern, name } = contentObj
10-
9+
const { base, packageName, pattern, name, frontmatterDefaults, frontmatterMapping } = contentObj
1110

1211
if (!base && !packageName) {
1312
// eslint-disable-next-line no-console
@@ -24,26 +23,57 @@ function defineContent(contentObj: CollectionDefinition) {
2423
convertToMDX(`${base}/${pattern}`)
2524
const mdxPattern = pattern.replace(/\.md$/, '.mdx')
2625

26+
const hasExternalFrontmatter = !!(frontmatterDefaults || frontmatterMapping)
27+
28+
const baseSchema = z.object({
29+
id: hasExternalFrontmatter ? z.string().optional() : z.string(),
30+
section: hasExternalFrontmatter ? z.string().optional() : z.string(),
31+
subsection: z.string().optional(),
32+
title: z.string().optional(),
33+
// Generic frontmatter fields from external sources
34+
category: z.string().optional(),
35+
subcategory: z.string().optional(),
36+
description: z.string().optional(),
37+
tags: z.array(z.string()).optional(),
38+
propComponents: z.array(z.string()).optional(),
39+
tab: z.string().optional().default(tabMap[name]), // for component tabs
40+
source: z.string().optional(),
41+
tabName: z.string().optional(),
42+
sortValue: z.number().optional(), // used for sorting nav entries,
43+
cssPrefix: z
44+
.union([
45+
z.string().transform((val: string) => [val]),
46+
z.array(z.string()),
47+
z.null().transform(() => undefined),
48+
])
49+
.optional(),
50+
}).transform((data) => {
51+
const result: Record<string, unknown> = { ...data }
52+
53+
// Apply frontmatter mapping (e.g. { title: "id" } maps the title value to id)
54+
if (frontmatterMapping) {
55+
for (const [sourceField, targetField] of Object.entries(frontmatterMapping)) {
56+
if (result[sourceField] != null && result[targetField] == null) {
57+
result[targetField] = result[sourceField]
58+
}
59+
}
60+
}
61+
62+
// Apply frontmatter defaults (e.g. { section: "AI" } sets section if not already present)
63+
if (frontmatterDefaults) {
64+
for (const [field, value] of Object.entries(frontmatterDefaults)) {
65+
if (result[field] == null) {
66+
result[field] = value
67+
}
68+
}
69+
}
70+
71+
return result
72+
})
73+
2774
return defineCollection({
2875
loader: glob({ base, pattern: mdxPattern }),
29-
schema: z.object({
30-
id: z.string(),
31-
section: z.string(),
32-
subsection: z.string().optional(),
33-
title: z.string().optional(),
34-
propComponents: z.array(z.string()).optional(),
35-
tab: z.string().optional().default(tabMap[name]), // for component tabs
36-
source: z.string().optional(),
37-
tabName: z.string().optional(),
38-
sortValue: z.number().optional(), // used for sorting nav entries,
39-
cssPrefix: z
40-
.union([
41-
z.string().transform((val: string) => [val]),
42-
z.array(z.string()),
43-
z.null().transform(() => undefined),
44-
])
45-
.optional(),
46-
}),
76+
schema: baseSchema,
4777
})
4878
}
4979

src/pages/[section]/[...page].astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export async function getStaticPaths() {
5757
}
5858
5959
return {
60-
params: { page: kebabCase(entry.data.id), section: entry.data.section },
60+
params: { page: kebabCase(entry.data.id), section: kebabCase(entry.data.section) },
6161
props: {
6262
entry,
6363
title: entry.data.title,

src/pages/[section]/[page]/[tab].astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export async function getStaticPaths() {
6464
return {
6565
params: {
6666
page: kebabCase(entry.data.id),
67-
section: entry.data.section,
67+
section: kebabCase(entry.data.section),
6868
tab,
6969
},
7070
props: { entry, ...entry.data },

0 commit comments

Comments
 (0)