@storybook/react-native
Version:
A better way to develop React Native Components for your app
160 lines (123 loc) • 3.65 kB
JavaScript
const {
toRequireContext,
ensureRelativePathHasDot,
getMain,
getPreviewExists,
resolveAddonFile,
getAddonName,
} = require('./common');
const { normalizeStories, globToRegexp } = require('storybook/internal/common');
const fs = require('fs');
const path = require('path');
const cwd = process.cwd();
function generate({ configPath, /* absolute = false, */ useJs = false, docTools = true }) {
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}
),
}`;
});
const registeredAddons = [];
for (const addon of main.addons) {
const registerPath = resolveAddonFile(
getAddonName(addon),
'register',
['js', 'mjs', 'jsx', 'ts', 'tsx'],
configPath
);
if (registerPath) {
registeredAddons.push(`import "${registerPath}";`);
}
}
const docToolsAnnotation = 'require("@storybook/react-native/preview")';
const enhancers = [];
if (docTools) {
enhancers.push(docToolsAnnotation);
}
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, null, 4)}`;
options = 'options';
}
const previewExists = getPreviewExists({ configPath });
if (previewExists) {
enhancers.unshift("require('./preview')");
}
const annotations = `[
${enhancers.join(',\n ')}
]`;
const globalTypes = `
declare global {
var view: View;
var STORIES: typeof normalizedStories;
}
`;
const fileContent = `/* do not change this file, it is auto generated by storybook. */
import { start, updateView${useJs ? '' : ', View'} } from '@storybook/react-native';
${registeredAddons.join('\n')}
const normalizedStories = [
${normalizedStories.join(',\n')}
];
${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 ? ` ${options},` : ''}
});
} else {
updateView(global.view, annotations, normalizedStories${options ? `, ${options}` : ''});
}
export const view${useJs ? '' : ': View'} = global.view;
`;
fs.writeFileSync(storybookRequiresLocation, fileContent, {
encoding: 'utf8',
flag: 'w',
});
}
module.exports = {
generate,
};