Skip to content

Commit

Permalink
fix: better rule extraction and bundle twind
Browse files Browse the repository at this point in the history
  • Loading branch information
sastan committed Mar 3, 2021
1 parent f920ea9 commit a271a7d
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 11 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@
"sade": "^1.7.4",
"supports-color": "^8.1.1",
"time-span": "^4.0.0",
"twind": ">=0.15.7",
"v8-compile-cache": "^2.2.0"
},
"peerDependencies": {
"twind": ">=0.15.7",
"typescript": "^4.1.0"
},
"peerDependenciesMeta": {
Expand All @@ -69,7 +69,6 @@
"esbuild-register": "^2.0.0",
"esm": "^3.2.25",
"prettier": "^2.0.5",
"twind": ">=0.15.7",
"typescript": "^4.1.3",
"uvu": "^0.5.1",
"watchlist": "^0.2.3"
Expand Down
2 changes: 1 addition & 1 deletion src/__fixtures__/test.svelte
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<div class:bg-purple-400={true} class="text-white">...</div>
<div class:bg-purple-400={true} class="text-white px-2.5">x-y-</div>
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const cli = (argv = process.argv) =>
.option('-o, --output', 'Set output css file path')
.option('-c, --config', 'Set config file path')
.option('-i, --ignore', 'Any file patterns to ignore')
.option('--ignore-file', 'gitignore like file', '.gitignore')
.option('-I, --ignore-file', 'gitignore like file', '.gitignore')
.option('-b, --beautify', 'Generate beautified css file', false)
.option('-C, --cwd', 'The current directory to resolve from', '.')
.option('-w, --watch', 'Watch for changes', false)
Expand Down
36 changes: 31 additions & 5 deletions src/extract.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,38 @@
import { readFile } from "fs/promises"
import { match } from 'assert'
import { readFile } from 'fs/promises'

function tailwindExtractor(content: string): string[] {
return content.match(/(?=[^\d<>.,;(){}#=%:/@$&])[^<>"'`\s(){}=]{3,}[^<>"'`\s.,;(){}#=%:/@$&]/g) || []
const cleanCandidate = (candidate: string): string => {
// 1. remove leading :class and class:
return candidate.replace(/^:?class:/, '')
}

export const extractRules = async (file: string): Promise<string[]> => {
const COMMON_INVALID_CANDIDATES = new Set(['!DOCTYPE'])

const removeInvalidCandidate = (candidate: string): boolean => {
return !(
COMMON_INVALID_CANDIDATES.has(candidate) ||
// Remove candiate match the following rules
// 1. url like
// 2. non number fractions and decimals
// 3. starting with number like
// 4. ending with -, /, @, $, &
// 5. empty
/^https?:\/\/|^mailto:|^tel:|\D[/.]\D|^[-\d.\/!]+|[-/@$&]$|^\s*$/.test(candidate)
)
}

export const extractRulesFromString = (content: string): string[] => {
return (
// TODO support @sm:..., >sm:..., <sm:...
content.match(/(?![<>"'`\s(){}=:#.,;?\d[\]%/$&])[^<>"'`\s(){}=]+[^<>"'`\s(){}=:#.,;?]/g) || []
)
.map(cleanCandidate)
.filter(removeInvalidCandidate)
}

export const extractRulesFromFile = async (file: string): Promise<string[]> => {
try {
return tailwindExtractor(await readFile(file, {encoding: 'utf-8'}))
return extractRulesFromString(await readFile(file, { encoding: 'utf-8' }))
} catch (error) {
// TODO log error
return []
Expand Down
4 changes: 2 additions & 2 deletions src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { create } from 'twind'
import { virtualSheet } from 'twind/sheets'

import { watch } from './watch'
import { extractRules } from './extract'
import { extractRulesFromFile } from './extract'

const tryLoadConfig = (configFile: string): Configuration => {
try {
Expand Down Expand Up @@ -122,7 +122,7 @@ const run$ = async (globs: string[], options: RunOptions, esbuild: Service): Pro
watchedStats.ino !== stats.ino
) {
pendingDetections.push(
extractRules(file).then((candidates) => {
extractRulesFromFile(file).then((candidates) => {
// console.log({file, candidates})
watched.set(file, stats)
candidatesByFile.set(file, candidates)
Expand Down

0 comments on commit a271a7d

Please sign in to comment.