8000 new directive parser wip · openwings/vue@3bde232 · GitHub
[go: up one dir, main page]

Skip to content 8000

Commit 3bde232

Browse files
committed
new directive parser wip
1 parent 293a16d commit 3bde232

File tree

2 files changed

+175
-53
lines changed

2 files changed

+175
-53
lines changed

src/directive.js

Lines changed: 171 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
var utils = require('./utils'),
22
dirId = 1,
33

4-
// Regexes!
5-
// regex to split multiple directive expressions
6-
// split by commas, but ignore commas within quotes, parens and escapes.
7-
SPLIT_RE = /(?:['"](?:\\.|[^'"])*['"]|\((?:\\.|[^\)])*\)|\\.|[^,])+/g,
84
// match up to the first single pipe, ignore those within quotes.
95
KEY_RE = /^(?:['"](?:\\.|[^'"])*['"]|\\.|[^\|]|\|\|)+/,
106
ARG_RE = /^([\w-$ ]+):(.+)$/,
@@ -140,59 +136,185 @@ DirProto.unbind = function () {
140136
* split a unquoted-comma separated expression into
141137
* multiple clauses
142138
*/
143-
Directive.split = function (exp) {
144-
return exp.indexOf(',') > -1
145-
? exp.match(SPLIT_RE) || ['']
146-
: [exp]
147-
}
139+
Directive.parse = function (str) {
148140

149-
/**
150-
* parse a key, extract argument
151-
*/
152-
Directive.parseArg = function (rawKey) {
153-
var key = rawKey,
154-
arg = null
155-
if (rawKey.indexOf(':') > -1) {
156-
var argMatch = rawKey.match(ARG_RE)
157-
key = argMatch
158-
? argMatch[2].trim()
159-
: key
160-
arg = argMatch
161-
? argMatch[1].trim()
162-
: arg
141+
var inSingle = false,
142+
inDouble = false,
143+
curly = 0,
144+
square = 0,
145+
paren = 0,
146+
begin = 0,
147+
argIndex = 0,
148+
dirs = [],
149+
dir = {},
150+
lastFilterIndex = 0
151+
152+
for (var c, i = 0, l = str.length; i < l; i++) {
153+
c = str.charAt(i)
154+
if (inSingle) {
155+
// check single quote
156+
if (c === "'") inSingle = !inSingle
157+
} else if (inDouble) {
158+
// check double quote
159+
if (c === '"') inDouble = !inDouble
160+
} else if (c === ',' && !paren && !curly && !square) {
161+
// reached the end of a directive
162+
pushDir()
163+
// reset & skip the comma
164+
dir = {}
165+
begin = argIndex = lastFilterIndex = i + 1
166+
} else if (c === ':' && !dir.key && !dir.arg) {
167+
// argument
168+
argIndex = i + 1
169+
dir.arg = str.slice(begin, i).trim()
170+
} else if (c === '|' && str.charAt(i + 1) !== '|') {
171+
if (!dir.key) {
172+
// first filter, end of key
173+
lastFilterIndex = i
174+
dir.key = str.slice(argIndex, i).trim()
175+
} else {
176+
// already has filter
177+
pushFilter()
178+
}
179+
} else if (c === '"') {
180+
inDouble = true
181+
} else if (c === "'") {
182+
inSingle = true
183+
} else if (c === '(') {
184+
paren++
185+
} else if (c === ')') {
186+
paren--
187+
} else if (c === '[') {
188+
square++
189+
} else if (c === ']') {
190+
square--
191+
} else if (c === '{') {
192+
curly++
193+
} else if (c === '}') {
194+
curly--
195+
}
163196
}
164-
return {
165-
key: key,
166-
arg: arg
197+
if (begin !== i) {
198+
pushDir()
167199
}
168-
}
169200

170-
/**
171-
* parse a the filters
172-
*/
173-
Directive.parseFilters = function (exp) {
174-
if (exp.indexOf('|') < 0) {
175-
return
176-
}
177-
var filters = exp.match(FILTERS_RE),
178-
res, i, l, tokens
179-
if (filters) {
180-
res = []
181-
for (i = 0, l = filters.length; i < l; i++) {
182-
tokens = filters[i].slice(1).match(FILTER_TOKEN_RE)
183-
if (tokens) {
184-
res.push({
185-
name: tokens[0],
186-
args: tokens.length > 1
187-
? tokens.slice(1)
188-
: null
189-
})
190-
}
201+
function pushDir () {
202+
dir.expression = str.slice(begin, i).trim()
203+
if (!dir.key) {
204+
dir.key = str.slice(argIndex, i).trim()
205+
} else if (lastFilterIndex !== begin) {
206+
pushFilter()
191207
}
208+
dirs.push(dir)
209+
}
210+
211+
function pushFilter () {
212+
(dir.filters = dir.filters || [])
213+
.push(str.slice(lastFilterIndex + 1, i).trim())
214+
lastFilterIndex = i + 1
192215
}
193-
return res
216+
217+
return dirs
194218
}
195219

220+
// function split (str) {
221+
// var inSingle = false,
222+
// inDouble = false,
223+
// curly = 0,
224+
// square = 0,
225+
// paren = 0,
226+
// begin = 0,
227+
// end = 0,
228+
// res = []
229+
// for (var c, i = 0, l = str.length; i < l; i++) {
230+
// c = str.charAt(i)
231+
// if (inSingle) {
232+
// if (c === "'") {
233+
// inSingle = !inSingle
234+
// }
235+
// end++
236+
// } else if (inDouble) {
237+
// if (c === '"') {
238+
// inDouble = !inDouble
239+
// }
240+
// end++
241+
// } else if (c === ',' && !paren && !curly && !square) {
242+
// res.push(str.slice(begin, end))
243+
// begin = end = i + 1
244+
// } else {
245+
// if (c === '"') {
246+
// inDouble = true
247+
// } else if (c === "'") {
248+
// inSingle = true
249+
// } else if (c === '(') {
250+
// paren++
251+
// } else if (c === ')') {
252+
// paren--
253+
// } else if (c === '[') {
254+
// square++
255+
// } else if (c === ']') {
256+
// square--
257+
// } else if (c === '{') {
258+
// curly++
259+
// } else if (c === '}') {
260+
// curly--
261+
// }
262+
// end++
263+
// }
264+
// }
265+
// if (begin !== end) {
266+
// res.push(str.slice(begin, end))
267+
// }
268+
// return res
269+
// }
270+
271+
// /**
272+
// * parse a key, extract argument
273+
// */
274+
// Directive.parseArg = function (rawKey) {
275+
// var key = rawKey,
276+
// arg = null
277+
// if (rawKey.indexOf(':') > -1) {
278+
// var argMatch = rawKey.match(ARG_RE)
279+
// key = argMatch
280+
// ? argMatch[2].trim()
281+
// : key
282+
// arg = argMatch
283+
// ? argMatch[1].trim()
284+
// : arg
285+
// }
286+
// return {
287+
// key: key,
288+
// arg: arg
289+
// }
290+
// }
291+
292+
// /**
293+
// * parse a the filters
294+
// */
295+
// Directive.parseFilters = function (exp) {
296+
// if (exp.indexOf('|') < 0) {
297+
// return
298+
// }
299+
// var filters = exp.match(FILTERS_RE),
300+
// res, i, l, tokens
301+
// if (filters) {
302+
// res = []
303+
// for (i = 0, l = filters.length; i < l; i++) {
304+
// tokens = filters[i].slice(1).match(FILTER_TOKEN_RE)
305+
// if (tokens) {
306+
// res.push({
307+
// name: tokens[0],
308+
// args: tokens.length > 1
309+
// ? tokens.slice(1)
310+
// : null
311+
// })
312+
// }
313+
// }
314+
// }
315+
// return res
316+
// }
317+
196318
/**
197319
* Inline computed filters so they become part
198320
* of the expression

test/unit/specs/directive.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ describe('Directive', function () {
2323

2424
it('should return array with the string if it\'s a single clause', function () {
2525
var e,
26-
test1 = 'fsef(a, b, c)',
26+
test1 = 'fsef(a, b(d,e(f,g),k), c)',
2727
test2 = 'ffsef + "fse,fsef"',
2828
test3 = 'fsef + \'fesfsfe\'',
2929
test4 = '\"fsefsf,fsef,fsef\"',
30-
test5 = '(a, b)'
30+
test5 = '(a, {a:1, b:2})'
3131

3232
e = Directive.split(test1)
3333
assert.strictEqual(e.length, 1)
@@ -53,8 +53,8 @@ describe('Directive', function () {
5353
it('should return split multiple clauses correctly', function () {
5454
var e,
5555
test1 = ['(fse,fggg)', 'fsf:({a:1,b:2}, [1,2,3])'],
56-
test2 = ['asf-fsef:fsf', '"efs,s(e,f)sf"'],
57-
test3 = ['\'fsef,sef\'', 'fse:fsf(a,b,c)'],
56+
test2 = ['asf-fsef:fsf', '"efs,s(e,f),sf"'],
57+
test3 = ['\'fsef,sef\'', 'fse:fsf(a,b(c,d),c)'],
5858
test4 = ['\"fsef,fsef\"', 'sefsef\'fesfsf']
5959

6060
e = Directive.split(test1.join(','))

0 commit comments

Comments
 (0)
0