UNPKG

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