ng-alain
Version:
Schematics specific to NG-ALAIN
152 lines (128 loc) • 4.41 kB
text/typescript
import { ProjectDefinition } from '@angular-devkit/core/src/workspace';
import { SchematicsException, Tree } from '@angular-devkit/schematics';
import { InsertChange } from '@schematics/angular/utility/change';
import * as parse5 from 'parse5';
import { BUILD_TARGET_BUILD, getProjectTarget } from './workspace';
/** Gets the app index.html file */
export function getIndexHtmlPath(host: Tree, project: ProjectDefinition): string {
const targetOptions = getProjectTarget(project, BUILD_TARGET_BUILD);
if (typeof targetOptions.index === 'string' && targetOptions.index.endsWith('index.html')) {
return targetOptions.index;
}
const htmlPath = `${project.sourceRoot}/index.html`;
if (host.exists(htmlPath)) {
return htmlPath;
}
throw new SchematicsException('No index.html file was found.');
}
/**
* Parses the index.html file to get the HEAD tag position.
*/
export function getTag(tree: Tree, src: string, tagName: string): { startOffset: any; endOffset: any } {
if ((parse5 as any).treeAdapters) {
return getTagInV4(tree, src, tagName);
}
const document = parse5.parse(src, {
sourceCodeLocationInfo: true
} as any) as any;
let resNode: any;
const visit = (nodes: any[]): void => {
nodes.forEach(node => {
const element = node as any;
if (element.nodeName === tagName) {
resNode = element;
} else {
if (element.childNodes) {
visit(element.childNodes);
}
}
});
};
visit(document.childNodes);
if (!resNode) {
throw new SchematicsException('Head element not found!');
}
return {
startOffset: resNode.sourceCodeLocation.startTag.endOffset,
endOffset: resNode.sourceCodeLocation.endTag.startOffset
};
}
export function getTagInV4(_host: Tree, src: string, tagName: string): { startOffset: any; endOffset: any } {
const document: any = parse5.parse(src, {
locationInfo: true
} as any);
let resNode;
const visit = (nodes: any[]): void => {
nodes.forEach(node => {
const element: any = node;
if (element.tagName === tagName) {
resNode = element;
} else {
if (element.childNodes) {
visit(element.childNodes);
}
}
});
};
visit(document.childNodes);
if (!resNode) {
throw new SchematicsException('Head element not found!');
}
return {
startOffset: resNode.__location.startTag.endOffset,
endOffset: resNode.__location.endTag.startOffset
};
}
/**
* Get index.html content
*/
export function getIndexHtmlContent(tree: Tree, project: ProjectDefinition): { indexPath: string; src: string } {
const indexPath = getIndexHtmlPath(tree, project);
const buffer = tree.read(indexPath);
if (!buffer) {
throw new SchematicsException(`Could not find file for path '${indexPath}'`);
}
return {
indexPath,
src: buffer.toString()
};
}
/**
* Adds a link to the index.html head tag
*/
export function addHeadLink(tree: Tree, project: ProjectDefinition, link: string): void {
const { indexPath, src } = getIndexHtmlContent(tree, project);
if (src.indexOf(link) === -1) {
const node = getTag(tree, src, 'head');
const insertion = new InsertChange(indexPath, node.startOffset, link);
const recorder = tree.beginUpdate(indexPath);
recorder.insertLeft(insertion.pos, insertion.toAdd);
tree.commitUpdate(recorder);
}
}
/**
* Adds a style to the index.html head end tag
*/
export function addHeadStyle(tree: Tree, project: ProjectDefinition, style: string): void {
const { indexPath, src } = getIndexHtmlContent(tree, project);
if (src.indexOf(style) === -1) {
const node = getTag(tree, src, 'head');
const insertion = new InsertChange(indexPath, node.endOffset, style);
const recorder = tree.beginUpdate(indexPath);
recorder.insertLeft(insertion.pos, insertion.toAdd);
tree.commitUpdate(recorder);
}
}
/**
* Adds a html to the index.html body end tag
*/
export function addHtmlToBody(tree: Tree, project: ProjectDefinition, html: string): void {
const { indexPath, src } = getIndexHtmlContent(tree, project);
if (src.indexOf(html) === -1) {
const node = getTag(tree, src, 'body');
const insertion = new InsertChange(indexPath, node.endOffset, html);
const recorder = tree.beginUpdate(indexPath);
recorder.insertLeft(insertion.pos, insertion.toAdd);
tree.commitUpdate(recorder);
}
}