summaryrefslogtreecommitdiffstats
path: root/browser/components/storybook/.storybook/main.js
blob: 5207172b6e31e5d15a004ceab3a23a9c61c9b5ee (plain)
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env node */

const path = require("path");
const webpack = require("webpack");

const [prefixMap, aliasMap, sourceMap] = require("./chrome-map.js");

const projectRoot = path.resolve(__dirname, "../../../../");

function rewriteChromeUri(uri) {
  if (uri in aliasMap) {
    return rewriteChromeUri(aliasMap[uri]);
  }
  for (let [prefix, [bundlePath]] of Object.entries(prefixMap)) {
    if (uri.startsWith(prefix)) {
      if (!bundlePath.endsWith("/")) {
        bundlePath += "/";
      }
      let relativePath = uri.slice(prefix.length);
      let objdirPath = bundlePath + relativePath;
      for (let [_objdirPath, [filePath]] of Object.entries(sourceMap)) {
        if (_objdirPath == objdirPath) {
          // We're just hoping this is the actual path =\
          return filePath;
        }
      }
    }
  }
  return "";
}

module.exports = {
  // The ordering for this stories array affects the order that they are displayed in Storybook
  stories: [
    // Docs section
    "../**/README.*.stories.md",
    // UI Widgets section
    `${projectRoot}/toolkit/content/widgets/**/*.stories.@(js|jsx|mjs|ts|tsx|md)`,
    // Everything else
    "../stories/**/*.stories.@(js|jsx|mjs|ts|tsx|md)",
  ],
  // Additions to the staticDirs might also need to get added to
  // MozXULElement.importCss in preview.mjs to enable auto-reloading.
  staticDirs: [
    `${projectRoot}/toolkit/content/widgets/`,
    `${projectRoot}/browser/themes/shared/`,
    `${projectRoot}/browser/components/firefoxview/`,
  ],
  addons: [
    "@storybook/addon-links",
    {
      name: "@storybook/addon-essentials",
      options: {
        backgrounds: false,
        measure: false,
        outline: false,
      },
    },
    "@storybook/addon-a11y",
    path.resolve(__dirname, "addon-pseudo-localization"),
    path.resolve(__dirname, "addon-component-status"),
  ],
  framework: "@storybook/web-components",
  webpackFinal: async (config, { configType }) => {
    // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
    // You can change the configuration based on that.
    // 'PRODUCTION' is used when building the static version of storybook.

    // Make whatever fine-grained changes you need
    config.resolve.alias.browser = `${projectRoot}/browser`;
    config.resolve.alias.toolkit = `${projectRoot}/toolkit`;
    config.resolve.alias[
      "toolkit-widgets"
    ] = `${projectRoot}/toolkit/content/widgets/`;
    config.resolve.alias[
      "lit.all.mjs"
    ] = `${projectRoot}/toolkit/content/widgets/vendor/lit.all.mjs`;
    // @mdx-js/react@1.x.x versions don't get hoisted to the root node_modules
    // folder due to the versions of React it accepts as a peer dependency. That
    // means we have to go one level deeper and look in the node_modules of
    // @storybook/addon-docs, which depends on @mdx-js/react.
    config.resolve.alias["@storybook/addon-docs"] =
      "browser/components/storybook/node_modules/@storybook/addon-docs";
    config.resolve.alias["@mdx-js/react"] =
      "@storybook/addon-docs/node_modules/@mdx-js/react";

    // The @storybook/web-components project uses lit-html. Redirect it to our
    // bundled version.
    config.resolve.alias["lit-html/directive-helpers.js"] = "lit.all.mjs";
    config.resolve.alias["lit-html"] = "lit.all.mjs";

    config.plugins.push(
      // Rewrite chrome:// URI imports to file system paths.
      new webpack.NormalModuleReplacementPlugin(/^chrome:\/\//, resource => {
        resource.request = rewriteChromeUri(resource.request);
      })
    );

    config.module.rules.push({
      test: /\.ftl$/,
      type: "asset/source",
    });

    // We're adding a rule for files matching this pattern in order to support
    // writing docs only stories in plain markdown.
    const MD_STORY_REGEX = /(stories|story)\.md$/;

    // Find the existing rule for MDX stories.
    let mdxStoryTest = /(stories|story)\.mdx$/.toString();
    let mdxRule = config.module.rules.find(
      rule => rule.test.toString() === mdxStoryTest
    );

    // Use a custom Webpack loader to transform our markdown stories into MDX,
    // then run our new MDX through the same loaders that Storybook usually uses
    // for MDX files. This is how we get a docs page from plain markdown.
    config.module.rules.push({
      test: MD_STORY_REGEX,
      use: [
        ...mdxRule.use,
        { loader: path.resolve(__dirname, "./markdown-story-loader.js") },
      ],
    });

    // Find the existing rule for markdown files.
    let markdownTest = /\.md$/.toString();
    let markdownRuleIndex = config.module.rules.findIndex(
      rule => rule.test.toString() === markdownTest
    );
    let markdownRule = config.module.rules[markdownRuleIndex];

    // Modify the existing markdown rule so it doesn't process .stories.md
    // files, but still treats any other markdown files as asset/source.
    config.module.rules[markdownRuleIndex] = {
      ...markdownRule,
      exclude: MD_STORY_REGEX,
    };

    config.optimization = {
      splitChunks: false,
      runtimeChunk: false,
      sideEffects: false,
      usedExports: false,
      concatenateModules: false,
      minimizer: [],
    };

    // Return the altered config
    return config;
  },
  core: {
    builder: "webpack5",
  },
};