refactor(ssr): adjust helper structure + renderList
This commit is contained in:
		
							parent
							
								
									889a0276eb
								
							
						
					
					
						commit
						2ad0eed5cd
					
				@ -5,7 +5,8 @@ export const SSR_RENDER_COMPONENT = Symbol(`renderComponent`)
 | 
			
		||||
export const SSR_RENDER_SLOT = Symbol(`renderSlot`)
 | 
			
		||||
export const SSR_RENDER_CLASS = Symbol(`renderClass`)
 | 
			
		||||
export const SSR_RENDER_STYLE = Symbol(`renderStyle`)
 | 
			
		||||
export const SSR_RENDER_PROPS = Symbol(`renderProps`)
 | 
			
		||||
export const SSR_RENDER_ATTRS = Symbol(`renderAttrs`)
 | 
			
		||||
export const SSR_RENDER_ATTR = Symbol(`renderAttr`)
 | 
			
		||||
export const SSR_RENDER_LIST = Symbol(`renderList`)
 | 
			
		||||
 | 
			
		||||
// Note: these are helpers imported from @vue/server-renderer
 | 
			
		||||
@ -16,6 +17,7 @@ registerRuntimeHelpers({
 | 
			
		||||
  [SSR_RENDER_SLOT]: `_renderSlot`,
 | 
			
		||||
  [SSR_RENDER_CLASS]: `_renderClass`,
 | 
			
		||||
  [SSR_RENDER_STYLE]: `_renderStyle`,
 | 
			
		||||
  [SSR_RENDER_PROPS]: `_renderProps`,
 | 
			
		||||
  [SSR_RENDER_ATTRS]: `renderAttrs`,
 | 
			
		||||
  [SSR_RENDER_ATTR]: `renderAttr`,
 | 
			
		||||
  [SSR_RENDER_LIST]: `_renderList`
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -1,16 +1,16 @@
 | 
			
		||||
import { _interpolate } from '../src'
 | 
			
		||||
import { interpolate } from '../src/helpers/interpolate'
 | 
			
		||||
import { escapeHtml } from '@vue/shared'
 | 
			
		||||
 | 
			
		||||
test('ssr: interpolate', () => {
 | 
			
		||||
  expect(_interpolate(0)).toBe(`0`)
 | 
			
		||||
  expect(_interpolate(`foo`)).toBe(`foo`)
 | 
			
		||||
  expect(_interpolate(`<div>`)).toBe(`<div>`)
 | 
			
		||||
  expect(interpolate(0)).toBe(`0`)
 | 
			
		||||
  expect(interpolate(`foo`)).toBe(`foo`)
 | 
			
		||||
  expect(interpolate(`<div>`)).toBe(`<div>`)
 | 
			
		||||
  // should escape interpolated values
 | 
			
		||||
  expect(_interpolate([1, 2, 3])).toBe(
 | 
			
		||||
  expect(interpolate([1, 2, 3])).toBe(
 | 
			
		||||
    escapeHtml(JSON.stringify([1, 2, 3], null, 2))
 | 
			
		||||
  )
 | 
			
		||||
  expect(
 | 
			
		||||
    _interpolate({
 | 
			
		||||
    interpolate({
 | 
			
		||||
      foo: 1,
 | 
			
		||||
      bar: `<div>`
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								packages/server-renderer/__tests__/renderList.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/server-renderer/__tests__/renderList.spec.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
test('ssr: renderList', () => {
 | 
			
		||||
  // TODO
 | 
			
		||||
})
 | 
			
		||||
@ -1,9 +1,13 @@
 | 
			
		||||
import { renderProps, renderClass, renderStyle } from '../src/renderProps'
 | 
			
		||||
import {
 | 
			
		||||
  renderAttrs,
 | 
			
		||||
  renderClass,
 | 
			
		||||
  renderStyle
 | 
			
		||||
} from '../src/helpers/renderAttrs'
 | 
			
		||||
 | 
			
		||||
describe('ssr: renderProps', () => {
 | 
			
		||||
  test('ignore reserved props', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      renderProps({
 | 
			
		||||
      renderAttrs({
 | 
			
		||||
        key: 1,
 | 
			
		||||
        ref: () => {},
 | 
			
		||||
        onClick: () => {}
 | 
			
		||||
@ -13,7 +17,7 @@ describe('ssr: renderProps', () => {
 | 
			
		||||
 | 
			
		||||
  test('normal attrs', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      renderProps({
 | 
			
		||||
      renderAttrs({
 | 
			
		||||
        id: 'foo',
 | 
			
		||||
        title: 'bar'
 | 
			
		||||
      })
 | 
			
		||||
@ -22,7 +26,7 @@ describe('ssr: renderProps', () => {
 | 
			
		||||
 | 
			
		||||
  test('escape attrs', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      renderProps({
 | 
			
		||||
      renderAttrs({
 | 
			
		||||
        id: '"><script'
 | 
			
		||||
      })
 | 
			
		||||
    ).toBe(` id=""><script"`)
 | 
			
		||||
@ -30,7 +34,7 @@ describe('ssr: renderProps', () => {
 | 
			
		||||
 | 
			
		||||
  test('boolean attrs', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      renderProps({
 | 
			
		||||
      renderAttrs({
 | 
			
		||||
        checked: true,
 | 
			
		||||
        multiple: false
 | 
			
		||||
      })
 | 
			
		||||
@ -39,7 +43,7 @@ describe('ssr: renderProps', () => {
 | 
			
		||||
 | 
			
		||||
  test('ignore falsy values', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      renderProps({
 | 
			
		||||
      renderAttrs({
 | 
			
		||||
        foo: false,
 | 
			
		||||
        title: null,
 | 
			
		||||
        baz: undefined
 | 
			
		||||
@ -49,7 +53,7 @@ describe('ssr: renderProps', () => {
 | 
			
		||||
 | 
			
		||||
  test('props to attrs', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      renderProps({
 | 
			
		||||
      renderAttrs({
 | 
			
		||||
        readOnly: true, // simple lower case conversion
 | 
			
		||||
        htmlFor: 'foobar' // special cases
 | 
			
		||||
      })
 | 
			
		||||
@ -58,7 +62,7 @@ describe('ssr: renderProps', () => {
 | 
			
		||||
 | 
			
		||||
  test('preserve name on custom element', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      renderProps(
 | 
			
		||||
      renderAttrs(
 | 
			
		||||
        {
 | 
			
		||||
          fooBar: 'ok'
 | 
			
		||||
        },
 | 
			
		||||
@ -71,7 +75,7 @@ describe('ssr: renderProps', () => {
 | 
			
		||||
describe('ssr: renderClass', () => {
 | 
			
		||||
  test('via renderProps', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      renderProps({
 | 
			
		||||
      renderAttrs({
 | 
			
		||||
        class: ['foo', 'bar']
 | 
			
		||||
      })
 | 
			
		||||
    ).toBe(` class="foo bar"`)
 | 
			
		||||
@ -92,7 +96,7 @@ describe('ssr: renderClass', () => {
 | 
			
		||||
describe('ssr: renderStyle', () => {
 | 
			
		||||
  test('via renderProps', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
      renderProps({
 | 
			
		||||
      renderAttrs({
 | 
			
		||||
        style: {
 | 
			
		||||
          color: 'red'
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								packages/server-renderer/src/helpers/interpolate.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								packages/server-renderer/src/helpers/interpolate.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
import { escapeHtml, toDisplayString } from '@vue/shared'
 | 
			
		||||
 | 
			
		||||
export function interpolate(value: unknown): string {
 | 
			
		||||
  return escapeHtml(toDisplayString(value))
 | 
			
		||||
}
 | 
			
		||||
@ -14,7 +14,7 @@ import {
 | 
			
		||||
 | 
			
		||||
const shouldIgnoreProp = makeMap(`key,ref,innerHTML,textContent`)
 | 
			
		||||
 | 
			
		||||
export function renderProps(
 | 
			
		||||
export function renderAttrs(
 | 
			
		||||
  props: Record<string, unknown>,
 | 
			
		||||
  tag?: string
 | 
			
		||||
): string {
 | 
			
		||||
@ -32,21 +32,28 @@ export function renderProps(
 | 
			
		||||
      ret += ` class="${renderClass(value)}"`
 | 
			
		||||
    } else if (key === 'style') {
 | 
			
		||||
      ret += ` style="${renderStyle(value)}"`
 | 
			
		||||
    } else if (value != null) {
 | 
			
		||||
    } else {
 | 
			
		||||
      ret += renderAttr(key, value, tag)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function renderAttr(key: string, value: unknown, tag?: string): string {
 | 
			
		||||
  if (value == null) {
 | 
			
		||||
    return ``
 | 
			
		||||
  }
 | 
			
		||||
  const attrKey =
 | 
			
		||||
    tag && tag.indexOf('-') > 0
 | 
			
		||||
      ? key // preserve raw name on custom elements
 | 
			
		||||
      : propsToAttrMap[key] || key.toLowerCase()
 | 
			
		||||
  if (isBooleanAttr(attrKey)) {
 | 
			
		||||
        if (value !== false) {
 | 
			
		||||
          ret += ` ${attrKey}`
 | 
			
		||||
        }
 | 
			
		||||
    return value === false ? `` : ` ${attrKey}`
 | 
			
		||||
  } else if (isSSRSafeAttrName(attrKey)) {
 | 
			
		||||
        ret += ` ${attrKey}="${escapeHtml(value)}"`
 | 
			
		||||
    return ` ${attrKey}="${escapeHtml(value)}"`
 | 
			
		||||
  } else {
 | 
			
		||||
    return ``
 | 
			
		||||
  }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function renderClass(raw: unknown): string {
 | 
			
		||||
							
								
								
									
										29
									
								
								packages/server-renderer/src/helpers/renderList.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								packages/server-renderer/src/helpers/renderList.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
import { isArray, isString, isObject } from '@vue/shared'
 | 
			
		||||
 | 
			
		||||
export function renderList(
 | 
			
		||||
  source: unknown,
 | 
			
		||||
  renderItem: (value: unknown, key: string | number, index?: number) => void
 | 
			
		||||
) {
 | 
			
		||||
  if (isArray(source) || isString(source)) {
 | 
			
		||||
    for (let i = 0, l = source.length; i < l; i++) {
 | 
			
		||||
      renderItem(source[i], i)
 | 
			
		||||
    }
 | 
			
		||||
  } else if (typeof source === 'number') {
 | 
			
		||||
    for (let i = 0; i < source; i++) {
 | 
			
		||||
      renderItem(i + 1, i)
 | 
			
		||||
    }
 | 
			
		||||
  } else if (isObject(source)) {
 | 
			
		||||
    if (source[Symbol.iterator as any]) {
 | 
			
		||||
      const arr = Array.from(source as Iterable<any>)
 | 
			
		||||
      for (let i = 0, l = arr.length; i < l; i++) {
 | 
			
		||||
        renderItem(arr[i], i)
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      const keys = Object.keys(source)
 | 
			
		||||
      for (let i = 0, l = keys.length; i < l; i++) {
 | 
			
		||||
        const key = keys[i]
 | 
			
		||||
        renderItem(source[key], key, i)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
// public
 | 
			
		||||
export { renderToString } from './renderToString'
 | 
			
		||||
 | 
			
		||||
// internal
 | 
			
		||||
// internal runtime helpers
 | 
			
		||||
export {
 | 
			
		||||
  renderComponent as _renderComponent,
 | 
			
		||||
  renderSlot as _renderSlot
 | 
			
		||||
@ -9,12 +9,7 @@ export {
 | 
			
		||||
export {
 | 
			
		||||
  renderClass as _renderClass,
 | 
			
		||||
  renderStyle as _renderStyle,
 | 
			
		||||
  renderProps as _renderProps
 | 
			
		||||
} from './renderProps'
 | 
			
		||||
 | 
			
		||||
// utils
 | 
			
		||||
import { escapeHtml, toDisplayString } from '@vue/shared'
 | 
			
		||||
 | 
			
		||||
export function _interpolate(value: unknown): string {
 | 
			
		||||
  return escapeHtml(toDisplayString(value))
 | 
			
		||||
}
 | 
			
		||||
  renderAttrs as _renderAttrs
 | 
			
		||||
} from './helpers/renderAttrs'
 | 
			
		||||
export { interpolate as _interpolate } from './helpers/interpolate'
 | 
			
		||||
export { renderList as _renderList } from './helpers/renderList'
 | 
			
		||||
 | 
			
		||||
@ -19,10 +19,10 @@ import {
 | 
			
		||||
  isPromise,
 | 
			
		||||
  isArray,
 | 
			
		||||
  isFunction,
 | 
			
		||||
  isVoidTag
 | 
			
		||||
  isVoidTag,
 | 
			
		||||
  escapeHtml
 | 
			
		||||
} from '@vue/shared'
 | 
			
		||||
import { renderProps } from './renderProps'
 | 
			
		||||
import { escapeHtml } from '@vue/shared'
 | 
			
		||||
import { renderAttrs } from './helpers/renderAttrs'
 | 
			
		||||
 | 
			
		||||
const {
 | 
			
		||||
  isVNode,
 | 
			
		||||
@ -213,7 +213,7 @@ function renderElement(
 | 
			
		||||
  // TODO directives
 | 
			
		||||
 | 
			
		||||
  if (props !== null) {
 | 
			
		||||
    openTag += renderProps(props, tag)
 | 
			
		||||
    openTag += renderAttrs(props, tag)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (scopeId !== null) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user