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 /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 /preload-locale.js
/locale.ts /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 /preload-theme.js
/theme.ts /themes.ts

View file

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

View file

@ -2,19 +2,35 @@ import { readFile, writeFile } from 'node:fs/promises';
import { resolve } from 'node:path'; import { resolve } from 'node:path';
import * as JSON5 from 'json5'; import * as JSON5 from 'json5';
Promise.all([ const keys = [
readFile(resolve(__dirname, '../src/themes/_light.json5'), 'utf8'), '_dark',
readFile(resolve(__dirname, '../src/themes/l-light.json5'), 'utf8'), '_light',
]).then((sources) => { 'l-light',
const base = JSON5.parse(sources[0]); 'l-coffee',
const theme = JSON5.parse(sources[1]); '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( writeFile(
resolve(__dirname, './theme.ts'), resolve(__dirname, './themes.ts'),
`export default ${JSON.stringify( `export default ${JSON.stringify(
Object.assign(theme, { Object.fromEntries(sources.map((source, i) => [keys[i], JSON5.parse(source)])),
base: undefined,
props: Object.assign(base.props, theme.props),
}),
undefined, undefined,
2, 2,
)} as const;`, )} 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 { initialize, mswDecorator } from 'msw-storybook-addon';
import locale from './locale'; import locale from './locale';
import { commonHandlers, onUnhandledRequest } from './mocks'; import { commonHandlers, onUnhandledRequest } from './mocks';
import theme from './theme'; import themes from './themes';
import '../src/style.scss'; 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({ initialize({
onUnhandledRequest, onUnhandledRequest,
}); });
localStorage.setItem("locale", JSON.stringify(locale)); localStorage.setItem("locale", JSON.stringify(locale));
Promise.all([ queueMicrotask(() => {
Promise.all([
import('../src/components'), import('../src/components'),
import('../src/directives'), import('../src/directives'),
import('../src/widgets'), import('../src/widgets'),
import('../src/scripts/theme').then(({ applyTheme }) => applyTheme(theme)), import('../src/scripts/theme'),
]).then(([{ default: components }, { default: directives }, { default: widgets }]) => { ]).then(([{ default: components }, { default: directives }, { default: widgets }, { applyTheme }]) => {
setup((app) => { setup((app) => {
initialized = true;
loadTheme(applyTheme);
components(app); components(app);
directives(app); directives(app);
widgets(app); widgets(app);
}); });
});
}); });
const preview = { const preview = {
decorators: [ decorators: [
mswDecorator, mswDecorator,
(Story, context) => {
const story = Story();
if (!initialized) {
const channel = addons.getChannel();
requestIdleCallback(() => {
channel.emit(FORCE_REMOUNT, { storyId: context.id });
});
}
return story;
}
], ],
parameters: { parameters: {
msw: { msw: {

View file

@ -75,10 +75,16 @@
"@storybook/addon-essentials": "^7.0.0-rc.4", "@storybook/addon-essentials": "^7.0.0-rc.4",
"@storybook/addon-interactions": "^7.0.0-rc.4", "@storybook/addon-interactions": "^7.0.0-rc.4",
"@storybook/addon-links": "^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/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/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": "^7.0.0-rc.4",
"@storybook/vue3-vite": "^7.0.0-rc.4", "@storybook/vue3-vite": "^7.0.0-rc.4",
"@testing-library/vue": "^6.6.1", "@testing-library/vue": "^6.6.1",
@ -114,6 +120,7 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"start-server-and-test": "2.0.0", "start-server-and-test": "2.0.0",
"storybook": "^7.0.0-rc.4", "storybook": "^7.0.0-rc.4",
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
"summaly": "github:misskey-dev/summaly", "summaly": "github:misskey-dev/summaly",
"vitest": "^0.29.2", "vitest": "^0.29.2",
"vitest-fetch-mock": "^0.2.2", "vitest-fetch-mock": "^0.2.2",

View file

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

File diff suppressed because it is too large Load diff