| OLD | NEW |
| (Empty) | |
| 1 <!-- |
| 2 @license |
| 3 Copyright (c) 2017 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --> |
| 10 |
| 11 <link rel="import" href="boot.html"> |
| 12 |
| 13 <script> |
| 14 (function() { |
| 15 'use strict'; |
| 16 |
| 17 /** |
| 18 * Module with utilities for manipulating structured data path strings. |
| 19 * |
| 20 * @namespace |
| 21 * @memberof Polymer |
| 22 * @summary Module with utilities for manipulating structured data path string
s. |
| 23 */ |
| 24 const Path = { |
| 25 |
| 26 /** |
| 27 * Returns true if the given string is a structured data path (has dots). |
| 28 * |
| 29 * Example: |
| 30 * |
| 31 * ``` |
| 32 * Polymer.Path.isPath('foo.bar.baz') // true |
| 33 * Polymer.Path.isPath('foo') // false |
| 34 * ``` |
| 35 * |
| 36 * @memberof Polymer.Path |
| 37 * @param {string} path Path string |
| 38 * @return {boolean} True if the string contained one or more dots |
| 39 */ |
| 40 isPath: function(path) { |
| 41 return path.indexOf('.') >= 0; |
| 42 }, |
| 43 |
| 44 /** |
| 45 * Returns the root property name for the given path. |
| 46 * |
| 47 * Example: |
| 48 * |
| 49 * ``` |
| 50 * Polymer.Path.root('foo.bar.baz') // 'foo' |
| 51 * Polymer.Path.root('foo') // 'foo' |
| 52 * ``` |
| 53 * |
| 54 * @memberof Polymer.Path |
| 55 * @param {string} path Path string |
| 56 * @return {string} Root property name |
| 57 */ |
| 58 root: function(path) { |
| 59 let dotIndex = path.indexOf('.'); |
| 60 if (dotIndex === -1) { |
| 61 return path; |
| 62 } |
| 63 return path.slice(0, dotIndex); |
| 64 }, |
| 65 |
| 66 /** |
| 67 * Given `base` is `foo.bar`, `foo` is an ancestor, `foo.bar` is not |
| 68 * Returns true if the given path is an ancestor of the base path. |
| 69 * |
| 70 * Example: |
| 71 * |
| 72 * ``` |
| 73 * Polymer.Path.isAncestor('foo.bar', 'foo') // true |
| 74 * Polymer.Path.isAncestor('foo.bar', 'foo.bar') // false |
| 75 * Polymer.Path.isAncestor('foo.bar', 'foo.bar.baz') // false |
| 76 * ``` |
| 77 * |
| 78 * @memberof Polymer.Path |
| 79 * @param {string} base Path string to test against. |
| 80 * @param {string} path Path string to test. |
| 81 * @return {boolean} True if `path` is an ancestor of `base`. |
| 82 */ |
| 83 isAncestor: function(base, path) { |
| 84 // base.startsWith(path + '.'); |
| 85 return base.indexOf(path + '.') === 0; |
| 86 }, |
| 87 |
| 88 /** |
| 89 * Given `base` is `foo.bar`, `foo.bar.baz` is an descendant |
| 90 * |
| 91 * Example: |
| 92 * |
| 93 * ``` |
| 94 * Polymer.Path.isDescendant('foo.bar', 'foo.bar.baz') // true |
| 95 * Polymer.Path.isDescendant('foo.bar', 'foo.bar') // false |
| 96 * Polymer.Path.isDescendant('foo.bar', 'foo') // false |
| 97 * ``` |
| 98 * |
| 99 * @memberof Polymer.Path |
| 100 * @param {string} base Path string to test against. |
| 101 * @param {string} path Path string to test. |
| 102 * @return {boolean} True if `path` is a descendant of `base`. |
| 103 */ |
| 104 isDescendant: function(base, path) { |
| 105 // path.startsWith(base + '.'); |
| 106 return path.indexOf(base + '.') === 0; |
| 107 }, |
| 108 |
| 109 /** |
| 110 * Replaces a previous base path with a new base path, preserving the |
| 111 * remainder of the path. |
| 112 * |
| 113 * User must ensure `path` has a prefix of `base`. |
| 114 * |
| 115 * Example: |
| 116 * |
| 117 * ``` |
| 118 * Polymer.Path.translate('foo.bar', 'zot' 'foo.bar.baz') // 'zot.baz' |
| 119 * ``` |
| 120 * |
| 121 * @memberof Polymer.Path |
| 122 * @param {string} base Current base string to remove |
| 123 * @param {string} newBase New base string to replace with |
| 124 * @param {string} path Path to translate |
| 125 * @return {string} Translated string |
| 126 */ |
| 127 translate: function(base, newBase, path) { |
| 128 return newBase + path.slice(base.length); |
| 129 }, |
| 130 |
| 131 matches: function(base, path) { |
| 132 return (base === path) || |
| 133 this.isAncestor(base, path) || |
| 134 this.isDescendant(base, path); |
| 135 }, |
| 136 |
| 137 /** |
| 138 * Converts array-based paths to flattened path. String-based paths |
| 139 * are returned as-is. |
| 140 * |
| 141 * Example: |
| 142 * |
| 143 * ``` |
| 144 * Polymer.Path.normalize(['foo.bar', 0, 'baz']) // 'foo.bar.0.baz' |
| 145 * Polymer.Path.normalize('foo.bar.0.baz') // 'foo.bar.0.baz' |
| 146 * ``` |
| 147 * |
| 148 * @memberof Polymer.Path |
| 149 * @param {string | !Array<string|number>} path Input path |
| 150 * @return {string} Flattened path |
| 151 */ |
| 152 normalize: function(path) { |
| 153 if (Array.isArray(path)) { |
| 154 let parts = []; |
| 155 for (let i=0; i<path.length; i++) { |
| 156 let args = path[i].toString().split('.'); |
| 157 for (let j=0; j<args.length; j++) { |
| 158 parts.push(args[j]); |
| 159 } |
| 160 } |
| 161 return parts.join('.'); |
| 162 } else { |
| 163 return path; |
| 164 } |
| 165 }, |
| 166 |
| 167 /** |
| 168 * Splits a path into an array of property names. Accepts either arrays |
| 169 * of path parts or strings. |
| 170 * |
| 171 * Example: |
| 172 * |
| 173 * ``` |
| 174 * Polymer.Path.split(['foo.bar', 0, 'baz']) // ['foo', 'bar', '0', 'baz'] |
| 175 * Polymer.Path.split('foo.bar.0.baz') // ['foo', 'bar', '0', 'baz'] |
| 176 * ``` |
| 177 * |
| 178 * @memberof Polymer.Path |
| 179 * @param {string | !Array<string|number>} path Input path |
| 180 * @return {!Array<string>} Array of path parts |
| 181 */ |
| 182 split: function(path) { |
| 183 if (Array.isArray(path)) { |
| 184 return this.normalize(path).split('.'); |
| 185 } |
| 186 return path.toString().split('.'); |
| 187 }, |
| 188 |
| 189 /** |
| 190 * Reads a value from a path. If any sub-property in the path is `undefined
`, |
| 191 * this method returns `undefined` (will never throw. |
| 192 * |
| 193 * @memberof Polymer.Path |
| 194 * @param {Object} root Object from which to dereference path from |
| 195 * @param {string | !Array<string|number>} path Path to read |
| 196 * @param {Object=} info If an object is provided to `info`, the normalized |
| 197 * (flattened) path will be set to `info.path`. |
| 198 * @return {*} Value at path, or `undefined` if the path could not be |
| 199 * fully dereferenced. |
| 200 */ |
| 201 get: function(root, path, info) { |
| 202 let prop = root; |
| 203 let parts = this.split(path); |
| 204 // Loop over path parts[0..n-1] and dereference |
| 205 for (let i=0; i<parts.length; i++) { |
| 206 if (!prop) { |
| 207 return; |
| 208 } |
| 209 let part = parts[i]; |
| 210 prop = prop[part]; |
| 211 } |
| 212 if (info) { |
| 213 info.path = parts.join('.'); |
| 214 } |
| 215 return prop; |
| 216 }, |
| 217 |
| 218 /** |
| 219 * Sets a value to a path. If any sub-property in the path is `undefined`, |
| 220 * this method will no-op. |
| 221 * |
| 222 * @memberof Polymer.Path |
| 223 * @param {Object} root Object from which to dereference path from |
| 224 * @param {string | !Array<string|number>} path Path to set |
| 225 * @param {*} value Value to set to path |
| 226 * @return {string | undefined} The normalized version of the input path |
| 227 */ |
| 228 set: function(root, path, value) { |
| 229 let prop = root; |
| 230 let parts = this.split(path); |
| 231 let last = parts[parts.length-1]; |
| 232 if (parts.length > 1) { |
| 233 // Loop over path parts[0..n-2] and dereference |
| 234 for (let i=0; i<parts.length-1; i++) { |
| 235 let part = parts[i]; |
| 236 prop = prop[part]; |
| 237 if (!prop) { |
| 238 return; |
| 239 } |
| 240 } |
| 241 // Set value to object at end of path |
| 242 prop[last] = value; |
| 243 } else { |
| 244 // Simple property set |
| 245 prop[path] = value; |
| 246 } |
| 247 return parts.join('.'); |
| 248 } |
| 249 |
| 250 }; |
| 251 |
| 252 /** |
| 253 * Returns true if the given string is a structured data path (has dots). |
| 254 * |
| 255 * This function is deprecated. Use `Polymer.Path.isPath` instead. |
| 256 * |
| 257 * Example: |
| 258 * |
| 259 * ``` |
| 260 * Polymer.Path.isDeep('foo.bar.baz') // true |
| 261 * Polymer.Path.isDeep('foo') // false |
| 262 * ``` |
| 263 * |
| 264 * @deprecated |
| 265 * @memberof Polymer.Path |
| 266 * @param {string} path Path string |
| 267 * @return {boolean} True if the string contained one or more dots |
| 268 */ |
| 269 Path.isDeep = Path.isPath; |
| 270 |
| 271 Polymer.Path = Path; |
| 272 |
| 273 })(); |
| 274 </script> |
| OLD | NEW |