@omnia/tooling-vue
Version:
Used to bundle and serve manifests web component that build on Vue framework.
425 lines (424 loc) • 20.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const fs = require('fs');
const shared_1 = require("../shared");
const $ = tslib_1.__importStar(require("../variables"));
let relativeOutDir = "client/tooling/vue/docs";
if ($.isExtensionEnv) {
relativeOutDir = "node_modules/@omnia/tooling-vue/internal-do-not-import-from-here/docs";
}
let outDir = $.tooling.utils.root(relativeOutDir);
let extensionEnvironment = {
paths: {
composorImportPath: $.isExtensionEnv ? '@omnia/tooling-composers' : '../../../tooling/composers',
topicImportPath: $.isExtensionEnv ? '@omnia/fx-models' : '../../../fx/models',
messageBusTopicMediatorImportPath: $.isExtensionEnv ? '@omnia/fx' : '../../../fx'
},
outPutPaths: {
folder: outDir + "/",
rawFile: outDir + '/docs.json',
manifest: outDir + '/docs.manifest.ts',
navRegistration: outDir + '/nav.ts'
}
};
$.tooling.core.registerBuildTask({
stage: $.tooling.core.TaskStage.AfterScanManifests,
order: 1,
task: function () {
return generateDocManifest();
}
});
function generateDocManifest() {
return new Promise(function (resolve, reject) {
resolve();
// documentalist package jave issue with security
// so we will find another solution in omnia 7.
//let enableDocs = $.composers.DevelopmentBuildConfiguration.isEnableDocumentation;
//if (enableDocs !== true && process.argv.length > 0) {
// enableDocs = process.argv.find(argv => argv === "--docs") !== undefined;
//}
//if (enableDocs !== true) {
// resolve();
//}
//else {
// $.tooling.log('Generating documentation manifest', $.tooling.LogTypes.HeadLine);
// let startTime = new Date().getTime();
// //ensure folder
// if (!fs.existsSync(outDir)) {
// fs.mkdirSync(outDir);
// }
// else {
// // cleanup exist docs
// $.del.sync([outDir + '/**', '!' + outDir]);
// }
// let componentRegistrations = $.composers.ComponentRegistry.getComponentRegistrations();
// let docs = extractDocPathForComponents(componentRegistrations);
// $.tooling.logTime(`Found [${docs.componentsDocCount}] component(s) have documentation`, startTime);
// if (docs.paths.length > 0) {
// generate(docs.paths).then(() => {
// $.tooling.logTime('Done - Generating documentation manifest', startTime);
// resolve();
// }, reject);
// }
// else {
// $.tooling.logTime('Done - Generating documentation manifest', startTime);
// resolve();
// }
//}
});
}
function generate(paths) {
return new Promise(function (resolve, reject) {
const { Documentalist, TypescriptPlugin } = require("documentalist");
new Documentalist()
.use(/\.ts?$/, new TypescriptPlugin())
.documentGlobs(...paths) // ← async operation, returns a Promise
.then(docs => {
//console.log("ahihi", docs.typescript);
var rootModel = docs.typescript;
var filterFilesPath = filterInterfaceFilePaths(rootModel, paths);
var elementInterfaces = getWebComponentAndMainInterface(Object.keys(filterFilesPath));
var fxDocs = builtFxDocs(rootModel, elementInterfaces);
writeFile(extensionEnvironment.outPutPaths.rawFile, JSON.stringify(fxDocs, null, 2)); //For debugging purpose
writeDocsManifest(extensionEnvironment.outPutPaths.manifest, extensionEnvironment.paths.composorImportPath, fxDocs);
writeNavRegistrion(extensionEnvironment.outPutPaths.navRegistration, extensionEnvironment.paths.topicImportPath, extensionEnvironment.paths.messageBusTopicMediatorImportPath, fxDocs);
writeDocsRegistration(extensionEnvironment.outPutPaths.folder, extensionEnvironment.paths.topicImportPath, extensionEnvironment.paths.messageBusTopicMediatorImportPath, fxDocs);
let docManifestRelativePath = relativeOutDir + "/docs.manifest.ts";
let docManifestAbsolutePath = $.tooling.utils.root(docManifestRelativePath);
// register docs manifest
if ($.fs.existsSync(docManifestAbsolutePath)) {
try {
$.composers.ManifestRegistry.setCurrentManifestPath(docManifestRelativePath);
require(docManifestAbsolutePath);
$.composers.ManifestRegistry.setCurrentManifestPath();
delete require.cache[docManifestAbsolutePath];
}
catch (ex) {
console.dir(ex.stack);
reject();
}
}
resolve();
}, reject);
});
}
function getSamples(interfaceFilePath) {
var elementNameReg = /elementName:( )*['"][^'"]+['"]/g; //Only @Prop has define default value
var entryPointReg = /entryPoint:( )*['"][^'"]+['"]/g;
var samples = [];
var interfaceSegments = interfaceFilePath.split('\\');
interfaceSegments.splice(-1, 1);
var folderPath = interfaceSegments.join('\\') + '\\samples';
var samplesManifests = getAllFilesInFolderRecursively(folderPath);
for (var sampleManifest of samplesManifests) {
var content = readFile(sampleManifest.filePath);
var elemNameMatches = content.match(elementNameReg);
var entryPointMatches = content.match(entryPointReg);
if (elemNameMatches && entryPointMatches) {
for (var i = 0; i < entryPointMatches.length; i++) {
var elemNameMatch = elemNameMatches[i];
var entryPointMatch = entryPointMatches[i];
var sampleElemDefinition = elemNameMatch.split(':').pop();
sampleElemDefinition = sampleElemDefinition.trim();
var sampleElem = sampleElemDefinition.substr(1, sampleElemDefinition.length - 2);
var entryPointDefinition = entryPointMatch.split(':').pop();
entryPointDefinition = entryPointDefinition.trim();
var entryPoint = entryPointDefinition.substr(1, entryPointDefinition.length - 2);
entryPoint = entryPoint.replace('./', '').replace('.jsx', '.tsx').split('/').join('\\');
var sampleTsxFilePath = sampleManifest.dirPath + '\\' + entryPoint;
var sampleTsxFileContent = readFile(sampleTsxFilePath);
sampleTsxFileContent = sampleTsxFileContent.replace(new RegExp('\\r\\n', 'g'), '\\\\r\\\\n');
//console.log(sampleTsxFileContent);
samples.push({ elem: sampleElem, content: sampleTsxFileContent });
}
}
}
return samples;
}
function writeDocsRegistration(outputFolder, topicImportPath, messageBusTopicMediatorImportPath, fxDocs) {
for (var elem of Object.keys(fxDocs)) {
var content = '';
var docsRegistrationMsg = generateDocsRegistrationMsg(fxDocs, elem);
var json = JSON.stringify(docsRegistrationMsg)
.replace(new RegExp('`', 'g'), '\\`');
json = json
.replace(new RegExp('\\\\\\\\\\\\`', 'g'), '\\\\\\\\\\`');
json = json
.replace(new RegExp('\\\\"', 'g'), '\\\\"');
content += `import { Topic } from "${topicImportPath}";\r\n`;
content += `import { MessageBusTopicMediator } from '${messageBusTopicMediatorImportPath}';\r\n`;
content += `const topic: Topic<string> = {namespace: "omfx.docs",name: "docs"};\r\n`;
content += `const registerNav = new MessageBusTopicMediator<any>(topic, { caching: { size: Number.MAX_SAFE_INTEGER} });\r\n`;
content += 'registerNav.publish(JSON.parse(`' + json + '`))';
writeFile(outputFolder + elem + '.ts', content);
}
}
function writeDocsManifest(path, composorImportPath, fxDocs) {
var content = '';
content += `import { Composer } from "${composorImportPath}";\r\n`;
content += '\r\n';
content += `Composer.registerManifest("${$.tooling.utils.generateGuid()}", "fxdocs")\r\n`;
content += ` .registerResources({resourcePaths:['./nav.ts']})\r\n`;
content += ` .withLoadRules().loadIfManifestLoaded({omniaServiceId:'da059968-e431-48b5-a865-d33d0fa29c9d', resourceId:'052f0298-1dc7-4d0c-b4b9-3c8497ca08f5'})\r\n`;
content += '\r\n';
for (var elem of Object.keys(fxDocs)) {
content += '\r\n';
content += `Composer.registerManifest("${$.tooling.utils.generateGuid()}", "${elem}")\r\n`;
content += ` .registerResources({resourcePaths:['./${elem}.ts']})\r\n`;
content += ` .withLoadRules().loadIfManifestLoaded({omniaServiceId:'da059968-e431-48b5-a865-d33d0fa29c9d', resourceId:'052f0298-1dc7-4d0c-b4b9-3c8497ca08f5'})\r\n`;
content += ` .and().loadByDomMatching({ cssSelector: "omfx-docs-resource[source='${elem}']" });\r\n`;
content += '\r\n';
}
writeFile(path, content);
}
function writeNavRegistrion(path, topicImportPath, messageBusTopicMediatorImportPath, fxDocs) {
var content = '';
var navRegistrationMsg = getNavRegistrationMsg(fxDocs);
content += `import { Topic } from "${topicImportPath}";\r\n`;
content += `import { MessageBusTopicMediator } from '${messageBusTopicMediatorImportPath}';\r\n`;
content += `const topic: Topic<string> = {namespace: "omfx.docs",name: "nav"};\r\n`;
content += `const registerNav = new MessageBusTopicMediator<any>(topic, { caching: { size: Number.MAX_SAFE_INTEGER} });\r\n`;
content += 'registerNav.publish(JSON.parse(`' + JSON.stringify(navRegistrationMsg) + '`))';
writeFile(path, content);
}
function generateDocsRegistrationMsg(fxDocs, elem) {
var props = [];
var elemDocumentation = elem;
if (fxDocs[elem] && fxDocs[elem].documentation && fxDocs[elem].documentation.contentsRaw) {
elemDocumentation = fxDocs[elem].documentation.contentsRaw;
}
var elemName = elemDocumentation.split('-')[0];
var elemDescription = elemDocumentation.split('-')[1] || '';
if (fxDocs[elem].props) {
for (var prop of Object.keys(fxDocs[elem].props)) {
var propObj = fxDocs[elem].props[prop];
var description = '';
if (propObj.documentation && propObj.documentation.contentsRaw) {
description = propObj.documentation.contentsRaw;
if (description && description.indexOf('\"') >= 0) {
description = description.replace(new RegExp('\\"', 'g'), '\\\"');
}
}
var defaultValue = propObj.defaultValue;
if (defaultValue && defaultValue.indexOf('\"') >= 0) {
defaultValue = defaultValue.replace(new RegExp('\\"', 'g'), '\\\"');
}
props.push({ name: prop, type: propObj.type, description: description, defaultValue: defaultValue });
}
}
return { elem: elem, name: elemName, description: elemDescription, props: props, sampleElems: fxDocs[elem].samples };
}
function getNavRegistrationMsg(fxDocs) {
var componentNodes = [];
for (var elem of Object.keys(fxDocs)) {
var name = elem;
if (fxDocs[elem] && fxDocs[elem].documentation && fxDocs[elem].documentation.contentsRaw) {
name = fxDocs[elem].documentation.contentsRaw.split('-')[0].trim();
}
componentNodes.push({ name: name, elem: elem });
}
return { extension: $.composers.ServiceManifestRegistry.getServiceInfo().title || $.composers.ServiceManifestRegistry.getServiceInfo().id, componentNodes };
}
function builtFxDocs(rootModel, elementInterfaces) {
var fxDocs = {};
let componentRegistrations = $.composers.ComponentRegistry.getComponentRegistrations();
for (var element in elementInterfaces) {
console.log('process for', element);
var elementDoc = {};
var elementInfo = elementInterfaces[element];
var rootNode = rootModel[elementInfo.interface];
elementDoc.documentation = rootNode.documentation;
var props = {};
getComponentProperties(rootModel, elementInfo.interface, props);
let componentRegistration = componentRegistrations.find(c => c.componentOptions.elementName === element);
if (componentRegistration) {
let componentPath = (0, shared_1.convertManifestPathToEntryPath)(componentRegistration.manifestPath, [componentRegistration.componentOptions.entryPoint])[0];
getComponentPropertiesDefaultValue(componentPath, props);
}
elementDoc.props = props;
var samples = getSamples(elementInfo.interfaceFilePath);
elementDoc.samples = samples;
fxDocs[element] = elementDoc;
}
return fxDocs;
}
function getComponentPropertiesDefaultValue(componentPath, props) {
//var folderPath = interfaceFilePath.substring(0, interfaceFilePath.lastIndexOf('\\') + 1);
//var interfaceFileName = interfaceFilePath.substring(folderPath.length);
//var implementationFileName = interfaceFileName.substring(1) + 'x'; // IName.ts => Name.tsx
//var implementationPath = folderPath + implementationFileName;
var fileContent = readFile(componentPath);
var reg = /@Prop\(\{[^\)d]+(default)[^\)]+\)[a-zA-Z0-9?_ ]+:/g; //Only @Prop has define default value
var regResults = fileContent.match(reg);
if (regResults) {
for (var regResultContent of regResults) {
var propertyName = getPropertyNameFromPropDecorator(regResultContent);
var defaultValue = getDefaultValueFromPropDecorator(regResultContent);
if (propertyName && props[propertyName]) {
props[propertyName].defaultValue = defaultValue;
}
}
}
}
function getDefaultValueFromPropDecorator(propDecorator) {
//Since default value is complex, so we cannot use regex to get it
var defaultValue = '';
var startIndex = propDecorator.indexOf("default") + "default".length;
var regularValueReg = /[a-zA-Z0-9_.]/;
var scope = 0;
let start = false;
let enteredScope = false;
let enteredScopeKind = "";
var beforeCharacter = '';
var character = '';
for (var index = startIndex; index < propDecorator.length; index++) {
beforeCharacter = character;
character = propDecorator[index];
if (start) {
//IF the first default value character is not a object begin ({...), then we mark a flag to stop by ending at a normal text
if (!defaultValue.trim() && (character === "{" || character === "[" || character === "'" || character === '"')) {
enteredScope = true;
}
defaultValue += character;
if (enteredScope && character.trim()) {
if (character === "{" && (!enteredScopeKind || enteredScopeKind === "{")) {
enteredScopeKind = "{";
scope++;
}
else if (character === "}" && enteredScopeKind === "{") {
scope--;
if (scope === 0)
break;
}
else if (character === "[" && (!enteredScopeKind || enteredScopeKind === "[")) {
enteredScopeKind = "[";
scope++;
}
else if (character === "]" && enteredScopeKind === "]") {
scope--;
if (scope === 0)
break;
}
else if (character === "'" && !enteredScopeKind) {
enteredScopeKind = "'";
}
else if (character === "'" && enteredScopeKind === "'" && beforeCharacter !== '\\') {
break;
}
else if (character === '"' && !enteredScopeKind) {
enteredScopeKind = '"';
}
else if (character === '"' && enteredScopeKind === '"' && beforeCharacter !== '\\') {
break;
}
}
if (!enteredScope && defaultValue.trim() && character && !regularValueReg.test(character))
break;
}
if (character === ":")
start = true;
}
return defaultValue.trim();
}
function getPropertyNameFromPropDecorator(propDecorator) {
propDecorator = propDecorator.substring(propDecorator.lastIndexOf(')') + 1);
propDecorator = propDecorator.substring(0, propDecorator.lastIndexOf(':'));
var name = propDecorator.trim();
name = name.replace("?", ""); //remove optional in name
return name;
}
function getComponentProperties(rootModel, key, props) {
var model = rootModel[key];
var properties = model.properties;
for (var property of properties) {
props[property.name] = {
documentation: property.documentation,
type: property.type || 'any'
};
}
if (model.extends) {
for (var extend of model.extends) {
if (extend !== 'any') {
getComponentProperties(rootModel, extend, props);
}
}
}
}
function getWebComponentAndMainInterface(interfacePaths) {
var result = {};
var infoReg = /\/\*@WebComponentInterface\([^\)]+\)\*\/[ \n\r]+export[ ]+interface[ ]+[^ ]+/m;
var elementReg = /\([^\)]+\)/m;
for (var path of interfacePaths) {
var fileContent = readFile(path);
var infoRegResult = infoReg.exec(fileContent);
if (infoRegResult) {
var infoRegResultContent = infoRegResult[0];
var elementRegResult = elementReg.exec(infoRegResultContent);
var elementRegResultContent = elementRegResult[0];
var element = elementRegResultContent.substring(2, elementRegResultContent.length - 2);
var interfaceName = infoRegResultContent.substring(infoRegResultContent.lastIndexOf(' ') + 1);
result[element] = {
interface: interfaceName,
interfaceFilePath: path
};
}
}
return result;
}
function filterInterfaceFilePaths(model, scanPaths) {
var filesPath = {};
for (var key in model) {
let filePath = model[key].fileName;
if (filePath) {
filePath = filePath.replace(/\\/g, "/");
if (scanPaths.find(path => path.indexOf(filePath) > -1) !== undefined) {
filesPath[filePath] = true;
}
}
}
return filesPath;
}
//function getFiles(filepath) {
// return fs.readdirSync(filepath).filter(function (file) {
// return fs.statSync($.path.join(filepath, file)).isFile();
// });
//}
function writeFile(filepath, content) {
fs.writeFileSync(filepath, content);
}
function readFile(filePath) {
return fs.readFileSync(filePath, 'utf-8');
}
function getAllFilesInFolderRecursively(dirPath) {
var files = [];
if (fs.existsSync(dirPath)) {
var paths = fs.readdirSync(dirPath).map(function (file) { return { dirPath: dirPath, filePath: dirPath + '\\' + file }; });
files = paths.filter(function (path) {
return fs.statSync(path.filePath).isFile() && path.filePath.indexOf('.manifest.ts') >= 0;
});
var folders = paths.filter(function (path) {
return fs.statSync(path.filePath).isFile() === false;
});
for (var path of folders) {
files = files.concat(getAllFilesInFolderRecursively(path.filePath));
}
}
return files;
}
;
function extractDocPathForComponents(componentRegistrations) {
let componentsDocCount = 0;
let paths = [];
componentRegistrations.forEach((comp) => {
let defPaths = comp.componentOptions.documentations;
if (defPaths) {
componentsDocCount++;
defPaths.forEach((defPath) => {
paths.push((0, shared_1.convertManifestPathToEntryPath)(comp.manifestPath, [defPath])[0]);
//paths.push($.tooling.utils.root(convertManifestPathToEntryPath(comp.manifestPath, [defPath])[0]));
});
}
});
return { componentsDocCount, paths };
}