feat(nx-dev): read description from markdown frontmatter for index pages (#31566)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior

Index pages read from the map.json description which is missing for a
lot of entries.

<img width="853" alt="image"
src="https://github.com/user-attachments/assets/8c0db9a2-d293-482d-8597-647cda47cc93"
/>


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

The new logic

- checks the corresponding markdown file `description` property which is
also used for the HTML meta description tags
- falls back to the `map.json` description

<img width="809" alt="image"
src="https://github.com/user-attachments/assets/716358f0-bab9-4bd4-97b2-b31fa151ebe0"
/>



## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
This commit is contained in:
Juri Strumpflohner 2025-06-13 14:52:53 +02:00 committed by GitHub
parent d2d18a6cb4
commit 6bc4ef47ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -5,9 +5,10 @@ import {
type RelatedDocument, type RelatedDocument,
} from '@nx/nx-dev/models-document'; } from '@nx/nx-dev/models-document';
import { type ProcessedPackageMetadata } from '@nx/nx-dev/models-package'; import { type ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
import { readdirSync, readFileSync } from 'node:fs'; import { readdirSync, readFileSync, existsSync } from 'node:fs';
import { join } from 'node:path'; import { join } from 'node:path';
import { type TagsApi } from './tags.api'; import { type TagsApi } from './tags.api';
import { extractFrontmatter } from '@nx/nx-dev/ui-markdoc';
interface StaticDocumentPaths { interface StaticDocumentPaths {
params: { segments: string[] }; params: { segments: string[] };
@ -282,11 +283,36 @@ export class DocumentsApi {
generateDocumentIndexTemplate(document: DocumentMetadata): string { generateDocumentIndexTemplate(document: DocumentMetadata): string {
const cardsTemplate = document.itemList const cardsTemplate = document.itemList
.map((i) => ({ .map((i) => {
title: i.name, // Try to get description from frontmatter first
description: i.description ?? '', let description = i.description ?? '';
url: i.path,
})) // Get the document metadata to find the file path
// i.path might already have a leading slash or might not, so we need to check both
const itemDocument =
this.manifest[i.path] || this.manifest[this.getManifestKey(i.path)];
if (itemDocument && itemDocument.file) {
const filePath = this.getFilePath(`${itemDocument.file}.md`);
if (existsSync(filePath)) {
try {
const content = readFileSync(filePath, 'utf8');
const frontmatter = extractFrontmatter(content);
// Use frontmatter description if available, otherwise fall back to map.json description
description = frontmatter.description || description;
} catch (e) {
// If there's an error reading the file, fall back to the original description
console.warn(`Could not read frontmatter from ${filePath}:`, e);
}
}
}
return {
title: i.name,
description,
url: i.path,
};
})
.map( .map(
(card) => (card) =>
`{% card title="${card.title}" description="${ `{% card title="${card.title}" description="${