Revision control

Copy as Markdown

Other Tools

/* 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 { useEffect, useGlobals, useChannel } from "@storybook/preview-api";
import {
DIRECTIONS,
DIRECTION_BY_STRATEGY,
UPDATE_STRATEGY_EVENT,
FLUENT_CHANGED,
} from "./constants.mjs";
import { provideFluent } from "../fluent-utils.mjs";
/**
* withPseudoLocalization is a Storybook decorator that handles emitting an
* event to update translations when a new pseudo localization strategy is
* applied. It also handles setting a "dir" attribute on the root element in the
* Storybook iframe.
*
* @param {Function} StoryFn - Provided by Storybook, used to render the story.
* @param {Object} context - Provided by Storybook, data about the story.
* @returns {Function} StoryFn with a modified "dir" attr set.
*/
export const withPseudoLocalization = (StoryFn, context) => {
const [{ pseudoStrategy }] = useGlobals();
const direction = DIRECTION_BY_STRATEGY[pseudoStrategy] || DIRECTIONS.ltr;
const isInDocs = context.viewMode === "docs";
const emit = useChannel({});
useEffect(() => {
if (pseudoStrategy) {
emit(UPDATE_STRATEGY_EVENT, pseudoStrategy);
}
}, [pseudoStrategy]);
useEffect(() => {
if (isInDocs) {
document.documentElement.setAttribute("dir", DIRECTIONS.ltr);
let storyElements = document.querySelectorAll(".docs-story");
storyElements.forEach(element => element.setAttribute("dir", direction));
} else {
document.documentElement.setAttribute("dir", direction);
}
}, [direction, isInDocs]);
return StoryFn();
};
/**
* withFluentStrings is a Storybook decorator that handles emitting an
* event to update the Fluent strings shown in the Fluent panel.
*
* @param {Function} StoryFn - Provided by Storybook, used to render the story.
* @param {Object} context - Provided by Storybook, data about the story.
* @returns {Function} StoryFn unmodified.
*/
export const withFluentStrings = (StoryFn, context) => {
const [{ fluentStrings }, updateGlobals] = useGlobals();
const emit = useChannel({});
const fileName = context.component + ".ftl";
let strings = [];
if (context.parameters?.fluent && fileName) {
if (fluentStrings.hasOwnProperty(fileName)) {
strings = fluentStrings[fileName];
} else {
let resource = provideFluent(context.parameters.fluent, fileName);
for (let message of resource.body) {
strings.push([
message.id,
[
message.value,
...Object.entries(message.attributes).map(
([key, value]) => ` .${key} = ${value}`
),
].join("\n"),
]);
}
updateGlobals({
fluentStrings: { ...fluentStrings, [fileName]: strings },
});
}
}
emit(FLUENT_CHANGED, strings, fileName);
return StoryFn();
};