1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.Pointer = void 0;
|
4 | /**
|
5 | Unescape token part of a JSON Pointer string
|
6 |
|
7 | `token` should *not* contain any '/' characters.
|
8 |
|
9 | > Evaluation of each reference token begins by decoding any escaped
|
10 | > character sequence. This is performed by first transforming any
|
11 | > occurrence of the sequence '~1' to '/', and then transforming any
|
12 | > occurrence of the sequence '~0' to '~'. By performing the
|
13 | > substitutions in this order, an implementation avoids the error of
|
14 | > turning '~01' first into '~1' and then into '/', which would be
|
15 | > incorrect (the string '~01' correctly becomes '~1' after
|
16 | > transformation).
|
17 |
|
18 | Here's my take:
|
19 |
|
20 | ~1 is unescaped with higher priority than ~0 because it is a lower-order escape character.
|
21 | I say "lower order" because '/' needs escaping due to the JSON Pointer serialization technique.
|
22 | Whereas, '~' is escaped because escaping '/' uses the '~' character.
|
23 | */
|
24 | function unescape(token) {
|
25 | return token.replace(/~1/g, '/').replace(/~0/g, '~');
|
26 | }
|
27 | /** Escape token part of a JSON Pointer string
|
28 |
|
29 | > '~' needs to be encoded as '~0' and '/'
|
30 | > needs to be encoded as '~1' when these characters appear in a
|
31 | > reference token.
|
32 |
|
33 | This is the exact inverse of `unescape()`, so the reverse replacements must take place in reverse order.
|
34 | */
|
35 | function escape(token) {
|
36 | return token.replace(/~/g, '~0').replace(/\//g, '~1');
|
37 | }
|
38 | /**
|
39 | JSON Pointer representation
|
40 | */
|
41 | var Pointer = /** @class */ (function () {
|
42 | function Pointer(tokens) {
|
43 | if (tokens === void 0) { tokens = ['']; }
|
44 | this.tokens = tokens;
|
45 | }
|
46 | /**
|
47 | `path` *must* be a properly escaped string.
|
48 | */
|
49 | Pointer.fromJSON = function (path) {
|
50 | var tokens = path.split('/').map(unescape);
|
51 | if (tokens[0] !== '')
|
52 | throw new Error("Invalid JSON Pointer: " + path);
|
53 | return new Pointer(tokens);
|
54 | };
|
55 | Pointer.prototype.toString = function () {
|
56 | return this.tokens.map(escape).join('/');
|
57 | };
|
58 | /**
|
59 | Returns an object with 'parent', 'key', and 'value' properties.
|
60 | In the special case that this Pointer's path == "",
|
61 | this object will be {parent: null, key: '', value: object}.
|
62 | Otherwise, parent and key will have the property such that parent[key] == value.
|
63 | */
|
64 | Pointer.prototype.evaluate = function (object) {
|
65 | var parent = null;
|
66 | var key = '';
|
67 | var value = object;
|
68 | for (var i = 1, l = this.tokens.length; i < l; i++) {
|
69 | parent = value;
|
70 | key = this.tokens[i];
|
71 | // not sure if this the best way to handle non-existant paths...
|
72 | value = (parent || {})[key];
|
73 | }
|
74 | return { parent: parent, key: key, value: value };
|
75 | };
|
76 | Pointer.prototype.get = function (object) {
|
77 | return this.evaluate(object).value;
|
78 | };
|
79 | Pointer.prototype.set = function (object, value) {
|
80 | var cursor = object;
|
81 | for (var i = 1, l = this.tokens.length - 1, token = this.tokens[i]; i < l; i++) {
|
82 | // not sure if this the best way to handle non-existant paths...
|
83 | cursor = (cursor || {})[token];
|
84 | }
|
85 | if (cursor) {
|
86 | cursor[this.tokens[this.tokens.length - 1]] = value;
|
87 | }
|
88 | };
|
89 | Pointer.prototype.push = function (token) {
|
90 | // mutable
|
91 | this.tokens.push(token);
|
92 | };
|
93 | /**
|
94 | `token` should be a String. It'll be coerced to one anyway.
|
95 |
|
96 | immutable (shallowly)
|
97 | */
|
98 | Pointer.prototype.add = function (token) {
|
99 | var tokens = this.tokens.concat(String(token));
|
100 | return new Pointer(tokens);
|
101 | };
|
102 | return Pointer;
|
103 | }());
|
104 | exports.Pointer = Pointer;
|