diff --git a/.circleci/config.yml b/.circleci/config.yml index 0d31d52c9a689..9fe269388f054 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -392,7 +392,7 @@ jobs: - run: echo 'export CYPRESS_RECORD_KEY="${CY_CLOUD_THEMES_DEV_RUNTIME}"' >> "$BASH_ENV" - e2e-test: test_path: e2e-tests/themes - test_command: cd development-runtime; yarn test + test_command: cd development-runtime; gatsby-dev --force-install --scan-once; yarn test themes_e2e_tests_production_runtime: <<: *e2e-executor @@ -400,7 +400,7 @@ jobs: - run: echo 'export CYPRESS_RECORD_KEY="${CY_CLOUD_THEMES_PROD_RUNTIME}"' >> "$BASH_ENV" - e2e-test: test_path: e2e-tests/themes - test_command: cd production-runtime; yarn test + test_command: cd production-runtime; gatsby-dev --force-install --scan-once; yarn test e2e_tests_mdx: <<: *e2e-executor diff --git a/e2e-tests/themes/development-runtime/content/posts/dune.mdx b/e2e-tests/themes/development-runtime/content/posts/dune.mdx new file mode 100644 index 0000000000000..d3e1924d7c9ae --- /dev/null +++ b/e2e-tests/themes/development-runtime/content/posts/dune.mdx @@ -0,0 +1,6 @@ +--- +title: Dune +slug: /dune +--- + +Dune is set in the distant future amidst a feudal interstellar society in which various noble houses control planetary fiefs. It tells the story of young Paul Atreides, whose family accepts the stewardship of the planet Arrakis. \ No newline at end of file diff --git a/e2e-tests/themes/development-runtime/package.json b/e2e-tests/themes/development-runtime/package.json index 901b3f07119c2..2b3357bac5da5 100644 --- a/e2e-tests/themes/development-runtime/package.json +++ b/e2e-tests/themes/development-runtime/package.json @@ -13,6 +13,7 @@ "scripts": { "build": "gatsby build", "develop": "gatsby develop", + "clean": "gatsby clean", "format": "prettier --write \"src/**/*.js\"", "serve": "gatsby serve", "start": "npm run develop", diff --git a/e2e-tests/themes/gatsby-theme-about/gatsby-config.js b/e2e-tests/themes/gatsby-theme-about/gatsby-config.js index 77b82a754b9b1..5550758ef636e 100644 --- a/e2e-tests/themes/gatsby-theme-about/gatsby-config.js +++ b/e2e-tests/themes/gatsby-theme-about/gatsby-config.js @@ -11,5 +11,13 @@ module.exports = { path: `${__dirname}/src/pages`, }, }, + { + resolve: `gatsby-source-filesystem`, + options: { + name: `posts`, + path: `./content/posts`, + }, + }, + `gatsby-plugin-mdx`, ], } diff --git a/e2e-tests/themes/gatsby-theme-about/gatsby-node.js b/e2e-tests/themes/gatsby-theme-about/gatsby-node.js index 4f29b8f3006b5..cfbb8c90a27f5 100644 --- a/e2e-tests/themes/gatsby-theme-about/gatsby-node.js +++ b/e2e-tests/themes/gatsby-theme-about/gatsby-node.js @@ -1,9 +1,44 @@ const bioTemplate = require.resolve(`./src/templates/bio.js`) +const postTemplate = require.resolve(`./src/templates/post.jsx`) -exports.createPages = async ({ actions }) => { - const { createPage } = actions - createPage({ - path: `/bio`, - component: bioTemplate, +exports.createPages = async ({ actions, graphql, reporter }) => { + const { createPage } = actions + + const result = await graphql(` + { + allMdx { + nodes { + id + frontmatter { + slug + } + internal { + contentFilePath + } + } + } + } + `) + + if (result.errors) { + reporter.panicOnBuild(`There was an error loading your posts or pages`, result.errors) + return + } + + const posts = result.data.allMdx.nodes + + posts.forEach((post) => { + createPage({ + path: post.frontmatter.slug, + component: `${postTemplate}?__contentFilePath=${post.internal.contentFilePath}`, + context: { + id: post.id, + }, }) + }) + + createPage({ + path: `/bio`, + component: bioTemplate, + }) } diff --git a/e2e-tests/themes/gatsby-theme-about/package.json b/e2e-tests/themes/gatsby-theme-about/package.json index 96555140a8f0b..a8d083c808e56 100644 --- a/e2e-tests/themes/gatsby-theme-about/package.json +++ b/e2e-tests/themes/gatsby-theme-about/package.json @@ -18,8 +18,11 @@ }, "homepage": "https://github.com/gatsbyjs/gatsby/tree/master/e2e-tests/themes/gatsby-theme-about#readme", "dependencies": { + "@mdx-js/react": "^2.3.0", "gatsby": "next", - "gatsby-plugin-page-creator": "next" + "gatsby-plugin-mdx": "next", + "gatsby-plugin-page-creator": "next", + "gatsby-source-filesystem": "next" }, "devDependencies": { "prettier": "2.8.7" diff --git a/e2e-tests/themes/gatsby-theme-about/src/templates/post.jsx b/e2e-tests/themes/gatsby-theme-about/src/templates/post.jsx new file mode 100644 index 0000000000000..eae806859ba07 --- /dev/null +++ b/e2e-tests/themes/gatsby-theme-about/src/templates/post.jsx @@ -0,0 +1,23 @@ +import React from "react" +import { graphql } from "gatsby" + +export default function Post({ data, children }) { + return ( +
+

{data.post.frontmatter.title}

+ {children} +
+ ) +} + +export const Head = () => Post + +export const query = graphql` + query($id: String!) { + post: mdx(id: { eq: $id }) { + frontmatter { + title + } + } + } +` diff --git a/e2e-tests/themes/production-runtime/content/posts/dune.mdx b/e2e-tests/themes/production-runtime/content/posts/dune.mdx new file mode 100644 index 0000000000000..d3e1924d7c9ae --- /dev/null +++ b/e2e-tests/themes/production-runtime/content/posts/dune.mdx @@ -0,0 +1,6 @@ +--- +title: Dune +slug: /dune +--- + +Dune is set in the distant future amidst a feudal interstellar society in which various noble houses control planetary fiefs. It tells the story of young Paul Atreides, whose family accepts the stewardship of the planet Arrakis. \ No newline at end of file diff --git a/e2e-tests/themes/production-runtime/cypress/integration/pages.js b/e2e-tests/themes/production-runtime/cypress/integration/pages.js index 6f6e3d978a638..b6fd555b5d8f7 100644 --- a/e2e-tests/themes/production-runtime/cypress/integration/pages.js +++ b/e2e-tests/themes/production-runtime/cypress/integration/pages.js @@ -28,4 +28,8 @@ describe(`Pages`, () => { cy.visit(`/about`).waitForRouteChange() cy.getTestElement(`author`).contains(`Sidhartha Chatterjee`) }) + it(`page templates with resourceQuery can be shadowed`, () => { + cy.visit(`/dune`).waitForRouteChange() + cy.getTestElement(`post-template`).contains(`Dune - Shadowed`) + }) }) diff --git a/e2e-tests/themes/production-runtime/package.json b/e2e-tests/themes/production-runtime/package.json index e8e36c3c82d46..885f266ce032d 100644 --- a/e2e-tests/themes/production-runtime/package.json +++ b/e2e-tests/themes/production-runtime/package.json @@ -13,6 +13,7 @@ "scripts": { "build": "gatsby build", "develop": "gatsby develop", + "clean": "gatsby clean", "format": "prettier --write \"src/**/*.js\"", "serve": "gatsby serve", "start": "npm run develop", diff --git a/e2e-tests/themes/production-runtime/src/gatsby-theme-about/templates/post.jsx b/e2e-tests/themes/production-runtime/src/gatsby-theme-about/templates/post.jsx new file mode 100644 index 0000000000000..7033efdb803ef --- /dev/null +++ b/e2e-tests/themes/production-runtime/src/gatsby-theme-about/templates/post.jsx @@ -0,0 +1,21 @@ +import React from "react" +import { graphql } from "gatsby" + +export default function Post({ data, children }) { + return ( +
+

{`${data.post.frontmatter.titleAlias} - Shadowed`}

+ {children} +
+ ) +} + +export const query = graphql` + query($id: String!) { + post: mdx(id: { eq: $id }) { + frontmatter { + titleAlias: title + } + } + } +` diff --git a/packages/gatsby/src/internal-plugins/webpack-theme-component-shadowing/index.js b/packages/gatsby/src/internal-plugins/webpack-theme-component-shadowing/index.js index f34f472740cd1..dfd8ca9b66beb 100644 --- a/packages/gatsby/src/internal-plugins/webpack-theme-component-shadowing/index.js +++ b/packages/gatsby/src/internal-plugins/webpack-theme-component-shadowing/index.js @@ -2,7 +2,7 @@ const path = require(`path`) const debug = require(`debug`)(`gatsby:component-shadowing`) const fs = require(`fs`) const _ = require(`lodash`) -const { getPathToLayoutComponent } = require(`gatsby-core-utils`) +const { splitComponentPath } = require(`gatsby-core-utils`) // A file can be shadowed by a file of the same extension, or a file of a // "compatible" file extension; two files extensions are compatible if they both @@ -22,6 +22,7 @@ const DEFAULT_FILE_EXTENSIONS_CATEGORIES = { tsx: `code`, cjs: `code`, mjs: `code`, + mts: `code`, coffee: `code`, // JSON-like data formats @@ -176,7 +177,13 @@ module.exports = class GatsbyThemeComponentShadowingResolverPlugin { } // check the user's project and the theme files - resolveComponentPath({ theme, component, originalRequestComponent }) { + resolveComponentPath({ + theme, + component: originalComponent, + originalRequestComponent, + }) { + const [component, content] = splitComponentPath(originalComponent) + // don't include matching theme in possible shadowing paths const themes = this.themes.filter( ({ themeName }) => themeName !== theme.themeName @@ -196,10 +203,7 @@ module.exports = class GatsbyThemeComponentShadowingResolverPlugin { ) for (const theme of themesArray) { - const possibleComponentPath = path.join( - theme, - getPathToLayoutComponent(component) - ) + const possibleComponentPath = path.join(theme, component) debug(`possibleComponentPath`, possibleComponentPath) let dir @@ -217,10 +221,16 @@ module.exports = class GatsbyThemeComponentShadowingResolverPlugin { existsDir.includes(shadowFile) ) if (matchingShadowFile) { - return path.join( + const shadowPath = path.join( path.dirname(possibleComponentPath), matchingShadowFile ) + + if (content) { + return `${shadowPath}?__contentFilePath=${content}` + } + + return shadowPath } } return null