@angular-devkit/schematics
Version:
Angular Schematics - Library
161 lines (160 loc) • 6.1 kB
JavaScript
/**
* @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.applyTemplates = exports.template = exports.renameTemplateFiles = exports.pathTemplate = exports.applyPathTemplate = exports.contentTemplate = exports.applyContentTemplate = exports.InvalidPipeException = exports.UnknownPipeException = exports.OptionIsNotDefinedException = exports.TEMPLATE_FILENAME_RE = void 0;
const core_1 = require("@angular-devkit/core");
const node_os_1 = require("node:os");
const base_1 = require("./base");
exports.TEMPLATE_FILENAME_RE = /\.template$/;
class OptionIsNotDefinedException extends core_1.BaseException {
constructor(name) {
super(`Option "${name}" is not defined.`);
}
}
exports.OptionIsNotDefinedException = OptionIsNotDefinedException;
class UnknownPipeException extends core_1.BaseException {
constructor(name) {
super(`Pipe "${name}" is not defined.`);
}
}
exports.UnknownPipeException = UnknownPipeException;
class InvalidPipeException extends core_1.BaseException {
constructor(name) {
super(`Pipe "${name}" is invalid.`);
}
}
exports.InvalidPipeException = InvalidPipeException;
const decoder = new TextDecoder('utf-8', { fatal: true });
function applyContentTemplate(options) {
return (entry) => {
const { path, content } = entry;
try {
const decodedContent = decoder.decode(content).replace(/\r?\n/g, node_os_1.EOL);
return {
path,
content: Buffer.from((0, core_1.template)(decodedContent, {})(options)),
};
}
catch (e) {
if (e instanceof TypeError) {
return entry;
}
throw e;
}
};
}
exports.applyContentTemplate = applyContentTemplate;
function contentTemplate(options) {
return (0, base_1.forEach)(applyContentTemplate(options));
}
exports.contentTemplate = contentTemplate;
function applyPathTemplate(data, options = {
interpolationStart: '__',
interpolationEnd: '__',
pipeSeparator: '@',
}) {
const is = options.interpolationStart;
const ie = options.interpolationEnd;
const isL = is.length;
const ieL = ie.length;
return (entry) => {
let path = entry.path;
const content = entry.content;
const original = path;
let start = path.indexOf(is);
// + 1 to have at least a length 1 name. `____` is not valid.
let end = path.indexOf(ie, start + isL + 1);
while (start != -1 && end != -1) {
const match = path.substring(start + isL, end);
let replacement = data[match];
if (!options.pipeSeparator) {
if (typeof replacement == 'function') {
replacement = replacement.call(data, original);
}
if (replacement === undefined) {
throw new OptionIsNotDefinedException(match);
}
}
else {
const [name, ...pipes] = match.split(options.pipeSeparator);
replacement = data[name];
if (typeof replacement == 'function') {
replacement = replacement.call(data, original);
}
if (replacement === undefined) {
throw new OptionIsNotDefinedException(name);
}
replacement = pipes.reduce((acc, pipe) => {
if (!pipe) {
return acc;
}
if (!(pipe in data)) {
throw new UnknownPipeException(pipe);
}
if (typeof data[pipe] != 'function') {
throw new InvalidPipeException(pipe);
}
// Coerce to string.
return '' + data[pipe](acc);
}, '' + replacement);
}
path = path.substring(0, start) + replacement + path.substring(end + ieL);
start = path.indexOf(options.interpolationStart);
// See above.
end = path.indexOf(options.interpolationEnd, start + isL + 1);
}
return { path: (0, core_1.normalize)(path), content };
};
}
exports.applyPathTemplate = applyPathTemplate;
function pathTemplate(options) {
return (0, base_1.forEach)(applyPathTemplate(options));
}
exports.pathTemplate = pathTemplate;
/**
* Remove every `.template` suffix from file names.
*/
function renameTemplateFiles() {
return (0, base_1.forEach)((entry) => {
if (entry.path.match(exports.TEMPLATE_FILENAME_RE)) {
return {
content: entry.content,
path: (0, core_1.normalize)(entry.path.replace(exports.TEMPLATE_FILENAME_RE, '')),
};
}
else {
return entry;
}
});
}
exports.renameTemplateFiles = renameTemplateFiles;
function template(options) {
return (0, base_1.chain)([
contentTemplate(options),
// Force cast to PathTemplateData. We need the type for the actual pathTemplate() call,
// but in this case we cannot do anything as contentTemplate are more permissive.
// Since values are coerced to strings in PathTemplates it will be fine in the end.
pathTemplate(options),
]);
}
exports.template = template;
function applyTemplates(options) {
return (0, base_1.forEach)((0, base_1.when)((path) => path.endsWith('.template'), (0, base_1.composeFileOperators)([
applyContentTemplate(options),
// See above for this weird cast.
applyPathTemplate(options),
(entry) => {
return {
content: entry.content,
path: entry.path.replace(exports.TEMPLATE_FILENAME_RE, ''),
};
},
])));
}
exports.applyTemplates = applyTemplates;
;