UNPKG

@omnia/tooling-vue

Version:

Used to bundle and serve manifests web component that build on Vue framework.

425 lines (424 loc) 20.4 kB
'use strict'; 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 }; }