Skip to content

Commit 00b71c5

Browse files
mirkaciampojsnajdr
authored
Add theme package (#72305)
* Add `theme` package Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> * Remove ts extensions * Handle CSS modules * Update package lock * Allow public documentation * Add content to readme * Lock private APIs * Fix missing React error in test file Due to "moduleResolution": "bundler" tsconfig in this package * Remove test for now (requires jest 30) * Remove Storybook for now (punt to follow-up) * Remove build scripts to bin * Move to prebuild folder * Lint all prebuild files * Move `design-tokens.ts` file to prebuild folder * Fixup * Prebuild as part of root build process * Try resolving floating point differences * Update readme * Remove layers from stylesheet * Reduce color ramp tests * Move prebuild files into src (fixes types) * Allow theme package to participate in private APIs * Output combined stylesheet * Rename prebuild to prebuilt --------- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org>
1 parent 4d30918 commit 00b71c5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+8569
-10
lines changed

.eslintrc.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ const developmentFiles = [
1414
'**/@(__mocks__|__tests__|test)/**/*.[tj]s?(x)',
1515
'**/@(storybook|stories)/**/*.[tj]s?(x)',
1616
'packages/babel-preset-default/bin/**/*.js',
17+
'packages/theme/bin/**/*.[tj]s?(x)',
18+
'packages/theme/terrazzo.config.ts',
1719
];
1820

1921
// All files from packages that have types provided with TypeScript.
@@ -430,7 +432,12 @@ module.exports = {
430432
},
431433
},
432434
{
433-
files: [ 'bin/**/*.js', 'bin/**/*.mjs', 'packages/env/**' ],
435+
files: [
436+
'bin/**/*.js',
437+
'bin/**/*.mjs',
438+
'packages/env/**',
439+
'packages/theme/bin/**/*.[tj]s?(x)',
440+
],
434441
rules: {
435442
'no-console': 'off',
436443
},

bin/packages/build.mjs

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import chokidar from 'chokidar';
1616
import browserslistToEsbuild from 'browserslist-to-esbuild';
1717
import { sassPlugin } from 'esbuild-sass-plugin';
1818
import postcss from 'postcss';
19+
import postcssModulesPlugin from 'postcss-modules';
1920
import autoprefixer from 'autoprefixer';
2021
import rtlcss from 'rtlcss';
2122
import cssnano from 'cssnano';
@@ -870,8 +871,10 @@ async function transpilePackage( packageName ) {
870871

871872
/**
872873
* Compile styles for a single package.
873-
* Discovers and compiles SCSS entry points based on package configuration.
874-
* Supports wpStyleEntryPoints in package.json for custom entry point patterns.
874+
*
875+
* Discovers and compiles SCSS entry points based on package configuration
876+
* (supporting wpStyleEntryPoints in package.json for custom entry point patterns),
877+
* and all .module.css files in src/ directory.
875878
*
876879
* @param {string} packageName Package name.
877880
* @return {Promise<number|null>} Build time in milliseconds, or null if no styles.
@@ -881,27 +884,93 @@ async function compileStyles( packageName ) {
881884
const packageJsonPath = path.join( packageDir, 'package.json' );
882885
const packageJson = JSON.parse( await readFile( packageJsonPath, 'utf8' ) );
883886

884-
// Get entry point patterns from package.json, default to root-level only
885-
const entryPointPatterns = packageJson.wpStyleEntryPoints || [
887+
// Get SCSS entry point patterns from package.json, default to root-level only
888+
const scssEntryPointPatterns = packageJson.wpStyleEntryPoints || [
886889
'src/*.scss',
887890
];
888891

889-
const styleEntries = await glob(
890-
entryPointPatterns.map( ( pattern ) =>
892+
// Find all matching SCSS files
893+
const scssEntries = await glob(
894+
scssEntryPointPatterns.map( ( pattern ) =>
891895
normalizePath( path.join( packageDir, pattern ) )
892896
)
893897
);
894898

895-
if ( styleEntries.length === 0 ) {
899+
// Get CSS modules from anywhere in src/
900+
const cssModuleEntries = await glob(
901+
normalizePath( path.join( packageDir, 'src/**/*.module.css' ) ),
902+
{ ignore: IGNORE_PATTERNS }
903+
);
904+
905+
if ( scssEntries.length === 0 && cssModuleEntries.length === 0 ) {
896906
return null;
897907
}
898908

899909
const startTime = Date.now();
900910
const buildStyleDir = path.join( packageDir, 'build-style' );
901911
const srcDir = path.join( packageDir, 'src' );
902912

913+
// Process .module.css files and generate JS modules
914+
const cssResults = await Promise.all(
915+
cssModuleEntries.map( async ( styleEntryPath ) => {
916+
const buildDir = path.join( packageDir, 'build' );
917+
const buildModuleDir = path.join( packageDir, 'build-module' );
918+
919+
const cssContent = await readFile( styleEntryPath, 'utf8' );
920+
const relativePath = path.relative( srcDir, styleEntryPath );
921+
922+
let mappings = {};
923+
const result = await postcss( [
924+
postcssModulesPlugin( {
925+
getJSON: ( _, json ) => ( mappings = json ),
926+
} ),
927+
] ).process( cssContent, { from: styleEntryPath } );
928+
929+
// Write processed CSS to build-style (preserving directory structure)
930+
const cssOutPath = path.join(
931+
buildStyleDir,
932+
relativePath.replace( '.module.css', '.css' )
933+
);
934+
await mkdir( path.dirname( cssOutPath ), { recursive: true } );
935+
await writeFile( cssOutPath, result.css );
936+
937+
// Generate JS modules with class name mappings (preserving directory structure)
938+
const jsExport = JSON.stringify( mappings );
939+
const jsPath = `${ relativePath }.js`;
940+
await Promise.all( [
941+
mkdir( path.dirname( path.join( buildDir, jsPath ) ), {
942+
recursive: true,
943+
} ),
944+
mkdir( path.dirname( path.join( buildModuleDir, jsPath ) ), {
945+
recursive: true,
946+
} ),
947+
] );
948+
await Promise.all( [
949+
writeFile(
950+
path.join( buildDir, jsPath ),
951+
`"use strict";\nmodule.exports = ${ jsExport };\n`
952+
),
953+
writeFile(
954+
path.join( buildModuleDir, jsPath ),
955+
`export default ${ jsExport };\n`
956+
),
957+
] );
958+
959+
// Return the processed CSS for combining
960+
return result.css;
961+
} )
962+
);
963+
964+
// Generate combined stylesheet from all CSS modules
965+
if ( cssResults.length > 0 ) {
966+
const combinedCss = cssResults.join( '\n' );
967+
await mkdir( buildStyleDir, { recursive: true } );
968+
await writeFile( path.join( buildStyleDir, 'style.css' ), combinedCss );
969+
}
970+
971+
// Process SCSS files
903972
await Promise.all(
904-
styleEntries.map( async ( styleEntryPath ) => {
973+
scssEntries.map( async ( styleEntryPath ) => {
905974
// Calculate relative path from src/ to preserve directory structure
906975
const relativePath = path.relative( srcDir, styleEntryPath );
907976
const relativeDir = path.dirname( relativePath );

docs/manifest.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,6 +1985,12 @@
19851985
"markdown_source": "../packages/sync/README.md",
19861986
"parent": "packages"
19871987
},
1988+
{
1989+
"title": "@wordpress/theme",
1990+
"slug": "packages-theme",
1991+
"markdown_source": "../packages/theme/README.md",
1992+
"parent": "packages"
1993+
},
19881994
{
19891995
"title": "@wordpress/token-list",
19901996
"slug": "packages-token-list",

0 commit comments

Comments
 (0)