@difizen/libro-common 0.0.2-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +0 -0
- package/es/array.d.ts +368 -0
- package/es/array.d.ts.map +1 -0
- package/es/array.js +577 -0
- package/es/display-wrapper.d.ts +6 -0
- package/es/display-wrapper.d.ts.map +1 -0
- package/es/display-wrapper.js +12 -0
- package/es/index.d.ts +11 -0
- package/es/index.d.ts.map +1 -0
- package/es/index.js +10 -0
- package/es/iter.d.ts +147 -0
- package/es/iter.d.ts.map +1 -0
- package/es/iter.js +162 -0
- package/es/json.d.ts +126 -0
- package/es/json.d.ts.map +1 -0
- package/es/json.js +274 -0
- package/es/path.d.ts +97 -0
- package/es/path.d.ts.map +1 -0
- package/es/path.js +60 -0
- package/es/polling/index.d.ts +3 -0
- package/es/polling/index.d.ts.map +1 -0
- package/es/polling/index.js +2 -0
- package/es/polling/poll.d.ts +193 -0
- package/es/polling/poll.d.ts.map +1 -0
- package/es/polling/poll.js +501 -0
- package/es/polling/protocol.d.ts +120 -0
- package/es/polling/protocol.d.ts.map +1 -0
- package/es/polling/protocol.js +13 -0
- package/es/posix.d.ts +2 -0
- package/es/posix.d.ts.map +1 -0
- package/es/posix.js +71 -0
- package/es/protocol/cell-protocol.d.ts +181 -0
- package/es/protocol/cell-protocol.d.ts.map +1 -0
- package/es/protocol/cell-protocol.js +1 -0
- package/es/protocol/index.d.ts +4 -0
- package/es/protocol/index.d.ts.map +1 -0
- package/es/protocol/index.js +3 -0
- package/es/protocol/notebook-protocol.d.ts +63 -0
- package/es/protocol/notebook-protocol.d.ts.map +1 -0
- package/es/protocol/notebook-protocol.js +41 -0
- package/es/protocol/output-protocol.d.ts +125 -0
- package/es/protocol/output-protocol.d.ts.map +1 -0
- package/es/protocol/output-protocol.js +1 -0
- package/es/sanitizer.d.ts +44 -0
- package/es/sanitizer.d.ts.map +1 -0
- package/es/sanitizer.js +659 -0
- package/es/url.d.ts +98 -0
- package/es/url.d.ts.map +1 -0
- package/es/url.js +134 -0
- package/es/utils.d.ts +57 -0
- package/es/utils.d.ts.map +1 -0
- package/es/utils.js +124 -0
- package/package.json +62 -0
- package/src/array.ts +608 -0
- package/src/display-wrapper.tsx +11 -0
- package/src/index.ts +10 -0
- package/src/iter.ts +199 -0
- package/src/json.ts +321 -0
- package/src/path.ts +138 -0
- package/src/polling/index.ts +2 -0
- package/src/polling/poll.ts +508 -0
- package/src/polling/protocol.ts +145 -0
- package/src/posix.ts +75 -0
- package/src/protocol/cell-protocol.ts +215 -0
- package/src/protocol/index.ts +3 -0
- package/src/protocol/notebook-protocol.ts +73 -0
- package/src/protocol/output-protocol.ts +162 -0
- package/src/sanitizer.ts +944 -0
- package/src/url.ts +157 -0
- package/src/utils.ts +145 -0
package/src/iter.ts
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An object which can produce an iterator over its values.
|
|
3
|
+
*/
|
|
4
|
+
export interface IIterable<T> {
|
|
5
|
+
/**
|
|
6
|
+
* Get an iterator over the object's values.
|
|
7
|
+
*
|
|
8
|
+
* @returns An iterator which yields the object's values.
|
|
9
|
+
*
|
|
10
|
+
* #### Notes
|
|
11
|
+
* Depending on the iterable, the returned iterator may or may not be
|
|
12
|
+
* a new object. A collection or other container-like object should
|
|
13
|
+
* typically return a new iterator, while an iterator itself should
|
|
14
|
+
* normally return `this`.
|
|
15
|
+
*/
|
|
16
|
+
iter: () => IIterator<T>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* An object which traverses a collection of values.
|
|
21
|
+
*
|
|
22
|
+
* #### Notes
|
|
23
|
+
* An `IIterator` is itself an `IIterable`. Most implementations of
|
|
24
|
+
* `IIterator` should simply return `this` from the `iter()` method.
|
|
25
|
+
*/
|
|
26
|
+
export interface IIterator<T> extends IIterable<T> {
|
|
27
|
+
/**
|
|
28
|
+
* Create an independent clone of the iterator.
|
|
29
|
+
*
|
|
30
|
+
* @returns A new independent clone of the iterator.
|
|
31
|
+
*
|
|
32
|
+
* #### Notes
|
|
33
|
+
* The cloned iterator can be consumed independently of the current
|
|
34
|
+
* iterator. In essence, it is a copy of the iterator value stream
|
|
35
|
+
* which starts at the current location.
|
|
36
|
+
*
|
|
37
|
+
* This can be useful for lookahead and stream duplication.
|
|
38
|
+
*/
|
|
39
|
+
clone: () => IIterator<T>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get the next value from the iterator.
|
|
43
|
+
*
|
|
44
|
+
* @returns The next value from the iterator, or `undefined`.
|
|
45
|
+
*
|
|
46
|
+
* #### Notes
|
|
47
|
+
* The `undefined` value is used to signal the end of iteration and
|
|
48
|
+
* should therefore not be used as a value in a collection.
|
|
49
|
+
*
|
|
50
|
+
* The use of the `undefined` sentinel is an explicit design choice
|
|
51
|
+
* which favors performance over purity. The ES6 iterator design of
|
|
52
|
+
* returning a `{ value, done }` pair is suboptimal, as it requires
|
|
53
|
+
* an object allocation on each iteration; and an `isDone()` method
|
|
54
|
+
* would increase implementation and runtime complexity.
|
|
55
|
+
*/
|
|
56
|
+
next: () => T | undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A type alias for an iterable or builtin array-like object.
|
|
61
|
+
*/
|
|
62
|
+
export type IterableOrArrayLike<T> = IIterable<T> | ArrayLike<T>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* An iterator for an array-like object.
|
|
66
|
+
*
|
|
67
|
+
* #### Notes
|
|
68
|
+
* This iterator can be used for any builtin JS array-like object.
|
|
69
|
+
*/
|
|
70
|
+
export class ArrayIterator<T> implements IIterator<T> {
|
|
71
|
+
/**
|
|
72
|
+
* Construct a new array iterator.
|
|
73
|
+
*
|
|
74
|
+
* @param source - The array-like object of interest.
|
|
75
|
+
*/
|
|
76
|
+
constructor(source: ArrayLike<T>) {
|
|
77
|
+
this._source = source;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get an iterator over the object's values.
|
|
82
|
+
*
|
|
83
|
+
* @returns An iterator which yields the object's values.
|
|
84
|
+
*/
|
|
85
|
+
iter(): IIterator<T> {
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Create an independent clone of the iterator.
|
|
91
|
+
*
|
|
92
|
+
* @returns A new independent clone of the iterator.
|
|
93
|
+
*/
|
|
94
|
+
clone(): IIterator<T> {
|
|
95
|
+
const result = new ArrayIterator<T>(this._source);
|
|
96
|
+
result._index = this._index;
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get the next value from the iterator.
|
|
102
|
+
*
|
|
103
|
+
* @returns The next value from the iterator, or `undefined`.
|
|
104
|
+
*/
|
|
105
|
+
next(): T | undefined {
|
|
106
|
+
if (this._index >= this._source.length) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
return this._source[this._index++];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private _index = 0;
|
|
113
|
+
private _source: ArrayLike<T>;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Create an iterator for an iterable object.
|
|
118
|
+
*
|
|
119
|
+
* @param object - The iterable or array-like object of interest.
|
|
120
|
+
*
|
|
121
|
+
* @returns A new iterator for the given object.
|
|
122
|
+
*
|
|
123
|
+
* #### Notes
|
|
124
|
+
* This function allows iteration algorithms to operate on user-defined
|
|
125
|
+
* iterable types and builtin array-like objects in a uniform fashion.
|
|
126
|
+
*/
|
|
127
|
+
export function iter<T>(object: IterableOrArrayLike<T>): IIterator<T> {
|
|
128
|
+
let it: IIterator<T>;
|
|
129
|
+
if (typeof (object as any).iter === 'function') {
|
|
130
|
+
it = (object as IIterable<T>).iter();
|
|
131
|
+
} else {
|
|
132
|
+
it = new ArrayIterator<T>(object as ArrayLike<T>);
|
|
133
|
+
}
|
|
134
|
+
return it;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Invoke a function for each value in an iterable.
|
|
139
|
+
*
|
|
140
|
+
* @param object - The iterable or array-like object of interest.
|
|
141
|
+
*
|
|
142
|
+
* @param fn - The callback function to invoke for each value.
|
|
143
|
+
*
|
|
144
|
+
* #### Notes
|
|
145
|
+
* Iteration can be terminated early by returning `false` from the
|
|
146
|
+
* callback function.
|
|
147
|
+
*
|
|
148
|
+
* #### Complexity
|
|
149
|
+
* Linear.
|
|
150
|
+
*
|
|
151
|
+
* #### Example
|
|
152
|
+
* ```typescript
|
|
153
|
+
*
|
|
154
|
+
* let data = [5, 7, 0, -2, 9];
|
|
155
|
+
*
|
|
156
|
+
* each(data, value => { console.log(value); });
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export function each<T>(
|
|
160
|
+
object: IterableOrArrayLike<T>,
|
|
161
|
+
fn: (value: T, index: number) => boolean | void,
|
|
162
|
+
): void {
|
|
163
|
+
let index = 0;
|
|
164
|
+
const it = iter(object);
|
|
165
|
+
let value: T | undefined;
|
|
166
|
+
while ((value = it.next()) !== undefined) {
|
|
167
|
+
if (fn(value, index++) === false) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Create an array from an iterable of values.
|
|
175
|
+
*
|
|
176
|
+
* @param object - The iterable or array-like object of interest.
|
|
177
|
+
*
|
|
178
|
+
* @returns A new array of values from the given object.
|
|
179
|
+
*
|
|
180
|
+
* #### Example
|
|
181
|
+
* ```typescript
|
|
182
|
+
*
|
|
183
|
+
* let data = [1, 2, 3, 4, 5, 6];
|
|
184
|
+
*
|
|
185
|
+
* let stream = iter(data);
|
|
186
|
+
*
|
|
187
|
+
* toArray(stream); // [1, 2, 3, 4, 5, 6];
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export function toArray<T>(object: IterableOrArrayLike<T>): T[] {
|
|
191
|
+
let index = 0;
|
|
192
|
+
const result: T[] = [];
|
|
193
|
+
const it = iter(object);
|
|
194
|
+
let value: T | undefined;
|
|
195
|
+
while ((value = it.next()) !== undefined) {
|
|
196
|
+
result[index++] = value;
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
}
|
package/src/json.ts
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A type alias for a JSON primitive.
|
|
3
|
+
*/
|
|
4
|
+
export type JSONPrimitive = boolean | number | string | null;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A type alias for a JSON value.
|
|
8
|
+
*/
|
|
9
|
+
export type JSONValue = JSONPrimitive | { [key: string]: JSONValue } | JSONValue[];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A type definition for a JSON object.
|
|
13
|
+
*/
|
|
14
|
+
export type JSONObject = Record<string, JSONValue>;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A type definition for a JSON array.
|
|
18
|
+
*/
|
|
19
|
+
export type JSONArray = JSONValue[];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A type definition for a readonly JSON object.
|
|
23
|
+
*/
|
|
24
|
+
export type ReadonlyJSONObject = Readonly<Record<string, ReadonlyJSONValue>>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A type definition for a readonly JSON array.
|
|
28
|
+
*/
|
|
29
|
+
export type ReadonlyJSONArray = readonly ReadonlyJSONValue[];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A type alias for a readonly JSON value.
|
|
33
|
+
*/
|
|
34
|
+
export type ReadonlyJSONValue =
|
|
35
|
+
| JSONPrimitive
|
|
36
|
+
| Readonly<{ [key: string]: ReadonlyJSONValue }>
|
|
37
|
+
| readonly ReadonlyJSONValue[];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A type alias for a partial JSON value.
|
|
41
|
+
*
|
|
42
|
+
* Note: Partial here means that JSON object attributes can be `undefined`.
|
|
43
|
+
*/
|
|
44
|
+
export type PartialJSONValue =
|
|
45
|
+
| JSONPrimitive
|
|
46
|
+
| Partial<{ [key: string]: PartialJSONValue }>
|
|
47
|
+
| PartialJSONValue[];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A type definition for a partial JSON array.
|
|
51
|
+
*
|
|
52
|
+
* Note: Partial here means that JSON object attributes can be `undefined`.
|
|
53
|
+
*/
|
|
54
|
+
export type PartialJSONArray = PartialJSONValue[];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A type definition for a partial JSON object.
|
|
58
|
+
*
|
|
59
|
+
* Note: Partial here means that the JSON object attributes can be `undefined`.
|
|
60
|
+
*/
|
|
61
|
+
export type PartialJSONObject = Record<string, PartialJSONValue | undefined>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A type definition for a readonly partial JSON object.
|
|
65
|
+
*
|
|
66
|
+
* Note: Partial here means that JSON object attributes can be `undefined`.
|
|
67
|
+
*/
|
|
68
|
+
export type ReadonlyPartialJSONObject = Readonly<
|
|
69
|
+
Record<string, ReadonlyPartialJSONValue | undefined>
|
|
70
|
+
>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A type definition for a readonly partial JSON array.
|
|
74
|
+
*
|
|
75
|
+
* Note: Partial here means that JSON object attributes can be `undefined`.
|
|
76
|
+
*/
|
|
77
|
+
export type ReadonlyPartialJSONArray = readonly ReadonlyPartialJSONValue[];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* A type alias for a readonly partial JSON value.
|
|
81
|
+
*
|
|
82
|
+
* Note: Partial here means that JSON object attributes can be `undefined`.
|
|
83
|
+
*/
|
|
84
|
+
export type ReadonlyPartialJSONValue =
|
|
85
|
+
| JSONPrimitive
|
|
86
|
+
| { readonly [key: string]: ReadonlyPartialJSONValue | undefined }
|
|
87
|
+
| readonly ReadonlyPartialJSONValue[];
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A shared frozen empty JSONObject
|
|
91
|
+
*/
|
|
92
|
+
export const emptyObject = Object.freeze({}) as ReadonlyJSONObject;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* A shared frozen empty JSONArray
|
|
96
|
+
*/
|
|
97
|
+
export const emptyArray = Object.freeze([]) as ReadonlyJSONArray;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Test whether a JSON value is a primitive.
|
|
101
|
+
*
|
|
102
|
+
* @param value - The JSON value of interest.
|
|
103
|
+
*
|
|
104
|
+
* @returns `true` if the value is a primitive,`false` otherwise.
|
|
105
|
+
*/
|
|
106
|
+
export function isPrimitive(value: ReadonlyPartialJSONValue): value is JSONPrimitive {
|
|
107
|
+
return (
|
|
108
|
+
value === null ||
|
|
109
|
+
typeof value === 'boolean' ||
|
|
110
|
+
typeof value === 'number' ||
|
|
111
|
+
typeof value === 'string'
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Test whether a JSON value is an array.
|
|
117
|
+
*
|
|
118
|
+
* @param value - The JSON value of interest.
|
|
119
|
+
*
|
|
120
|
+
* @returns `true` if the value is a an array, `false` otherwise.
|
|
121
|
+
*/
|
|
122
|
+
export function isArray(value: JSONValue): value is JSONArray;
|
|
123
|
+
// export function isArray(value: ReadonlyJSONValue): value is ReadonlyJSONArray;
|
|
124
|
+
export function isArray(value: PartialJSONValue): value is PartialJSONArray;
|
|
125
|
+
export function isArray(
|
|
126
|
+
value: ReadonlyPartialJSONValue,
|
|
127
|
+
): value is ReadonlyPartialJSONArray;
|
|
128
|
+
export function isArray(value: ReadonlyPartialJSONValue): boolean {
|
|
129
|
+
return Array.isArray(value);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Test whether a JSON value is an object.
|
|
134
|
+
*
|
|
135
|
+
* @param value - The JSON value of interest.
|
|
136
|
+
*
|
|
137
|
+
* @returns `true` if the value is a an object, `false` otherwise.
|
|
138
|
+
*/
|
|
139
|
+
export function isObject(value: JSONValue): value is JSONObject;
|
|
140
|
+
// export function isObject(value: ReadonlyJSONValue): value is ReadonlyJSONObject;
|
|
141
|
+
export function isObject(value: PartialJSONValue): value is PartialJSONObject;
|
|
142
|
+
// export function isObject(value: ReadonlyPartialJSONValue): value is ReadonlyPartialJSONObject;
|
|
143
|
+
export function isObject(value: ReadonlyPartialJSONValue): boolean {
|
|
144
|
+
return !isPrimitive(value) && !isArray(value);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Compare two JSON values for deep equality.
|
|
149
|
+
*
|
|
150
|
+
* @param first - The first JSON value of interest.
|
|
151
|
+
*
|
|
152
|
+
* @param second - The second JSON value of interest.
|
|
153
|
+
*
|
|
154
|
+
* @returns `true` if the values are equivalent, `false` otherwise.
|
|
155
|
+
*/
|
|
156
|
+
export function deepEqual(
|
|
157
|
+
first: ReadonlyPartialJSONValue,
|
|
158
|
+
second: ReadonlyPartialJSONValue,
|
|
159
|
+
): boolean {
|
|
160
|
+
// Check referential and primitive equality first.
|
|
161
|
+
if (first === second) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// If one is a primitive, the `===` check ruled out the other.
|
|
166
|
+
if (isPrimitive(first) || isPrimitive(second)) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Test whether they are arrays.
|
|
171
|
+
const a1 = isArray(first);
|
|
172
|
+
const a2 = isArray(second);
|
|
173
|
+
|
|
174
|
+
// Bail if the types are different.
|
|
175
|
+
if (a1 !== a2) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// If they are both arrays, compare them.
|
|
180
|
+
if (a1 && a2) {
|
|
181
|
+
return deepArrayEqual(
|
|
182
|
+
first as ReadonlyPartialJSONArray,
|
|
183
|
+
second as ReadonlyPartialJSONArray,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// At this point, they must both be objects.
|
|
188
|
+
return deepObjectEqual(
|
|
189
|
+
first as ReadonlyPartialJSONObject,
|
|
190
|
+
second as ReadonlyPartialJSONObject,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Create a deep copy of a JSON value.
|
|
196
|
+
*
|
|
197
|
+
* @param value - The JSON value to copy.
|
|
198
|
+
*
|
|
199
|
+
* @returns A deep copy of the given JSON value.
|
|
200
|
+
*/
|
|
201
|
+
export function deepCopy<T extends ReadonlyPartialJSONValue>(value: T): T {
|
|
202
|
+
// Do nothing for primitive values.
|
|
203
|
+
if (isPrimitive(value)) {
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Deep copy an array.
|
|
208
|
+
if (isArray(value)) {
|
|
209
|
+
return deepArrayCopy(value);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Deep copy an object.
|
|
213
|
+
return deepObjectCopy(value);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Compare two JSON arrays for deep equality.
|
|
218
|
+
*/
|
|
219
|
+
function deepArrayEqual(
|
|
220
|
+
first: ReadonlyPartialJSONArray,
|
|
221
|
+
second: ReadonlyPartialJSONArray,
|
|
222
|
+
): boolean {
|
|
223
|
+
// Check referential equality first.
|
|
224
|
+
if (first === second) {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Test the arrays for equal length.
|
|
229
|
+
if (first.length !== second.length) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Compare the values for equality.
|
|
234
|
+
for (let i = 0, n = first.length; i < n; ++i) {
|
|
235
|
+
if (!deepEqual(first[i], second[i])) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// At this point, the arrays are equal.
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Compare two JSON objects for deep equality.
|
|
246
|
+
*/
|
|
247
|
+
function deepObjectEqual(
|
|
248
|
+
first: ReadonlyPartialJSONObject,
|
|
249
|
+
second: ReadonlyPartialJSONObject,
|
|
250
|
+
): boolean {
|
|
251
|
+
// Check referential equality first.
|
|
252
|
+
if (first === second) {
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Check for the first object's keys in the second object.
|
|
257
|
+
for (const key in first) {
|
|
258
|
+
if (first[key] !== undefined && !(key in second)) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Check for the second object's keys in the first object.
|
|
264
|
+
for (const key in second) {
|
|
265
|
+
if (second[key] !== undefined && !(key in first)) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Compare the values for equality.
|
|
271
|
+
for (const key in first) {
|
|
272
|
+
// Get the values.
|
|
273
|
+
const firstValue = first[key];
|
|
274
|
+
const secondValue = second[key];
|
|
275
|
+
|
|
276
|
+
// If both are undefined, ignore the key.
|
|
277
|
+
if (firstValue === undefined && secondValue === undefined) {
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// If only one value is undefined, the objects are not equal.
|
|
282
|
+
if (firstValue === undefined || secondValue === undefined) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Compare the values.
|
|
287
|
+
if (!deepEqual(firstValue, secondValue)) {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// At this point, the objects are equal.
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Create a deep copy of a JSON array.
|
|
298
|
+
*/
|
|
299
|
+
function deepArrayCopy(value: any): any {
|
|
300
|
+
const result = new Array<any>(value.length);
|
|
301
|
+
for (let i = 0, n = value.length; i < n; ++i) {
|
|
302
|
+
result[i] = deepCopy(value[i]);
|
|
303
|
+
}
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Create a deep copy of a JSON object.
|
|
309
|
+
*/
|
|
310
|
+
function deepObjectCopy(value: any): any {
|
|
311
|
+
const result: any = {};
|
|
312
|
+
for (const key in value) {
|
|
313
|
+
// Ignore undefined values.
|
|
314
|
+
const subvalue = value[key];
|
|
315
|
+
if (subvalue === undefined) {
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
result[key] = deepCopy(subvalue);
|
|
319
|
+
}
|
|
320
|
+
return result;
|
|
321
|
+
}
|
package/src/path.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-namespace */
|
|
3
|
+
|
|
4
|
+
import { posix } from 'path-browserify';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The namespace for path-related functions.
|
|
8
|
+
*
|
|
9
|
+
* Note that Jupyter server paths do not start with a leading slash.
|
|
10
|
+
*/
|
|
11
|
+
export namespace PathExt {
|
|
12
|
+
/**
|
|
13
|
+
* Join all arguments together and normalize the resulting path.
|
|
14
|
+
* Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown.
|
|
15
|
+
*
|
|
16
|
+
* @param paths - The string paths to join.
|
|
17
|
+
*/
|
|
18
|
+
export function join(...paths: string[]): string {
|
|
19
|
+
const path = posix.join(...paths);
|
|
20
|
+
return path === '.' ? '' : removeSlash(path);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Return the last portion of a path. Similar to the Unix basename command.
|
|
25
|
+
* Often used to extract the file name from a fully qualified path.
|
|
26
|
+
*
|
|
27
|
+
* @param path - The path to evaluate.
|
|
28
|
+
*
|
|
29
|
+
* @param ext - An extension to remove from the result.
|
|
30
|
+
*/
|
|
31
|
+
export function basename(path: string, ext?: string): string {
|
|
32
|
+
return posix.basename(path, ext);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get the directory name of a path, similar to the Unix dirname command.
|
|
37
|
+
* When an empty path is given, returns the root path.
|
|
38
|
+
*
|
|
39
|
+
* @param path - The file path.
|
|
40
|
+
*/
|
|
41
|
+
export function dirname(path: string): string {
|
|
42
|
+
const dir = removeSlash(posix.dirname(path));
|
|
43
|
+
return dir === '.' ? '' : dir;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get the extension of the path.
|
|
48
|
+
*
|
|
49
|
+
* @param path - The file path.
|
|
50
|
+
*
|
|
51
|
+
* @returns the extension of the file.
|
|
52
|
+
*
|
|
53
|
+
* #### Notes
|
|
54
|
+
* The extension is the string from the last occurrence of the `.`
|
|
55
|
+
* character to end of string in the last portion of the path, inclusive.
|
|
56
|
+
* If there is no `.` in the last portion of the path, or if the first
|
|
57
|
+
* character of the basename of path [[basename]] is `.`, then an
|
|
58
|
+
* empty string is returned.
|
|
59
|
+
*/
|
|
60
|
+
export function extname(path: string): string {
|
|
61
|
+
return posix.extname(path);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Normalize a string path, reducing '..' and '.' parts.
|
|
66
|
+
* When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used.
|
|
67
|
+
* When an empty path is given, returns the root path.
|
|
68
|
+
*
|
|
69
|
+
* @param path - The string path to normalize.
|
|
70
|
+
*/
|
|
71
|
+
export function normalize(path: string): string {
|
|
72
|
+
if (path === '') {
|
|
73
|
+
return '';
|
|
74
|
+
}
|
|
75
|
+
return removeSlash(posix.normalize(path));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Resolve a sequence of paths or path segments into an absolute path.
|
|
80
|
+
* The root path in the application has no leading slash, so it is removed.
|
|
81
|
+
*
|
|
82
|
+
* @param parts - The paths to join.
|
|
83
|
+
*
|
|
84
|
+
* #### Notes
|
|
85
|
+
* The right-most parameter is considered {to}. Other parameters are considered an array of {from}.
|
|
86
|
+
*
|
|
87
|
+
* Starting from leftmost {from} parameter, resolves {to} to an absolute path.
|
|
88
|
+
*
|
|
89
|
+
* If {to} isn't already absolute, {from} arguments are prepended in right to left order, until an absolute path is found. If after using all {from} paths still no absolute path is found, the current working directory is used as well. The resulting path is normalized, and trailing slashes are removed unless the path gets resolved to the root directory.
|
|
90
|
+
*/
|
|
91
|
+
export function resolve(...parts: string[]): string {
|
|
92
|
+
return removeSlash(posix.resolve(...parts));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Solve the relative path from {from} to {to}.
|
|
97
|
+
*
|
|
98
|
+
* @param from - The source path.
|
|
99
|
+
*
|
|
100
|
+
* @param to - The target path.
|
|
101
|
+
*
|
|
102
|
+
* #### Notes
|
|
103
|
+
* If from and to each resolve to the same path (after calling
|
|
104
|
+
* path.resolve() on each), a zero-length string is returned.
|
|
105
|
+
* If a zero-length string is passed as from or to, `/`
|
|
106
|
+
* will be used instead of the zero-length strings.
|
|
107
|
+
*/
|
|
108
|
+
export function relative(from: string, to: string): string {
|
|
109
|
+
return removeSlash(posix.relative(from, to));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Normalize a file extension to be of the type `'.foo'`.
|
|
114
|
+
*
|
|
115
|
+
* @param extension - the file extension.
|
|
116
|
+
*
|
|
117
|
+
* #### Notes
|
|
118
|
+
* Adds a leading dot if not present and converts to lower case.
|
|
119
|
+
*/
|
|
120
|
+
export function normalizeExtension(extension: string): string {
|
|
121
|
+
if (extension.length > 0 && extension.indexOf('.') !== 0) {
|
|
122
|
+
extension = `.${extension}`;
|
|
123
|
+
}
|
|
124
|
+
return extension;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Remove the leading slash from a path.
|
|
129
|
+
*
|
|
130
|
+
* @param path: the path from which to remove a leading slash.
|
|
131
|
+
*/
|
|
132
|
+
export function removeSlash(path: string): string {
|
|
133
|
+
if (path.indexOf('/') === 0) {
|
|
134
|
+
path = path.slice(1);
|
|
135
|
+
}
|
|
136
|
+
return path;
|
|
137
|
+
}
|
|
138
|
+
}
|