Skip to content
This repository has been archived by the owner on Feb 17, 2023. It is now read-only.

Commit

Permalink
fix: parse custom block code correctly. (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
yfwz100 authored Apr 19, 2021
1 parent 318fdf0 commit 2d6175b
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 16 deletions.
3 changes: 3 additions & 0 deletions playground/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TestBlockSrcImport/>
<TestScopedCss/>
<TestCssModules/>
<TestCustomBlock/>
<TestHmr/>
<TestAssets/>
<TestJsx/>
Expand All @@ -15,6 +16,7 @@
import TestBlockSrcImport from './src-import/TestBlockSrcImport.vue'
import TestScopedCss from './css/TestScopedCss.vue'
import TestCssModules from './css/TestCssModules.vue'
import TestCustomBlock from './custom/TestCustomBlock.vue'
import TestHmr from './hmr/TestHmr.vue'
import TestAssets from './test-assets/TestAssets.vue'
import TestJsx from './TestJsx.tsx'
Expand All @@ -26,6 +28,7 @@ export default {
TestScopedCss,
TestBlockSrcImport,
TestCssModules,
TestCustomBlock,
TestHmr,
TestAssets,
TestJsx,
Expand Down
39 changes: 39 additions & 0 deletions playground/custom/TestCustomBlock.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<div>
<p class="custom-block">{{ custom }}</p>
<p class="custom-block-lang">{{ customLang }}</p>
<p class="custom-block-src">{{ customSrc }}</p>
</div>
</template>

<script>
export default {
name: 'TestCustomBlock',
data() {
return {
custom: '',
customLang: '',
customSrc: '',
}
},
created() {
this.custom = this.$options.__customBlock.custom
this.customLang = this.$options.__customBlock.customLang
this.customSrc = this.$options.__customBlock.customSrc
},
}
</script>

<custom>
export default {
"custom": "Custom Block"
}
</custom>

<custom lang="json">
{
"customLang": "Custom Block"
}
</custom>

<custom src="./custom.json"></custom>
3 changes: 3 additions & 0 deletions playground/custom/custom.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"customSrc": "Custom Block"
}
24 changes: 23 additions & 1 deletion playground/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,29 @@ const config = defineConfig({
// sourcemap: true,
minify: false,
},
plugins: [createVuePlugin({ jsx: true })],
plugins: [
createVuePlugin({ jsx: true }),
{
name: 'customBlock',
transform(code, id) {
if (/type=custom/i.test(id)) {
const transformedAssginment = code
.trim()
.replace(/export default/, 'const __customBlock =')
return {
code: `${transformedAssginment}
export default function (component) {
const options = component.options;
if (!options.__customBlock) {
options.__customBlock = {};
}
Object.assign(options.__customBlock, __customBlock);
}`,
}
}
},
},
],
})

export default config
41 changes: 26 additions & 15 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ function injectStyles (context) {
}\n`

// custom block
code += genCustomBlockCode(filePath, descriptor)
result += await genCustomBlockCode(filePath, descriptor, pluginContext)
// Expose filename. This is used by the devtools and Vue runtime warnings.
if (options.isProduction) {
// Expose the file's full path in development, so that it can be opened
// from the devtools.
code += `\ncomponent.options.__file = ${JSON.stringify(
result += `\ncomponent.options.__file = ${JSON.stringify(
path.relative(options.root, filePath).replace(/\\/g, '/')
)}`
}
Expand Down Expand Up @@ -194,20 +194,31 @@ async function genTemplateRequest(
}
}

function genCustomBlockCode(filename: string, descriptor: SFCDescriptor) {
async function genCustomBlockCode(
filename: string,
descriptor: SFCDescriptor,
pluginContext: TransformPluginContext
) {
let code = ''
descriptor.customBlocks.forEach((block, index) => {
// if (block.src) {
// linkSrcToDescriptor(block.src, descriptor)
// }
const src = filename
const attrsQuery = attrsToQuery(block.attrs, block.type)
// const srcQuery = block.src ? `&src` : ``
const query = `?vue&type=${block.type}&index=${index}${attrsQuery}`
const request = JSON.stringify(src + query)
code += `import block${index} from ${request}\n`
code += `if (typeof block${index} === 'function') block${index}(component)\n`
})
await Promise.all(
descriptor.customBlocks.map(async (block, index) => {
const blockSrc =
typeof block.attrs.src === 'string' ? block.attrs.src : ''
if (blockSrc) {
await linkSrcToDescriptor(blockSrc, filename, descriptor, pluginContext)
}
const src = blockSrc || filename
const attrsQuery = attrsToQuery(
block.attrs,
path.extname(blockSrc) || block.type
)
const srcQuery = block.attrs.src ? `&src` : ``
const query = `?vue&type=${block.type}&index=${index}${srcQuery}${attrsQuery}`
const request = JSON.stringify(src + query)
code += `import block${index} from ${request}\n`
code += `if (typeof block${index} === 'function') block${index}(component)\n`
})
)
return code
}

Expand Down
6 changes: 6 additions & 0 deletions test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ export function declareTests(isBuild: boolean) {
}
})

test('SFC <custom>', async () => {
expect(await getText('.custom-block')).toMatch('Custom Block')
expect(await getText('.custom-block-lang')).toMatch('Custom Block')
expect(await getText('.custom-block-src')).toMatch('Custom Block')
})

test('SFC src imports', async () => {
expect(await getText('.src-imports-script')).toMatch('src="./script.ts"')
const el = await getEl('.src-imports-style')
Expand Down

0 comments on commit 2d6175b

Please sign in to comment.