From 2d3666c9077be00c3b247ef5c7429fefbe85289f Mon Sep 17 00:00:00 2001 From: Tirth Gajjar Date: Sat, 12 Jun 2021 21:07:22 +0530 Subject: [PATCH] added support for sorting variant based classes as well --- package-lock.json | 2 +- package.json | 28 +++++++++++- src/extension.ts | 6 ++- src/utils.ts | 107 ++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 127 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 11fedb8..0bd44e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "headwind", - "version": "1.7.0", + "version": "2.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9273ea2..5b776fe 100755 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "color": "#f1f5f8" }, "icon": "icon.png", - "version": "2.0.0", + "version": "2.1.0", "publisher": "heybourn", "license": "MIT", "author": "Ryan Heybourn ", @@ -54,6 +54,32 @@ { "title": "Headwind", "properties": { + "headwind.defaultVariantSortOrder": { + "type": "array", + "default": [ + "xs", + "sm", + "md", + "lg", + "xl", + "2xl", + "dark", + "first", + "last", + "odd", + "even", + "visited", + "checked", + "group-hover", + "group-focus", + "focus-within", + "hover", + "focus", + "focus-visible", + "active", + "disabled" + ] + }, "headwind.defaultSortOrder": { "type": "array", "default": [ diff --git a/src/extension.ts b/src/extension.ts index b8111f0..c2be448 100755 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,9 +1,9 @@ 'use strict'; -import { commands, workspace, ExtensionContext, Range, window } from 'vscode'; -import { sortClassString, getTextMatch, buildMatchers } from './utils'; import { spawn } from 'child_process'; import { rustyWindPath } from 'rustywind'; +import { commands, ExtensionContext, Range, window, workspace } from 'vscode'; +import { buildMatchers, getTextMatch, sortClassString } from './utils'; export type LangConfig = | string @@ -16,6 +16,7 @@ const langConfig: { [key: string]: LangConfig | LangConfig[] } = config.get('headwind.classRegex') || {}; const sortOrder = config.get('headwind.defaultSortOrder'); +const variantSortOrder = config.get('headwind.defaultVariantSortOrder'); const customTailwindPrefixConfig = config.get('headwind.customTailwindPrefix'); const customTailwindPrefix = @@ -69,6 +70,7 @@ export function activate(context: ExtensionContext) { sortClassString( text, Array.isArray(sortOrder) ? sortOrder : [], + Array.isArray(variantSortOrder) ? variantSortOrder : [], options ) ); diff --git a/src/utils.ts b/src/utils.ts index 04bc54a..e1e1146 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -18,6 +18,7 @@ export interface Options { export const sortClassString = ( classString: string, sortOrder: string[], + variantSortOrder: string[], options: Options ): string => { let classArray = classString.split(options.separator || /\s+/g); @@ -37,28 +38,110 @@ export const sortClassString = ( classArray = sortClassArray( classArray, sortOrderClone, + variantSortOrder, options.shouldPrependCustomClasses ); return classArray.join(options.replacement || ' ').trim(); }; +interface ClassParts { + variants: string[]; + className: string; + original: string; + length: number; +} + +const getClassParts = (className: string) => { + const classParts = className && className.split(':'); + return { + original: className, + length: classParts.length, + variants: + classParts.length > 1 + ? [...classParts.slice(0, classParts.length - 1)] + : [], + className: classParts[classParts.length - 1], + }; +}; + +const sortBasedOnVariants = ( + classArray: string[], + variantSortOrder: string[] +) => { + const classesParted: ClassParts[] = classArray.map(getClassParts); + const maxLength = + classesParted.length > 0 + ? classesParted.sort((a, b) => b.length - a.length)[0].length + : 0; + const sortFunc = (index: number) => { + return (a: ClassParts, b: ClassParts) => { + const aVariant = a.variants.length > index ? a.variants[index] : ''; + const bVariant = b.variants.length > index ? b.variants[index] : ''; + const aVariantPath = + a.variants.length >= index ? a.variants.slice(0, index).join('-') : ''; + const bVariantPath = + b.variants.length >= index ? b.variants.slice(0, index).join('-') : ''; + + if (aVariantPath === bVariantPath) { + return 0; + } + if (aVariant && bVariant) { + return ( + variantSortOrder.indexOf(aVariant) - + variantSortOrder.indexOf(bVariant) + ); + } else if (aVariant) { + return 1; + } else { + // if (bVariant) + return -1; + } + }; + }; + let sortedList = classesParted; + + for (let index = 0; index < maxLength - 1; index++) { + sortedList = sortedList.sort(sortFunc(index)); + } + return sortedList.map((el) => el.original); +}; + const sortClassArray = ( classArray: string[], sortOrder: string[], + variantSortOrder: string[], shouldPrependCustomClasses: boolean -): string[] => [ - ...classArray.filter( - (el) => shouldPrependCustomClasses && sortOrder.indexOf(el) === -1 - ), // append the classes that were not in the sort order if configured this way - ...classArray - .filter((el) => sortOrder.indexOf(el) !== -1) // take the classes that are in the sort order - .sort((a, b) => sortOrder.indexOf(a) - sortOrder.indexOf(b)), // and sort them - ...classArray.filter( - (el) => !shouldPrependCustomClasses && sortOrder.indexOf(el) === -1 - ), // prepend the classes that were not in the sort order if configured this way -]; - +): string[] => { + return [ + ...classArray.filter( + (el) => + shouldPrependCustomClasses && + sortOrder.indexOf(el) === -1 && + sortOrder.indexOf(getClassParts(el).className) === -1 + ), // append the classes that were not in the sort order if configured this way + ...classArray + .filter((el) => { + const className = getClassParts(el).className; + return ( + sortOrder.indexOf(el) !== -1 && + className && + sortOrder.indexOf(className) !== -1 + ); + }) // take the classes that are in the sort order + .sort((a, b) => sortOrder.indexOf(a) - sortOrder.indexOf(b)), // and sort them + ...sortBasedOnVariants( + classArray.filter((el) => getClassParts(el).variants.length > 0), + variantSortOrder + ), // and sort them + ...classArray.filter( + (el) => + !shouldPrependCustomClasses && + sortOrder.indexOf(el) === -1 && + sortOrder.indexOf(getClassParts(el).className) === -1 + ), // prepend the classes that were not in the sort order if configured this way + ]; +}; const removeDuplicates = (classArray: string[]): string[] => [ ...new Set(classArray), ];