diff --git a/e2e-tests/mdx-less-babel/cypress/integration/frontmatter.js b/e2e-tests/mdx-less-babel/cypress/integration/frontmatter.js
new file mode 100644
index 0000000000000..95804c9b7e9a5
--- /dev/null
+++ b/e2e-tests/mdx-less-babel/cypress/integration/frontmatter.js
@@ -0,0 +1,91 @@
+const page = {
+ js: `/frontmatter-js`,
+ javascript: `/frontmatter-javascript`,
+ yaml: `/frontmatter-yaml`,
+ json: `/frontmatter-json`,
+ graphqlQuery: `/frontmatter-graphql-query`,
+}
+
+// Attribute selector for element we assert against in pages
+const selector = `[data-cy="frontmatter"]`
+
+// Strings used for frontmatter titles
+const titles = {
+ notParsed: `I should not be parsed`,
+ parsed: `I am parsed`,
+}
+
+// Frontmatter that should not be rendered
+const otherKey = `Some other key`
+
+describe(`webpack loader`, () => {
+ describe(`---yaml frontmatter`, () => {
+ beforeEach(() => {
+ cy.visit(page.yaml).waitForRouteChange()
+ })
+
+ it(`should parse`, () => {
+ cy.get(selector).invoke(`text`).should(`eq`, titles.parsed)
+ })
+
+ it(`should not leak into the page`, () => {
+ cy.contains(otherKey).should(`not.exist`)
+ })
+ })
+
+ describe(`---json frontmatter`, () => {
+ beforeEach(() => {
+ cy.visit(page.json).waitForRouteChange()
+ })
+
+ it(`should parse`, () => {
+ cy.get(selector).invoke(`text`).should(`eq`, titles.parsed)
+ })
+
+ it(`should not leak into the page`, () => {
+ cy.contains(otherKey).should(`not.exist`)
+ })
+ })
+
+ describe(`---js frontmatter`, () => {
+ beforeEach(() => {
+ cy.visit(page.js).waitForRouteChange()
+ })
+
+ it(`should parse`, () => {
+ cy.get(selector).invoke(`text`).should(`eq`, `disabled`)
+ })
+
+ it(`should not leak into the page`, () => {
+ cy.contains(otherKey).should(`not.exist`)
+ })
+ })
+
+ describe(`---javascript frontmatter`, () => {
+ beforeEach(() => {
+ cy.visit(page.javascript).waitForRouteChange()
+ })
+
+ it(`should parse`, () => {
+ cy.get(selector).invoke(`text`).should(`eq`, `disabled`)
+ })
+
+ it(`should not leak into the page`, () => {
+ cy.contains(otherKey).should(`not.exist`)
+ })
+ })
+})
+
+describe(`data layer`, () => {
+ it(`---js or ---javascript frontmatter should not parse by default`, () => {
+ cy.visit(page.graphqlQuery).waitForRouteChange()
+ cy.contains(titles.notParsed).should(`not.exist`)
+ })
+})
+
+it(`---js and ---javascript frontmatter should not allow remote code execution`, () => {
+ cy.readFile(`cypress/fixtures/file-to-attempt-rce-on.txt`).should(
+ `eq`,
+ `Nothing here, do not remove`
+ )
+})
diff --git a/e2e-tests/mdx-less-babel/cypress/integration/js-frontmatter.js b/e2e-tests/mdx-less-babel/cypress/integration/js-frontmatter.js
deleted file mode 100644
index ac26fcb0aba45..0000000000000
--- a/e2e-tests/mdx-less-babel/cypress/integration/js-frontmatter.js
+++ /dev/null
@@ -1,29 +0,0 @@
-describe(`webpack loader`, () => {
- it(`---js frontmatter should not parse by default`, () => {
- cy.visit(`/js-frontmatter`).waitForRouteChange()
-
- // Check frontmatter not parsed in page context
- cy.get(`[data-cy="js-frontmatter"]`).invoke(`text`).should(`eq`, `disabled`)
- })
-
- it(`---javascript frontmatter should not parse by default`, () => {
- cy.visit(`/javascript-frontmatter`).waitForRouteChange()
-
- // Check frontmatter not parsed in page context
- cy.get(`[data-cy="js-frontmatter"]`).invoke(`text`).should(`eq`, `disabled`)
- })
-})
-
-describe(`data layer`, () => {
- it(`---js or ---javascript frontmatter should not parse by default`, () => {
- cy.visit(`/mdx-query-js-frontmatter/`).waitForRouteChange()
- cy.contains(`I should not be parsed`).should("not.exist")
- })
-})
-
-it(`---js and ---javascript frontmatter should not allow remote code execution`, () => {
- cy.readFile(`cypress/fixtures/file-to-attempt-rce-on.txt`).should(
- `eq`,
- `Nothing here, do not remove`
- )
-})
diff --git a/e2e-tests/mdx/src/pages/mdx-query-js-frontmatter.js b/e2e-tests/mdx-less-babel/src/pages/frontmatter-graphql-query.js
similarity index 100%
rename from e2e-tests/mdx/src/pages/mdx-query-js-frontmatter.js
rename to e2e-tests/mdx-less-babel/src/pages/frontmatter-graphql-query.js
diff --git a/e2e-tests/mdx/src/pages/javascript-frontmatter.mdx b/e2e-tests/mdx-less-babel/src/pages/frontmatter-javascript.mdx
similarity index 80%
rename from e2e-tests/mdx/src/pages/javascript-frontmatter.mdx
rename to e2e-tests/mdx-less-babel/src/pages/frontmatter-javascript.mdx
index 5210c21d086d4..9b4cfa869eaee 100644
--- a/e2e-tests/mdx/src/pages/javascript-frontmatter.mdx
+++ b/e2e-tests/mdx-less-babel/src/pages/frontmatter-javascript.mdx
@@ -3,7 +3,8 @@
require(`fs`).writeFileSync(`${process.cwd()}/cypress/fixtures/file-to-attempt-rce-on.txt`, (new Error('Helpful stack trace if this does execute. It should not execute.')).stack)
console.trace()
return {
-title: `I should not be parsed`
+title: `I should not be parsed`,
+otherKey: `Some other key`
}
})()
@@ -11,6 +12,6 @@ title: `I should not be parsed`
JS frontmatter engine is disabled by default
-
+
{props.pageContext.frontmatter?.title || `disabled`}
diff --git a/e2e-tests/mdx-less-babel/src/pages/js-frontmatter.mdx b/e2e-tests/mdx-less-babel/src/pages/frontmatter-js.mdx
similarity index 79%
rename from e2e-tests/mdx-less-babel/src/pages/js-frontmatter.mdx
rename to e2e-tests/mdx-less-babel/src/pages/frontmatter-js.mdx
index fcb411cdccfda..0496fe83ca8eb 100644
--- a/e2e-tests/mdx-less-babel/src/pages/js-frontmatter.mdx
+++ b/e2e-tests/mdx-less-babel/src/pages/frontmatter-js.mdx
@@ -3,7 +3,8 @@
require(`fs`).writeFileSync(`${process.cwd()}/cypress/fixtures/file-to-attempt-rce-on.txt`, (new Error('Helpful stack trace if this does execute. It should not execute.')).stack)
console.trace()
return {
-title: `I should not be parsed`
+title: `I should not be parsed`,
+otherKey: `Some other key`
}
})()
@@ -11,6 +12,6 @@ title: `I should not be parsed`
JS frontmatter engine is disabled by default
-
+
{props.pageContext.frontmatter?.title || `disabled`}
diff --git a/e2e-tests/mdx-less-babel/src/pages/frontmatter-json.mdx b/e2e-tests/mdx-less-babel/src/pages/frontmatter-json.mdx
new file mode 100644
index 0000000000000..e64f1e0fec826
--- /dev/null
+++ b/e2e-tests/mdx-less-babel/src/pages/frontmatter-json.mdx
@@ -0,0 +1,8 @@
+---json
+{ "title": "I am parsed", "otherKey": "Some other key" }
+
+---
+
+A page with JSON frontmatter
+
+{props.pageContext.frontmatter?.title}
diff --git a/e2e-tests/mdx-less-babel/src/pages/frontmatter-yaml.mdx b/e2e-tests/mdx-less-babel/src/pages/frontmatter-yaml.mdx
new file mode 100644
index 0000000000000..baa4ab4363889
--- /dev/null
+++ b/e2e-tests/mdx-less-babel/src/pages/frontmatter-yaml.mdx
@@ -0,0 +1,9 @@
+---yaml
+title: I am parsed
+otherKey: Some other key
+
+---
+
+A page with YAML frontmatter
+
+{props.pageContext.frontmatter?.title}
diff --git a/e2e-tests/mdx/cypress/integration/frontmatter.js b/e2e-tests/mdx/cypress/integration/frontmatter.js
new file mode 100644
index 0000000000000..95804c9b7e9a5
--- /dev/null
+++ b/e2e-tests/mdx/cypress/integration/frontmatter.js
@@ -0,0 +1,91 @@
+const page = {
+ js: `/frontmatter-js`,
+ javascript: `/frontmatter-javascript`,
+ yaml: `/frontmatter-yaml`,
+ json: `/frontmatter-json`,
+ graphqlQuery: `/frontmatter-graphql-query`,
+}
+
+// Attribute selector for element we assert against in pages
+const selector = `[data-cy="frontmatter"]`
+
+// Strings used for frontmatter titles
+const titles = {
+ notParsed: `I should not be parsed`,
+ parsed: `I am parsed`,
+}
+
+// Frontmatter that should not be rendered
+const otherKey = `Some other key`
+
+describe(`webpack loader`, () => {
+ describe(`---yaml frontmatter`, () => {
+ beforeEach(() => {
+ cy.visit(page.yaml).waitForRouteChange()
+ })
+
+ it(`should parse`, () => {
+ cy.get(selector).invoke(`text`).should(`eq`, titles.parsed)
+ })
+
+ it(`should not leak into the page`, () => {
+ cy.contains(otherKey).should(`not.exist`)
+ })
+ })
+
+ describe(`---json frontmatter`, () => {
+ beforeEach(() => {
+ cy.visit(page.json).waitForRouteChange()
+ })
+
+ it(`should parse`, () => {
+ cy.get(selector).invoke(`text`).should(`eq`, titles.parsed)
+ })
+
+ it(`should not leak into the page`, () => {
+ cy.contains(otherKey).should(`not.exist`)
+ })
+ })
+
+ describe(`---js frontmatter`, () => {
+ beforeEach(() => {
+ cy.visit(page.js).waitForRouteChange()
+ })
+
+ it(`should parse`, () => {
+ cy.get(selector).invoke(`text`).should(`eq`, `disabled`)
+ })
+
+ it(`should not leak into the page`, () => {
+ cy.contains(otherKey).should(`not.exist`)
+ })
+ })
+
+ describe(`---javascript frontmatter`, () => {
+ beforeEach(() => {
+ cy.visit(page.javascript).waitForRouteChange()
+ })
+
+ it(`should parse`, () => {
+ cy.get(selector).invoke(`text`).should(`eq`, `disabled`)
+ })
+
+ it(`should not leak into the page`, () => {
+ cy.contains(otherKey).should(`not.exist`)
+ })
+ })
+})
+
+describe(`data layer`, () => {
+ it(`---js or ---javascript frontmatter should not parse by default`, () => {
+ cy.visit(page.graphqlQuery).waitForRouteChange()
+ cy.contains(titles.notParsed).should(`not.exist`)
+ })
+})
+
+it(`---js and ---javascript frontmatter should not allow remote code execution`, () => {
+ cy.readFile(`cypress/fixtures/file-to-attempt-rce-on.txt`).should(
+ `eq`,
+ `Nothing here, do not remove`
+ )
+})
diff --git a/e2e-tests/mdx/cypress/integration/js-frontmatter.js b/e2e-tests/mdx/cypress/integration/js-frontmatter.js
deleted file mode 100644
index ac26fcb0aba45..0000000000000
--- a/e2e-tests/mdx/cypress/integration/js-frontmatter.js
+++ /dev/null
@@ -1,29 +0,0 @@
-describe(`webpack loader`, () => {
- it(`---js frontmatter should not parse by default`, () => {
- cy.visit(`/js-frontmatter`).waitForRouteChange()
-
- // Check frontmatter not parsed in page context
- cy.get(`[data-cy="js-frontmatter"]`).invoke(`text`).should(`eq`, `disabled`)
- })
-
- it(`---javascript frontmatter should not parse by default`, () => {
- cy.visit(`/javascript-frontmatter`).waitForRouteChange()
-
- // Check frontmatter not parsed in page context
- cy.get(`[data-cy="js-frontmatter"]`).invoke(`text`).should(`eq`, `disabled`)
- })
-})
-
-describe(`data layer`, () => {
- it(`---js or ---javascript frontmatter should not parse by default`, () => {
- cy.visit(`/mdx-query-js-frontmatter/`).waitForRouteChange()
- cy.contains(`I should not be parsed`).should("not.exist")
- })
-})
-
-it(`---js and ---javascript frontmatter should not allow remote code execution`, () => {
- cy.readFile(`cypress/fixtures/file-to-attempt-rce-on.txt`).should(
- `eq`,
- `Nothing here, do not remove`
- )
-})
diff --git a/e2e-tests/mdx/src/pages/frontmatter-graphql-query.js b/e2e-tests/mdx/src/pages/frontmatter-graphql-query.js
new file mode 100644
index 0000000000000..c94d169a7699e
--- /dev/null
+++ b/e2e-tests/mdx/src/pages/frontmatter-graphql-query.js
@@ -0,0 +1,30 @@
+import React from "react"
+import { graphql } from "gatsby"
+
+export default function PageRunningGraphqlResolversOnJSFrontmatterTestInputs({
+ data,
+}) {
+ return {JSON.stringify(data.allMdx.nodes, null, 2)}
+}
+
+export const query = graphql`
+ {
+ allMdx(filter: { slug: { glob: "frontmatter-engine/*" } }) {
+ nodes {
+ frontmatter {
+ title
+ }
+ body
+ excerpt
+ tableOfContents
+ timeToRead
+ wordCount {
+ paragraphs
+ sentences
+ words
+ }
+ mdxAST
+ }
+ }
+ }
+`
diff --git a/e2e-tests/mdx-less-babel/src/pages/javascript-frontmatter.mdx b/e2e-tests/mdx/src/pages/frontmatter-javascript.mdx
similarity index 80%
rename from e2e-tests/mdx-less-babel/src/pages/javascript-frontmatter.mdx
rename to e2e-tests/mdx/src/pages/frontmatter-javascript.mdx
index 5210c21d086d4..9b4cfa869eaee 100644
--- a/e2e-tests/mdx-less-babel/src/pages/javascript-frontmatter.mdx
+++ b/e2e-tests/mdx/src/pages/frontmatter-javascript.mdx
@@ -3,7 +3,8 @@
require(`fs`).writeFileSync(`${process.cwd()}/cypress/fixtures/file-to-attempt-rce-on.txt`, (new Error('Helpful stack trace if this does execute. It should not execute.')).stack)
console.trace()
return {
-title: `I should not be parsed`
+title: `I should not be parsed`,
+otherKey: `Some other key`
}
})()
@@ -11,6 +12,6 @@ title: `I should not be parsed`
JS frontmatter engine is disabled by default
-
+
{props.pageContext.frontmatter?.title || `disabled`}
diff --git a/e2e-tests/mdx/src/pages/js-frontmatter.mdx b/e2e-tests/mdx/src/pages/frontmatter-js.mdx
similarity index 79%
rename from e2e-tests/mdx/src/pages/js-frontmatter.mdx
rename to e2e-tests/mdx/src/pages/frontmatter-js.mdx
index fcb411cdccfda..0496fe83ca8eb 100644
--- a/e2e-tests/mdx/src/pages/js-frontmatter.mdx
+++ b/e2e-tests/mdx/src/pages/frontmatter-js.mdx
@@ -3,7 +3,8 @@
require(`fs`).writeFileSync(`${process.cwd()}/cypress/fixtures/file-to-attempt-rce-on.txt`, (new Error('Helpful stack trace if this does execute. It should not execute.')).stack)
console.trace()
return {
-title: `I should not be parsed`
+title: `I should not be parsed`,
+otherKey: `Some other key`
}
})()
@@ -11,6 +12,6 @@ title: `I should not be parsed`
JS frontmatter engine is disabled by default
-
+
{props.pageContext.frontmatter?.title || `disabled`}
diff --git a/e2e-tests/mdx/src/pages/frontmatter-json.mdx b/e2e-tests/mdx/src/pages/frontmatter-json.mdx
new file mode 100644
index 0000000000000..e64f1e0fec826
--- /dev/null
+++ b/e2e-tests/mdx/src/pages/frontmatter-json.mdx
@@ -0,0 +1,8 @@
+---json
+{ "title": "I am parsed", "otherKey": "Some other key" }
+
+---
+
+A page with JSON frontmatter
+
+{props.pageContext.frontmatter?.title}
diff --git a/e2e-tests/mdx/src/pages/frontmatter-yaml.mdx b/e2e-tests/mdx/src/pages/frontmatter-yaml.mdx
new file mode 100644
index 0000000000000..baa4ab4363889
--- /dev/null
+++ b/e2e-tests/mdx/src/pages/frontmatter-yaml.mdx
@@ -0,0 +1,9 @@
+---yaml
+title: I am parsed
+otherKey: Some other key
+
+---
+
+A page with YAML frontmatter
+
+{props.pageContext.frontmatter?.title}
diff --git a/packages/gatsby-plugin-mdx/loaders/mdx-loader.js b/packages/gatsby-plugin-mdx/loaders/mdx-loader.js
index 5309e93009f65..af3c6a30603cb 100644
--- a/packages/gatsby-plugin-mdx/loaders/mdx-loader.js
+++ b/packages/gatsby-plugin-mdx/loaders/mdx-loader.js
@@ -182,12 +182,9 @@ export const _frontmatter = ${JSON.stringify(data)};`
// check needs to happen first.
if (!hasDefaultExport(content, options) && !!defaultLayout) {
debug(`inserting default layout`, defaultLayout)
- const { content: contentWithoutFrontmatter, matter } = grayMatter(
- content,
- options
- )
+ const { content: contentWithoutFrontmatter } = grayMatter(content, options)
- code = `${matter ? matter : ``}
+ code = `
import DefaultLayout from "${slash(defaultLayout)}"