From f7ad0f5d4e6fdccd16df770431321dced77cc887 Mon Sep 17 00:00:00 2001 From: Bart Veneman Date: Fri, 26 Jul 2024 22:20:02 +0200 Subject: [PATCH] install and run prettier --- index.js | 333 +++++++++++++++++++------------------- package-lock.json | 23 +++ package.json | 14 +- test/atrules.test.js | 17 +- test/comments.test.js | 8 +- test/declarations.test.js | 30 ++-- test/minify.test.js | 16 +- test/rules.test.js | 138 ++++++++-------- test/selectors.test.js | 57 +++---- test/test.js | 12 +- test/values.test.js | 57 +++---- 11 files changed, 368 insertions(+), 337 deletions(-) diff --git a/index.js b/index.js index 2ebd52f..cfdd5d0 100644 --- a/index.js +++ b/index.js @@ -1,32 +1,32 @@ // @ts-expect-error Typing of css-tree is incomplete -import parse from "css-tree/parser"; - -const SPACE = " "; -const EMPTY_STRING = ""; -const COLON = ":"; -const SEMICOLON = ";"; -const TYPE_ATRULE = "Atrule"; -const TYPE_RULE = "Rule"; -const TYPE_BLOCK = "Block"; -const TYPE_SELECTORLIST = "SelectorList"; -const TYPE_SELECTOR = "Selector"; -const TYPE_DECLARATION = "Declaration"; -const TYPE_OPERATOR = "Operator"; +import parse from 'css-tree/parser' + +const SPACE = ' ' +const EMPTY_STRING = '' +const COLON = ':' +const SEMICOLON = ';' +const TYPE_ATRULE = 'Atrule' +const TYPE_RULE = 'Rule' +const TYPE_BLOCK = 'Block' +const TYPE_SELECTORLIST = 'SelectorList' +const TYPE_SELECTOR = 'Selector' +const TYPE_DECLARATION = 'Declaration' +const TYPE_OPERATOR = 'Operator' /** * Check if a string contains uppercase characters * @param {string} str */ function is_uppercase(str) { - return /[A-Z]/.test(str); + return /[A-Z]/.test(str) } /** @param {string} str */ function lowercase(str) { if (is_uppercase(str)) { - return str.toLowerCase(); + return str.toLowerCase() } - return str; + return str } /** @@ -45,12 +45,12 @@ export function format(css, { minify = false } = {}) { parseAtrulePrelude: false, parseCustomProperty: true, parseValue: true, - }); + }) - const TAB = minify ? EMPTY_STRING : "\t"; - const NEWLINE = minify ? EMPTY_STRING : "\n"; - const OPTIONAL_SPACE = minify ? EMPTY_STRING : SPACE; - const LAST_SEMICOLON = minify ? EMPTY_STRING : SEMICOLON; + const TAB = minify ? EMPTY_STRING : '\t' + const NEWLINE = minify ? EMPTY_STRING : '\n' + const OPTIONAL_SPACE = minify ? EMPTY_STRING : SPACE + const LAST_SEMICOLON = minify ? EMPTY_STRING : SEMICOLON let indent_level = 0 @@ -60,7 +60,7 @@ export function format(css, { minify = false } = {}) { * @returns A string with {size} tabs */ function indent(size) { - return TAB.repeat(size); + return TAB.repeat(size) } /** @@ -68,12 +68,12 @@ export function format(css, { minify = false } = {}) { * @returns A portion of the CSS */ function substr(node) { - let loc = node.loc; - if (!loc) return EMPTY_STRING; + let loc = node.loc + if (!loc) return EMPTY_STRING - let start = loc.start; - let end = loc.end; - return css.slice(start.offset, end.offset); + let start = loc.start + let end = loc.end + return css.slice(start.offset, end.offset) } /** @@ -81,9 +81,9 @@ export function format(css, { minify = false } = {}) { * @returns A portion of the CSS */ function substr_raw(node) { - let loc = node.loc; - if (!loc) return EMPTY_STRING; - return css.slice(loc.start.offset, loc.end.offset); + let loc = node.loc + if (!loc) return EMPTY_STRING + return css.slice(loc.start.offset, loc.end.offset) } /** @@ -91,22 +91,22 @@ export function format(css, { minify = false } = {}) { * @returns {string} A formatted Rule */ function print_rule(node) { - let buffer; - let prelude = node.prelude; - let block = node.block; + let buffer + let prelude = node.prelude + let block = node.block if (prelude.type === TYPE_SELECTORLIST) { - buffer = print_selectorlist(prelude); + buffer = print_selectorlist(prelude) } else { // In case parsing the selector list fails we'll print it as-is - buffer = print_unknown(prelude, indent_level); + buffer = print_unknown(prelude, indent_level) } if (block.type === TYPE_BLOCK) { - buffer += print_block(block); + buffer += print_block(block) } - return buffer; + return buffer } /** @@ -114,119 +114,119 @@ export function format(css, { minify = false } = {}) { * @returns {string} A formatted SelectorList */ function print_selectorlist(node) { - let buffer = EMPTY_STRING; - let children = node.children; + let buffer = EMPTY_STRING + let children = node.children children.forEach((selector, item) => { if (selector.type === TYPE_SELECTOR) { - buffer += print_selector(selector); + buffer += print_selector(selector) } if (item.next !== null) { - buffer += `,` + NEWLINE; + buffer += `,` + NEWLINE } - }); + }) - return buffer; + return buffer } /** * @param {import('css-tree').Selector|import('css-tree').PseudoClassSelector} node */ function print_simple_selector(node) { - let buffer = EMPTY_STRING; - let children = node.children || []; + let buffer = EMPTY_STRING + let children = node.children || [] children.forEach((child) => { switch (child.type) { - case "Combinator": { + case 'Combinator': { // putting spaces around `child.name` (+ > ~ or ' '), unless the combinator is ' ' - buffer += SPACE; + buffer += SPACE - if (child.name !== " ") { - buffer += child.name + SPACE; + if (child.name !== ' ') { + buffer += child.name + SPACE } - break; + break } - case "PseudoElementSelector": { - buffer += COLON + COLON; - buffer += lowercase(child.name); - break; + case 'PseudoElementSelector': { + buffer += COLON + COLON + buffer += lowercase(child.name) + break } - case "PseudoClassSelector": { - buffer += COLON; + case 'PseudoClassSelector': { + buffer += COLON // Special case for `:before` and `:after` which were used in CSS2 and are usually minified // as `:before` and `:after`, but we want to keep them as `::before` and `::after` - let pseudo = lowercase(child.name); + let pseudo = lowercase(child.name) - if (pseudo === "before" || pseudo === "after") { - buffer += COLON; + if (pseudo === 'before' || pseudo === 'after') { + buffer += COLON } - buffer += pseudo; + buffer += pseudo if (child.children) { - buffer += "(" + print_simple_selector(child) + ")"; + buffer += '(' + print_simple_selector(child) + ')' } - break; + break } case TYPE_SELECTORLIST: { child.children.forEach((grandchild, item) => { if (grandchild.type === TYPE_SELECTOR) { - buffer += print_simple_selector(grandchild); + buffer += print_simple_selector(grandchild) } if (item.next) { - buffer += "," + SPACE; + buffer += ',' + SPACE } - }); - break; + }) + break } - case "Nth": { - let nth = child.nth; + case 'Nth': { + let nth = child.nth if (nth) { - if (nth.type === "AnPlusB") { - let a = nth.a; - let b = nth.b; + if (nth.type === 'AnPlusB') { + let a = nth.a + let b = nth.b if (a !== null) { - buffer += a + "n"; + buffer += a + 'n' } if (a !== null && b !== null) { - buffer += SPACE; + buffer += SPACE } if (b !== null) { // When (1n + x) but not (1n - x) - if (a !== null && !b.startsWith("-")) { - buffer += "+" + SPACE; + if (a !== null && !b.startsWith('-')) { + buffer += '+' + SPACE } - buffer += b; + buffer += b } } else { // For odd/even or maybe other identifiers later on - buffer += substr(nth); + buffer += substr(nth) } } if (child.selector !== null) { // `of .selector` // @ts-expect-error Typing of child.selector is SelectorList, which doesn't seem to be correct - buffer += SPACE + "of" + SPACE + print_simple_selector(child.selector); + buffer += SPACE + 'of' + SPACE + print_simple_selector(child.selector) } - break; + break } default: { - buffer += substr(child); - break; + buffer += substr(child) + break } } - }); + }) - return buffer; + return buffer } /** @@ -234,7 +234,7 @@ export function format(css, { minify = false } = {}) { * @returns {string} A formatted Selector */ function print_selector(node) { - return indent(indent_level) + print_simple_selector(node); + return indent(indent_level) + print_simple_selector(node) } /** @@ -242,55 +242,55 @@ export function format(css, { minify = false } = {}) { * @returns {string} A formatted Block */ function print_block(node) { - let children = node.children; - let buffer = OPTIONAL_SPACE; + let children = node.children + let buffer = OPTIONAL_SPACE if (children.isEmpty) { - return buffer + "{}"; + return buffer + '{}' } - buffer += "{" + NEWLINE; + buffer += '{' + NEWLINE - indent_level++; + indent_level++ children.forEach((child, item) => { if (child.type === TYPE_DECLARATION) { - buffer += print_declaration(child); + buffer += print_declaration(child) if (item.next === null) { - buffer += LAST_SEMICOLON; + buffer += LAST_SEMICOLON } else { - buffer += SEMICOLON; + buffer += SEMICOLON } } else { if (item.prev !== null && item.prev.data.type === TYPE_DECLARATION) { - buffer += NEWLINE; + buffer += NEWLINE } if (child.type === TYPE_RULE) { - buffer += print_rule(child); + buffer += print_rule(child) } else if (child.type === TYPE_ATRULE) { - buffer += print_atrule(child); + buffer += print_atrule(child) } else { - buffer += print_unknown(child, indent_level); + buffer += print_unknown(child, indent_level) } } if (item.next !== null) { - buffer += NEWLINE; + buffer += NEWLINE if (child.type !== TYPE_DECLARATION) { - buffer += NEWLINE; + buffer += NEWLINE } } - }); + }) - indent_level--; + indent_level-- - buffer += NEWLINE; - buffer += indent(indent_level) + "}"; + buffer += NEWLINE + buffer += indent(indent_level) + '}' - return buffer; + return buffer } /** @@ -298,24 +298,24 @@ export function format(css, { minify = false } = {}) { * @returns {string} A formatted Atrule */ function print_atrule(node) { - let buffer = indent(indent_level) + "@"; - let prelude = node.prelude; - let block = node.block; - buffer += lowercase(node.name); + let buffer = indent(indent_level) + '@' + let prelude = node.prelude + let block = node.block + buffer += lowercase(node.name) // @font-face has no prelude if (prelude !== null) { - buffer += SPACE + print_prelude(prelude); + buffer += SPACE + print_prelude(prelude) } if (block === null) { // `@import url(style.css);` has no block, neither does `@layer layer1;` - buffer += SEMICOLON; + buffer += SEMICOLON } else if (block.type === TYPE_BLOCK) { - buffer += print_block(block); + buffer += print_block(block) } - return buffer; + return buffer } /** @@ -327,17 +327,14 @@ export function format(css, { minify = false } = {}) { * @param {import('css-tree').AtrulePrelude | import('css-tree').Raw} node */ function print_prelude(node) { - let buffer = substr(node); + let buffer = substr(node) return buffer - .replace(/\s*([:,])/g, buffer.includes("selector(") ? "$1" : "$1 ") // force whitespace after colon or comma, except inside `selector()` - .replace(/\s*(=>|<=)\s*/g, " $1 ") // force whitespace around => and <= - .replace(/\)([a-zA-Z])/g, ") $1") // force whitespace between closing parenthesis and following text (usually and|or) - .replace( - /(?)(?])(?![<= ])(?![=> ])(?![ =>])/g, - " $1 " - ) - .replace(/\s+/g, SPACE); // collapse multiple whitespaces into one + .replace(/\s*([:,])/g, buffer.includes('selector(') ? '$1' : '$1 ') // force whitespace after colon or comma, except inside `selector()` + .replace(/\s*(=>|<=)\s*/g, ' $1 ') // force whitespace around => and <= + .replace(/\)([a-zA-Z])/g, ') $1') // force whitespace between closing parenthesis and following text (usually and|or) + .replace(/(?)(?])(?![<= ])(?![=> ])(?![ =>])/g, ' $1 ') + .replace(/\s+/g, SPACE) // collapse multiple whitespaces into one } /** @@ -345,65 +342,65 @@ export function format(css, { minify = false } = {}) { * @returns {string} A formatted Declaration */ function print_declaration(node) { - let property = node.property; + let property = node.property // Lowercase the property, unless it's a custom property (starts with --) if (!(property.charCodeAt(0) === 45 && property.charCodeAt(1) === 45)) { // 45 == '-' - property = lowercase(property); + property = lowercase(property) } - let value = print_value(node.value); + let value = print_value(node.value) // Special case for `font` shorthand: remove whitespace around / - if (property === "font") { - value = value.replace(/\s*\/\s*/, "/"); + if (property === 'font') { + value = value.replace(/\s*\/\s*/, '/') } // Hacky: add a space in case of a `space toggle` during minification if (value === EMPTY_STRING && OPTIONAL_SPACE === EMPTY_STRING) { - value += SPACE; + value += SPACE } - return indent(indent_level) + property + COLON + OPTIONAL_SPACE + value; + return indent(indent_level) + property + COLON + OPTIONAL_SPACE + value } /** * @param {import('css-tree').List} children */ function print_list(children) { - let buffer = EMPTY_STRING; + let buffer = EMPTY_STRING children.forEach((node, item) => { - if (node.type === "Identifier") { - buffer += node.name; - } else if (node.type === "Function") { - buffer += print_function(node); - } else if (node.type === "Dimension") { - buffer += print_dimension(node); - } else if (node.type === "Value") { + if (node.type === 'Identifier') { + buffer += node.name + } else if (node.type === 'Function') { + buffer += print_function(node) + } else if (node.type === 'Dimension') { + buffer += print_dimension(node) + } else if (node.type === 'Value') { // Values can be inside var() as fallback // var(--prop, VALUE) - buffer += print_value(node); + buffer += print_value(node) } else if (node.type === TYPE_OPERATOR) { - buffer += print_operator(node); - } else if (node.type === "Parentheses") { - buffer += "(" + print_list(node.children) + ")"; + buffer += print_operator(node) + } else if (node.type === 'Parentheses') { + buffer += '(' + print_list(node.children) + ')' } else { - buffer += substr(node); + buffer += substr(node) } // Add space after the item coming after an operator if (node.type !== TYPE_OPERATOR) { if (item.next !== null) { if (item.next.data.type !== TYPE_OPERATOR) { - buffer += SPACE; + buffer += SPACE } } } - }); + }) - return buffer; + return buffer } /** @@ -411,61 +408,61 @@ export function format(css, { minify = false } = {}) { * @returns {string} A formatted Operator */ function print_operator(node) { - let buffer = EMPTY_STRING; + let buffer = EMPTY_STRING // https://developer.mozilla.org/en-US/docs/Web/CSS/calc#notes // The + and - operators must be surrounded by whitespace // Whitespace around other operators is optional // Trim the operator because CSSTree adds whitespace around it - let operator = node.value.trim(); - let code = operator.charCodeAt(0); + let operator = node.value.trim() + let code = operator.charCodeAt(0) if (code === 43 || code === 45) { // + or - // Add required space before + and - operators - buffer += SPACE; + buffer += SPACE } else if (code !== 44) { // , // Add optional space before operator - buffer += OPTIONAL_SPACE; + buffer += OPTIONAL_SPACE } // FINALLY, render the operator - buffer += operator; + buffer += operator if (code === 43 || code === 45) { // + or - // Add required space after + and - operators - buffer += SPACE; + buffer += SPACE } else { // Add optional space after other operators (like *, /, and ,) - buffer += OPTIONAL_SPACE; + buffer += OPTIONAL_SPACE } - return buffer; + return buffer } /** @param {import('css-tree').Dimension} node */ function print_dimension(node) { - return node.value + lowercase(node.unit); + return node.value + lowercase(node.unit) } /** * @param {import('css-tree').Value | import('css-tree').Raw} node */ function print_value(node) { - if (node.type === "Raw") { - return print_unknown(node, 0); + if (node.type === 'Raw') { + return print_unknown(node, 0) } - return print_list(node.children); + return print_list(node.children) } /** * @param {import('css-tree').FunctionNode} node */ function print_function(node) { - return lowercase(node.name) + "(" + print_list(node.children) + ")"; + return lowercase(node.name) + '(' + print_list(node.children) + ')' } /** @@ -474,7 +471,7 @@ export function format(css, { minify = false } = {}) { * @returns {string} A formatted unknown CSS string */ function print_unknown(node, indent_level) { - return indent(indent_level) + substr_raw(node).trim(); + return indent(indent_level) + substr_raw(node).trim() } /** @@ -482,30 +479,30 @@ export function format(css, { minify = false } = {}) { * @returns {string} A formatted Stylesheet */ function print(node) { - let buffer = EMPTY_STRING; + let buffer = EMPTY_STRING /** @type {import('css-tree').List} */ // @ts-expect-error Property 'children' does not exist on type 'AnPlusB', but we're never using that - let children = node.children; + let children = node.children children.forEach((child, item) => { if (child.type === TYPE_RULE) { - buffer += print_rule(child); + buffer += print_rule(child) } else if (child.type === TYPE_ATRULE) { - buffer += print_atrule(child); + buffer += print_atrule(child) } else { - buffer += print_unknown(child, indent_level); + buffer += print_unknown(child, indent_level) } if (item.next !== null) { - buffer += NEWLINE + NEWLINE; + buffer += NEWLINE + NEWLINE } - }); + }) - return buffer; + return buffer } - return print(ast); + return print(ast) } /** @@ -514,5 +511,5 @@ export function format(css, { minify = false } = {}) { * @returns {string} The minified CSS */ export function minify(css) { - return format(css, { minify: true }); + return format(css, { minify: true }) } diff --git a/package-lock.json b/package-lock.json index 65ae48d..ca53af6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@types/css-tree": "^2.3.4", "c8": "^9.1.0", "oxlint": "^0.2.8", + "prettier": "^3.3.3", "tinybench": "^2.8.0", "typescript": "^5.3.3", "uvu": "^0.5.6", @@ -2453,6 +2454,22 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -4739,6 +4756,12 @@ "source-map-js": "^1.2.0" } }, + "prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true + }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", diff --git a/package.json b/package.json index e883cf9..bb88c30 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "build": "vite build", "test": "c8 --reporter=lcov uvu", "check": "tsc", - "lint": "oxlint -D perf" + "lint": "oxlint -D perf", + "prettier": "prettier --check index.js test/**/*.js" }, "devDependencies": { "@codecov/vite-plugin": "^0.0.1-beta.8", @@ -25,6 +26,7 @@ "@types/css-tree": "^2.3.4", "c8": "^9.1.0", "oxlint": "^0.2.8", + "prettier": "^3.3.3", "tinybench": "^2.8.0", "typescript": "^5.3.3", "uvu": "^0.5.6", @@ -46,5 +48,11 @@ "prettifier", "pretty", "prettier" - ] -} + ], + "prettier": { + "semi": false, + "useTabs": true, + "printWidth": 140, + "singleQuote": true + } +} \ No newline at end of file diff --git a/test/atrules.test.js b/test/atrules.test.js index 311d987..f6670bf 100644 --- a/test/atrules.test.js +++ b/test/atrules.test.js @@ -61,7 +61,10 @@ test('@media prelude formatting', () => { [`@media (min-width:1000px){}`, `@media (min-width: 1000px) {}`], [`@media (min-width : 1000px) {}`, `@media (min-width: 1000px) {}`], [`@media all and (transform-3d) {}`, `@media all and (transform-3d) {}`], - [`@media only screen and (min-width: 1024px)and (max-width: 1439px), only screen and (min-width: 768px)and (max-width: 1023px) {}`, `@media only screen and (min-width: 1024px) and (max-width: 1439px), only screen and (min-width: 768px) and (max-width: 1023px) {}`], + [ + `@media only screen and (min-width: 1024px)and (max-width: 1439px), only screen and (min-width: 768px)and (max-width: 1023px) {}`, + `@media only screen and (min-width: 1024px) and (max-width: 1439px), only screen and (min-width: 768px) and (max-width: 1023px) {}`, + ], [`@media (min-width: 1024px)or (max-width: 1439px) {}`, `@media (min-width: 1024px) or (max-width: 1439px) {}`], [`@media all and (transform-3d), (-webkit-transform-3d) {}`, `@media all and (transform-3d), (-webkit-transform-3d) {}`], [`@media screen or print {}`, `@media screen or print {}`], @@ -71,8 +74,14 @@ test('@media prelude formatting', () => { [`@layer tbody,thead;`, `@layer tbody, thead;`], [`@supports (display:grid){}`, `@supports (display: grid) {}`], [`@supports (-webkit-appearance: none) {}`, `@supports (-webkit-appearance: none) {}`], - [`@media all and (-moz-images-in-menus:0) and (min-resolution:.001dpcm) {}`, `@media all and (-moz-images-in-menus: 0) and (min-resolution: .001dpcm) {}`], - [`@media all and (-webkit-min-device-pixel-ratio: 10000),not all and (-webkit-min-device-pixel-ratio: 0) {}`, `@media all and (-webkit-min-device-pixel-ratio: 10000), not all and (-webkit-min-device-pixel-ratio: 0) {}`], + [ + `@media all and (-moz-images-in-menus:0) and (min-resolution:.001dpcm) {}`, + `@media all and (-moz-images-in-menus: 0) and (min-resolution: .001dpcm) {}`, + ], + [ + `@media all and (-webkit-min-device-pixel-ratio: 10000),not all and (-webkit-min-device-pixel-ratio: 0) {}`, + `@media all and (-webkit-min-device-pixel-ratio: 10000), not all and (-webkit-min-device-pixel-ratio: 0) {}`, + ], ['@supports selector([popover]:open) {}', '@supports selector([popover]:open) {}'], ] @@ -246,4 +255,4 @@ test.skip('preserves comments', () => { assert.is(actual, expected) }) -test.run(); \ No newline at end of file +test.run() diff --git a/test/comments.test.js b/test/comments.test.js index be4541f..dcee547 100644 --- a/test/comments.test.js +++ b/test/comments.test.js @@ -1,8 +1,8 @@ -import { suite } from "uvu" -import * as assert from "uvu/assert" -import { format } from "../index.js" +import { suite } from 'uvu' +import * as assert from 'uvu/assert' +import { format } from '../index.js' -let test = suite("Comments") +let test = suite('Comments') test.skip('regular comment before rule', () => { let actual = format(` diff --git a/test/declarations.test.js b/test/declarations.test.js index 6e1b8ef..c2ed7a2 100644 --- a/test/declarations.test.js +++ b/test/declarations.test.js @@ -1,10 +1,10 @@ -import { suite } from "uvu"; -import * as assert from "uvu/assert"; -import { format } from "../index.js"; +import { suite } from 'uvu' +import * as assert from 'uvu/assert' +import { format } from '../index.js' -let test = suite("Declarations"); +let test = suite('Declarations') -test("Declarations end with a semicolon (;)", () => { +test('Declarations end with a semicolon (;)', () => { let actual = format(` @font-face { src: url('test'); @@ -28,7 +28,7 @@ test("Declarations end with a semicolon (;)", () => { } } } - `); + `) let expected = `@font-face { src: url('test'); font-family: Test; @@ -50,18 +50,18 @@ css { property1: value5; } } -}`; +}` - assert.equal(actual, expected); -}); + assert.equal(actual, expected) +}) -test("lowercases properties", () => { - let actual = format(`a { COLOR: green }`); +test('lowercases properties', () => { + let actual = format(`a { COLOR: green }`) let expected = `a { color: green; -}`; - assert.is(actual, expected); -}); +}` + assert.is(actual, expected) +}) test('does not lowercase custom properties', () => { let actual = format(`a { @@ -85,4 +85,4 @@ test.skip('preserves comments', () => { assert.is(actual, expected) }) -test.run(); +test.run() diff --git a/test/minify.test.js b/test/minify.test.js index feaec27..cfc774c 100644 --- a/test/minify.test.js +++ b/test/minify.test.js @@ -1,8 +1,8 @@ -import { suite } from "uvu" -import * as assert from "uvu/assert" -import { minify } from "../index.js" +import { suite } from 'uvu' +import * as assert from 'uvu/assert' +import { minify } from '../index.js' -let test = suite("Minify") +let test = suite('Minify') test('empty rule', () => { let actual = minify(`a {}`) @@ -28,7 +28,7 @@ test('empty atrule', () => { assert.equal(actual, expected) }) -test("formats multiline values on a single line", () => { +test('formats multiline values on a single line', () => { let actual = minify(` a { background: linear-gradient( @@ -36,9 +36,9 @@ a { 10% blue, 20% green,100% yellow); } - `); - let expected = `a{background:linear-gradient(red,10% blue,20% green,100% yellow)}`; - assert.equal(actual, expected); + `) + let expected = `a{background:linear-gradient(red,10% blue,20% green,100% yellow)}` + assert.equal(actual, expected) }) test('correctly minifies operators', () => { diff --git a/test/rules.test.js b/test/rules.test.js index 40175e0..d5ed3a8 100644 --- a/test/rules.test.js +++ b/test/rules.test.js @@ -1,10 +1,10 @@ -import { suite } from "uvu"; -import * as assert from "uvu/assert"; -import { format } from "../index.js"; +import { suite } from 'uvu' +import * as assert from 'uvu/assert' +import { format } from '../index.js' -let test = suite("Rules"); +let test = suite('Rules') -test("AtRules and Rules start on a new line", () => { +test('AtRules and Rules start on a new line', () => { let actual = format(` selector { property: value; } @media (min-width: 1000px) { @@ -14,7 +14,7 @@ test("AtRules and Rules start on a new line", () => { @layer test { selector { property: value; } } - `); + `) let expected = `selector { property: value; } @@ -33,33 +33,33 @@ selector { selector { property: value; } -}`; +}` - assert.equal(actual, expected); -}); + assert.equal(actual, expected) +}) -test("An empty line is rendered in between Rules", () => { +test('An empty line is rendered in between Rules', () => { let actual = format(` rule1 { property: value } rule2 { property: value } - `); + `) let expected = `rule1 { property: value; } rule2 { property: value; -}`; - assert.equal(actual, expected); -}); +}` + assert.equal(actual, expected) +}) -test("single empty line after a rule, before atrule", () => { +test('single empty line after a rule, before atrule', () => { let actual = format(` rule1 { property: value } @media (min-width: 1000px) { rule2 { property: value } } - `); + `) let expected = `rule1 { property: value; } @@ -68,11 +68,11 @@ test("single empty line after a rule, before atrule", () => { rule2 { property: value; } -}`; - assert.equal(actual, expected); -}); +}` + assert.equal(actual, expected) +}) -test("newline between last declaration and nested ruleset", () => { +test('newline between last declaration and nested ruleset', () => { let actual = format(` test { property1: value1; @@ -83,7 +83,7 @@ test("newline between last declaration and nested ruleset", () => { } } } - `); + `) let expected = `test { property1: value1; @@ -94,11 +94,11 @@ test("newline between last declaration and nested ruleset", () => { property3: value3; } } -}`; - assert.equal(actual, expected); -}); +}` + assert.equal(actual, expected) +}) -test("newline between last declaration and nested atrule", () => { +test('newline between last declaration and nested atrule', () => { let actual = format(` test { property1: value1; @@ -106,34 +106,34 @@ test("newline between last declaration and nested atrule", () => { property2: value2; } } - `); + `) let expected = `test { property1: value1; @media all { property2: value2; } -}`; - assert.equal(actual, expected); -}); +}` + assert.equal(actual, expected) +}) -test("no trailing newline on empty nested rule", () => { +test('no trailing newline on empty nested rule', () => { let actual = format(` @layer test { empty {} } - `); + `) let expected = `@layer test { empty {} -}`; - assert.equal(actual, expected); -}); +}` + assert.equal(actual, expected) +}) -test("formats Raw rule prelude", () => { - let actual = format(`:lang("nl","de"),li:nth-child() {}`); - let expected = `:lang("nl","de"),li:nth-child() {}`; // no formatting applied - assert.equal(actual, expected); -}); +test('formats Raw rule prelude', () => { + let actual = format(`:lang("nl","de"),li:nth-child() {}`) + let expected = `:lang("nl","de"),li:nth-child() {}` // no formatting applied + assert.equal(actual, expected) +}) test('formats nested rules with selectors starting with', () => { let actual = format(` @@ -142,17 +142,17 @@ test('formats nested rules with selectors starting with', () => { property: value; } } - `); + `) let expected = `selector { & > item { property: value; } -}`; - assert.equal(actual, expected); +}` + assert.equal(actual, expected) }) test('newlines between declarations, nested rules and more declarations', () => { - let actual = format(`/* test */ a { font: 0/0; & b { color: red; } color: green;}`); + let actual = format(`/* test */ a { font: 0/0; & b { color: red; } color: green;}`) let expected = `a { font: 0/0; @@ -161,11 +161,11 @@ test('newlines between declarations, nested rules and more declarations', () => } color: green; -}`; - assert.equal(actual, expected); +}` + assert.equal(actual, expected) }) -test("formats nested rules with a selector starting with &", () => { +test('formats nested rules with a selector starting with &', () => { let actual = format(` selector { & a { color: red; } @@ -175,8 +175,8 @@ test("formats nested rules with a selector starting with &", () => { & a { color: red; } -}`; - assert.equal(actual, expected); +}` + assert.equal(actual, expected) }) test('formats unknown stuff in curly braces', () => { @@ -187,11 +187,11 @@ test('formats unknown stuff in curly braces', () => { `) let expected = `selector { { color: red; } -}`; - assert.is(actual, expected); +}` + assert.is(actual, expected) }) -test("[check broken test] Relaxed nesting: formats nested rules with a selector with a &", () => { +test('[check broken test] Relaxed nesting: formats nested rules with a selector with a &', () => { let actual = format(` selector { a & { color:red } @@ -199,11 +199,11 @@ test("[check broken test] Relaxed nesting: formats nested rules with a selector `) let expected = `selector { a & { color:red } -}`; - assert.equal(actual, expected); +}` + assert.equal(actual, expected) }) -test.skip("Relaxed nesting: formats nested rules with a selector with a &", () => { +test.skip('Relaxed nesting: formats nested rules with a selector with a &', () => { let actual = format(` selector { a & { color:red } @@ -213,11 +213,11 @@ test.skip("Relaxed nesting: formats nested rules with a selector with a &", () = a & { color: red; } -}`; - assert.equal(actual, expected); +}` + assert.equal(actual, expected) }) -test("[check broken test] Relaxed nesting: formats nested rules with a selector without a &", () => { +test('[check broken test] Relaxed nesting: formats nested rules with a selector without a &', () => { let actual = format(` selector { a { color:red } @@ -225,11 +225,11 @@ test("[check broken test] Relaxed nesting: formats nested rules with a selector `) let expected = `selector { a { color:red } -}`; - assert.equal(actual, expected); +}` + assert.equal(actual, expected) }) -test.skip("Relaxed nesting: formats nested rules with a selector without a &", () => { +test.skip('Relaxed nesting: formats nested rules with a selector without a &', () => { let actual = format(` selector { a { color:red } @@ -239,11 +239,11 @@ test.skip("Relaxed nesting: formats nested rules with a selector without a &", ( a { color: red; } -}`; - assert.equal(actual, expected); +}` + assert.equal(actual, expected) }) -test("[check broken test] Relaxed nesting: formats nested rules with a selector starting with a selector combinator", () => { +test('[check broken test] Relaxed nesting: formats nested rules with a selector starting with a selector combinator', () => { let actual = format(` selector { > a { color:red } @@ -255,11 +255,11 @@ test("[check broken test] Relaxed nesting: formats nested rules with a selector > a { color:red } ~ a { color:red } + a { color:red } -}`; - assert.equal(actual, expected); +}` + assert.equal(actual, expected) }) -test.skip("Relaxed nesting: formats nested rules with a selector starting with a selector combinator", () => { +test.skip('Relaxed nesting: formats nested rules with a selector starting with a selector combinator', () => { let actual = format(` selector { > a { color:red } @@ -279,8 +279,8 @@ test.skip("Relaxed nesting: formats nested rules with a selector starting with a + a { color: red; } -}`; - assert.equal(actual, expected); +}` + assert.equal(actual, expected) }) -test.run(); +test.run() diff --git a/test/selectors.test.js b/test/selectors.test.js index 62d2dab..86d9094 100644 --- a/test/selectors.test.js +++ b/test/selectors.test.js @@ -1,19 +1,17 @@ -import { suite } from "uvu" -import * as assert from "uvu/assert" -import { format } from "../index.js" +import { suite } from 'uvu' +import * as assert from 'uvu/assert' +import { format } from '../index.js' -let test = suite("Selectors") +let test = suite('Selectors') -test("A single selector is rendered without a trailing comma", () => { - let actual = format("a {}") - let expected = "a {}"; +test('A single selector is rendered without a trailing comma', () => { + let actual = format('a {}') + let expected = 'a {}' assert.is(actual, expected) }) -test( - "Multiple selectors are placed on a new line, separated by commas", - () => { - let actual = format(` +test('Multiple selectors are placed on a new line, separated by commas', () => { + let actual = format(` selector1, selector1a, selector1b, @@ -23,18 +21,17 @@ test( selector3 { } `) - let expected = `selector1, + let expected = `selector1, selector1a, selector1b, selector1aa, selector2, -selector3 {}`; +selector3 {}` - assert.equal(actual, expected) - } -) + assert.equal(actual, expected) +}) -test("formats multiline selectors on a single line", () => { +test('formats multiline selectors on a single line', () => { let actual = format(` a.b .c .d @@ -43,11 +40,11 @@ color: green } `) let expected = `a.b .c .d .e .f { color: green; -}`; +}` assert.equal(actual, expected) }) -test("formats simple selector combinators", () => { +test('formats simple selector combinators', () => { let actual = format(` a>b, a>b~c d, @@ -55,17 +52,17 @@ test("formats simple selector combinators", () => { `) let expected = `a > b, a > b ~ c d, -.article-content ol li > * {}`; +.article-content ol li > * {}` assert.equal(actual, expected) }) -test("formats nested selector combinators", () => { +test('formats nested selector combinators', () => { let fixtures = [ [`:where(a+b) {}`, `:where(a + b) {}`], [`:where(:is(ol,ul)) {}`, `:where(:is(ol, ul)) {}`], [`li:nth-of-type(1) {}`, `li:nth-of-type(1) {}`], [`li:nth-of-type(2n) {}`, `li:nth-of-type(2n) {}`], - ]; + ] for (let [css, expected] of fixtures) { let actual = format(css) @@ -111,22 +108,16 @@ d::first-letter {}` assert.equal(actual, expected) }) -test("formats selectors with Nth", () => { +test('formats selectors with Nth', () => { let fixtures = [ [`li:nth-child(3n-2) {}`, `li:nth-child(3n -2) {}`], [`li:nth-child(0n+1) {}`, `li:nth-child(0n + 1) {}`], [`li:nth-child(even of .noted) {}`, `li:nth-child(even of .noted) {}`], [`li:nth-child(2n of .noted) {}`, `li:nth-child(2n of .noted) {}`], [`li:nth-child(-n + 3 of .noted) {}`, `li:nth-child(-1n + 3 of .noted) {}`], - [ - `li:nth-child(-n+3 of li.important) {}`, - `li:nth-child(-1n + 3 of li.important) {}`, - ], - [ - `p:nth-child(n+8):nth-child(-n+15) {}`, - `p:nth-child(1n + 8):nth-child(-1n + 15) {}`, - ], - ]; + [`li:nth-child(-n+3 of li.important) {}`, `li:nth-child(-1n + 3 of li.important) {}`], + [`p:nth-child(n+8):nth-child(-n+15) {}`, `p:nth-child(1n + 8):nth-child(-1n + 15) {}`], + ] for (let [css, expected] of fixtures) { let actual = format(css) @@ -142,7 +133,7 @@ test('formats multiline selectors', () => { c ) {} `) - let expected = `a:is(a, b, c) {}`; + let expected = `a:is(a, b, c) {}` assert.is(actual, expected) }) diff --git a/test/test.js b/test/test.js index d04ab09..9c798ad 100644 --- a/test/test.js +++ b/test/test.js @@ -1,14 +1,14 @@ -import { suite } from "uvu" -import * as assert from "uvu/assert" -import { format } from "../index.js" +import { suite } from 'uvu' +import * as assert from 'uvu/assert' +import { format } from '../index.js' -let test = suite("Stylesheet") +let test = suite('Stylesheet') -test("empty input", () => { +test('empty input', () => { let actual = format(``) let expected = `` assert.equal(actual, expected) -}); +}) test('handles invalid input', () => { let actual = format(`;`) diff --git a/test/values.test.js b/test/values.test.js index ecd91ef..23dae7e 100644 --- a/test/values.test.js +++ b/test/values.test.js @@ -1,8 +1,8 @@ -import { suite } from "uvu"; -import * as assert from "uvu/assert"; -import { format } from "../index.js"; +import { suite } from 'uvu' +import * as assert from 'uvu/assert' +import { format } from '../index.js' -let test = suite("Values"); +let test = suite('Values') test('collapses abundant whitespace', () => { let actual = format(`a { @@ -18,7 +18,7 @@ test('collapses abundant whitespace', () => { assert.is(actual, expected) }) -test("formats simple value lists", () => { +test('formats simple value lists', () => { let actual = format(` a { transition-property: all,opacity; @@ -29,7 +29,7 @@ test("formats simple value lists", () => { content: 'Test'; background-image: url("EXAMPLE.COM"); } - `); + `) let expected = `a { transition-property: all, opacity; transition: all 100ms ease, opacity 10ms 20ms linear; @@ -38,37 +38,37 @@ test("formats simple value lists", () => { color: hsl(0%, 10%, 50%); content: 'Test'; background-image: url("EXAMPLE.COM"); -}`; - assert.equal(actual, expected); -}); +}` + assert.equal(actual, expected) +}) -test("formats nested value lists", () => { +test('formats nested value lists', () => { let actual = format(` a { background: red,linear-gradient(to bottom,red 10%,green 50%,blue 100%); } - `); + `) let expected = `a { background: red, linear-gradient(to bottom, red 10%, green 50%, blue 100%); -}`; - assert.equal(actual, expected); -}); +}` + assert.equal(actual, expected) +}) -test("formats nested var()", () => { +test('formats nested var()', () => { let actual = format(` a { color: var(--test1,var(--test2,green)); color: var(--test3,rgb(0,0,0)); } - `); + `) let expected = `a { color: var(--test1, var(--test2, green)); color: var(--test3, rgb(0, 0, 0)); -}`; - assert.equal(actual, expected); -}); +}` + assert.equal(actual, expected) +}) -test("formats multiline values on a single line", () => { +test('formats multiline values on a single line', () => { let actual = format(` a { background: linear-gradient( @@ -81,13 +81,13 @@ a { 0 ); } - `); + `) let expected = `a { background: linear-gradient(red, 10% blue, 20% green, 100% yellow); color: rgb(0, 0, 0); -}`; - assert.equal(actual, expected); -}); +}` + assert.equal(actual, expected) +}) test('does not break font shorthand', () => { let actual = format(`a { @@ -252,12 +252,15 @@ test('does not break space toggles', () => { }) test('does not break space toggles (minified)', () => { - let actual = format(`a { + let actual = format( + `a { --ON: initial; --OFF: ; - }`, { minify: true }) + }`, + { minify: true }, + ) let expected = `a{--ON:initial;--OFF: }` assert.is(actual, expected) }) -test.run(); +test.run()