[READ-ONLY] Mirror of https://github.com/danielroe/postcss-capsize. PostCSS plugin to inject Capsize font metrics
0

Configure Feed

Select the types of activity you want to include in your feed.

feat: add new split-style `line-gap` syntax

Daniel Roe (Mar 16, 2021, 11:37 PM UTC) 63709397 62c7664b

+125 -37
+14
README.md
··· 64 64 65 65 ## Example 66 66 67 + ### Split syntax 68 + ```css 69 + .test { 70 + line-gap: 10px; 71 + /* both properties below must be declared alongside `line-gap` */ 72 + /* The first matching font-family from your plugin config will be used */ 73 + font-family: 'Gaudy Mono', 'Test Mono', sans-serif; 74 + font-size: 24px; 75 + } 76 + ``` 77 + 78 + ### Combined syntax (deprecated) 67 79 ```css 68 80 .test { 69 81 /* font-metrics: [font-size] [font-family] [line-gap] */ ··· 76 88 .test { 77 89 line-height: 12.4px; 78 90 font-size: 24px; 91 + font-family: 'Gaudy Mono', 'Test Mono', sans-serif; 92 + /* Or, with combined syntax */ 79 93 font-family: Test Mono; 80 94 } 81 95 .test::before {
+62 -25
src/index.ts
··· 58 58 return declareAllOnParent 59 59 } 60 60 61 + type FontConfig = { 62 + size: string 63 + fontFamily: string 64 + gap: string 65 + } 66 + 61 67 const plugin: PluginCreator<PluginOptions> = ctx => { 62 68 /* istanbul ignore next */ 63 69 const { metrics = {} } = ctx || {} ··· 70 76 ')) (?<gap>\\d+)px$' 71 77 ) 72 78 79 + function addCapsizedRules( 80 + fontConfig: FontConfig, 81 + source: Declaration, 82 + helpers: Helpers 83 + ) { 84 + const { size, fontFamily, gap } = fontConfig 85 + const { Declaration, Rule } = helpers 86 + 87 + const declare = useDeclare(source, Declaration) 88 + const declareOnParent = useParentDeclare( 89 + source.parent as Rule, 90 + Declaration, 91 + Rule 92 + ) 93 + 94 + const values = capsize({ 95 + fontMetrics: metrics[fontFamily], 96 + fontSize: Number(size), 97 + lineGap: Number(gap), 98 + }) 99 + 100 + declare({ 101 + lineHeight: values.lineHeight, 102 + }) 103 + 104 + declareOnParent({ 105 + '::before': values['::before'], 106 + '::after': values['::after'], 107 + }) 108 + 109 + source.remove() 110 + } 111 + 73 112 return { 74 113 postcssPlugin: 'postcss-capsize', 75 114 76 115 Declaration: { 77 - 'font-metrics'(declaration, { Declaration, Rule }) { 78 - const { size, family: fontFamily, gap } = 79 - declaration.value.match(matcher)?.groups || {} 116 + 'font-metrics': (declaration, helpers) => { 117 + const { size, family: fontFamily, gap } = declaration.value.match(matcher)?.groups || {} 80 118 81 119 if (!size || !fontFamily || !gap) { 82 - throw new Error( 83 - 'Correct syntax is `font-metrics: 24px serif 4px;`, or [font-size] [font-family] [line-gap]' 84 - ) 120 + throw new Error('Correct syntax is `font-metrics: [font-size]px [font-family] [line-gap]px;') 85 121 } 86 122 87 - const declare = useDeclare(declaration, Declaration) 88 - const declareOnParent = useParentDeclare( 89 - declaration.parent as Rule, 90 - Declaration, 91 - Rule 92 - ) 93 - 94 - const values = capsize({ 95 - fontMetrics: metrics[fontFamily], 96 - fontSize: Number(size), 97 - lineGap: Number(gap), 98 - }) 99 - 123 + const declare = useDeclare(declaration, helpers.Declaration) 124 + 100 125 declare({ 101 126 fontFamily, 102 - fontSize: values.fontSize, 103 - lineHeight: values.lineHeight, 127 + fontSize: `${size}px`, 104 128 }) 105 129 106 - declareOnParent({ 107 - '::before': values['::before'], 108 - '::after': values['::after'], 130 + addCapsizedRules({ size, fontFamily, gap }, declaration, helpers) 131 + }, 132 + 'line-gap': (declaration, helpers) => { 133 + let fontFamily!: string 134 + let size!: string 135 + const gap = (declaration.value.match(/^(\d+)px$/) || [])[1] 136 + 137 + declaration.parent?.walkDecls('font-family', d => { 138 + fontFamily = d.value 139 + .split(',') 140 + .map(val => val.trim().replace(/['"]/g, '')) 141 + .find(val => fontFamilies.includes(val))! 109 142 }) 110 143 111 - declaration.remove() 144 + declaration.parent?.walkDecls('font-size', d => { 145 + size = (d.value.match(/^(\d+)px$/) || [])[1] 146 + }) 147 + 148 + addCapsizedRules({ size, fontFamily, gap }, declaration, helpers) 112 149 }, 113 150 }, 114 151 }
+30 -12
test/index.spec.ts
··· 31 31 ) 32 32 expect(result.css).toMatchSnapshot() 33 33 }) 34 - it('throws an error with invalid declaration', async () => { 35 - let errored = false 36 - try { 37 - await processor.process( 38 - ` 34 + it('renders correct CSS with line-gap syntax', async () => { 35 + const result = await processor.process( 36 + ` 39 37 .test { 40 - font-metrics: Test Mono 10px; 38 + font-family: 'Gaudy Mono', 'Test Mono', sans-serif; 39 + font-size: 24px; 40 + line-gap: 10px; 41 41 }`, 42 - { from: undefined } 43 - ) 44 - } catch { 45 - errored = true 46 - } 47 - expect(errored).toBeTruthy() 42 + { from: undefined } 43 + ) 44 + expect(result.css).toMatchSnapshot() 45 + }) 46 + it('throws an error with invalid declaration', async () => { 47 + const invalidOptions = [ 48 + `.test { font-metrics: Test Mono 10px; }`, 49 + `.test { line-gap: 10rem; }`, 50 + `.test { line-gap: 10px; }`, 51 + `.test { line-gap: 10px; font-size: 10vw; }`, 52 + `.test { line-gap: 10px; font-size: 10px; }`, 53 + ] 54 + await Promise.all(invalidOptions.map(async (css) => { 55 + let errored = false 56 + try { 57 + await processor.process( 58 + css, 59 + { from: undefined } 60 + ) 61 + } catch { 62 + errored = true 63 + } 64 + expect(errored).toBeTruthy() 65 + })) 48 66 }) 49 67 })
+19
test/__snapshots__/index.spec.ts.snap
··· 18 18 display: table; 19 19 }" 20 20 `; 21 + 22 + exports[`plugin renders correct CSS with line-gap syntax 1`] = ` 23 + " 24 + .test { 25 + font-family: 'Gaudy Mono', 'Test Mono', sans-serif; 26 + font-size: 24px; 27 + line-height: 12.4px; 28 + } 29 + .test::after { 30 + content: ''; 31 + margin-top: 0.0417em; 32 + display: table; 33 + } 34 + .test::before { 35 + content: ''; 36 + margin-bottom: -0.4583em; 37 + display: table; 38 + }" 39 + `;