This repository has been archived by the owner on Jan 2, 2025. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy path.postcss.custom.js
123 lines (102 loc) · 3.08 KB
/
.postcss.custom.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* eslint-env node */
/* global Set */
const postcss = require( 'postcss' );
/**
* Add custom units for modular scale vertical rhythm values.
*/
module.exports = postcss.plugin( '.postcss.custom.js', ( options )=> {
options = options || {
fontSize: 1,
fontUnit: 'em',
lineHeight: 1.5,
rhythmUnit: 'rem',
ratio: 1.2,
bases: [ 1 ],
round: 5
};
/**
* Calculate a modular scale value.
*
* @param {int} power The power of the modular scale value.
* @param {float} ratio The modular scale ratio.
* @param {array} bases One or more modular scale bases.
* @return {float}
*/
function modularScale( power, ratio, bases ) {
const scale = [];
let step = 0;
while ( Math.abs( step ) <= Math.abs( power ) ) {
for ( let i = 0; i < bases.length; i++ ) {
scale.push( bases[i] * Math.pow( ratio, step ) );
}
step += 1;
if ( 0 > power ) {
step -= 2;
}
}
return Array.from( new Set( scale ) )[Math.abs( step ) - 1];
}
/**
* Calculate a unitless line height for a given modular scale.
*
* @param {float} lineHeight The base, unitless line height.
* @param {int} power The power of the modular scale value.
* @param {float} ratio The modular scale ratio.
* @param {array} bases One or more modular scale bases.
* @return {float}
*/
function lineHeightScale( lineHeight, power, ratio, bases ) {
const baseHeight = lineHeight / modularScale( power, ratio, bases );
let realHeight = baseHeight;
while ( 1 > realHeight ) {
realHeight += baseHeight;
}
return realHeight;
}
return ( root )=> {
root.walkDecls( ( decl )=> {
if ( ':root' !== decl.parent.selector ) {
return;
}
if ( '--font-size' === decl.prop ) {
options.fontSize = parseFloat( decl.value );
options.fontUnit = decl.value.replace( /(\d|\.|-)+/, '' );
} else if ( '--line-height' === decl.prop ) {
options.lineHeight = parseFloat( decl.value );
options.rhythmUnit = decl.value.replace( /(\d|\.|-)+/, '' );
} else if ( '--modular-scale' === decl.prop ) {
const [ ratio, ...bases ] = postcss.list.space( decl.value );
options.ratio = parseFloat( ratio );
options.bases = Array.from( new Set( bases ) ).map( value=> parseFloat( value ) );
if ( ! options.bases.length ) {
options.bases.push( 1 );
}
}
});
root.replaceValues(
/(-?\d*\.?\d+)mfs\b/g,
( value )=> {
const size = modularScale( parseFloat( value ), options.ratio, options.bases ) * options.fontSize;
return size.toFixed( options.round ) + options.fontUnit;
}
);
root.replaceValues(
/(-?\d*\.?\d+)mlh\b/g,
( value )=> {
const height = lineHeightScale( options.lineHeight, parseFloat( value ), options.ratio, options.bases );
return height.toFixed( options.round );
}
);
root.replaceValues(
/(-?\d*\.?\d+)msu\b/g,
value=> modularScale( parseFloat( value ), options.ratio, options.bases ).toFixed( options.round )
);
root.replaceValues(
/(-?\d*\.?\d+)vru\b/g,
( value )=> {
const rhythm = parseFloat( value ) * options.lineHeight;
return rhythm.toFixed( options.round ) + options.rhythmUnit;
}
);
};
});