@storybook/react-native
Version:
A better way to develop React Native Components for your app
152 lines (115 loc) • 3.63 kB
JavaScript
const {
toRequireContext,
ensureRelativePathHasDot,
getMain,
getPreviewExists,
resolveAddonFile,
getAddonName,
} = require('./common');
const { normalizeStories, globToRegexp } = require('@storybook/core/common');
const fs = require('fs');
const prettier = require('prettier');
const path = require('path');
const cwd = process.cwd();
function generate({ configPath, absolute = false, useJs = false }) {
const storybookRequiresLocation = path.resolve(
cwd,
configPath,
`storybook.requires.${useJs ? 'js' : 'ts'}`
);
const mainImport = getMain({ configPath });
const main = mainImport.default ?? mainImport;
// const reactNativeOptions = main.reactNativeOptions;
const storiesSpecifiers = normalizeStories(main.stories, {
configDir: configPath,
workingDir: cwd,
});
const normalizedStories = storiesSpecifiers.map((specifier) => {
// TODO why????
const reg = globToRegexp(`./${specifier.files}`);
const { path: p, recursive: r, match: m } = toRequireContext(specifier);
const pathToStory = ensureRelativePathHasDot(path.posix.relative(configPath, p));
return `{
titlePrefix: "${specifier.titlePrefix}",
directory: "${specifier.directory}",
files: "${specifier.files}",
importPathMatcher: /${reg.source}/,
${useJs ? '' : '// @ts-ignore'}
req: require.context('${pathToStory}', ${r}, ${m})
}`;
});
let registerAddons = '';
for (const addon of main.addons) {
const registerPath = resolveAddonFile(
getAddonName(addon),
'register',
['js', 'mjs', 'jsx', 'ts', 'tsx'],
configPath
);
if (registerPath) {
registerAddons += `import "${registerPath}";\n`;
}
}
const docTools = 'require("@storybook/react-native/preview")';
const enhancers = [docTools];
for (const addon of main.addons) {
const previewPath = resolveAddonFile(
getAddonName(addon),
'preview',
['js', 'mjs', 'jsx', 'ts', 'tsx'],
configPath
);
if (previewPath) {
enhancers.push(`require('${previewPath}')`);
continue;
}
}
let options = '';
let optionsVar = '';
const reactNativeOptions = main.reactNative;
if (reactNativeOptions && typeof reactNativeOptions === 'object') {
optionsVar = `const options = ${JSON.stringify(reactNativeOptions)}`;
options = 'options';
}
const previewExists = getPreviewExists({ configPath });
if (previewExists) {
enhancers.unshift("require('./preview')");
}
const annotations = `[${enhancers.join(', ')}]`;
const globalTypes = `
declare global {
var view: ReturnType<typeof start>;
var STORIES: typeof normalizedStories;
}
`;
const fileContent = `
/* do not change this file, it is auto generated by storybook. */
import { start, updateView } from '@storybook/react-native';
${registerAddons}
const normalizedStories = [${normalizedStories.join(',')}];
${useJs ? '' : globalTypes}
const annotations = ${annotations};
global.STORIES = normalizedStories;
${useJs ? '' : '// @ts-ignore'}
module?.hot?.accept?.();
${optionsVar}
if (!global.view) {
global.view = start({
annotations,
storyEntries: normalizedStories,
${options}
});
} else {
updateView(global.view, annotations, normalizedStories, ${options});
}
export const view = global.view;
`;
const formattedFileContent = prettier.format(fileContent, { parser: 'babel-ts' });
fs.writeFileSync(storybookRequiresLocation, formattedFileContent, {
encoding: 'utf8',
flag: 'w',
});
}
module.exports = {
generate,
};