Skip to content

Commit 3c90e82

Browse files
committed
add pre & post css transform callbacks to customize css transformation behavior
1 parent 34dd1e6 commit 3c90e82

File tree

12 files changed

+147
-70
lines changed

12 files changed

+147
-70
lines changed

e2e/__projects__/babel-config/__snapshots__/test.js.snap

+4
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,7 @@ __options__.staticRenderFns = staticRenderFns
140140
141141
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkJhc2ljU3JjLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBS0E7QUFQQTtBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSEE7QUFqQkEiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCB7XG4gIG5hbWU6ICdiYXNpYycsXG4gIGNvbXB1dGVkOiB7XG4gICAgaGVhZGluZ0NsYXNzZXM6IGZ1bmN0aW9uIGhlYWRpbmdDbGFzc2VzKCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVkOiB0aGlzLmlzQ3JhenksXG4gICAgICAgIGJsdWU6ICF0aGlzLmlzQ3JhenksXG4gICAgICAgIHNoYWRvdzogdGhpcy5pc0NyYXp5XG4gICAgICB9XG4gICAgfVxuICB9LFxuICBkYXRhOiBmdW5jdGlvbiBkYXRhKCkge1xuICAgIHJldHVybiB7XG4gICAgICBtc2c6ICdXZWxjb21lIHRvIFlvdXIgVnVlLmpzIEFwcCcsXG4gICAgICBpc0NyYXp5OiBmYWxzZVxuICAgIH1cbiAgfSxcbiAgbWV0aG9kczoge1xuICAgIHRvZ2dsZUNsYXNzOiBmdW5jdGlvbiB0b2dnbGVDbGFzcygpIHtcbiAgICAgIHRoaXMuaXNDcmF6eSA9ICF0aGlzLmlzQ3JhenlcbiAgICB9XG4gIH1cbn1cbiJdfQ=="
142142
`;
143+
144+
exports[`processes SCSS using user specified post transforms 1`] = `"<div class=\\"testA\\"><span class=\\"g\\"></span> <span class=\\"f\\"></span></div>"`;
145+
146+
exports[`processes SCSS using user specified pre transforms 1`] = `"<div class=\\"testA\\"><span class=\\"g\\"></span> <span class=\\"f\\"></span></div>"`;

e2e/__projects__/babel-config/components/Sass.vue

+5
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@
1313
.d
1414
background-color: blue
1515
</style>
16+
17+
<style lang="sass" module themed>
18+
.e
19+
background-color: blue
20+
</style>

e2e/__projects__/babel-config/components/Scss.vue

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
2-
<div class="testA"></div>
2+
<div class="testA">
3+
<span :class="this.$style.g"></span>
4+
<span :class="this.$style.dark.f"></span>
5+
</div>
36
</template>
47

58
<style module lang="scss">
@@ -15,3 +18,9 @@
1518
background-color: red;
1619
}
1720
</style>
21+
22+
<style lang="scss" module themed>
23+
.f {
24+
background-color: red;
25+
}
26+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const cssExtract = require('extract-from-css')
2+
module.exports = function (cssContent, config, attrs) {
3+
const cssNames = cssExtract.extractClasses(cssContent)
4+
const obj = {}
5+
for (let i = 0, l = cssNames.length; i < l; i++) {
6+
obj[cssNames[i]] = cssNames[i]
7+
}
8+
9+
if (attrs.themed) {
10+
return {
11+
light: obj,
12+
dark: obj
13+
}
14+
}
15+
return obj;
16+
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = function (cssContent, config, attrs) {
2+
return `${cssContent}\n .g{width: 10px}`;
3+
4+
}

e2e/__projects__/babel-config/package.json

+6
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@
4040
"vue-jest": {
4141
"pug": {
4242
"basedir": "./"
43+
},
44+
"cssTransform": {
45+
"scss": {
46+
"post": "./cssPostTransform.js",
47+
"pre": "./cssPreTransform.js"
48+
}
4349
}
4450
}
4551
}

e2e/__projects__/babel-config/test.js

+16
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ it('processes Sass', () => {
145145
expect(wrapper.vm.$style.a).toEqual('a')
146146
expect(wrapper.vm.$style.b).toEqual('b')
147147
expect(wrapper.vm.$style.c).toEqual('c')
148+
expect(wrapper.vm.$style.light).toBeUndefined()
148149
})
149150

150151
it('processes SCSS', () => {
@@ -154,6 +155,21 @@ it('processes SCSS', () => {
154155
expect(wrapper.vm.$style.c).toEqual('c')
155156
})
156157

158+
test('processes SCSS using user specified post transforms', () => {
159+
const wrapper = mount(Scss)
160+
expect(wrapper.vm.$style.light.a).toBeUndefined()
161+
expect(wrapper.vm.$style.light.f).toEqual('f')
162+
expect(wrapper.vm.$style.dark.f).toEqual('f')
163+
expect(wrapper.vm.$style.dark.g).toEqual('g')
164+
expect(wrapper.html()).toMatchSnapshot()
165+
})
166+
167+
test('processes SCSS using user specified pre transforms', () => {
168+
const wrapper = mount(Scss)
169+
expect(wrapper.vm.$style.g).toEqual('g')
170+
expect(wrapper.html()).toMatchSnapshot()
171+
})
172+
157173
test('process Stylus', () => {
158174
const wrapper = mount(Stylus)
159175
expect(wrapper.vm).toBeTruthy()

lib/compilers/helpers/module-name-mapper-helper.js

+16-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
const path = require('path')
2-
2+
const matchModuleImport = /^[^?]*~/
33
/**
4-
* Resolves the path to the file locally.
4+
* Resolves the path to the file/modeule.
55
*
66
* @param {String} to - the name of the file to resolve to
7-
* @param {String} localPath - the local path
7+
* @param {String} importPath - the local path
8+
* @param {String} fileType - extn of the file to be resolved
89
* @returns {String} path - path to the file to import
910
*/
10-
function localResolve(to, localPath) {
11-
if (localPath.startsWith('/')) {
12-
return localPath
11+
function resolve(to, importPath, fileType) {
12+
importPath =
13+
path.extname(importPath) === '' ? `${importPath}.${fileType}` : importPath
14+
if (importPath.startsWith('/')) {
15+
return importPath
16+
} else if (matchModuleImport.test(importPath)) {
17+
return require.resolve(importPath.replace(matchModuleImport, ''))
1318
}
14-
return path.join(path.dirname(to), localPath)
19+
return path.join(path.dirname(to), importPath)
1520
}
1621

1722
/**
@@ -20,12 +25,14 @@ function localResolve(to, localPath) {
2025
* @param {String} source - the original string
2126
* @param {String} filePath - the path of the current file (where the source originates)
2227
* @param {Object} jestConfig - the jestConfig holding the moduleNameMapper settings
28+
* @param {Object} fileType - extn of the file to be resolved
2329
* @returns {String} path - the final path to import (including replacements via moduleNameMapper)
2430
*/
2531
module.exports = function applyModuleNameMapper(
2632
source,
2733
filePath,
28-
jestConfig = {}
34+
jestConfig = {},
35+
fileType = ''
2936
) {
3037
if (!jestConfig.moduleNameMapper) return source
3138

@@ -47,5 +54,5 @@ module.exports = function applyModuleNameMapper(
4754
)
4855
}, source)
4956

50-
return localResolve(filePath, importPath)
57+
return resolve(filePath, importPath, fileType)
5158
}

lib/compilers/sass-compiler.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ module.exports = (content, filePath, jestConfig = {}) => {
2828
file: applyModuleNameMapper(
2929
url,
3030
prev === 'stdin' ? filePath : prev,
31-
jestConfig
31+
jestConfig,
32+
'sass'
3233
)
3334
})
3435
})

lib/compilers/scss-compiler.js

+3-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
const path = require('path')
2-
const fs = require('fs')
31
const ensureRequire = require('../ensure-require')
42
const getVueJestConfig = require('../utils').getVueJestConfig
53
const warn = require('../utils').warn
@@ -19,26 +17,17 @@ module.exports = (content, filePath, jestConfig = {}) => {
1917

2018
ensureRequire('scss', ['node-sass'])
2119
const sass = require('node-sass')
22-
23-
let scssResources = ''
24-
if (vueJestConfig.resources && vueJestConfig.resources.scss) {
25-
scssResources = vueJestConfig.resources.scss
26-
.map(scssResource => path.resolve(process.cwd(), scssResource))
27-
.filter(scssResourcePath => fs.existsSync(scssResourcePath))
28-
.map(scssResourcePath => fs.readFileSync(scssResourcePath).toString())
29-
.join('\n')
30-
}
31-
3220
try {
3321
return sass
3422
.renderSync({
35-
data: scssResources + content,
23+
data: content,
3624
outputStyle: 'compressed',
3725
importer: (url, prev, done) => ({
3826
file: applyModuleNameMapper(
3927
url,
4028
prev === 'stdin' ? filePath : prev,
41-
jestConfig
29+
jestConfig,
30+
'scss'
4231
)
4332
})
4433
})

lib/process-style.js

+61-10
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,65 @@
1+
const path = require('path')
2+
const fs = require('fs')
13
const getVueJestConfig = require('./utils').getVueJestConfig
4+
const warn = require('./utils').warn
25
const cssExtract = require('extract-from-css')
36

47
module.exports = function processStyle(stylePart, filePath, jestConfig = {}) {
58
const vueJestConfig = getVueJestConfig(jestConfig)
9+
let cssTransform =
10+
vueJestConfig['cssTransform'] &&
11+
vueJestConfig['cssTransform'][stylePart.lang]
12+
const validTransforms = cssTransform && (cssTransform.pre || cssTransform.post)
13+
cssTransform = cssTransform || {}
614

715
if (!stylePart || vueJestConfig.experimentalCSSCompile === false) {
816
return {}
917
}
1018

11-
const processStyleByLang = lang =>
12-
require('./compilers/' + lang + '-compiler')(
13-
stylePart.content,
19+
const globaResources = lang => {
20+
let globalResources = ''
21+
if (vueJestConfig.resources && vueJestConfig.resources[lang]) {
22+
globalResources = vueJestConfig.resources[lang]
23+
.map(resource => path.resolve(process.cwd(), resource))
24+
.filter(resourcePath => fs.existsSync(resourcePath))
25+
.map(resourcePath => fs.readFileSync(resourcePath).toString())
26+
.join('\n')
27+
}
28+
return globalResources
29+
}
30+
31+
const cssTransfomer = (transform, content) => {
32+
if (!validTransforms || !transform || typeof transform !== 'string') {
33+
return content
34+
}
35+
36+
const transformPath = /^(\.\.\/|\.\/|\/)/.test(transform) ? path.resolve(process.cwd(), transform) : transform
37+
return require(transformPath)(
38+
content,
39+
vueJestConfig,
40+
stylePart.attrs
41+
)
42+
}
43+
44+
const processStyleByLang = lang => {
45+
const content = globaResources(lang) + stylePart.content
46+
const preProcessedContent = cssTransfomer(cssTransform.pre, content)
47+
return require('./compilers/' + lang + '-compiler')(
48+
preProcessedContent,
1449
filePath,
1550
jestConfig
1651
)
52+
}
53+
54+
const extractClassMap = cssCode => {
55+
const cssNames = cssExtract.extractClasses(cssCode)
56+
const obj = {}
57+
for (let i = 0, l = cssNames.length; i < l; i++) {
58+
obj[cssNames[i]] = cssNames[i]
59+
}
60+
61+
return obj
62+
}
1763

1864
let cssCode = stylePart.content
1965
switch (stylePart.lang) {
@@ -29,12 +75,17 @@ module.exports = function processStyle(stylePart, filePath, jestConfig = {}) {
2975
break
3076
}
3177

32-
const cssNames = cssExtract.extractClasses(cssCode)
33-
34-
const obj = {}
35-
for (let i = 0, l = cssNames.length; i < l; i++) {
36-
obj[cssNames[i]] = cssNames[i]
78+
if (validTransforms) {
79+
let locals = cssTransfomer(cssTransform.post, cssCode)
80+
if (typeof locals !== 'object') {
81+
!vueJestConfig.hideStyleWarn &&
82+
warn(
83+
'post-transformers are expected to return an object with key value pair as class names of the component'
84+
)
85+
locals = extractClassMap(locals)
86+
}
87+
return locals
88+
} else {
89+
return extractClassMap(cssCode)
3790
}
38-
39-
return obj
4091
}

yarn.lock

+3-35
Original file line numberDiff line numberDiff line change
@@ -2402,7 +2402,7 @@ debug@^3.1.0:
24022402
dependencies:
24032403
ms "^2.1.1"
24042404

2405-
debuglog@*, debuglog@^1.0.1:
2405+
debuglog@^1.0.1:
24062406
version "1.0.1"
24072407
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
24082408
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
@@ -3902,7 +3902,7 @@ import-local@^1.0.0:
39023902
pkg-dir "^2.0.0"
39033903
resolve-cwd "^2.0.0"
39043904

3905-
imurmurhash@*, imurmurhash@^0.1.4:
3905+
imurmurhash@^0.1.4:
39063906
version "0.1.4"
39073907
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
39083908
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
@@ -5225,11 +5225,6 @@ lockfile@^1.0.4:
52255225
dependencies:
52265226
signal-exit "^3.0.2"
52275227

5228-
lodash._baseindexof@*:
5229-
version "3.1.0"
5230-
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
5231-
integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=
5232-
52335228
lodash._baseuniq@~4.6.0:
52345229
version "4.6.0"
52355230
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
@@ -5238,33 +5233,11 @@ lodash._baseuniq@~4.6.0:
52385233
lodash._createset "~4.0.0"
52395234
lodash._root "~3.0.0"
52405235

5241-
lodash._bindcallback@*:
5242-
version "3.0.1"
5243-
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
5244-
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=
5245-
5246-
lodash._cacheindexof@*:
5247-
version "3.0.2"
5248-
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
5249-
integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=
5250-
5251-
lodash._createcache@*:
5252-
version "3.1.2"
5253-
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
5254-
integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=
5255-
dependencies:
5256-
lodash._getnative "^3.0.0"
5257-
52585236
lodash._createset@~4.0.0:
52595237
version "4.0.3"
52605238
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
52615239
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=
52625240

5263-
lodash._getnative@*, lodash._getnative@^3.0.0:
5264-
version "3.9.1"
5265-
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
5266-
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
5267-
52685241
lodash._reinterpolate@~3.0.0:
52695242
version "3.0.0"
52705243
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@@ -5320,11 +5293,6 @@ lodash.pick@^4.4.0:
53205293
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
53215294
integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=
53225295

5323-
lodash.restparam@*:
5324-
version "3.6.1"
5325-
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
5326-
integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=
5327-
53285296
lodash.set@^4.3.2:
53295297
version "4.3.2"
53305298
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
@@ -7260,7 +7228,7 @@ readable-stream@~1.1.10:
72607228
isarray "0.0.1"
72617229
string_decoder "~0.10.x"
72627230

7263-
readdir-scoped-modules@*, readdir-scoped-modules@^1.0.0:
7231+
readdir-scoped-modules@^1.0.0:
72647232
version "1.0.2"
72657233
resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747"
72667234
integrity sha1-n6+jfShr5dksuuve4DDcm19AZ0c=

0 commit comments

Comments
 (0)