diff --git a/website/src/theme/DocItem/Content/index.tsx b/website/src/theme/DocItem/Content/index.tsx index 63ea4b0e01..78e02c3b25 100644 --- a/website/src/theme/DocItem/Content/index.tsx +++ b/website/src/theme/DocItem/Content/index.tsx @@ -26,9 +26,41 @@ class MarkdownLintError extends Error { } } +function useBadgeLinterEffect() { + const { frontMatter, metadata } = useDoc(); + const { hide_title } = frontMatter; + const { id } = metadata; + + useEffect(() => { + if (hide_title) { + console.debug(`Skipping badge linting for ${id} because \`hide_title\` is set`); + return; + } + + const invalidBadges = document.querySelectorAll(`.theme-doc-markdown > header + .badge, + .theme-doc-markdown .markdown > .badge + `); + + const badgeCount = invalidBadges.length; + + if (!badgeCount) return; + + const badgeContent = Array.from(invalidBadges, (badge) => `"${badge.textContent}"`); + + const message = `${id}: ${badgeCount} Badge(s) defined in Markdown content instead of the frontmatter:\n ${badgeContent.join("\n")}`; + + console.error(message); + + console.error(`Found ${badgeCount} invalid badges on ${id}`, invalidBadges); + + throw new MarkdownLintError(message); + }, [hide_title, id]); +} + const DocItemContent: React.FC = ({ children }) => { const syntheticTitle = useSyntheticTitle(); const { frontMatter, metadata, contentTitle } = useDoc(); + const { id } = metadata; const { // --- support_level, @@ -37,6 +69,8 @@ const DocItemContent: React.FC = ({ children }) => { authentik_preview, } = frontMatter; + useBadgeLinterEffect(); + const badges: JSX.Element[] = []; if (authentik_version) { @@ -57,46 +91,23 @@ const DocItemContent: React.FC = ({ children }) => { if (badges.length && !syntheticTitle) { throw new MarkdownLintError( - `${metadata.id}: ${badges.length} Badge(s) found with a missing synthetic title. Remove the page heading and set it via the frontmatter.`, + `${id}: ${badges.length} Badge(s) found with a missing synthetic title. Remove the page heading and set it via the frontmatter.`, ); } if (frontMatter.title && contentTitle && frontMatter.title === contentTitle) { throw new MarkdownLintError( - `${metadata.id}: Synthetic title "${frontMatter.title}" and content title "${contentTitle}" are the same. Remove the first heading and let the frontmatter set the title.`, + `${id}: Synthetic title "${frontMatter.title}" and content title "${contentTitle}" are the same. Remove the first heading and let the frontmatter set the title.`, ); } - useEffect(() => { - const invalidBadges = document.querySelectorAll(`.theme-doc-markdown > header + .badge, - .theme-doc-markdown .markdown > .badge - `); - - if (!invalidBadges.length) return; - - console.error( - `Found ${invalidBadges.length} invalid badges on ${metadata.id}`, - invalidBadges, - ); - - throw new MarkdownLintError( - `${metadata.id}: ${invalidBadges.length} Badge(s) defined in markdown content instead of the frontmatter.`, - ); - }, [metadata.id]); - return (
{syntheticTitle ? (
{syntheticTitle} - {badges.length ? ( -

- {badges.map((badge, index) => ( - {badge} - ))} -

- ) : null} +
) : null} @@ -105,4 +116,20 @@ const DocItemContent: React.FC = ({ children }) => { ); }; +interface BadgesProps { + badges: JSX.Element[]; +} + +const BadgeGroup: React.FC = ({ badges }) => { + if (!badges.length) return null; + + return ( +

+ {badges.map((badge, index) => ( + {badge} + ))} +

+ ); +}; + export default DocItemContent;