Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ let minified = minify("a {}");
let formatted_mini = format("a {}", { minify: true });
```

## Tab size

For cases where you cannot control the tab size with CSS there is an option to override the default tabbed indentation with N spaces.

```js
import { format } from "@projectwallace/format-css";

let formatted = format("a { color: red; }", {
tab_size: 2
});
```

## Acknowledgements

- Thanks to [CSSTree](https://github.com/csstree/csstree) for providing the necessary parser and the interfaces for our CSS Types (the **bold** elements in the list above)
Expand Down
21 changes: 18 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,22 @@ function lowercase(str) {
/**
* @typedef {Object} Options
* @property {boolean} [minify] Whether to minify the CSS or keep it formatted
* @property {number} [tab_size] Tell the formatter to use N spaces instead of tabs
*
* Format a string of CSS using some simple rules
* @param {string} css The original CSS
* @param {Options} options
* @returns {string} The formatted CSS
*/
export function format(css, { minify = false } = {}) {
export function format(css, {
minify = false,
tab_size = undefined,
} = Object.create(null)) {

if (tab_size !== undefined && Number(tab_size) < 1) {
throw new TypeError('tab_size must be a number greater than 0')
}

/** @type {number[]} */
let comments = []

Expand All @@ -64,10 +73,16 @@ export function format(css, { minify = false } = {}) {
/**
* Indent a string
* @param {number} size
* @returns {string} A string with {size} tabs
* @returns {string} A string with [size] tabs/spaces
*/
function indent(size) {
return minify ? EMPTY_STRING : '\t'.repeat(size)
if (minify) return EMPTY_STRING

if (tab_size) {
return SPACE.repeat(tab_size * size)
}

return '\t'.repeat(size)
}

/** @param {import('css-tree').CssNode} node */
Expand Down
54 changes: 54 additions & 0 deletions test/tab-size.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { suite } from 'uvu'
import * as assert from 'uvu/assert'
import { format } from '../index.js'

let test = suite('Tab Size')

let fixture = `
selector {
color: red;
}
`

test('tab_size: 2', () => {
let actual = format(`
selector {
color: red;
}

@media (min-width: 100px) {
selector {
color: blue;
}
}
`, { tab_size: 2 })
let expected = `selector {
color: red;
}

@media (min-width: 100px) {
selector {
color: blue;
}
}`
assert.equal(actual, expected)
})

test('invalid tab_size: 0', () => {
assert.throws(() => format(fixture, { tab_size: 0 }))
})

test('invalid tab_size: negative', () => {
assert.throws(() => format(fixture, { tab_size: -1 }))
})

test('combine tab_size and minify', () => {
let actual = format(fixture, {
tab_size: 2,
minify: true
})
let expected = `selector{color:red}`
assert.equal(actual, expected)
})

test.run()