From ad3a4728bebb1a1d37e6d650b48b8417d7c2d8c2 Mon Sep 17 00:00:00 2001 From: Maxwell Barvian Date: Sun, 26 May 2024 08:12:22 -0500 Subject: [PATCH] Better output for i.e. #23 --- plugin/src/index.ts | 17 ++++++++++++----- plugin/src/util/errors.ts | 16 ++++++++++------ plugin/src/util/expr.ts | 17 +++++++++++------ plugin/tests/text.test.ts | 21 +++++++++++++++++++++ 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/plugin/src/index.ts b/plugin/src/index.ts index acfd8db..0cbd853 100644 --- a/plugin/src/index.ts +++ b/plugin/src/index.ts @@ -80,7 +80,7 @@ function getFluidAPI( if (end === null && DEFAULT) end = DEFAULT try { - const clamp = expr.generate(start, end, context) + const [clamp] = expr.generate(start, end, context) return origFn(clamp, { modifier: null }) // don't pass along the modifier } catch (e) { handle(e, `~${util}`) @@ -106,7 +106,7 @@ function getFluidAPI( if (end === null && DEFAULT) end = DEFAULT try { - const clamp = expr.generate(start, end, context, { negate: true }) + const [clamp] = expr.generate(start, end, context, { negate: true }) return origFn(clamp, { modifier: null }) // don't pass along the modifier } catch (e) { handle(e, `~-${util}`) @@ -216,9 +216,12 @@ const fluidPlugin = (options: PluginOptions = {}, api: PluginAPI) => { // Font size try { - rules['font-size'] = expr.generate(from.fontSize, to.fontSize, context, { + const [clamp, err] = expr.generate(from.fontSize, to.fontSize, context, { type: true }) + rules['font-size'] = clamp + // Don't output anything else if this one failed: + if (err) return rules } catch (e) { handle(e, '~text: Font size') } @@ -228,7 +231,7 @@ const fluidPlugin = (options: PluginOptions = {}, api: PluginAPI) => { rules['line-height'] = from.lineHeight ?? null } else { try { - rules['line-height'] = expr.generate(from.lineHeight, to.lineHeight, context) + rules['line-height'] = expr.generate(from.lineHeight, to.lineHeight, context)[0] } catch (e) { handle(e, '~text: Line height') } @@ -239,7 +242,11 @@ const fluidPlugin = (options: PluginOptions = {}, api: PluginAPI) => { rules['letter-spacing'] = from.letterSpacing ?? null } else { try { - rules['letter-spacing'] = expr.generate(from.letterSpacing, to.letterSpacing, context) + rules['letter-spacing'] = expr.generate( + from.letterSpacing, + to.letterSpacing, + context + )[0] } catch (e) { handle(e, '~text: Letter spacing') } diff --git a/plugin/src/util/errors.ts b/plugin/src/util/errors.ts index 1760fa0..fd56cc1 100644 --- a/plugin/src/util/errors.ts +++ b/plugin/src/util/errors.ts @@ -35,16 +35,20 @@ export class FluidError extends Error { ) { super(message) } + + static fromCode(code: C, ...args: Parameters<(typeof codes)[C]>) { + const fn = codes[code] + + // @ts-expect-error + const message = fn(...args) + + return new this(code, message) + } } export function error( code: C, ...args: Parameters<(typeof codes)[C]> ): never { - const fn = codes[code] - - // @ts-expect-error - const message = fn(...args) - - throw new FluidError(code, message) + throw FluidError.fromCode(code, ...args) } diff --git a/plugin/src/util/expr.ts b/plugin/src/util/expr.ts index c6a49c1..386058b 100644 --- a/plugin/src/util/expr.ts +++ b/plugin/src/util/expr.ts @@ -1,6 +1,6 @@ import { Container } from 'postcss' import { Length, type RawValue } from './css' -import { codes, error } from './errors' +import { FluidError, codes, error } from './errors' import { clamp, precision, toPrecision } from './math' import type { Context } from './context' @@ -51,7 +51,7 @@ export const generate = ( final?: boolean negate?: boolean } = {} -) => { +): [expr: string] | [expr: string, err: FluidError] => { if (!_start) error('missing-start') const start = length(_start, context) if (!start) error('non-length-start', _start as string) @@ -78,11 +78,14 @@ export const generate = ( const comment = ( code?: C, ...args: typeof code extends undefined ? never : Parameters<(typeof codes)[C]> - ) => - `/* ${code ? 'not ' : ''}fluid${type ? ' type' : ''} from ${start.cssText} at ${startBP.cssText} to ${end.cssText} at ${endBP.cssText}${atContainer ? ' (container)' : ''}${ + ): [expr: string] | [expr: string, err: FluidError] => { + const expr = `/* ${code ? 'not ' : ''}fluid${type ? ' type' : ''} from ${start.cssText} at ${startBP.cssText} to ${end.cssText} at ${endBP.cssText}${atContainer ? ' (container)' : ''}${ // @ts-expect-error code ? ': ' + codes[code](...args) : '' } */` + if (code) return [expr, FluidError.fromCode(code, ...args)] + return [expr] + } if (startBP.number === 0) { startBP.unit = endBP.unit @@ -126,7 +129,9 @@ export const generate = ( return (final ? error : comment)('fails-sc-144', endBP) } - return `clamp(${min},${toPrecision(intercept, p)}${unit} + ${toPrecision(slope * 100, p)}${atContainer ? 'cqw' : 'vw'},${max})${comment()}` + return [ + `clamp(${min},${toPrecision(intercept, p)}${unit} + ${toPrecision(slope * 100, p)}${atContainer ? 'cqw' : 'vw'},${max})${comment()}` + ] } export const rewrite = ( @@ -161,7 +166,7 @@ export const rewrite = ( atContainer, type: Boolean(type), final: true - }) + })[0] } ) }) diff --git a/plugin/tests/text.test.ts b/plugin/tests/text.test.ts index 2481334..6582d16 100644 --- a/plugin/tests/text.test.ts +++ b/plugin/tests/text.test.ts @@ -397,3 +397,24 @@ it(`doesn't apply inconsistent letter spacing`, async () => { } `) }) + +it(`outputs nothing if font-size errors`, async () => { + const result = await run({ + content: [ + { + raw: html`
` + } + ], + theme: { + fontSize: { + sm: ['1rem', { lineHeight: '1rem', fontWeight: 600, letterSpacing: '.01rem' }], + lg: ['6rem', { lineHeight: '6rem', fontWeight: 600, letterSpacing: '0.02rem' }] + } + } + }) + expect(result.css).toMatchFormattedCss(css` + .\~text-sm\/lg { + font-size:; /* not fluid type from 1rem at 40rem to 6rem at 96rem: Fails WCAG SC 1.4.4 at i.e. 200rem */ + } + `) +})