Skip to content

Commit

Permalink
fix(nextra): use rehype-mdx-title to determine page title (#515)
Browse files Browse the repository at this point in the history
* fix(nextra): use `rehype-mdx-title` to determine page title

* Update packages/nextra/src/loader.ts

* Update packages/nextra/src/loader.ts

* add changeset
  • Loading branch information
dimaMachina committed Jul 23, 2022
1 parent 283e1f2 commit 8101efe
Show file tree
Hide file tree
Showing 13 changed files with 223 additions and 64 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-ghosts-argue.md
@@ -0,0 +1,5 @@
---
'nextra': patch
---

fix(nextra): use `rehype-mdx-title` to determine page title
5 changes: 1 addition & 4 deletions packages/nextra-theme-blog/src/index.tsx
Expand Up @@ -34,7 +34,6 @@ const BlogLayout = ({ config, contentNodes, opts }: LayoutProps) => {
let navPages: PageMapItem[] = []
const type = opts.meta.type || 'post'
const route = opts.route
const hasH1 = opts.hasH1
let back: string | null = null
// This only renders once per page
if (type === 'posts' || type === 'tag' || type === 'page') {
Expand Down Expand Up @@ -93,8 +92,6 @@ const BlogLayout = ({ config, contentNodes, opts }: LayoutProps) => {
const { theme, resolvedTheme } = useTheme()
const { query } = router
const tagName = type === 'tag' ? query.tag : null
const pageTitle = opts.meta.title || opts.titleText || ''
const mdxTitle = hasH1 && !pageTitle
let comments

if (config.cusdis) {
Expand Down Expand Up @@ -168,6 +165,7 @@ const BlogLayout = ({ config, contentNodes, opts }: LayoutProps) => {
</div>
) : null
const ref = React.useRef<HTMLHeadingElement>(null)
const pageTitle = opts.meta.title || opts.titleText || ''

return (
<>
Expand All @@ -186,7 +184,6 @@ const BlogLayout = ({ config, contentNodes, opts }: LayoutProps) => {
<article className="container prose prose-sm md:prose dark:prose-dark">
<HeadingContext.Provider value={ref}>
{pageTitle ? <h1>{pageTitle}</h1> : null}
{mdxTitle ? <h1 ref={ref}></h1> : null}
{type === 'post' ? (
/** @ts-expect-error */
<Meta {...meta} back={back} config={config} />
Expand Down
140 changes: 136 additions & 4 deletions packages/nextra/__test__/__snapshots__/compile.test.ts.snap
@@ -1,8 +1,141 @@
// Vitest Snapshot v1

exports[`process heading > code-h1 1`] = `
{
"headings": [
{
"children": [
{
"position": {
"end": {
"column": 16,
"line": 1,
"offset": 15,
},
"start": {
"column": 3,
"line": 1,
"offset": 2,
},
},
"type": "inlineCode",
"value": "codegen.yml",
},
],
"depth": 1,
"position": {
"end": {
"column": 16,
"line": 1,
"offset": 15,
},
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"type": "heading",
"value": "codegen.yml",
},
],
"result": "/*@jsxRuntime automatic @jsxImportSource react*/
import {useMDXComponents as _provideComponents} from \\"@mdx-js/react\\";
export const titleText = \\"codegen.yml\\";
function _createMdxContent(props) {
const _components = Object.assign({
h1: \\"h1\\",
code: \\"code\\"
}, _provideComponents(), props.components);
return <_components.h1><_components.code>{\\"codegen.yml\\"}</_components.code></_components.h1>;
}
function MDXContent(props = {}) {
const {wrapper: MDXLayout} = Object.assign({}, _provideComponents(), props.components);
return MDXLayout ? <MDXLayout {...props}><_createMdxContent {...props} /></MDXLayout> : _createMdxContent(props);
}
export default MDXContent;
",
"structurizedData": {},
}
`;

exports[`process heading > code-with-text-h1 1`] = `
{
"headings": [
{
"children": [
{
"position": {
"end": {
"column": 16,
"line": 1,
"offset": 15,
},
"start": {
"column": 3,
"line": 1,
"offset": 2,
},
},
"type": "inlineCode",
"value": "codegen.yml",
},
{
"position": {
"end": {
"column": 21,
"line": 1,
"offset": 20,
},
"start": {
"column": 16,
"line": 1,
"offset": 15,
},
},
"type": "text",
"value": " file",
},
],
"depth": 1,
"position": {
"end": {
"column": 21,
"line": 1,
"offset": 20,
},
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"type": "heading",
"value": "codegen.yml file",
},
],
"result": "/*@jsxRuntime automatic @jsxImportSource react*/
import {useMDXComponents as _provideComponents} from \\"@mdx-js/react\\";
export const titleText = \\"codegen.yml file\\";
function _createMdxContent(props) {
const _components = Object.assign({
h1: \\"h1\\",
code: \\"code\\"
}, _provideComponents(), props.components);
return <_components.h1><_components.code>{\\"codegen.yml\\"}</_components.code>{\\" file\\"}</_components.h1>;
}
function MDXContent(props = {}) {
const {wrapper: MDXLayout} = Object.assign({}, _provideComponents(), props.components);
return MDXLayout ? <MDXLayout {...props}><_createMdxContent {...props} /></MDXLayout> : _createMdxContent(props);
}
export default MDXContent;
",
"structurizedData": {},
}
`;

exports[`process heading > dynamic-h1 1`] = `
{
"hasH1": true,
"headings": [
{
"children": [
Expand Down Expand Up @@ -79,6 +212,7 @@ exports[`process heading > dynamic-h1 1`] = `
],
"result": "/*@jsxRuntime automatic @jsxImportSource react*/
import {useMDXComponents as _provideComponents} from \\"@mdx-js/react\\";
export const titleText = \\"Posts Tagged with “”\\";
import {useRouter} from 'next/router';
export const TagName = () => {
const {tag} = useRouter().query;
Expand All @@ -102,7 +236,6 @@ export default MDXContent;

exports[`process heading > no-h1 1`] = `
{
"hasH1": false,
"headings": [
{
"children": [
Expand Down Expand Up @@ -160,7 +293,6 @@ export default MDXContent;
exports[`process heading > static-h1 1`] = `
{
"hasH1": true,
"headings": [
{
"children": [
Expand Down Expand Up @@ -200,6 +332,7 @@ exports[`process heading > static-h1 1`] = `
],
"result": "/*@jsxRuntime automatic @jsxImportSource react*/
import {useMDXComponents as _provideComponents} from \\"@mdx-js/react\\";
export const titleText = \\"Hello World\\";
function _createMdxContent(props) {
const _components = Object.assign({
h1: \\"h1\\"
Expand All @@ -213,6 +346,5 @@ function MDXContent(props = {}) {
export default MDXContent;
",
"structurizedData": {},
"titleText": "Hello World",
}
`;
19 changes: 18 additions & 1 deletion packages/nextra/__test__/compile.test.ts
Expand Up @@ -3,7 +3,14 @@ import { it, describe, expect } from 'vitest'
import path from 'path'
import fs from 'fs/promises'

function loadFixture(name: string) {
type Name =
| 'code-h1.mdx'
| 'code-with-text-h1.mdx'
| 'dynamic-h1.mdx'
| 'no-h1.mdx'
| 'static-h1.mdx'

function loadFixture(name: Name): string {
const filePath = path.join(
process.cwd(),
'__test__',
Expand All @@ -15,6 +22,16 @@ function loadFixture(name: string) {
}

describe('process heading', () => {
it('code-h1', async () => {
const data = await loadFixture('code-h1.mdx')
const result = await compileMdx(data)
expect(result).toMatchSnapshot()
})
it('code-with-text-h1', async () => {
const data = await loadFixture('code-with-text-h1.mdx')
const result = await compileMdx(data)
expect(result).toMatchSnapshot()
})
it('static-h1', async () => {
const data = await loadFixture('static-h1.mdx')
const result = await compileMdx(data)
Expand Down
1 change: 1 addition & 0 deletions packages/nextra/__test__/fixture/headings/code-h1.mdx
@@ -0,0 +1 @@
# `codegen.yml`
@@ -0,0 +1 @@
# `codegen.yml` file
16 changes: 0 additions & 16 deletions packages/nextra/__test__/fixture/headings/index.ts

This file was deleted.

1 change: 1 addition & 0 deletions packages/nextra/package.json
Expand Up @@ -32,6 +32,7 @@
"github-slugger": "^1.4.0",
"graceful-fs": "^4.2.10",
"gray-matter": "^4.0.3",
"rehype-mdx-title": "^1.0.0",
"rehype-pretty-code": "^0.1.0",
"remark-gfm": "^3.0.1",
"shiki": "0.10.1",
Expand Down
11 changes: 6 additions & 5 deletions packages/nextra/src/compile.ts
@@ -1,8 +1,9 @@
import { createProcessor, ProcessorOptions } from '@mdx-js/mdx'
import remarkGfm from 'remark-gfm'
import rehypePrettyCode from 'rehype-pretty-code'
import { rehypeMdxTitle } from 'rehype-mdx-title';
import { remarkStaticImage } from './mdx-plugins/static-image'
import remarkHandler, { HeadingMeta } from './mdx-plugins/remark'
import { remarkHeadings, HeadingMeta } from './mdx-plugins/remark'
import { LoaderOptions } from './types'
import structurize from './mdx-plugins/structurize'
import { parseMeta, attachMeta } from './mdx-plugins/rehype-handler'
Expand All @@ -13,7 +14,6 @@ import theme from './theme.json'
const createCompiler = (mdxOptions: ProcessorOptions) => {
const compiler = createProcessor(mdxOptions)
compiler.data('headingMeta', {
hasH1: false,
headings: []
})
return compiler
Expand Down Expand Up @@ -50,17 +50,17 @@ export async function compileMdx(
LoaderOptions,
'unstable_staticImage' | 'unstable_flexsearch'
> = {},
resourcePath: string
resourcePath = ''
) {
let structurizedData = {}
const structurizedData = {}
const compiler = createCompiler({
jsx: mdxOptions.jsx ?? true,
outputFormat: mdxOptions.outputFormat,
providerImportSource: '@mdx-js/react',
remarkPlugins: [
...(mdxOptions.remarkPlugins || []),
remarkGfm,
remarkHandler,
remarkHeadings,
...(nextraOptions.unstable_staticImage ? [remarkStaticImage] : []),
...(nextraOptions.unstable_flexsearch
? [structurize(structurizedData, nextraOptions.unstable_flexsearch)]
Expand All @@ -74,6 +74,7 @@ export async function compileMdx(
rehypePrettyCode,
{ ...rehypePrettyCodeOptions, ...mdxOptions.rehypePrettyCodeOptions }
],
[rehypeMdxTitle, { name: 'titleText' }],
attachMeta
].filter(Boolean)
})
Expand Down

0 comments on commit 8101efe

Please sign in to comment.