@oasisdigital/ng-doc-portal-plugin
Version:
Nx plugin for adding the ng-doc-portal system to your nx workspace
257 lines (256 loc) • 9.27 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.accumulatePayloads = accumulatePayloads;
exports.sortFullPayloadList = sortFullPayloadList;
exports.insertIntoSortedPayloadList = insertIntoSortedPayloadList;
exports.comparePayloadTitles = comparePayloadTitles;
exports.findTitlePrefixFromGlobPatterns = findTitlePrefixFromGlobPatterns;
exports.generateTitleFromFilePath = generateTitleFromFilePath;
exports.getTitleFromTypeScript = getTitleFromTypeScript;
exports.extractTitleFromDocPageFile = extractTitleFromDocPageFile;
exports.generateDocPageLoader = generateDocPageLoader;
exports.formatContent = formatContent;
exports.wrapTypescriptBoilerplate = wrapTypescriptBoilerplate;
exports.convertPatternOrGlobPatternArray = convertPatternOrGlobPatternArray;
exports.timeNow = timeNow;
const tslib_1 = require("tslib");
const tsquery_1 = require("@phenomnomnominal/tsquery");
const date_fns_1 = require("date-fns");
const minimatch_1 = require("minimatch");
const prettier_1 = require("prettier");
const fs_1 = require("fs");
const path_1 = require("path");
/**
* Extract all the payloads from the various processed file events.
*
* @param acc The previous accumulated payloads
* @param curr The current file event
*/
function accumulatePayloads(acc, curr) {
if (curr.type === 'init') {
const list = sortFullPayloadList(curr.payload);
return list;
}
else if (curr.type === 'add') {
return insertIntoSortedPayloadList(acc, {
filePath: curr.filePath,
title: curr.title,
});
}
else if (curr.type === 'unlink') {
return acc.filter((f) => f.filePath !== curr.filePath);
}
else if (curr.type === 'change') {
const index = acc.findIndex((f) => f.filePath === curr.filePath);
if (index < 0) {
return acc;
}
const copy = [...acc];
copy[index] = {
filePath: curr.filePath,
title: curr.title,
};
return copy;
}
// Can't happen, but needed for the compiler
return [];
}
function sortFullPayloadList(list) {
return list.sort(comparePayloadTitles);
}
function insertIntoSortedPayloadList(list, item) {
let index = 0;
let low = 0;
let mid = -1;
let high = list.length;
let c = 0;
while (low < high) {
mid = Math.floor((low + high) / 2);
c = comparePayloadTitles(list[mid], item);
if (c < 0) {
low = mid + 1;
}
else if (c > 0) {
high = mid;
}
else {
index = mid;
break;
}
}
index = low;
list.splice(index, 0, item);
return list;
}
function comparePayloadTitles(a, b) {
if (a.title > b.title) {
return 1;
}
else if (a.title < b.title) {
return -1;
}
else {
return 0;
}
}
function findTitlePrefixFromGlobPatterns(filePath, globPatterns) {
const pattern = globPatterns.find((globPattern) => {
if (typeof globPattern === 'string') {
return (0, minimatch_1.minimatch)(filePath, globPattern);
}
else {
return (0, minimatch_1.minimatch)(filePath, globPattern.pattern);
}
});
if (!pattern || typeof pattern === 'string') {
return undefined;
}
else {
let prefix = pattern.titlePrefix;
// Some quick cleanup just in case folks put `/` characters at start/end of prefix
while (prefix && prefix.endsWith('/')) {
prefix = prefix.slice(0, -1);
}
while (prefix && prefix.startsWith('/')) {
prefix = prefix.slice(1);
}
// ---
return prefix;
}
}
function generateTitleFromFilePath(filePath) {
const baseName = (0, path_1.basename)(filePath);
const fileName = baseName.substring(0, baseName.indexOf('.'));
const words = fileName.split('-');
let title = '';
for (let word of words) {
word = word.charAt(0).toUpperCase() + word.substring(1);
if (title) {
title = `${title} ${word}`;
}
else {
title = word;
}
}
return title.charAt(0).toUpperCase() + title.substring(1);
}
function getTitleFromTypeScript(filePath) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
const rawTS = (0, fs_1.readFileSync)('./' + filePath).toString();
const ast = tsquery_1.tsquery.ast(rawTS);
const defaultExportClassDeclaration = (0, tsquery_1.tsquery)(ast, 'ClassDeclaration:has(ExportKeyword):has(DefaultKeyword)').at(0);
if (defaultExportClassDeclaration) {
// generate title dynamically
// TODO: Add folder structure to title generated here
// Should be based off whatever glob picked up this file
return generateTitleFromFilePath(filePath);
}
else {
// Find ExportAssignment in the TS file
const exportAssignment = (0, tsquery_1.tsquery)(ast, 'ExportAssignment').at(0);
if (exportAssignment) {
// There are two paths on this front
// Either there is an in-line ObjectLiteral
// Or there is an identifier that points to a VariableDeclaration
// with the ObjectLiteral
let objectLiteralExpression = (0, tsquery_1.tsquery)(exportAssignment, 'ObjectLiteralExpression').at(0);
if (!objectLiteralExpression) {
const identifier = (0, tsquery_1.tsquery)(exportAssignment, 'Identifier').at(0);
objectLiteralExpression = (0, tsquery_1.tsquery)(ast, `VariableDeclaration:has(Identifier[name="${identifier === null || identifier === void 0 ? void 0 : identifier.getText(ast)}"]) > ObjectLiteralExpression`).at(0);
}
if (objectLiteralExpression) {
// Once the ObjectLiteral is found
// Find the `title` property's string value
const title = (_a = (0, tsquery_1.tsquery)(objectLiteralExpression, 'PropertyAssignment:has(Identifier[name="title"]) > StringLiteral')
.at(0)) === null || _a === void 0 ? void 0 : _a.getText(ast);
if (title) {
// For some reason `.getText()` returns the quotes of the string
return title.replace(/'/g, '');
}
else {
throw new Error(`No property found for 'title' in exported object literal for file: ${filePath}`);
}
}
else {
throw new Error(`No object literal export found for file: ${filePath}`);
}
}
else {
throw new Error(`No exports found for file: ${filePath}`);
}
}
});
}
/**
* Extract the title from the doc page file's config
*
* @param filePath The location of the file. Both the filename and the
* contents of the file will be used to extract title from the config in the file
*/
function extractTitleFromDocPageFile(filePath, globPatterns) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const title = yield getTitleFromTypeScript(filePath);
const prefix = findTitlePrefixFromGlobPatterns(filePath, globPatterns);
if (prefix) {
return `${prefix}/${title}`;
}
else {
return title;
}
});
}
/**
* Generate the doc page loader from the filePath and the title.
*
* @param filePath The original filePath (with '.ts')
* @param title The title for the file
*/
function generateDocPageLoader(filePath, title) {
// Figure out variables for config list file output
const filePathWithoutExtension = filePath.replace('.ts', '');
const route = title.toLowerCase().replace(/[ /]/g, '-');
return `
'${route}': {
title: '${title}',
fetch: () => import('../../../../${filePathWithoutExtension}').then((file) => file.default)
}
`;
}
/**
* Prettier formats any file content string passed in
*
* @param content The file content to be prettified
*/
function formatContent(content) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
return (0, prettier_1.format)(content, {
parser: 'typescript',
printWidth: 100,
singleQuote: true,
});
});
}
/**
* Generate the text of formatted TypeScript file around the config strings.
*
* @param configStrings The config strings generated from our path files
*/
function wrapTypescriptBoilerplate(configStrings) {
return `
/* eslint-disable */
import { DocPageLoaderRecord } from '@oasisdigital/ng-doc-portal';
export const docPageLoaders: DocPageLoaderRecord = {
${configStrings.toString()}
};
`;
}
function convertPatternOrGlobPatternArray(patterns) {
return patterns.map((strOrGlobPattern) => typeof strOrGlobPattern === 'string'
? strOrGlobPattern
: strOrGlobPattern.pattern);
}
function timeNow() {
return (0, date_fns_1.format)(new Date(), 'HH:mm:ss:SSS');
}
//# sourceMappingURL=util.js.map