# core/converters/css.converter.ts

> 33 lines of code and 12 definitions.

Tree: GovLab Quality
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-converters-css-converter-ts
Source text: https://banes-lab.com/source/quality/core/converters/css.converter.ts.txt

Listed in [core/converters](https://banes-lab.com/api/source/quality/core/converters.md), after [core/converters/concern.converter.ts](https://banes-lab.com/source/quality/core/converters/concern.converter.ts.md) and before [core/converters/edit.converter.ts](https://banes-lab.com/source/quality/core/converters/edit.converter.ts.md).

## Definitions

- `numericPrefixEnd` (lexical_declaration, line 4)
- `i` (lexical_declaration, line 5)
- `hasDot` (lexical_declaration, line 6)
- `code` (lexical_declaration, line 8)
- `leadingNumberString` (lexical_declaration, line 21)
- `start` (lexical_declaration, line 22)
- `end` (lexical_declaration, line 23)
- `numStr` (lexical_declaration, line 24)
- `numericPx` (lexical_declaration, line 28, exported)
- `{ numStr, next }` (lexical_declaration, line 29, exported)
- `value` (lexical_declaration, line 30, exported)
- `rest` (lexical_declaration, line 34, exported)

## Contained in

- [core/converters](https://banes-lab.com/anatomy/quality/folder-quality-core-converters.md)

## Uses

- [core/predicates/code-point.predicate.ts](https://banes-lab.com/source/quality/core/predicates/code-point.predicate.ts.md)

## Linked from

- [core/predicates](https://banes-lab.com/anatomy/quality/folder-quality-core-predicates.md)

## Source

```typescript
import { isAsciiDigit, isDot } from "#core/predicates/code-point.predicate";
import { BASE_FONT_PX } from "#configuration/constants/css.constants";

const numericPrefixEnd = function numericPrefixEnd(token: string, start: number): number {
    let i = start;
    let hasDot = false;
    while (i < token.length) {
        const code = token.codePointAt(i);
        if (isAsciiDigit(code)) {
            i += 1;
        } else if (isDot(code) && !hasDot) {
            hasDot = true;
            i += 1;
        } else {
            break;
        }
    }
    return i;
};

const leadingNumberString = function leadingNumberString(token: string): { next: number; numStr: string } {
    const start = token.startsWith("-") ? 1 : 0;
    const end = numericPrefixEnd(token, start);
    const numStr = (start === 1 ? "-" : "") + token.slice(start, end);
    return { next: end, numStr };
};

export const numericPx = function numericPx(token: string): number | null {
    const { numStr, next } = leadingNumberString(token);
    const value = numStr === "" || numStr === "-" ? Number.NaN : Number(numStr);
    if (!Number.isFinite(value)) {
        return null;
    }
    const rest = token.slice(next).trim();
    return rest.startsWith("rem") || rest.startsWith("em") ? value * BASE_FONT_PX : value;
};
```
