5a264b498dc504f6ae19ac98e2164c3ef6e0f4a66748539765da23a081956e1a0547472b10694b3cf8333b0e4b5b6c16350e40569fc448759a5cb69093e6b8 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /* @flow */
  2. import { escape, isSSRUnsafeAttr } from 'web/server/util'
  3. import { isObject, extend } from 'shared/util'
  4. import { renderAttr } from 'web/server/modules/attrs'
  5. import { renderClass } from 'web/util/class'
  6. import { genStyle } from 'web/server/modules/style'
  7. import { normalizeStyleBinding } from 'web/util/style'
  8. import {
  9. normalizeChildren,
  10. simpleNormalizeChildren
  11. } from 'core/vdom/helpers/normalize-children'
  12. import {
  13. propsToAttrMap,
  14. isRenderableAttr
  15. } from 'web/server/util'
  16. const ssrHelpers = {
  17. _ssrEscape: escape,
  18. _ssrNode: renderStringNode,
  19. _ssrList: renderStringList,
  20. _ssrAttr: renderAttr,
  21. _ssrAttrs: renderAttrs,
  22. _ssrDOMProps: renderDOMProps,
  23. _ssrClass: renderSSRClass,
  24. _ssrStyle: renderSSRStyle
  25. }
  26. export function installSSRHelpers (vm: Component) {
  27. if (vm._ssrNode) {
  28. return
  29. }
  30. let Vue = vm.constructor
  31. while (Vue.super) {
  32. Vue = Vue.super
  33. }
  34. extend(Vue.prototype, ssrHelpers)
  35. if (Vue.FunctionalRenderContext) {
  36. extend(Vue.FunctionalRenderContext.prototype, ssrHelpers)
  37. }
  38. }
  39. class StringNode {
  40. isString: boolean;
  41. open: string;
  42. close: ?string;
  43. children: ?Array<any>;
  44. constructor (
  45. open: string,
  46. close?: string,
  47. children?: Array<any>,
  48. normalizationType?: number
  49. ) {
  50. this.isString = true
  51. this.open = open
  52. this.close = close
  53. if (children) {
  54. this.children = normalizationType === 1
  55. ? simpleNormalizeChildren(children)
  56. : normalizationType === 2
  57. ? normalizeChildren(children)
  58. : children
  59. } else {
  60. this.children = void 0
  61. }
  62. }
  63. }
  64. function renderStringNode (
  65. open: string,
  66. close?: string,
  67. children?: Array<any>,
  68. normalizationType?: number
  69. ): StringNode {
  70. return new StringNode(open, close, children, normalizationType)
  71. }
  72. function renderStringList (
  73. val: any,
  74. render: (
  75. val: any,
  76. keyOrIndex: string | number,
  77. index?: number
  78. ) => string
  79. ): string {
  80. let ret = ''
  81. let i, l, keys, key
  82. if (Array.isArray(val) || typeof val === 'string') {
  83. for (i = 0, l = val.length; i < l; i++) {
  84. ret += render(val[i], i)
  85. }
  86. } else if (typeof val === 'number') {
  87. for (i = 0; i < val; i++) {
  88. ret += render(i + 1, i)
  89. }
  90. } else if (isObject(val)) {
  91. keys = Object.keys(val)
  92. for (i = 0, l = keys.length; i < l; i++) {
  93. key = keys[i]
  94. ret += render(val[key], key, i)
  95. }
  96. }
  97. return ret
  98. }
  99. function renderAttrs (obj: Object): string {
  100. let res = ''
  101. for (const key in obj) {
  102. if (isSSRUnsafeAttr(key)) {
  103. continue
  104. }
  105. res += renderAttr(key, obj[key])
  106. }
  107. return res
  108. }
  109. function renderDOMProps (obj: Object): string {
  110. let res = ''
  111. for (const key in obj) {
  112. const attr = propsToAttrMap[key] || key.toLowerCase()
  113. if (isRenderableAttr(attr)) {
  114. res += renderAttr(attr, obj[key])
  115. }
  116. }
  117. return res
  118. }
  119. function renderSSRClass (
  120. staticClass: ?string,
  121. dynamic: any
  122. ): string {
  123. const res = renderClass(staticClass, dynamic)
  124. return res === '' ? res : ` class="${escape(res)}"`
  125. }
  126. function renderSSRStyle (
  127. staticStyle: ?Object,
  128. dynamic: any,
  129. extra: ?Object
  130. ): string {
  131. const style = {}
  132. if (staticStyle) extend(style, staticStyle)
  133. if (dynamic) extend(style, normalizeStyleBinding(dynamic))
  134. if (extra) extend(style, extra)
  135. const res = genStyle(style)
  136. return res === '' ? res : ` style=${JSON.stringify(escape(res))}`
  137. }