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
2 changes: 2 additions & 0 deletions javascript/packages/tailwind-class-sorter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
"build": "yarn clean && rollup -c",
"dev": "rollup -c -w",
"clean": "rimraf dist",
"setup-fixtures": "bash scripts/setup-fixtures.sh",
"pretest": "yarn setup-fixtures",
"test": "vitest run",
"test:watch": "vitest --watch",
"prepublishOnly": "yarn clean && yarn build && yarn test"
Expand Down
22 changes: 20 additions & 2 deletions javascript/packages/tailwind-class-sorter/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@ export default [
format: "esm",
sourcemap: true,
},
external: ["tailwindcss", "tailwindcss/loadConfig", "tailwindcss/resolveConfig", "fs/promises", "path", "url"],
external: [
"tailwindcss",
"tailwindcss/loadConfig.js",
"tailwindcss/resolveConfig.js",
"tailwindcss/lib/lib/generateRules.js",
"tailwindcss/lib/lib/setupContextUtils.js",
"fs/promises",
"path",
"url"
],
plugins: [
nodeResolve({ preferBuiltins: true }),
commonjs(),
Expand All @@ -32,7 +41,16 @@ export default [
format: "cjs",
sourcemap: true,
},
external: ["tailwindcss", "tailwindcss/loadConfig", "tailwindcss/resolveConfig", "fs/promises", "path", "url"],
external: [
"tailwindcss",
"tailwindcss/loadConfig.js",
"tailwindcss/resolveConfig.js",
"tailwindcss/lib/lib/generateRules.js",
"tailwindcss/lib/lib/setupContextUtils.js",
"fs/promises",
"path",
"url"
],
plugins: [
nodeResolve({ preferBuiltins: true }),
commonjs(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

set -e

echo "Setting up test fixtures..."

if [ -d "test/fixtures/project-v3" ]; then
echo "Installing dependencies for project-v3..."
cd test/fixtures/project-v3
yarn install --frozen-lockfile --non-interactive
cd ../../..
fi

if [ -d "test/fixtures/project-v4" ]; then
echo "Installing dependencies for project-v4..."
cd test/fixtures/project-v4
yarn install --frozen-lockfile --non-interactive
cd ../../..
fi

echo "Fixture setup complete!"
88 changes: 72 additions & 16 deletions javascript/packages/tailwind-class-sorter/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ import { createJiti, type Jiti } from 'jiti'
import postcss from 'postcss'
// @ts-ignore
import postcssImport from 'postcss-import'
// @ts-ignore
import { generateRules as generateRulesFallback } from 'tailwindcss/lib/lib/generateRules'
// @ts-ignore
import { createContext as createContextFallback } from 'tailwindcss/lib/lib/setupContextUtils'
import loadConfigFallback from 'tailwindcss/loadConfig'
import resolveConfigFallback from 'tailwindcss/resolveConfig'
import type { RequiredConfig } from 'tailwindcss/types/config.js'
import { expiringMap } from './expiring-map.js'
import { resolveCssFrom, resolveJsFrom } from './resolve'
Expand Down Expand Up @@ -84,22 +78,53 @@ async function loadTailwindConfig(
tailwindConfigPath: string | null,
entryPoint: string | null,
): Promise<ContextContainer> {
let createContext = createContextFallback
let generateRules = generateRulesFallback
let resolveConfig = resolveConfigFallback
let loadConfig = loadConfigFallback
let createContext: any
let generateRules: any
let resolveConfig: any
let loadConfig: any
let tailwindConfig: RequiredConfig = { content: [] }

try {
let pkgFile = resolveJsFrom(baseDir, `${pkgName}/package.json`)
let pkgDir = path.dirname(pkgFile)
let pkgPath = resolveJsFrom(baseDir, pkgName)
let pkgJsonPath: string

try {
const Module = require('module')
const requireFromBase = Module.createRequire(path.join(baseDir, 'index.js'))

pkgJsonPath = requireFromBase.resolve(`${pkgName}/package.json`)
} catch {
// Fallback: assume pkgPath is in a subdirectory of the package
// Let's walk up until we find package.json
let currentDir = path.dirname(pkgPath)

while (currentDir !== path.dirname(currentDir)) {
const candidatePkgJson = path.join(currentDir, 'package.json')

try {
require('fs').accessSync(candidatePkgJson)
pkgJsonPath = candidatePkgJson
break
} catch {}

currentDir = path.dirname(currentDir)
}

if (!pkgJsonPath!) {
throw new Error('Could not find Tailwind CSS package.json')
}
}

let pkgDir = path.dirname(pkgJsonPath)

try {
let v4 = await loadV4(baseDir, pkgDir, pkgName, entryPoint)
if (v4) {
return v4
}
} catch {}
} catch (err) {
// V4 loading failed, will try v3 below
}

resolveConfig = require(path.join(pkgDir, 'resolveConfig'))
createContext = require(
Expand All @@ -111,7 +136,9 @@ async function loadTailwindConfig(

// Prior to `tailwindcss@3.3.0` this won't exist so we load it last
loadConfig = require(path.join(pkgDir, 'loadConfig'))
} catch {}
} catch (err: any) {
// Tailwind isn't installed or loading failed, will use defaults
}

if (tailwindConfigPath) {
try {
Expand All @@ -123,10 +150,15 @@ async function loadTailwindConfig(
}
}

// suppress "empty content" warning
if (!resolveConfig || !createContext || !generateRules) {
return {
context: null,
generateRules: null,
}
}

tailwindConfig.content = ['no-op']

// Create the context
let context = createContext(resolveConfig(tailwindConfig))

return {
Expand Down Expand Up @@ -340,5 +372,29 @@ function getEntryPoint(options: SortTailwindClassesOptions, baseDir: string): st
return path.resolve(baseDir, options.tailwindConfig)
}

try {
const commonPaths = [
'app/assets/tailwind/application.css',
'app/assets/stylesheets/application.tailwind.css',
'app/assets/stylesheets/application.css',
'src/styles/tailwind.css',
'src/tailwind.css',
'styles/tailwind.css',
'tailwind.css',
'app.css',
'src/app.css',
]

for (const cssPath of commonPaths) {
const fullPath = path.resolve(baseDir, cssPath)
try {
require('fs').accessSync(fullPath, require('fs').constants.R_OK)
return fullPath
} catch {
// File doesn't exist or isn't readable, continue to next path
}
}
} catch {}

return null
}
8 changes: 8 additions & 0 deletions javascript/packages/tailwind-class-sorter/src/sorting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ function getClassOrderPolyfill(
classes: string[],
{ env }: { env: SortEnv },
): [string, bigint | null][] {
if (!env.context || !env.generateRules) {
return classes.map(name => [name, null] as [string, bigint | null])
}

// A list of utilities that are used by certain Tailwind CSS utilities but
// that don't exist on their own. This will result in them "not existing" and
// sorting could be weird since you still require them in order to make the
Expand Down Expand Up @@ -48,6 +52,10 @@ function getClassOrderPolyfill(
}

function reorderClasses(classList: string[], { env }: { env: SortEnv }) {
if (!env.context) {
return classList.map(name => [name, null] as [string, bigint | null])
}

let orderedClasses = env.context.getClassOrder
? env.context.getClassOrder(classList)
: getClassOrderPolyfill(classList, { env })
Expand Down
12 changes: 6 additions & 6 deletions javascript/packages/tailwind-class-sorter/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ export interface TailwindContext {
}

export interface SortEnv {
context: TailwindContext
generateRules: (
context: TailwindContext | null
generateRules: ((
classes: Iterable<string>,
context: TailwindContext,
) => [bigint][]
) => [bigint][]) | null
options: SortTailwindClassesOptions
}

export interface ContextContainer {
context: any
generateRules: (
context: any | null
generateRules: ((
classes: Iterable<string>,
context: TailwindContext,
) => [bigint][]
) => [bigint][]) | null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "test-fixture-v3",
"private": true,
"dependencies": {
"tailwindcss": "^3.4.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
content: [],
theme: {
extend: {
colors: {
'brand-primary': '#3b82f6',
'brand-secondary': '#10b981',
'neon-pink': '#ff1493',
'accent': {
50: '#f0f9ff',
100: '#e0f2fe',
500: '#06b6d4',
900: '#0c4a6e',
}
}
}
}
}
Loading
Loading