From 090eb0ce677dd137ab4fedba579488529edba6ea Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 3 Feb 2020 11:46:14 -0500 Subject: [PATCH] wip(compiler-ssr): v-html, v-text & textarea value --- .../compiler-ssr/__tests__/ssrCompile.spec.ts | 62 ------------------- .../compiler-ssr/__tests__/ssrElement.spec.ts | 52 ++++++++++++++++ .../compiler-ssr/__tests__/ssrText.spec.ts | 37 +++++++++++ packages/compiler-ssr/__tests__/utils.ts | 5 ++ packages/compiler-ssr/src/runtimeHelpers.ts | 2 +- .../src/transforms/ssrTransformElement.ts | 53 ++++++++++++---- 6 files changed, 137 insertions(+), 74 deletions(-) delete mode 100644 packages/compiler-ssr/__tests__/ssrCompile.spec.ts create mode 100644 packages/compiler-ssr/__tests__/ssrElement.spec.ts create mode 100644 packages/compiler-ssr/__tests__/ssrText.spec.ts create mode 100644 packages/compiler-ssr/__tests__/utils.ts diff --git a/packages/compiler-ssr/__tests__/ssrCompile.spec.ts b/packages/compiler-ssr/__tests__/ssrCompile.spec.ts deleted file mode 100644 index ab9013a0..00000000 --- a/packages/compiler-ssr/__tests__/ssrCompile.spec.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { compile } from '../src' - -function getString(src: string): string { - return compile(src).code.match(/_push\((.*)\)/)![1] -} - -describe('element', () => { - test('basic elements', () => { - expect(getString(`
`)).toMatchInlineSnapshot(`"\`
\`"`) - expect(getString(`
`)).toMatchInlineSnapshot(`"\`
\`"`) - }) - - test('static attrs', () => { - expect(getString(`
`)).toMatchInlineSnapshot( - `"\`
\`"` - ) - }) - - test('nested elements', () => { - expect( - getString(`
`) - ).toMatchInlineSnapshot(`"\`
\`"`) - }) - - test('void element', () => { - expect(getString(``)).toMatchInlineSnapshot(`"\`\`"`) - }) -}) - -describe('text', () => { - test('static text', () => { - expect(getString(`foo`)).toMatchInlineSnapshot(`"\`foo\`"`) - }) - - test('static text escape', () => { - expect(getString(`<foo>`)).toMatchInlineSnapshot(`"\`<foo>\`"`) - }) - - test('nested elements with static text', () => { - expect( - getString(`
hellobye
`) - ).toMatchInlineSnapshot( - `"\`
hellobye
\`"` - ) - }) - - test('interpolation', () => { - expect(getString(`foo {{ bar }} baz`)).toMatchInlineSnapshot( - `"\`foo \${interpolate(_ctx.bar)} baz\`"` - ) - }) - - test('nested elements with interpolation', () => { - expect( - getString( - `
{{ foo }} barbaz {{ qux }}
` - ) - ).toMatchInlineSnapshot( - `"\`
\${interpolate(_ctx.foo)} barbaz \${interpolate(_ctx.qux)}
\`"` - ) - }) -}) diff --git a/packages/compiler-ssr/__tests__/ssrElement.spec.ts b/packages/compiler-ssr/__tests__/ssrElement.spec.ts new file mode 100644 index 00000000..c4c9add5 --- /dev/null +++ b/packages/compiler-ssr/__tests__/ssrElement.spec.ts @@ -0,0 +1,52 @@ +import { getCompiledString } from './utils' + +describe('element', () => { + test('basic elements', () => { + expect(getCompiledString(`
`)).toMatchInlineSnapshot( + `"\`
\`"` + ) + expect(getCompiledString(`
`)).toMatchInlineSnapshot( + `"\`
\`"` + ) + }) + + test('static attrs', () => { + expect( + getCompiledString(`
`) + ).toMatchInlineSnapshot(`"\`
\`"`) + }) + + test('nested elements', () => { + expect( + getCompiledString(`
`) + ).toMatchInlineSnapshot(`"\`
\`"`) + }) + + test('void element', () => { + expect(getCompiledString(``)).toMatchInlineSnapshot(`"\`\`"`) + }) + + test('v-html', () => { + expect(getCompiledString(`
`)).toMatchInlineSnapshot( + `"\`
\${_ctx.foo}
\`"` + ) + }) + + test('v-text', () => { + expect(getCompiledString(`
`)).toMatchInlineSnapshot( + `"\`
\${interpolate(_ctx.foo)}
\`"` + ) + }) + + test('\`"` + ) + }) + + test('\`"`) + }) +}) diff --git a/packages/compiler-ssr/__tests__/ssrText.spec.ts b/packages/compiler-ssr/__tests__/ssrText.spec.ts new file mode 100644 index 00000000..9f0bb224 --- /dev/null +++ b/packages/compiler-ssr/__tests__/ssrText.spec.ts @@ -0,0 +1,37 @@ +import { getCompiledString } from './utils' + +describe('text', () => { + test('static text', () => { + expect(getCompiledString(`foo`)).toMatchInlineSnapshot(`"\`foo\`"`) + }) + + test('static text escape', () => { + expect(getCompiledString(`<foo>`)).toMatchInlineSnapshot( + `"\`<foo>\`"` + ) + }) + + test('nested elements with static text', () => { + expect( + getCompiledString(`
hellobye
`) + ).toMatchInlineSnapshot( + `"\`
hellobye
\`"` + ) + }) + + test('interpolation', () => { + expect(getCompiledString(`foo {{ bar }} baz`)).toMatchInlineSnapshot( + `"\`foo \${interpolate(_ctx.bar)} baz\`"` + ) + }) + + test('nested elements with interpolation', () => { + expect( + getCompiledString( + `
{{ foo }} barbaz {{ qux }}
` + ) + ).toMatchInlineSnapshot( + `"\`
\${interpolate(_ctx.foo)} barbaz \${interpolate(_ctx.qux)}
\`"` + ) + }) +}) diff --git a/packages/compiler-ssr/__tests__/utils.ts b/packages/compiler-ssr/__tests__/utils.ts new file mode 100644 index 00000000..333b1e1c --- /dev/null +++ b/packages/compiler-ssr/__tests__/utils.ts @@ -0,0 +1,5 @@ +import { compile } from '../src' + +export function getCompiledString(src: string): string { + return compile(src).code.match(/_push\((.*)\)/)![1] +} diff --git a/packages/compiler-ssr/src/runtimeHelpers.ts b/packages/compiler-ssr/src/runtimeHelpers.ts index 3af2ec55..5a327dd1 100644 --- a/packages/compiler-ssr/src/runtimeHelpers.ts +++ b/packages/compiler-ssr/src/runtimeHelpers.ts @@ -1,4 +1,4 @@ -import { registerRuntimeHelpers } from '@vue/compiler-core' +import { registerRuntimeHelpers } from '@vue/compiler-dom' export const INTERPOLATE = Symbol(`interpolate`) diff --git a/packages/compiler-ssr/src/transforms/ssrTransformElement.ts b/packages/compiler-ssr/src/transforms/ssrTransformElement.ts index 89b514d9..bb3e0200 100644 --- a/packages/compiler-ssr/src/transforms/ssrTransformElement.ts +++ b/packages/compiler-ssr/src/transforms/ssrTransformElement.ts @@ -3,7 +3,8 @@ import { NodeTypes, ElementTypes, TemplateLiteral, - createTemplateLiteral + createTemplateLiteral, + createInterpolation } from '@vue/compiler-dom' import { escapeHtml } from '@vue/shared' @@ -43,27 +44,57 @@ export const ssrTransformElement: NodeTransform = (node, context) => { // element // generate the template literal representing the open tag. const openTag: TemplateLiteral['elements'] = [`<${node.tag}`] + let rawChildren for (let i = 0; i < node.props.length; i++) { const prop = node.props[i] if (prop.type === NodeTypes.DIRECTIVE) { - const directiveTransform = context.directiveTransforms[prop.name] - if (directiveTransform) { - // TODO directive transforms + // special cases with children override + if (prop.name === 'html' && prop.exp) { + node.children = [] + rawChildren = prop.exp + } else if (prop.name === 'text' && prop.exp) { + node.children = [createInterpolation(prop.exp, prop.loc)] + } else if ( + // v-bind:value on textarea + node.tag === 'textarea' && + prop.name === 'bind' && + prop.exp && + prop.arg && + prop.arg.type === NodeTypes.SIMPLE_EXPRESSION && + prop.arg.isStatic && + prop.arg.content === 'value' + ) { + node.children = [createInterpolation(prop.exp, prop.loc)] + // TODO handle with dynamic v-bind } else { - // no corresponding ssr directive transform found. - // TODO emit error + const directiveTransform = context.directiveTransforms[prop.name] + if (directiveTransform) { + // TODO directive transforms + } else { + // no corresponding ssr directive transform found. + // TODO emit error + } } } else { - // static prop - openTag.push( - ` ${prop.name}` + - (prop.value ? `="${escapeHtml(prop.value.content)}"` : ``) - ) + // special case: value on