Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { hasFile } from './hasFile.js'
import { convertToMDX } from './convertToMDX.js'
import { mkdir, copyFile } from 'fs/promises'
import { fileURLToPath } from 'url'
import { fileExists } from './fileExists.js'

const currentDir = process.cwd()
Expand All @@ -34,8 +35,11 @@
.replace('file://', '')
} catch (e: any) {
if (e.code === 'ERR_MODULE_NOT_FOUND') {
console.log('@patternfly/patternfly-doc-core not found, using current directory as astroRoot')
astroRoot = process.cwd()
// When running from the doc-core package itself (e.g. via portal: link),
// derive astroRoot from the CLI's own location (dist/cli/cli.js)
const cliDir = dirname(fileURLToPath(import.meta.url))

Check failure on line 40 in cli/cli.ts

View workflow job for this annotation

GitHub Actions / build (22.x)

Cannot find name 'dirname'. Did you mean '__dirname'?
astroRoot = resolve(cliDir, '..', '..')
Comment thread
coderabbitai[bot] marked this conversation as resolved.
console.log('Resolved astroRoot from CLI location:', astroRoot)
} else {
console.error('Error resolving astroRoot', e)
}
Expand Down
2 changes: 2 additions & 0 deletions cli/getConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export interface CollectionDefinition {
version?: string
pattern: string
name: string
frontmatterDefaults?: Record<string, string>
frontmatterMapping?: Record<string, string>
}

export interface PropsGlobs {
Expand Down
1 change: 1 addition & 0 deletions src/components/NavEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface TextContentEntry {
section: string
tab?: string
sortValue?: number
subsection?: string
}
}

Expand Down
35 changes: 32 additions & 3 deletions src/components/NavSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,20 @@ export const NavSection = ({
const isExpanded = window.location.pathname.includes(kebabCase(sectionId))
const isActive = entries.some((entry) => entry.id === activeItem)

const items = entries.map((entry) => (
// Group entries by subsection
const topLevelEntries = entries.filter((entry) => !entry.data.subsection)
const subsections = new Map<string, TextContentEntry[]>()
entries.forEach((entry) => {
if (entry.data.subsection) {
const sub = entry.data.subsection
if (!subsections.has(sub)) {
subsections.set(sub, [])
}
subsections.get(sub)!.push(entry)
}
})

const renderEntry = (entry: TextContentEntry) => (
<NavEntry
key={entry.id}
entry={entry}
Expand All @@ -25,7 +38,7 @@ export const NavSection = ({
window.location.pathname.includes(kebabCase(entry.data.id))
}
/>
))
)

return (
<NavExpandable
Expand All @@ -34,7 +47,23 @@ export const NavSection = ({
isExpanded={isExpanded}
id={`nav-section-${sectionId}`}
>
{items}
{topLevelEntries.map(renderEntry)}
{Array.from(subsections.entries()).map(([subsection, subEntries]) => {
const subIsExpanded = subEntries.some(
(entry) => activeItem === entry.id || window.location.pathname.includes(kebabCase(entry.data.id))
)
return (
<NavExpandable
key={subsection}
title={sentenceCase(subsection)}
isActive={subIsExpanded}
isExpanded={subIsExpanded || isExpanded}
id={`nav-subsection-${sectionId}-${subsection}`}
>
{subEntries.map(renderEntry)}
</NavExpandable>
)
})}
</NavExpandable>
)
}
2 changes: 1 addition & 1 deletion src/components/Navigation.astro
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const sortedSections = [...orderedSections, ...unorderedSections.sort()]
const navData = sortedSections.map((section) => {
const entries = navDataRaw
.filter((entry) => entry.data.section === section)
.map(entry => ({ id: entry.id, data: { id: entry.data.id, section, sortValue: entry.data.sortValue }} as TextContentEntry))
.map(entry => ({ id: entry.id, data: { id: entry.data.id, section, sortValue: entry.data.sortValue, subsection: entry.data.subsection }} as TextContentEntry))

const uniqueEntries = [
...entries
Expand Down
70 changes: 50 additions & 20 deletions src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import type { CollectionDefinition } from '../cli/getConfig'
import { convertToMDX } from '../cli/convertToMDX'

function defineContent(contentObj: CollectionDefinition) {
const { base, packageName, pattern, name } = contentObj

const { base, packageName, pattern, name, frontmatterDefaults, frontmatterMapping } = contentObj

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

const hasExternalFrontmatter = !!(frontmatterDefaults || frontmatterMapping)

const baseSchema = z.object({
id: hasExternalFrontmatter ? z.string().optional() : z.string(),
section: hasExternalFrontmatter ? z.string().optional() : z.string(),
subsection: z.string().optional(),
title: z.string().optional(),
// Generic frontmatter fields from external sources
category: z.string().optional(),
subcategory: z.string().optional(),
description: z.string().optional(),
tags: z.array(z.string()).optional(),
propComponents: z.array(z.string()).optional(),
tab: z.string().optional().default(tabMap[name]), // for component tabs
source: z.string().optional(),
tabName: z.string().optional(),
sortValue: z.number().optional(), // used for sorting nav entries,
cssPrefix: z
.union([
z.string().transform((val: string) => [val]),
z.array(z.string()),
z.null().transform(() => undefined),
])
.optional(),
}).transform((data) => {
const result: Record<string, unknown> = { ...data }
Comment thread
wise-king-sullyman marked this conversation as resolved.

// Apply frontmatter mapping (e.g. { title: "id" } maps the title value to id)
if (frontmatterMapping) {
for (const [sourceField, targetField] of Object.entries(frontmatterMapping)) {
if (result[sourceField] != null && result[targetField] == null) {
result[targetField] = result[sourceField]
}
}
}

// Apply frontmatter defaults (e.g. { section: "AI" } sets section if not already present)
if (frontmatterDefaults) {
for (const [field, value] of Object.entries(frontmatterDefaults)) {
if (result[field] == null) {
result[field] = value
}
}
}

return result
})

return defineCollection({
loader: glob({ base, pattern: mdxPattern }),
schema: z.object({
id: z.string(),
section: z.string(),
subsection: z.string().optional(),
title: z.string().optional(),
propComponents: z.array(z.string()).optional(),
tab: z.string().optional().default(tabMap[name]), // for component tabs
source: z.string().optional(),
tabName: z.string().optional(),
sortValue: z.number().optional(), // used for sorting nav entries,
cssPrefix: z
.union([
z.string().transform((val: string) => [val]),
z.array(z.string()),
z.null().transform(() => undefined),
])
.optional(),
}),
schema: baseSchema,
})
}

Expand Down
2 changes: 1 addition & 1 deletion src/pages/[section]/[...page].astro
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export async function getStaticPaths() {
}

return {
params: { page: kebabCase(entry.data.id), section: entry.data.section },
params: { page: kebabCase(entry.data.id), section: kebabCase(entry.data.section) },
Comment thread
coderabbitai[bot] marked this conversation as resolved.
props: {
entry,
title: entry.data.title,
Expand Down
2 changes: 1 addition & 1 deletion src/pages/[section]/[page]/[tab].astro
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export async function getStaticPaths() {
return {
params: {
page: kebabCase(entry.data.id),
section: entry.data.section,
section: kebabCase(entry.data.section),
Comment thread
coderabbitai[bot] marked this conversation as resolved.
tab,
},
props: { entry, ...entry.data },
Expand Down
Loading