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 854b5e225b7e8..18ce416a9290c 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 @@ -212,6 +212,20 @@ Object { } `; +exports[`Excerpt is generated correctly from schema given MARKDOWN without excerpt separator, falls back to pruneLength 1`] = ` +Object { + "excerpt": "Where oh where **is** my little pony? Lorem… +", +} +`; + +exports[`Excerpt is generated correctly from schema given MARKDOWN, pruning is done not counting markdown characters 1`] = ` +Object { + "excerpt": "Where oh where **is**… +", +} +`; + exports[`Excerpt is generated correctly from schema given PLAIN correctly uses excerpt separator 1`] = ` Object { "excerpt": "Where oh where is my little pony?", diff --git a/packages/gatsby-transformer-remark/src/__tests__/extend-node.js b/packages/gatsby-transformer-remark/src/__tests__/extend-node.js index 2c54465a9a443..e424354383d51 100644 --- a/packages/gatsby-transformer-remark/src/__tests__/extend-node.js +++ b/packages/gatsby-transformer-remark/src/__tests__/extend-node.js @@ -290,6 +290,40 @@ In quis lectus sed eros efficitur luctus. Morbi tempor, nisl eget feugiat tincid { pluginOptions: { excerpt_separator: `` } } ) + const contentWithoutSeparator = `--- +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 MARKDOWN without excerpt separator, falls back to pruneLength`, + contentWithoutSeparator, + `excerpt(pruneLength: 40, format: MARKDOWN)`, + node => { + expect(node).toMatchSnapshot() + expect(node.excerpt.length).toBe(45) + expect(node.excerpt).toBe( + `Where oh where **is** my little pony? Lorem…\n` + ) + }, + { pluginOptions: { excerpt_separator: `` } } + ) + + bootstrapTest( + `given MARKDOWN, pruning is done not counting markdown characters`, + contentWithoutSeparator, + `excerpt(pruneLength: 19, format: MARKDOWN)`, + node => { + expect(node).toMatchSnapshot() + // we want the pruning to preserve markdown chars and not count them in the length + expect(node.excerpt.length).toBe(23) + expect(node.excerpt).toBe(`Where oh where **is**…\n`) + } + ) 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 56dcbc2ea77eb..8adf3a50e4377 100644 --- a/packages/gatsby-transformer-remark/src/extend-node-type.js +++ b/packages/gatsby-transformer-remark/src/extend-node-type.js @@ -347,10 +347,10 @@ module.exports = ( } async function getExcerptAst( + fullAST, markdownNode, { pruneLength, truncate, excerptSeparator } ) { - const fullAST = await getHTMLAst(markdownNode) if (excerptSeparator && markdownNode.excerpt !== ``) { return cloneTreeUntil( fullAST, @@ -375,12 +375,13 @@ module.exports = ( } const lastTextNode = findLastTextNode(excerptAST) - const amountToPruneLastNode = - pruneLength - (unprunedExcerpt.length - lastTextNode.value.length) + const amountToPruneBy = unprunedExcerpt.length - pruneLength + const desiredLengthOfLastNode = + lastTextNode.value.length - amountToPruneBy if (!truncate) { lastTextNode.value = prune( lastTextNode.value, - amountToPruneLastNode, + desiredLengthOfLastNode, `…` ) } else { @@ -398,7 +399,8 @@ module.exports = ( truncate, excerptSeparator ) { - const excerptAST = await getExcerptAst(markdownNode, { + const fullAST = await getHTMLAst(markdownNode) + const excerptAST = await getExcerptAst(fullAST, markdownNode, { pruneLength, truncate, excerptSeparator, @@ -415,18 +417,20 @@ module.exports = ( truncate, excerptSeparator ) { - if (excerptSeparator) { + // if excerptSeparator in options and excerptSeparator in content then we will get an excerpt from grayMatter that we can use + if (excerptSeparator && markdownNode.excerpt !== ``) { return markdownNode.excerpt } - // TODO truncate respecting markdown AST - const excerptText = markdownNode.rawMarkdownBody - if (!truncate) { - return prune(excerptText, pruneLength, `…`) - } - return _.truncate(excerptText, { - length: pruneLength, - omission: `…`, + const ast = await getMarkdownAST(markdownNode) + const excerptAST = await getExcerptAst(ast, markdownNode, { + pruneLength, + truncate, + excerptSeparator, }) + var excerptMarkdown = unified() + .use(stringify) + .stringify(excerptAST) + return excerptMarkdown } async function getExcerptPlain( @@ -552,14 +556,18 @@ module.exports = ( }, }, resolve(markdownNode, { pruneLength, truncate }) { - return getExcerptAst(markdownNode, { - pruneLength, - truncate, - excerptSeparator: pluginOptions.excerpt_separator, - }).then(ast => { - const strippedAst = stripPosition(_.clone(ast), true) - return hastReparseRaw(strippedAst) - }) + return getHTMLAst(markdownNode) + .then(fullAST => + getExcerptAst(fullAST, markdownNode, { + pruneLength, + truncate, + excerptSeparator: pluginOptions.excerpt_separator, + }) + ) + .then(ast => { + const strippedAst = stripPosition(_.clone(ast), true) + return hastReparseRaw(strippedAst) + }) }, }, headings: {