Repository: ProjectEvergreen/greenwood (js)

Issue:
templates with (inline) template strings breaks bundling of SSR pages
## Summary
Noticed that when bundling an SSR page that itself happened to contain template literal strings, Rollup was breaking.

For example
```sh
src/
  pages/
    posts.js
  template/
    app.html
```

And then _app.html_ might look something like this
```html
<!DOCTYPE html>
<html lang="en" prefix="og:http://ogp.me/ns#">
  <head>
    <title>Some  Title</title>
    <script>
      const message = `The current time is ${new Date().getTime()}`;

      alert(message);
    </script>
  </head>
  <body>
    <page-outlet></page-outlet>
  </body>
</html>
```

Will result in a parse error from Rollup
```
SyntaxError: Unexpected token (28:17) in /Users/owenbuckley/Workspace/project-evergreen/greenwood/packages/cli/test/cases/serve.default.ssr/.greenwood/_artists.js
    at pp$4.raise (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:19420:13)
    at pp$9.unexpected (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:16714:8)
    at pp$9.semicolon (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:16691:66)
    at pp$8.parseVarStatement (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:17122:8)
    at pp$8.parseStatement (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:16869:17)
    at pp$8.parseBlock (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:17190:21)
    at pp$5.parseFunctionBody (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:19246:22)
    at pp$8.parseFunction (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:17312:8)
    at pp$8.parseFunctionStatement (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:17012:15)
    at pp$8.parseStatement (file:///Users/owenbuckley/Workspace/project-evergreen/greenwood/node_modules/rollup/dist/es/shared/rollup.js:16901:19) {
  pos: 10688,
  loc: {
    column: 17,
    file: '/Users/owenbuckley/Workspace/project-evergreen/greenwood/packages/cli/test/cases/serve.default.ssr/.greenwood/_artists.js',
    line: 28
  },
  raisedAt: 10691,
  frame: '26:           <style>*{color:blue}h1{width:50%;margin:0 auto;text-align:center;color:red;}</style>\n' +
    '27:           <script type="module" src="/header.4557af3c.js"></script>\n' +
    '28: <script>const e=`The current time is ${(new Date).getTime()}`;alert(e);\n' +
    '                     ^\n' +
    '29: //# sourceMappingURL=55016989.32ad046b.js.map\n' +
    '30: </script>',
  id: '/Users/owenbuckley/Workspace/project-evergreen/greenwood/packages/cli/test/cases/serve.default.ssr/.greenwood/_artists.js',
  hook: 'transform',
  code: 'PLUGIN_ERROR',
  plugin: 'commonjs',
  watchFiles: [
    '/Users/owenbuckley/Workspace/project-evergreen/greenwood/packages/cli/test/cases/serve.default.ssr/.greenwood/_artists.js',
    '/Users/owenbuckley/Workspace/project-evergreen/greenwood/packages/cli/test/cases/serve.default.ssr/.greenwood/_index.js',
    '/Users/owenbuckley/Workspace/project-evergreen/greenwood/packages/cli/test/cases/serve.default.ssr/.greenwood/_users.js',
    '/Users/owenbuckley/Workspace/project-evergreen/greenwood/packages/cli/test/cases/serve.default.ssr/src/pages/index.js',
    '/Users/owenbuckley/Workspace/project-evergreen/greenwood/packages/cli/test/cases/serve.default.ssr/src/pages/artists.js',
    '/Users/owenbuckley/Workspace/project-evergreen/greenwood/packages/cli/test/cases/serve.default.ssr/src/pages/users.js'
  ]
}
```

## Details
You'll notice that the parse error happens on a line where a the ` from _app.html_ starts.  This is likely an escaping issue with how we are ["packing" static templates into SSR pages at build time](https://github.com/ProjectEvergreen/greenwood/blob/v0.29.0-alpha.4/packages/cli/src/lifecycles/bundle.js#L215).

Pull request description:
Bug/issue 1154 inline template strings in SSR page templates break bundling
<!--
## Submitting a Pull Request
We love contributions and appreciate any help you can offer!
-->

## Related Issue
resolves #1154 

## Summary of Changes
1. Proper escaping for packing / bundling of template contents in SSR page bundles
1. Added / updates test cases

Patch:
diff --git a/packages/cli/src/lifecycles/bundle.js b/packages/cli/src/lifecycles/bundle.js
index a6fb8c97..e931847f 100644
--- a/packages/cli/src/lifecycles/bundle.js
+++ b/packages/cli/src/lifecycles/bundle.js
@@ -202,6 +202,7 @@ async function bundleSsrPages(compilation) {
         staticHtml = await getAppTemplate(staticHtml, compilation.context, imports, [], false, title);
         staticHtml = await getUserScripts(staticHtml, compilation.context);
         staticHtml = await (await htmlOptimizer.optimize(new URL(`http://localhost:8080${route}`), new Response(staticHtml))).text();
+        staticHtml = staticHtml.replace(/[`\\$]/g, '\\$&'); // https://stackoverflow.com/a/75688937/417806
 
         // better way to write out this inline code?
         await fs.writeFile(entryFileUrl, `


Test patch:
diff --git a/packages/cli/test/cases/serve.default.ssr/serve.default.ssr.spec.js b/packages/cli/test/cases/serve.default.ssr/serve.default.ssr.spec.js
index e323513a..6dde6c7f 100644
--- a/packages/cli/test/cases/serve.default.ssr/serve.default.ssr.spec.js
+++ b/packages/cli/test/cases/serve.default.ssr/serve.default.ssr.spec.js
@@ -180,7 +180,7 @@ describe('Serve Greenwood With: ', function() {
       it('should have the expected number of <script> tags in the <head>', function() {
         const scripts = artistsPageDom.window.document.querySelectorAll('head > script');
 
-        expect(scripts.length).to.equal(3);
+        expect(scripts.length).to.equal(4);
       });
 
       it('should have the expected <app-header> tag from the app template in the <head>', function() {
@@ -194,8 +194,8 @@ describe('Serve Greenwood With: ', function() {
         const scripts = Array.from(artistsPageDom.window.document.querySelectorAll('head > script'))
           .filter(tag => !tag.getAttribute('type'));
 
-        expect(scripts.length).to.equal(1);
-        expect(scripts[0].textContent).to.contain('console.log');
+        expect(scripts.length).to.equal(2);
+        expect(scripts[1].textContent).to.contain('console.log');
       });
 
       it('should have the expected number of table rows of content', function() {
@@ -251,7 +251,7 @@ describe('Serve Greenwood With: ', function() {
       it('should append the expected graph resource scripts for the page from a template', function() {
         const { resources } = artistsPageGraphData;
 
-        expect(resources.length).to.equal(4);
+        expect(resources.length).to.equal(5);
         expect(resources.find(resource => resource.endsWith('/header.js'))).to.not.be.undefined;
       });
 
diff --git a/packages/cli/test/cases/serve.default.ssr/src/templates/app.html b/packages/cli/test/cases/serve.default.ssr/src/templates/app.html
index 2d1227c9..a9e8b7e0 100644
--- a/packages/cli/test/cases/serve.default.ssr/src/templates/app.html
+++ b/packages/cli/test/cases/serve.default.ssr/src/templates/app.html
@@ -5,6 +5,12 @@
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1"/>
     <script type="module" src="../components/header.js"></script>
+    <script>
+      // https://github.com/ProjectEvergreen/greenwood/issues/1154
+      const message = `The current time is ${new Date().getTime()}`;
+
+      alert(message);
+    </script>
   </head>
   <body>
     <app-header></app-header>