@angular-devkit/build-angular
Version:
Angular Webpack Build Facade
189 lines (188 loc) • 7.34 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.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.postcss = void 0;
exports.default = default_1;
const loader_utils_1 = require("loader-utils");
const path = __importStar(require("node:path"));
const url = __importStar(require("node:url"));
const error_1 = require("../../../utils/error");
function wrapUrl(url) {
let wrappedUrl;
const hasSingleQuotes = url.indexOf("'") >= 0;
if (hasSingleQuotes) {
wrappedUrl = `"${url}"`;
}
else {
wrappedUrl = `'${url}'`;
}
return `url(${wrappedUrl})`;
}
async function resolve(file, base, resolver) {
try {
return await resolver('./' + file, base);
}
catch {
return resolver(file, base);
}
}
exports.postcss = true;
function default_1(options) {
if (!options) {
throw new Error('No options were specified to "postcss-cli-resources".');
}
const { deployUrl = '', resourcesOutputPath = '', filename, loader, emitFile, extracted, } = options;
const process = async (inputUrl, context, resourceCache) => {
// If root-relative, absolute or protocol relative url, leave as is
if (/^((?:\w+:)?\/\/|data:|chrome:|#)/.test(inputUrl)) {
return inputUrl;
}
if (/^\//.test(inputUrl)) {
return inputUrl;
}
// If starts with a caret, remove and return remainder
// this supports bypassing asset processing
if (inputUrl.startsWith('^')) {
return inputUrl.slice(1);
}
const cacheKey = path.resolve(context, inputUrl);
const cachedUrl = resourceCache.get(cacheKey);
if (cachedUrl) {
return cachedUrl;
}
if (inputUrl.startsWith('~')) {
inputUrl = inputUrl.slice(1);
}
const { pathname, hash, search } = url.parse(inputUrl.replace(/\\/g, '/'));
const resolver = (file, base) => new Promise((resolve, reject) => {
loader.resolve(base, decodeURI(file), (err, result) => {
if (err) {
reject(err);
return;
}
resolve(result);
});
});
const result = await resolve(pathname, context, resolver);
return new Promise((resolve, reject) => {
loader.fs.readFile(result, (err, content) => {
if (err) {
reject(err);
return;
}
let outputPath = (0, loader_utils_1.interpolateName)(
// TODO: Revisit. Previously due to lack of type safety, this object
// was fine, but in practice it doesn't match the type of the loader context.
{ resourcePath: result }, filename(result), {
content,
context: loader.context || loader.rootContext,
}).replace(/\\|\//g, '-');
if (resourcesOutputPath) {
outputPath = path.posix.join(resourcesOutputPath, outputPath);
}
loader.addDependency(result);
if (emitFile) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
loader.emitFile(outputPath, content, undefined, { sourceFilename: result });
}
let outputUrl = outputPath.replace(/\\/g, '/');
if (hash || search) {
outputUrl = url.format({ pathname: outputUrl, hash, search });
}
if (deployUrl && !extracted) {
outputUrl = url.resolve(deployUrl, outputUrl);
}
resourceCache.set(cacheKey, outputUrl);
resolve(outputUrl);
});
});
};
const resourceCache = new Map();
const processed = Symbol('postcss-cli-resources');
return {
postcssPlugin: 'postcss-cli-resources',
async Declaration(decl) {
if (!decl.value.includes('url') || processed in decl) {
return;
}
const value = decl.value;
const urlRegex = /url(?:\(\s*(['"]?))(.*?)(?:\1\s*\))/g;
const segments = [];
let match;
let lastIndex = 0;
let modified = false;
// We want to load it relative to the file that imports
const inputFile = decl.source && decl.source.input.file;
const context = (inputFile && path.dirname(inputFile)) || loader.context;
while ((match = urlRegex.exec(value))) {
const originalUrl = match[2];
let processedUrl;
try {
processedUrl = await process(originalUrl, context, resourceCache);
}
catch (err) {
(0, error_1.assertIsError)(err);
loader.emitError(decl.error(err.message, { word: originalUrl }));
continue;
}
if (lastIndex < match.index) {
segments.push(value.slice(lastIndex, match.index));
}
if (!processedUrl || originalUrl === processedUrl) {
segments.push(match[0]);
}
else {
segments.push(wrapUrl(processedUrl));
modified = true;
}
lastIndex = match.index + match[0].length;
}
if (lastIndex < value.length) {
segments.push(value.slice(lastIndex));
}
if (modified) {
decl.value = segments.join('');
}
decl[processed] = true;
},
};
}
;