Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(v2): fix contentTitle issues when markdown h1 title contains code blocks #4882

Merged
merged 11 commits into from
Jun 3, 2021
Merged
11 changes: 7 additions & 4 deletions packages/docusaurus-mdx-loader/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ module.exports = async function docusaurusMdxLoader(fileString) {

const {frontMatter, content: contentWithTitle} = parseFrontMatter(fileString);

// By default, will remove the markdown title from the content
const {content} = parseMarkdownContentTitle(contentWithTitle, {
keepContentTitle: reqOptions.keepContentTitle,
const {content, contentTitle} = parseMarkdownContentTitle(contentWithTitle, {
removeContentTitle: reqOptions.removeContentTitle,
});

const hasFrontMatter = Object.keys(frontMatter).length > 0;
Expand Down Expand Up @@ -69,7 +68,11 @@ module.exports = async function docusaurusMdxLoader(fileString) {
return callback(err);
}

let exportStr = `export const frontMatter = ${stringifyObject(frontMatter)};`;
let exportStr = ``;
exportStr += `\nexport const frontMatter = ${stringifyObject(frontMatter)};`;
exportStr += `\nexport const contentTitle = ${stringifyObject(
contentTitle,
)};`;

// Read metadata for this MDX and export it.
if (options.metadataPath && typeof options.metadataPath === 'function') {
Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus-plugin-content-blog/src/blogUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export async function generateBlogPosts(
content,
contentTitle,
excerpt,
} = await parseMarkdownFile(source);
} = await parseMarkdownFile(source, {removeContentTitle: true});
const frontMatter = validateBlogPostFrontMatter(unsafeFrontMatter);

const aliasedSource = aliasedSitePath(source, siteDir);
Expand Down
3 changes: 3 additions & 0 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,9 @@ export default function pluginContentBlog(
`${docuHash(aliasedPath)}.json`,
);
},
// For blog posts a title in markdown is always removed
// Blog posts title are rendered separately
removeContentTitle: true,
},
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ Object {
\\"unversionedId\\": \\"foo/bar\\",
\\"id\\": \\"foo/bar\\",
\\"isDocsHomePage\\": false,
\\"title\\": \\"Remarkable\\",
\\"title\\": \\"Bar\\",
\\"description\\": \\"This is custom description\\",
\\"source\\": \\"@site/docs/foo/bar.md\\",
\\"sourceDirName\\": \\"foo\\",
Expand All @@ -190,7 +190,7 @@ Object {
\\"unversionedId\\": \\"foo/baz\\",
\\"id\\": \\"foo/baz\\",
\\"isDocsHomePage\\": false,
\\"title\\": \\"Baz markdown title\\",
\\"title\\": \\"baz\\",
\\"description\\": \\"Images\\",
\\"source\\": \\"@site/docs/foo/baz.md\\",
\\"sourceDirName\\": \\"foo\\",
Expand Down Expand Up @@ -418,12 +418,12 @@ Object {
\\"items\\": [
{
\\"type\\": \\"link\\",
\\"label\\": \\"Remarkable\\",
\\"label\\": \\"Bar\\",
\\"href\\": \\"/docs/foo/bar\\"
},
{
\\"type\\": \\"link\\",
\\"label\\": \\"Baz markdown title\\",
\\"label\\": \\"baz\\",
\\"href\\": \\"/docs/foo/bazSlug.html\\"
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ describe('simple site', () => {
isDocsHomePage: false,
permalink: '/docs/foo/bar',
slug: '/foo/bar',
title: 'Remarkable',
title: 'Bar',
description: 'This is custom description',
frontMatter: {
description: 'This is custom description',
Expand Down Expand Up @@ -254,7 +254,7 @@ describe('simple site', () => {
isDocsHomePage: true,
permalink: '/docs/',
slug: '/',
title: 'Remarkable',
title: 'Bar',
description: 'This is custom description',
frontMatter: {
description: 'This is custom description',
Expand Down Expand Up @@ -286,7 +286,7 @@ describe('simple site', () => {
isDocsHomePage: false,
permalink: '/docs/foo/bazSlug.html',
slug: '/foo/bazSlug.html',
title: 'Baz markdown title',
title: 'baz',
editUrl:
'https://github.com/facebook/docusaurus/edit/master/website/docs/foo/baz.md',
description: 'Images',
Expand Down Expand Up @@ -345,7 +345,7 @@ describe('simple site', () => {
isDocsHomePage: false,
permalink: '/docs/foo/bazSlug.html',
slug: '/foo/bazSlug.html',
title: 'Baz markdown title',
title: 'baz',
editUrl: hardcodedEditUrl,
description: 'Images',
frontMatter: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ describe('simple website', () => {
'foo',
'bar.md',
),
title: 'Remarkable',
title: 'Bar',
description: 'This is custom description',
frontMatter: {
description: 'This is custom description',
Expand Down
10 changes: 4 additions & 6 deletions packages/docusaurus-plugin-content-docs/src/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,9 @@ export function processDocMetadata({
numberPrefixParser: options.numberPrefixParser,
});

// TODO expose both headingTitle+metaTitle to theme?
// Different fallbacks order on purpose!
// See https://github.com/facebook/docusaurus/issues/4665#issuecomment-825831367
const headingTitle: string = contentTitle ?? frontMatter.title ?? baseID;
// const metaTitle: string = frontMatter.title ?? contentTitle ?? baseID;
// Note: the title is used by default for page title, sidebar label, pagination buttons...
// frontMatter.title should be used in priority over contentTitle (because it can contain markdown/JSX syntax)
const title: string = frontMatter.title ?? contentTitle ?? baseID;

const description: string = frontMatter.description ?? excerpt ?? '';

Expand Down Expand Up @@ -245,7 +243,7 @@ export function processDocMetadata({
unversionedId,
id,
isDocsHomePage,
title: headingTitle,
title,
description,
source: aliasedSitePath(filePath, siteDir),
sourceDirName,
Expand Down
6 changes: 1 addition & 5 deletions packages/docusaurus-plugin-content-docs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,7 @@ export default function pluginContentDocs(
nextId,
} = sidebarsUtils.getDocNavigation(doc.id);
const toDocNavLink = (navDocId: string): DocNavLink => ({
// Use frontMatter.title in priority over a potential # title found in markdown
// See https://github.com/facebook/docusaurus/issues/4665#issuecomment-825831367
title:
docsBaseById[navDocId].frontMatter.title ||
docsBaseById[navDocId].title,
title: docsBaseById[navDocId].title,
permalink: docsBaseById[navDocId].permalink,
});
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ declare module '@theme/DocItem' {
readonly frontMatter: FrontMatter;
readonly metadata: Metadata;
readonly toc: readonly TOCItem[];
readonly contentTitle: string | undefined;
(): JSX.Element;
};
};
Expand Down
1 change: 0 additions & 1 deletion packages/docusaurus-plugin-content-pages/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ export default function pluginContentPages(
rehypePlugins,
beforeDefaultRehypePlugins,
beforeDefaultRemarkPlugins,
keepContentTitle: true,
staticDir: path.join(siteDir, STATIC_DIR_NAME),
// Note that metadataPath must be the same/in-sync as
// the path from createData for each MDX.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ function BlogPostItem(props: Props): JSX.Element {
truncated,
isBlogPostPage = false,
} = props;
const {date, formattedDate, permalink, tags, readingTime} = metadata;
const {author, title, image, keywords} = frontMatter;
const {date, formattedDate, permalink, tags, readingTime, title} = metadata;
const {author, image, keywords} = frontMatter;

const authorURL = frontMatter.author_url || frontMatter.authorURL;
const authorTitle = frontMatter.author_title || frontMatter.authorTitle;
Expand Down
22 changes: 13 additions & 9 deletions packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import LastUpdated from '@theme/LastUpdated';
import type {Props} from '@theme/DocItem';
import TOC from '@theme/TOC';
import EditThisPage from '@theme/EditThisPage';
import {MainHeading} from '@theme/Heading';

import clsx from 'clsx';
import styles from './styles.module.css';
Expand Down Expand Up @@ -49,13 +50,15 @@ function DocItem(props: Props): JSX.Element {
// See https://github.com/facebook/docusaurus/issues/3362
const showVersionBadge = versions.length > 1;

// For meta title, using frontMatter.title in priority over a potential # title found in markdown
// See https://github.com/facebook/docusaurus/issues/4665#issuecomment-825831367
const metaTitle = frontMatter.title || title;
// We only add a title if:
// - user asks to hide it with frontmatter
// - the markdown content does not already contain a top-level h1 heading
const shouldAddTitle =
!hideTitle && typeof DocContent.contentTitle === 'undefined';

return (
<>
<Seo {...{title: metaTitle, description, keywords, image}} />
<Seo {...{title, description, keywords, image}} />

<div className="row">
<div
Expand All @@ -72,12 +75,13 @@ function DocItem(props: Props): JSX.Element {
</span>
</div>
)}
{!hideTitle && (
<header>
<h1 className={styles.docTitle}>{title}</h1>
</header>
)}
<div className="markdown">
{/*
Title can be declared inside md content or declared through frontmatter and added manually
To make both cases consistent, the added title is added under the same div.markdown block
See https://github.com/facebook/docusaurus/pull/4882#issuecomment-853021120
*/}
{shouldAddTitle && <MainHeading>{title}</MainHeading>}
<DocContent />
</div>
</article>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/

.docTitle {
font-size: 3rem;
margin-bottom: calc(var(--ifm-leading-desktop) * var(--ifm-leading));
}

.docItemContainer {
margin: 0 auto;
padding: 0 0.5rem;
Expand Down
23 changes: 22 additions & 1 deletion packages/docusaurus-theme-classic/src/theme/Heading/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,24 @@ import {useThemeConfig} from '@docusaurus/theme-common';
import './styles.css';
import styles from './styles.module.css';

const Heading = (Tag: HeadingType): ((props: Props) => JSX.Element) =>
type HeadingComponent = (props: Props) => JSX.Element;

export const MainHeading: HeadingComponent = function MainHeading({...props}) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For h1 found in MDX we don't add anchors.

This is a potential side-effect for a minority of users but using multiple h1 in a doc is not something they should do in the first place

return (
<header>
<h1
{...props}
id={undefined} // h1 headings do not need an id because they don't appear in the TOC
className={styles.h1Heading}>
{props.children}
</h1>
</header>
);
};

const createAnchorHeading = (
Tag: HeadingType,
): ((props: Props) => JSX.Element) =>
function TargetComponent({id, ...props}) {
const {
navbar: {hideOnScroll},
Expand Down Expand Up @@ -51,4 +68,8 @@ const Heading = (Tag: HeadingType): ((props: Props) => JSX.Element) =>
);
};

const Heading = (headingType: HeadingType): ((props: Props) => JSX.Element) => {
return headingType === 'h1' ? MainHeading : createAnchorHeading(headingType);
};

export default Heading;
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@
.enhancedAnchor {
top: calc(var(--ifm-navbar-height) * -1 - 0.5rem);
}

.h1Heading {
font-size: 3rem;
margin-bottom: calc(var(--ifm-leading-desktop) * var(--ifm-leading));
}
1 change: 1 addition & 0 deletions packages/docusaurus-theme-classic/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ declare module '@theme/Heading' {

const Heading: (Tag: HeadingType) => (props: Props) => JSX.Element;
export default Heading;
export const MainHeading: (props: Props) => JSX.Element;
}

declare module '@theme/hooks/useAnnouncementBar' {
Expand Down
Loading