tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

render-activity-stream-html.js (8253B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /* eslint-disable no-console */
      6 const fs = require("fs");
      7 const { mkdir } = require("shelljs");
      8 const path = require("path");
      9 const { pathToFileURL } = require("url");
     10 const chalk = require("chalk");
     11 
     12 const DEFAULT_OPTIONS = {
     13  // Glob leading from CWD to the parent of the intended prerendered directory.
     14  // Starting in newtab/bin/ and we want to write to newtab/prerendered/ so we
     15  // go up one level.
     16  addonPath: "..",
     17  // depends on the registration in browser/extensions/newtab/jar.mn
     18  baseUrl: "resource://newtab/",
     19  baseVendorUrl: "chrome://global/content/",
     20 };
     21 
     22 /**
     23 * templateHTML - Generates HTML for activity stream, given some options and
     24 * prerendered HTML if necessary.
     25 *
     26 * @param  {obj} options
     27 *         {str} options.baseUrl        The base URL for all local assets
     28 *  *      {str} options.baseVendorUrl  The base URL for all vendor dependencies
     29 *         {bool} options.debug         Should we use dev versions of JS libraries?
     30 *         {bool} options.noscripts     Should we include scripts in the prerendered files?
     31 * @return {str}         An HTML document as a string
     32 */
     33 function templateHTML(options) {
     34  const debugString = options.debug ? "-dev" : "";
     35  // This list must match any similar ones in AboutNewTabChild.sys.mjs
     36  const scripts = [
     37    "chrome://browser/content/contentTheme.js",
     38    `${options.baseVendorUrl}vendor/react${debugString}.js`,
     39    `${options.baseVendorUrl}vendor/react-dom${debugString}.js`,
     40    `${options.baseVendorUrl}vendor/prop-types.js`,
     41    `${options.baseVendorUrl}vendor/redux.js`,
     42    `${options.baseVendorUrl}vendor/react-redux.js`,
     43    `${options.baseVendorUrl}vendor/react-transition-group.js`,
     44    `${options.baseUrl}data/content/activity-stream.bundle.js`,
     45    `${options.baseUrl}data/content/newtab-render.js`,
     46  ];
     47 
     48  // Add spacing and script tags
     49  const scriptRender = `\n${scripts
     50    .map(script => `    <script src="${script}"></script>`)
     51    .join("\n")}`;
     52 
     53  // The markup below needs to be formatted by Prettier. But any diff after
     54  // running this script should be caught by try-runnner.js
     55  return `
     56 <!-- This Source Code Form is subject to the terms of the Mozilla Public
     57   - License, v. 2.0. If a copy of the MPL was not distributed with this file,
     58   - You can obtain one at http://mozilla.org/MPL/2.0/. -->
     59 
     60 <!-- Note: This page is pre-rendered by render-activity-stream-html.js -->
     61 
     62 <!doctype html>
     63 <html>
     64  <head>
     65    <meta charset="utf-8" />
     66    <meta
     67      http-equiv="Content-Security-Policy"
     68      content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob: chrome:; style-src 'unsafe-inline';"
     69    />
     70    <meta name="color-scheme" content="light dark" />
     71    <meta name="viewport" content="width=device-width, initial-scale=1" />
     72    <title data-l10n-id="newtab-page-title"></title>
     73    <link
     74      rel="icon"
     75      type="image/png"
     76      href="chrome://branding/content/icon32.png"
     77    />
     78    <link rel="localization" href="branding/brand.ftl" />
     79    <link rel="localization" href="toolkit/branding/brandings.ftl" />
     80    <link rel="localization" href="browser/newtab/newtab.ftl" />
     81    <link rel="localization" href="toolkit/global/mozMessageBar.ftl" />
     82    <link
     83      rel="stylesheet"
     84      href="chrome://global/skin/design-system/tokens-brand.css"
     85    />
     86    <link
     87      rel="stylesheet"
     88      href="chrome://newtab/content/css/activity-stream.css"
     89    />
     90  </head>
     91  <body class="activity-stream">
     92    <div id="root"></div>${options.noscripts ? "" : scriptRender}
     93    <script
     94      async
     95      type="module"
     96      src="chrome://global/content/elements/moz-toggle.mjs"
     97    ></script>
     98    <script
     99      async
    100      type="module"
    101      src="chrome://global/content/elements/moz-badge.mjs"
    102    ></script>
    103    <script
    104      async
    105      type="module"
    106      src="chrome://global/content/elements/moz-button.mjs"
    107    ></script>
    108    <script
    109      async
    110      type="module"
    111      src="chrome://global/content/elements/moz-button-group.mjs"
    112    ></script>
    113    <script
    114      async
    115      type="module"
    116      src="chrome://global/content/elements/moz-box-button.mjs"
    117    ></script>
    118    <script
    119      async
    120      type="module"
    121      src="chrome://global/content/elements/moz-message-bar.mjs"
    122    ></script>
    123    <script
    124      async
    125      type="module"
    126      src="chrome://global/content/elements/moz-radio-group.mjs"
    127    ></script>
    128    <script
    129      async
    130      type="module"
    131      src="chrome://global/content/elements/moz-select.mjs"
    132    ></script>
    133    <script
    134      async
    135      type="module"
    136      src="chrome://global/content/elements/moz-reorderable-list.mjs"
    137    ></script>
    138    <script
    139      async
    140      type="module"
    141      src="chrome://global/content/elements/panel-list.js"
    142    ></script>
    143    <script
    144      async
    145      type="module"
    146      src="chrome://global/content/elements/moz-support-link.mjs"
    147    ></script>
    148  </body>
    149 </html>
    150 `.trimLeft();
    151 }
    152 
    153 /**
    154 * writeFiles - Writes to the desired files the result of a template given
    155 * various prerendered data and options.
    156 *
    157 * @param {string} destPath      Path to write the files to
    158 * @param {Map}    filesMap      Mapping of a string file name to templater
    159 * @param {object} options       Various options for the templater
    160 */
    161 function writeFiles(destPath, filesMap, options) {
    162  for (const [file, templater] of filesMap) {
    163    fs.writeFileSync(path.join(destPath, file), templater({ options }));
    164    console.log(chalk.green(`✓ ${file}`));
    165  }
    166 }
    167 
    168 const STATIC_FILES = new Map([
    169  ["activity-stream.html", ({ options }) => templateHTML(options)],
    170  [
    171    "activity-stream-debug.html",
    172    ({ options }) => templateHTML(Object.assign({}, options, { debug: true })),
    173  ],
    174  [
    175    "activity-stream-noscripts.html",
    176    ({ options }) =>
    177      templateHTML(Object.assign({}, options, { noscripts: true })),
    178  ],
    179 ]);
    180 
    181 /**
    182 * main - Parses command line arguments, generates html and js with templates,
    183 *        and writes files to their specified locations.
    184 */
    185 async function main() {
    186  const { default: meow } = await import("meow");
    187  const fileUrl = pathToFileURL(__filename);
    188  const cli = meow(
    189    `
    190    Usage
    191      $ node ./bin/render-activity-stream-html.js [options]
    192 
    193    Options
    194      -a PATH, --addon-path PATH   Path to the parent of the target directory.
    195                                   default: "${DEFAULT_OPTIONS.addonPath}"
    196      -b URL, --base-url URL       Base URL for assets.
    197                                   default: "${DEFAULT_OPTIONS.baseUrl}"
    198      --help                       Show this help message.
    199 `,
    200    {
    201      description: false,
    202      // `pkg` is a tiny optimization. It prevents meow from looking for a package
    203      // that doesn't technically exist. meow searches for a package and changes
    204      // the process name to the package name. It resolves to the newtab
    205      // package.json, which would give a confusing name and be wasteful.
    206      pkg: {
    207        name: "render-activity-stream-html",
    208        version: "0.0.0",
    209      },
    210      // `importMeta` is required by meow 10+. It was added to support ESM, but
    211      // meow now requires it, and no longer supports CJS style imports. But it
    212      // only uses import.meta.url, which can be polyfilled like this:
    213      importMeta: { url: fileUrl },
    214      flags: {
    215        addonPath: {
    216          type: "string",
    217          shortFlag: "a",
    218          default: DEFAULT_OPTIONS.addonPath,
    219        },
    220        baseUrl: {
    221          type: "string",
    222          shortFlag: "b",
    223          default: DEFAULT_OPTIONS.baseUrl,
    224        },
    225        baseVendorUrl: {
    226          type: "string",
    227          shortFlag: "v",
    228          default: DEFAULT_OPTIONS.baseVendorUrl,
    229        },
    230      },
    231    }
    232  );
    233 
    234  const options = Object.assign({ debug: false }, cli.flags || {});
    235  const addonPath = path.resolve(__dirname, options.addonPath);
    236  const prerenderedPath = path.join(addonPath, "prerendered");
    237  console.log(`Writing prerendered files to ${prerenderedPath}:`);
    238 
    239  mkdir("-p", prerenderedPath);
    240  writeFiles(prerenderedPath, STATIC_FILES, options);
    241 }
    242 
    243 main();