All files / repo-tools/src/vite-plugins html-trusted-prelude.ts

0% Statements 0/13
0% Branches 0/8
0% Functions 0/2
0% Lines 0/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51                                                                                                     
import { load as loadHtml } from 'cheerio';
import { format as prettierFormat } from 'prettier';
import type { Plugin as VitePlugin } from 'vite';
 
/**
 * Vite plugin to insert the endoify script before the first script in the head element.
 * Assumes that `endoify.js` is located in the root of the web app.
 *
 * @throws If the HTML document already references the endoify script or lacks the expected
 * structure.
 * @returns The Vite plugin.
 */
export function htmlTrustedPrelude(): VitePlugin {
  return {
    name: 'ocap-kernel:html-trusted-prelude',
    async transformIndexHtml(htmlString): Promise<string> {
      const htmlDoc = loadHtml(htmlString);
 
      if (htmlDoc('script[src="endoify.ts"]').length > 0) {
        throw new Error(
          `HTML document should not reference "endoify.ts" directly:\n${htmlString}`,
        );
      }
 
      if (htmlDoc('script[src*="endoify.js"]').length > 0) {
        throw new Error(
          `HTML document already references endoify script:\n${htmlString}`,
        );
      }
 
      if (htmlDoc('head').length !== 1) {
        throw new Error(
          `Expected HTML document with a single <head>. Received:\n${htmlString}`,
        );
      }
 
      const endoifyElement = `<script src="/endoify.js" type="module"></script>`;
      if (htmlDoc('head > script').length >= 1) {
        htmlDoc(endoifyElement).insertBefore('head:first script:first');
      } else {
        htmlDoc(endoifyElement).appendTo('head:first');
      }
 
      return await prettierFormat(htmlDoc.html(), {
        parser: 'html',
        tabWidth: 2,
      });
    },
  };
}