From 4f72687ce9b2c9edcf1358c9ece3a5aad3d003f3 Mon Sep 17 00:00:00 2001 From: Ryosuke IWANAGA Date: Fri, 14 Jun 2019 02:07:51 -0700 Subject: [PATCH] feat(gatsby-transformer-remark): change excerpt behavior (#14723) Change gatsby-transformer-remark excerpt behavior - Plain text even with separator - New format for MARKDOWN --- packages/gatsby-transformer-remark/README.md | 14 +++ .../__snapshots__/extend-node.js.snap | 23 +++- .../src/__tests__/extend-node.js | 46 +++++++ .../src/extend-node-type.js | 112 ++++++++++++++---- 4 files changed, 169 insertions(+), 26 deletions(-) diff --git a/packages/gatsby-transformer-remark/README.md b/packages/gatsby-transformer-remark/README.md index ffea63c965858..22d813e6f0de9 100644 --- a/packages/gatsby-transformer-remark/README.md +++ b/packages/gatsby-transformer-remark/README.md @@ -191,6 +191,20 @@ It's also possible to ask Gatsby to return excerpts formatted as HTML. You might } ``` +You can also get excerpts in Markdown format. + +```graphql +{ + allMarkdownRemark { + edges { + node { + excerpt(format: MARKDOWN) + } + } + } +} +``` + ## gray-matter options `gatsby-transformer-remark` uses [gray-matter](https://github.com/jonschlinkert/gray-matter) to parse markdown frontmatter, so you can specify any of the options mentioned [here](https://github.com/jonschlinkert/gray-matter#options) in the `gatsby-config.js` file. diff --git a/packages/gatsby-transformer-remark/src/__tests__/__snapshots__/extend-node.js.snap b/packages/gatsby-transformer-remark/src/__tests__/__snapshots__/extend-node.js.snap index c981b915e38e1..849360d229d6b 100644 --- a/packages/gatsby-transformer-remark/src/__tests__/__snapshots__/extend-node.js.snap +++ b/packages/gatsby-transformer-remark/src/__tests__/__snapshots__/extend-node.js.snap @@ -130,8 +130,7 @@ Object { exports[`Excerpt is generated correctly from schema correctly uses excerpt separator 1`] = ` Object { - "excerpt": "Where oh where is my little pony? -", + "excerpt": "Where oh where is my little pony?", "excerptAst": Object { "children": Array [ Object { @@ -162,6 +161,26 @@ Object { } `; +exports[`Excerpt is generated correctly from schema given HTML correctly uses excerpt separator 1`] = ` +Object { + "excerpt": "

Where oh where is my little pony?

+", +} +`; + +exports[`Excerpt is generated correctly from schema given MARKDOWN correctly uses excerpt separator 1`] = ` +Object { + "excerpt": "Where oh where **is** my little pony? +", +} +`; + +exports[`Excerpt is generated correctly from schema given PLAIN correctly uses excerpt separator 1`] = ` +Object { + "excerpt": "Where oh where is my little pony?", +} +`; + exports[`Excerpt is generated correctly from schema given an html format, it correctly maps nested markdown to html 1`] = ` Object { "excerpt": "

Where oh where is \\"that?

", diff --git a/packages/gatsby-transformer-remark/src/__tests__/extend-node.js b/packages/gatsby-transformer-remark/src/__tests__/extend-node.js index fab644ab84a21..da45a4a33bf14 100644 --- a/packages/gatsby-transformer-remark/src/__tests__/extend-node.js +++ b/packages/gatsby-transformer-remark/src/__tests__/extend-node.js @@ -222,6 +222,52 @@ In quis lectus sed eros efficitur luctus. Morbi tempor, nisl eget feugiat tincid { pluginOptions: { excerpt_separator: `` } } ) + const contentWithSeparator = `--- +title: "my little pony" +date: "2017-09-18T23:19:51.246Z" +--- +Where oh where **is** my little pony? + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi auctor sit amet velit id facilisis. Nulla viverra, eros at efficitur pulvinar, lectus orci accumsan nisi, eu blandit elit nulla nec lectus. Integer porttitor imperdiet sapien. Quisque in orci sed nisi consequat aliquam. Aenean id mollis nisi. Sed auctor odio id erat facilisis venenatis. Quisque posuere faucibus libero vel fringilla. + +In quis lectus sed eros efficitur luctus. Morbi tempor, nisl eget feugiat tincidunt, sem velit vulputate enim, nec interdum augue enim nec mauris. Nulla iaculis ante sed enim placerat pretium. Nulla metus odio, facilisis vestibulum lobortis vitae, bibendum at nunc. Donec sit amet efficitur metus, in bibendum nisi. Vivamus tempus vel turpis sit amet auctor. Maecenas luctus vestibulum velit, at sagittis leo volutpat quis. Praesent posuere nec augue eget sodales. Pellentesque vitae arcu ut est varius venenatis id maximus sem. Curabitur non consectetur turpis. +` + + bootstrapTest( + `given PLAIN correctly uses excerpt separator`, + contentWithSeparator, + `excerpt(format: PLAIN)`, + node => { + expect(node).toMatchSnapshot() + expect(node.excerpt).toMatch(`Where oh where is my little pony?`) + }, + { pluginOptions: { excerpt_separator: `` } } + ) + + bootstrapTest( + `given HTML correctly uses excerpt separator`, + contentWithSeparator, + `excerpt(format: HTML)`, + node => { + expect(node).toMatchSnapshot() + expect(node.excerpt).toMatch( + `

Where oh where is my little pony?

` + ) + }, + { pluginOptions: { excerpt_separator: `` } } + ) + + bootstrapTest( + `given MARKDOWN correctly uses excerpt separator`, + contentWithSeparator, + `excerpt(format: MARKDOWN)`, + node => { + expect(node).toMatchSnapshot() + expect(node.excerpt).toMatch(`Where oh where **is** my little pony?`) + }, + { pluginOptions: { excerpt_separator: `` } } + ) + const content = `--- title: "my little pony" date: "2017-09-18T23:19:51.246Z" diff --git a/packages/gatsby-transformer-remark/src/extend-node-type.js b/packages/gatsby-transformer-remark/src/extend-node-type.js index 33442a3a9eb37..45f53d62d46ba 100644 --- a/packages/gatsby-transformer-remark/src/extend-node-type.js +++ b/packages/gatsby-transformer-remark/src/extend-node-type.js @@ -409,42 +409,78 @@ module.exports = ( return excerptAST } - async function getExcerpt( + async function getExcerptHtml( markdownNode, - { format, pruneLength, truncate, excerptSeparator } + pruneLength, + truncate, + excerptSeparator ) { - if (format === `html`) { - const excerptAST = await getExcerptAst(markdownNode, { - pruneLength, - truncate, - excerptSeparator, - }) - const html = hastToHTML(excerptAST, { - allowDangerousHTML: true, - }) - return html - } + const excerptAST = await getExcerptAst(markdownNode, { + pruneLength, + truncate, + excerptSeparator, + }) + const html = hastToHTML(excerptAST, { + allowDangerousHTML: true, + }) + return html + } - if (markdownNode.excerpt) { + async function getExcerptMarkdown( + markdownNode, + pruneLength, + truncate, + excerptSeparator + ) { + if (excerptSeparator) { return markdownNode.excerpt } + // TODO truncate respecting markdown AST + const excerptText = markdownNode.rawMarkdownBody + if (!truncate) { + return prune(excerptText, pruneLength, `…`) + } + return _.truncate(excerptText, { + length: pruneLength, + omission: `…`, + }) + } + async function getExcerptPlain( + markdownNode, + pruneLength, + truncate, + excerptSeparator + ) { const text = await getAST(markdownNode).then(ast => { let excerptNodes = [] - visit(ast, node => { - if (node.type === `text` || node.type === `inlineCode`) { - excerptNodes.push(node.value) - } - if (node.type === `image`) { - excerptNodes.push(node.alt) + let isBeforeSeparator = true + visit( + ast, + node => isBeforeSeparator, + node => { + if (excerptSeparator && node.value === excerptSeparator) { + isBeforeSeparator = false + return + } + if (node.type === `text` || node.type === `inlineCode`) { + excerptNodes.push(node.value) + } + if (node.type === `image`) { + excerptNodes.push(node.alt) + } } - return - }) + ) + + const excerptText = excerptNodes.join(``) + if (excerptSeparator) { + return excerptText + } if (!truncate) { - return prune(excerptNodes.join(``), pruneLength, `…`) + return prune(excerptText, pruneLength, `…`) } - return _.truncate(excerptNodes.join(``), { + return _.truncate(excerptText, { length: pruneLength, omission: `…`, }) @@ -452,6 +488,33 @@ module.exports = ( return text } + async function getExcerpt( + markdownNode, + { format, pruneLength, truncate, excerptSeparator } + ) { + if (format === `html`) { + return getExcerptHtml( + markdownNode, + pruneLength, + truncate, + excerptSeparator + ) + } else if (format === `markdown`) { + return getExcerptMarkdown( + markdownNode, + pruneLength, + truncate, + excerptSeparator + ) + } + return getExcerptPlain( + markdownNode, + pruneLength, + truncate, + excerptSeparator + ) + } + const HeadingType = new GraphQLObjectType({ name: `MarkdownHeading`, fields: { @@ -487,6 +550,7 @@ module.exports = ( values: { PLAIN: { value: `plain` }, HTML: { value: `html` }, + MARKDOWN: { value: `markdown` }, }, })