Gathering detailed insights and metrics for @poupe/css
Gathering detailed insights and metrics for @poupe/css
Gathering detailed insights and metrics for @poupe/css
Gathering detailed insights and metrics for @poupe/css
npm install @poupe/css
Typescript
Module System
Min. Node Version
Node Version
NPM Version
73.6
Supply Chain
98.9
Quality
90.4
Maintenance
100
Vulnerability
100
License
TypeScript (75.04%)
CSS (17.24%)
Vue (6.86%)
HTML (0.5%)
JavaScript (0.23%)
Shell (0.13%)
Total Downloads
885
Last Day
95
Last Week
420
Last Month
885
Last Year
885
MIT License
2 Stars
1,214 Commits
1 Forks
1 Watchers
22 Branches
2 Contributors
Updated on Jun 21, 2025
Minified
Minified + Gzipped
Latest Version
0.3.1
Package Id
@poupe/css@0.3.1
Unpacked Size
115.59 kB
Size
25.88 kB
File Count
7
NPM Version
11.4.1
Node Version
22.16.0
Published on
Jun 10, 2025
Cumulative downloads
Total Downloads
Last Day
533.3%
95
Compared to previous day
Last Week
445.5%
420
Compared to previous week
Last Month
0%
885
Compared to previous month
Last Year
0%
885
Compared to previous year
1
A TypeScript utility library for CSS property manipulation, formatting, and CSS-in-JS operations.
1npm install -D @poupe/css
1yarn add -D @poupe/css
1pnpm add -D @poupe/css
The library exports several categories of utilities:
CSSValue
Represents a valid CSS property value:
1type CSSValue = string | number | (string | number)[];
CSSProperties<K extends string = string>
A typed record of CSS properties:
1type CSSProperties<K extends string = string> = Record<K, CSSValue>;
CSSPropertiesOptions
Configuration options for CSS properties stringification:
1type CSSPropertiesOptions = { 2 /** Indentation string, defaults to two spaces. */ 3 indent?: string 4 /** Prefix string added before each line, defaults to empty string. */ 5 prefix?: string 6 /** New line character, defaults to LF. */ 7 newLine?: string 8 /** Whether to format output on a single line, defaults to false. */ 9 inline?: boolean 10 /** Max properties to format on a single line, defaults to 1. */ 11 singleLineThreshold?: number 12}
CSSRules
Represents a structured CSS rule set that can contain nested rules:
1type CSSRules = { 2 [name: string]: null | string | string[] | CSSRules | CSSRules[] 3};
CSSRuleObject
A more restrictive subset of CSSRules that is compatible with TailwindCSS plugin API:
1type CSSRuleObject = { 2 [key: string]: string | string[] | CSSRuleObject 3};
CSSRulesFormatOptions
Configuration options for formatting CSS rules:
1interface CSSRulesFormatOptions { 2 /** Indentation string for each level of nesting, defaults to two spaces. */ 3 indent?: string 4 /** Prefix string added before each line, defaults to empty string. */ 5 prefix?: string 6 /** Optional validation function to determine which rules to include. */ 7 valid?: (key: string, value: CSSRulesValue) => boolean 8 /** Whether to normalize CSS property names from camelCase to kebab-case. */ 9 normalizeProperties?: boolean 10}
stringifyCSSProperties<K extends string>
(object: CSSProperties<K>, options?: CSSPropertiesOptions): string
Converts a CSSProperties object into a formatted CSS string representation
with proper indentation. Property values are intelligently formatted based on
their type and the CSS property name - space-delimited properties (like
margin, padding) use spaces between multiple values, while other properties
use commas.
1import { stringifyCSSProperties } from '@poupe/css'; 2 3const styles = { 4 fontSize: '16px', 5 backgroundColor: 'red', 6 margin: [10, '20px', '30px', '40px'], 7 fontFamily: ['Arial', 'sans-serif'] 8}; 9 10// Default multi-line formatting 11const cssString = stringifyCSSProperties(styles); 12// "{ 13// font-size: 16px; 14// background-color: red; 15// margin: 10 20px 30px 40px; 16// font-family: Arial, sans-serif; 17// }" 18 19// Inline formatting 20const inlineCSS = stringifyCSSProperties(styles, { inline: true }); 21// "{ font-size: 16px; background-color: red; margin: 10 20px 30px 40px; 22// font-family: Arial, sans-serif }"
formatCSSProperties<K extends string>(object: CSSProperties<K>): string[]
Formats a CSS properties object into an array of CSS property strings. Automatically handles deduplication of properties, where later declarations override earlier ones while preserving the original insertion order.
1import { formatCSSProperties } from '@poupe/css'; 2 3const styles = { 4 fontSize: '16px', 5 backgroundColor: 'red', 6 margin: [10, '20px', '30px', '40px'], 7 // Later declarations override earlier ones: 8 backgroundColor: 'blue' 9}; 10 11const cssLines = formatCSSProperties(styles); 12// [ 13// "font-size: 16px", 14// "background-color: blue", // Note: red was overridden by blue 15// "margin: 10, 20px, 30px" 16// ]
formatCSSValue(value: CSSValue, useComma = true): string
Formats a CSS value into a string. If the value is an array:
font-family
)useComma
is set to false
, it uses spaces (appropriate for
properties like margin
or padding
)The function automatically handles quoting strings that contain spaces (except
CSS functions like rgb()
or calc()
), enclosing them in double quotes.
1import { formatCSSValue } from '@poupe/css'; 2 3formatCSSValue('16px'); // "16px" 4formatCSSValue('Open Sans'); // "\"Open Sans\"" 5formatCSSValue([10, '20px', '30px']); // "10, 20px, 30px" (comma-separated) 6formatCSSValue([10, '20px', '30px'], false); // "10 20px 30px" (space-separated) 7formatCSSValue('rgb(255, 0, 0)'); // "rgb(255, 0, 0)" - Not quoted despite 8formatCSSValue('calc(100% - 20px)'); // "calc(100% - 20px)" - Not quoted
properties<K extends string>
(object: CSSProperties<K>): Generator<[K, CSSValue]>
Generates a sequence of valid CSS property key-value pairs from a
CSSProperties object.
Filters out invalid or empty CSS property values.
1import { properties } from '@poupe/css'; 2 3const styles = { 4 fontSize: '16px', 5 backgroundColor: 'red', 6 _private: 'hidden', 7 empty: '' 8}; 9 10// Iterate through valid properties only 11for (const [key, value] of properties(styles)) { 12 console.log(`${key}: ${value}`); 13} 14// Output: 15// fontSize: 16px 16// backgroundColor: red
stringifyCSSRules(rules: CSSRules | CSSRuleObject, options?): string
Converts a CSS rule object into a formatted string representation with proper indentation and nesting.
1import { stringifyCSSRules } from '@poupe/css'; 2 3const rules = { 4 'body': { 5 'color': 'red', 6 'font-size': '16px', 7 '@media (max-width: 768px)': { 8 'font-size': '14px' 9 } 10 }, 11 '.container': { 12 'max-width': '1200px', 13 'margin': ['0', 'auto'] 14 } 15}; 16 17const cssString = stringifyCSSRules(rules); 18// Output: 19// body { 20// color: red; 21// font-size: 16px; 22// @media (max-width: 768px) { 23// font-size: 14px; 24// } 25// } 26// .container { 27// max-width: 1200px; 28// margin: 0 auto; 29// }
formatCSSRules(rules: CSSRules | CSSRuleObject, options?): string[]
Processes a CSS rule object and returns an array of strings, where each
string represents a line in the formatted CSS output. Internally uses the
generateCSSRules
generator for memory efficiency.
1import { formatCSSRules } from '@poupe/css'; 2 3const rules = { 4 'body': { 5 'color': 'red', 6 'font-size': '16px' 7 } 8}; 9 10const lines = formatCSSRules(rules); 11// Returns: ['body {', ' color: red;', ' font-size: 16px;', '}'] 12 13// Custom indentation 14const indentedLines = formatCSSRules(rules, { indent: ' ' }); 15// Returns: ['body {', ' color: red;', ' font-size: 16px;', '}'] 16 17// Property name normalization (camelCase to kebab-case) 18const camelRules = { 19 body: { 20 fontSize: '16px', 21 backgroundColor: 'blue', 22 marginTop: '20px' 23 } 24}; 25 26const normalized = formatCSSRules(camelRules, { normalizeProperties: true }); 27// Returns: ['body {', ' font-size: 16px;', ' background-color: blue;', ' margin-top: 20px;', '}'] 28 29// Selectors and at-rules are intelligently preserved 30const complexRules = { 31 fontSize: '18px', // Will be normalized to font-size 32 '.button': { // Selector preserved as-is 33 paddingLeft: '10px' // Will be normalized to padding-left 34 }, 35 '@media print': { // At-rule preserved as-is 36 backgroundColor: 'white' // Will be normalized to background-color 37 } 38}; 39 40const result = formatCSSRules(complexRules, { normalizeProperties: true }); 41// Returns: 42// ['font-size: 18px;', '.button {', ' padding-left: 10px;', '}', '@media print {', ' background-color: white;', '}']
generateCSSRules(rules: CSSRules | CSSRuleObject, options?): Generator<string>
Generator version of formatCSSRules
that yields lines as they're generated.
More memory-efficient for large CSS files as it doesn't build the entire
array in memory.
1import { generateCSSRules } from '@poupe/css'; 2 3const rules = { 4 'body': { 5 'color': 'red', 6 'font-size': '16px' 7 } 8}; 9 10// Use generator for streaming or large files 11for (const line of generateCSSRules(rules)) { 12 console.log(line); 13} 14// Output: 15// body { 16// color: red; 17// font-size: 16px; 18// } 19 20// Or collect all lines (same as formatCSSRules) 21const lines = [...generateCSSRules(rules)];
formatCSSRulesArray
(rules: (string | CSSRules | CSSRuleObject)[], options?): string[]
Formats an array of CSS rules into indented lines recursively. Internally uses
the generateCSSRulesArray
generator for memory efficiency.
1import { formatCSSRulesArray } from '@poupe/css'; 2 3const rulesArray = [ 4 { 'color': 'red' }, 5 { 'font-size': '16px' }, 6 'font-weight: bold', 7 { 8 '@media (max-width: 768px)': { 9 'font-size': '14px' 10 } 11 } 12]; 13 14const lines = formatCSSRulesArray(rulesArray); 15// Returns lines with proper indentation for each rule
generateCSSRulesArray
(rules: (string | CSSRules | CSSRuleObject)[], options?): Generator<string>
Generator version of formatCSSRulesArray
that yields lines as they're
generated. Efficiently handles large arrays of CSS rules without building
the entire result in memory.
1import { generateCSSRulesArray } from '@poupe/css'; 2 3const rulesArray = [ 4 { 'color': 'red' }, 5 '', // Empty string creates blank line 6 { 'font-size': '16px' } 7]; 8 9// Stream through large rule arrays 10for (const line of generateCSSRulesArray(rulesArray)) { 11 process.stdout.write(line + '\n'); 12}
defaultValidCSSRule(key: string, value: CSSRulesValue): boolean
Default validation function that determines if a CSS rule key-value pair should be included in the output. A rule is considered valid if the key is not empty and the value is neither undefined nor null.
1import { defaultValidCSSRule } from '@poupe/css'; 2 3// Use with custom rule validation 4const customValid = (key, value) => { 5 return defaultValidCSSRule(key, value) && !key.startsWith('_'); 6};
interleavedRules(rules: CSSRules[]): CSSRules[]
Interleaves an array of CSS rule objects with empty objects, useful for creating spacing between rule blocks in the output.
1import { interleavedRules } from '@poupe/css'; 2 3const rules = [ 4 { '.button': { color: 'blue' } }, 5 { '.input': { border: '1px solid gray' } } 6]; 7 8const spacedRules = interleavedRules(rules); 9// Returns: 10// [ 11// { '.button': { color: 'blue' } }, 12// {}, // Empty object for spacing 13// { '.input': { border: '1px solid gray' } } 14// ] 15 16// When stringified, this creates an empty line between rule blocks
renameRules(rules: CSSRules, fn: (name: string) => string): CSSRules
Renames the keys in a CSS rules object using the provided function, allowing for advanced selector manipulation.
1import { renameRules } from '@poupe/css'; 2 3const rules = { 4 '.button': { color: 'blue' }, 5 '.input': { border: '1px solid gray' } 6}; 7 8// Add a prefix to all selectors 9const prefixedRules = renameRules(rules, key => `.prefix ${key}`); 10// Returns: 11// { 12// '.prefix .button': { color: 'blue' }, 13// '.prefix .input': { border: '1px solid gray' } 14// } 15 16// Transform selectors to utility classes 17const utilityRules = renameRules(rules, key => `@utility ${key.slice(1)}`); 18// Returns: 19// { 20// '@utility button': { color: 'blue' }, 21// '@utility input': { border: '1px solid gray' } 22// } 23 24// Return falsy from the function to skip/remove a rule 25const filteredRules = renameRules(rules, key => 26 key.includes('button') ? key : null); 27// Returns: 28// { 29// '.button': { color: 'blue' } 30// }
setDeepRule(target, path, object)
Sets a CSS rule object at a specified path within a target object,
merging with existing objects and creating intermediate objects as needed.
This function is overloaded to provide type safety for both general
CSSRules
objects and TailwindCSS-compatible CSSRuleObject
types.
1import { setDeepRule } from '@poupe/css'; 2 3const rules = {}; 4 5// Direct assignment 6setDeepRule(rules, 'button', { color: 'blue' }); 7// Result: { button: { color: 'blue' } } 8 9// Nested assignment 10setDeepRule(rules, ['components', 'button'], { color: 'blue' }); 11// Result: { components: { button: { color: 'blue' } } } 12 13// Merging with existing object (new values take precedence) 14const existingRules = { button: { color: 'red', margin: '5px' } }; 15setDeepRule(existingRules, 'button', { color: 'blue', padding: '10px' }); 16// Result: { button: { color: 'blue', margin: '5px', padding: '10px' } }
getDeepRule(target, path)
Retrieves a CSS rule value from a specified path within a target object.
This function is overloaded to provide type safety for both general
CSSRules
objects and TailwindCSS-compatible CSSRuleObject
types.
1import { getDeepRule } from '@poupe/css'; 2 3const rules = { 4 components: { button: { color: 'blue' } }, 5 utils: ['clearfix', 'sr-only'] 6}; 7 8// Direct access 9getDeepRule(rules, 'utils'); 10// Result: ['clearfix', 'sr-only'] 11 12// Nested access 13getDeepRule(rules, ['components', 'button', 'color']); 14// Result: 'blue' 15 16// Non-existent path 17getDeepRule(rules, ['components', 'header']); 18// Result: undefined 19 20// Root access (empty array) 21getDeepRule(rules, []); 22// Result: { components: { ... }, utils: [...] }
expandSelectorAlias(selector: string, aliases?: Record<string, string>): string
Expands selector aliases into their full forms using built-in or custom aliases.
Built-in aliases include:
'media'
→ '@media (prefers-color-scheme: dark)'
'dark'
→ '@media (prefers-color-scheme: dark)'
'light'
→ '@media (prefers-color-scheme: light)'
'mobile'
→ '@media (max-width: 768px)'
'tablet'
→ '@media (min-width: 769px) and (max-width: 1024px)'
'desktop'
→ '@media (min-width: 1025px)'
1import { expandSelectorAlias } from '@poupe/css'; 2 3// Using built-in aliases 4expandSelectorAlias('media'); // '@media (prefers-color-scheme: dark)' 5expandSelectorAlias('mobile'); // '@media (max-width: 768px)' 6 7// Using custom aliases 8const customAliases = { 9 'print': '@media print', 10 'landscape': '@media (orientation: landscape)' 11}; 12expandSelectorAlias('print', customAliases); // '@media print' 13 14// Non-aliased selectors pass through unchanged 15expandSelectorAlias('.my-class'); // '.my-class'
processCSSSelectors(selectors: string | string[], options?: ProcessCSSSelectorOptions): string[] | undefined
Processes CSS selectors and at-rules, handling both strings and arrays.
Merges consecutive selectors with OR and adds * variants, while keeping
at-rules stacked separately. Returns undefined
if no valid selectors are
found.
1import { processCSSSelectors } from '@poupe/css'; 2 3// Single string selector 4processCSSSelectors('.test'); 5// Result: ['.test, .test *'] 6 7// Array of selectors 8processCSSSelectors(['.dark', '.custom']); 9// Result: ['.dark, .dark *, .custom, .custom *'] 10 11// Comma-separated selectors pass through (when allowCommaPassthrough is true) 12processCSSSelectors('.test, .other'); 13// Result: ['.test, .other'] 14 15// Disable star variants 16processCSSSelectors(['.test1', '.test2'], { addStarVariants: false }); 17// Result: ['.test1, .test2'] 18 19// Use custom aliases 20const customAliases = { 'custom': '@media (min-width: 1200px)' }; 21processCSSSelectors('custom', { aliases: customAliases }); 22// Result: ['@media (min-width: 1200px), @media (min-width: 1200px) *'] 23 24// Mixed selectors and aliases 25processCSSSelectors(['.test', 'mobile'], { addStarVariants: false }); 26// Result: ['.test', '@media (max-width: 768px)'] 27 28// At-rules are kept separate 29processCSSSelectors([ 30 '.dark', 31 '@media (max-width: 768px)', 32 '.mobile' 33]); 34// Result: [ 35// '.dark, .dark *', 36// '@media (max-width: 768px)', 37// '.mobile, .mobile *' 38// ] 39 40// Returns undefined for empty arrays 41processCSSSelectors([]); // undefined 42 43// Alias expansion with single string 44processCSSSelectors('media'); 45// Result: ['@media (prefers-color-scheme: dark), @media (prefers-color-scheme: dark) *'] 46 47// Disable comma pass-through 48processCSSSelectors('.test, .other', { allowCommaPassthrough: false }); 49// Result: ['.test, .other, .test, .other *']
unsafeKeys<T>(object: T): Array<keyof T>
A type-safe wrapper around Object.keys for preserving the object's key types.
keys<T, K extends keyof T>
(object: T, valid?: (key: keyof T) => boolean): Generator<K>
A generator function that yields keys of an object that pass an optional validation function.
1import { keys } from '@poupe/css'; 2 3const obj = { a: 1, b: 2, _private: 3 }; 4 5// Use with default validation (includes all keys) 6for (const key of keys(obj)) { 7 console.log(key); // "a", "b", "_private" 8} 9 10// Use with custom validation 11for (const key of keys(obj, k => !k.startsWith('_'))) { 12 console.log(key); // "a", "b" 13}
pairs<K extends string, T>
(object: Record<K, T>, valid?: (k: K, v: T) => boolean): Generator<[K, T]>
A generator function that yields valid key-value pairs from an object. Allows providing a custom validation function to determine which pairs to include.
1import { pairs } from '@poupe/css'; 2 3const obj = { color: 'red', fontSize: '16px', _private: 'hidden', empty: '' }; 4 5// Use with default validation (excludes keys starting with underscore and 6// null/empty values) 7for (const [key, value] of pairs(obj)) { 8 console.log(`${key}: ${value}`); // "color: red", "fontSize: 16px" 9} 10 11// Use with custom validation 12const customValid = (key: string, value: unknown) => 13 typeof value === 'string' && value.length > 3; 14for (const [key, value] of pairs(obj, customValid)) { 15 console.log(`${key}: ${value}`); // "color: red", "_private: hidden" 16}
defaultValidPair<K extends string, T>(key: K, value: T): boolean
Validates if a key-value pair meets default criteria:
kebabCase(s: string): string
Converts a given string to kebab-case:
1import { kebabCase } from '@poupe/css'; 2 3kebabCase('XMLHttpRequest'); // 'xml-http-request' 4kebabCase('camelCase'); // 'camel-case' 5kebabCase('snake_case'); // 'snake-case' 6kebabCase('WebkitTransition'); // '-webkit-transition'
camelCase(s: string): string
Converts a given string to camelCase:
1import { camelCase } from '@poupe/css'; 2 3camelCase('kebab-case'); // 'kebabCase' 4camelCase('PascalCase'); // 'pascalCase' 5camelCase('snake_case'); // 'snakeCase' 6camelCase('-webkit-transition'); // 'webkitTransition' 7camelCase('HTMLElement'); // 'htmlElement' 8camelCase('BGColor'); // 'bgColor'
1import { kebabCase, camelCase } from '@poupe/css'; 2 3// Kebab-case to camelCase 4const camelProperty = camelCase('background-color'); // 'backgroundColor' 5 6// CamelCase to kebab-case 7const kebabProperty = kebabCase('backgroundColor'); // 'background-color' 8 9// Useful for converting between CSS and JavaScript property names 10const styleObject = { 11 backgroundColor: 'red', 12 fontSize: '16px' 13}; 14 15// Convert to CSS properties 16const cssProperties = Object.entries(styleObject).map( 17 ([key, value]) => `${kebabCase(key)}: ${value};` 18); 19// ['background-color: red;', 'font-size: 16px;']
1import { processCSSSelectors, expandSelectorAlias } from '@poupe/css'; 2 3// Theme-aware selector processing 4const darkModeSelectors = processCSSSelectors(['.dark', 'media']); 5// Result: ['.dark, .dark *', '@media (prefers-color-scheme: dark)'] 6 7// Custom aliases for responsive design 8const customAliases = { 9 'wide': '@media (min-width: 1440px)', 10 'touch': '@media (hover: none) and (pointer: coarse)' 11}; 12 13const responsiveSelectors = processCSSSelectors( 14 ['mobile', 'wide'], 15 { aliases: customAliases } 16); 17// Result: ['@media (max-width: 768px)', '@media (min-width: 1440px)'] 18 19// Expand individual aliases 20expandSelectorAlias('tablet'); 21// '@media (min-width: 769px) and (max-width: 1024px)'
MIT licensed.
No vulnerabilities found.
No security vulnerabilities found.