fix(ssr): handle fallthrough attrs in ssr compile output
This commit is contained in:
parent
30584bcc61
commit
d5dbd27193
@ -210,7 +210,7 @@ export function generate(
|
|||||||
if (!ssr) {
|
if (!ssr) {
|
||||||
push(`function render(_ctx, _cache) {`)
|
push(`function render(_ctx, _cache) {`)
|
||||||
} else {
|
} else {
|
||||||
push(`function ssrRender(_ctx, _push, _parent) {`)
|
push(`function ssrRender(_ctx, _push, _parent, _attrs) {`)
|
||||||
}
|
}
|
||||||
indent()
|
indent()
|
||||||
|
|
||||||
|
@ -3,16 +3,16 @@ import { compile } from '../src'
|
|||||||
describe('ssr: components', () => {
|
describe('ssr: components', () => {
|
||||||
test('basic', () => {
|
test('basic', () => {
|
||||||
expect(compile(`<foo id="a" :prop="b" />`).code).toMatchInlineSnapshot(`
|
expect(compile(`<foo id="a" :prop="b" />`).code).toMatchInlineSnapshot(`
|
||||||
"const { resolveComponent: _resolveComponent } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, mergeProps: _mergeProps } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, {
|
_push(_ssrRenderComponent(_component_foo, _mergeProps({
|
||||||
id: \\"a\\",
|
id: \\"a\\",
|
||||||
prop: _ctx.b
|
prop: _ctx.b
|
||||||
}, null, _parent))
|
}, _attrs), null, _parent))
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
@ -20,21 +20,21 @@ describe('ssr: components', () => {
|
|||||||
test('dynamic component', () => {
|
test('dynamic component', () => {
|
||||||
expect(compile(`<component is="foo" prop="b" />`).code)
|
expect(compile(`<component is="foo" prop="b" />`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { resolveDynamicComponent: _resolveDynamicComponent } = require(\\"vue\\")
|
"const { resolveDynamicComponent: _resolveDynamicComponent, mergeProps: _mergeProps } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(_ssrRenderComponent(_resolveDynamicComponent(\\"foo\\"), { prop: \\"b\\" }, null, _parent))
|
_push(_ssrRenderComponent(_resolveDynamicComponent(\\"foo\\"), _mergeProps({ prop: \\"b\\" }, _attrs), null, _parent))
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(compile(`<component :is="foo" prop="b" />`).code)
|
expect(compile(`<component :is="foo" prop="b" />`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { resolveDynamicComponent: _resolveDynamicComponent } = require(\\"vue\\")
|
"const { resolveDynamicComponent: _resolveDynamicComponent, mergeProps: _mergeProps } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(_ssrRenderComponent(_resolveDynamicComponent(_ctx.foo), { prop: \\"b\\" }, null, _parent))
|
_push(_ssrRenderComponent(_resolveDynamicComponent(_ctx.foo), _mergeProps({ prop: \\"b\\" }, _attrs), null, _parent))
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
@ -45,10 +45,10 @@ describe('ssr: components', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, createTextVNode: _createTextVNode } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, createTextVNode: _createTextVNode } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, {
|
_push(_ssrRenderComponent(_component_foo, _attrs, {
|
||||||
default: _withCtx((_, _push, _parent, _scopeId) => {
|
default: _withCtx((_, _push, _parent, _scopeId) => {
|
||||||
if (_push) {
|
if (_push) {
|
||||||
_push(\`hello<div\${_scopeId}></div>\`)
|
_push(\`hello<div\${_scopeId}></div>\`)
|
||||||
@ -71,10 +71,10 @@ describe('ssr: components', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, {
|
_push(_ssrRenderComponent(_component_foo, _attrs, {
|
||||||
default: _withCtx(({ msg }, _push, _parent, _scopeId) => {
|
default: _withCtx(({ msg }, _push, _parent, _scopeId) => {
|
||||||
if (_push) {
|
if (_push) {
|
||||||
_push(\`\${_ssrInterpolate(msg + _ctx.outer)}\`)
|
_push(\`\${_ssrInterpolate(msg + _ctx.outer)}\`)
|
||||||
@ -100,10 +100,10 @@ describe('ssr: components', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, {
|
_push(_ssrRenderComponent(_component_foo, _attrs, {
|
||||||
default: _withCtx((_, _push, _parent, _scopeId) => {
|
default: _withCtx((_, _push, _parent, _scopeId) => {
|
||||||
if (_push) {
|
if (_push) {
|
||||||
_push(\`foo\`)
|
_push(\`foo\`)
|
||||||
@ -137,10 +137,10 @@ describe('ssr: components', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode, createSlots: _createSlots } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode, createSlots: _createSlots } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, _createSlots({ _: 1 }, [
|
_push(_ssrRenderComponent(_component_foo, _attrs, _createSlots({ _: 1 }, [
|
||||||
(_ctx.ok)
|
(_ctx.ok)
|
||||||
? {
|
? {
|
||||||
name: \\"named\\",
|
name: \\"named\\",
|
||||||
@ -169,10 +169,10 @@ describe('ssr: components', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, renderList: _renderList, createSlots: _createSlots } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, renderList: _renderList, createSlots: _createSlots } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, _createSlots({ _: 1 }, [
|
_push(_ssrRenderComponent(_component_foo, _attrs, _createSlots({ _: 1 }, [
|
||||||
_renderList(_ctx.names, (key) => {
|
_renderList(_ctx.names, (key) => {
|
||||||
return {
|
return {
|
||||||
name: key,
|
name: key,
|
||||||
@ -210,10 +210,10 @@ describe('ssr: components', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode, createCommentVNode: _createCommentVNode } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode, createCommentVNode: _createCommentVNode } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, {
|
_push(_ssrRenderComponent(_component_foo, _attrs, {
|
||||||
foo: _withCtx(({ list }, _push, _parent, _scopeId) => {
|
foo: _withCtx(({ list }, _push, _parent, _scopeId) => {
|
||||||
if (_push) {
|
if (_push) {
|
||||||
if (_ctx.ok) {
|
if (_ctx.ok) {
|
||||||
@ -270,7 +270,7 @@ describe('ssr: components', () => {
|
|||||||
expect(compile(`<transition><div/></transition>`).code)
|
expect(compile(`<transition><div/></transition>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
@ -278,7 +278,7 @@ describe('ssr: components', () => {
|
|||||||
expect(compile(`<transition-group><div/></transition-group>`).code)
|
expect(compile(`<transition-group><div/></transition-group>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<!--[--><div></div><!--]-->\`)
|
_push(\`<!--[--><div></div><!--]-->\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
@ -288,7 +288,7 @@ describe('ssr: components', () => {
|
|||||||
"const { resolveComponent: _resolveComponent } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, null, _parent))
|
_push(_ssrRenderComponent(_component_foo, null, null, _parent))
|
||||||
|
@ -23,23 +23,28 @@ describe('ssr: element', () => {
|
|||||||
|
|
||||||
describe('children override', () => {
|
describe('children override', () => {
|
||||||
test('v-html', () => {
|
test('v-html', () => {
|
||||||
expect(getCompiledString(`<div v-html="foo"/>`)).toMatchInlineSnapshot(
|
expect(getCompiledString(`<div v-html="foo"/>`)).toMatchInlineSnapshot(`
|
||||||
`"\`<div>\${_ctx.foo}</div>\`"`
|
"\`<div>\${
|
||||||
)
|
_ctx.foo
|
||||||
|
}</div>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('v-text', () => {
|
test('v-text', () => {
|
||||||
expect(getCompiledString(`<div v-text="foo"/>`)).toMatchInlineSnapshot(
|
expect(getCompiledString(`<div v-text="foo"/>`)).toMatchInlineSnapshot(`
|
||||||
`"\`<div>\${_ssrInterpolate(_ctx.foo)}</div>\`"`
|
"\`<div>\${
|
||||||
)
|
_ssrInterpolate(_ctx.foo)
|
||||||
|
}</div>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<textarea> with dynamic value', () => {
|
test('<textarea> with dynamic value', () => {
|
||||||
expect(
|
expect(getCompiledString(`<textarea :value="foo"/>`))
|
||||||
getCompiledString(`<textarea :value="foo"/>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<textarea>\${
|
||||||
`"\`<textarea>\${_ssrInterpolate(_ctx.foo)}</textarea>\`"`
|
_ssrInterpolate(_ctx.foo)
|
||||||
)
|
}</textarea>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<textarea> with static value', () => {
|
test('<textarea> with static value', () => {
|
||||||
@ -51,13 +56,14 @@ describe('ssr: element', () => {
|
|||||||
test('<textarea> with dynamic v-bind', () => {
|
test('<textarea> with dynamic v-bind', () => {
|
||||||
expect(compile(`<textarea v-bind="obj">fallback</textarea>`).code)
|
expect(compile(`<textarea v-bind="obj">fallback</textarea>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
"const { mergeProps: _mergeProps } = require(\\"vue\\")
|
||||||
|
const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
let _temp0
|
let _temp0
|
||||||
|
|
||||||
_push(\`<textarea\${
|
_push(\`<textarea\${
|
||||||
_ssrRenderAttrs(_temp0 = _ctx.obj, \\"textarea\\")
|
_ssrRenderAttrs(_temp0 = _mergeProps(_ctx.obj, _attrs), \\"textarea\\")
|
||||||
}>\${
|
}>\${
|
||||||
_ssrInterpolate((\\"value\\" in _temp0) ? _temp0.value : \\"fallback\\")
|
_ssrInterpolate((\\"value\\" in _temp0) ? _temp0.value : \\"fallback\\")
|
||||||
}</textarea>\`)
|
}</textarea>\`)
|
||||||
@ -71,10 +77,11 @@ describe('ssr: element', () => {
|
|||||||
isCustomElement: () => true
|
isCustomElement: () => true
|
||||||
}).code
|
}).code
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
"const { mergeProps: _mergeProps } = require(\\"vue\\")
|
||||||
|
const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<my-foo\${_ssrRenderAttrs(_ctx.obj, \\"my-foo\\")}></my-foo>\`)
|
_push(\`<my-foo\${_ssrRenderAttrs(_mergeProps(_ctx.obj, _attrs), \\"my-foo\\")}></my-foo>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
@ -88,107 +95,126 @@ describe('ssr: element', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('v-bind:class', () => {
|
test('v-bind:class', () => {
|
||||||
expect(
|
expect(getCompiledString(`<div id="foo" :class="bar"></div>`))
|
||||||
getCompiledString(`<div id="foo" :class="bar"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<div id=\\"foo\\" class=\\"\${
|
||||||
`"\`<div id=\\"foo\\" class=\\"\${_ssrRenderClass(_ctx.bar)}\\"></div>\`"`
|
_ssrRenderClass(_ctx.bar)
|
||||||
)
|
}\\"></div>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('static class + v-bind:class', () => {
|
test('static class + v-bind:class', () => {
|
||||||
expect(
|
expect(getCompiledString(`<div class="foo" :class="bar"></div>`))
|
||||||
getCompiledString(`<div class="foo" :class="bar"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<div class=\\"\${
|
||||||
`"\`<div class=\\"\${_ssrRenderClass([_ctx.bar, \\"foo\\"])}\\"></div>\`"`
|
_ssrRenderClass([_ctx.bar, \\"foo\\"])
|
||||||
)
|
}\\"></div>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('v-bind:style', () => {
|
test('v-bind:style', () => {
|
||||||
expect(
|
expect(getCompiledString(`<div id="foo" :style="bar"></div>`))
|
||||||
getCompiledString(`<div id="foo" :style="bar"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<div id=\\"foo\\" style=\\"\${
|
||||||
`"\`<div id=\\"foo\\" style=\\"\${_ssrRenderStyle(_ctx.bar)}\\"></div>\`"`
|
_ssrRenderStyle(_ctx.bar)
|
||||||
)
|
}\\"></div>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('static style + v-bind:style', () => {
|
test('static style + v-bind:style', () => {
|
||||||
expect(
|
expect(getCompiledString(`<div style="color:red;" :style="bar"></div>`))
|
||||||
getCompiledString(`<div style="color:red;" :style="bar"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<div style=\\"\${
|
||||||
`"\`<div style=\\"\${_ssrRenderStyle([{\\"color\\":\\"red\\"}, _ctx.bar])}\\"></div>\`"`
|
_ssrRenderStyle([{\\"color\\":\\"red\\"}, _ctx.bar])
|
||||||
)
|
}\\"></div>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('v-bind:key (boolean)', () => {
|
test('v-bind:key (boolean)', () => {
|
||||||
expect(
|
expect(getCompiledString(`<input type="checkbox" :checked="checked">`))
|
||||||
getCompiledString(`<input type="checkbox" :checked="checked">`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<input type=\\"checkbox\\"\${
|
||||||
`"\`<input type=\\"checkbox\\"\${(_ctx.checked) ? \\" checked\\" : \\"\\"}>\`"`
|
(_ctx.checked) ? \\" checked\\" : \\"\\"
|
||||||
)
|
}>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('v-bind:key (non-boolean)', () => {
|
test('v-bind:key (non-boolean)', () => {
|
||||||
expect(
|
expect(getCompiledString(`<div :id="id" class="bar"></div>`))
|
||||||
getCompiledString(`<div :id="id" class="bar"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<div\${
|
||||||
`"\`<div\${_ssrRenderAttr(\\"id\\", _ctx.id)} class=\\"bar\\"></div>\`"`
|
_ssrRenderAttr(\\"id\\", _ctx.id)
|
||||||
)
|
} class=\\"bar\\"></div>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('v-bind:[key]', () => {
|
test('v-bind:[key]', () => {
|
||||||
expect(
|
expect(getCompiledString(`<div v-bind:[key]="value"></div>`))
|
||||||
getCompiledString(`<div v-bind:[key]="value"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<div\${
|
||||||
`"\`<div\${_ssrRenderAttrs({ [_ctx.key]: _ctx.value })}></div>\`"`
|
_ssrRenderAttrs({ [_ctx.key]: _ctx.value })
|
||||||
)
|
}></div>\`"
|
||||||
|
`)
|
||||||
|
|
||||||
expect(getCompiledString(`<div class="foo" v-bind:[key]="value"></div>`))
|
expect(getCompiledString(`<div class="foo" v-bind:[key]="value"></div>`))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"\`<div\${_ssrRenderAttrs({
|
"\`<div\${
|
||||||
class: \\"foo\\",
|
_ssrRenderAttrs({
|
||||||
[_ctx.key]: _ctx.value
|
class: \\"foo\\",
|
||||||
})}></div>\`"
|
[_ctx.key]: _ctx.value
|
||||||
|
})
|
||||||
|
}></div>\`"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(getCompiledString(`<div :id="id" v-bind:[key]="value"></div>`))
|
expect(getCompiledString(`<div :id="id" v-bind:[key]="value"></div>`))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"\`<div\${_ssrRenderAttrs({
|
"\`<div\${
|
||||||
id: _ctx.id,
|
_ssrRenderAttrs({
|
||||||
[_ctx.key]: _ctx.value
|
id: _ctx.id,
|
||||||
})}></div>\`"
|
[_ctx.key]: _ctx.value
|
||||||
|
})
|
||||||
|
}></div>\`"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('v-bind="obj"', () => {
|
test('v-bind="obj"', () => {
|
||||||
expect(
|
expect(getCompiledString(`<div v-bind="obj"></div>`))
|
||||||
getCompiledString(`<div v-bind="obj"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(`"\`<div\${_ssrRenderAttrs(_ctx.obj)}></div>\`"`)
|
"\`<div\${
|
||||||
|
_ssrRenderAttrs(_ctx.obj)
|
||||||
|
}></div>\`"
|
||||||
|
`)
|
||||||
|
|
||||||
expect(
|
expect(getCompiledString(`<div class="foo" v-bind="obj"></div>`))
|
||||||
getCompiledString(`<div class="foo" v-bind="obj"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<div\${
|
||||||
`"\`<div\${_ssrRenderAttrs(_mergeProps({ class: \\"foo\\" }, _ctx.obj))}></div>\`"`
|
_ssrRenderAttrs(_mergeProps({ class: \\"foo\\" }, _ctx.obj))
|
||||||
)
|
}></div>\`"
|
||||||
|
`)
|
||||||
|
|
||||||
expect(
|
expect(getCompiledString(`<div :id="id" v-bind="obj"></div>`))
|
||||||
getCompiledString(`<div :id="id" v-bind="obj"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<div\${
|
||||||
`"\`<div\${_ssrRenderAttrs(_mergeProps({ id: _ctx.id }, _ctx.obj))}></div>\`"`
|
_ssrRenderAttrs(_mergeProps({ id: _ctx.id }, _ctx.obj))
|
||||||
)
|
}></div>\`"
|
||||||
|
`)
|
||||||
|
|
||||||
// dynamic key + v-bind="object"
|
// dynamic key + v-bind="object"
|
||||||
expect(
|
expect(getCompiledString(`<div :[key]="id" v-bind="obj"></div>`))
|
||||||
getCompiledString(`<div :[key]="id" v-bind="obj"></div>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(
|
"\`<div\${
|
||||||
`"\`<div\${_ssrRenderAttrs(_mergeProps({ [_ctx.key]: _ctx.id }, _ctx.obj))}></div>\`"`
|
_ssrRenderAttrs(_mergeProps({ [_ctx.key]: _ctx.id }, _ctx.obj))
|
||||||
)
|
}></div>\`"
|
||||||
|
`)
|
||||||
|
|
||||||
// should merge class and :class
|
// should merge class and :class
|
||||||
expect(getCompiledString(`<div class="a" :class="b" v-bind="obj"></div>`))
|
expect(getCompiledString(`<div class="a" :class="b" v-bind="obj"></div>`))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"\`<div\${_ssrRenderAttrs(_mergeProps({
|
"\`<div\${
|
||||||
class: [\\"a\\", _ctx.b]
|
_ssrRenderAttrs(_mergeProps({
|
||||||
}, _ctx.obj))}></div>\`"
|
class: [\\"a\\", _ctx.b]
|
||||||
|
}, _ctx.obj))
|
||||||
|
}></div>\`"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
// should merge style and :style
|
// should merge style and :style
|
||||||
@ -197,9 +223,11 @@ describe('ssr: element', () => {
|
|||||||
`<div style="color:red;" :style="b" v-bind="obj"></div>`
|
`<div style="color:red;" :style="b" v-bind="obj"></div>`
|
||||||
)
|
)
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"\`<div\${_ssrRenderAttrs(_mergeProps({
|
"\`<div\${
|
||||||
style: [{\\"color\\":\\"red\\"}, _ctx.b]
|
_ssrRenderAttrs(_mergeProps({
|
||||||
}, _ctx.obj))}></div>\`"
|
style: [{\\"color\\":\\"red\\"}, _ctx.b]
|
||||||
|
}, _ctx.obj))
|
||||||
|
}></div>\`"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -210,9 +238,12 @@ describe('ssr: element', () => {
|
|||||||
expect(
|
expect(
|
||||||
getCompiledString(`<div id="foo" v-on="bar"/>`)
|
getCompiledString(`<div id="foo" v-on="bar"/>`)
|
||||||
).toMatchInlineSnapshot(`"\`<div id=\\"foo\\"></div>\`"`)
|
).toMatchInlineSnapshot(`"\`<div id=\\"foo\\"></div>\`"`)
|
||||||
expect(
|
expect(getCompiledString(`<div v-bind="foo" v-on="bar"/>`))
|
||||||
getCompiledString(`<div v-bind="foo" v-on="bar"/>`)
|
.toMatchInlineSnapshot(`
|
||||||
).toMatchInlineSnapshot(`"\`<div\${_ssrRenderAttrs(_ctx.foo)}></div>\`"`)
|
"\`<div\${
|
||||||
|
_ssrRenderAttrs(_ctx.foo)
|
||||||
|
}></div>\`"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -6,7 +6,7 @@ describe('ssr compile: teleport', () => {
|
|||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderTeleport: _ssrRenderTeleport } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderTeleport: _ssrRenderTeleport } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_ssrRenderTeleport(_push, (_push) => {
|
_ssrRenderTeleport(_push, (_push) => {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div></div>\`)
|
||||||
}, _ctx.target, false, _parent)
|
}, _ctx.target, false, _parent)
|
||||||
@ -18,26 +18,26 @@ describe('ssr compile: teleport', () => {
|
|||||||
expect(
|
expect(
|
||||||
compile(`<teleport :target="target" disabled><div/></teleport>`).code
|
compile(`<teleport :target="target" disabled><div/></teleport>`).code
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderTeleport: _ssrRenderTeleport } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderTeleport: _ssrRenderTeleport } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_ssrRenderTeleport(_push, (_push) => {
|
_ssrRenderTeleport(_push, (_push) => {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div></div>\`)
|
||||||
}, _ctx.target, true, _parent)
|
}, _ctx.target, true, _parent)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
compile(`<teleport :target="target" :disabled="foo"><div/></teleport>`)
|
compile(`<teleport :target="target" :disabled="foo"><div/></teleport>`)
|
||||||
.code
|
.code
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderTeleport: _ssrRenderTeleport } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderTeleport: _ssrRenderTeleport } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_ssrRenderTeleport(_push, (_push) => {
|
_ssrRenderTeleport(_push, (_push) => {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div></div>\`)
|
||||||
}, _ctx.target, _ctx.foo, _parent)
|
}, _ctx.target, _ctx.foo, _parent)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -9,9 +9,10 @@ describe('ssr: scopeId', () => {
|
|||||||
scopeId
|
scopeId
|
||||||
}).code
|
}).code
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
|
||||||
_push(\`<div data-v-xxxxxxx><span data-v-xxxxxxx>hello</span></div>\`)
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${_ssrRenderAttrs(_attrs)} data-v-xxxxxxx><span data-v-xxxxxxx>hello</span></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
@ -26,10 +27,10 @@ describe('ssr: scopeId', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, {
|
_push(_ssrRenderComponent(_component_foo, _attrs, {
|
||||||
default: _withCtx((_, _push, _parent, _scopeId) => {
|
default: _withCtx((_, _push, _parent, _scopeId) => {
|
||||||
if (_push) {
|
if (_push) {
|
||||||
_push(\`foo\`)
|
_push(\`foo\`)
|
||||||
@ -54,10 +55,10 @@ describe('ssr: scopeId', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, {
|
_push(_ssrRenderComponent(_component_foo, _attrs, {
|
||||||
default: _withCtx((_, _push, _parent, _scopeId) => {
|
default: _withCtx((_, _push, _parent, _scopeId) => {
|
||||||
if (_push) {
|
if (_push) {
|
||||||
_push(\`<span data-v-xxxxxxx\${_scopeId}>hello</span>\`)
|
_push(\`<span data-v-xxxxxxx\${_scopeId}>hello</span>\`)
|
||||||
@ -82,11 +83,11 @@ describe('ssr: scopeId', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
const _component_bar = _resolveComponent(\\"bar\\")
|
const _component_bar = _resolveComponent(\\"bar\\")
|
||||||
|
|
||||||
_push(_ssrRenderComponent(_component_foo, null, {
|
_push(_ssrRenderComponent(_component_foo, _attrs, {
|
||||||
default: _withCtx((_, _push, _parent, _scopeId) => {
|
default: _withCtx((_, _push, _parent, _scopeId) => {
|
||||||
if (_push) {
|
if (_push) {
|
||||||
_push(\`<span data-v-xxxxxxx\${_scopeId}>hello</span>\`)
|
_push(\`<span data-v-xxxxxxx\${_scopeId}>hello</span>\`)
|
||||||
|
@ -5,7 +5,7 @@ describe('ssr: <slot>', () => {
|
|||||||
expect(compile(`<slot/>`).code).toMatchInlineSnapshot(`
|
expect(compile(`<slot/>`).code).toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderSlot: _ssrRenderSlot } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderSlot: _ssrRenderSlot } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_ssrRenderSlot(_ctx.$slots, \\"default\\", {}, null, _push, _parent)
|
_ssrRenderSlot(_ctx.$slots, \\"default\\", {}, null, _push, _parent)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
@ -15,7 +15,7 @@ describe('ssr: <slot>', () => {
|
|||||||
expect(compile(`<slot name="foo" />`).code).toMatchInlineSnapshot(`
|
expect(compile(`<slot name="foo" />`).code).toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderSlot: _ssrRenderSlot } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderSlot: _ssrRenderSlot } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_ssrRenderSlot(_ctx.$slots, \\"foo\\", {}, null, _push, _parent)
|
_ssrRenderSlot(_ctx.$slots, \\"foo\\", {}, null, _push, _parent)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
@ -25,7 +25,7 @@ describe('ssr: <slot>', () => {
|
|||||||
expect(compile(`<slot :name="bar.baz" />`).code).toMatchInlineSnapshot(`
|
expect(compile(`<slot :name="bar.baz" />`).code).toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderSlot: _ssrRenderSlot } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderSlot: _ssrRenderSlot } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_ssrRenderSlot(_ctx.$slots, _ctx.bar.baz, {}, null, _push, _parent)
|
_ssrRenderSlot(_ctx.$slots, _ctx.bar.baz, {}, null, _push, _parent)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
@ -36,7 +36,7 @@ describe('ssr: <slot>', () => {
|
|||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderSlot: _ssrRenderSlot } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderSlot: _ssrRenderSlot } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_ssrRenderSlot(_ctx.$slots, \\"foo\\", {
|
_ssrRenderSlot(_ctx.$slots, \\"foo\\", {
|
||||||
p: 1,
|
p: 1,
|
||||||
bar: \\"2\\"
|
bar: \\"2\\"
|
||||||
@ -50,7 +50,7 @@ describe('ssr: <slot>', () => {
|
|||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderSlot: _ssrRenderSlot, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderSlot: _ssrRenderSlot, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_ssrRenderSlot(_ctx.$slots, \\"default\\", {}, () => {
|
_ssrRenderSlot(_ctx.$slots, \\"default\\", {}, () => {
|
||||||
_push(\`some \${_ssrInterpolate(_ctx.fallback)} content\`)
|
_push(\`some \${_ssrInterpolate(_ctx.fallback)} content\`)
|
||||||
}, _push, _parent)
|
}, _push, _parent)
|
||||||
|
@ -6,7 +6,7 @@ describe('ssr compile: suspense', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSuspense: _ssrRenderSuspense } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSuspense: _ssrRenderSuspense } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_ssrRenderSuspense(_push, {
|
_ssrRenderSuspense(_push, {
|
||||||
@ -33,7 +33,7 @@ describe('ssr compile: suspense', () => {
|
|||||||
"const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\\"vue\\")
|
"const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\\"vue\\")
|
||||||
const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSuspense: _ssrRenderSuspense } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSuspense: _ssrRenderSuspense } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
const _component_foo = _resolveComponent(\\"foo\\")
|
const _component_foo = _resolveComponent(\\"foo\\")
|
||||||
|
|
||||||
_ssrRenderSuspense(_push, {
|
_ssrRenderSuspense(_push, {
|
||||||
|
@ -45,7 +45,7 @@ describe('ssr: text', () => {
|
|||||||
expect(compile(`foo {{ bar }} baz`).code).toMatchInlineSnapshot(`
|
expect(compile(`foo {{ bar }} baz`).code).toMatchInlineSnapshot(`
|
||||||
"const { ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
"const { ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`foo \${_ssrInterpolate(_ctx.bar)} baz\`)
|
_push(\`foo \${_ssrInterpolate(_ctx.bar)} baz\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
@ -56,10 +56,12 @@ describe('ssr: text', () => {
|
|||||||
compile(`<div><span>{{ foo }} bar</span><span>baz {{ qux }}</span></div>`)
|
compile(`<div><span>{{ foo }} bar</span><span>baz {{ qux }}</span></div>`)
|
||||||
.code
|
.code
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<div><span>\${
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><span>\${
|
||||||
_ssrInterpolate(_ctx.foo)
|
_ssrInterpolate(_ctx.foo)
|
||||||
} bar</span><span>baz \${
|
} bar</span><span>baz \${
|
||||||
_ssrInterpolate(_ctx.qux)
|
_ssrInterpolate(_ctx.qux)
|
||||||
|
@ -5,7 +5,7 @@ describe('ssr: v-for', () => {
|
|||||||
expect(compile(`<div v-for="i in list" />`).code).toMatchInlineSnapshot(`
|
expect(compile(`<div v-for="i in list" />`).code).toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<!--[-->\`)
|
_push(\`<!--[-->\`)
|
||||||
_ssrRenderList(_ctx.list, (i) => {
|
_ssrRenderList(_ctx.list, (i) => {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div></div>\`)
|
||||||
@ -20,7 +20,7 @@ describe('ssr: v-for', () => {
|
|||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<!--[-->\`)
|
_push(\`<!--[-->\`)
|
||||||
_ssrRenderList(_ctx.list, (i) => {
|
_ssrRenderList(_ctx.list, (i) => {
|
||||||
_push(\`<div>foo<span>bar</span></div>\`)
|
_push(\`<div>foo<span>bar</span></div>\`)
|
||||||
@ -40,7 +40,7 @@ describe('ssr: v-for', () => {
|
|||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<!--[-->\`)
|
_push(\`<!--[-->\`)
|
||||||
_ssrRenderList(_ctx.list, (row, i) => {
|
_ssrRenderList(_ctx.list, (row, i) => {
|
||||||
_push(\`<div><!--[-->\`)
|
_push(\`<div><!--[-->\`)
|
||||||
@ -63,7 +63,7 @@ describe('ssr: v-for', () => {
|
|||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<!--[-->\`)
|
_push(\`<!--[-->\`)
|
||||||
_ssrRenderList(_ctx.list, (i) => {
|
_ssrRenderList(_ctx.list, (i) => {
|
||||||
_push(\`<!--[-->\${_ssrInterpolate(i)}<!--]-->\`)
|
_push(\`<!--[-->\${_ssrInterpolate(i)}<!--]-->\`)
|
||||||
@ -80,7 +80,7 @@ describe('ssr: v-for', () => {
|
|||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<!--[-->\`)
|
_push(\`<!--[-->\`)
|
||||||
_ssrRenderList(_ctx.list, (i) => {
|
_ssrRenderList(_ctx.list, (i) => {
|
||||||
_push(\`<span>\${_ssrInterpolate(i)}</span>\`)
|
_push(\`<span>\${_ssrInterpolate(i)}</span>\`)
|
||||||
@ -98,7 +98,7 @@ describe('ssr: v-for', () => {
|
|||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<!--[-->\`)
|
_push(\`<!--[-->\`)
|
||||||
_ssrRenderList(_ctx.list, (i) => {
|
_ssrRenderList(_ctx.list, (i) => {
|
||||||
_push(\`<!--[--><span>\${
|
_push(\`<!--[--><span>\${
|
||||||
@ -122,7 +122,7 @@ describe('ssr: v-for', () => {
|
|||||||
expect(code).toMatchInlineSnapshot(`
|
expect(code).toMatchInlineSnapshot(`
|
||||||
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<!--[-->\`)
|
_push(\`<!--[-->\`)
|
||||||
_ssrRenderList(_ctx.list, ({ foo }, index) => {
|
_ssrRenderList(_ctx.list, ({ foo }, index) => {
|
||||||
_push(\`<div>\${_ssrInterpolate(foo + _ctx.bar + index)}</div>\`)
|
_push(\`<div>\${_ssrInterpolate(foo + _ctx.bar + index)}</div>\`)
|
||||||
|
@ -3,10 +3,11 @@ import { compile } from '../src'
|
|||||||
describe('ssr: v-if', () => {
|
describe('ssr: v-if', () => {
|
||||||
test('basic', () => {
|
test('basic', () => {
|
||||||
expect(compile(`<div v-if="foo"></div>`).code).toMatchInlineSnapshot(`
|
expect(compile(`<div v-if="foo"></div>`).code).toMatchInlineSnapshot(`
|
||||||
"
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}></div>\`)
|
||||||
} else {
|
} else {
|
||||||
_push(\`<!---->\`)
|
_push(\`<!---->\`)
|
||||||
}
|
}
|
||||||
@ -17,10 +18,11 @@ describe('ssr: v-if', () => {
|
|||||||
test('with nested content', () => {
|
test('with nested content', () => {
|
||||||
expect(compile(`<div v-if="foo">hello<span>ok</span></div>`).code)
|
expect(compile(`<div v-if="foo">hello<span>ok</span></div>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<div>hello<span>ok</span></div>\`)
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}>hello<span>ok</span></div>\`)
|
||||||
} else {
|
} else {
|
||||||
_push(\`<!---->\`)
|
_push(\`<!---->\`)
|
||||||
}
|
}
|
||||||
@ -31,12 +33,13 @@ describe('ssr: v-if', () => {
|
|||||||
test('v-if + v-else', () => {
|
test('v-if + v-else', () => {
|
||||||
expect(compile(`<div v-if="foo"/><span v-else/>`).code)
|
expect(compile(`<div v-if="foo"/><span v-else/>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}></div>\`)
|
||||||
} else {
|
} else {
|
||||||
_push(\`<span></span>\`)
|
_push(\`<span\${_ssrRenderAttrs(_attrs)}></span>\`)
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
@ -45,12 +48,13 @@ describe('ssr: v-if', () => {
|
|||||||
test('v-if + v-else-if', () => {
|
test('v-if + v-else-if', () => {
|
||||||
expect(compile(`<div v-if="foo"/><span v-else-if="bar"/>`).code)
|
expect(compile(`<div v-if="foo"/><span v-else-if="bar"/>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}></div>\`)
|
||||||
} else if (_ctx.bar) {
|
} else if (_ctx.bar) {
|
||||||
_push(\`<span></span>\`)
|
_push(\`<span\${_ssrRenderAttrs(_attrs)}></span>\`)
|
||||||
} else {
|
} else {
|
||||||
_push(\`<!---->\`)
|
_push(\`<!---->\`)
|
||||||
}
|
}
|
||||||
@ -61,14 +65,15 @@ describe('ssr: v-if', () => {
|
|||||||
test('v-if + v-else-if + v-else', () => {
|
test('v-if + v-else-if + v-else', () => {
|
||||||
expect(compile(`<div v-if="foo"/><span v-else-if="bar"/><p v-else/>`).code)
|
expect(compile(`<div v-if="foo"/><span v-else-if="bar"/><p v-else/>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}></div>\`)
|
||||||
} else if (_ctx.bar) {
|
} else if (_ctx.bar) {
|
||||||
_push(\`<span></span>\`)
|
_push(\`<span\${_ssrRenderAttrs(_attrs)}></span>\`)
|
||||||
} else {
|
} else {
|
||||||
_push(\`<p></p>\`)
|
_push(\`<p\${_ssrRenderAttrs(_attrs)}></p>\`)
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
@ -78,7 +83,7 @@ describe('ssr: v-if', () => {
|
|||||||
expect(compile(`<template v-if="foo">hello</template>`).code)
|
expect(compile(`<template v-if="foo">hello</template>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<!--[-->hello<!--]-->\`)
|
_push(\`<!--[-->hello<!--]-->\`)
|
||||||
} else {
|
} else {
|
||||||
@ -92,10 +97,11 @@ describe('ssr: v-if', () => {
|
|||||||
// single element should not wrap with fragment
|
// single element should not wrap with fragment
|
||||||
expect(compile(`<template v-if="foo"><div>hi</div></template>`).code)
|
expect(compile(`<template v-if="foo"><div>hi</div></template>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<div>hi</div>\`)
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}>hi</div>\`)
|
||||||
} else {
|
} else {
|
||||||
_push(\`<!---->\`)
|
_push(\`<!---->\`)
|
||||||
}
|
}
|
||||||
@ -108,7 +114,7 @@ describe('ssr: v-if', () => {
|
|||||||
compile(`<template v-if="foo"><div>hi</div><div>ho</div></template>`).code
|
compile(`<template v-if="foo"><div>hi</div><div>ho</div></template>`).code
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<!--[--><div>hi</div><div>ho</div><!--]-->\`)
|
_push(\`<!--[--><div>hi</div><div>ho</div><!--]-->\`)
|
||||||
} else {
|
} else {
|
||||||
@ -124,7 +130,7 @@ describe('ssr: v-if', () => {
|
|||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<!--[-->\`)
|
_push(\`<!--[-->\`)
|
||||||
_ssrRenderList(_ctx.list, (i) => {
|
_ssrRenderList(_ctx.list, (i) => {
|
||||||
@ -144,12 +150,13 @@ describe('ssr: v-if', () => {
|
|||||||
`<template v-if="foo"><div>hi</div><div>ho</div></template><div v-else/>`
|
`<template v-if="foo"><div>hi</div><div>ho</div></template><div v-else/>`
|
||||||
).code
|
).code
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
if (_ctx.foo) {
|
if (_ctx.foo) {
|
||||||
_push(\`<!--[--><div>hi</div><div>ho</div><!--]-->\`)
|
_push(\`<!--[--><div>hi</div><div>ho</div><!--]-->\`)
|
||||||
} else {
|
} else {
|
||||||
_push(\`<div></div>\`)
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}></div>\`)
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
@ -1,136 +1,186 @@
|
|||||||
import { compile } from '../src'
|
import { compile } from '../src'
|
||||||
|
|
||||||
|
function compileWithWrapper(src: string) {
|
||||||
|
return compile(`<div>${src}</div>`)
|
||||||
|
}
|
||||||
|
|
||||||
describe('ssr: v-model', () => {
|
describe('ssr: v-model', () => {
|
||||||
test('<input> (text types)', () => {
|
test('<input> (text types)', () => {
|
||||||
expect(compile(`<input v-model="bar">`).code).toMatchInlineSnapshot(`
|
expect(compileWithWrapper(`<input v-model="bar">`).code)
|
||||||
"const { ssrRenderAttr: _ssrRenderAttr } = require(\\"@vue/server-renderer\\")
|
.toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<input\${_ssrRenderAttr(\\"value\\", _ctx.bar)}>\`)
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input\${
|
||||||
|
_ssrRenderAttr(\\"value\\", _ctx.bar)
|
||||||
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(compile(`<input type="email" v-model="bar">`).code)
|
expect(compileWithWrapper(`<input type="email" v-model="bar">`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderAttr: _ssrRenderAttr } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<input type=\\"email\\"\${_ssrRenderAttr(\\"value\\", _ctx.bar)}>\`)
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input type=\\"email\\"\${
|
||||||
|
_ssrRenderAttr(\\"value\\", _ctx.bar)
|
||||||
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<input type="radio">', () => {
|
test('<input type="radio">', () => {
|
||||||
expect(compile(`<input type="radio" value="foo" v-model="bar">`).code)
|
expect(
|
||||||
.toMatchInlineSnapshot(`
|
compileWithWrapper(`<input type="radio" value="foo" v-model="bar">`).code
|
||||||
"const { ssrLooseEqual: _ssrLooseEqual } = require(\\"@vue/server-renderer\\")
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<input type=\\"radio\\" value=\\"foo\\"\${(_ssrLooseEqual(_ctx.bar, \\"foo\\")) ? \\" checked\\" : \\"\\"}>\`)
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input type=\\"radio\\" value=\\"foo\\"\${
|
||||||
|
(_ssrLooseEqual(_ctx.bar, \\"foo\\")) ? \\" checked\\" : \\"\\"
|
||||||
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<input type="checkbox"', () => {
|
test('<input type="checkbox"', () => {
|
||||||
expect(compile(`<input type="checkbox" v-model="bar">`).code)
|
expect(compileWithWrapper(`<input type="checkbox" v-model="bar">`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrLooseContain: _ssrLooseContain } = require(\\"@vue/server-renderer\\")
|
"const { ssrLooseContain: _ssrLooseContain, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<input type=\\"checkbox\\"\${((Array.isArray(_ctx.bar))
|
_push(\`<div\${
|
||||||
? _ssrLooseContain(_ctx.bar, null)
|
_ssrRenderAttrs(_attrs)
|
||||||
: _ctx.bar) ? \\" checked\\" : \\"\\"}>\`)
|
}><input type=\\"checkbox\\"\${
|
||||||
|
((Array.isArray(_ctx.bar))
|
||||||
|
? _ssrLooseContain(_ctx.bar, null)
|
||||||
|
: _ctx.bar) ? \\" checked\\" : \\"\\"
|
||||||
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(compile(`<input type="checkbox" value="foo" v-model="bar">`).code)
|
expect(
|
||||||
.toMatchInlineSnapshot(`
|
compileWithWrapper(`<input type="checkbox" value="foo" v-model="bar">`)
|
||||||
"const { ssrLooseContain: _ssrLooseContain } = require(\\"@vue/server-renderer\\")
|
.code
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrLooseContain: _ssrLooseContain, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<input type=\\"checkbox\\" value=\\"foo\\"\${((Array.isArray(_ctx.bar))
|
_push(\`<div\${
|
||||||
? _ssrLooseContain(_ctx.bar, \\"foo\\")
|
_ssrRenderAttrs(_attrs)
|
||||||
: _ctx.bar) ? \\" checked\\" : \\"\\"}>\`)
|
}><input type=\\"checkbox\\" value=\\"foo\\"\${
|
||||||
|
((Array.isArray(_ctx.bar))
|
||||||
|
? _ssrLooseContain(_ctx.bar, \\"foo\\")
|
||||||
|
: _ctx.bar) ? \\" checked\\" : \\"\\"
|
||||||
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<textarea>', () => {
|
test('<textarea>', () => {
|
||||||
expect(compile(`<textarea v-model="foo">bar</textarea>`).code)
|
expect(compileWithWrapper(`<textarea v-model="foo">bar</textarea>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<textarea>\${_ssrInterpolate(_ctx.foo)}</textarea>\`)
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><textarea>\${
|
||||||
|
_ssrInterpolate(_ctx.foo)
|
||||||
|
}</textarea></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<input :type="x">', () => {
|
test('<input :type="x">', () => {
|
||||||
expect(compile(`<input :type="x" v-model="foo">`).code)
|
expect(compileWithWrapper(`<input :type="x" v-model="foo">`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<input\${
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input\${
|
||||||
_ssrRenderAttr(\\"type\\", _ctx.x)
|
_ssrRenderAttr(\\"type\\", _ctx.x)
|
||||||
}\${
|
}\${
|
||||||
_ssrRenderDynamicModel(_ctx.x, _ctx.foo, null)
|
_ssrRenderDynamicModel(_ctx.x, _ctx.foo, null)
|
||||||
}>\`)
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(compile(`<input :type="x" v-model="foo" value="bar">`).code)
|
expect(
|
||||||
.toMatchInlineSnapshot(`
|
compileWithWrapper(`<input :type="x" v-model="foo" value="bar">`).code
|
||||||
"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel } = require(\\"@vue/server-renderer\\")
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<input\${
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input\${
|
||||||
_ssrRenderAttr(\\"type\\", _ctx.x)
|
_ssrRenderAttr(\\"type\\", _ctx.x)
|
||||||
}\${
|
}\${
|
||||||
_ssrRenderDynamicModel(_ctx.x, _ctx.foo, \\"bar\\")
|
_ssrRenderDynamicModel(_ctx.x, _ctx.foo, \\"bar\\")
|
||||||
} value=\\"bar\\">\`)
|
} value=\\"bar\\"></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(compile(`<input :type="x" v-model="foo" :value="bar">`).code)
|
expect(
|
||||||
.toMatchInlineSnapshot(`
|
compileWithWrapper(`<input :type="x" v-model="foo" :value="bar">`).code
|
||||||
"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel } = require(\\"@vue/server-renderer\\")
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<input\${
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input\${
|
||||||
_ssrRenderAttr(\\"type\\", _ctx.x)
|
_ssrRenderAttr(\\"type\\", _ctx.x)
|
||||||
}\${
|
}\${
|
||||||
_ssrRenderDynamicModel(_ctx.x, _ctx.foo, _ctx.bar)
|
_ssrRenderDynamicModel(_ctx.x, _ctx.foo, _ctx.bar)
|
||||||
}\${
|
}\${
|
||||||
_ssrRenderAttr(\\"value\\", _ctx.bar)
|
_ssrRenderAttr(\\"value\\", _ctx.bar)
|
||||||
}>\`)
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<input v-bind="obj">', () => {
|
test('<input v-bind="obj">', () => {
|
||||||
expect(compile(`<input v-bind="obj" v-model="foo">`).code)
|
expect(compileWithWrapper(`<input v-bind="obj" v-model="foo">`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { mergeProps: _mergeProps } = require(\\"vue\\")
|
"const { mergeProps: _mergeProps } = require(\\"vue\\")
|
||||||
const { ssrRenderAttrs: _ssrRenderAttrs, ssrGetDynamicModelProps: _ssrGetDynamicModelProps } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderAttrs: _ssrRenderAttrs, ssrGetDynamicModelProps: _ssrGetDynamicModelProps } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
let _temp0
|
let _temp0
|
||||||
|
|
||||||
_push(\`<input\${_ssrRenderAttrs((_temp0 = _ctx.obj, _mergeProps(_temp0, _ssrGetDynamicModelProps(_temp0, _ctx.foo))))}>\`)
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input\${
|
||||||
|
_ssrRenderAttrs((_temp0 = _ctx.obj, _mergeProps(_temp0, _ssrGetDynamicModelProps(_temp0, _ctx.foo))))
|
||||||
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(compile(`<input id="x" v-bind="obj" v-model="foo" class="y">`).code)
|
expect(
|
||||||
.toMatchInlineSnapshot(`
|
compileWithWrapper(`<input id="x" v-bind="obj" v-model="foo" class="y">`)
|
||||||
|
.code
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
"const { mergeProps: _mergeProps } = require(\\"vue\\")
|
"const { mergeProps: _mergeProps } = require(\\"vue\\")
|
||||||
const { ssrRenderAttrs: _ssrRenderAttrs, ssrGetDynamicModelProps: _ssrGetDynamicModelProps } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderAttrs: _ssrRenderAttrs, ssrGetDynamicModelProps: _ssrGetDynamicModelProps } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
let _temp0
|
let _temp0
|
||||||
|
|
||||||
_push(\`<input\${_ssrRenderAttrs((_temp0 = _mergeProps({ id: \\"x\\" }, _ctx.obj, { class: \\"y\\" }), _mergeProps(_temp0, _ssrGetDynamicModelProps(_temp0, _ctx.foo))))}>\`)
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input\${
|
||||||
|
_ssrRenderAttrs((_temp0 = _mergeProps({ id: \\"x\\" }, _ctx.obj, { class: \\"y\\" }), _mergeProps(_temp0, _ssrGetDynamicModelProps(_temp0, _ctx.foo))))
|
||||||
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
@ -1,78 +1,118 @@
|
|||||||
import { compile } from '../src'
|
import { compile } from '../src'
|
||||||
|
|
||||||
describe('ssr: v-show', () => {
|
function compileWithWrapper(src: string) {
|
||||||
test('basic', () => {
|
return compile(`<div>${src}</div>`)
|
||||||
expect(compile(`<div v-show="foo"/>`).code).toMatchInlineSnapshot(`
|
}
|
||||||
"const { ssrRenderStyle: _ssrRenderStyle } = require(\\"@vue/server-renderer\\")
|
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
describe('ssr: v-show', () => {
|
||||||
_push(\`<div style=\\"\${_ssrRenderStyle((_ctx.foo) ? null : { display: \\"none\\" })}\\"></div>\`)
|
test('basic as root', () => {
|
||||||
|
expect(compile(`<div v-show="foo"/>`).code).toMatchInlineSnapshot(`
|
||||||
|
"const { mergeProps: _mergeProps } = require(\\"vue\\")
|
||||||
|
const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${_ssrRenderAttrs(_mergeProps({
|
||||||
|
style: (_ctx.foo) ? null : { display: \\"none\\" }
|
||||||
|
}, _attrs))}></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('basic', () => {
|
||||||
|
expect(compileWithWrapper(`<div v-show="foo"/>`).code)
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderStyle: _ssrRenderStyle, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><div style=\\"\${
|
||||||
|
_ssrRenderStyle((_ctx.foo) ? null : { display: \\"none\\" })
|
||||||
|
}\\"></div></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('with static style', () => {
|
test('with static style', () => {
|
||||||
expect(compile(`<div style="color:red" v-show="foo"/>`).code)
|
expect(compileWithWrapper(`<div style="color:red" v-show="foo"/>`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderStyle: _ssrRenderStyle } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderStyle: _ssrRenderStyle, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<div style=\\"\${_ssrRenderStyle([
|
_push(\`<div\${
|
||||||
{\\"color\\":\\"red\\"},
|
_ssrRenderAttrs(_attrs)
|
||||||
(_ctx.foo) ? null : { display: \\"none\\" }
|
}><div style=\\"\${
|
||||||
])}\\"></div>\`)
|
_ssrRenderStyle([
|
||||||
|
{\\"color\\":\\"red\\"},
|
||||||
|
(_ctx.foo) ? null : { display: \\"none\\" }
|
||||||
|
])
|
||||||
|
}\\"></div></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('with dynamic style', () => {
|
test('with dynamic style', () => {
|
||||||
expect(compile(`<div :style="{ color: 'red' }" v-show="foo"/>`).code)
|
expect(
|
||||||
.toMatchInlineSnapshot(`
|
compileWithWrapper(`<div :style="{ color: 'red' }" v-show="foo"/>`).code
|
||||||
"const { ssrRenderStyle: _ssrRenderStyle } = require(\\"@vue/server-renderer\\")
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderStyle: _ssrRenderStyle, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<div style=\\"\${_ssrRenderStyle([
|
_push(\`<div\${
|
||||||
{ color: 'red' },
|
_ssrRenderAttrs(_attrs)
|
||||||
(_ctx.foo) ? null : { display: \\"none\\" }
|
}><div style=\\"\${
|
||||||
])}\\"></div>\`)
|
_ssrRenderStyle([
|
||||||
|
{ color: 'red' },
|
||||||
|
(_ctx.foo) ? null : { display: \\"none\\" }
|
||||||
|
])
|
||||||
|
}\\"></div></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('with static + dynamic style', () => {
|
test('with static + dynamic style', () => {
|
||||||
expect(
|
expect(
|
||||||
compile(`<div style="color:red" :style="{ fontSize: 14 }" v-show="foo"/>`)
|
compileWithWrapper(
|
||||||
.code
|
`<div style="color:red" :style="{ fontSize: 14 }" v-show="foo"/>`
|
||||||
|
).code
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { ssrRenderStyle: _ssrRenderStyle } = require(\\"@vue/server-renderer\\")
|
"const { ssrRenderStyle: _ssrRenderStyle, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<div style=\\"\${_ssrRenderStyle([
|
_push(\`<div\${
|
||||||
{\\"color\\":\\"red\\"},
|
_ssrRenderAttrs(_attrs)
|
||||||
{ fontSize: 14 },
|
}><div style=\\"\${
|
||||||
(_ctx.foo) ? null : { display: \\"none\\" }
|
_ssrRenderStyle([
|
||||||
])}\\"></div>\`)
|
{\\"color\\":\\"red\\"},
|
||||||
|
{ fontSize: 14 },
|
||||||
|
(_ctx.foo) ? null : { display: \\"none\\" }
|
||||||
|
])
|
||||||
|
}\\"></div></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('with v-bind', () => {
|
test('with v-bind', () => {
|
||||||
expect(
|
expect(
|
||||||
compile(
|
compileWithWrapper(
|
||||||
`<div v-bind="baz" style="color:red" :style="{ fontSize: 14 }" v-show="foo"/>`
|
`<div v-bind="baz" style="color:red" :style="{ fontSize: 14 }" v-show="foo"/>`
|
||||||
).code
|
).code
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const { mergeProps: _mergeProps } = require(\\"vue\\")
|
"const { mergeProps: _mergeProps } = require(\\"vue\\")
|
||||||
const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent) {
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
_push(\`<div\${_ssrRenderAttrs(_mergeProps(_ctx.baz, {
|
_push(\`<div\${
|
||||||
style: [
|
_ssrRenderAttrs(_attrs)
|
||||||
{\\"color\\":\\"red\\"},
|
}><div\${
|
||||||
{ fontSize: 14 },
|
_ssrRenderAttrs(_mergeProps(_ctx.baz, {
|
||||||
(_ctx.foo) ? null : { display: \\"none\\" }
|
style: [
|
||||||
]
|
{\\"color\\":\\"red\\"},
|
||||||
}))}></div>\`)
|
{ fontSize: 14 },
|
||||||
|
(_ctx.foo) ? null : { display: \\"none\\" }
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
}></div></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,17 @@
|
|||||||
import { compile } from '../src'
|
import { compile } from '../src'
|
||||||
|
|
||||||
export function getCompiledString(src: string): string {
|
export function getCompiledString(src: string): string {
|
||||||
return compile(src).code.match(/_push\(([^]*)\)/)![1]
|
// Wrap src template in a root div so that it doesn't get injected
|
||||||
|
// fallthrough attr. This results in less noise in generated snapshots
|
||||||
|
// but also means this util can only be used for non-root cases.
|
||||||
|
const { code } = compile(`<div>${src}</div>`)
|
||||||
|
const match = code.match(
|
||||||
|
/_push\(\`<div\${\s*_ssrRenderAttrs\(_attrs\)\s*}>([^]*)<\/div>\`\)/
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
throw new Error(`Unexpected compile result:\n${code}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return `\`${match[1]}\``
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import { ssrTransformIf } from './transforms/ssrVIf'
|
|||||||
import { ssrTransformFor } from './transforms/ssrVFor'
|
import { ssrTransformFor } from './transforms/ssrVFor'
|
||||||
import { ssrTransformModel } from './transforms/ssrVModel'
|
import { ssrTransformModel } from './transforms/ssrVModel'
|
||||||
import { ssrTransformShow } from './transforms/ssrVShow'
|
import { ssrTransformShow } from './transforms/ssrVShow'
|
||||||
|
import { ssrInjectFallthroughAttrs } from './transforms/ssrInjectFallthroughAttrs'
|
||||||
|
|
||||||
export function compile(
|
export function compile(
|
||||||
template: string,
|
template: string,
|
||||||
@ -55,6 +56,7 @@ export function compile(
|
|||||||
trackVForSlotScopes,
|
trackVForSlotScopes,
|
||||||
transformExpression,
|
transformExpression,
|
||||||
ssrTransformSlotOutlet,
|
ssrTransformSlotOutlet,
|
||||||
|
ssrInjectFallthroughAttrs,
|
||||||
ssrTransformElement,
|
ssrTransformElement,
|
||||||
ssrTransformComponent,
|
ssrTransformComponent,
|
||||||
trackSlotScopes,
|
trackSlotScopes,
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
import {
|
||||||
|
NodeTransform,
|
||||||
|
NodeTypes,
|
||||||
|
ElementTypes,
|
||||||
|
locStub,
|
||||||
|
createSimpleExpression,
|
||||||
|
RootNode,
|
||||||
|
TemplateChildNode,
|
||||||
|
ParentNode,
|
||||||
|
findDir
|
||||||
|
} from '@vue/compiler-dom'
|
||||||
|
|
||||||
|
const hasSingleChild = (node: ParentNode): boolean =>
|
||||||
|
node.children.filter(n => n.type !== NodeTypes.COMMENT).length === 1
|
||||||
|
|
||||||
|
export const ssrInjectFallthroughAttrs: NodeTransform = (node, context) => {
|
||||||
|
// _attrs is provided as a function argument.
|
||||||
|
// mark it as a known identifier so that it doesn't get prefixed by
|
||||||
|
// transformExpression.
|
||||||
|
if (node.type === NodeTypes.ROOT) {
|
||||||
|
context.identifiers._attrs = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = context.parent
|
||||||
|
if (!parent || parent.type !== NodeTypes.ROOT) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.type === NodeTypes.IF_BRANCH && hasSingleChild(node)) {
|
||||||
|
injectFallthroughAttrs(node.children[0])
|
||||||
|
} else if (hasSingleChild(parent)) {
|
||||||
|
injectFallthroughAttrs(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function injectFallthroughAttrs(node: RootNode | TemplateChildNode) {
|
||||||
|
if (
|
||||||
|
node.type === NodeTypes.ELEMENT &&
|
||||||
|
(node.tagType === ElementTypes.ELEMENT ||
|
||||||
|
node.tagType === ElementTypes.COMPONENT) &&
|
||||||
|
!findDir(node, 'for')
|
||||||
|
) {
|
||||||
|
node.props.push({
|
||||||
|
type: NodeTypes.DIRECTIVE,
|
||||||
|
name: 'bind',
|
||||||
|
arg: undefined,
|
||||||
|
exp: createSimpleExpression(`_attrs`, false),
|
||||||
|
modifiers: [],
|
||||||
|
loc: locStub
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,8 @@ import {
|
|||||||
hasDynamicKeyVBind,
|
hasDynamicKeyVBind,
|
||||||
MERGE_PROPS,
|
MERGE_PROPS,
|
||||||
isBindKey,
|
isBindKey,
|
||||||
createSequenceExpression
|
createSequenceExpression,
|
||||||
|
InterpolationNode
|
||||||
} from '@vue/compiler-dom'
|
} from '@vue/compiler-dom'
|
||||||
import {
|
import {
|
||||||
escapeHtml,
|
escapeHtml,
|
||||||
@ -53,30 +54,40 @@ const rawChildrenMap = new WeakMap<
|
|||||||
|
|
||||||
export const ssrTransformElement: NodeTransform = (node, context) => {
|
export const ssrTransformElement: NodeTransform = (node, context) => {
|
||||||
if (
|
if (
|
||||||
node.type === NodeTypes.ELEMENT &&
|
node.type !== NodeTypes.ELEMENT ||
|
||||||
node.tagType === ElementTypes.ELEMENT
|
node.tagType !== ElementTypes.ELEMENT
|
||||||
) {
|
) {
|
||||||
return function ssrPostTransformElement() {
|
return
|
||||||
// element
|
}
|
||||||
// generate the template literal representing the open tag.
|
|
||||||
const openTag: TemplateLiteral['elements'] = [`<${node.tag}`]
|
|
||||||
// some tags need to be pasesd to runtime for special checks
|
|
||||||
const needTagForRuntime =
|
|
||||||
node.tag === 'textarea' || node.tag.indexOf('-') > 0
|
|
||||||
|
|
||||||
// v-bind="obj" or v-bind:[key] can potentially overwrite other static
|
return function ssrPostTransformElement() {
|
||||||
// attrs and can affect final rendering result, so when they are present
|
// element
|
||||||
// we need to bail out to full `renderAttrs`
|
// generate the template literal representing the open tag.
|
||||||
const hasDynamicVBind = hasDynamicKeyVBind(node)
|
const openTag: TemplateLiteral['elements'] = [`<${node.tag}`]
|
||||||
if (hasDynamicVBind) {
|
// some tags need to be pasesd to runtime for special checks
|
||||||
const { props } = buildProps(node, context, node.props, true /* ssr */)
|
const needTagForRuntime =
|
||||||
if (props) {
|
node.tag === 'textarea' || node.tag.indexOf('-') > 0
|
||||||
const propsExp = createCallExpression(
|
|
||||||
context.helper(SSR_RENDER_ATTRS),
|
|
||||||
[props]
|
|
||||||
)
|
|
||||||
|
|
||||||
if (node.tag === 'textarea') {
|
// v-bind="obj" or v-bind:[key] can potentially overwrite other static
|
||||||
|
// attrs and can affect final rendering result, so when they are present
|
||||||
|
// we need to bail out to full `renderAttrs`
|
||||||
|
const hasDynamicVBind = hasDynamicKeyVBind(node)
|
||||||
|
if (hasDynamicVBind) {
|
||||||
|
const { props } = buildProps(node, context, node.props, true /* ssr */)
|
||||||
|
if (props) {
|
||||||
|
const propsExp = createCallExpression(
|
||||||
|
context.helper(SSR_RENDER_ATTRS),
|
||||||
|
[props]
|
||||||
|
)
|
||||||
|
|
||||||
|
if (node.tag === 'textarea') {
|
||||||
|
const existingText = node.children[0] as
|
||||||
|
| TextNode
|
||||||
|
| InterpolationNode
|
||||||
|
| undefined
|
||||||
|
// If interpolation, this is dynamic <textarea> content, potentially
|
||||||
|
// injected by v-model and takes higher priority than v-bind value
|
||||||
|
if (!existingText || existingText.type !== NodeTypes.INTERPOLATION) {
|
||||||
// <textarea> with dynamic v-bind. We don't know if the final props
|
// <textarea> with dynamic v-bind. We don't know if the final props
|
||||||
// will contain .value, so we will have to do something special:
|
// will contain .value, so we will have to do something special:
|
||||||
// assign the merged props to a temp variable, and check whether
|
// assign the merged props to a temp variable, and check whether
|
||||||
@ -88,7 +99,6 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
|
|||||||
props
|
props
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
const existingText = node.children[0] as TextNode | undefined
|
|
||||||
rawChildrenMap.set(
|
rawChildrenMap.set(
|
||||||
node,
|
node,
|
||||||
createCallExpression(context.helper(SSR_INTERPOLATE), [
|
createCallExpression(context.helper(SSR_INTERPOLATE), [
|
||||||
@ -103,189 +113,189 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
|
|||||||
)
|
)
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
} else if (node.tag === 'input') {
|
}
|
||||||
// <input v-bind="obj" v-model>
|
} else if (node.tag === 'input') {
|
||||||
// we need to determine the props to render for the dynamic v-model
|
// <input v-bind="obj" v-model>
|
||||||
// and merge it with the v-bind expression.
|
// we need to determine the props to render for the dynamic v-model
|
||||||
const vModel = findVModel(node)
|
// and merge it with the v-bind expression.
|
||||||
if (vModel) {
|
const vModel = findVModel(node)
|
||||||
// 1. save the props (san v-model) in a temp variable
|
if (vModel) {
|
||||||
const tempId = `_temp${context.temps++}`
|
// 1. save the props (san v-model) in a temp variable
|
||||||
const tempExp = createSimpleExpression(tempId, false)
|
const tempId = `_temp${context.temps++}`
|
||||||
propsExp.arguments = [
|
const tempExp = createSimpleExpression(tempId, false)
|
||||||
createSequenceExpression([
|
propsExp.arguments = [
|
||||||
createAssignmentExpression(tempExp, props),
|
createSequenceExpression([
|
||||||
createCallExpression(context.helper(MERGE_PROPS), [
|
createAssignmentExpression(tempExp, props),
|
||||||
tempExp,
|
createCallExpression(context.helper(MERGE_PROPS), [
|
||||||
createCallExpression(
|
tempExp,
|
||||||
context.helper(SSR_GET_DYNAMIC_MODEL_PROPS),
|
createCallExpression(
|
||||||
[
|
context.helper(SSR_GET_DYNAMIC_MODEL_PROPS),
|
||||||
tempExp, // existing props
|
[
|
||||||
vModel.exp! // model
|
tempExp, // existing props
|
||||||
]
|
vModel.exp! // model
|
||||||
)
|
]
|
||||||
])
|
)
|
||||||
])
|
])
|
||||||
]
|
])
|
||||||
}
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needTagForRuntime) {
|
|
||||||
propsExp.arguments.push(`"${node.tag}"`)
|
|
||||||
}
|
|
||||||
|
|
||||||
openTag.push(propsExp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needTagForRuntime) {
|
||||||
|
propsExp.arguments.push(`"${node.tag}"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
openTag.push(propsExp)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// book keeping static/dynamic class merging.
|
// book keeping static/dynamic class merging.
|
||||||
let dynamicClassBinding: CallExpression | undefined = undefined
|
let dynamicClassBinding: CallExpression | undefined = undefined
|
||||||
let staticClassBinding: string | undefined = undefined
|
let staticClassBinding: string | undefined = undefined
|
||||||
// all style bindings are converted to dynamic by transformStyle.
|
// all style bindings are converted to dynamic by transformStyle.
|
||||||
// but we need to make sure to merge them.
|
// but we need to make sure to merge them.
|
||||||
let dynamicStyleBinding: CallExpression | undefined = undefined
|
let dynamicStyleBinding: CallExpression | undefined = undefined
|
||||||
|
|
||||||
for (let i = 0; i < node.props.length; i++) {
|
for (let i = 0; i < node.props.length; i++) {
|
||||||
const prop = node.props[i]
|
const prop = node.props[i]
|
||||||
// special cases with children override
|
// special cases with children override
|
||||||
if (prop.type === NodeTypes.DIRECTIVE) {
|
if (prop.type === NodeTypes.DIRECTIVE) {
|
||||||
if (prop.name === 'html' && prop.exp) {
|
if (prop.name === 'html' && prop.exp) {
|
||||||
rawChildrenMap.set(node, prop.exp)
|
rawChildrenMap.set(node, prop.exp)
|
||||||
} else if (prop.name === 'text' && prop.exp) {
|
} else if (prop.name === 'text' && prop.exp) {
|
||||||
|
node.children = [createInterpolation(prop.exp, prop.loc)]
|
||||||
|
} else if (prop.name === 'slot') {
|
||||||
|
context.onError(
|
||||||
|
createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, prop.loc)
|
||||||
|
)
|
||||||
|
} else if (isTextareaWithValue(node, prop) && prop.exp) {
|
||||||
|
if (!hasDynamicVBind) {
|
||||||
node.children = [createInterpolation(prop.exp, prop.loc)]
|
node.children = [createInterpolation(prop.exp, prop.loc)]
|
||||||
} else if (prop.name === 'slot') {
|
}
|
||||||
|
} else {
|
||||||
|
// Directive transforms.
|
||||||
|
const directiveTransform = context.directiveTransforms[prop.name]
|
||||||
|
if (!directiveTransform) {
|
||||||
|
// no corresponding ssr directive transform found.
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, prop.loc)
|
createSSRCompilerError(
|
||||||
|
SSRErrorCodes.X_SSR_CUSTOM_DIRECTIVE_NO_TRANSFORM,
|
||||||
|
prop.loc
|
||||||
|
)
|
||||||
)
|
)
|
||||||
} else if (isTextareaWithValue(node, prop) && prop.exp) {
|
} else if (!hasDynamicVBind) {
|
||||||
if (!hasDynamicVBind) {
|
const { props, ssrTagParts } = directiveTransform(
|
||||||
node.children = [createInterpolation(prop.exp, prop.loc)]
|
prop,
|
||||||
|
node,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
if (ssrTagParts) {
|
||||||
|
openTag.push(...ssrTagParts)
|
||||||
}
|
}
|
||||||
} else {
|
for (let j = 0; j < props.length; j++) {
|
||||||
// Directive transforms.
|
const { key, value } = props[j]
|
||||||
const directiveTransform = context.directiveTransforms[prop.name]
|
if (key.type === NodeTypes.SIMPLE_EXPRESSION && key.isStatic) {
|
||||||
if (!directiveTransform) {
|
let attrName = key.content
|
||||||
// no corresponding ssr directive transform found.
|
// static key attr
|
||||||
context.onError(
|
if (attrName === 'class') {
|
||||||
createSSRCompilerError(
|
openTag.push(
|
||||||
SSRErrorCodes.X_SSR_CUSTOM_DIRECTIVE_NO_TRANSFORM,
|
` class="`,
|
||||||
prop.loc
|
(dynamicClassBinding = createCallExpression(
|
||||||
)
|
context.helper(SSR_RENDER_CLASS),
|
||||||
)
|
[value]
|
||||||
} else if (!hasDynamicVBind) {
|
)),
|
||||||
const { props, ssrTagParts } = directiveTransform(
|
`"`
|
||||||
prop,
|
)
|
||||||
node,
|
} else if (attrName === 'style') {
|
||||||
context
|
if (dynamicStyleBinding) {
|
||||||
)
|
// already has style binding, merge into it.
|
||||||
if (ssrTagParts) {
|
mergeCall(dynamicStyleBinding, value)
|
||||||
openTag.push(...ssrTagParts)
|
} else {
|
||||||
}
|
|
||||||
for (let j = 0; j < props.length; j++) {
|
|
||||||
const { key, value } = props[j]
|
|
||||||
if (key.type === NodeTypes.SIMPLE_EXPRESSION && key.isStatic) {
|
|
||||||
let attrName = key.content
|
|
||||||
// static key attr
|
|
||||||
if (attrName === 'class') {
|
|
||||||
openTag.push(
|
openTag.push(
|
||||||
` class="`,
|
` style="`,
|
||||||
(dynamicClassBinding = createCallExpression(
|
(dynamicStyleBinding = createCallExpression(
|
||||||
context.helper(SSR_RENDER_CLASS),
|
context.helper(SSR_RENDER_STYLE),
|
||||||
[value]
|
[value]
|
||||||
)),
|
)),
|
||||||
`"`
|
`"`
|
||||||
)
|
)
|
||||||
} else if (attrName === 'style') {
|
|
||||||
if (dynamicStyleBinding) {
|
|
||||||
// already has style binding, merge into it.
|
|
||||||
mergeCall(dynamicStyleBinding, value)
|
|
||||||
} else {
|
|
||||||
openTag.push(
|
|
||||||
` style="`,
|
|
||||||
(dynamicStyleBinding = createCallExpression(
|
|
||||||
context.helper(SSR_RENDER_STYLE),
|
|
||||||
[value]
|
|
||||||
)),
|
|
||||||
`"`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
attrName =
|
|
||||||
node.tag.indexOf('-') > 0
|
|
||||||
? attrName // preserve raw name on custom elements
|
|
||||||
: propsToAttrMap[attrName] || attrName.toLowerCase()
|
|
||||||
if (isBooleanAttr(attrName)) {
|
|
||||||
openTag.push(
|
|
||||||
createConditionalExpression(
|
|
||||||
value,
|
|
||||||
createSimpleExpression(' ' + attrName, true),
|
|
||||||
createSimpleExpression('', true),
|
|
||||||
false /* no newline */
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else if (isSSRSafeAttrName(attrName)) {
|
|
||||||
openTag.push(
|
|
||||||
createCallExpression(context.helper(SSR_RENDER_ATTR), [
|
|
||||||
key,
|
|
||||||
value
|
|
||||||
])
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
context.onError(
|
|
||||||
createSSRCompilerError(
|
|
||||||
SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME,
|
|
||||||
key.loc
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// dynamic key attr
|
attrName =
|
||||||
// this branch is only encountered for custom directive
|
node.tag.indexOf('-') > 0
|
||||||
// transforms that returns properties with dynamic keys
|
? attrName // preserve raw name on custom elements
|
||||||
const args: CallExpression['arguments'] = [key, value]
|
: propsToAttrMap[attrName] || attrName.toLowerCase()
|
||||||
if (needTagForRuntime) {
|
if (isBooleanAttr(attrName)) {
|
||||||
args.push(`"${node.tag}"`)
|
openTag.push(
|
||||||
}
|
createConditionalExpression(
|
||||||
openTag.push(
|
value,
|
||||||
createCallExpression(
|
createSimpleExpression(' ' + attrName, true),
|
||||||
context.helper(SSR_RENDER_DYNAMIC_ATTR),
|
createSimpleExpression('', true),
|
||||||
args
|
false /* no newline */
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
} else if (isSSRSafeAttrName(attrName)) {
|
||||||
|
openTag.push(
|
||||||
|
createCallExpression(context.helper(SSR_RENDER_ATTR), [
|
||||||
|
key,
|
||||||
|
value
|
||||||
|
])
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
context.onError(
|
||||||
|
createSSRCompilerError(
|
||||||
|
SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME,
|
||||||
|
key.loc
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// dynamic key attr
|
||||||
|
// this branch is only encountered for custom directive
|
||||||
|
// transforms that returns properties with dynamic keys
|
||||||
|
const args: CallExpression['arguments'] = [key, value]
|
||||||
|
if (needTagForRuntime) {
|
||||||
|
args.push(`"${node.tag}"`)
|
||||||
|
}
|
||||||
|
openTag.push(
|
||||||
|
createCallExpression(
|
||||||
|
context.helper(SSR_RENDER_DYNAMIC_ATTR),
|
||||||
|
args
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// special case: value on <textarea>
|
} else {
|
||||||
if (node.tag === 'textarea' && prop.name === 'value' && prop.value) {
|
// special case: value on <textarea>
|
||||||
rawChildrenMap.set(node, escapeHtml(prop.value.content))
|
if (node.tag === 'textarea' && prop.name === 'value' && prop.value) {
|
||||||
} else if (!hasDynamicVBind) {
|
rawChildrenMap.set(node, escapeHtml(prop.value.content))
|
||||||
// static prop
|
} else if (!hasDynamicVBind) {
|
||||||
if (prop.name === 'class' && prop.value) {
|
// static prop
|
||||||
staticClassBinding = JSON.stringify(prop.value.content)
|
if (prop.name === 'class' && prop.value) {
|
||||||
}
|
staticClassBinding = JSON.stringify(prop.value.content)
|
||||||
openTag.push(
|
|
||||||
` ${prop.name}` +
|
|
||||||
(prop.value ? `="${escapeHtml(prop.value.content)}"` : ``)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
openTag.push(
|
||||||
|
` ${prop.name}` +
|
||||||
|
(prop.value ? `="${escapeHtml(prop.value.content)}"` : ``)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle co-existence of dynamic + static class bindings
|
|
||||||
if (dynamicClassBinding && staticClassBinding) {
|
|
||||||
mergeCall(dynamicClassBinding, staticClassBinding)
|
|
||||||
removeStaticBinding(openTag, 'class')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.scopeId) {
|
|
||||||
openTag.push(` ${context.scopeId}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
node.ssrCodegenNode = createTemplateLiteral(openTag)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle co-existence of dynamic + static class bindings
|
||||||
|
if (dynamicClassBinding && staticClassBinding) {
|
||||||
|
mergeCall(dynamicClassBinding, staticClassBinding)
|
||||||
|
removeStaticBinding(openTag, 'class')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.scopeId) {
|
||||||
|
openTag.push(` ${context.scopeId}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
node.ssrCodegenNode = createTemplateLiteral(openTag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,8 @@ export interface ComponentOptionsBase<
|
|||||||
ssrRender?: (
|
ssrRender?: (
|
||||||
ctx: any,
|
ctx: any,
|
||||||
push: (item: any) => void,
|
push: (item: any) => void,
|
||||||
parentInstance: ComponentInternalInstance
|
parentInstance: ComponentInternalInstance,
|
||||||
|
attrs?: Data
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -554,8 +554,7 @@ export function normalizeChildren(vnode: VNode, children: unknown) {
|
|||||||
const handlersRE = /^on|^vnode/
|
const handlersRE = /^on|^vnode/
|
||||||
|
|
||||||
export function mergeProps(...args: (Data & VNodeProps)[]) {
|
export function mergeProps(...args: (Data & VNodeProps)[]) {
|
||||||
const ret: Data = {}
|
const ret = extend({}, args[0])
|
||||||
extend(ret, args[0])
|
|
||||||
for (let i = 1; i < args.length; i++) {
|
for (let i = 1; i < args.length; i++) {
|
||||||
const toMerge = args[i]
|
const toMerge = args[i]
|
||||||
for (const key in toMerge) {
|
for (const key in toMerge) {
|
||||||
|
@ -65,7 +65,7 @@ describe('ssr: renderToString', () => {
|
|||||||
expect(
|
expect(
|
||||||
await renderToString(
|
await renderToString(
|
||||||
createApp(
|
createApp(
|
||||||
defineComponent((props: {}) => {
|
defineComponent(() => {
|
||||||
const msg = ref('hello')
|
const msg = ref('hello')
|
||||||
return () => h('div', msg.value)
|
return () => h('div', msg.value)
|
||||||
})
|
})
|
||||||
@ -89,31 +89,6 @@ describe('ssr: renderToString', () => {
|
|||||||
).toBe(`<div>hello</div>`)
|
).toBe(`<div>hello</div>`)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('template components', () => {
|
|
||||||
test('render', async () => {
|
|
||||||
expect(
|
|
||||||
await renderToString(
|
|
||||||
createApp({
|
|
||||||
data() {
|
|
||||||
return { msg: 'hello' }
|
|
||||||
},
|
|
||||||
template: `<div>{{ msg }}</div>`
|
|
||||||
})
|
|
||||||
)
|
|
||||||
).toBe(`<div>hello</div>`)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('handle compiler errors', async () => {
|
|
||||||
await renderToString(createApp({ template: `<` }))
|
|
||||||
|
|
||||||
expect(
|
|
||||||
'Template compilation error: Unexpected EOF in tag.\n' +
|
|
||||||
'1 | <\n' +
|
|
||||||
' | ^'
|
|
||||||
).toHaveBeenWarned()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test('nested vnode components', async () => {
|
test('nested vnode components', async () => {
|
||||||
const Child = {
|
const Child = {
|
||||||
props: ['msg'],
|
props: ['msg'],
|
||||||
@ -247,7 +222,7 @@ describe('ssr: renderToString', () => {
|
|||||||
{ msg: 'hello' },
|
{ msg: 'hello' },
|
||||||
{
|
{
|
||||||
// optimized slot using string push
|
// optimized slot using string push
|
||||||
default: ({ msg }: any, push: any, p: any) => {
|
default: ({ msg }: any, push: any, _p: any) => {
|
||||||
push(`<span>${msg}</span>`)
|
push(`<span>${msg}</span>`)
|
||||||
},
|
},
|
||||||
// important to avoid slots being normalized
|
// important to avoid slots being normalized
|
||||||
@ -583,4 +558,29 @@ describe('ssr: renderToString', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('integration w/ compiled template', () => {
|
||||||
|
test('render', async () => {
|
||||||
|
expect(
|
||||||
|
await renderToString(
|
||||||
|
createApp({
|
||||||
|
data() {
|
||||||
|
return { msg: 'hello' }
|
||||||
|
},
|
||||||
|
template: `<div>{{ msg }}</div>`
|
||||||
|
})
|
||||||
|
)
|
||||||
|
).toBe(`<div>hello</div>`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('handle compiler errors', async () => {
|
||||||
|
await renderToString(createApp({ template: `<` }))
|
||||||
|
|
||||||
|
expect(
|
||||||
|
'Template compilation error: Unexpected EOF in tag.\n' +
|
||||||
|
'1 | <\n' +
|
||||||
|
' | ^'
|
||||||
|
).toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import { renderToString } from '../src/renderToString'
|
||||||
|
|
||||||
|
describe('ssr: attr fallthrough', () => {
|
||||||
|
test('basic', async () => {
|
||||||
|
const Child = {
|
||||||
|
template: `<div class="foo" />`
|
||||||
|
}
|
||||||
|
const Parent = {
|
||||||
|
components: { Child },
|
||||||
|
template: `<child class="bar"/>`
|
||||||
|
}
|
||||||
|
const app = createApp(Parent)
|
||||||
|
expect(await renderToString(app)).toBe(`<div class="foo bar"></div>`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('with v-if', async () => {
|
||||||
|
const Child = {
|
||||||
|
props: ['ok'],
|
||||||
|
template: `<div v-if="ok" class="foo" /><span v-else />`
|
||||||
|
}
|
||||||
|
const Parent = {
|
||||||
|
props: ['ok'],
|
||||||
|
components: { Child },
|
||||||
|
template: `<child :ok="ok" class="bar"/>`
|
||||||
|
}
|
||||||
|
expect(await renderToString(createApp(Parent, { ok: true }))).toBe(
|
||||||
|
`<div class="foo bar"></div>`
|
||||||
|
)
|
||||||
|
expect(await renderToString(createApp(Parent, { ok: false }))).toBe(
|
||||||
|
`<span class="bar"></span>`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('with v-model', async () => {
|
||||||
|
const Child = {
|
||||||
|
props: ['text'],
|
||||||
|
template: `<input v-model="text">`
|
||||||
|
}
|
||||||
|
const Parent = {
|
||||||
|
components: { Child },
|
||||||
|
template: `<child text="hello" class="bar"/>`
|
||||||
|
}
|
||||||
|
expect(await renderToString(createApp(Parent))).toBe(
|
||||||
|
`<input class="bar" value="hello">`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('with v-bind', async () => {
|
||||||
|
const Child = {
|
||||||
|
props: ['obj'],
|
||||||
|
template: `<div v-bind="obj" />`
|
||||||
|
}
|
||||||
|
const Parent = {
|
||||||
|
components: { Child },
|
||||||
|
template: `<child :obj="{ class: 'foo' }" class="bar"/>`
|
||||||
|
}
|
||||||
|
expect(await renderToString(createApp(Parent))).toBe(
|
||||||
|
`<div class="foo bar"></div>`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('nested fallthrough', async () => {
|
||||||
|
const Child = {
|
||||||
|
props: ['id'],
|
||||||
|
template: `<div :id="id"></div>`
|
||||||
|
}
|
||||||
|
const Parent = {
|
||||||
|
components: { Child },
|
||||||
|
template: `<child id="foo" class="bar"/>`
|
||||||
|
}
|
||||||
|
// pass to parent, fallthrough to child and merge
|
||||||
|
const app = createApp(Parent, { class: 'baz' })
|
||||||
|
expect(await renderToString(app)).toBe(
|
||||||
|
`<div id="foo" class="bar baz"></div>`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
@ -111,7 +111,10 @@ function renderComponentSubTree(
|
|||||||
// optimized
|
// optimized
|
||||||
// set current rendering instance for asset resolution
|
// set current rendering instance for asset resolution
|
||||||
setCurrentRenderingInstance(instance)
|
setCurrentRenderingInstance(instance)
|
||||||
comp.ssrRender(instance.proxy, push, instance)
|
// fallthrough attrs
|
||||||
|
const attrs =
|
||||||
|
instance.type.inheritAttrs !== false ? instance.attrs : undefined
|
||||||
|
comp.ssrRender(instance.proxy, push, instance, attrs)
|
||||||
setCurrentRenderingInstance(null)
|
setCurrentRenderingInstance(null)
|
||||||
} else if (instance.render) {
|
} else if (instance.render) {
|
||||||
renderVNode(push, renderComponentRoot(instance), instance)
|
renderVNode(push, renderComponentRoot(instance), instance)
|
||||||
|
Loading…
Reference in New Issue
Block a user