@spartacus/schematics
Version:
Spartacus schematics
94 lines • 4.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.appendHtmlElementToHead = void 0;
const schematics_1 = require("@angular-devkit/schematics");
const parse5_1 = require("parse5");
/**
* @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
*
* see: https://github.com/angular/components/blob/master/src/cdk/schematics/utils/html-manipulation.ts
*/
/** 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.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const endTagOffset = headTag.sourceCodeLocation.endTag.startOffset;
const indentationOffset = 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);
}
/** 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;
}
/**
* @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
*
* See https://github.com/angular/components/blob/master/src/cdk/schematics/utils/parse5-element.ts
*/
/** Determines the indentation of child elements for the given Parse5 element. */
function getChildElementIndentation(element) {
const childElement = element.childNodes.find((node) => {
return !!node.tagName;
});
if ((childElement && !childElement.sourceCodeLocation) ||
!element.sourceCodeLocation) {
throw new schematics_1.SchematicsException('Cannot determine child element indentation because the ' +
'specified Parse5 element does not have any source code location metadata.');
}
const startColumns = childElement
? // In case there are child elements inside of the element, we assume that their
// indentation is also applicable for other child elements.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
childElement.sourceCodeLocation.startCol
: // In case there is no child element, we just assume that child elements should be indented
// by two spaces.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
element.sourceCodeLocation.startCol + 2;
// Since Parse5 does not set the `startCol` properties as zero-based, we need to subtract
// one column in order to have a proper zero-based offset for the indentation.
return startColumns - 1;
}
//# sourceMappingURL=html-utils.js.map