mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-02 05:03:44 +08:00
Merge branch 'next' into feature/removeA11yDecorator
This commit is contained in:
commit
cf6c75f027
@ -41,7 +41,7 @@
|
||||
"@storybook/components": "6.0.0-alpha.33",
|
||||
"@storybook/core-events": "6.0.0-alpha.33",
|
||||
"@storybook/theming": "6.0.0-alpha.33",
|
||||
"axe-core": "^3.3.2",
|
||||
"axe-core": "^3.5.2",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"lodash": "^4.17.15",
|
||||
|
@ -15,6 +15,12 @@ It's possible to theme Storybook globally.
|
||||
|
||||
We've created two basic themes that look good out of the box: "normal" (a light theme) and "dark" (a dark theme). Unless you've set your preferred color scheme as dark Storybook will use the light theme as default.
|
||||
|
||||
Make sure you have installed `@storybook/addons` and `@storybook/theming` packages.
|
||||
```sh
|
||||
npm install @storybook/addons --save-dev
|
||||
npm install @storybook/theming --save-dev
|
||||
```
|
||||
|
||||
As an example, you can tell Storybook to use the "dark" theme by modifying `.storybook/manager.js`:
|
||||
|
||||
```js
|
||||
|
@ -47,7 +47,11 @@ export type RefUrl = string;
|
||||
export const getSourceType = (source: string) => {
|
||||
const { origin, pathname } = location;
|
||||
|
||||
if (source === origin || source === `${origin + pathname}iframe.html`) {
|
||||
if (
|
||||
source === origin ||
|
||||
source === `${origin + pathname}iframe.html` ||
|
||||
source === `${origin + pathname.replace(/(?!.*\/).*\.html$/, '')}iframe.html`
|
||||
) {
|
||||
return 'local';
|
||||
}
|
||||
return 'external';
|
||||
|
41
lib/api/src/tests/refs.test.js
Normal file
41
lib/api/src/tests/refs.test.js
Normal file
@ -0,0 +1,41 @@
|
||||
import { getSourceType } from '../modules/refs';
|
||||
|
||||
jest.mock('global', () => {
|
||||
const globalMock = {};
|
||||
// Change global.location value to handle edge cases
|
||||
// Add additional variations of global.location mock return values in this array.
|
||||
// NOTE: The order must match the order that global.location is called in the unit tests.
|
||||
const edgecaseLocations = [
|
||||
{ origin: 'https://storybook.js.org', pathname: '/storybook/index.html' },
|
||||
];
|
||||
// global.location value after all edgecaseLocations are returned
|
||||
const lastLocation = { origin: 'https://storybook.js.org', pathname: '/storybook/' };
|
||||
Object.defineProperties(globalMock, {
|
||||
location: {
|
||||
get: edgecaseLocations
|
||||
.reduce((mockFn, location) => mockFn.mockReturnValueOnce(location), jest.fn())
|
||||
.mockReturnValue(lastLocation),
|
||||
},
|
||||
});
|
||||
return globalMock;
|
||||
});
|
||||
|
||||
describe('refs', () => {
|
||||
describe('getSourceType(source)', () => {
|
||||
// These tests must be run first and in correct order.
|
||||
// The order matches the "edgecaseLocations" order in the 'global' mock function above.
|
||||
describe('edge cases', () => {
|
||||
it('returns "local" when source matches location with /index.html in path', () => {
|
||||
// mockReturnValue(edgecaseLocations[0])
|
||||
expect(getSourceType('https://storybook.js.org/storybook/iframe.html')).toBe('local');
|
||||
});
|
||||
});
|
||||
// Other tests use "lastLocation" for the 'global' mock
|
||||
it('returns "local" when source matches location', () => {
|
||||
expect(getSourceType('https://storybook.js.org/storybook/iframe.html')).toBe('local');
|
||||
});
|
||||
it('returns "external" when source does not match location', () => {
|
||||
expect(getSourceType('https://external.com/storybook/iframe.html')).toBe('external');
|
||||
});
|
||||
});
|
||||
});
|
@ -58,6 +58,7 @@
|
||||
"babel-plugin-emotion": "^10.0.20",
|
||||
"babel-plugin-macros": "^2.8.0",
|
||||
"babel-preset-minify": "^0.5.0 || 0.6.0-alpha.5",
|
||||
"better-opn": "^2.0.0",
|
||||
"boxen": "^4.1.0",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.2.0",
|
||||
"chalk": "^3.0.0",
|
||||
@ -86,7 +87,6 @@
|
||||
"lazy-universal-dotenv": "^3.0.1",
|
||||
"micromatch": "^4.0.2",
|
||||
"node-fetch": "^2.6.0",
|
||||
"open": "^7.0.1",
|
||||
"pkg-dir": "^4.2.0",
|
||||
"pnp-webpack-plugin": "1.6.4",
|
||||
"postcss-flexbugs-fixes": "^4.1.0",
|
||||
|
@ -9,7 +9,7 @@ import chalk from 'chalk';
|
||||
import { logger, colors, instance as npmLog } from '@storybook/node-logger';
|
||||
import fetch from 'node-fetch';
|
||||
import Cache from 'file-system-cache';
|
||||
import open from 'open';
|
||||
import open from 'better-opn';
|
||||
import boxen from 'boxen';
|
||||
import semver from 'semver';
|
||||
import dedent from 'ts-dedent';
|
||||
@ -234,13 +234,15 @@ async function outputStats(previewStats, managerStats) {
|
||||
}
|
||||
|
||||
function openInBrowser(address) {
|
||||
open(address).catch(() => {
|
||||
try {
|
||||
open(address);
|
||||
} catch (error) {
|
||||
logger.error(dedent`
|
||||
Could not open ${address} inside a browser. If you're running this command inside a
|
||||
docker container or on a CI, you need to pass the '--ci' flag to prevent opening a
|
||||
browser by default.
|
||||
`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function buildDevStandalone(options) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import path from 'path';
|
||||
import serverRequire from '../utils/server-require';
|
||||
import { serverRequire, serverResolve } from '../utils/server-require';
|
||||
import validateConfigurationFiles from '../utils/validate-configuration-files';
|
||||
|
||||
export default function loadCustomPresets({ configDir }) {
|
||||
@ -9,7 +9,7 @@ export default function loadCustomPresets({ configDir }) {
|
||||
const main = serverRequire(path.resolve(configDir, 'main'));
|
||||
|
||||
if (main) {
|
||||
return [path.resolve(configDir, 'main')];
|
||||
return [serverResolve(path.resolve(configDir, 'main'))];
|
||||
}
|
||||
|
||||
return presets || [];
|
||||
|
@ -128,7 +128,7 @@ export default ({
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.mjs', '.js', '.jsx', '.json'],
|
||||
extensions: ['.mjs', '.js', '.jsx', '.json', '.cjs'],
|
||||
modules: ['node_modules'].concat(raw.NODE_PATH || []),
|
||||
alias: {
|
||||
...themingPaths,
|
||||
|
@ -147,7 +147,7 @@ export default async ({
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.mjs', '.js', '.jsx', '.json'],
|
||||
extensions: ['.mjs', '.js', '.jsx', '.json', '.cjs'],
|
||||
modules: ['node_modules'].concat(raw.NODE_PATH || []),
|
||||
alias: {
|
||||
'babel-runtime/core-js/object/assign': require.resolve('core-js/es/object/assign'),
|
||||
|
@ -22,9 +22,6 @@ export function getInterpretedFile(pathToFile) {
|
||||
|
||||
export function getInterpretedFileWithExt(pathToFile) {
|
||||
return possibleExtensions
|
||||
.map((ext) => ({
|
||||
path: `${pathToFile}${ext}`,
|
||||
ext,
|
||||
}))
|
||||
.map((ext) => ({ path: `${pathToFile}${ext}`, ext }))
|
||||
.find((candidate) => fs.existsSync(candidate.path));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import path from 'path';
|
||||
import serverRequire from './server-require';
|
||||
import { serverRequire } from './server-require';
|
||||
|
||||
const webpackConfigs = ['webpack.config', 'webpackfile'];
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import interpret from 'interpret';
|
||||
import path from 'path';
|
||||
import { logger } from '@storybook/node-logger';
|
||||
import { getInterpretedFileWithExt } from './interpret-files';
|
||||
|
||||
@ -68,16 +69,14 @@ function getCandidate(paths) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export default function serverRequire(filePath) {
|
||||
const paths = Array.isArray(filePath) ? filePath : [filePath];
|
||||
const existingCandidate = getCandidate(paths);
|
||||
export function serverRequire(filePath) {
|
||||
const candidatePath = serverResolve(filePath);
|
||||
|
||||
if (!existingCandidate) {
|
||||
if (!candidatePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { path: candidatePath, ext: candidateExt } = existingCandidate;
|
||||
|
||||
const candidateExt = path.extname(candidatePath);
|
||||
const moduleDescriptor = interpret.extensions[candidateExt];
|
||||
|
||||
// The "moduleDescriptor" either "undefined" or "null". The warning isn't needed in these cases.
|
||||
@ -90,3 +89,14 @@ export default function serverRequire(filePath) {
|
||||
|
||||
return interopRequireDefault(candidatePath);
|
||||
}
|
||||
|
||||
export function serverResolve(filePath) {
|
||||
const paths = Array.isArray(filePath) ? filePath : [filePath];
|
||||
const existingCandidate = getCandidate(paths);
|
||||
|
||||
if (!existingCandidate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return existingCandidate.path;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import Provider from './provider';
|
||||
|
||||
// @ts-ignore
|
||||
ThemeProvider.displayName = 'ThemeProvider';
|
||||
// @ts-ignore
|
||||
HelmetProvider.displayName = 'HelmetProvider';
|
||||
|
||||
const getDocsMode = () => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user