build(#10336): control themes

This commit is contained in:
Acid Chicken (硫酸鶏) 2023-03-21 02:05:00 +09:00
parent bdbbb92ff6
commit 0ac4d744fd
No known key found for this signature in database
GPG Key ID: 3E87B98A3F6BAB99
7 changed files with 843 additions and 195 deletions

View File

@ -1,8 +1,8 @@
# (cd .; pnpm tsc --jsx react --jsxFactory h ./generate.tsx && node ./generate.js)
# (cd path/to/frontend; pnpm tsc --jsx react --jsxFactory h .storybook/generate.tsx && node .storybook/generate.js)
/generate.js
# (cd .; pnpm tsc ./preload-locale.ts && node ./preload-locale.js)
# (cd path/to/frontend; pnpm tsc .storybook/preload-locale.ts && node .storybook/preload-locale.js)
/preload-locale.js
/locale.ts
# (cd .; pnpm tsc ./preload-theme.ts && node ./preload-theme.js)
# (cd path/to/frontend; pnpm tsc .storybook/preload-theme.ts && node .storybook/preload-theme.js)
/preload-theme.js
/theme.ts
/themes.ts

View File

@ -8,6 +8,7 @@ const config = {
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'../node_modules/storybook-addon-misskey-theme',
],
framework: {
name: '@storybook/vue3-vite',

View File

@ -2,19 +2,35 @@ import { readFile, writeFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import * as JSON5 from 'json5';
Promise.all([
readFile(resolve(__dirname, '../src/themes/_light.json5'), 'utf8'),
readFile(resolve(__dirname, '../src/themes/l-light.json5'), 'utf8'),
]).then((sources) => {
const base = JSON5.parse(sources[0]);
const theme = JSON5.parse(sources[1]);
const keys = [
'_dark',
'_light',
'l-light',
'l-coffee',
'l-apricot',
'l-rainy',
'l-botanical',
'l-vivid',
'l-cherry',
'l-sushi',
'l-u0',
'd-dark',
'd-persimmon',
'd-astro',
'd-future',
'd-botanical',
'd-green-lime',
'd-green-orange',
'd-cherry',
'd-ice',
'd-u0',
]
Promise.all(keys.map((key) => readFile(resolve(__dirname, `../src/themes/${key}.json5`), 'utf8'))).then((sources) => {
writeFile(
resolve(__dirname, './theme.ts'),
resolve(__dirname, './themes.ts'),
`export default ${JSON.stringify(
Object.assign(theme, {
base: undefined,
props: Object.assign(base.props, theme.props),
}),
Object.fromEntries(sources.map((source, i) => [keys[i], JSON5.parse(source)])),
undefined,
2,
)} as const;`,

View File

@ -1,30 +1,75 @@
import { type Preview, setup } from '@storybook/vue3';
import { addons } from '@storybook/addons';
import { FORCE_REMOUNT } from '@storybook/core-events';
import { type Preview, forceReRender, setup } from '@storybook/vue3';
import { initialize, mswDecorator } from 'msw-storybook-addon';
import locale from './locale';
import { commonHandlers, onUnhandledRequest } from './mocks';
import theme from './theme';
import themes from './themes';
import '../src/style.scss';
let initialized = false;
let unobserve = () => {};
function loadTheme(applyTheme: typeof import('../src/scripts/theme')['applyTheme']) {
unobserve();
const theme = themes[document.documentElement.dataset.misskeyTheme];
if (theme) {
applyTheme(themes[document.documentElement.dataset.misskeyTheme]);
}
const observer = new MutationObserver((entries) => {
for (const entry of entries) {
if (entry.attributeName === 'data-misskey-theme') {
const target = entry.target as HTMLElement;
const theme = themes[target.dataset.misskeyTheme];
if (theme) {
applyTheme(themes[target.dataset.misskeyTheme]);
} else {
target.removeAttribute('style');
}
}
}
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-misskey-theme'],
});
unobserve = () => observer.disconnect();
}
initialize({
onUnhandledRequest,
});
localStorage.setItem("locale", JSON.stringify(locale));
Promise.all([
import('../src/components'),
import('../src/directives'),
import('../src/widgets'),
import('../src/scripts/theme').then(({ applyTheme }) => applyTheme(theme)),
]).then(([{ default: components }, { default: directives }, { default: widgets }]) => {
setup((app) => {
components(app);
directives(app);
widgets(app);
queueMicrotask(() => {
Promise.all([
import('../src/components'),
import('../src/directives'),
import('../src/widgets'),
import('../src/scripts/theme'),
]).then(([{ default: components }, { default: directives }, { default: widgets }, { applyTheme }]) => {
setup((app) => {
initialized = true;
loadTheme(applyTheme);
components(app);
directives(app);
widgets(app);
});
});
});
const preview = {
decorators: [
mswDecorator,
(Story, context) => {
const story = Story();
if (!initialized) {
const channel = addons.getChannel();
requestIdleCallback(() => {
channel.emit(FORCE_REMOUNT, { storyId: context.id });
});
}
return story;
}
],
parameters: {
msw: {

View File

@ -75,10 +75,16 @@
"@storybook/addon-essentials": "^7.0.0-rc.4",
"@storybook/addon-interactions": "^7.0.0-rc.4",
"@storybook/addon-links": "^7.0.0-rc.4",
"@storybook/addons": "7.0.0-rc.5",
"@storybook/blocks": "^7.0.0-rc.4",
"@storybook/manager-api": "7.0.0-rc.4",
"@storybook/core-events": "^7.0.0-rc.4",
"@storybook/manager-api": "^7.0.0-rc.4",
"@storybook/preview-api": "^7.0.0-rc.4",
"@storybook/react": "^7.0.0-rc.4",
"@storybook/react-vite": "^7.0.0-rc.4",
"@storybook/testing-library": "^0.0.14-next.1",
"@storybook/theming": "7.0.0-rc.4",
"@storybook/theming": "^7.0.0-rc.4",
"@storybook/types": "^7.0.0-rc.4",
"@storybook/vue3": "^7.0.0-rc.4",
"@storybook/vue3-vite": "^7.0.0-rc.4",
"@testing-library/vue": "^6.6.1",
@ -114,6 +120,7 @@
"react-dom": "^18.2.0",
"start-server-and-test": "2.0.0",
"storybook": "^7.0.0-rc.4",
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
"summaly": "github:misskey-dev/summaly",
"vitest": "^0.29.2",
"vitest-fetch-mock": "^0.2.2",

View File

@ -3,7 +3,6 @@ export class I18n<T extends Record<string, any>> {
constructor(locale: T) {
this.ts = locale;
console.log(this);
//#region BIND
this.t = this.t.bind(this);

910
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff