Skip to content

Commit 11ea4fa

Browse files
authored
chore: convert package to typescript (#135)
1 parent 118231d commit 11ea4fa

14 files changed

+721
-401
lines changed

index.js renamed to index.ts

Lines changed: 61 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
1-
// @ts-expect-error Typing of css-tree is incomplete
2-
import parse from 'css-tree/parser'
3-
4-
/**
5-
* @typedef {import('css-tree').CssNode} CssNode
6-
* @typedef {import('css-tree').List<CssNode>} List
7-
* @typedef {import('css-tree').CssLocation} CssLocation
8-
* @typedef {import('css-tree').Raw} Raw
9-
* @typedef {import('css-tree').StyleSheet} StyleSheet
10-
* @typedef {import('css-tree').Atrule} Atrule
11-
* @typedef {import('css-tree').AtrulePrelude} AtrulePrelude
12-
* @typedef {import('css-tree').Rule} Rule
13-
* @typedef {import('css-tree').SelectorList} SelectorList
14-
* @typedef {import('css-tree').Selector} Selector
15-
* @typedef {import('css-tree').PseudoClassSelector} PseudoClassSelector
16-
* @typedef {import('css-tree').PseudoElementSelector} PseudoElementSelector
17-
* @typedef {import('css-tree').Block} Block
18-
* @typedef {import('css-tree').Declaration} Declaration
19-
* @typedef {import('css-tree').Value} Value
20-
* @typedef {import('css-tree').Operator} Operator
21-
*/
1+
import {
2+
parse,
3+
type CssNode,
4+
type List,
5+
type CssLocation,
6+
type Raw,
7+
type StyleSheet,
8+
type Atrule,
9+
type AtrulePrelude,
10+
type Rule,
11+
type SelectorList,
12+
type Selector,
13+
type PseudoClassSelector,
14+
type PseudoElementSelector,
15+
type Block,
16+
type Declaration,
17+
type Value,
18+
type Operator,
19+
} from 'css-tree'
2220

2321
const SPACE = ' '
2422
const EMPTY_STRING = ''
@@ -42,66 +40,51 @@ const TYPE_PSEUDO_ELEMENT_SELECTOR = 'PseudoElementSelector'
4240
const TYPE_DECLARATION = 'Declaration'
4341
const TYPE_OPERATOR = 'Operator'
4442

45-
/** @param {string} str */
46-
function lowercase(str) {
43+
function lowercase(str: string) {
4744
// Only create new strings in memory if we need to
4845
if (/[A-Z]/.test(str)) {
4946
return str.toLowerCase()
5047
}
5148
return str
5249
}
5350

51+
export type FormatOptions = {
52+
/** Whether to minify the CSS or keep it formatted */
53+
minify?: boolean
54+
/** Tell the formatter to use N spaces instead of tabs */
55+
tab_size?: number
56+
}
57+
5458
/**
55-
* @typedef {Object} Options
56-
* @property {boolean} [minify] Whether to minify the CSS or keep it formatted
57-
* @property {number} [tab_size] Tell the formatter to use N spaces instead of tabs
58-
*
5959
* Format a string of CSS using some simple rules
60-
* @param {string} css The original CSS
61-
* @param {Options} [options]
62-
* @returns {string} The formatted CSS
6360
*/
64-
export function format(css, {
65-
minify = false,
66-
tab_size = undefined,
67-
} = Object.create(null)) {
68-
61+
export function format(css: string, { minify = false, tab_size = undefined }: FormatOptions = Object.create(null)): string {
6962
if (tab_size !== undefined && Number(tab_size) < 1) {
7063
throw new TypeError('tab_size must be a number greater than 0')
7164
}
7265

73-
/** @type {number[]} [start0, end0, start1, end1, etc.]*/
74-
let comments = []
66+
/** [start0, end0, start1, end1, etc.]*/
67+
let comments: number[] = []
7568

76-
/**
77-
* @param {string} _ The comment text
78-
* @param {CssLocation} position
79-
*/
80-
function on_comment(_, position) {
69+
function on_comment(_: string, position: CssLocation) {
8170
comments.push(position.start.offset, position.end.offset)
8271
}
8372

84-
/** @type {StyleSheet} */
8573
let ast = parse(css, {
8674
positions: true,
8775
parseAtrulePrelude: false,
8876
parseCustomProperty: true,
8977
parseValue: true,
9078
onComment: on_comment,
91-
})
79+
}) as StyleSheet
9280

9381
const NEWLINE = minify ? EMPTY_STRING : '\n'
9482
const OPTIONAL_SPACE = minify ? EMPTY_STRING : SPACE
9583
const LAST_SEMICOLON = minify ? EMPTY_STRING : SEMICOLON
9684

9785
let indent_level = 0
9886

99-
/**
100-
* Indent a string
101-
* @param {number} size
102-
* @returns {string} A string with [size] tabs/spaces
103-
*/
104-
function indent(size) {
87+
function indent(size: number) {
10588
if (minify === true) return EMPTY_STRING
10689

10790
if (tab_size !== undefined) {
@@ -111,34 +94,29 @@ export function format(css, {
11194
return '\t'.repeat(size)
11295
}
11396

114-
/** @param {CssNode} node */
115-
function substr(node) {
97+
function substr(node: CssNode) {
11698
let loc = node.loc
11799
// If the node has no location, return an empty string
118100
// This is necessary for space toggles
119101
if (loc === undefined || loc === null) return EMPTY_STRING
120102
return css.slice(loc.start.offset, loc.end.offset)
121103
}
122104

123-
/** @param {CssNode} node */
124-
function start_offset(node) {
125-
let loc = /** @type {CssLocation} */(node.loc)
126-
return loc.start.offset
105+
function start_offset(node: CssNode) {
106+
return node.loc?.start.offset
127107
}
128108

129-
/** @param {CssNode} node */
130-
function end_offset(node) {
131-
let loc = /** @type {CssLocation} */(node.loc)
132-
return loc.end.offset
109+
function end_offset(node: CssNode) {
110+
return node.loc?.end.offset
133111
}
134112

135113
/**
136114
* Get a comment from the CSS string after the first offset and before the second offset
137-
* @param {number | undefined} after After which offset to look for comments
138-
* @param {number | undefined} before Before which offset to look for comments
139-
* @returns {string | undefined} The comment string, if found
115+
* @param after After which offset to look for comments
116+
* @param before Before which offset to look for comments
117+
* @returns The comment string, if found
140118
*/
141-
function print_comment(after, before) {
119+
function print_comment(after?: number, before?: number): string | undefined {
142120
if (minify === true || after === undefined || before === undefined) {
143121
return EMPTY_STRING
144122
}
@@ -160,9 +138,8 @@ export function format(css, {
160138
return buffer
161139
}
162140

163-
/** @param {Rule} node */
164-
function print_rule(node) {
165-
let buffer
141+
function print_rule(node: Rule) {
142+
let buffer = ''
166143
let prelude = node.prelude
167144
let block = node.block
168145

@@ -182,8 +159,7 @@ export function format(css, {
182159
return buffer
183160
}
184161

185-
/** @param {SelectorList} node */
186-
function print_selectorlist(node) {
162+
function print_selectorlist(node: SelectorList) {
187163
let buffer = EMPTY_STRING
188164

189165
node.children.forEach((selector, item) => {
@@ -205,12 +181,11 @@ export function format(css, {
205181
return buffer
206182
}
207183

208-
/** @param {Selector | PseudoClassSelector | PseudoElementSelector} node */
209-
function print_simple_selector(node) {
184+
function print_simple_selector(node: Selector | PseudoClassSelector | PseudoElementSelector) {
210185
let buffer = EMPTY_STRING
211-
let children = node.children || []
186+
let children = node.children
212187

213-
children.forEach((child) => {
188+
children?.forEach((child) => {
214189
switch (child.type) {
215190
case 'TypeSelector': {
216191
buffer += lowercase(child.name)
@@ -327,8 +302,7 @@ export function format(css, {
327302
return buffer
328303
}
329304

330-
/** @param {Block} node */
331-
function print_block(node) {
305+
function print_block(node: Block) {
332306
let children = node.children
333307
let buffer = OPTIONAL_SPACE
334308

@@ -348,7 +322,7 @@ export function format(css, {
348322

349323
indent_level++
350324

351-
let opening_comment = print_comment(start_offset(node), start_offset(/** @type {CssNode} */(children.first)))
325+
let opening_comment = print_comment(start_offset(node), start_offset(children.first!))
352326
if (opening_comment) {
353327
buffer += indent(indent_level) + opening_comment + NEWLINE
354328
}
@@ -392,7 +366,7 @@ export function format(css, {
392366
}
393367
})
394368

395-
let closing_comment = print_comment(end_offset(/** @type {CssNode} */(children.last)), end_offset(node))
369+
let closing_comment = print_comment(end_offset(children.last!), end_offset(node))
396370
if (closing_comment) {
397371
buffer += NEWLINE + indent(indent_level) + closing_comment
398372
}
@@ -403,8 +377,7 @@ export function format(css, {
403377
return buffer
404378
}
405379

406-
/** @param {Atrule} node */
407-
function print_atrule(node) {
380+
function print_atrule(node: Atrule) {
408381
let buffer = indent(indent_level) + '@'
409382
let prelude = node.prelude
410383
let block = node.block
@@ -431,9 +404,8 @@ export function format(css, {
431404
* here to force some nice formatting.
432405
* Should be OK perf-wise, since the amount of atrules in most
433406
* stylesheets are limited, so this won't be called too often.
434-
* @param {AtrulePrelude | Raw} node
435407
*/
436-
function print_prelude(node) {
408+
function print_prelude(node: AtrulePrelude | Raw) {
437409
let buffer = substr(node)
438410

439411
return buffer
@@ -447,11 +419,10 @@ export function format(css, {
447419
let space = operator === '+' || operator === '-' ? SPACE : OPTIONAL_SPACE
448420
return `calc(${left.trim()}${space}${operator}${space}${right.trim()})`
449421
})
450-
.replace(/selector|url|supports|layer\(/ig, (match) => lowercase(match)) // lowercase function names
422+
.replace(/selector|url|supports|layer\(/gi, (match) => lowercase(match)) // lowercase function names
451423
}
452424

453-
/** @param {Declaration} node */
454-
function print_declaration(node) {
425+
function print_declaration(node: Declaration) {
455426
let property = node.property
456427

457428
// Lowercase the property, unless it's a custom property (starts with --)
@@ -481,8 +452,7 @@ export function format(css, {
481452
return indent(indent_level) + property + COLON + OPTIONAL_SPACE + value
482453
}
483454

484-
/** @param {List} children */
485-
function print_list(children) {
455+
function print_list(children: List<CssNode>) {
486456
let buffer = EMPTY_STRING
487457

488458
children.forEach((node, item) => {
@@ -519,8 +489,7 @@ export function format(css, {
519489
return buffer
520490
}
521491

522-
/** @param {Operator} node */
523-
function print_operator(node) {
492+
function print_operator(node: Operator) {
524493
let buffer = EMPTY_STRING
525494
// https://developer.mozilla.org/en-US/docs/Web/CSS/calc#notes
526495
// The + and - operators must be surrounded by whitespace
@@ -555,21 +524,15 @@ export function format(css, {
555524
return buffer
556525
}
557526

558-
/** @param {Value | Raw} node */
559-
function print_value(node) {
527+
function print_value(node: Value | Raw) {
560528
if (node.type === 'Raw') {
561529
return print_unknown(node, 0)
562530
}
563531

564532
return print_list(node.children)
565533
}
566534

567-
/**
568-
* @param {CssNode} node
569-
* @param {number} indent_level
570-
* @returns {string} A formatted unknown CSS string
571-
*/
572-
function print_unknown(node, indent_level) {
535+
function print_unknown(node: CssNode, indent_level: number) {
573536
return indent(indent_level) + substr(node).trim()
574537
}
575538

@@ -603,7 +566,7 @@ export function format(css, {
603566
}
604567
})
605568

606-
let closing_comment = print_comment(end_offset(/** @type {CssNode} */(children.last)), end_offset(ast))
569+
let closing_comment = print_comment(end_offset(children.last!), end_offset(ast))
607570
if (closing_comment) {
608571
buffer += NEWLINE + closing_comment
609572
}
@@ -619,6 +582,6 @@ export function format(css, {
619582
* @param {string} css The original CSS
620583
* @returns {string} The minified CSS
621584
*/
622-
export function minify(css) {
585+
export function minify(css: string): string {
623586
return format(css, { minify: true })
624587
}

0 commit comments

Comments
 (0)