mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-21 22:34:21 +08:00
fix(@angular-devkit/build-angular): update list of known tailwind configuration files
With this change we added `tailwind.config.mjs` and `tailwind.config.ts` to known tailwind config files. Closes #24943
This commit is contained in:
parent
d5fed32096
commit
758b0695f3
@ -13,6 +13,7 @@ import path from 'node:path';
|
||||
import { normalizeAssetPatterns, normalizeOptimization, normalizeSourceMaps } from '../../utils';
|
||||
import { normalizeCacheOptions } from '../../utils/normalize-cache';
|
||||
import { generateEntryPoints } from '../../utils/package-chunk-sort';
|
||||
import { findTailwindConfigurationFile } from '../../utils/tailwind';
|
||||
import { getIndexInputFile, getIndexOutputFile } from '../../utils/webpack-browser-config';
|
||||
import { globalScriptsByBundleName, normalizeGlobalStyles } from '../../webpack/utils/helpers';
|
||||
import { Schema as BrowserBuilderOptions, OutputHashing } from './schema';
|
||||
@ -97,7 +98,7 @@ export async function normalizeOptions(
|
||||
}
|
||||
|
||||
let tailwindConfiguration: { file: string; package: string } | undefined;
|
||||
const tailwindConfigurationPath = findTailwindConfigurationFile(workspaceRoot, projectRoot);
|
||||
const tailwindConfigurationPath = await findTailwindConfigurationFile(workspaceRoot, projectRoot);
|
||||
if (tailwindConfigurationPath) {
|
||||
// Create a node resolver at the project root as a directory
|
||||
const resolver = createRequire(projectRoot + '/');
|
||||
@ -203,27 +204,6 @@ export async function normalizeOptions(
|
||||
};
|
||||
}
|
||||
|
||||
function findTailwindConfigurationFile(
|
||||
workspaceRoot: string,
|
||||
projectRoot: string,
|
||||
): string | undefined {
|
||||
// A configuration file can exist in the project or workspace root
|
||||
// The list of valid config files can be found:
|
||||
// https://github.com/tailwindlabs/tailwindcss/blob/8845d112fb62d79815b50b3bae80c317450b8b92/src/util/resolveConfigPath.js#L46-L52
|
||||
const tailwindConfigFiles = ['tailwind.config.js', 'tailwind.config.cjs'];
|
||||
for (const basePath of [projectRoot, workspaceRoot]) {
|
||||
for (const configFile of tailwindConfigFiles) {
|
||||
// Project level configuration should always take precedence.
|
||||
const fullPath = path.join(basePath, configFile);
|
||||
if (fs.existsSync(fullPath)) {
|
||||
return fullPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a directory path string.
|
||||
* Currently only removes a trailing slash if present.
|
||||
|
40
packages/angular_devkit/build_angular/src/utils/tailwind.ts
Normal file
40
packages/angular_devkit/build_angular/src/utils/tailwind.ts
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
import { readdir } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const tailwindConfigFiles: string[] = [
|
||||
'tailwind.config.js',
|
||||
'tailwind.config.cjs',
|
||||
'tailwind.config.mjs',
|
||||
'tailwind.config.ts',
|
||||
];
|
||||
|
||||
export async function findTailwindConfigurationFile(
|
||||
workspaceRoot: string,
|
||||
projectRoot: string,
|
||||
): Promise<string | undefined> {
|
||||
const dirEntries = [projectRoot, workspaceRoot].map((root) =>
|
||||
readdir(root, { withFileTypes: false }).then((entries) => ({
|
||||
root,
|
||||
files: new Set(entries),
|
||||
})),
|
||||
);
|
||||
|
||||
// A configuration file can exist in the project or workspace root
|
||||
for await (const { root, files } of dirEntries) {
|
||||
for (const potentialConfig of tailwindConfigFiles) {
|
||||
if (files.has(potentialConfig)) {
|
||||
return join(root, potentialConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import { pathToFileURL } from 'node:url';
|
||||
import type { FileImporter } from 'sass';
|
||||
@ -19,6 +18,7 @@ import {
|
||||
import { SassLegacyWorkerImplementation } from '../../sass/sass-service-legacy';
|
||||
import { WebpackConfigOptions } from '../../utils/build-options';
|
||||
import { useLegacySass } from '../../utils/environment-options';
|
||||
import { findTailwindConfigurationFile } from '../../utils/tailwind';
|
||||
import {
|
||||
AnyComponentStyleBudgetChecker,
|
||||
PostcssCliResources,
|
||||
@ -34,8 +34,8 @@ import {
|
||||
} from '../utils/helpers';
|
||||
|
||||
// eslint-disable-next-line max-lines-per-function
|
||||
export function getStylesConfig(wco: WebpackConfigOptions): Configuration {
|
||||
const { root, buildOptions, logger } = wco;
|
||||
export async function getStylesConfig(wco: WebpackConfigOptions): Promise<Configuration> {
|
||||
const { root, buildOptions, logger, projectRoot } = wco;
|
||||
const extraPlugins: Configuration['plugins'] = [];
|
||||
|
||||
extraPlugins.push(new AnyComponentStyleBudgetChecker(buildOptions.budgets));
|
||||
@ -86,13 +86,13 @@ export function getStylesConfig(wco: WebpackConfigOptions): Configuration {
|
||||
// Only load Tailwind CSS plugin if configuration file was found.
|
||||
// This acts as a guard to ensure the project actually wants to use Tailwind CSS.
|
||||
// The package may be unknowningly present due to a third-party transitive package dependency.
|
||||
const tailwindConfigPath = getTailwindConfigPath(wco);
|
||||
const tailwindConfigPath = await findTailwindConfigurationFile(root, projectRoot);
|
||||
if (tailwindConfigPath) {
|
||||
let tailwindPackagePath;
|
||||
try {
|
||||
tailwindPackagePath = require.resolve('tailwindcss', { paths: [wco.root] });
|
||||
tailwindPackagePath = require.resolve('tailwindcss', { paths: [root] });
|
||||
} catch {
|
||||
const relativeTailwindConfigPath = path.relative(wco.root, tailwindConfigPath);
|
||||
const relativeTailwindConfigPath = path.relative(root, tailwindConfigPath);
|
||||
logger.warn(
|
||||
`Tailwind CSS configuration file found (${relativeTailwindConfigPath})` +
|
||||
` but the 'tailwindcss' package is not installed.` +
|
||||
@ -315,24 +315,6 @@ export function getStylesConfig(wco: WebpackConfigOptions): Configuration {
|
||||
};
|
||||
}
|
||||
|
||||
function getTailwindConfigPath({ projectRoot, root }: WebpackConfigOptions): string | undefined {
|
||||
// A configuration file can exist in the project or workspace root
|
||||
// The list of valid config files can be found:
|
||||
// https://github.com/tailwindlabs/tailwindcss/blob/8845d112fb62d79815b50b3bae80c317450b8b92/src/util/resolveConfigPath.js#L46-L52
|
||||
const tailwindConfigFiles = ['tailwind.config.js', 'tailwind.config.cjs'];
|
||||
for (const basePath of [projectRoot, root]) {
|
||||
for (const configFile of tailwindConfigFiles) {
|
||||
// Irrespective of the name project level configuration should always take precedence.
|
||||
const fullPath = path.join(basePath, configFile);
|
||||
if (fs.existsSync(fullPath)) {
|
||||
return fullPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getSassLoaderOptions(
|
||||
root: string,
|
||||
implementation: SassWorkerImplementation | SassLegacyWorkerImplementation,
|
||||
@ -399,7 +381,7 @@ function getSassResolutionImporter(
|
||||
root: string,
|
||||
preserveSymlinks: boolean,
|
||||
): FileImporter<'async'> {
|
||||
const commonResolverOptions: Parameters<typeof loaderContext['getResolve']>[0] = {
|
||||
const commonResolverOptions: Parameters<(typeof loaderContext)['getResolve']>[0] = {
|
||||
conditionNames: ['sass', 'style'],
|
||||
mainFields: ['sass', 'style', 'main', '...'],
|
||||
extensions: ['.scss', '.sass', '.css'],
|
||||
|
Loading…
x
Reference in New Issue
Block a user