Skip to content

Commit 85f12c7

Browse files
committed
feat: eval script mangle
1 parent f08df1d commit 85f12c7

File tree

4 files changed

+53
-20
lines changed

4 files changed

+53
-20
lines changed

packages/unplugin-tailwindcss-mangle/src/js/index.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import type { StringLiteral, TemplateElement } from '@babel/types'
2-
import { transformSync, type BabelFileResult, type NodePath } from '@babel/core'
1+
import type { StringLiteral, TemplateElement, CallExpression } from '@babel/types'
2+
import * as t from '@babel/types'
3+
import { transformSync, type BabelFileResult, type NodePath, parseSync } from '@babel/core'
34
import type { IHandlerOptions } from '../types'
45
import { escapeStringRegexp } from '../utils'
56
import { splitCode } from './split'
@@ -48,6 +49,20 @@ export function jsHandler(rawSource: string, options: IHandlerOptions) {
4849
const n = p.node
4950
n.value.raw = handleValue(n.value.raw, n, options)
5051
}
52+
},
53+
CallExpression: {
54+
enter(p: NodePath<CallExpression>) {
55+
const n = p.node
56+
// eval()
57+
if (t.isIdentifier(n.callee) && n.callee.name === 'eval') {
58+
if (t.isStringLiteral(n.arguments[0])) {
59+
const res = jsHandler(n.arguments[0].value, options)
60+
if (res.code) {
61+
n.arguments[0].value = res.code
62+
}
63+
}
64+
}
65+
}
5166
}
5267
// noScope: true
5368
}

packages/unplugin-tailwindcss-mangle/test/__snapshots__/js.test.ts.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ exports[`js handler common TemplateElement 1`] = `
77
element.innerHTML = \`<div class="tw-a tw-b">count is \${counter}</div>\`;"
88
`;
99
10+
exports[`js handler eval script case 1`] = `
11+
"(function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
12+
"use strict";
13+
14+
eval("__webpack_require__.r(__webpack_exports__);\\n/* harmony export */\\n__webpack_require__.d(__webpack_exports__, {\\n /* harmony export */\\"render\\": function () {\\n return (/* binding */render\\n );\\n }\\n /* harmony export */\\n});\\n/* harmony import */\\nvar vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__( /*! vue */\\"../../node_modules/.pnpm/[email protected]/node_modules/vue/dist/vue.runtime.esm-bundler.js\\");\\n/* harmony import */\\nvar _assets_logo_png__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__( /*! ./assets/logo.png */\\"./src/assets/logo.png\\");\\nconst _hoisted_1 = {\\n class: \\"flex tw-a tw-b tw-c tw-d tw-e\\"\\n};\\nconst _hoisted_2 = /*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\\"div\\", {\\n class: \\"tw-f tw-g tw-h tw-c tw-d tw-i tw-j tw-k\\"\\n}, [/*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\\"p\\", {\\n class: \\"fixed tw-l tw-m flex tw-g tw-n tw-o tw-p tw-q tw-r tw-s tw-t tw-u tw-v tw-w tw-x tw-y tw-z tw-aa tw-ba tw-ca tw-da tw-ea\\"\\n}, [/*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(\\" Get started by editing\\xA0 \\"), /*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\\"code\\", {\\n class: \\"tw-i tw-fa\\"\\n}, \\"pages/index.tsx\\")]), /*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\\"div\\", {\\n class: \\"fixed tw-ga tw-l flex tw-ha tw-g tw-ia tw-n tw-ja tw-ka tw-la tw-ma tw-na tw-y tw-oa tw-z tw-pa\\"\\n}, [/*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\\"a\\", {\\n class: \\"tw-qa flex tw-ra tw-sa tw-ta tw-ua tw-va\\",\\n href: \\"https://vercel.com?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app\\",\\n target: \\"_blank\\",\\n rel: \\"noopener noreferrer\\"\\n}, [/*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(\\" By \\"), /*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\\"img\\", {\\n src: _assets_logo_png__WEBPACK_IMPORTED_MODULE_1__,\\n alt: \\"Vercel Logo\\",\\n class: \\"tw-wa\\",\\n priority: \\"\\"\\n})])])], -1 /* HOISTED */);\\nconst _hoisted_3 = /*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\\"div\\", {\\n class: \\"relative flex tw-ra tw-xa tw-ya tw-za tw-ab tw-bb tw-cb tw-db tw-eb tw-fb tw-gb tw-hb tw-ib tw-jb tw-kb tw-lb tw-mb tw-nb tw-ob tw-pb tw-qb tw-rb tw-sb tw-tb tw-ub tw-vb tw-wb\\"\\n}, [/*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\\"img\\", {\\n class: \\"relative tw-xb tw-wa\\",\\n src: _assets_logo_png__WEBPACK_IMPORTED_MODULE_1__,\\n alt: \\"Next.js Logo\\",\\n priority: \\"\\"\\n})], -1 /* HOISTED */);\\nconst _hoisted_4 = /*#__PURE__*/(0, vue__WEBPACK_IMPORTED_MODULE_0__.createStaticVNode)(\\"<div class=\\\\\\"tw-yb grid tw-zb tw-ac tw-bc tw-cc\\\\\\"><a href=\\\\\\"https://nextjs.org/docs?utm_source=create-next-app&amp;utm_medium=default-template-tw&amp;utm_campaign=create-next-app\\\\\\" class=\\\\\\"group tw-dc border tw-ec tw-fc tw-gc tw-hc tw-ic tw-jc tw-kc tw-lc\\\\\\" target=\\\\\\"_blank\\\\\\" rel=\\\\\\"noopener noreferrer\\\\\\"><h2 class=\\\\\\"tw-mc tw-nc tw-oc\\\\\\"> Docs <span class=\\\\\\"tw-pc tw-qc tw-rc tw-sc\\\\\\">-&gt;</span></h2><p class=\\\\\\"tw-tc tw-uc tw-j tw-vc\\\\\\">Find in-depth information about Next.js features and API.</p></a><a href=\\\\\\"https://nextjs.org/learn?utm_source=create-next-app&amp;utm_medium=default-template-tw&amp;utm_campaign=create-next-app\\\\\\" class=\\\\\\"group tw-dc border tw-ec tw-fc tw-gc tw-hc tw-ic tw-jc tw-kc tw-lc\\\\\\" target=\\\\\\"_blank\\\\\\" rel=\\\\\\"noopener noreferrer\\\\\\"><h2 class=\\\\\\"tw-mc tw-nc tw-oc tw-wc\\\\\\"> Learn <span class=\\\\\\"tw-pc tw-qc tw-rc tw-sc\\\\\\">-&gt;</span></h2><p class=\\\\\\"tw-tc tw-uc tw-j tw-vc\\\\\\">Learn about Next.js in an interactive course with\\\\xA0quizzes!</p></a><a href=\\\\\\"https://vercel.com/templates?framework=next.js&amp;utm_source=create-next-app&amp;utm_medium=default-template-tw&amp;utm_campaign=create-next-app\\\\\\" class=\\\\\\"group tw-dc border tw-ec tw-fc tw-gc tw-hc tw-ic tw-jc tw-kc tw-lc\\\\\\" target=\\\\\\"_blank\\\\\\" rel=\\\\\\"noopener noreferrer\\\\\\"><h2 class=\\\\\\"tw-mc tw-nc tw-oc\\\\\\"> Templates <span class=\\\\\\"tw-pc tw-qc tw-rc tw-sc\\\\\\">-&gt;</span></h2><p class=\\\\\\"tw-tc tw-uc tw-j tw-vc\\\\\\">Discover and deploy boilerplate example Next.js\\\\xA0projects.</p></a><a href=\\\\\\"https://vercel.com/new?utm_source=create-next-app&amp;utm_medium=default-template-tw&amp;utm_campaign=create-next-app\\\\\\" class=\\\\\\"group tw-dc border tw-ec tw-fc tw-gc tw-hc tw-ic tw-jc tw-kc tw-lc\\\\\\" target=\\\\\\"_blank\\\\\\" rel=\\\\\\"noopener noreferrer\\\\\\"><h2 class=\\\\\\"tw-mc tw-nc tw-oc\\\\\\"> Deploy <span class=\\\\\\"tw-pc tw-qc tw-rc tw-sc\\\\\\">-&gt;</span></h2><p class=\\\\\\"tw-tc tw-uc tw-j tw-vc\\\\\\">Instantly deploy your Next.js site to a shareable URL with Vercel.</p></a></div>\\", 1);\\nconst _hoisted_5 = [_hoisted_2, _hoisted_3, _hoisted_4];\\nfunction render(_ctx, _cache) {\\n return (0, vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0, vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\\"main\\", _hoisted_1, _hoisted_5);\\n} //# sourceURL=[module]\\n\\n//# sourceURL=webpack-internal:///../../node_modules/.pnpm/[email protected]_c3tfwv7p35clwcmkb5fnkshzei/node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[4]!../../node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=template&id=7ba5bd90");
15+
});"
16+
`;
17+
1018
exports[`js handler nextjs server side mangle 1`] = `
1119
""use strict";
1220

packages/unplugin-tailwindcss-mangle/test/fixtures/tw-class-set.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[
2+
"text-[red]",
23
"after:-z-20",
34
"after:absolute",
45
"after:bg-gradient-conic",

packages/unplugin-tailwindcss-mangle/test/js.test.ts

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import { getCss, getTestCase } from './utils'
44
// import { getClassCacheSet } from 'tailwindcss-patch'
55

66
describe('js handler', () => {
7+
let classGenerator: ClassGenerator
8+
beforeEach(() => {
9+
classGenerator = new ClassGenerator()
10+
})
711
it('common StringLiteral', () => {
8-
const classGenerator = new ClassGenerator()
912
const runtimeSet = new Set<string>()
1013
runtimeSet.add('dark:bg-zinc-800/30')
1114
runtimeSet.add('lg:dark:bg-zinc-800/30')
@@ -19,7 +22,6 @@ describe('js handler', () => {
1922
})
2023

2124
it('common TemplateElement', () => {
22-
const classGenerator = new ClassGenerator()
2325
const runtimeSet = new Set<string>()
2426
runtimeSet.add('dark:bg-zinc-800/30')
2527
runtimeSet.add('lg:dark:bg-zinc-800/30')
@@ -32,24 +34,22 @@ describe('js handler', () => {
3234
expect(code).toMatchSnapshot()
3335
})
3436

35-
it('text-[red]', () => {
36-
const classGenerator = new ClassGenerator()
37-
const runtimeSet = new Set<string>()
37+
// it('text-[red]', () => {
38+
// const runtimeSet = new Set<string>()
3839

39-
// eslint-disable-next-line no-template-curly-in-string
40-
const testCase = ''
41-
testCase.split(' ').forEach((x) => {
42-
runtimeSet.add(x)
43-
})
44-
const code = jsHandler(testCase, {
45-
classGenerator,
46-
runtimeSet
47-
}).code
48-
expect(code).toMatchSnapshot()
49-
})
40+
// // eslint-disable-next-line no-template-curly-in-string
41+
// const testCase = ''
42+
// testCase.split(' ').forEach((x) => {
43+
// runtimeSet.add(x)
44+
// })
45+
// const code = jsHandler(testCase, {
46+
// classGenerator,
47+
// runtimeSet
48+
// }).code
49+
// expect(code).toMatchSnapshot()
50+
// })
5051

5152
it('z-10 not transform', () => {
52-
const classGenerator = new ClassGenerator()
5353
const runtimeSet = new Set<string>()
5454
'z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex'.split(' ').forEach((cls) => {
5555
runtimeSet.add(cls)
@@ -64,7 +64,6 @@ describe('js handler', () => {
6464
})
6565

6666
it('nextjs server side mangle', () => {
67-
const classGenerator = new ClassGenerator()
6867
const testCase = getTestCase('next-server-page.js')
6968
getCss(testCase)
7069
const runtimeSet = new Set(require('./fixtures/tw-class-set.json') as string[]) // getClassCacheSet()
@@ -76,4 +75,14 @@ describe('js handler', () => {
7675
}).code
7776
expect(code).toMatchSnapshot()
7877
})
78+
79+
it('eval script case', () => {
80+
const testCase = getTestCase('webpack-dev-content.js')
81+
const runtimeSet = new Set(require('./fixtures/tw-class-set.json') as string[])
82+
const code = jsHandler(testCase, {
83+
classGenerator,
84+
runtimeSet
85+
}).code
86+
expect(code).toMatchSnapshot()
87+
})
7988
})

0 commit comments

Comments
 (0)