blob: a2c5ca752ab9188687419e2f7893b380c0b9e77b [file] [log] [blame]
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.addBodyClass = exports.getHtmlHeadTagElement = exports.appendHtmlElementToHead = void 0;
const schematics_1 = require("@angular-devkit/schematics");
const parse5_element_1 = require("./parse5-element");
const parse5_1 = require("parse5");
/** Appends the given element HTML fragment to the `<head>` element of the specified HTML file. */
function appendHtmlElementToHead(host, htmlFilePath, elementHtml) {
const htmlFileBuffer = host.read(htmlFilePath);
if (!htmlFileBuffer) {
throw new schematics_1.SchematicsException(`Could not read file for path: ${htmlFilePath}`);
}
const htmlContent = htmlFileBuffer.toString();
if (htmlContent.includes(elementHtml)) {
return;
}
const headTag = getHtmlHeadTagElement(htmlContent);
if (!headTag) {
throw Error(`Could not find '<head>' element in HTML file: ${htmlFileBuffer}`);
}
// We always have access to the source code location here because the `getHeadTagElement`
// function explicitly has the `sourceCodeLocationInfo` option enabled.
const endTagOffset = headTag.sourceCodeLocation.endTag.startOffset;
const indentationOffset = parse5_element_1.getChildElementIndentation(headTag);
const insertion = `${' '.repeat(indentationOffset)}${elementHtml}`;
const recordedChange = host
.beginUpdate(htmlFilePath)
.insertRight(endTagOffset, `${insertion}\n`);
host.commitUpdate(recordedChange);
}
exports.appendHtmlElementToHead = appendHtmlElementToHead;
/** Parses the given HTML file and returns the head element if available. */
function getHtmlHeadTagElement(htmlContent) {
return getElementByTagName('head', htmlContent);
}
exports.getHtmlHeadTagElement = getHtmlHeadTagElement;
/** Adds a class to the body of the document. */
function addBodyClass(host, htmlFilePath, className) {
const htmlFileBuffer = host.read(htmlFilePath);
if (!htmlFileBuffer) {
throw new schematics_1.SchematicsException(`Could not read file for path: ${htmlFilePath}`);
}
const htmlContent = htmlFileBuffer.toString();
const body = getElementByTagName('body', htmlContent);
if (!body) {
throw Error(`Could not find <body> element in HTML file: ${htmlFileBuffer}`);
}
const classAttribute = body.attrs.find(attribute => attribute.name === 'class');
if (classAttribute) {
const hasClass = classAttribute.value.split(' ').map(part => part.trim()).includes(className);
if (!hasClass) {
const classAttributeLocation = body.sourceCodeLocation.attrs.class;
const recordedChange = host
.beginUpdate(htmlFilePath)
.insertRight(classAttributeLocation.endOffset - 1, ` ${className}`);
host.commitUpdate(recordedChange);
}
}
else {
const recordedChange = host
.beginUpdate(htmlFilePath)
.insertRight(body.sourceCodeLocation.startTag.endOffset - 1, ` class="${className}"`);
host.commitUpdate(recordedChange);
}
}
exports.addBodyClass = addBodyClass;
/** Finds an element by its tag name. */
function getElementByTagName(tagName, htmlContent) {
const document = parse5_1.parse(htmlContent, { sourceCodeLocationInfo: true });
const nodeQueue = [...document.childNodes];
while (nodeQueue.length) {
const node = nodeQueue.shift();
if (node.nodeName.toLowerCase() === tagName) {
return node;
}
else if (node.childNodes) {
nodeQueue.push(...node.childNodes);
}
}
return null;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHRtbC1tYW5pcHVsYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvY2RrL3NjaGVtYXRpY3MvdXRpbHMvaHRtbC1tYW5pcHVsYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7O0FBRUgsMkRBQXFFO0FBQ3JFLHFEQUE0RDtBQUM1RCxtQ0FBbUY7QUFFbkYsa0dBQWtHO0FBQ2xHLFNBQWdCLHVCQUF1QixDQUFDLElBQVUsRUFBRSxZQUFvQixFQUFFLFdBQW1CO0lBQzNGLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7SUFFL0MsSUFBSSxDQUFDLGNBQWMsRUFBRTtRQUNuQixNQUFNLElBQUksZ0NBQW1CLENBQUMsaUNBQWlDLFlBQVksRUFBRSxDQUFDLENBQUM7S0FDaEY7SUFFRCxNQUFNLFdBQVcsR0FBRyxjQUFjLENBQUMsUUFBUSxFQUFFLENBQUM7SUFFOUMsSUFBSSxXQUFXLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxFQUFFO1FBQ3JDLE9BQU87S0FDUjtJQUVELE1BQU0sT0FBTyxHQUFHLHFCQUFxQixDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBRW5ELElBQUksQ0FBQyxPQUFPLEVBQUU7UUFDWixNQUFNLEtBQUssQ0FBQyxpREFBaUQsY0FBYyxFQUFFLENBQUMsQ0FBQztLQUNoRjtJQUVELHlGQUF5RjtJQUN6Rix1RUFBdUU7SUFDdkUsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLGtCQUFtQixDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUM7SUFDcEUsTUFBTSxpQkFBaUIsR0FBRywyQ0FBMEIsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM5RCxNQUFNLFNBQVMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsR0FBRyxXQUFXLEVBQUUsQ0FBQztJQUVuRSxNQUFNLGNBQWMsR0FBRyxJQUFJ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QUksQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUNwQztLQUNGO0lBRUQsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7U2NoZW1hdGljc0V4Y2VwdGlvbiwgVHJlZX0gZnJvbSAnQGFuZ3VsYXItZGV2a2l0L3NjaGVtYXRpY3MnO1xuaW1wb3J0IHtnZXRDaGlsZEVsZW1lbnRJbmRlbnRhdGlvbn0gZnJvbSAnLi9wYXJzZTUtZWxlbWVudCc7XG5pbXBvcnQge0RlZmF1bHRUcmVlRG9jdW1lbnQsIERlZmF1bHRUcmVlRWxlbWVudCwgcGFyc2UgYXMgcGFyc2VIdG1sfSBmcm9tICdwYXJzZTUnO1xuXG4vKiogQXBwZW5kcyB0aGUgZ2l2ZW4gZWxlbWVudCBIVE1MIGZyYWdtZW50IHRvIHRoZSBgPGhlYWQ+YCBlbGVtZW50IG9mIHRoZSBzcGVjaWZpZWQgSFRNTCBmaWxlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGVuZEh0bWxFbGVtZW50VG9IZWFkKGhvc3Q6IFRyZWUsIGh0bWxGaWxlUGF0aDogc3RyaW5nLCBlbGVtZW50SHRtbDogc3RyaW5nKSB7XG4gIGNvbnN0IGh0bWxGaWxlQnVmZmVyID0gaG9zdC5yZWFkKGh0bWxGaWxlUGF0aCk7XG5cbiAgaWYgKCFodG1sRmlsZUJ1ZmZlcikge1xuICAgIHRocm93IG5ldyBTY2hlbWF0aWNzRXhjZXB0aW9uKGBDb3VsZCBub3QgcmVhZCBmaWxlIGZvciBwYXRoOiAke2h0bWxGaWxlUGF0aH1gKTtcbiAgfVxuXG4gIGNvbnN0IGh0bWxDb250ZW50ID0gaHRtbEZpbGVCdWZmZXIudG9TdHJpbmcoKTtcblxuICBpZiAoaHRtbENvbnRlbnQuaW5jbHVkZXMoZWxlbWVudEh0bWwpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgaGVhZFRhZyA9IGdldEh0bWxIZWFkVGFnRWxlbWVudChodG1sQ29udGVudCk7XG5cbiAgaWYgKCFoZWFkVGFnKSB7XG4gICAgdGhyb3cgRXJyb3IoYENvdWxkIG5vdCBmaW5kICc8aGVhZD4nIGVsZW1lbnQgaW4gSFRNTCBmaWxlOiAke2h0bWxGaWxlQnVmZmVyfWApO1xuICB9XG5cbiAgLy8gV2UgYWx3YXlzIGhhdmUgYWNjZXNzIHRvIHRoZSBzb3VyY2UgY29kZSBsb2NhdGlvbiBoZXJlIGJlY2F1c2UgdGhlIGBnZXRIZWFkVGFnRWxlbWVudGBcbiAgLy8gZnVuY3Rpb24gZXhwbGljaXRseSBoYXMgdGhlIGBzb3VyY2VDb2RlTG9jYXRpb25JbmZvYCBvcHRpb24gZW5hYmxlZC5cbiAgY29uc3QgZW5kVGFnT2Zmc2V0ID0gaGVhZFRhZy5zb3VyY2VDb2RlTG9jYXRpb24hLmVuZFRhZy5zdGFydE9mZnNldDtcbiAgY29uc3QgaW5kZW50YXRpb25PZmZzZXQgPSBnZXRDaGlsZEVsZW1lbnRJbmRlbnRhdGlvbihoZWFkVGFnKTtcbiAgY29uc3QgaW5zZXJ0aW9uID0gYCR7JyAnLnJlcGVhdChpbmRlbnRhdGlvbk9mZnNldCl9JHtlbGVtZW50SHRtbH1gO1xuXG4gIGNvbnN0IHJlY29yZGVkQ2hhbmdlID0gaG9zdFxuICAgIC5iZWdpblVwZGF0ZShodG1sRmlsZVBhdGgpXG4gICAgLmluc2VydFJpZ2h0KGVuZFRhZ09mZnNldCwgYCR7aW5zZXJ0aW9ufVxcbmApO1xuXG4gIGhvc3QuY29tbWl0VXBkYXRlKHJlY29yZGVkQ2hhbmdlKTtcbn1cblxuLyoqIFBhcnNlcyB0aGUgZ2l2ZW4gSFRNTCBmaWxlIGFuZCByZXR1cm5zIHRoZSBoZWFkIGVsZW1lbnQgaWYgYXZhaWxhYmxlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEh0bWxIZWFkVGFnRWxlbWVudChodG1sQ29udGVudDogc3RyaW5nKTogRGVmYXVsdFRyZWVFbGVtZW50IHwgbnVsbCB7XG4gIHJldHVybiBnZXRFbGVtZW50QnlUYWdOYW1lKCdoZWFkJywgaHRtbENvbnRlbnQpO1xufVxuXG4vKiogQWRkcyBhIGNsYXNzIHRvIHRoZSBib2R5IG9mIHRoZSBkb2N1bWVudC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRCb2R5Q2xhc3MoaG9zdDogVHJlZSwgaHRtbEZpbGVQYXRoOiBzdHJpbmcsIGNsYXNzTmFtZTogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IGh0bWxGaWxlQnVmZmVyID0gaG9zdC5yZWFkKGh0bWxGaWxlUGF0aCk7XG5cbiAgaWYgKCFodG1sRmlsZUJ1ZmZlcikge1xuICAgIHRocm93IG5ldyBTY2hlbWF0aWNzRXhjZXB0aW9uKGBDb3VsZCBub3QgcmVhZCBmaWxlIGZvciBwYXRoOiAke2h0bWxGaWxlUGF0aH1gKTtcbiAgfVxuXG4gIGNvbnN0IGh0bWxDb250ZW50ID0gaHRtbEZpbGVCdWZmZXIudG9TdHJpbmcoKTtcbiAgY29uc3QgYm9keSA9IGdldEVsZW1lbnRCeVRhZ05hbWUoJ2JvZHknLCBodG1sQ29udGVudCk7XG5cbiAgaWYgKCFib2R5KSB7XG4gICAgdGhyb3cgRXJyb3IoYENvdWxkIG5vdCBmaW5kIDxib2R5PiBlbGVtZW50IGluIEhUTUwgZmlsZTogJHtodG1sRmlsZUJ1ZmZlcn1gKTtcbiAgfVxuXG4gIGNvbnN0IGNsYXNzQXR0cmlidXRlID0gYm9keS5hdHRycy5maW5kKGF0dHJpYnV0ZSA9PiBhdHRyaWJ1dGUubmFtZSA9PT0gJ2NsYXNzJyk7XG5cbiAgaWYgKGNsYXNzQXR0cmlidXRlKSB7XG4gICAgY29uc3QgaGFzQ2xhc3MgPSBjbGFzc0F0dHJpYnV0ZS52YWx1ZS5zcGxpdCgnICcpLm1hcChwYXJ0ID0+IHBhcnQudHJpbSgpKS5pbmNsdWRlcyhjbGFzc05hbWUpO1xuXG4gICAgaWYgKCFoYXNDbGFzcykge1xuICAgICAgY29uc3QgY2xhc3NBdHRyaWJ1dGVMb2NhdGlvbiA9IGJvZHkuc291cmNlQ29kZUxvY2F0aW9uIS5hdHRycy5jbGFzcztcbiAgICAgIGNvbnN0IHJlY29yZGVkQ2hhbmdlID0gaG9zdFxuICAgICAgICAuYmVnaW5VcGRhdGUoaHRtbEZpbGVQYXRoKVxuICAgICAgICAuaW5zZXJ0UmlnaHQoY2xhc3NBdHRyaWJ1dGVMb2NhdGlvbi5lbmRPZmZzZXQgLSAxLCBgICR7Y2xhc3NOYW1lfWApO1xuICAgICAgaG9zdC5jb21taXRVcGRhdGUocmVjb3JkZWRDaGFuZ2UpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjb25zdCByZWNvcmRlZENoYW5nZSA9IGhvc3RcbiAgICAgIC5iZWdpblVwZGF0ZShodG1sRmlsZVBhdGgpXG4gICAgICAuaW5zZXJ0UmlnaHQoYm9keS5zb3VyY2VDb2RlTG9jYXRpb24hLnN0YXJ0VGFnLmVuZE9mZnNldCAtIDEsIGAgY2xhc3M9XCIke2NsYXNzTmFtZX1cImApO1xuICAgIGhvc3QuY29tbWl0VXBkYXRlKHJlY29yZGVkQ2hhbmdlKTtcbiAgfVxufVxuXG4vKiogRmluZHMgYW4gZWxlbWVudCBieSBpdHMgdGFnIG5hbWUuICovXG5mdW5jdGlvbiBnZXRFbGVtZW50QnlUYWdOYW1lKHRhZ05hbWU6IHN0cmluZywgaHRtbENvbnRlbnQ6IHN0cmluZyk6XG4gIERlZmF1bHRUcmVlRWxlbWVudCB8IG51bGwge1xuICBjb25zdCBkb2N1bWVudCA9IHBhcnNlSHRtbChodG1sQ29udGVudCwge3NvdXJjZUNvZGVMb2NhdGlvbkluZm86IHRydWV9KSBhcyBEZWZhdWx0VHJlZURvY3VtZW50O1xuICBjb25zdCBub2RlUXVldWUgPSBbLi4uZG9jdW1lbnQuY2hpbGROb2Rlc107XG5cbiAgd2hpbGUgKG5vZGVRdWV1ZS5sZW5ndGgpIHtcbiAgICBjb25zdCBub2RlID0gbm9kZVF1ZXVlLnNoaWZ0KCkgYXMgRGVmYXVsdFRyZWVFbGVtZW50O1xuXG4gICAgaWYgKG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gdGFnTmFtZSkge1xuICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSBlbHNlIGlmIChub2RlLmNoaWxkTm9kZXMpIHtcbiAgICAgIG5vZGVRdWV1ZS5wdXNoKC4uLm5vZGUuY2hpbGROb2Rlcyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG4iXX0=