UNPKG

igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

266 lines (265 loc) • 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.stringifyAttributes = exports.makeNgIf = exports.serializeNodes = exports.flatten = exports.getSourceOffset = exports.getAttribute = exports.hasAttribute = exports.findElementNodes = exports.parseFile = exports.FileChange = exports.tryUninstallPackage = exports.tryInstallPackage = exports.getPackageVersion = exports.canResolvePackage = exports.getPackageManager = exports.supports = exports.replaceMatch = exports.escapeRegExp = exports.getProjects = exports.getWorkspace = exports.getWorkspacePath = exports.getProjectPaths = void 0; const core_1 = require("@angular-devkit/core"); const path = require("path"); const child_process_1 = require("child_process"); const configPaths = ['/.angular.json', '/angular.json']; const getProjectPaths = (config) => { const sourceDirs = []; const projects = (0, exports.getProjects)(config); for (const proj of projects) { const sourcePath = path.join('/', proj.sourceRoot); sourceDirs.push((0, core_1.normalize)(sourcePath)); } return sourceDirs; }; exports.getProjectPaths = getProjectPaths; const getWorkspacePath = (host) => configPaths.find(x => host.exists(x)); exports.getWorkspacePath = getWorkspacePath; const getWorkspace = (host) => { const configPath = (0, exports.getWorkspacePath)(host); if (configPath) { return JSON.parse(host.read(configPath).toString()); } return null; }; exports.getWorkspace = getWorkspace; const getProjects = (config) => { const projects = []; for (const projName of Object.keys(config.projects)) { const proj = config.projects[projName]; if ((proj.architect && proj.architect.e2e && !proj.architect.build)) { // skip old style e2e-only projects continue; } projects.push(proj); } return projects; }; exports.getProjects = getProjects; const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string exports.escapeRegExp = escapeRegExp; const replaceMatch = (content, toReplace, replaceWith, index) => content.substring(0, index) + replaceWith + content.substring(index + toReplace.length, content.length); exports.replaceMatch = replaceMatch; const supports = (name) => { try { (0, child_process_1.execSync)(`${name} --version`, { stdio: 'ignore' }); return true; } catch (_a) { return false; } }; exports.supports = supports; const getPackageManager = (host) => { const hasYarn = (0, exports.supports)('yarn'); const hasYarnLock = host.exists('yarn.lock'); if (hasYarn && hasYarnLock) { return 'yarn'; } return 'npm'; }; exports.getPackageManager = getPackageManager; const canResolvePackage = (pkg) => { try { // attempt resolve in child process to keep result out of package.json cache // otherwise resolve will not read the json again (after install) and won't load the main correctly // https://stackoverflow.com/questions/59865584/how-to-invalidate-cached-require-resolve-results (0, child_process_1.execSync)(`node -e "require.resolve('${pkg}');"`, { stdio: 'ignore' }); return true; } catch (_a) { return false; } }; exports.canResolvePackage = canResolvePackage; const getPackageVersion = (pkg) => { var _a; let version = null; try { version = (_a = require(path.posix.join(pkg, 'package.json'))) === null || _a === void 0 ? void 0 : _a.version; } catch (_b) { return version; } return version; }; exports.getPackageVersion = getPackageVersion; const tryInstallPackage = (context, packageManager, pkg) => { try { context.logger.debug(`Installing ${pkg} via ${packageManager}.`); switch (packageManager) { case 'yarn': (0, child_process_1.execSync)(`${packageManager} add ${pkg}`, { stdio: 'ignore' }); break; case 'npm': (0, child_process_1.execSync)(`${packageManager} i ${pkg} --no-save --no-audit`, { stdio: 'ignore' }); break; } context.logger.debug(`${pkg} installed successfully.`); } catch (e) { context.logger.warn(`Could not install ${pkg}.`, e); } }; exports.tryInstallPackage = tryInstallPackage; const tryUninstallPackage = (context, packageManager, pkg) => { try { context.logger.debug(`Uninstalling ${pkg} via ${packageManager}`); switch (packageManager) { case 'yarn': (0, child_process_1.execSync)(`${packageManager} remove ${pkg}`, { stdio: 'ignore' }); break; case 'npm': (0, child_process_1.execSync)(`${packageManager} uninstall ${pkg} --no-save`, { stdio: 'ignore' }); break; } context.logger.debug(`${pkg} uninstalled successfully.`); } catch (e) { context.logger .warn(`Could not uninstall ${pkg}, you may want to uninstall it manually.`, e); } }; exports.tryUninstallPackage = tryUninstallPackage; class FileChange { constructor(position = 0, text = '', replaceText = '', type = 'insert') { this.position = position; this.text = text; this.replaceText = replaceText; this.type = type; } apply(content) { if (this.type === 'insert') { return `${content.substring(0, this.position)}${this.text}${content.substring(this.position)}`; } return (0, exports.replaceMatch)(content, this.replaceText, this.text, this.position); } } exports.FileChange = FileChange; /** * Parses an Angular template file/content and returns an array of the root nodes of the file. * TODO: Maybe make async and dynamically import the HtmlParser * @param host * @param filePath * @param encoding */ const parseFile = (parser, host, filePath, encoding = 'utf8') => parser.parse(host.read(filePath).toString(encoding), filePath).rootNodes; exports.parseFile = parseFile; // export const parseFile = async (host: Tree, filePath: string, encoding = 'utf8') => { // const { HtmlParser } = await import('@angular/compiler') // return new HtmlParser().parse(host.read(filePath).toString(encoding), filePath).rootNodes; // } const findElementNodes = (root, tag) => { const tags = new Set(Array.isArray(tag) ? tag : [tag]); return (0, exports.flatten)(Array.isArray(root) ? root : [root]) .filter((node) => tags.has(node.name)); }; exports.findElementNodes = findElementNodes; const hasAttribute = (root, attribute) => { const attrs = Array.isArray(attribute) ? attribute : [attribute]; return !!root.attrs.find(a => attrs.includes(a.name)); }; exports.hasAttribute = hasAttribute; const getAttribute = (root, attribute) => { const attrs = Array.isArray(attribute) ? attribute : [attribute]; return root.attrs.filter(a => attrs.includes(a.name)); }; exports.getAttribute = getAttribute; const getSourceOffset = (element) => { const { startSourceSpan, endSourceSpan } = element; return { startTag: { start: startSourceSpan.start.offset, end: startSourceSpan.end.offset }, // V.S. May 11th, 2021: Tag could be self-closing endTag: { start: endSourceSpan === null || endSourceSpan === void 0 ? void 0 : endSourceSpan.start.offset, end: endSourceSpan === null || endSourceSpan === void 0 ? void 0 : endSourceSpan.end.offset }, file: { content: startSourceSpan.start.file.content, url: startSourceSpan.start.file.url }, node: element }; }; exports.getSourceOffset = getSourceOffset; const isElement = (node) => node.children !== undefined; /** * Given an array of `Node` objects, flattens the ast tree to a single array. * De facto only `Element` type objects have children. * * @param list */ const flatten = (list) => { let r = []; for (const node of list) { r.push(node); if (isElement(node)) { r = r.concat((0, exports.flatten)(node.children)); } } return r; }; exports.flatten = flatten; /** * https://github.com/angular/angular/blob/master/packages/compiler/test/ml_parser/util/util.ts * * May be useful for validating the output of our own migrations, */ class SerializerVisitor { /** * */ constructor(getHtmlTagDefinition) { this.getHtmlTagDefinition = getHtmlTagDefinition; } visitElement(element, _context) { if (this.getHtmlTagDefinition(element.name).isVoid) { return `<${element.name}${this._visitAll(element.attrs, ' ', ' ')}/>`; } return `<${element.name}${this._visitAll(element.attrs, ' ', ' ')}>${this._visitAll(element.children)}</${element.name}>`; } visitAttribute(attribute, _context) { return attribute.value === '' ? `${attribute.name}` : `${attribute.name}="${attribute.value}"`; } visitText(text, _context) { return text.value; } visitComment(comment, _context) { return `<!--${comment.value}-->`; } visitExpansion(expansion, _context) { return `{${expansion.switchValue}, ${expansion.type},${this._visitAll(expansion.cases)}}`; } visitExpansionCase(expansionCase, _context) { return ` ${expansionCase.value} {${this._visitAll(expansionCase.expression)}}`; } visitBlock(block, _context) { const params = block.parameters.length === 0 ? ' ' : ` (${this._visitAll(block.parameters, ';', ' ')}) `; return `@${block.name}${params}{${this._visitAll(block.children)}}`; } visitBlockParameter(parameter, _context) { return parameter.expression; } visitLetDeclaration(decl, _context) { return decl; } _visitAll(nodes, separator = '', prefix = '') { return nodes.length > 0 ? prefix + nodes.map(a => a.visit(this, null)).join(separator) : ''; } } const serializeNodes = (nodes, getHtmlTagDefinition) => { return nodes.map(node => node.visit(new SerializerVisitor(getHtmlTagDefinition), null)); }; exports.serializeNodes = serializeNodes; const makeNgIf = (name, value) => name.startsWith('[') && value !== 'true'; exports.makeNgIf = makeNgIf; const stringifyAttributes = (attributes) => { let stringAttributes = ''; attributes.forEach(element => { // eslint-disable-next-line max-len stringAttributes = stringAttributes.concat(element.name.includes('#') ? ` ${element.name} ` : `${element.name}="${element.value}" `); }); return stringAttributes; }; exports.stringifyAttributes = stringifyAttributes;