4bf102932a8d7103e54da581347662adfddb006330e420274fd251c3e2e7fe9ae42cc3c8d884cf4adfd65871c37f68adc61289c2af776a2f3b6f96769a1da5 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /* @flow */
  2. import { emptyObject } from 'shared/util'
  3. import { parseFilters } from './parser/filter-parser'
  4. type Range = { start?: number, end?: number };
  5. /* eslint-disable no-unused-vars */
  6. export function baseWarn (msg: string, range?: Range) {
  7. console.error(`[Vue compiler]: ${msg}`)
  8. }
  9. /* eslint-enable no-unused-vars */
  10. export function pluckModuleFunction<F: Function> (
  11. modules: ?Array<Object>,
  12. key: string
  13. ): Array<F> {
  14. return modules
  15. ? modules.map(m => m[key]).filter(_ => _)
  16. : []
  17. }
  18. export function addProp (el: ASTElement, name: string, value: string, range?: Range, dynamic?: boolean) {
  19. (el.props || (el.props = [])).push(rangeSetItem({ name, value, dynamic }, range))
  20. el.plain = false
  21. }
  22. export function addAttr (el: ASTElement, name: string, value: any, range?: Range, dynamic?: boolean) {
  23. const attrs = dynamic
  24. ? (el.dynamicAttrs || (el.dynamicAttrs = []))
  25. : (el.attrs || (el.attrs = []))
  26. attrs.push(rangeSetItem({ name, value, dynamic }, range))
  27. el.plain = false
  28. }
  29. // add a raw attr (use this in preTransforms)
  30. export function addRawAttr (el: ASTElement, name: string, value: any, range?: Range) {
  31. el.attrsMap[name] = value
  32. el.attrsList.push(rangeSetItem({ name, value }, range))
  33. }
  34. export function addDirective (
  35. el: ASTElement,
  36. name: string,
  37. rawName: string,
  38. value: string,
  39. arg: ?string,
  40. isDynamicArg: boolean,
  41. modifiers: ?ASTModifiers,
  42. range?: Range
  43. ) {
  44. (el.directives || (el.directives = [])).push(rangeSetItem({
  45. name,
  46. rawName,
  47. value,
  48. arg,
  49. isDynamicArg,
  50. modifiers
  51. }, range))
  52. el.plain = false
  53. }
  54. function prependModifierMarker (symbol: string, name: string, dynamic?: boolean): string {
  55. return dynamic
  56. ? `_p(${name},"${symbol}")`
  57. : symbol + name // mark the event as captured
  58. }
  59. export function addHandler (
  60. el: ASTElement,
  61. name: string,
  62. value: string,
  63. modifiers: ?ASTModifiers,
  64. important?: boolean,
  65. warn?: ?Function,
  66. range?: Range,
  67. dynamic?: boolean
  68. ) {
  69. modifiers = modifiers || emptyObject
  70. // warn prevent and passive modifier
  71. /* istanbul ignore if */
  72. if (
  73. process.env.NODE_ENV !== 'production' && warn &&
  74. modifiers.prevent && modifiers.passive
  75. ) {
  76. warn(
  77. 'passive and prevent can\'t be used together. ' +
  78. 'Passive handler can\'t prevent default event.',
  79. range
  80. )
  81. }
  82. // normalize click.right and click.middle since they don't actually fire
  83. // this is technically browser-specific, but at least for now browsers are
  84. // the only target envs that have right/middle clicks.
  85. if (modifiers.right) {
  86. if (dynamic) {
  87. name = `(${name})==='click'?'contextmenu':(${name})`
  88. } else if (name === 'click') {
  89. name = 'contextmenu'
  90. delete modifiers.right
  91. }
  92. } else if (modifiers.middle) {
  93. if (dynamic) {
  94. name = `(${name})==='click'?'mouseup':(${name})`
  95. } else if (name === 'click') {
  96. name = 'mouseup'
  97. }
  98. }
  99. // check capture modifier
  100. if (modifiers.capture) {
  101. delete modifiers.capture
  102. name = prependModifierMarker('!', name, dynamic)
  103. }
  104. if (modifiers.once) {
  105. delete modifiers.once
  106. name = prependModifierMarker('~', name, dynamic)
  107. }
  108. /* istanbul ignore if */
  109. if (modifiers.passive) {
  110. delete modifiers.passive
  111. name = prependModifierMarker('&', name, dynamic)
  112. }
  113. let events
  114. if (modifiers.native) {
  115. delete modifiers.native
  116. events = el.nativeEvents || (el.nativeEvents = {})
  117. } else {
  118. events = el.events || (el.events = {})
  119. }
  120. const newHandler: any = rangeSetItem({ value: value.trim(), dynamic }, range)
  121. if (modifiers !== emptyObject) {
  122. newHandler.modifiers = modifiers
  123. }
  124. const handlers = events[name]
  125. /* istanbul ignore if */
  126. if (Array.isArray(handlers)) {
  127. important ? handlers.unshift(newHandler) : handlers.push(newHandler)
  128. } else if (handlers) {
  129. events[name] = important ? [newHandler, handlers] : [handlers, newHandler]
  130. } else {
  131. events[name] = newHandler
  132. }
  133. el.plain = false
  134. }
  135. export function getRawBindingAttr (
  136. el: ASTElement,
  137. name: string
  138. ) {
  139. return el.rawAttrsMap[':' + name] ||
  140. el.rawAttrsMap['v-bind:' + name] ||
  141. el.rawAttrsMap[name]
  142. }
  143. export function getBindingAttr (
  144. el: ASTElement,
  145. name: string,
  146. getStatic?: boolean
  147. ): ?string {
  148. const dynamicValue =
  149. getAndRemoveAttr(el, ':' + name) ||
  150. getAndRemoveAttr(el, 'v-bind:' + name)
  151. if (dynamicValue != null) {
  152. return parseFilters(dynamicValue)
  153. } else if (getStatic !== false) {
  154. const staticValue = getAndRemoveAttr(el, name)
  155. if (staticValue != null) {
  156. return JSON.stringify(staticValue)
  157. }
  158. }
  159. }
  160. // note: this only removes the attr from the Array (attrsList) so that it
  161. // doesn't get processed by processAttrs.
  162. // By default it does NOT remove it from the map (attrsMap) because the map is
  163. // needed during codegen.
  164. export function getAndRemoveAttr (
  165. el: ASTElement,
  166. name: string,
  167. removeFromMap?: boolean
  168. ): ?string {
  169. let val
  170. if ((val = el.attrsMap[name]) != null) {
  171. const list = el.attrsList
  172. for (let i = 0, l = list.length; i < l; i++) {
  173. if (list[i].name === name) {
  174. list.splice(i, 1)
  175. break
  176. }
  177. }
  178. }
  179. if (removeFromMap) {
  180. delete el.attrsMap[name]
  181. }
  182. return val
  183. }
  184. export function getAndRemoveAttrByRegex (
  185. el: ASTElement,
  186. name: RegExp
  187. ) {
  188. const list = el.attrsList
  189. for (let i = 0, l = list.length; i < l; i++) {
  190. const attr = list[i]
  191. if (name.test(attr.name)) {
  192. list.splice(i, 1)
  193. return attr
  194. }
  195. }
  196. }
  197. function rangeSetItem (
  198. item: any,
  199. range?: { start?: number, end?: number }
  200. ) {
  201. if (range) {
  202. if (range.start != null) {
  203. item.start = range.start
  204. }
  205. if (range.end != null) {
  206. item.end = range.end
  207. }
  208. }
  209. return item
  210. }