Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support custom blocks for Vue 3 #364

Merged
merged 2 commits into from
Nov 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions e2e/3.x/custom-block/__snapshots__/test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Basic 1`] = `
Array [
Object {
"en": Object {
"hello": "Hello!",
},
"ja": Object {
"hello": "こんにちは!",
},
},
]
`;

exports[`Multiple blocks 1`] = `
Array [
Object {
"en": Object {
"hello": "Hello!",
},
"ja": Object {
"hello": "こんにちは!",
},
},
Object {
"foo": "foo",
},
]
`;
3 changes: 3 additions & 0 deletions e2e/3.x/custom-block/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: ['@babel/preset-env']
}
20 changes: 20 additions & 0 deletions e2e/3.x/custom-block/components/Basic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<template>
<p>basic custom block</p>
</template>

<script>
export default {
name: 'Basic'
}
</script>

<custom>
{
"en": {
"hello": "Hello!"
},
"ja": {
"hello": "こんにちは!"
}
}
</custom>
26 changes: 26 additions & 0 deletions e2e/3.x/custom-block/components/Multiple.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<template>
<p>multiple custom block</p>
</template>

<script>
export default {
name: 'Multiple'
}
</script>

<custom>
{
"en": {
"hello": "Hello!"
},
"ja": {
"hello": "こんにちは!"
}
}
</custom>

<custom>
{
"foo": "foo"
}
</custom>
40 changes: 40 additions & 0 deletions e2e/3.x/custom-block/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "vue3-custom-block",
"version": "1.0.0",
"license": "MIT",
"private": true,
"scripts": {
"test": "jest --no-cache --coverage test.js"
},
"dependencies": {
"vue": "^3.0.3"
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.0",
"@vue/compiler-sfc": "^3.0.3",
"jest": "^26.0.0",
"vue3-jest": "^26.0.0-alpha.10"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.vue$": "vue3-jest"
},
"moduleNameMapper": {
"^~?__styles/(.*)$": "<rootDir>/components/styles/$1"
},
"globals": {
"vue-jest": {
"transform": {
"custom": "./transformer.js"
}
}
}
}
}
33 changes: 33 additions & 0 deletions e2e/3.x/custom-block/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Basic from './components/Basic.vue'
import Multiple from './components/Multiple.vue'

test('Basic', () => {
expect(Basic.__custom).toMatchObject([
{
en: {
hello: 'Hello!'
},
ja: {
hello: 'こんにちは!'
}
}
])
expect(Basic.__custom).toMatchSnapshot()
})

test('Multiple blocks', () => {
expect(Multiple.__custom).toMatchObject([
{
en: {
hello: 'Hello!'
},
ja: {
hello: 'こんにちは!'
}
},
{
foo: 'foo'
}
])
expect(Multiple.__custom).toMatchSnapshot()
})
21 changes: 21 additions & 0 deletions e2e/3.x/custom-block/transformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function convert(content) {
return JSON.stringify(JSON.parse(content))
.replace(/\u2028/g, '\\u2028') // LINE SEPARATOR
.replace(/\u2029/g, '\\u2029') // PARAGRAPH SEPARATOR
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
}

module.exports = {
process({ blocks, componentNamespace, filename, config }) {
const ret = blocks.reduce((codes, block) => {
codes.push(
`${componentNamespace}.__custom = ${componentNamespace}.__custom || [];${componentNamespace}.__custom.push(${convert(
block.content
)});`
)
return codes
}, [])
return ret
}
}
2 changes: 1 addition & 1 deletion packages/vue3-jest/lib/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
vueOptionsNamespace: '__options__',
vueComponentNamespace: 'Component',
defaultVueJestConfig: {
transform: {}
}
Expand Down
14 changes: 12 additions & 2 deletions packages/vue3-jest/lib/generate-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ function addToSourceMap(node, result) {
}
}

module.exports = function generateCode(
module.exports = function generateCode({
scriptResult,
scriptSetupResult,
templateResult,
customBlocksResult,
componentNamespace,
filename,
stylesResult
) {
}) {
var node = new SourceNode(null, null, null)
addToSourceMap(node, scriptResult)
addToSourceMap(node, scriptSetupResult)
Expand Down Expand Up @@ -63,5 +65,13 @@ module.exports = function generateCode(
)
}

if (Array.isArray(customBlocksResult)) {
customBlocksResult.forEach(codes => {
codes.forEach(code => {
node.add(`;((${componentNamespace}) => { ${code} })(exports.default);`)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Custom blocks can now be handled for components like vue-loader and @vitejs/plugin-vue.

})
})
}

return node.toStringWithSourceMap({ file: filename })
}
16 changes: 7 additions & 9 deletions packages/vue3-jest/lib/process-custom-blocks.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
const { getVueJestConfig, getCustomTransformer } = require('./utils')
const vueOptionsNamespace = require('./constants').vueOptionsNamespace

function applyTransformer(
transformer,
blocks,
vueOptionsNamespace,
componentNamespace,
filename,
config
) {
return transformer.process({ blocks, vueOptionsNamespace, filename, config })
return transformer.process({ blocks, componentNamespace, filename, config })
}

function groupByType(acc, block) {
Expand All @@ -17,9 +16,9 @@ function groupByType(acc, block) {
return acc
}

module.exports = function(allBlocks, filename, config) {
module.exports = (allBlocks, filename, componentNamespace, config) => {
const blocksByType = allBlocks.reduce(groupByType, {})
const code = []
const codes = []
for (const [type, blocks] of Object.entries(blocksByType)) {
const transformer = getCustomTransformer(
getVueJestConfig(config).transform,
Expand All @@ -29,13 +28,12 @@ module.exports = function(allBlocks, filename, config) {
const codeStr = applyTransformer(
transformer,
blocks,
vueOptionsNamespace,
componentNamespace,
filename,
config
)
code.push(codeStr)
codes.push(codeStr)
}
}

return code.length ? code.join('\n') : ''
return codes
}
22 changes: 14 additions & 8 deletions packages/vue3-jest/lib/process.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const babelTransformer = require('babel-jest')
const typescriptTransformer = require('./transformers/typescript')
const coffeescriptTransformer = require('./transformers/coffee')
const _processStyle = require('./process-style')
// const processCustomBlocks = require('./process-custom-blocks')
const processCustomBlocks = require('./process-custom-blocks')
const getVueJestConfig = require('./utils').getVueJestConfig
const getTsJestConfig = require('./utils').getTsJestConfig
const logResultErrors = require('./utils').logResultErrors
Expand All @@ -14,6 +14,7 @@ const getCustomTransformer = require('./utils').getCustomTransformer
const loadSrc = require('./utils').loadSrc
const generateCode = require('./generate-code')
const mapLines = require('./map-lines')
const vueComponentNamespace = require('./constants').vueComponentNamespace

function resolveTransformer(lang = 'js', vueJestConfig) {
const transformer = getCustomTransformer(vueJestConfig['transform'], lang)
Expand Down Expand Up @@ -133,23 +134,28 @@ function processStyle(styles, filename, config) {

module.exports = function(src, filename, config) {
const { descriptor } = parse(src, { filename })
const componentNamespace =
getVueJestConfig(config)['componentNamespace'] || vueComponentNamespace
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have added the componentNamespace option to the vue-jest config.
This is because we want the transformer (parser) side of custom blocks to be able to handle them flexibly.

In the case of i18n custom blocks, we are using a common library for generic processing for various bundlers such as vue-i18n-loader, rollup-plugin-vue-i18n, and vite-plugin-vue-i18n. For example, it's handled the below:

https://github.com/intlify/cli/blob/4875ec52e0256bf2cf9723dde999b8efa8c043cd/src/generator/json.ts#L91-L103

In the code in the URL above, the component pass to the function, and uses the variable name Component.

In order to reuse this logic in vue-jest transformer, I need to change it a bit, but in any case, being able to specify the variable name allows for flexible processing on the transformer side.


const templateResult = processTemplate(descriptor, filename, config)
const scriptResult = processScript(descriptor.script, filename, config)
const scriptSetupResult = processScriptSetup(descriptor, filename, config)
const stylesResult = processStyle(descriptor.styles, filename, config)
// const customBlocksResult = processCustomBlocks(
// descriptor.customBlocks,
// filename,
// config
// )
const output = generateCode(
const customBlocksResult = processCustomBlocks(
descriptor.customBlocks,
filename,
componentNamespace,
config
)
const output = generateCode({
scriptResult,
scriptSetupResult,
templateResult,
customBlocksResult,
componentNamespace,
filename,
stylesResult
)
})

return {
code: output.code,
Expand Down