Skip to content

Commit

Permalink
fix: multiline class sorting is not supported #161 (PR #221)
Browse files Browse the repository at this point in the history
* fix: respect separators while sorting

fixes issue #161

* test(sort.test.ts): add tests for sorting

* test(sort.test.ts): add tests for malformed HTML

* perf(commands.ts, index.ts): improve sorting

Use new strategy to sort classes and
preserve formatting.

* test(sort.test.ts): use new functions for testing
  • Loading branch information
Diptesh Choudhuri authored Aug 11, 2021
1 parent f03a776 commit 6dc8f22
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 4 deletions.
5 changes: 3 additions & 2 deletions src/lib/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { StyleSheet } from 'windicss/utils/style';

import { Log } from '../utils/console';
import { HTMLParser } from '../utils/parser';
import { sortClassNames } from '../utils';
import { rearrangeClasses, sortClassNames } from '../utils';
import { toggleConfig } from '../utils/helpers';

import type { Processor } from 'windicss/lib';
Expand Down Expand Up @@ -80,7 +80,8 @@ export default class Commands {

for (const p of classes) {
const sortedP = sortClassNames(p.result, variantsMap);
textEdit.replace(new Range(textEditor.document.positionAt(p.start), textEditor.document.positionAt(p.end)), sortedP);
const toReplace = rearrangeClasses(p.result, sortedP);
textEdit.replace(new Range(textEditor.document.positionAt(p.start), textEditor.document.positionAt(p.end)), toReplace);
}
});
}
Expand Down
36 changes: 34 additions & 2 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function connectList<T>(list: T[][]) {

export function sortClassNames(classNames: string, variantsMap: { [key: string]: number }) {
const variantsArray = Object.keys(variantsMap);
const ast = new ClassParser(classNames, ":", variantsArray).parse();
const ast = new ClassParser(classNames, ':', variantsArray).parse();
return ast.map(({ raw, variants, important }) => {
const head = variants.join(':') + ':';
const utility = raw.replace(head, '');
Expand All @@ -45,7 +45,39 @@ export function sortClassNames(classNames: string, variantsMap: { [key: string]:
const offset = variants.map(i => variantsMap[i] * 100).reduce((p, c) => p + c, 0) + (important ? 500 : 0) + (hasDynamicValue ? 25 : 0);
if (key === null) return { raw, weight: offset };
return { raw, weight: (keyOrder[key[0]] ?? 300) + offset };
}).sort((a, b) => a.weight - b.weight).map(i => i.raw).join(' ');
}).sort((a, b) => a.weight - b.weight).map(i => i.raw);
}

function replaceBetweenIndices(
origin: string,
startIndex: number,
endIndex: number,
find: string,
replace: string
) {
return (
origin.substring(0, startIndex) +
origin.substring(startIndex, endIndex).replace(find, replace)
);
}

export function rearrangeClasses(classesText: string, sortedP: string[]) {
const unsortedClasses = classesText
.split(/\s+/)
.map((s) => s.trim())
.filter(Boolean);
let occurrenceIndex = 0;
for (let i = 0; i < sortedP.length; i++) {
classesText = replaceBetweenIndices(
classesText,
occurrenceIndex,
classesText.length,
unsortedClasses[i],
sortedP[i]
);
occurrenceIndex = occurrenceIndex + sortedP[0].length + 1;
}
return classesText;
}

export function rem2px(str?: string) {
Expand Down
79 changes: 79 additions & 0 deletions test/sort.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { HTMLParser } from 'windicss/utils/parser';
import {
sortClassNames,
rearrangeClasses,
} from '../src/utils';

it('sorts classes single line', () => {
const parser = new HTMLParser();
parser.html = `
<div class="p-4 text-transparent bg-transparent backdrop-blur" />
`;
const p = parser.parseClasses()[0];
const expected = 'bg-transparent text-transparent p-4 backdrop-blur';
const sortedP = sortClassNames(p.result, {});
const toReplace = rearrangeClasses(p.result, sortedP);
expect(toReplace).toBe(expected);
});

it('sorts classes single line but malformed', () => {
const parser = new HTMLParser();
parser.html = `
<div class=" p-4 text-transparent bg-transparent backdrop-blur" />
`;
const p = parser.parseClasses()[0];
const expected = ' bg-transparent text-transparent p-4 backdrop-blur';
const sortedP = sortClassNames(p.result, {});
const toReplace = rearrangeClasses(p.result, sortedP);
expect(toReplace).toBe(expected);
});

it('sorts classes multi line', () => {
const parser = new HTMLParser();
parser.html = `
<div
class="
p-4
text-transparent
bg-transparent
backdrop-blur
"
/>
`;
const p = parser.parseClasses()[0];
const expected = `
bg-transparent
text-transparent
p-4
backdrop-blur
`;

const sortedP = sortClassNames(p.result, {});
const toReplace = rearrangeClasses(p.result, sortedP);
expect(toReplace).toBe(expected);
});

it('sorts classes multi line but malformed', () => {
const parser = new HTMLParser();
parser.html = `
<div
class="
p-4
text-transparent
bg-transparent
backdrop-blur
"
/>
`;
const p = parser.parseClasses()[0];
const expected = `
bg-transparent
text-transparent
p-4
backdrop-blur
`;

const sortedP = sortClassNames(p.result, {});
const toReplace = rearrangeClasses(p.result, sortedP);
expect(toReplace).toBe(expected);
});

0 comments on commit 6dc8f22

Please sign in to comment.