react-docgen-typescript-loader
Version:
Webpack loader to generate docgen information from TypeScript React components.
194 lines • 8.04 kB
JavaScript
;
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