UNPKG

@angular-devkit/build-angular

Version:
189 lines (188 loc) 7.34 kB
"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.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; }, }; }