Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e03e4f0

Browse files
committedFeb 7, 2019
Add Ptr with support for parsing/serializing
1 parent 9d20418 commit e03e4f0

File tree

4 files changed

+3783
-111
lines changed

4 files changed

+3783
-111
lines changed
 

‎package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
{
22
"devDependencies": {
3+
"@types/jest": "^23.0.0",
4+
"jest": "^23.0.0",
5+
"ts-jest": "^23.10.5",
6+
"tslint": "^5.12.1",
37
"typedoc": "^0.14.2",
48
"typescript": "^3.3.1"
9+
},
10+
"jest": {
11+
"transform": {
12+
"^.+\\.tsx?$": "ts-jest"
13+
},
14+
"rootDir": "src",
15+
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
16+
"moduleFileExtensions": [
17+
"js",
18+
"ts"
19+
]
520
}
621
}

‎src/index.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import Ptr, { InvalidPtrError } from "./index";
2+
3+
describe("Ptr", () => {
4+
describe("parse", () => {
5+
it("handles well-formed JSON Pointer strings correctly", () => {
6+
// These test cases are lifted from RFC6901, Section 5:
7+
//
8+
// https://tools.ietf.org/html/rfc6901#section-5
9+
const cases = {
10+
"": [],
11+
"/foo": ["foo"],
12+
"/foo/0": ["foo", "0"],
13+
"/": [""],
14+
"/a~1b": ["a/b"],
15+
"/c%d": ["c%d"],
16+
"/e^f": ["e^f"],
17+
"/g|h": ["g|h"],
18+
"/i\\j": ["i\\j"],
19+
"/k\"l": ["k\"l"],
20+
"/ ": [" "],
21+
"/m~0n": ["m~n"],
22+
"/o~0~1p/q~1~0r": ["o~/p", "q/~r"],
23+
};
24+
25+
for (const [input, output] of Object.entries(cases)) {
26+
const ptr = Ptr.parse(input);
27+
expect(ptr.tokens).toEqual(output);
28+
expect(ptr.toString()).toEqual(input);
29+
}
30+
});
31+
32+
it("throws an error for bad input", () => {
33+
expect(() => {
34+
Ptr.parse(" ");
35+
}).toThrowError(new InvalidPtrError(" "));
36+
});
37+
});
38+
});

‎src/index.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
export default class Ptr {
2+
public tokens: string[];
3+
4+
constructor(tokens: string[]) {
5+
this.tokens = tokens;
6+
}
7+
8+
public static parse(s: string): Ptr {
9+
// From the ABNF syntax of JSON Pointer, the only valid initial character
10+
// for a JSON Pointer is "/". Empty strings are acceptable.
11+
//
12+
// https://tools.ietf.org/html/rfc6901#section-3
13+
//
14+
// Other than this limitation, all strings are valid JSON Pointers.
15+
if (s === "") {
16+
return new Ptr([]);
17+
}
18+
19+
if (!s.startsWith("/")) {
20+
throw new InvalidPtrError(s);
21+
}
22+
23+
const [, ...tokens] = s.split("/");
24+
return new Ptr(tokens.map(token => {
25+
return token.replace("~1", "/").replace("~0", "~");
26+
}));
27+
}
28+
29+
public toString(): string {
30+
if (this.tokens.length === 0) {
31+
return "";
32+
}
33+
34+
const tokens = this.tokens.map(token => {
35+
return token.replace("~", "~0").replace("/", "~1");
36+
});
37+
38+
return `/${tokens.join("/")}`;
39+
}
40+
}
41+
42+
export class InvalidPtrError extends Error {
43+
public ptr: string;
44+
45+
constructor(ptr: string) {
46+
super(`Invalid JSON Pointer: ${ptr}`);
47+
this.ptr = ptr;
48+
}
49+
}

‎yarn.lock

Lines changed: 3681 additions & 111 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.