UNPKG

react-docgen-typescript-loader

Version:

Webpack loader to generate docgen information from TypeScript React components.

194 lines 8.04 kB
"use strict"; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spread = (this && this.__spread) || function () { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var ts = __importStar(require("typescript")); var path_1 = __importDefault(require("path")); var fs_1 = __importDefault(require("fs")); // TODO: Import from "react-docgen-typescript" directly when // https://github.com/styleguidist/react-docgen-typescript/pull/104 is hopefully // merged in. Will be considering to make a peer dependency as that point. var parser_js_1 = require("react-docgen-typescript/lib/parser.js"); var validateOptions_1 = __importDefault(require("./validateOptions")); var generateDocgenCodeBlock_1 = __importDefault(require("./generateDocgenCodeBlock")); var loader_utils_1 = require("loader-utils"); var languageService = null; var files = new Map(); function loader(source) { // Loaders can operate in either synchronous or asynchronous mode. Errors in // asynchronous mode should be reported using the supplied callback. // Will return a callback if operating in asynchronous mode. var callback = this.async(); try { var newSource = processResource(this, source); if (!callback) return newSource; callback(null, newSource); return; } catch (e) { if (callback) { callback(e); return; } throw e; } } exports.default = loader; function processResource(context, source) { // Mark the loader as being cacheable since the result should be // deterministic. context.cacheable(true); var options = Object.assign({}, loader_utils_1.getOptions(context)); validateOptions_1.default(options); options.docgenCollectionName = options.docgenCollectionName || "STORYBOOK_REACT_CLASSES"; if (typeof options.setDisplayName !== "boolean") { options.setDisplayName = true; } // Convert the loader's flat options into the expected structure for // react-docgen-typescript. // See: node_modules/react-docgen-typescript/lib/parser.d.ts var parserOptions = { componentNameResolver: options.componentNameResolver, propFilter: options.skipPropsWithName || options.skipPropsWithoutDoc ? { skipPropsWithName: options.skipPropsWithName || undefined, skipPropsWithoutDoc: options.skipPropsWithoutDoc || undefined, } : options.propFilter, shouldExtractLiteralValuesFromEnum: options.shouldExtractLiteralValuesFromEnum, savePropValueAsString: options.savePropValueAsString, }; // Configure parser using settings provided to loader. // See: node_modules/react-docgen-typescript/lib/parser.d.ts var parser = parser_js_1.withDefaultConfig(parserOptions); var compilerOptions = { allowJs: true, }; var tsConfigFile = null; if (options.tsconfigPath) { parser = parser_js_1.withCustomConfig(options.tsconfigPath, parserOptions); tsConfigFile = getTSConfigFile(options.tsconfigPath); compilerOptions = tsConfigFile.options; var filesToLoad = tsConfigFile.fileNames; loadFiles(filesToLoad); } else if (options.compilerOptions) { parser = parser_js_1.withCompilerOptions(options.compilerOptions, parserOptions); compilerOptions = options.compilerOptions; } if (!tsConfigFile) { var basePath = path_1.default.dirname(context.context); tsConfigFile = getDefaultTSConfigFile(basePath); var filesToLoad = tsConfigFile.fileNames; loadFiles(filesToLoad); } var componentDocs = parser.parseWithProgramProvider(context.resourcePath, function () { if (languageService) { return languageService.getProgram(); } var servicesHost = createServiceHost(compilerOptions, files); languageService = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()); return languageService.getProgram(); }); options.typePropName = options.typePropName || "type"; // Return amended source code if there is docgen information available. if (componentDocs.length) { return generateDocgenCodeBlock_1.default({ filename: context.resourcePath, source: source, componentDocs: componentDocs, docgenCollectionName: options.docgenCollectionName, setDisplayName: options.setDisplayName, typePropName: options.typePropName, }); } // Return unchanged source code if no docgen information was available. return source; } function getTSConfigFile(tsconfigPath) { var basePath = path_1.default.dirname(tsconfigPath); var configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile); return ts.parseJsonConfigFileContent(configFile.config, ts.sys, basePath, {}, tsconfigPath); } function getDefaultTSConfigFile(basePath) { return ts.parseJsonConfigFileContent({}, ts.sys, basePath, {}); } function loadFiles(filesToLoad) { filesToLoad.forEach(function (filePath) { var normalizedFilePath = path_1.default.normalize(filePath); var file = files.get(normalizedFilePath); var text = fs_1.default.readFileSync(normalizedFilePath, "utf-8"); if (!file) { files.set(normalizedFilePath, { text: text, version: 0, }); } else if (file.text !== text) { files.set(normalizedFilePath, { text: text, version: file.version + 1, }); } }); } function createServiceHost(compilerOptions, files) { return { getScriptFileNames: function () { return __spread(files.keys()); }, getScriptVersion: function (fileName) { var file = files.get(fileName); return (file && file.version.toString()) || ""; }, getScriptSnapshot: function (fileName) { if (!fs_1.default.existsSync(fileName)) { return undefined; } var file = files.get(fileName); if (file === undefined) { var text = fs_1.default.readFileSync(fileName).toString(); file = { version: 0, text: text }; files.set(fileName, file); } return ts.ScriptSnapshot.fromString(file.text); }, getCurrentDirectory: function () { return process.cwd(); }, getCompilationSettings: function () { return compilerOptions; }, getDefaultLibFileName: function (options) { return ts.getDefaultLibFilePath(options); }, fileExists: ts.sys.fileExists, readFile: ts.sys.readFile, readDirectory: ts.sys.readDirectory, }; } //# sourceMappingURL=loader.js.map