Skip to content
This repository has been archived by the owner on Jan 18, 2022. It is now read-only.

Commit

Permalink
fix: call transformer from whitelisted custom blocks (#310)
Browse files Browse the repository at this point in the history
  • Loading branch information
znck committed Nov 21, 2019
1 parent a983704 commit ab13f3b
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 45 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -46,7 +46,7 @@
"runtime/"
],
"dependencies": {
"@vue/component-compiler": "^4.1.0",
"@vue/component-compiler": "^4.2.0",
"@vue/component-compiler-utils": "^3.0.0",
"debug": "^4.1.1",
"hash-sum": "^1.0.2",
Expand Down
47 changes: 29 additions & 18 deletions src/index.ts
Expand Up @@ -4,7 +4,8 @@ import {
parseVuePartRequest,
resolveVuePart,
isVuePartRequest,
transformRequireToImport
transformRequireToImport,
DEFAULT_LANGS
} from './utils'
import {
createDefaultCompiler,
Expand Down Expand Up @@ -183,11 +184,15 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
if (!opts.styleInjectorShadow)
opts.styleInjectorShadow = '~' + require.resolve('../runtime/shadow')

createVuePartRequest.defaultLang = {
...createVuePartRequest.defaultLang,
const defaultLang: Record<string, string> = {
...DEFAULT_LANGS,
...opts.defaultLang
}

if (opts.defaultLang && typeof opts.defaultLang.styles === 'string') {
defaultLang.style = opts.defaultLang.styles
}

const shouldExtractCss = opts.css === false
const customBlocks: string[] = []

Expand Down Expand Up @@ -269,10 +274,10 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {

resolveId(id, importer) {
const request = id
if (!importer) return

if (!importer) return
if (!isVuePartRequest(id)) return

id = path.resolve(path.dirname(importer), id)
const ref = parseVuePartRequest(id)

Expand Down Expand Up @@ -307,7 +312,12 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
let map = element.map as any

if (request.meta.type === 'styles') {
code = prependStyle(id, request.meta.lang, code, map).code
code = prependStyle(
id,
request.meta.lang || defaultLang.style,
code,
map
).code
}

dL(`id: ${id}\ncode: \n${code}\nmap: ${JSON.stringify(map, null, 2)}\n\n`)
Expand Down Expand Up @@ -344,7 +354,7 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
if (style.content) {
style.content = prependStyle(
filename,
style.lang || 'css',
style.lang || defaultLang.style,
style.content,
style.map
).code
Expand Down Expand Up @@ -388,12 +398,12 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
code: `
export * from '${createVuePartRequest(
filename,
descriptor.script.lang || 'js',
descriptor.script.lang || defaultLang.script,
'script'
)}'
import script from '${createVuePartRequest(
filename,
descriptor.script.lang || 'js',
descriptor.script.lang || defaultLang.script,
'script'
)}'
export default script
Expand Down Expand Up @@ -433,22 +443,23 @@ export default function vue(opts: Partial<VuePluginOptions> = {}): Plugin {
.filter(Boolean)
}

// Why?
input.script.code = input.script.code.replace(/^\s+/gm, '')

const result = assemble(compiler, filename, beforeAssemble(input), opts)

descriptor.customBlocks.forEach((block, index) => {
if (!isAllowed(block.type)) return
const lang =
typeof block.attrs.lang === 'string'
? block.attrs.lang
: defaultLang[block.type] || block.type
const id = createVuePartRequest(filename, lang, block.type, index)
result.code +=
'\n' +
`export * from '${createVuePartRequest(
filename,
(typeof block.attrs.lang === 'string' && block.attrs.lang) ||
createVuePartRequest.defaultLang[block.type] ||
block.type,
'customBlocks',
index
)}'`
`export * from '${id}'\n` +
`import __custom_block_${index}__ from '${id}'\n` +
`__custom_block_${index}__(__vue_component__)`
})

dT(
Expand Down
30 changes: 14 additions & 16 deletions src/utils.ts
Expand Up @@ -21,14 +21,6 @@ export interface VuePartRequestMeta {
index?: number
}

export interface VuePartRequestCreator {
(filename: string, lang: string, type: string, index?: number): string

defaultLang: {
[key: string]: string
}
}

export function createVueFilter(
include: Array<string | RegExp> | string | RegExp = [/\.vue$/i],
exclude: Array<string | RegExp> | string | RegExp = []
Expand All @@ -49,7 +41,11 @@ export function getVueMetaFromQuery(id: string): VuePartRequestMeta | null {
? (query[PARAM_NAME] as any)[0]
: query[PARAM_NAME]) as string

const [type, index, lang] = data.split('.')
let [type, index, lang] = data.split('.')

if (!/^(template|styles|script)$/i.test(type)) {
type = 'customBlocks'
}

return (lang
? { type, lang, index: parseInt(index) } // styles.0.css
Expand All @@ -64,13 +60,13 @@ export function isVuePartRequest(id: string): boolean {
return getVueMetaFromQuery(id) !== null
}

export const createVuePartRequest: VuePartRequestCreator = ((
export function createVuePartRequest(
filename: string,
lang: string | undefined,
type: string,
index?: number
): string => {
lang = lang || createVuePartRequest.defaultLang[type]
): string {
lang = DEFAULT_LANGS[type] || lang

const match = GET_QUERY.exec(filename)

Expand All @@ -81,12 +77,14 @@ export const createVuePartRequest: VuePartRequestCreator = ((
.join('.')

return `${path.basename(filename)}?${queryString.stringify(query)}`
}) as VuePartRequestCreator
}

createVuePartRequest.defaultLang = {
export const DEFAULT_LANGS: Record<string, string> = {
template: 'html',
styles: 'css',
script: 'js'
style: 'css',
script: 'js',
docs: 'md',
i18n: 'json'
}

export function parseVuePartRequest(id: string): VuePartRequest | undefined {
Expand Down
52 changes: 52 additions & 0 deletions test/options/__snapshots__/custom-blocks.spec.ts.snap
@@ -0,0 +1,52 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`customBlocks transform 1`] = `
"var __custom_block_1__ = \\"// My Docs Block\\";
/* script */
/* template */
var __vue_render__ = function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c(\\"div\\", [_vm._v(\\"Hello, world\\")])
};
var __vue_staticRenderFns__ = [];
__vue_render__._withStripped = true;
/* style */
const __vue_inject_styles__ = undefined;
/* scoped */
const __vue_scope_id__ = undefined;
/* module identifier */
const __vue_module_identifier__ = undefined;
/* functional template */
const __vue_is_functional_template__ = false;
/* component normalizer */
const __vue_normalize__ = vue-runtime-helpers/dist/normalize-component.mjs;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__ = __vue_normalize__(
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
__vue_inject_styles__,
{},
__vue_scope_id__,
__vue_is_functional_template__,
__vue_module_identifier__,
false,
undefined,
undefined,
undefined
);
__custom_block_1__(__vue_component__);
export default __vue_component__;
"
`;
36 changes: 30 additions & 6 deletions test/options/custom-blocks.spec.ts
@@ -1,6 +1,16 @@
import vue, { VuePluginOptions } from '../../src'
import { pluginInline } from '../setup/plugins'
import { rollup } from 'rollup'
function pluginText() {
return {
name: 'text',
transform(source: string, id: string) {
if (/\.(md|txt)$/.test(id)) {
return `export default ${JSON.stringify(source.trim())}`
}
},
}
}

describe('customBlocks', () => {
async function setup(options?: Partial<VuePluginOptions>) {
Expand All @@ -21,11 +31,16 @@ describe('customBlocks', () => {
</docs>
`
),
pluginText(),
vue({
...options,
normalizer: 'vue-runtime-helpers/dist/normalize-component.mjs'
})
]
defaultLang: {
docs: 'md',
custom: 'txt',
},
normalizer: 'vue-runtime-helpers/dist/normalize-component.mjs',
}),
],
})
.then(bundle => bundle.generate({ format: 'es' }))
.then(generated => generated.output[0])
Expand All @@ -40,15 +55,15 @@ describe('customBlocks', () => {

it('array of tags', async () => {
const { code } = await setup({
customBlocks: ['custom']
customBlocks: ['custom'],
})

expect(code).toEqual(expect.stringContaining('My Custom Block'))
expect(code).not.toEqual(expect.stringContaining('My Docs Block'))
})
it('negative array of tags', async () => {
const { code } = await setup({
customBlocks: ['*', '!custom']
customBlocks: ['*', '!custom'],
})

expect(code).not.toEqual(expect.stringContaining('My Custom Block'))
Expand All @@ -58,10 +73,19 @@ describe('customBlocks', () => {
const { code } = await setup({
customBlocks(tag) {
return tag === 'custom'
}
},
})

expect(code).toEqual(expect.stringContaining('My Custom Block'))
expect(code).not.toEqual(expect.stringContaining('My Docs Block'))
})

it('transform', async () => {
const { code } = await setup({
customBlocks: ['docs'],
})

expect(code).toEqual(expect.stringContaining('__custom_block_1__(__vue_component__)'))
expect(code).toMatchSnapshot()
})
})
8 changes: 4 additions & 4 deletions yarn.lock
Expand Up @@ -1571,10 +1571,10 @@
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"

"@vue/component-compiler@^4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler/-/component-compiler-4.1.0.tgz#92ccb90e425aa7e61d58bf092a5cfcdd6d0f9315"
integrity sha512-20S7mm7CYP94m2Morw2ftz1tqoBu1nX7KYiqo5rlgKPZ0dlY7VZX7wAL/etN3s4HD0PBeenr1pUUCBIgGSaB2g==
"@vue/component-compiler@^4.2.0":
version "4.2.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler/-/component-compiler-4.2.0.tgz#437855cd59f3d713a4eef81bac7ab0f4950977b4"
integrity sha512-bxFNxUpKzLfHDoGTsAe2w7gEz4OwII7tp5m7sAXES1DApbpYglH4YSpYxdZRZ4GN/wj2fPD0u72QRJXd4UPvFQ==
dependencies:
"@vue/component-compiler-utils" "^3.0.0"
clean-css "^4.1.11"
Expand Down

0 comments on commit ab13f3b

Please sign in to comment.