1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | !function(URI) {
|
13 | "use strict";
|
14 |
|
15 | |
16 |
|
17 |
|
18 |
|
19 |
|
20 | var RESERVED = /[!'()]/g
|
21 |
|
22 | , SEPARATORS = {"": ",", "+": ",", "#": ",", "?": "&"}
|
23 | , escapeRe = /[$-\/?[-^{|}]/g
|
24 | , expandRe = /\{([#&+.\/;?]?)((?:[-\w%.]+(\*|:\d+)?,?)+)\}/g
|
25 | , parseRe = RegExp(expandRe.source + "|.[^{]*?", "g")
|
26 |
|
27 |
|
28 | function encodeNormal(val) {
|
29 | return encodeURIComponent(val).replace(RESERVED, escape)
|
30 | }
|
31 |
|
32 | function notNull(s) {
|
33 | return s != null
|
34 | }
|
35 |
|
36 | function mapCleanJoin(arr, mapFn, joinStr) {
|
37 | arr = arr.map(mapFn).filter(notNull)
|
38 | return arr.length && arr.join(joinStr)
|
39 | }
|
40 |
|
41 | function expand(template, data) {
|
42 | return template.replace(expandRe, function(_, op, vals) {
|
43 | var sep = SEPARATORS[op] || op
|
44 | , named = sep == ";" || sep == "&"
|
45 | , enc = op && sep == "," ? encodeURI : encodeNormal
|
46 | , out = mapCleanJoin(vals.split(","), function(_name) {
|
47 | var mod = _name.split(/[*:]/)
|
48 | , name = mod[0]
|
49 | , val = data[name]
|
50 |
|
51 | if (val == null) return
|
52 |
|
53 | if (typeof val == "object") {
|
54 | mod = name != _name
|
55 | if (Array.isArray(val)) {
|
56 | val = mapCleanJoin(val, enc, mod ? named ? sep + name + "=" : sep : "," )
|
57 | } else {
|
58 | val = mapCleanJoin(Object.keys(val), function(key) {
|
59 | return enc(key) + (mod ? "=" : ",") + enc(val[key])
|
60 | }, mod && (named || sep == "/") ? sep : ",")
|
61 | if (mod) named = 0
|
62 | }
|
63 | if (!val) return
|
64 | } else {
|
65 | val = enc(mod[1] ? val.slice(0, mod[1]) : val)
|
66 | }
|
67 |
|
68 | return (
|
69 | named ?
|
70 | name + (val || sep == "&" ? "=" + val : val) :
|
71 | val
|
72 | )
|
73 | }, sep)
|
74 |
|
75 | return out || out === "" ? (op != "+" ? op + out : out) : ""
|
76 | }
|
77 | )}
|
78 |
|
79 | URI.expand = expand
|
80 |
|
81 |
|
82 | URI.Template = function Template(template) {
|
83 | var self = this
|
84 |
|
85 |
|
86 | , pos = 0
|
87 | , lengths = {}
|
88 | , fnStr = ""
|
89 | , reStr = "^" + template.replace(parseRe, function(_, op, vals) {
|
90 | if (!vals) return escapeRegExp(_)
|
91 |
|
92 | var sep = SEPARATORS[op] || op
|
93 | , named = sep == ";" || sep == "&"
|
94 | , reGroup = vals.split(",").map(function(_name) {
|
95 | var mod = _name.split(/[*:]/)
|
96 | , name = mod[0]
|
97 | , re = (lengths[name] || "(") + ".*?)"
|
98 |
|
99 | pos++
|
100 |
|
101 | if (mod[1]) {
|
102 | re = "((?:%..|.){1," + mod[1] + "})"
|
103 | lengths[name] = "(\\" + pos
|
104 | }
|
105 |
|
106 | fnStr += "t=($[" + pos + "]||'').split('" + sep + "').map(decodeURIComponent);"
|
107 | fnStr += "o[\"" + name + "\"]=t.length>1?t:t[0];"
|
108 | return (
|
109 | named ?
|
110 | escapeRegExp(name) + "(?:=" + re + ")?" :
|
111 | sep == "&" ?
|
112 | escapeRegExp(name + "=") + re :
|
113 | re
|
114 | )
|
115 | }).join(escapeRegExp(sep))
|
116 | return (op != "+" ? escapeRegExp(op) + reGroup : reGroup)
|
117 |
|
118 | }) + "$"
|
119 | , re = RegExp(reStr)
|
120 | , fn = Function("$", "var t,o={};" + fnStr + "return o")
|
121 | self.template = template
|
122 | self.match = function(uri) {
|
123 | var match = re.exec(uri)
|
124 | return match && fn(match)
|
125 | }
|
126 |
|
127 | function escapeRegExp(string) {
|
128 | return string.replace(escapeRe, "\\$&")
|
129 | }
|
130 |
|
131 |
|
132 | self.expand = expand.bind(self, template)
|
133 |
|
134 | }
|
135 |
|
136 |
|
137 | }(this.URI || (this.URI = {}));
|
138 |
|