1 | ;
|
2 | /**
|
3 | * @license
|
4 | * Copyright Google LLC All Rights Reserved.
|
5 | *
|
6 | * Use of this source code is governed by an MIT-style license that can be
|
7 | * found in the LICENSE file at https://angular.io/license
|
8 | */
|
9 | Object.defineProperty(exports, "__esModule", { value: true });
|
10 | exports.createCssResourcePlugin = void 0;
|
11 | const promises_1 = require("node:fs/promises");
|
12 | const node_path_1 = require("node:path");
|
13 | const stylesheet_processor_1 = require("./stylesheet-processor");
|
14 | const CSS_RESOURCE_NAMESPACE = 'angular:css-resource';
|
15 | /**
|
16 | * Symbol marker used to indicate CSS resource resolution is being attempted.
|
17 | * This is used to prevent an infinite loop within the plugin's resolve hook.
|
18 | */
|
19 | const CSS_RESOURCE_RESOLUTION = Symbol('CSS_RESOURCE_RESOLUTION');
|
20 | /**
|
21 | * Creates an esbuild {@link Plugin} that loads all CSS url token references using the
|
22 | * built-in esbuild `file` loader. A plugin is used to allow for all file extensions
|
23 | * and types to be supported without needing to manually specify all extensions
|
24 | * within the build configuration.
|
25 | *
|
26 | * @returns An esbuild {@link Plugin} instance.
|
27 | */
|
28 | function createCssResourcePlugin(url) {
|
29 | return {
|
30 | name: 'angular-css-resource',
|
31 | setup(build) {
|
32 | build.onResolve({ filter: /.*/ }, async (args) => {
|
33 | var _a, _b;
|
34 | // Only attempt to resolve url tokens which only exist inside CSS.
|
35 | // Also, skip this plugin if already attempting to resolve the url-token.
|
36 | if (args.kind !== 'url-token' || ((_a = args.pluginData) === null || _a === void 0 ? void 0 : _a[CSS_RESOURCE_RESOLUTION])) {
|
37 | return null;
|
38 | }
|
39 | // If root-relative, absolute or protocol relative url, mark as external to leave the
|
40 | // path/URL in place.
|
41 | if (url !== stylesheet_processor_1.CssUrl.inline || /^((?:\w+:)?\/\/|data:|chrome:|#|\/)/.test(args.path)) {
|
42 | return {
|
43 | path: args.path,
|
44 | external: true,
|
45 | };
|
46 | }
|
47 | const { importer, kind, resolveDir, namespace, pluginData = {} } = args;
|
48 | pluginData[CSS_RESOURCE_RESOLUTION] = true;
|
49 | const result = await build.resolve(args.path, {
|
50 | importer,
|
51 | kind,
|
52 | namespace,
|
53 | pluginData,
|
54 | resolveDir,
|
55 | });
|
56 | if (result.errors.length) {
|
57 | const error = result.errors[0];
|
58 | if (args.path[0] === '~') {
|
59 | error.notes = [
|
60 | {
|
61 | location: null,
|
62 | text: 'You can remove the tilde and use a relative path to reference it, which should remove this error.',
|
63 | },
|
64 | ];
|
65 | }
|
66 | else if (args.path[0] === '^') {
|
67 | error.notes = [
|
68 | {
|
69 | location: null,
|
70 | text: 'You can remove the caret and use a relative path to reference it, which should remove this error.',
|
71 | },
|
72 | ];
|
73 | }
|
74 | const extension = importer && (0, node_path_1.extname)(importer);
|
75 | if (extension !== '.css') {
|
76 | error.notes.push({
|
77 | location: null,
|
78 | text: 'Preprocessor stylesheets may not show the exact file location of the error.',
|
79 | });
|
80 | }
|
81 | }
|
82 | // Return results that are not files since these are most likely specific to another plugin
|
83 | // and cannot be loaded by this plugin.
|
84 | if (result.namespace !== 'file') {
|
85 | return result;
|
86 | }
|
87 | // All file results are considered CSS resources and will be loaded via the file loader
|
88 | return {
|
89 | ...result,
|
90 | // Use a relative path to prevent fully resolved paths in the metafile (JSON stats file).
|
91 | // This is only necessary for custom namespaces. esbuild will handle the file namespace.
|
92 | path: (0, node_path_1.relative)((_b = build.initialOptions.absWorkingDir) !== null && _b !== void 0 ? _b : '', result.path),
|
93 | namespace: CSS_RESOURCE_NAMESPACE,
|
94 | };
|
95 | });
|
96 | build.onLoad({ filter: /./, namespace: CSS_RESOURCE_NAMESPACE }, async (args) => {
|
97 | var _a;
|
98 | const resourcePath = (0, node_path_1.join)((_a = build.initialOptions.absWorkingDir) !== null && _a !== void 0 ? _a : '', args.path);
|
99 | return {
|
100 | contents: await (0, promises_1.readFile)(resourcePath),
|
101 | loader: 'dataurl',
|
102 | watchFiles: [resourcePath],
|
103 | };
|
104 | });
|
105 | },
|
106 | };
|
107 | }
|
108 | exports.createCssResourcePlugin = createCssResourcePlugin;
|
109 | //# sourceMappingURL=css-resource-plugin.js.map |
\ | No newline at end of file |