Skip to content

Commit

Permalink
fix: skip :class and :hover-class
Browse files Browse the repository at this point in the history
  • Loading branch information
zguolee committed Aug 31, 2022
1 parent ae60e47 commit f1b602b
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 57 deletions.
52 changes: 29 additions & 23 deletions packages/transformer-applet/src/index.ts
Expand Up @@ -3,40 +3,46 @@ import MagicString from 'magic-string'
import type { TransformerAppletOptions } from './types'
import { compileApplet } from './compile'

export default function transformerApplet(options: TransformerAppletOptions = {}): SourceCodeTransformer {
// Regular expression of characters to be escaped
const charReg = /[.:%!#()[\/\],]/
const elementRE = /<\w(?=.*>)[\w:\.$-]*\s(((\&>)|.*?)*?)\/?>/gs
const valuedAttributeRE = /([?]|(?!\d|-{2}|-\d)[a-zA-Z0-9\u00A0-\uFFFF-_:!%-]+)(?:={?(["'])([^\2]*?)\2}?)?/g

// Regular expression of characters to be escaped
const charReg = /[.:%!#()[\/\],]/

const classRE = /:?(hover-)?class=\".*?\"/g
const string1RE = /([']).*?(['])/g
const string2RE = /([\`]).*?([\`])/g
const string1RE = /([']).*?(['])/g
const string2RE = /([\`]).*?([\`])/g

export default function transformerApplet(options: TransformerAppletOptions = {}): SourceCodeTransformer {
return {
name: 'transformer-applet',
enforce: 'pre',
async transform(s, _, ctx) {
const code = new MagicString(s.toString())
// process class
const classMatches = [...code.original.matchAll(classRE)]
for (const match of classMatches) {
// skip `... ? ... : ...`
if (/\?.*:/g.test(match[0]))
continue
let code = new MagicString(s.toString())

// skip `... : ...`
if (/{.+:.+}/g.test(match[0]))
continue
// process class attribute
const elementMatches = code.original.matchAll(elementRE)
for (const eleMatch of elementMatches) {
const start = eleMatch.index!
let matchStrTemp = eleMatch[0]
const valuedAttributes = Array.from((eleMatch[1] || '').matchAll(valuedAttributeRE))

const start = match.index!
const matchSplit = match[0].split('class=')

const body = matchSplit[1].slice(1, -1)
for (const attribute of valuedAttributes) {
// const matchStr = attribute[0]
const name = attribute[1]
const content = attribute[3]

if (charReg.test(body)) {
const replacements = await compileApplet(body, ctx, options)
code.overwrite(start, start + match[0].length, `${matchSplit[0]}class="${replacements.join(' ')}"`)
if (!content)
continue
if (['class', 'className', 'hover-class'].includes(name)) {
if (!name.includes(':')) {
const replacements = await compileApplet(content, ctx, options)
matchStrTemp = matchStrTemp.replace(content, replacements.join(' '))
}
}
}
code.overwrite(start, start + eleMatch[0].length, matchStrTemp)
}
code = new MagicString(code.toString())

// process string1
const string1Matches = [...code.original.matchAll(string1RE)]
Expand Down
12 changes: 8 additions & 4 deletions playground/src/pages/index/index.vue
@@ -1,7 +1,7 @@
<script setup lang="ts">
const bg = 'bg-[hsl(2.7,81.9%,69.6%)]'
const index = 1
const type = 'text'
const customClass = 'text-red'
const bool = true
</script>

Expand All @@ -13,12 +13,12 @@ const bool = true
0123456789
</div>
</div>
<div :class="{ 'bg-blue': bool }" p-2>
class
<div :class="{ 'bg-blue': bool }" p-2 :hover-class="['!bg-green']">
class="hover:bg-green"
</div>
<div class="p-1" :class="bool ? 'text-yellow-500 px-2.5' : ''">
{{ `index${index + 1}` }}
</div>
</div>
<div i-carbon-campsite inline-block color="blue" />
<div flex="~ col gap-2" border="2 blue">
<div text-center w-10 h-10 flex="1" text="red">
Expand All @@ -35,5 +35,9 @@ const bool = true
<div class="m-0.5 p-1 text-2xl" :class="bool ? '' : 'text-yellow-500 p-2.5'">
abckefghijklmnopqrstuvwxyz
</div>
<!-- eslint-disable-next-line vue/prefer-separate-static-class -->
<view :class="['underline', customClass]">
aaa
</view>
</div>
</template>
31 changes: 21 additions & 10 deletions test/fixtures/rules.vue
@@ -1,33 +1,44 @@
<script setup lang="ts">
const bg = 'bg-[hsl(2.7,81.9%,69.6%)]'
const index = 1
const type = 'text'
const customClass = 'text-red'
const bool = true
</script>

<template>
<div class="flex aaa flex-col justify-center items-center">
<div text="green-500 4xl" class="rotate-180 i-carbon-campsite" :class="bool ? bg : ''" />
<div class="border bg-blue-200 px-2 transition-all bg-red-500 font-(light mono)" h20>
<div class="text-green-200/50 hover:(!bg-gray-400 text-white font-medium)">
<div text="4xl" class="rotate-180 i-carbon-campsite" :class="bg" />
<div class="border bg-blue-200 font-(light mono) ">
<div class="hover:(!bg-gray-400 text-white font-medium)" text="#6f4">
0123456789
</div>
</div>
<div class="p-1" :class="bool ? 'text-yellow-500' : ''">
<div :class="{ 'bg-blue': bool }" p-2 :hover-class="['!bg-green']">
class="hover:bg-green"
</div>
<div class="p-1" :class="bool ? 'text-yellow-500 px-2.5' : ''">
{{ `index${index + 1}` }}
</div>
<div class="grid-cols-[0.7fr_repeat(7,1fr)]" flex="~ col">
<div w-10 h-10 flex="1">
<div i-carbon-campsite inline-block color="blue" />
<div flex="~ col gap-2" border="2 blue">
<div text-center w-10 h-10 flex="1" text="red">
1
</div>
<div w-10 h-10 flex="1">
<div w-10 h-10 flex="1" text-blue>
2
</div>
</div>

<button />
<uni-easyinput />
<div class="bg-[url(https://static.runoob.com/images/demo/demo3.jpg)]" w-20 h-10>
bg-img
</div>
<div class="m-0.5 p-1 text-2xl" :class="bool ? '' : 'text-yellow-500 p-2.5'">
abckefghijklmnopqrstuvwxyz
</div>
<!-- eslint-disable-next-line vue/prefer-separate-static-class -->
<view :class="['underline', customClass]">
aaa
</view>
</div>
</template>

60 changes: 40 additions & 20 deletions test/transformer-applet.test.ts
Expand Up @@ -36,54 +36,74 @@ describe('transformer-applet', () => {
"code": "<script setup lang=\\"ts\\">
const bg = 'uno-98db2v'
const index = 1
const type = 'text'
const customClass = 'text-red'
const bool = true
</script>
<template>
<div class=\\"flex aaa flex-col justify-center items-center\\">
<div text=\\"green-500 4xl\\" class=\\"rotate-180 i-carbon-campsite\\" :class=\\"bool ? bg : ''\\" />
<div class=\\"uno-qwn8dt font-(light mono)\\" h20>
<div class=\\"uno-144q2o hover:(!bg-gray-400 font-medium)\\">
<div class=\\"uno-j2nj36 aaa\\">
<div text=\\"4xl\\" class=\\"uno-e22fjo i-carbon-campsite\\" :class=\\"bg\\" />
<div class=\\"uno-1lreki font-(light mono)\\">
<div class=\\"uno-4oaq3e hover:(!bg-gray-400 font-medium)\\" text=\\"#6f4\\">
0123456789
</div>
</div>
<div class=\\"p-1\\" :class=\\"bool ? 'text-yellow-500' : ''\\">
<div :class=\\"{ 'bg-blue': bool }\\" p-2 :hover-class=\\"['uno-y5ng0p']\\">
class=\\"hover:bg-green\\"
</div>
<div class=\\"uno-82knp1\\" :class=\\"bool ? 'uno-2z589z' : ''\\">
{{ \`index\${index + 1}\` }}
</div>
<div class=\\"uno-1k8588\\" flex=\\"~ col\\">
<div w-10 h-10 flex=\\"1\\">
<div i-carbon-campsite inline-block color=\\"blue\\" />
<div flex=\\"~ col gap-2\\" border=\\"2 blue\\">
<div text-center w-10 h-10 flex=\\"1\\" text=\\"red\\">
1
</div>
<div w-10 h-10 flex=\\"1\\">
<div w-10 h-10 flex=\\"1\\" text-blue>
2
</div>
</div>
<button />
<uni-easyinput />
<div class=\\"uno-gdmskp\\" w-20 h-10>
bg-img
</div>
<div class=\\"uno-tw4biu\\" :class=\\"bool ? '' : 'uno-qju0i9'\\">
abckefghijklmnopqrstuvwxyz
</div>
<!-- eslint-disable-next-line vue/prefer-separate-static-class -->
<view :class=\\"['underline', customClass]\\">
aaa
</view>
</div>
</template>
",
"css": "/* layer: applet_shortcuts */
.uno-1k8588{grid-template-columns:0.7fr repeat(7,1fr);}
.uno-tw4biu{margin:0.125rem;padding:0.25rem;font-size:1.5rem;line-height:2rem;}
.uno-qwn8dt{border-width:1px;border-style:solid;--un-bg-opacity:1;background-color:rgba(191,219,254,var(--un-bg-opacity));background-color:rgba(239,68,68,var(--un-bg-opacity));padding-left:0.5rem;padding-right:0.5rem;transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;}
.uno-j2nj36{display:flex;flex-direction:column;align-items:center;justify-content:center;}
.uno-e22fjo{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:180deg;transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z));}
.uno-1lreki{border-width:1px;border-style:solid;--un-bg-opacity:1;background-color:rgba(191,219,254,var(--un-bg-opacity));}
.uno-98db2v{--un-bg-opacity:1;background-color:hsla(2.7,81.9%,69.6%,var(--un-bg-opacity));}
.uno-y5ng0p{--un-bg-opacity:1 !important;background-color:rgba(74,222,128,var(--un-bg-opacity)) !important;}
.uno-gdmskp{--un-url:url(https://static.runoob.com/images/demo/demo3.jpg);background-image:var(--un-url);}
.uno-82knp1{padding:0.25rem;}
.uno-qju0i9{padding:0.625rem;--un-text-opacity:1;color:rgba(234,179,8,var(--un-text-opacity));}
.uno-144q2o{color:rgba(187,247,208,0.5);--un-text-opacity:1;color:rgba(255,255,255,var(--un-text-opacity));}
.uno-2z589z{padding-left:0.625rem;padding-right:0.625rem;--un-text-opacity:1;color:rgba(234,179,8,var(--un-text-opacity));}
.uno-4oaq3e{--un-text-opacity:1;color:rgba(255,255,255,var(--un-text-opacity));}
/* layer: default */
.inline-block{display:inline-block;}
.h-10{height:2.5rem;}
.w-10{width:2.5rem;}
.w-20{width:5rem;}
.flex{display:flex;}
.flex-col{flex-direction:column;}
.rotate-180{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:180deg;transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z));}
.items-center{align-items:center;}
.justify-center{justify-content:center;}
.p-1{padding:0.25rem;}
.text-yellow-500{--un-text-opacity:1;color:rgba(234,179,8,var(--un-text-opacity));}",
.gap-2{grid-gap:0.5rem;gap:0.5rem;}
.border{border-width:1px;border-style:solid;}
.bg-blue{--un-bg-opacity:1;background-color:rgba(96,165,250,var(--un-bg-opacity));}
.hover\\\\:bg-green:hover{--un-bg-opacity:1;background-color:rgba(74,222,128,var(--un-bg-opacity));}
.p-2{padding:0.5rem;}
.text-center{text-align:center;}
.text-red{--un-text-opacity:1;color:rgba(248,113,113,var(--un-text-opacity));}
.underline{text-decoration-line:underline;}",
}
`)
})
Expand Down

0 comments on commit f1b602b

Please sign in to comment.