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
JavaScript
;
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;