Skip to content

Commit

Permalink
feat: complete transformer
Browse files Browse the repository at this point in the history
  • Loading branch information
zyyv committed Nov 7, 2024
1 parent 597fd2e commit dd129bb
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 37 deletions.
45 changes: 33 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,62 @@
<p align="center">
<img src="logo" alt='logo' style="width:100px;" />
</p>
<h1 align="center">unocss-transformer-hash</h1>

<h1 align="center">unocss-transformer-starter</h1>

<p align="center">A Unocss transformer starter template.</p>
<p align="center">A Unocss transformer hash template.</p>

<p align="center">
<a>
<img src="https://img.shields.io/npm/v/unocss-transformer-starter?style=flat&colorA=080f12&colorB=1fa669" alt="npm version" />
<img src="https://img.shields.io/npm/v/unocss-transformer-hash?style=flat&colorA=080f12&colorB=1fa669" alt="npm version" />
</a>
<a>
<img src="https://img.shields.io/npm/dm/unocss-transformer-starter?style=flat&colorA=080f12&colorB=1fa669" alt="npm downloads" />
<img src="https://img.shields.io/npm/dm/unocss-transformer-hash?style=flat&colorA=080f12&colorB=1fa669" alt="npm downloads" />
</a>
<a>
<img src="https://img.shields.io/github/license/unpreset/unocss-transformer-starter.svg?style=flat&colorA=080f12&colorB=1fa669" alt="License" />
<img src="https://img.shields.io/github/license/unpreset/unocss-transformer-hash.svg?style=flat&colorA=080f12&colorB=1fa669" alt="License" />
</a>
</p>

## Install
```shell
pnpm i -D unocss-transformer-starter
pnpm i -D unocss-transformer-hash
```

```ts
// uno.config.ts
import { defineConfig } from 'unocss'
import transformerAlias from 'unocss-transformer-starter'
import transformerHash from 'unocss-transformer-hash'

export default defineConfig({
// ...
transformers: [
transformerAlias(),
transformerHash({
// options
}),
],
})
```

## Usage

```html
<div class="flex items-center justify-center hover:text-red"></div>
```

Will be transformed to:

```html
<div class="222f 7155 a503 sm:hover:5d96"></div>
```

## Options

```ts
export interface TransformerHashOptions {
/**
* Custom hash function
*/
hashfn?: (input: string) => string
}
```

## License

MIT License &copy; 2023-PRESENT [Chris](https://github.com/zyyv)
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
{
"name": "unocss-transformer-starter",
"name": "unocss-transformer-hash",
"type": "module",
"version": "0.0.0",
"packageManager": "[email protected]",
"description": "A Unocss transformer starter template.",
"description": "Unocss transformer to hash class names",
"author": "Chris <https://github.com/zyyv>",
"license": "MIT",
"homepage": "https://github.com/unpreset/unocss-transformer-starter#readme",
"homepage": "https://github.com/unpreset/unocss-transformer-hash#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/unpreset/unocss-transformer-starter.git"
"url": "git+https://github.com/unpreset/unocss-transformer-hash.git"
},
"bugs": {
"url": "https://github.com/unpreset/unocss-transformer-starter/issues"
"url": "https://github.com/unpreset/unocss-transformer-hash/issues"
},
"keywords": [
"unpreset",
Expand Down
2 changes: 1 addition & 1 deletion playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@vitejs/plugin-vue": "^5.1.4",
"typescript": "^5.6.3",
"unocss": "^0.64.0",
"unocss-transformer-starter": "workspace:*",
"unocss-transformer-hash": "workspace:*",
"vite": "^5.4.10",
"vue-tsc": "^2.1.10"
}
Expand Down
10 changes: 8 additions & 2 deletions playground/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<template>
<div>
<h1>Playground</h1>
<p>hello UnoCSS</p>
<div class="flex items-center foo justify-center hover:text-red">
<h1 text-yellow>
Playground
</h1>
<p class="text-purple">
hello UnoCSS
</p>
</div>
</div>
</template>
6 changes: 4 additions & 2 deletions playground/uno.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import {
defineConfig,
presetAttributify,
presetUno,
} from 'unocss'
import transformerStarter from 'unocss-transformer-starter'
import transformerHash from 'unocss-transformer-hash'

export default defineConfig({
presets: [
presetUno(),
presetAttributify(),
],
transformers: [
transformerStarter(),
transformerHash(),
],
})
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 50 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,66 @@
import type MagicString from 'magic-string'
import type { SourceCodeTransformer, UnoGenerator } from 'unocss'
import { createHash } from 'node:crypto'

export interface TransformerStarterOptions {

export interface TransformerHashOptions {
/**
* Custom hash function
*/
hashfn?: (input: string) => string
}

export default function transformerAlias(options?: TransformerStarterOptions): SourceCodeTransformer {
export default function transformerHash(options?: TransformerHashOptions): SourceCodeTransformer {
return {
name: 'unocss-transformer-starter',
name: 'unocss-transformer-hash',
enforce: 'pre',
async transform(code, _, { uno }) {
await transformStarter(code, uno, options)
await transform(code, uno, options)
},
}
}

export async function transformStarter(
export async function transform(
code: MagicString,
uno: UnoGenerator,
// eslint-disable-next-line unused-imports/no-unused-vars
options: TransformerStarterOptions = {},
options: TransformerHashOptions = {},
) {
// Your logic here
code.replace('UnoCSS', 'UnoCSS is awesome')
const { hashfn = getHash } = options
const cache = new Map<string, string>()
const classRegex = /(?:class|className)\s*=\s*[{"'`]([^"'`{}]+)["'`}]/g
const classValueRegex = /\S+/g

for (const match of code.original.matchAll(classRegex)) {
const idx = match.index + match[0].indexOf(match[1])

for (const clsMatch of match[1].matchAll(classValueRegex)) {
const cls = clsMatch[0]
const applied = await uno.matchVariants(cls)
if (!applied || uno.isBlocked(applied[1]))
continue

const currentSelector = applied[1]
const variantOffset = cls.indexOf(currentSelector)

const parsed = await uno.parseToken(currentSelector)
if (!parsed)
continue

const hash = hashfn(cls)
if (cache.get(currentSelector)) {
code.overwrite(idx + clsMatch.index, idx + clsMatch.index + cls.length, cache.get(currentSelector)!)
continue
}

cache.set(currentSelector, hash)
uno.config.shortcuts.push([hash, currentSelector])
code.overwrite(idx + clsMatch.index + variantOffset, idx + clsMatch.index + variantOffset + currentSelector.length, hash)
}
}
}

function getHash(input: string, length = 4) {
return createHash('sha256')
.update(input)
.digest('hex')
.slice(0, length)
}
9 changes: 5 additions & 4 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { UnoGenerator } from 'unocss'
import MagicString from 'magic-string'
import { createGenerator, presetUno } from 'unocss'
import { expect, it } from 'vitest'
import { transformStarter } from '../src'
import { transform } from '../src'

const uno = createGenerator({
presets: [presetUno()],
Expand All @@ -11,14 +11,15 @@ const uno = createGenerator({
function createTransformer() {
return async (code: string, _uno: UnoGenerator = uno) => {
const s = new MagicString(code)
await transformStarter(s, _uno, {})
await transform(s, _uno, {})
return s.toString()
}
}

it('basic', async () => {
const code = `<div attr='bar' class="flex items-center foo justify-center sm:hover:text-red"></div>`

const transform = createTransformer()
const code = `hello UnoCSS`

expect(await transform(code)).toMatchInlineSnapshot(`"hello UnoCSS is awesome"`)
expect(await transform(code)).toMatchInlineSnapshot(`"<div attr='bar' class="222f 7155 foo a503 sm:hover:5d96"></div>"`)
})

0 comments on commit dd129bb

Please sign in to comment.