diff --git a/README.md b/README.md index 226a6ad..50b09a0 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/index.js b/index.js index 87325e2..5db76b7 100644 --- a/index.js +++ b/index.js @@ -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 = [] @@ -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 */ diff --git a/test/tab-size.js b/test/tab-size.js new file mode 100644 index 0000000..931a4c7 --- /dev/null +++ b/test/tab-size.js @@ -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()