diff --git a/packages/cli/src/plugins/resource/plugin-standard-html.js b/packages/cli/src/plugins/resource/plugin-standard-html.js index f492c0faf..3e090a91a 100644 --- a/packages/cli/src/plugins/resource/plugin-standard-html.js +++ b/packages/cli/src/plugins/resource/plugin-standard-html.js @@ -159,13 +159,28 @@ class StandardHtmlResource extends ResourceInterface { }); } + // https://github.com/ProjectEvergreen/greenwood/issues/1375 + async shouldIntercept(url) { + const { pathname } = url; + const matchingRoute = this.compilation.graph.find((node) => node.route === pathname) || {}; + + return matchingRoute?.pageHref?.endsWith(this.extensions[1]) && this.compilation.config.prerender && process.env.__GWD_COMMAND__ === 'build'; // eslint-disable-line no-underscore-dangle + } + + async intercept(url, request, response) { + const body = await response.text(); + + return new Response(body.replace(/</g, 'greenwood-custom-left-bracket')); + } + async shouldOptimize(url, response) { return response.headers.get('Content-Type')?.indexOf(this.contentType) >= 0; } async optimize(url, response) { - const { optimization, basePath } = this.compilation.config; + const { optimization, basePath, prerender } = this.compilation.config; const { pathname } = url; + const matchingRoute = this.compilation.graph.find((node) => node.route === pathname) || {}; const pageResources = this.compilation.graph.find(page => page.route === pathname).resources; let body = await response.text(); @@ -245,6 +260,10 @@ class StandardHtmlResource extends ResourceInterface { } } + if (matchingRoute?.pageHref?.endsWith(this.extensions[1]) && prerender) { + body = body.replace(/greenwood-custom-left-bracket/g, '<'); + } + return new Response(body); } } diff --git a/packages/cli/test/cases/build.config.prerender-markdown/build.config.prerender-markdown.spec.js b/packages/cli/test/cases/build.config.prerender-markdown/build.config.prerender-markdown.spec.js new file mode 100644 index 000000000..08171dcd5 --- /dev/null +++ b/packages/cli/test/cases/build.config.prerender-markdown/build.config.prerender-markdown.spec.js @@ -0,0 +1,73 @@ +/* + * Use Case + * Run Greenwood with custom markdown content and prerendering enabled with WCC. + * + * User Result + * Should generate a bare bones Greenwood build and in particular make sure HTML entities are preserved. + * + * User Command + * greenwood build + * + * User Config + * { + * prerender: true + * } + * + * User Workspace + * src/ + * components/ + * ctc-block.js + * pages/ + * index.md + */ +import fs from 'fs/promises'; +import path from 'path'; +import chai from 'chai'; +import { runSmokeTest } from '../../../../../test/smoke-test.js'; +import { getOutputTeardownFiles } from '../../../../../test/utils.js'; +import { Runner } from 'gallinago'; +import { fileURLToPath, URL } from 'url'; + +const expect = chai.expect; + +// https://github.com/ProjectEvergreen/greenwood/issues/1375 +describe('Build Greenwood With: ', function() { + const LABEL = 'Markdown with prerendering and HTML entities'; + const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js'); + const outputPath = fileURLToPath(new URL('.', import.meta.url)); + let runner; + + before(function() { + this.context = { + publicDir: path.join(outputPath, 'public') + }; + runner = new Runner(); + }); + + describe(LABEL, function() { + before(function() { + runner.setup(outputPath); + runner.runCommand(cliPath, 'build'); + }); + + runSmokeTest(['public', 'index'], LABEL); + + describe('Markdown Rendering', function() { + let html; + + before(async function() { + html = await fs.readFile(path.resolve(this.context.publicDir, 'index.html'), 'utf-8'); + }); + + it('should correctly render out code fences with HTML entities preserved', function() { + expect(html).to.contain('<x-card>'); + }); + }); + + }); + + after(function() { + runner.teardown(getOutputTeardownFiles(outputPath)); + }); + +}); \ No newline at end of file diff --git a/packages/cli/test/cases/build.config.prerender-markdown/greenwood.config.js b/packages/cli/test/cases/build.config.prerender-markdown/greenwood.config.js new file mode 100644 index 000000000..8dc4be464 --- /dev/null +++ b/packages/cli/test/cases/build.config.prerender-markdown/greenwood.config.js @@ -0,0 +1,3 @@ +export default { + prerender: true +}; \ No newline at end of file diff --git a/packages/cli/test/cases/build.config.prerender-markdown/src/components/x-ctc.js b/packages/cli/test/cases/build.config.prerender-markdown/src/components/x-ctc.js new file mode 100644 index 000000000..b86b693ed --- /dev/null +++ b/packages/cli/test/cases/build.config.prerender-markdown/src/components/x-ctc.js @@ -0,0 +1,5 @@ +export default class CopyToClipboardBlock extends HTMLElement { + +} + +customElements.define('x-ctc', CopyToClipboardBlock); \ No newline at end of file diff --git a/packages/cli/test/cases/build.config.prerender-markdown/src/pages/index.md b/packages/cli/test/cases/build.config.prerender-markdown/src/pages/index.md new file mode 100644 index 000000000..3eef5117f --- /dev/null +++ b/packages/cli/test/cases/build.config.prerender-markdown/src/pages/index.md @@ -0,0 +1,35 @@ +--- +imports: + - /components/x-ctc.js +--- + +## Server Rendering + +You will need to use version <= 20.6.0. + + + + ```js + import "../components/card/card.js"; // + + export default class UsersPage extends HTMLElement { + async connectedCallback() { + const users = await fetch("https://www.example.com/api/users").then((resp) => resp.json()); + const html = users + .map((user) => { + const { name, imageUrl } = user; + return ` + +

${name}

+ ${name} +
+ `; + }) + .join(""); + + this.innerHTML = html; + } + } + ``` + +
\ No newline at end of file diff --git a/packages/cli/test/cases/build.default.markdown/build.default.markdown.spec.js b/packages/cli/test/cases/build.default.markdown/build.default.markdown.spec.js index 5b774e0bd..b43258fd3 100644 --- a/packages/cli/test/cases/build.default.markdown/build.default.markdown.spec.js +++ b/packages/cli/test/cases/build.default.markdown/build.default.markdown.spec.js @@ -1,9 +1,9 @@ /* * Use Case - * Run Greenwood with custom markdown preset in greenwood config. + * Run Greenwood with markdown content. * * User Result - * Should generate a bare bones Greenwood build. (same as build.default.spec.js) with custom markdown and rehype links + * Should generate a bare bones Greenwood build with markdown correctly transformed. * * User Command * greenwood build @@ -12,7 +12,9 @@ * None * * User Workspace - * Greenwood default + * src/ + * pages/ + * index.md */ import { JSDOM } from 'jsdom'; import path from 'path';