UNPKG

3.66 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Pointer = void 0;
4/**
5Unescape 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
18Here's my take:
19
20~1 is unescaped with higher priority than ~0 because it is a lower-order escape character.
21I say "lower order" because '/' needs escaping due to the JSON Pointer serialization technique.
22Whereas, '~' is escaped because escaping '/' uses the '~' character.
23*/
24function 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
33This is the exact inverse of `unescape()`, so the reverse replacements must take place in reverse order.
34*/
35function escape(token) {
36 return token.replace(/~/g, '~0').replace(/\//g, '~1');
37}
38/**
39JSON Pointer representation
40*/
41var 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}());
104exports.Pointer = Pointer;