From 16c3d7214b8295a35520a0990dedc02fbd3016ce Mon Sep 17 00:00:00 2001 From: Mark Striemer Date: Mon, 12 Sep 2022 21:13:20 +0000 Subject: [PATCH] Bug 1788798 - Support fluent in storybook r=hjones Depends on D156241 Differential Revision: https://phabricator.services.mozilla.com/D156244 --- .eslintignore | 3 + .../components/storybook/.storybook/main.js | 37 +++++++----- .../storybook/.storybook/preview.js | 60 +++++++++++++++++++ .../components/storybook/package-lock.json | 55 +++++++++++++++++ browser/components/storybook/package.json | 2 + .../storybook/stories/message-bar.stories.js | 8 --- 6 files changed, 141 insertions(+), 24 deletions(-) diff --git a/.eslintignore b/.eslintignore index d1e876e516d1..a3f5ffae1543 100644 --- a/.eslintignore +++ b/.eslintignore @@ -42,6 +42,9 @@ browser/components/enterprisepolicies/schemas/schema.jsm browser/components/pocket/content/panels/js/tmpl.js browser/components/pocket/content/panels/js/vendor.bundle.js browser/components/pocket/content/panels/js/main.bundle.js +# Include the Storybook config files. +!browser/components/storybook/.storybook/ +!browser/components/storybook/.storybook/*.js # Ignore newtab files browser/components/newtab/aboutwelcome/content/aboutwelcome.bundle.js diff --git a/browser/components/storybook/.storybook/main.js b/browser/components/storybook/.storybook/main.js index 230dc5add9c8..0061e164e69a 100644 --- a/browser/components/storybook/.storybook/main.js +++ b/browser/components/storybook/.storybook/main.js @@ -1,32 +1,37 @@ /* 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 path = require("path"); // ./mach environment --format json // topobjdir should be the build location module.exports = { - "stories": [ + stories: [ "../stories/**/*.stories.mdx", - "../stories/**/*.stories.@(js|jsx|ts|tsx)" + "../stories/**/*.stories.@(js|jsx|ts|tsx)", ], - "addons": [ - "@storybook/addon-links", - "@storybook/addon-essentials" - ], - "framework": "@storybook/web-components", - "webpackFinal": async (config, { configType }) => { + addons: ["@storybook/addon-links", "@storybook/addon-essentials"], + 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 const projectRoot = path.resolve(__dirname, "../../../../"); - config.resolve.alias["browser"] = `${projectRoot}/browser`; - config.resolve.alias["toolkit"] = `${projectRoot}/toolkit`; - config.resolve.alias["toolkit-widgets"] = `${projectRoot}/toolkit/content/widgets/`; + config.resolve.alias.browser = `${projectRoot}/browser`; + config.resolve.alias.toolkit = `${projectRoot}/toolkit`; + config.resolve.alias[ + "toolkit-widgets" + ] = `${projectRoot}/toolkit/content/widgets/`; + + config.module.rules.push({ + test: /\.ftl$/, + type: "asset/source", + }); config.optimization = { splitChunks: false, @@ -40,7 +45,7 @@ module.exports = { // Return the altered config return config; }, - "core": { - "builder": "webpack5" - } -} + core: { + builder: "webpack5", + }, +}; diff --git a/browser/components/storybook/.storybook/preview.js b/browser/components/storybook/.storybook/preview.js index e69de29bb2d1..942ae621e8ee 100644 --- a/browser/components/storybook/.storybook/preview.js +++ b/browser/components/storybook/.storybook/preview.js @@ -0,0 +1,60 @@ +/* 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/. */ + +import { DOMLocalization } from "@fluent/dom"; +import { FluentBundle, FluentResource } from "@fluent/bundle"; + +// Base Fluent set up. +let storybookBundle = new FluentBundle("en-US"); +let loadedResources = new Set(); +function* generateBundles() { + yield* [storybookBundle]; +} +document.l10n = new DOMLocalization([], generateBundles); +document.l10n.connectRoot(document.documentElement); + +// Any fluent imports should go through MozXULElement.insertFTLIfNeeded. +window.MozXULElement = { + async insertFTLIfNeeded(name) { + if (loadedResources.has(name)) { + return; + } + + // This should be browser or toolkit. + let root = name.split("/")[0]; + let ftlContents; + // + // TODO(mstriemer): These seem like they could be combined but I don't want + // to fight with webpack anymore. + if (root == "toolkit") { + // eslint-disable-next-line no-unsanitized/method + let imported = await import( + /* webpackInclude: /.*[\/\\].*\.ftl/ */ + `toolkit/locales/en-US/${name}` + ); + ftlContents = imported.default; + } else if (root == "browser") { + // eslint-disable-next-line no-unsanitized/method + let imported = await import( + /* webpackInclude: /.*[\/\\].*\.ftl/ */ + `browser/locales/en-US/${name}` + ); + ftlContents = imported.default; + } + + if (loadedResources.has(name)) { + // Seems possible we've attempted to load this twice before the first call + // resolves, so once the first load is complete we can abandon the others. + return; + } + + let ftlResource = new FluentResource(ftlContents); + storybookBundle.addResource(ftlResource); + loadedResources.add(name); + document.l10n.translateRoots(); + }, +}; + +// Most companion elements expect this to be on the page already. +window.MozXULElement.insertFTLIfNeeded("browser/companion.ftl"); diff --git a/browser/components/storybook/package-lock.json b/browser/components/storybook/package-lock.json index 2d875c5585d0..a19c81809d64 100644 --- a/browser/components/storybook/package-lock.json +++ b/browser/components/storybook/package-lock.json @@ -13,6 +13,8 @@ }, "devDependencies": { "@babel/core": "^7.16.0", + "@fluent/bundle": "^0.17.1", + "@fluent/dom": "^0.8.1", "@storybook/addon-actions": "^6.4.8", "@storybook/addon-essentials": "^6.4.8", "@storybook/addon-links": "^6.4.8", @@ -1996,6 +1998,29 @@ "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==", "dev": true }, + "node_modules/@fluent/bundle": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@fluent/bundle/-/bundle-0.17.1.tgz", + "integrity": "sha512-CRFNT9QcSFAeFDneTF59eyv3JXFGhIIN4boUO2y22YmsuuKLyDk+N1I/NQUYz9Ab63e6V7T6vItoZIG/2oOOuw==", + "dev": true, + "engines": { + "node": ">=12.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@fluent/dom": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@fluent/dom/-/dom-0.8.1.tgz", + "integrity": "sha512-wlQ3vHgioDL8dC0wcZ9AyCSpOgor0OREKXJMvvnx6bzk/PT2SZNA5frslmSdbEaiBQIVy2MhVvAIDtbKbdoVCg==", + "dev": true, + "dependencies": { + "cached-iterable": "^0.3" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@gar/promisify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", @@ -7932,6 +7957,15 @@ "node": ">=0.10.0" } }, + "node_modules/cached-iterable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/cached-iterable/-/cached-iterable-0.3.0.tgz", + "integrity": "sha512-MDqM6TpBVebZD4UDtmlFp8EjVtRcsB6xt9aRdWymjk0fWVUUGgmt/V7o0H0gkI2Tkvv8B0ucjidZm4mLosdlWw==", + "dev": true, + "engines": { + "node": ">=8.9.0" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -21458,6 +21492,21 @@ "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==", "dev": true }, + "@fluent/bundle": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@fluent/bundle/-/bundle-0.17.1.tgz", + "integrity": "sha512-CRFNT9QcSFAeFDneTF59eyv3JXFGhIIN4boUO2y22YmsuuKLyDk+N1I/NQUYz9Ab63e6V7T6vItoZIG/2oOOuw==", + "dev": true + }, + "@fluent/dom": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@fluent/dom/-/dom-0.8.1.tgz", + "integrity": "sha512-wlQ3vHgioDL8dC0wcZ9AyCSpOgor0OREKXJMvvnx6bzk/PT2SZNA5frslmSdbEaiBQIVy2MhVvAIDtbKbdoVCg==", + "dev": true, + "requires": { + "cached-iterable": "^0.3" + } + }, "@gar/promisify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", @@ -25961,6 +26010,12 @@ "unset-value": "^1.0.0" } }, + "cached-iterable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/cached-iterable/-/cached-iterable-0.3.0.tgz", + "integrity": "sha512-MDqM6TpBVebZD4UDtmlFp8EjVtRcsB6xt9aRdWymjk0fWVUUGgmt/V7o0H0gkI2Tkvv8B0ucjidZm4mLosdlWw==", + "dev": true + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", diff --git a/browser/components/storybook/package.json b/browser/components/storybook/package.json index 74a23eaf35cd..2c5ffd5c5069 100644 --- a/browser/components/storybook/package.json +++ b/browser/components/storybook/package.json @@ -12,6 +12,8 @@ "license": "MPL-2.0", "devDependencies": { "@babel/core": "^7.16.0", + "@fluent/bundle": "^0.17.1", + "@fluent/dom": "^0.8.1", "@storybook/addon-actions": "^6.4.8", "@storybook/addon-essentials": "^6.4.8", "@storybook/addon-links": "^6.4.8", diff --git a/browser/components/storybook/stories/message-bar.stories.js b/browser/components/storybook/stories/message-bar.stories.js index 9da7f4178a4c..2948c5a7c7c9 100644 --- a/browser/components/storybook/stories/message-bar.stories.js +++ b/browser/components/storybook/stories/message-bar.stories.js @@ -2,14 +2,6 @@ * 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/. */ -// TODO(mstriemer): These stubs should be moved somewhere central, or ideally -// they wouldn't be needed. -window.MozXULElement = { insertFTLIfNeeded() {} }; -document.l10n = { - connectRoot() {}, - setAttributes() {}, -}; - import { html } from "lit"; import "toolkit-widgets/message-bar.js";