diff --git a/.gitignore b/.gitignore index 9aeac5f..2bf86a5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules *.log dist +coverage \ No newline at end of file diff --git a/package.json b/package.json index 5f72ef1..845feb6 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "typings": "dist/index.d.ts", "scripts": { "lint": "prettier --write \"{lib,test}/**/*.ts\"", - "test": "prettier --list-different \"{lib,test}/**/*.ts\" && jest", + "test": "prettier --list-different \"{lib,test}/**/*.ts\" && jest --coverage", "build": "rm -rf dist && tsc", "prepublishOnly": "yarn build && conventional-changelog -p angular -r 2 -i CHANGELOG.md -s" }, @@ -47,7 +47,8 @@ "stylus": "^0.54.5", "ts-jest": "^22.4.2", "typescript": "^2.7.2", - "vue-template-compiler": "^2.5.16", + "vue": "^2.5.17", + "vue-template-compiler": "^2.5.17", "yorkie": "^1.0.3" }, "dependencies": { diff --git a/test/compileStyle.spec.ts b/test/compileStyle.spec.ts index d233d50..efc35ca 100644 --- a/test/compileStyle.spec.ts +++ b/test/compileStyle.spec.ts @@ -161,3 +161,41 @@ test('async postcss plugin', async () => { expect(result.errors).toHaveLength(0) expect(result.code).toEqual(expect.stringContaining('color: red')) }) + +test('media query', () => { + const result = compileStyle({ + id: 'v-scope-xxx', + scoped: true, + filename: 'example.vue', + source: ` +@media print { + .foo { + color: #000; + } +}` + }) + + expect(result.errors).toHaveLength(0) + expect(result.code).toContain( + '@media print {\n.foo[v-scope-xxx] {\n color: #000;\n}\n}' + ) +}) + +test('supports query', () => { + const result = compileStyle({ + id: 'v-scope-xxx', + scoped: true, + filename: 'example.vue', + source: ` +@supports ( color: #000 ) { + .foo { + color: #000; + } +}` + }) + + expect(result.errors).toHaveLength(0) + expect(result.code).toContain( + '@supports ( color: #000 ) {\n.foo[v-scope-xxx] {\n color: #000;\n}\n}' + ) +}) diff --git a/test/compileTemplate.spec.ts b/test/compileTemplate.spec.ts index 2152416..d4f88e1 100644 --- a/test/compileTemplate.spec.ts +++ b/test/compileTemplate.spec.ts @@ -2,6 +2,19 @@ import { parse } from '../lib/parse' import { compileTemplate } from '../lib/compileTemplate' import * as compiler from 'vue-template-compiler' +import Vue from 'vue' + +afterEach(() => jest.resetAllMocks().resetModules()) + +function mockRender(code, options = {}) { + eval( + `${code}; options.render = render; options.staticRenderFns = staticRenderFns` + ) + const vm = new Vue(Object.assign({}, options)) + vm.$mount() + return vm._vnode +} + test('should work', () => { const source = `

{{ render }}

` @@ -63,3 +76,81 @@ test('warn missing preprocessor', () => { expect(result.errors.length).toBe(1) }) + +test('transform assetUrls', () => { + const source = ` +
+ + + +
+` + const result = compileTemplate({ + compiler: compiler, + filename: 'example.vue', + source, + transformAssetUrls: true + }) + expect(result.errors.length).toBe(0) + + jest.mock('./logo.png', () => 'a', { virtual: true }) + jest.mock('fixtures/logo.png', () => 'b', { virtual: true }) + + const vnode = mockRender(result.code) + expect(vnode.children[0].data.attrs.src).toBe('a') + expect(vnode.children[2].data.attrs.src).toBe('b') + expect(vnode.children[4].data.attrs.src).toBe('b') +}) + +test('transform srcset', () => { + // TODO: + const source = ` +
+ + + + + + + + + + + +
+` + const result = compileTemplate({ + compiler: compiler, + filename: 'example.vue', + source, + transformAssetUrls: true + }) + expect(result.errors.length).toBe(0) + + jest.mock('./logo.png', () => 'test-url', { virtual: true }) + const vnode = mockRender(result.code) + + // img tag + expect(vnode.children[0].data.attrs.src).toBe('test-url') + // image tag (SVG) + expect(vnode.children[2].children[0].data.attrs['xlink:href']).toBe( + 'test-url' + ) + + // image tag with srcset + expect(vnode.children[4].data.attrs.srcset).toBe('test-url') + expect(vnode.children[6].data.attrs.srcset).toBe('test-url 2x') + // image tag with multiline srcset + expect(vnode.children[8].data.attrs.srcset).toBe('test-url, test-url 2x') + expect(vnode.children[10].data.attrs.srcset).toBe('test-url 2x, test-url') + expect(vnode.children[12].data.attrs.srcset).toBe('test-url 2x, test-url 3x') + expect(vnode.children[14].data.attrs.srcset).toBe( + 'test-url, test-url 2x, test-url 3x' + ) + expect(vnode.children[16].data.attrs.srcset).toBe('test-url 2x, test-url 3x') +}) diff --git a/test/stylePluginScoped.spec.ts b/test/stylePluginScoped.spec.ts index cb80717..23e7e13 100644 --- a/test/stylePluginScoped.spec.ts +++ b/test/stylePluginScoped.spec.ts @@ -20,3 +20,85 @@ test('leading deep selector', () => { expect(code).toMatch(`[test] .foo { color: red;`) }) + +test('scoped css', () => { + const { code: style } = compileStyle({ + id: 'v-scope-xxx', + scoped: true, + filename: 'example.vue', + source: ` +.test { + color: yellow; +} +.test:after { + content: 'bye!'; +} +h1 { + color: green; +} +.anim { + animation: color 5s infinite, other 5s; +} +.anim-2 { + animation-name: color; + animation-duration: 5s; +} +.anim-3 { + animation: 5s color infinite, 5s other; +} +.anim-multiple { + animation: color 5s infinite, opacity 2s; +} +.anim-multiple-2 { + animation-name: color, opacity; + animation-duration: 5s, 2s; +} + +@keyframes color { + from { color: red; } + to { color: green; } +} +@-webkit-keyframes color { + from { color: red; } + to { color: green; } +} +@keyframes opacity { + from { opacity: 0; } + to { opacity: 1; } +} +@-webkit-keyframes opacity { + from { opacity: 0; } + to { opacity: 1; } +} +.foo p >>> .bar { + color: red; +}` + }) + + expect(style).toContain(`.test[v-scope-xxx] {\n color: yellow;\n}`) + expect(style).toContain(`.test[v-scope-xxx]:after {\n content: \'bye!\';\n}`) + expect(style).toContain(`h1[v-scope-xxx] {\n color: green;\n}`) + // scoped keyframes + expect(style).toContain( + `.anim[v-scope-xxx] {\n animation: color-v-scope-xxx 5s infinite, other 5s;` + ) + expect(style).toContain( + `.anim-2[v-scope-xxx] {\n animation-name: color-v-scope-xxx` + ) + expect(style).toContain( + `.anim-3[v-scope-xxx] {\n animation: 5s color-v-scope-xxx infinite, 5s other;` + ) + expect(style).toContain(`@keyframes color-v-scope-xxx {`) + expect(style).toContain(`@-webkit-keyframes color-v-scope-xxx {`) + + expect(style).toContain( + `.anim-multiple[v-scope-xxx] {\n animation: color-v-scope-xxx 5s infinite,opacity-v-scope-xxx 2s;` + ) + expect(style).toContain( + `.anim-multiple-2[v-scope-xxx] {\n animation-name: color-v-scope-xxx,opacity-v-scope-xxx;` + ) + expect(style).toContain(`@keyframes opacity-v-scope-xxx {`) + expect(style).toContain(`@-webkit-keyframes opacity-v-scope-xxx {`) + // >>> combinator + expect(style).toContain(`.foo p[v-scope-xxx] .bar {\n color: red;\n}`) +}) diff --git a/yarn.lock b/yarn.lock index f7f31be..657d1bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4669,9 +4669,9 @@ void-elements@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" -vue-template-compiler@^2.5.16: - version "2.5.16" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.16.tgz#93b48570e56c720cdf3f051cc15287c26fbd04cb" +vue-template-compiler@^2.5.17: + version "2.5.17" + resolved "http://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.5.17.tgz#52a4a078c327deb937482a509ae85c06f346c3cb" dependencies: de-indent "^1.0.2" he "^1.1.0" @@ -4680,6 +4680,10 @@ vue-template-es2015-compiler@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18" +vue@^2.5.17: + version "2.5.17" + resolved "http://registry.npm.taobao.org/vue/download/vue-2.5.17.tgz#0f8789ad718be68ca1872629832ed533589c6ada" + w3c-hr-time@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045"