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

MDX v2: Support FS routes #36118

Merged
merged 11 commits into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
14 changes: 6 additions & 8 deletions packages/gatsby-core-utils/src/parse-component-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ export const splitComponentPath = (componentPath: string): Array<string> => {
return [componentPath]
}

const splitPath = componentPath.split(CONTENT_FILE_PATH_QUERY)
const cleanedComponentPath = componentPath.replace(
/&export=(default|head)$/,
``
)
const splitPath = cleanedComponentPath.split(CONTENT_FILE_PATH_QUERY)

// We only support URI paths with the `?__contentFilePath=` parameter
if (splitPath.length !== 2) {
throw new Error(
`The following page component must contain '${CONTENT_FILE_PATH_QUERY}':\n${componentPath}`
`The following page component must contain '${CONTENT_FILE_PATH_QUERY}':\n${cleanedComponentPath}`
)
}

// Other URI parameters are not supported
if (splitPath[1].includes(`&`)) {
throw new Error(
`You can not pass any other parameters to a page component URI as 'contentFilePath'. Remove the ampersand (&):\n${componentPath}`
)
}
return splitPath
}

Expand Down
3 changes: 2 additions & 1 deletion packages/gatsby-plugin-mdx/src/gatsby-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const onCreateWebpackConfig: GatsbyNode["onCreateWebpackConfig"] =
},
{
test: /\.[tj]sx?$/,
resourceQuery: /__contentFilePath=.+\.mdx?$/,
resourceQuery: /__contentFilePath=.+\.mdx?(&export=.*)?$/,
use: [
loaders.js(),
{
Expand Down Expand Up @@ -281,6 +281,7 @@ export const onCreateNode: GatsbyNode<FileSystemNode>["onCreateNode"] = async ({
internal: {
type: `Mdx`,
contentDigest: node.internal.contentDigest,
contentFilePath: node.absolutePath,
},
body,
frontmatter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allProduct{nodes{name,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allProduct{nodes{name,id,internal{contentFilePath}}}}"`
)
})

it(`will create a basic query from the route with minimal length`, async () => {
Expand All @@ -53,7 +55,9 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allP{nodes{n,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allP{nodes{n,id,internal{contentFilePath}}}}"`
)
})

it(`will create a basic query from the route with a prefix variant 1`, async () => {
Expand All @@ -70,7 +74,9 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allProduct{nodes{name,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allProduct{nodes{name,id,internal{contentFilePath}}}}"`
)
})

it(`will create a basic query from the route with a prefix variant 2`, async () => {
Expand All @@ -87,7 +93,9 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allProduct{nodes{name,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allProduct{nodes{name,id,internal{contentFilePath}}}}"`
)
})

it(`will create a basic query from the route with a prefix variant 3`, async () => {
Expand All @@ -104,7 +112,9 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allProduct{nodes{name,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allProduct{nodes{name,id,internal{contentFilePath}}}}"`
)
})

it(`will create a basic query from the route with a postfix`, async () => {
Expand All @@ -121,7 +131,9 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allProduct{nodes{name,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allProduct{nodes{name,id,internal{contentFilePath}}}}"`
)
})

it(`will create a basic query with multiple entries`, async () => {
Expand All @@ -138,7 +150,9 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allProduct{nodes{name,color,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allProduct{nodes{name,color,id,internal{contentFilePath}}}}"`
)
})

it(`will create a basic query with multiple entries and different delimiters variant 1`, async () => {
Expand All @@ -155,7 +169,9 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allProduct{nodes{name,color,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allProduct{nodes{name,color,id,internal{contentFilePath}}}}"`
)
})

it(`will create a basic query with multiple entries and different delimiters variant 1`, async () => {
Expand All @@ -172,7 +188,9 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allProduct{nodes{name,color,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allProduct{nodes{name,color,id,internal{contentFilePath}}}}"`
)
})

it(`will create a basic query with multiple entries and different delimiters variant 1`, async () => {
Expand All @@ -189,6 +207,8 @@ describe(`collectionExtractQueryString`, () => {
reporter
)

expect(query).toMatchInlineSnapshot(`"{allProduct{nodes{name,color,id}}}"`)
expect(query).toMatchInlineSnapshot(
`"{allProduct{nodes{name,color,id,internal{contentFilePath}}}}"`
)
})
})
76 changes: 56 additions & 20 deletions packages/gatsby-plugin-page-creator/src/__tests__/extract-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ describe(`extract query`, () => {
`Thing`,
compatiblePath(`/foo/bar/{Thing.id}.js`)
)
).toBe(`{allThing{nodes{id}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{id,internal{contentFilePath}}}}"`
)
})

it(`handles lowercased model name`, () => {
Expand All @@ -24,7 +26,9 @@ describe(`extract query`, () => {
`contentfulType`,
compatiblePath(`/foo/{contentfulType.id}.js`)
)
).toBe(`{allContentfulType{nodes{id}}}`)
).toMatchInlineSnapshot(
`"{allContentfulType{nodes{id,internal{contentFilePath}}}}"`
)
})

it(`handles model name with underscore`, () => {
Expand All @@ -33,7 +37,9 @@ describe(`extract query`, () => {
`_customType`,
compatiblePath(`/foo/{_customType.id}.js`)
)
).toBe(`{allCustomType{nodes{id}}}`)
).toMatchInlineSnapshot(
`"{allCustomType{nodes{id,internal{contentFilePath}}}}"`
)
})

it(`handles model name with number`, () => {
Expand All @@ -42,7 +48,9 @@ describe(`extract query`, () => {
`Type123`,
compatiblePath(`/foo/{Type123.id}.js`)
)
).toBe(`{allType123{nodes{id}}}`)
).toMatchInlineSnapshot(
`"{allType123{nodes{id,internal{contentFilePath}}}}"`
)
})

it(`handles fields with number or underscore`, () => {
Expand All @@ -51,13 +59,17 @@ describe(`extract query`, () => {
`_type123`,
compatiblePath(`/foo/{_type123.field123}.js`)
)
).toBe(`{allType123{nodes{field123,id}}}`)
).toMatchInlineSnapshot(
`"{allType123{nodes{field123,id,internal{contentFilePath}}}}"`
)
expect(
generateQueryFromString(
`_type123`,
compatiblePath(`/foo/{_type123._field123}.js`)
)
).toBe(`{allType123{nodes{_field123,id}}}`)
).toMatchInlineSnapshot(
`"{allType123{nodes{_field123,id,internal{contentFilePath}}}}"`
)
})

it(`works with different file extensions`, () => {
Expand All @@ -66,7 +78,9 @@ describe(`extract query`, () => {
`Thing`,
compatiblePath(`/foo/bar/{Thing.id}.tsx`)
)
).toBe(`{allThing{nodes{id}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{id,internal{contentFilePath}}}}"`
)
})
})

Expand All @@ -77,7 +91,9 @@ describe(`extract query`, () => {
`Thing`,
compatiblePath(`/foo/bar/{Thing.id}.js`)
)
).toBe(`{allThing{nodes{id}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{id,internal{contentFilePath}}}}"`
)
})

it(`always queries id`, () => {
Expand All @@ -86,7 +102,9 @@ describe(`extract query`, () => {
`Thing`,
compatiblePath(`/foo/bar/{Thing.baz}.js`)
)
).toBe(`{allThing{nodes{baz,id}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{baz,id,internal{contentFilePath}}}}"`
)
})

it(`multiple nodes`, () => {
Expand All @@ -95,13 +113,17 @@ describe(`extract query`, () => {
`Thing`,
compatiblePath(`/foo/bar/{Thing.id}/{Thing.name}.js`)
)
).toBe(`{allThing{nodes{id,name}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{id,name,internal{contentFilePath}}}}"`
)
expect(
generateQueryFromString(
`Thing`,
compatiblePath(`/foo/bar/{Thing.id}-{Thing.name}.js`)
)
).toBe(`{allThing{nodes{id,name}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{id,name,internal{contentFilePath}}}}"`
)
})

it(`nested nodes`, () => {
Expand All @@ -110,7 +132,9 @@ describe(`extract query`, () => {
`Thing`,
compatiblePath(`/foo/bar/{Thing.id}/{Thing.fields__name}.js`)
)
).toBe(`{allThing{nodes{id,fields{name}}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{id,fields{name},internal{contentFilePath}}}}"`
)
})

it(`multiple nested nodes`, () => {
Expand All @@ -121,7 +145,9 @@ describe(`extract query`, () => {
`/foo/bar/{thing.fields__name}/{thing.fields__description}.js`
)
)
).toBe(`{allThing{nodes{fields{name},fields{description},id}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{fields{name},fields{description},id,internal{contentFilePath}}}}"`
)
})

it(`deeply nested nodes`, () => {
Expand All @@ -130,15 +156,19 @@ describe(`extract query`, () => {
`Thing`,
compatiblePath(`/foo/bar/{Thing.id}/{Thing.fields__name__thing}.js`)
)
).toBe(`{allThing{nodes{id,fields{name{thing}}}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{id,fields{name{thing}},internal{contentFilePath}}}}"`
)
expect(
generateQueryFromString(
`customType`,
compatiblePath(
`/foo/bar/{customType.id}/{customType.fields__name__thing}.js`
)
)
).toBe(`{allCustomType{nodes{id,fields{name{thing}}}}}`)
).toMatchInlineSnapshot(
`"{allCustomType{nodes{id,fields{name{thing}},internal{contentFilePath}}}}"`
)
})

it(`deeply nested nodes with prefixes`, () => {
Expand All @@ -149,7 +179,9 @@ describe(`extract query`, () => {
`/foo/bar/prefix-{Thing.id}/another-prefix_{Thing.fields__name__thing}.js`
)
)
).toBe(`{allThing{nodes{id,fields{name{thing}}}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{id,fields{name{thing}},internal{contentFilePath}}}}"`
)
})

it(`deeply nested nodes with postfixes`, () => {
Expand All @@ -160,7 +192,9 @@ describe(`extract query`, () => {
`/foo/bar/{Thing.id}-postfix/{Thing.fields__name__thing}_another-postfix.js`
)
)
).toBe(`{allThing{nodes{id,fields{name{thing}}}}}`)
).toMatchInlineSnapshot(
`"{allThing{nodes{id,fields{name{thing}},internal{contentFilePath}}}}"`
)
})

it(`supports graphql unions`, () => {
Expand All @@ -171,7 +205,9 @@ describe(`extract query`, () => {
`/foo/bar/{UnionQuery.id}/{UnionQuery.parent__(File)__relativePath}.js`
)
)
).toBe(`{allUnionQuery{nodes{id,parent{... on File{relativePath}}}}}`)
).toMatchInlineSnapshot(
`"{allUnionQuery{nodes{id,parent{... on File{relativePath}},internal{contentFilePath}}}}"`
)
})

it(`supports nested graphql unions`, () => {
Expand All @@ -182,8 +218,8 @@ describe(`extract query`, () => {
`/foo/bar/{UnionQuery.id}/{UnionQuery.parent__(File)__parent__(Bar)__relativePath}.js`
)
)
).toBe(
`{allUnionQuery{nodes{id,parent{... on File{parent{... on Bar{relativePath}}}}}}}`
).toMatchInlineSnapshot(
`"{allUnionQuery{nodes{id,parent{... on File{parent{... on Bar{relativePath}}}},internal{contentFilePath}}}}"`
)
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ ${errors.map(error => error.message).join(`\n`)}`.trim(),
// the watcher will use this data to delete the pages if the query changes significantly.
const paths: Array<string> = []
nodes.forEach((node: Record<string, Record<string, unknown>>) => {
const contentFilePath = node.internal?.contentFilePath
// URL path for the component and node
const { derivedPath, errors } = derivePath(
filePath,
Expand All @@ -141,10 +142,14 @@ ${errors.map(error => error.message).join(`\n`)}`.trim(),

const modifiedPath = applyTrailingSlashOption(path, trailingSlash)

const componentPath = contentFilePath
? `${absolutePath}?__contentFilePath=${contentFilePath}`
: absolutePath

actions.createPage({
path: modifiedPath,
matchPath,
component: absolutePath,
component: componentPath,
context: {
...nodeParams,
__params: params,
Expand Down
Loading