Merge pull request #32761 from backstage/rugvip/css-exports-support
cli: add support for CSS exports in package build
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Added support for CSS exports in package builds. When a package declares a CSS file in its `exports` field (e.g., `"./styles.css": "./src/styles.css"`), the CLI will automatically bundle it during `backstage-cli package build`, resolving any `@import` statements. The export path is rewritten from `src/` to `dist/` at publish time.
|
||||
|
||||
Fixed `backstage-cli repo fix` to not add `typesVersions` entries for non-script exports like CSS files.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Migrated to use the standard `backstage-cli package build` for CSS bundling instead of a custom build script.
|
||||
@@ -138,10 +138,6 @@ jobs:
|
||||
- name: build all packages
|
||||
run: yarn backstage-cli repo build --all
|
||||
|
||||
# For now BUI has a custom build script and needs to be built separately
|
||||
- name: build BUI
|
||||
run: yarn --cwd packages/ui build
|
||||
|
||||
# Build docs-ui to ensure documentation site builds successfully
|
||||
- name: install docs-ui dependencies
|
||||
working-directory: docs-ui
|
||||
|
||||
@@ -110,10 +110,6 @@ jobs:
|
||||
- name: build
|
||||
run: yarn backstage-cli repo build --all
|
||||
|
||||
# For now BUI has a custom build script and needs to be built separately
|
||||
- name: build BUI
|
||||
run: yarn --cwd packages/ui build
|
||||
|
||||
- name: verify type dependencies
|
||||
run: yarn lint:type-deps
|
||||
|
||||
|
||||
@@ -78,8 +78,6 @@ jobs:
|
||||
|
||||
- run: yarn tsc
|
||||
- run: yarn backstage-cli repo build
|
||||
# BUI has a custom build script and needs to be built separately
|
||||
- run: yarn --cwd packages/ui build
|
||||
- name: run E2E test
|
||||
run: |
|
||||
sudo sysctl fs.inotify.max_user_watches=524288
|
||||
|
||||
@@ -86,8 +86,6 @@ jobs:
|
||||
|
||||
- run: yarn tsc
|
||||
- run: yarn backstage-cli repo build
|
||||
# BUI has a custom build script and needs to be built separately
|
||||
- run: yarn --cwd packages/ui build
|
||||
- name: run E2E test
|
||||
run: yarn e2e-test run
|
||||
env:
|
||||
|
||||
@@ -118,6 +118,7 @@
|
||||
"p-queue": "^6.6.2",
|
||||
"pirates": "^4.0.6",
|
||||
"postcss": "^8.1.0",
|
||||
"postcss-import": "^16.1.0",
|
||||
"process": "^0.11.10",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react-dev-utils": "^12.0.0-next.60",
|
||||
|
||||
@@ -33,18 +33,25 @@ const defaultIndex = {
|
||||
ext: '.ts',
|
||||
};
|
||||
|
||||
const SCRIPT_EXTS = ['.js', '.jsx', '.ts', '.tsx'];
|
||||
|
||||
function parseEntryPoint(mount: string, path: string): EntryPoint {
|
||||
const ext = extname(path);
|
||||
|
||||
let name = mount;
|
||||
if (name === '.') {
|
||||
name = 'index';
|
||||
} else if (name.startsWith('./')) {
|
||||
name = name.slice(2);
|
||||
}
|
||||
if (name.includes('/')) {
|
||||
|
||||
// Script entry points can't have slashes because we create backward-compat
|
||||
// directories for them. Non-script files (like CSS) can have nested paths.
|
||||
if (name.includes('/') && SCRIPT_EXTS.includes(ext)) {
|
||||
throw new Error(`Mount point '${mount}' may not contain multiple slashes`);
|
||||
}
|
||||
|
||||
return { mount, path, name, ext: extname(path) };
|
||||
return { mount, path, name, ext };
|
||||
}
|
||||
|
||||
export function readEntryPoints(pkg: BackstagePackageJson): Array<EntryPoint> {
|
||||
|
||||
@@ -15,9 +15,14 @@
|
||||
*/
|
||||
|
||||
import { OptionValues } from 'commander';
|
||||
import fs from 'fs-extra';
|
||||
import { buildPackage, Output } from '../../../lib/builder';
|
||||
import { findRoleFromCommand } from '../../../../../lib/role';
|
||||
import { PackageGraph, PackageRoles } from '@backstage/cli-node';
|
||||
import {
|
||||
BackstagePackageJson,
|
||||
PackageGraph,
|
||||
PackageRoles,
|
||||
} from '@backstage/cli-node';
|
||||
import { paths } from '../../../../../lib/paths';
|
||||
import { buildFrontend } from '../../../lib/buildFrontend';
|
||||
import { buildBackend } from '../../../lib/buildBackend';
|
||||
@@ -85,8 +90,13 @@ export async function command(opts: OptionValues): Promise<void> {
|
||||
outputs.add(Output.types);
|
||||
}
|
||||
|
||||
const packageJson = (await fs.readJson(
|
||||
paths.resolveTarget('package.json'),
|
||||
)) as BackstagePackageJson;
|
||||
|
||||
return buildPackage({
|
||||
outputs,
|
||||
packageJson,
|
||||
minify: Boolean(opts.minify),
|
||||
workspacePackages: await PackageGraph.listTargetPackages(),
|
||||
});
|
||||
|
||||
@@ -37,7 +37,7 @@ import {
|
||||
OutputPlugin,
|
||||
} from 'rollup';
|
||||
|
||||
import { forwardFileImports } from './plugins';
|
||||
import { forwardFileImports, cssEntryPoints } from './plugins';
|
||||
import { BuildOptions, Output } from './types';
|
||||
import { paths } from '../../../../lib/paths';
|
||||
import { BackstagePackageJson } from '@backstage/cli-node';
|
||||
@@ -275,6 +275,7 @@ export async function makeRollupConfigs(
|
||||
target: 'ES2023',
|
||||
minify: options.minify,
|
||||
}),
|
||||
cssEntryPoints({ entryPoints, targetDir }),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -107,7 +107,8 @@ export const buildPackage = async (options: BuildOptions) => {
|
||||
|
||||
const rollupConfigs = await makeRollupConfigs(options);
|
||||
|
||||
await fs.remove(resolvePath(options.targetDir ?? paths.targetDir, 'dist'));
|
||||
const targetDir = options.targetDir ?? paths.targetDir;
|
||||
await fs.remove(resolvePath(targetDir, 'dist'));
|
||||
|
||||
const buildTasks = rollupConfigs.map(rollupBuild);
|
||||
|
||||
|
||||
@@ -22,9 +22,25 @@ import {
|
||||
PluginContext,
|
||||
} from 'rollup';
|
||||
|
||||
import { forwardFileImports } from './plugins';
|
||||
import { forwardFileImports, cssEntryPoints } from './plugins';
|
||||
import { createMockDirectory } from '@backstage/backend-test-utils';
|
||||
|
||||
// Helper to call generateBundle hook which can be a function or ObjectHook
|
||||
async function callGenerateBundle(
|
||||
plugin: ReturnType<typeof cssEntryPoints>,
|
||||
ctx: PluginContext,
|
||||
options: NormalizedOutputOptions,
|
||||
bundle: Record<string, OutputChunk | OutputAsset>,
|
||||
isWrite: boolean,
|
||||
) {
|
||||
const hook = plugin.generateBundle;
|
||||
if (typeof hook === 'function') {
|
||||
await hook.call(ctx, options, bundle, isWrite);
|
||||
} else if (hook && typeof hook === 'object' && 'handler' in hook) {
|
||||
await hook.handler.call(ctx, options, bundle, isWrite);
|
||||
}
|
||||
}
|
||||
|
||||
const context = {
|
||||
meta: {
|
||||
rollupVersion: '0.0.0',
|
||||
@@ -194,3 +210,139 @@ describe('forwardFileImports', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('cssEntryPoints', () => {
|
||||
it('should be created with correct name', () => {
|
||||
const plugin = cssEntryPoints({
|
||||
entryPoints: [],
|
||||
targetDir: '/dev',
|
||||
});
|
||||
expect(plugin.name).toBe('backstage-css-entry-points');
|
||||
});
|
||||
|
||||
describe('with createMockDirectory', () => {
|
||||
const mockDir = createMockDirectory();
|
||||
|
||||
const emittedFiles: Array<{ fileName: string; source: string }> = [];
|
||||
const emitContext = {
|
||||
...context,
|
||||
emitFile: (file: { fileName: string; source: string }) => {
|
||||
emittedFiles.push(file);
|
||||
return 'asset-id';
|
||||
},
|
||||
} as unknown as PluginContext;
|
||||
|
||||
beforeEach(() => {
|
||||
emittedFiles.length = 0;
|
||||
mockDir.setContent({
|
||||
dev: {
|
||||
src: {
|
||||
css: {
|
||||
'styles.css': '@import "./base.css";\n.root { color: red; }',
|
||||
'base.css': '.base { margin: 0; }',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should not emit when isWrite is false', async () => {
|
||||
const plugin = cssEntryPoints({
|
||||
entryPoints: [
|
||||
{
|
||||
mount: './css/styles.css',
|
||||
path: './src/css/styles.css',
|
||||
name: 'css/styles.css',
|
||||
ext: '.css',
|
||||
},
|
||||
],
|
||||
targetDir: mockDir.resolve('dev'),
|
||||
});
|
||||
|
||||
await callGenerateBundle(
|
||||
plugin,
|
||||
emitContext,
|
||||
{ dir: mockDir.resolve('dev/dist') } as NormalizedOutputOptions,
|
||||
{},
|
||||
false,
|
||||
);
|
||||
|
||||
expect(emittedFiles).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should emit only CSS entry points with resolved imports', async () => {
|
||||
const plugin = cssEntryPoints({
|
||||
entryPoints: [
|
||||
// Non-CSS entry should be ignored
|
||||
{ mount: '.', path: './src/index.ts', name: 'index', ext: '.ts' },
|
||||
{
|
||||
mount: './css/styles.css',
|
||||
path: './src/css/styles.css',
|
||||
name: 'css/styles.css',
|
||||
ext: '.css',
|
||||
},
|
||||
],
|
||||
targetDir: mockDir.resolve('dev'),
|
||||
});
|
||||
|
||||
await callGenerateBundle(
|
||||
plugin,
|
||||
emitContext,
|
||||
{ dir: mockDir.resolve('dev/dist') } as NormalizedOutputOptions,
|
||||
{},
|
||||
true,
|
||||
);
|
||||
|
||||
// Only CSS file should be emitted, not the .ts entry
|
||||
expect(emittedFiles).toHaveLength(1);
|
||||
expect(emittedFiles[0].fileName).toBe('css/styles.css');
|
||||
expect(emittedFiles[0].source).toContain('.base { margin: 0; }');
|
||||
expect(emittedFiles[0].source).toContain('.root { color: red; }');
|
||||
expect(emittedFiles[0].source).not.toContain('@import');
|
||||
});
|
||||
|
||||
it('should only emit once per output directory', async () => {
|
||||
const plugin = cssEntryPoints({
|
||||
entryPoints: [
|
||||
{
|
||||
mount: './css/styles.css',
|
||||
path: './src/css/styles.css',
|
||||
name: 'css/styles.css',
|
||||
ext: '.css',
|
||||
},
|
||||
],
|
||||
targetDir: mockDir.resolve('dev'),
|
||||
});
|
||||
|
||||
// First call should emit
|
||||
await callGenerateBundle(
|
||||
plugin,
|
||||
emitContext,
|
||||
{ dir: mockDir.resolve('dev/dist') } as NormalizedOutputOptions,
|
||||
{},
|
||||
true,
|
||||
);
|
||||
expect(emittedFiles).toHaveLength(1);
|
||||
|
||||
// Second call to same dir should not emit again
|
||||
await callGenerateBundle(
|
||||
plugin,
|
||||
emitContext,
|
||||
{ dir: mockDir.resolve('dev/dist') } as NormalizedOutputOptions,
|
||||
{},
|
||||
true,
|
||||
);
|
||||
expect(emittedFiles).toHaveLength(1);
|
||||
|
||||
// Call to different dir should emit
|
||||
await callGenerateBundle(
|
||||
plugin,
|
||||
emitContext,
|
||||
{ dir: mockDir.resolve('dev/dist2') } as NormalizedOutputOptions,
|
||||
{},
|
||||
true,
|
||||
);
|
||||
expect(emittedFiles).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import postcss from 'postcss';
|
||||
import postcssImport from 'postcss-import';
|
||||
import {
|
||||
dirname,
|
||||
resolve as resolvePath,
|
||||
@@ -27,6 +29,7 @@ import {
|
||||
OutputChunk,
|
||||
HasModuleSideEffects,
|
||||
} from 'rollup';
|
||||
import { EntryPoint } from '../../../../lib/entryPoints';
|
||||
|
||||
type ForwardFileImportsOptions = {
|
||||
include: Array<string | RegExp> | string | RegExp | null;
|
||||
@@ -169,3 +172,58 @@ export function forwardFileImports(options: ForwardFileImportsOptions) {
|
||||
},
|
||||
} satisfies Plugin;
|
||||
}
|
||||
|
||||
interface CssEntryPointsOptions {
|
||||
entryPoints: EntryPoint[];
|
||||
targetDir: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollup plugin that bundles CSS entry points using postcss-import.
|
||||
* CSS files declared in package.json exports are processed and emitted
|
||||
* as part of the Rollup bundle.
|
||||
*/
|
||||
export function cssEntryPoints(options: CssEntryPointsOptions): Plugin {
|
||||
const cssEntries = options.entryPoints.filter(ep => ep.ext === '.css');
|
||||
|
||||
// Track output directories we've already emitted CSS to, to avoid duplicates
|
||||
// when Rollup runs generateBundle multiple times (once per output format)
|
||||
const generatedFor = new Set<string>();
|
||||
|
||||
return {
|
||||
name: 'backstage-css-entry-points',
|
||||
|
||||
async generateBundle(outputOptions, _bundle, isWrite) {
|
||||
if (!isWrite) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dir = outputOptions.dir || dirname(outputOptions.file!);
|
||||
if (generatedFor.has(dir)) {
|
||||
return;
|
||||
}
|
||||
generatedFor.add(dir);
|
||||
|
||||
for (const entryPoint of cssEntries) {
|
||||
const sourcePath = resolvePath(options.targetDir, entryPoint.path);
|
||||
// Strip the src/ prefix to create an output filename relative to the Rollup output directory
|
||||
const outputPath = entryPoint.path.replace(/^(\.\/)?src\//, '');
|
||||
|
||||
// Read source CSS
|
||||
const source = await fs.readFile(sourcePath, 'utf8');
|
||||
|
||||
// Bundle @import statements using postcss-import
|
||||
const result = await postcss([postcssImport()]).process(source, {
|
||||
from: sourcePath,
|
||||
});
|
||||
|
||||
// Emit the bundled CSS as an asset
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: outputPath,
|
||||
source: result.css,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -148,7 +148,11 @@ async function rewriteEntryPoints(
|
||||
|
||||
for (const entryPoint of entryPoints) {
|
||||
if (!SCRIPT_EXTS.includes(entryPoint.ext)) {
|
||||
outputExports[entryPoint.mount] = entryPoint.path;
|
||||
// Non-script files (like CSS) get their paths rewritten from src/ to dist/
|
||||
outputExports[entryPoint.mount] = entryPoint.path.replace(
|
||||
/^(\.\/)?src\//,
|
||||
'./dist/',
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,13 @@ import {
|
||||
resolve as resolvePath,
|
||||
posix,
|
||||
relative as relativePath,
|
||||
extname,
|
||||
} from 'node:path';
|
||||
import { paths } from '../../../../lib/paths';
|
||||
import { publishPreflightCheck } from '../../lib/publishing';
|
||||
|
||||
const SCRIPT_EXTS = ['.js', '.jsx', '.ts', '.tsx', '.json'];
|
||||
|
||||
/**
|
||||
* A mutable object representing a package.json file with potential fixes.
|
||||
*/
|
||||
@@ -122,29 +125,46 @@ export function fixPackageExports(pkg: FixablePackage) {
|
||||
}
|
||||
const newPath = trimRelative(path);
|
||||
|
||||
// Only script files and package.json should be added to typesVersions
|
||||
if (typeof value === 'string') {
|
||||
typeEntries[newPath] = [trimRelative(value)];
|
||||
if (SCRIPT_EXTS.includes(extname(value))) {
|
||||
typeEntries[newPath] = [trimRelative(value)];
|
||||
}
|
||||
} else if (value && typeof value === 'object' && !Array.isArray(value)) {
|
||||
if (typeof value.types === 'string') {
|
||||
typeEntries[newPath] = [trimRelative(value.types)];
|
||||
} else if (typeof value.default === 'string') {
|
||||
} else if (
|
||||
typeof value.default === 'string' &&
|
||||
SCRIPT_EXTS.includes(extname(value.default))
|
||||
) {
|
||||
typeEntries[newPath] = [trimRelative(value.default)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const typesVersions = { '*': typeEntries };
|
||||
if (existingTypesVersions !== JSON.stringify(typesVersions)) {
|
||||
const newPkgEntries = Object.entries(pkg.packageJson).filter(
|
||||
([name]) => name !== 'typesVersions',
|
||||
);
|
||||
newPkgEntries.splice(
|
||||
newPkgEntries.findIndex(([name]) => name === 'exports') + 1,
|
||||
0,
|
||||
['typesVersions', typesVersions],
|
||||
);
|
||||
const hasTypeEntries = Object.keys(typeEntries).length > 0;
|
||||
const typesVersions = hasTypeEntries ? { '*': typeEntries } : undefined;
|
||||
|
||||
pkg.packageJson = Object.fromEntries(newPkgEntries) as BackstagePackageJson;
|
||||
if (existingTypesVersions !== JSON.stringify(typesVersions)) {
|
||||
if (pkg.packageJson.typesVersions) {
|
||||
// Update in place to preserve field order
|
||||
if (typesVersions) {
|
||||
pkg.packageJson.typesVersions = typesVersions;
|
||||
} else {
|
||||
delete pkg.packageJson.typesVersions;
|
||||
}
|
||||
} else if (typesVersions) {
|
||||
// Insert after exports when adding for the first time
|
||||
const newPkgEntries = Object.entries(pkg.packageJson);
|
||||
newPkgEntries.splice(
|
||||
newPkgEntries.findIndex(([name]) => name === 'exports') + 1,
|
||||
0,
|
||||
['typesVersions', typesVersions],
|
||||
);
|
||||
pkg.packageJson = Object.fromEntries(
|
||||
newPkgEntries,
|
||||
) as BackstagePackageJson;
|
||||
}
|
||||
pkg.changed = true;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+6
@@ -259,3 +259,9 @@ declare module 'webpack-node-externals' {
|
||||
}
|
||||
|
||||
declare module '@esbuild-kit/cjs-loader' {}
|
||||
|
||||
declare module 'postcss-import' {
|
||||
import { Plugin } from 'postcss';
|
||||
|
||||
export default function postcssImport(): Plugin;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+15
-12
@@ -5,9 +5,7 @@
|
||||
"role": "web-library"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"main": "dist/index.esm.js",
|
||||
"types": "dist/index.d.ts"
|
||||
"access": "public"
|
||||
},
|
||||
"keywords": [
|
||||
"backstage"
|
||||
@@ -22,17 +20,25 @@
|
||||
"sideEffects": [
|
||||
"*.css"
|
||||
],
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./css/styles.css": "./src/css/styles.css",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"package.json": [
|
||||
"package.json"
|
||||
]
|
||||
}
|
||||
},
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"css"
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "yarn build:app && yarn build:css",
|
||||
"build:app": "backstage-cli package build",
|
||||
"build:css": "node scripts/build-css.mjs",
|
||||
"build:css:watch": "node scripts/build-css.mjs --watch",
|
||||
"build": "backstage-cli package build",
|
||||
"clean": "backstage-cli package clean",
|
||||
"lint": "backstage-cli package lint",
|
||||
"prepack": "backstage-cli package prepack",
|
||||
@@ -50,12 +56,9 @@
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"chalk": "^5.4.1",
|
||||
"eslint-plugin-storybook": "^10.3.0-alpha.1",
|
||||
"glob": "^11.0.1",
|
||||
"globals": "^15.11.0",
|
||||
"lightningcss": "^1.29.1",
|
||||
"mini-css-extract-plugin": "^2.9.2",
|
||||
"react": "^18.0.2",
|
||||
"react-dom": "^18.0.2",
|
||||
"react-router-dom": "^6.30.2",
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-restricted-imports */
|
||||
import { transform, bundle } from 'lightningcss';
|
||||
import fs from 'node:fs';
|
||||
import chalk from 'chalk';
|
||||
/* eslint-enable no-restricted-imports */
|
||||
|
||||
const srcFile = 'src/css/styles.css';
|
||||
const distDir = 'css';
|
||||
const distFile = `${distDir}/styles.css`;
|
||||
|
||||
// Check if styles.css exists
|
||||
if (!fs.existsSync(srcFile)) {
|
||||
console.error(`${srcFile} does not exist`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Ensure the dist/css directory exists
|
||||
if (!fs.existsSync(distDir)) {
|
||||
fs.mkdirSync(distDir, { recursive: true });
|
||||
}
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const watchMode = args.includes('--watch');
|
||||
|
||||
async function buildCSS(logs = true) {
|
||||
const css = fs.readFileSync(srcFile);
|
||||
|
||||
let { code: bundleCode } = bundle({
|
||||
filename: srcFile,
|
||||
});
|
||||
|
||||
const { code } = transform({
|
||||
filename: distFile,
|
||||
code: bundleCode,
|
||||
minify: false,
|
||||
});
|
||||
|
||||
// Prepend the layer order declaration that lightningcss removes during bundling
|
||||
// This is crucial to maintain the correct layer cascade order
|
||||
const layerDeclaration = '@layer tokens, base, components, utilities;\n\n';
|
||||
const finalCode = layerDeclaration + code;
|
||||
|
||||
fs.writeFileSync(distFile, finalCode);
|
||||
if (logs) {
|
||||
console.log(chalk.blue('CSS transformed and minified: ') + 'styles.css');
|
||||
console.log(chalk.green('CSS file built successfully!'));
|
||||
}
|
||||
}
|
||||
|
||||
if (watchMode) {
|
||||
fs.watch('src/css', { recursive: true }, (eventType, filename) => {
|
||||
if (filename === 'styles.css') {
|
||||
console.log(
|
||||
chalk.yellow(`Changes detected in ${filename}, rebuilding...`),
|
||||
);
|
||||
buildCSS(false).catch(console.error);
|
||||
}
|
||||
});
|
||||
buildCSS().catch(console.error);
|
||||
console.log(chalk.yellow('Watching for CSS changes...'));
|
||||
} else {
|
||||
buildCSS().catch(console.error);
|
||||
}
|
||||
@@ -3395,6 +3395,7 @@ __metadata:
|
||||
p-queue: "npm:^6.6.2"
|
||||
pirates: "npm:^4.0.6"
|
||||
postcss: "npm:^8.1.0"
|
||||
postcss-import: "npm:^16.1.0"
|
||||
process: "npm:^0.11.10"
|
||||
raw-loader: "npm:^4.0.2"
|
||||
react-dev-utils: "npm:^12.0.0-next.60"
|
||||
@@ -8050,13 +8051,10 @@ __metadata:
|
||||
"@tanstack/react-table": "npm:^8.21.3"
|
||||
"@types/react": "npm:^18.0.0"
|
||||
"@types/react-dom": "npm:^18.0.0"
|
||||
chalk: "npm:^5.4.1"
|
||||
clsx: "npm:^2.1.1"
|
||||
eslint-plugin-storybook: "npm:^10.3.0-alpha.1"
|
||||
glob: "npm:^11.0.1"
|
||||
globals: "npm:^15.11.0"
|
||||
lightningcss: "npm:^1.29.1"
|
||||
mini-css-extract-plugin: "npm:^2.9.2"
|
||||
react: "npm:^18.0.2"
|
||||
react-aria-components: "npm:^1.14.0"
|
||||
react-dom: "npm:^18.0.2"
|
||||
@@ -29160,7 +29158,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"detect-libc@npm:^2.0.0, detect-libc@npm:^2.0.3":
|
||||
"detect-libc@npm:^2.0.0":
|
||||
version: 2.0.3
|
||||
resolution: "detect-libc@npm:2.0.3"
|
||||
checksum: 10/b4ea018d623e077bd395f168a9e81db77370dde36a5b01d067f2ad7989924a81d31cb547ff764acb2aa25d50bb7fdde0b0a93bec02212b0cb430621623246d39
|
||||
@@ -34835,7 +34833,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1":
|
||||
"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.1":
|
||||
version: 2.16.1
|
||||
resolution: "is-core-module@npm:2.16.1"
|
||||
dependencies:
|
||||
@@ -37303,126 +37301,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-android-arm64@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-android-arm64@npm:1.30.2"
|
||||
conditions: os=android & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-darwin-arm64@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-darwin-arm64@npm:1.30.2"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-darwin-x64@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-darwin-x64@npm:1.30.2"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-freebsd-x64@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-freebsd-x64@npm:1.30.2"
|
||||
conditions: os=freebsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-linux-arm-gnueabihf@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-linux-arm-gnueabihf@npm:1.30.2"
|
||||
conditions: os=linux & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-linux-arm64-gnu@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-linux-arm64-gnu@npm:1.30.2"
|
||||
conditions: os=linux & cpu=arm64 & libc=glibc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-linux-arm64-musl@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-linux-arm64-musl@npm:1.30.2"
|
||||
conditions: os=linux & cpu=arm64 & libc=musl
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-linux-x64-gnu@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-linux-x64-gnu@npm:1.30.2"
|
||||
conditions: os=linux & cpu=x64 & libc=glibc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-linux-x64-musl@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-linux-x64-musl@npm:1.30.2"
|
||||
conditions: os=linux & cpu=x64 & libc=musl
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-win32-arm64-msvc@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-win32-arm64-msvc@npm:1.30.2"
|
||||
conditions: os=win32 & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss-win32-x64-msvc@npm:1.30.2":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss-win32-x64-msvc@npm:1.30.2"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lightningcss@npm:^1.29.1":
|
||||
version: 1.30.2
|
||||
resolution: "lightningcss@npm:1.30.2"
|
||||
dependencies:
|
||||
detect-libc: "npm:^2.0.3"
|
||||
lightningcss-android-arm64: "npm:1.30.2"
|
||||
lightningcss-darwin-arm64: "npm:1.30.2"
|
||||
lightningcss-darwin-x64: "npm:1.30.2"
|
||||
lightningcss-freebsd-x64: "npm:1.30.2"
|
||||
lightningcss-linux-arm-gnueabihf: "npm:1.30.2"
|
||||
lightningcss-linux-arm64-gnu: "npm:1.30.2"
|
||||
lightningcss-linux-arm64-musl: "npm:1.30.2"
|
||||
lightningcss-linux-x64-gnu: "npm:1.30.2"
|
||||
lightningcss-linux-x64-musl: "npm:1.30.2"
|
||||
lightningcss-win32-arm64-msvc: "npm:1.30.2"
|
||||
lightningcss-win32-x64-msvc: "npm:1.30.2"
|
||||
dependenciesMeta:
|
||||
lightningcss-android-arm64:
|
||||
optional: true
|
||||
lightningcss-darwin-arm64:
|
||||
optional: true
|
||||
lightningcss-darwin-x64:
|
||||
optional: true
|
||||
lightningcss-freebsd-x64:
|
||||
optional: true
|
||||
lightningcss-linux-arm-gnueabihf:
|
||||
optional: true
|
||||
lightningcss-linux-arm64-gnu:
|
||||
optional: true
|
||||
lightningcss-linux-arm64-musl:
|
||||
optional: true
|
||||
lightningcss-linux-x64-gnu:
|
||||
optional: true
|
||||
lightningcss-linux-x64-musl:
|
||||
optional: true
|
||||
lightningcss-win32-arm64-msvc:
|
||||
optional: true
|
||||
lightningcss-win32-x64-msvc:
|
||||
optional: true
|
||||
checksum: 10/d6cc06d9bac295589a49446e9c45a241dfa16f4f81a7318c26cbc0be3e189003ec0da5d9a0fd9bdffc63a3ce05878cc7329277eaac77a826e8b68c73dc96cfda
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lilconfig@npm:^2.0.3":
|
||||
version: 2.1.0
|
||||
resolution: "lilconfig@npm:2.1.0"
|
||||
@@ -39318,7 +39196,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mini-css-extract-plugin@npm:^2.4.2, mini-css-extract-plugin@npm:^2.9.2":
|
||||
"mini-css-extract-plugin@npm:^2.4.2":
|
||||
version: 2.10.0
|
||||
resolution: "mini-css-extract-plugin@npm:2.10.0"
|
||||
dependencies:
|
||||
@@ -42652,6 +42530,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"postcss-import@npm:^16.1.0":
|
||||
version: 16.1.1
|
||||
resolution: "postcss-import@npm:16.1.1"
|
||||
dependencies:
|
||||
postcss-value-parser: "npm:^4.0.0"
|
||||
read-cache: "npm:^1.0.0"
|
||||
resolve: "npm:^1.1.7"
|
||||
peerDependencies:
|
||||
postcss: ^8.0.0
|
||||
checksum: 10/2afac2b6e25f263f45ac2168c5f5e4b2e49e3d44c620338138fe89cf81bd83e6056784a26d54c58611d05dda18bc56069212484ec750bbf6d2e29b623460a7f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"postcss-load-config@npm:^3.0.0":
|
||||
version: 3.0.1
|
||||
resolution: "postcss-load-config@npm:3.0.1"
|
||||
@@ -42973,7 +42864,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"postcss-value-parser@npm:^4.0.2, postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0":
|
||||
"postcss-value-parser@npm:^4.0.0, postcss-value-parser@npm:^4.0.2, postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0":
|
||||
version: 4.2.0
|
||||
resolution: "postcss-value-parser@npm:4.2.0"
|
||||
checksum: 10/e4e4486f33b3163a606a6ed94f9c196ab49a37a7a7163abfcd469e5f113210120d70b8dd5e33d64636f41ad52316a3725655421eb9a1094f1bcab1db2f555c62
|
||||
@@ -44784,6 +44675,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"read-cache@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "read-cache@npm:1.0.0"
|
||||
dependencies:
|
||||
pify: "npm:^2.3.0"
|
||||
checksum: 10/83a39149d9dfa38f0c482ea0d77b34773c92fef07fe7599cdd914d255b14d0453e0229ef6379d8d27d6947f42d7581635296d0cfa7708f05a9bd8e789d398b31
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"read-cmd-shim@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "read-cmd-shim@npm:2.0.0"
|
||||
@@ -45364,16 +45264,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@npm:^1.1.6, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.10, resolve@npm:^1.22.4, resolve@npm:^1.22.8, resolve@npm:~1.22.1, resolve@npm:~1.22.2":
|
||||
version: 1.22.10
|
||||
resolution: "resolve@npm:1.22.10"
|
||||
"resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.10, resolve@npm:^1.22.4, resolve@npm:^1.22.8, resolve@npm:~1.22.1, resolve@npm:~1.22.2":
|
||||
version: 1.22.11
|
||||
resolution: "resolve@npm:1.22.11"
|
||||
dependencies:
|
||||
is-core-module: "npm:^2.16.0"
|
||||
is-core-module: "npm:^2.16.1"
|
||||
path-parse: "npm:^1.0.7"
|
||||
supports-preserve-symlinks-flag: "npm:^1.0.0"
|
||||
bin:
|
||||
resolve: bin/resolve
|
||||
checksum: 10/0a398b44da5c05e6e421d70108822c327675febb880eebe905587628de401854c61d5df02866ff34fc4cb1173a51c9f0e84a94702738df3611a62e2acdc68181
|
||||
checksum: 10/e1b2e738884a08de03f97ee71494335eba8c2b0feb1de9ae065e82c48997f349f77a2b10e8817e147cf610bfabc4b1cb7891ee8eaf5bf80d4ad514a34c4fab0a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -45403,16 +45303,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.10#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A~1.22.1#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A~1.22.2#optional!builtin<compat/resolve>":
|
||||
version: 1.22.10
|
||||
resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin<compat/resolve>::version=1.22.10&hash=c3c19d"
|
||||
"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.1.7#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.10#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A~1.22.1#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A~1.22.2#optional!builtin<compat/resolve>":
|
||||
version: 1.22.11
|
||||
resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin<compat/resolve>::version=1.22.11&hash=c3c19d"
|
||||
dependencies:
|
||||
is-core-module: "npm:^2.16.0"
|
||||
is-core-module: "npm:^2.16.1"
|
||||
path-parse: "npm:^1.0.7"
|
||||
supports-preserve-symlinks-flag: "npm:^1.0.0"
|
||||
bin:
|
||||
resolve: bin/resolve
|
||||
checksum: 10/d4d878bfe3702d215ea23e75e0e9caf99468e3db76f5ca100d27ebdc527366fee3877e54bce7d47cc72ca8952fc2782a070d238bfa79a550eeb0082384c3b81a
|
||||
checksum: 10/fd342cad25e52cd6f4f3d1716e189717f2522bfd6641109fe7aa372f32b5714a296ed7c238ddbe7ebb0c1ddfe0b7f71c9984171024c97cf1b2073e3e40ff71a8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user