Files
xrpl-dev-portal/postcss.config.cjs
Zack Davis abff40b977 Merge xrpl-brand-update-2026 into button-updates
Brings the merged Link component work (PR #3868) plus panelstack and
carousel fixes onto the new Button system.

Conflict resolutions:
- about/{index,history,impact}.page.tsx: keep both branches' imports;
  /about CTAs use the new Button; Link component retained for the
  inline validators links and FAQ markup.
- StandardCard: link color moves to $black/$lilac-500. Required, not
  cosmetic: the branch's $bds-btn-neutral-black no longer exists after
  the Button token system was replaced by $bds-btn-palette.
- Compiled CSS regenerated via npm run build-css rather than resolved
  by hand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 13:00:09 -07:00

175 lines
6.3 KiB
JavaScript

/**
* PostCSS Configuration
*
* Processes compiled Sass output through:
* 1. PurgeCSS - Removes unused CSS selectors
* 2. Autoprefixer - Adds vendor prefixes for browser compatibility
* 3. cssnano - Minifies and optimizes CSS (production only)
*/
const purgecss = require('@fullhuman/postcss-purgecss').default;
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
plugins: [
// Only run PurgeCSS in production or when explicitly enabled
...(isProduction || process.env.PURGECSS === 'true'
? [
purgecss({
// Scan all content files for class names (TSX/TS/HTML = usage; SCSS = BEM modifier definitions)
content: [
'./**/*.tsx',
'./**/*.ts',
'./**/*.md',
'./**/*.yaml',
'./**/*.html',
'./**/*.scss',
'./static/js/**/*.js',
'./static/vendor/**/*.js',
// Ignore node_modules except for specific libraries that inject classes
'!./node_modules/**/*',
],
// Default extractor - looks for class names in content
defaultExtractor: content => {
// Match all words, including those with dashes and numbers
const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || [];
// Match class names in className="..." or class="..."
const classMatches = content.match(/(?:class|className)=["']([^"']*)["']/g) || [];
const classes = classMatches.flatMap(match => {
const m = match.match(/["']([^"']*)["']/);
return m ? m[1].split(/\s+/) : [];
});
// Extract BEM modifier classes from SCSS (e.g. .bds-callout-media-banner--green)
// These are dynamically applied in TSX via template literals so PurgeCSS won't find them as literals
const scssBemMatches = content.match(/\.(bds-[a-z0-9-]+--[a-z0-9-]+)/g) || [];
const bemModifiers = [...new Set(scssBemMatches.map(m => m.replace(/^\./, '')))];
return [...new Set([...broadMatches, ...classes, ...bemModifiers])];
},
// Safelist - classes that should never be removed
safelist: {
// Standard safelist - dynamic state classes
standard: [
'html',
'body',
'light',
'dark',
'show',
'hide',
'active',
'disabled',
'open',
'collapsed',
'collapsing',
'lang-ja', // Japanese language class
/^lang-/, // All language classes
// Common Bootstrap utility patterns that should always be kept
/^container/, // All container classes
/^row$/, // Row class
/^col-/, // Column classes
/^bds-grid__col/, // PageGrid column classes (dynamic span values)
/^bds-grid__offset/, // PageGrid offset classes
// BDS BEM modifier classes - applied dynamically via template literals (e.g. bds-callout-media-banner--green)
// Required: PurgeCSS cannot find these in TSX/SCSS due to interpolation
/^bds-[a-z0-9-]+--/,
// Icon classes. Referenced only from inside the SVG components,
// where PurgeCSS does not look, so nothing here is ever found as
// a literal in the content it scans.
/^bds-icon/,
// RebrandButton - the group/emphasis/context classes are composed
// from props at runtime and emitted from a Sass @each loop, so
// neither side of the build ever contains them as literals
/^rb-btn/,
// XRPL Link classes
/^xrpl-link--/,
/^g-/, // Gap utilities
/^p-/, // Padding utilities
/^m-/, // Margin utilities
/^px-/, /^py-/, /^pt-/, /^pb-/, /^ps-/, /^pe-/, // Directional padding
/^mx-/, /^my-/, /^mt-/, /^mb-/, /^ms-/, /^me-/, // Directional margin
/^d-/, // Display utilities
/^flex-/, // Flexbox utilities
/^justify-/, // Justify content
/^align-/, // Align items
/^w-/, // Width utilities
/^h-/, // Height utilities
/^text-/, // Text utilities
/^bg-/, // Background utilities
/^border/, // Border utilities
/^rounded/, // Border radius
],
// Deep safelist - MINIMAL - only truly dynamic components
deep: [
// Bootstrap JS components (only if actually used with JS)
/dropdown-menu/,
/dropdown-item/,
/modal-backdrop/,
/fade/,
// Third-party libraries
/cm-/,
/CodeMirror/,
/lottie/,
],
// Greedy safelist - VERY MINIMAL
greedy: [
/data-theme/, // Theme switching
],
},
// Reject specific patterns - don't remove these even if not found
rejected: [],
// Variables - keep CSS custom properties
variables: true,
// Keyframes - keep animation keyframes
keyframes: true,
// Font-face rules
fontFace: true,
}),
]
: []),
// Autoprefixer - adds vendor prefixes
autoprefixer({
overrideBrowserslist: [
'>0.2%',
'not dead',
'not op_mini all',
'last 2 versions',
],
}),
// cssnano - minification (production only)
...(isProduction
? [
cssnano({
preset: [
'default',
{
discardComments: {
removeAll: true,
},
normalizeWhitespace: true,
colormin: true,
minifySelectors: true,
},
],
}),
]
: []),
],
};