zustand-querystring 0.4.0 → 0.5.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/README.md +277 -60
- package/dist/chunk-TQQUWVLF.mjs +367 -0
- package/dist/format/json.d.mts +6 -0
- package/dist/format/json.d.ts +6 -0
- package/dist/format/json.js +59 -0
- package/dist/format/json.mjs +35 -0
- package/dist/format/marked.d.mts +67 -0
- package/dist/format/marked.d.ts +67 -0
- package/dist/format/marked.js +393 -0
- package/dist/format/marked.mjs +14 -0
- package/dist/format/plain.d.mts +49 -0
- package/dist/format/plain.d.ts +49 -0
- package/dist/format/plain.js +446 -0
- package/dist/format/plain.mjs +421 -0
- package/dist/index.d.mts +33 -16
- package/dist/index.d.ts +33 -16
- package/dist/index.js +454 -70
- package/dist/index.mjs +101 -71
- package/package.json +34 -8
- package/dist/format/readable.d.mts +0 -14
- package/dist/format/readable.d.ts +0 -14
- package/dist/format/readable.js +0 -238
- package/dist/format/readable.mjs +0 -212
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// src/parser.ts
|
|
5
|
-
function stringify(input) {
|
|
6
|
-
return encodeURIComponent(JSON.stringify(input));
|
|
7
|
-
}
|
|
8
|
-
function parse(str) {
|
|
9
|
-
return JSON.parse(decodeURIComponent(str));
|
|
10
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
marked
|
|
3
|
+
} from "./chunk-TQQUWVLF.mjs";
|
|
11
4
|
|
|
12
5
|
// src/middleware.ts
|
|
6
|
+
import { isEqual, mergeWith } from "lodash-es";
|
|
13
7
|
var compact = (newState, initialState, syncNull = false, syncUndefined = false) => {
|
|
14
8
|
const output = {};
|
|
15
9
|
const removed = [];
|
|
@@ -51,38 +45,60 @@ var translateSelectionToState = (selection, state) => {
|
|
|
51
45
|
return acc;
|
|
52
46
|
}, {});
|
|
53
47
|
};
|
|
48
|
+
var parseSearchString = (search) => {
|
|
49
|
+
const result = {};
|
|
50
|
+
search.slice(search.startsWith("?") ? 1 : 0).split("&").filter(Boolean).forEach((param) => {
|
|
51
|
+
const eqIndex = param.indexOf("=");
|
|
52
|
+
if (eqIndex === -1) return;
|
|
53
|
+
const key = param.slice(0, eqIndex);
|
|
54
|
+
const value = param.slice(eqIndex + 1);
|
|
55
|
+
if (!result[key]) {
|
|
56
|
+
result[key] = [];
|
|
57
|
+
}
|
|
58
|
+
result[key].push(value);
|
|
59
|
+
});
|
|
60
|
+
return result;
|
|
61
|
+
};
|
|
54
62
|
var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
55
63
|
const defaultedOptions = {
|
|
56
|
-
key:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
parse
|
|
60
|
-
},
|
|
64
|
+
key: false,
|
|
65
|
+
prefix: "",
|
|
66
|
+
format: marked,
|
|
61
67
|
syncNull: false,
|
|
62
68
|
syncUndefined: false,
|
|
63
69
|
...options
|
|
64
70
|
};
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
if (defaultedOptions.prefix === void 0) {
|
|
72
|
+
defaultedOptions.prefix = "";
|
|
73
|
+
}
|
|
74
|
+
const format = defaultedOptions.format;
|
|
75
|
+
const standalone = defaultedOptions.key === false;
|
|
76
|
+
const getStateFromUrl = (url, initialState) => {
|
|
77
|
+
const params = parseSearchString(url.search);
|
|
67
78
|
if (standalone) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
for (const param of params) {
|
|
77
|
-
const eqIndex = param.indexOf("=");
|
|
78
|
-
if (eqIndex === -1) continue;
|
|
79
|
-
const key = param.slice(0, eqIndex);
|
|
80
|
-
if (key === defaultedOptions.key) {
|
|
81
|
-
const value = param.slice(eqIndex + 1);
|
|
82
|
-
return value ? defaultedOptions.format.parse(value, false) : null;
|
|
79
|
+
let filteredParams = params;
|
|
80
|
+
if (defaultedOptions.prefix) {
|
|
81
|
+
filteredParams = {};
|
|
82
|
+
for (const [key, values] of Object.entries(params)) {
|
|
83
|
+
if (key.startsWith(defaultedOptions.prefix)) {
|
|
84
|
+
filteredParams[key.slice(defaultedOptions.prefix.length)] = values;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
83
87
|
}
|
|
88
|
+
const result = format.parseStandalone(filteredParams, { initialState });
|
|
89
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
90
|
+
} else {
|
|
91
|
+
const fullKey = defaultedOptions.prefix + defaultedOptions.key;
|
|
92
|
+
const values = params[fullKey];
|
|
93
|
+
if (values && values.length > 0) {
|
|
94
|
+
try {
|
|
95
|
+
return format.parse(values[0], { initialState });
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
84
101
|
}
|
|
85
|
-
return null;
|
|
86
102
|
};
|
|
87
103
|
const getSelectedState = (state, pathname) => {
|
|
88
104
|
if (defaultedOptions.select) {
|
|
@@ -94,18 +110,25 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
94
110
|
};
|
|
95
111
|
const initialize = (url, initialState) => {
|
|
96
112
|
try {
|
|
97
|
-
const
|
|
98
|
-
if (!
|
|
113
|
+
const stateFromUrl = getStateFromUrl(url, initialState);
|
|
114
|
+
if (!stateFromUrl) {
|
|
99
115
|
return initialState;
|
|
100
116
|
}
|
|
117
|
+
const selected = getSelectedState(stateFromUrl, url.pathname);
|
|
101
118
|
const merged = mergeWith(
|
|
102
119
|
{},
|
|
103
120
|
initialState,
|
|
104
|
-
|
|
121
|
+
selected,
|
|
122
|
+
(_objValue, srcValue) => {
|
|
123
|
+
if (Array.isArray(srcValue)) {
|
|
124
|
+
return srcValue;
|
|
125
|
+
}
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
105
128
|
);
|
|
106
129
|
return merged;
|
|
107
130
|
} catch (error) {
|
|
108
|
-
console.error(error);
|
|
131
|
+
console.error("[initialize] error:", error);
|
|
109
132
|
return initialState;
|
|
110
133
|
}
|
|
111
134
|
};
|
|
@@ -128,31 +151,53 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
128
151
|
defaultedOptions.syncUndefined
|
|
129
152
|
);
|
|
130
153
|
const previous = url.search;
|
|
154
|
+
let stateParams;
|
|
155
|
+
let managedKeys;
|
|
156
|
+
if (standalone) {
|
|
157
|
+
const allParams = format.stringifyStandalone(selectedState);
|
|
158
|
+
managedKeys = new Set(Object.keys(allParams).map((k) => defaultedOptions.prefix + k));
|
|
159
|
+
const compactedParams = format.stringifyStandalone(newCompacted);
|
|
160
|
+
stateParams = {};
|
|
161
|
+
for (const [key, values] of Object.entries(compactedParams)) {
|
|
162
|
+
stateParams[defaultedOptions.prefix + key] = values;
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
const fullKey = defaultedOptions.prefix + defaultedOptions.key;
|
|
166
|
+
if (Object.keys(newCompacted).length > 0) {
|
|
167
|
+
stateParams = { [fullKey]: [format.stringify(newCompacted)] };
|
|
168
|
+
} else {
|
|
169
|
+
stateParams = {};
|
|
170
|
+
}
|
|
171
|
+
managedKeys = /* @__PURE__ */ new Set([fullKey]);
|
|
172
|
+
}
|
|
173
|
+
const valuesToWrite = /* @__PURE__ */ new Map();
|
|
174
|
+
const keyOrder = [];
|
|
175
|
+
for (const [key, values] of Object.entries(stateParams)) {
|
|
176
|
+
valuesToWrite.set(key, [...values]);
|
|
177
|
+
keyOrder.push(key);
|
|
178
|
+
}
|
|
131
179
|
const params = url.search.slice(1).split("&").filter(Boolean);
|
|
132
|
-
const managedKeys = standalone ? new Set(Object.keys(selectedState).map(encodeURI)) : /* @__PURE__ */ new Set([defaultedOptions.key]);
|
|
133
|
-
const valuesToWrite = standalone ? new Map(
|
|
134
|
-
Object.entries(newCompacted).map(([k, v]) => [encodeURI(k), v])
|
|
135
|
-
) : Object.keys(newCompacted).length ? /* @__PURE__ */ new Map([[defaultedOptions.key, newCompacted]]) : /* @__PURE__ */ new Map();
|
|
136
180
|
const result = [];
|
|
137
|
-
params.forEach((
|
|
138
|
-
const
|
|
181
|
+
params.forEach((param) => {
|
|
182
|
+
const eqIndex = param.indexOf("=");
|
|
183
|
+
if (eqIndex === -1) return;
|
|
184
|
+
const key = param.slice(0, eqIndex);
|
|
139
185
|
if (!managedKeys.has(key)) {
|
|
140
|
-
result.push(
|
|
186
|
+
result.push(param);
|
|
141
187
|
return;
|
|
142
188
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
);
|
|
148
|
-
result.push(`${key}=${encoded}`);
|
|
149
|
-
valuesToWrite.delete(key);
|
|
189
|
+
const values = valuesToWrite.get(key);
|
|
190
|
+
if (values && values.length > 0) {
|
|
191
|
+
const value = values.shift();
|
|
192
|
+
result.push(`${key}=${value}`);
|
|
150
193
|
}
|
|
151
194
|
});
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
195
|
+
for (const key of keyOrder) {
|
|
196
|
+
const values = valuesToWrite.get(key);
|
|
197
|
+
if (values) {
|
|
198
|
+
values.forEach((v) => result.push(`${key}=${v}`));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
156
201
|
url.search = result.length ? "?" + result.join("&") : "";
|
|
157
202
|
if (url.search !== previous) {
|
|
158
203
|
history.replaceState(history.state, "", url);
|
|
@@ -189,21 +234,6 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
189
234
|
return fn(set, get, api);
|
|
190
235
|
};
|
|
191
236
|
var querystring = queryStringImpl;
|
|
192
|
-
|
|
193
|
-
// src/utils.ts
|
|
194
|
-
var createURL = ({
|
|
195
|
-
baseUrl,
|
|
196
|
-
key,
|
|
197
|
-
state
|
|
198
|
-
}) => {
|
|
199
|
-
const url = new URL(baseUrl);
|
|
200
|
-
const stringified = stringify(state);
|
|
201
|
-
url.searchParams.set(key, stringified);
|
|
202
|
-
return url.href;
|
|
203
|
-
};
|
|
204
237
|
export {
|
|
205
|
-
|
|
206
|
-
parse,
|
|
207
|
-
querystring,
|
|
208
|
-
stringify
|
|
238
|
+
querystring
|
|
209
239
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zustand-querystring",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -25,17 +25,33 @@
|
|
|
25
25
|
"import": "./dist/index.mjs",
|
|
26
26
|
"require": "./dist/index.js"
|
|
27
27
|
},
|
|
28
|
-
"./format/
|
|
29
|
-
"types": "./dist/format/
|
|
30
|
-
"import": "./dist/format/
|
|
31
|
-
"require": "./dist/format/
|
|
28
|
+
"./format/marked": {
|
|
29
|
+
"types": "./dist/format/marked.d.ts",
|
|
30
|
+
"import": "./dist/format/marked.mjs",
|
|
31
|
+
"require": "./dist/format/marked.js"
|
|
32
|
+
},
|
|
33
|
+
"./format/plain": {
|
|
34
|
+
"types": "./dist/format/plain.d.ts",
|
|
35
|
+
"import": "./dist/format/plain.mjs",
|
|
36
|
+
"require": "./dist/format/plain.js"
|
|
37
|
+
},
|
|
38
|
+
"./format/json": {
|
|
39
|
+
"types": "./dist/format/json.d.ts",
|
|
40
|
+
"import": "./dist/format/json.mjs",
|
|
41
|
+
"require": "./dist/format/json.js"
|
|
32
42
|
},
|
|
33
43
|
"./package.json": "./package.json"
|
|
34
44
|
},
|
|
35
45
|
"typesVersions": {
|
|
36
46
|
"*": {
|
|
37
|
-
"format/
|
|
38
|
-
"./dist/format/
|
|
47
|
+
"format/marked": [
|
|
48
|
+
"./dist/format/marked.d.ts"
|
|
49
|
+
],
|
|
50
|
+
"format/plain": [
|
|
51
|
+
"./dist/format/plain.d.ts"
|
|
52
|
+
],
|
|
53
|
+
"format/json": [
|
|
54
|
+
"./dist/format/json.d.ts"
|
|
39
55
|
]
|
|
40
56
|
}
|
|
41
57
|
},
|
|
@@ -48,7 +64,9 @@
|
|
|
48
64
|
],
|
|
49
65
|
"entry": {
|
|
50
66
|
"index": "src/index.ts",
|
|
51
|
-
"format/
|
|
67
|
+
"format/marked": "src/format/marked.ts",
|
|
68
|
+
"format/plain": "src/format/plain.ts",
|
|
69
|
+
"format/json": "src/format/json.ts"
|
|
52
70
|
},
|
|
53
71
|
"dts": true
|
|
54
72
|
},
|
|
@@ -64,10 +82,18 @@
|
|
|
64
82
|
},
|
|
65
83
|
"devDependencies": {
|
|
66
84
|
"@types/lodash-es": "^4.17.12",
|
|
85
|
+
"@types/react": "^19.0.10",
|
|
86
|
+
"@types/react-dom": "^19.0.4",
|
|
87
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
88
|
+
"@vitest/browser-playwright": "^4.0.14",
|
|
89
|
+
"@vitest/coverage-v8": "^4.0.14",
|
|
90
|
+
"react": "^19.0.0",
|
|
91
|
+
"react-dom": "^19.0.0",
|
|
67
92
|
"rimraf": "^6.0.1",
|
|
68
93
|
"tsup": "^8.4.0",
|
|
69
94
|
"typescript": "^5.8.2",
|
|
70
95
|
"vitest": "^4.0.12",
|
|
96
|
+
"vitest-browser-react": "^2.0.2",
|
|
71
97
|
"zustand": "^5.0.3"
|
|
72
98
|
}
|
|
73
99
|
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* URL-Safe Serialization
|
|
3
|
-
*
|
|
4
|
-
* Inspired by URLON (https://github.com/cerebral/urlon)
|
|
5
|
-
* Copyright (c) 2021 Cerebral - MIT License
|
|
6
|
-
*/
|
|
7
|
-
declare function stringify(value: unknown, standalone?: boolean): string;
|
|
8
|
-
declare function parse<T = unknown>(input: string, standalone?: boolean): T;
|
|
9
|
-
declare const readable: {
|
|
10
|
-
stringify: typeof stringify;
|
|
11
|
-
parse: typeof parse;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export { parse, readable, stringify };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* URL-Safe Serialization
|
|
3
|
-
*
|
|
4
|
-
* Inspired by URLON (https://github.com/cerebral/urlon)
|
|
5
|
-
* Copyright (c) 2021 Cerebral - MIT License
|
|
6
|
-
*/
|
|
7
|
-
declare function stringify(value: unknown, standalone?: boolean): string;
|
|
8
|
-
declare function parse<T = unknown>(input: string, standalone?: boolean): T;
|
|
9
|
-
declare const readable: {
|
|
10
|
-
stringify: typeof stringify;
|
|
11
|
-
parse: typeof parse;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export { parse, readable, stringify };
|
package/dist/format/readable.js
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
-
var __export = (target, all) => {
|
|
6
|
-
for (var name in all)
|
|
7
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
-
};
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
-
|
|
19
|
-
// src/format/readable.ts
|
|
20
|
-
var readable_exports = {};
|
|
21
|
-
__export(readable_exports, {
|
|
22
|
-
parse: () => parse,
|
|
23
|
-
readable: () => readable,
|
|
24
|
-
stringify: () => stringify
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(readable_exports);
|
|
27
|
-
var TYPE_OBJECT = ".";
|
|
28
|
-
var TYPE_ARRAY = "@";
|
|
29
|
-
var TYPE_STRING = "=";
|
|
30
|
-
var TYPE_PRIMITIVE = ":";
|
|
31
|
-
var SEPARATOR = ",";
|
|
32
|
-
var TERMINATOR = "~";
|
|
33
|
-
var ESCAPE = "/";
|
|
34
|
-
var DATE_PREFIX = "D";
|
|
35
|
-
var esc = (c) => /[.$^*+?()[\]{}|\\]/.test(c) ? `\\${c}` : c;
|
|
36
|
-
var KEY_STOP = new RegExp(
|
|
37
|
-
`[${TYPE_STRING}${TYPE_PRIMITIVE}${TYPE_ARRAY}${esc(TYPE_OBJECT)}${esc(SEPARATOR)}]`
|
|
38
|
-
);
|
|
39
|
-
var VALUE_STOP = new RegExp(`[${esc(SEPARATOR)}${TERMINATOR}]`);
|
|
40
|
-
var KEY_ESCAPE = new RegExp(
|
|
41
|
-
`([${TYPE_STRING}${TYPE_PRIMITIVE}${TYPE_ARRAY}${esc(TYPE_OBJECT)}${ESCAPE}${esc(SEPARATOR)}])`,
|
|
42
|
-
"g"
|
|
43
|
-
);
|
|
44
|
-
var VALUE_ESCAPE = new RegExp(
|
|
45
|
-
`([${esc(SEPARATOR)}${TERMINATOR}${ESCAPE}])`,
|
|
46
|
-
"g"
|
|
47
|
-
);
|
|
48
|
-
function escapeStr(str, pattern) {
|
|
49
|
-
return encodeURI(str.replace(pattern, `${ESCAPE}$1`));
|
|
50
|
-
}
|
|
51
|
-
function cleanResult(str, standalone) {
|
|
52
|
-
while (str.endsWith(TERMINATOR)) str = str.slice(0, -1);
|
|
53
|
-
const datePattern = new RegExp(`^${esc(TYPE_STRING)}${DATE_PREFIX}-?\\d+$`);
|
|
54
|
-
if (standalone && datePattern.test(str)) {
|
|
55
|
-
return str.slice(1);
|
|
56
|
-
}
|
|
57
|
-
if (!standalone && str.startsWith(TYPE_OBJECT)) {
|
|
58
|
-
return str.slice(1);
|
|
59
|
-
}
|
|
60
|
-
return str;
|
|
61
|
-
}
|
|
62
|
-
function stringify(value, standalone = false) {
|
|
63
|
-
return cleanResult(serialize(value, standalone), standalone);
|
|
64
|
-
}
|
|
65
|
-
function serialize(value, standalone, inArray = false) {
|
|
66
|
-
if (value === null) return `${TYPE_PRIMITIVE}null`;
|
|
67
|
-
if (value === void 0) return `${TYPE_PRIMITIVE}undefined`;
|
|
68
|
-
if (typeof value === "function") return "";
|
|
69
|
-
if (typeof value === "number") {
|
|
70
|
-
return `${TYPE_PRIMITIVE}${String(value).replace(/\./g, `${ESCAPE}.`)}`;
|
|
71
|
-
}
|
|
72
|
-
if (typeof value === "boolean") {
|
|
73
|
-
return `${TYPE_PRIMITIVE}${value}`;
|
|
74
|
-
}
|
|
75
|
-
if (value instanceof Date) {
|
|
76
|
-
return `${TYPE_STRING}${DATE_PREFIX}${value.getTime()}`;
|
|
77
|
-
}
|
|
78
|
-
if (Array.isArray(value)) {
|
|
79
|
-
const items = value.map((v) => serialize(v, standalone, true));
|
|
80
|
-
return `${TYPE_ARRAY}${items.join(SEPARATOR)}${TERMINATOR}`;
|
|
81
|
-
}
|
|
82
|
-
if (typeof value === "object") {
|
|
83
|
-
const entries = [];
|
|
84
|
-
for (const [k, v] of Object.entries(value)) {
|
|
85
|
-
const val = serialize(v, false, false);
|
|
86
|
-
if (val || v === void 0) {
|
|
87
|
-
entries.push(`${escapeStr(k, KEY_ESCAPE)}${val}`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return `${TYPE_OBJECT}${entries.join(SEPARATOR)}${TERMINATOR}`;
|
|
91
|
-
}
|
|
92
|
-
const strVal = String(value);
|
|
93
|
-
let escaped = escapeStr(strVal, VALUE_ESCAPE);
|
|
94
|
-
const datePattern = new RegExp(`^${DATE_PREFIX}-?\\d`);
|
|
95
|
-
if (datePattern.test(strVal)) {
|
|
96
|
-
escaped = ESCAPE + escaped;
|
|
97
|
-
}
|
|
98
|
-
return standalone || inArray ? escaped : `${TYPE_STRING}${escaped}`;
|
|
99
|
-
}
|
|
100
|
-
function parse(input, standalone = false) {
|
|
101
|
-
const str = decodeURI(input);
|
|
102
|
-
if (str.length === 0) {
|
|
103
|
-
return standalone ? "" : {};
|
|
104
|
-
}
|
|
105
|
-
const first = str[0];
|
|
106
|
-
const hasMarker = first === TYPE_STRING || first === TYPE_PRIMITIVE || first === TYPE_ARRAY || first === TYPE_OBJECT;
|
|
107
|
-
let source;
|
|
108
|
-
if (hasMarker) {
|
|
109
|
-
source = str;
|
|
110
|
-
} else if (standalone) {
|
|
111
|
-
const datePattern = new RegExp(`^${DATE_PREFIX}-?\\d+$`);
|
|
112
|
-
if (datePattern.test(str)) {
|
|
113
|
-
const timestamp = parseInt(str.slice(DATE_PREFIX.length), 10);
|
|
114
|
-
if (!isNaN(timestamp)) {
|
|
115
|
-
return new Date(timestamp);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return str;
|
|
119
|
-
} else {
|
|
120
|
-
const markers = `${TYPE_STRING}${TYPE_PRIMITIVE}${TYPE_ARRAY}${TYPE_OBJECT}`;
|
|
121
|
-
const objectPattern = new RegExp(
|
|
122
|
-
`[^${ESCAPE}${markers}${SEPARATOR}${TERMINATOR}][${markers}]`
|
|
123
|
-
);
|
|
124
|
-
source = objectPattern.test(str) ? `${TYPE_OBJECT}${str}` : `${TYPE_STRING}${str}`;
|
|
125
|
-
}
|
|
126
|
-
let pos = 0;
|
|
127
|
-
function peek() {
|
|
128
|
-
return source[pos] || "";
|
|
129
|
-
}
|
|
130
|
-
function advance() {
|
|
131
|
-
pos++;
|
|
132
|
-
}
|
|
133
|
-
function readUntil(stopPattern, checkEscape = false) {
|
|
134
|
-
let result = "";
|
|
135
|
-
let wasEscaped = false;
|
|
136
|
-
while (pos < source.length) {
|
|
137
|
-
const ch = peek();
|
|
138
|
-
if (ch === ESCAPE) {
|
|
139
|
-
if (checkEscape && pos + 1 < source.length && source[pos + 1] === DATE_PREFIX) {
|
|
140
|
-
wasEscaped = true;
|
|
141
|
-
}
|
|
142
|
-
advance();
|
|
143
|
-
if (pos < source.length) {
|
|
144
|
-
result += peek();
|
|
145
|
-
advance();
|
|
146
|
-
}
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
if (stopPattern.test(ch)) break;
|
|
150
|
-
result += ch;
|
|
151
|
-
advance();
|
|
152
|
-
}
|
|
153
|
-
return { value: result, wasEscaped };
|
|
154
|
-
}
|
|
155
|
-
function parseString() {
|
|
156
|
-
const { value, wasEscaped } = readUntil(VALUE_STOP, true);
|
|
157
|
-
const datePattern = new RegExp(`^${DATE_PREFIX}-?\\d+$`);
|
|
158
|
-
if (!wasEscaped && datePattern.test(value)) {
|
|
159
|
-
const timestamp = parseInt(value.slice(DATE_PREFIX.length), 10);
|
|
160
|
-
if (!isNaN(timestamp)) {
|
|
161
|
-
return new Date(timestamp);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return value;
|
|
165
|
-
}
|
|
166
|
-
function parsePrimitive() {
|
|
167
|
-
const { value } = readUntil(VALUE_STOP, false);
|
|
168
|
-
if (value === "null") return null;
|
|
169
|
-
if (value === "undefined") return void 0;
|
|
170
|
-
if (value === "true") return true;
|
|
171
|
-
if (value === "false") return false;
|
|
172
|
-
return parseFloat(value);
|
|
173
|
-
}
|
|
174
|
-
function parseArray() {
|
|
175
|
-
const result = [];
|
|
176
|
-
let lastWasSeparator = false;
|
|
177
|
-
while (pos < source.length && peek() !== TERMINATOR) {
|
|
178
|
-
if (peek() === SEPARATOR) {
|
|
179
|
-
result.push("");
|
|
180
|
-
advance();
|
|
181
|
-
lastWasSeparator = true;
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
lastWasSeparator = false;
|
|
185
|
-
const ch = peek();
|
|
186
|
-
if (ch === TYPE_PRIMITIVE || ch === TYPE_ARRAY || ch === TYPE_OBJECT || ch === TYPE_STRING) {
|
|
187
|
-
result.push(parseValue());
|
|
188
|
-
} else {
|
|
189
|
-
result.push(parseString());
|
|
190
|
-
}
|
|
191
|
-
if (pos < source.length && peek() === SEPARATOR) {
|
|
192
|
-
advance();
|
|
193
|
-
lastWasSeparator = true;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
if (lastWasSeparator && (peek() === TERMINATOR || pos >= source.length)) {
|
|
197
|
-
result.push("");
|
|
198
|
-
}
|
|
199
|
-
if (peek() === TERMINATOR) advance();
|
|
200
|
-
return result;
|
|
201
|
-
}
|
|
202
|
-
function parseObject() {
|
|
203
|
-
const result = {};
|
|
204
|
-
while (pos < source.length && peek() !== TERMINATOR) {
|
|
205
|
-
const { value: key } = readUntil(KEY_STOP, false);
|
|
206
|
-
result[key] = parseValue();
|
|
207
|
-
if (pos < source.length && peek() !== TERMINATOR && peek() === SEPARATOR) {
|
|
208
|
-
advance();
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
if (peek() === TERMINATOR) advance();
|
|
212
|
-
return result;
|
|
213
|
-
}
|
|
214
|
-
function parseValue() {
|
|
215
|
-
const type = peek();
|
|
216
|
-
advance();
|
|
217
|
-
switch (type) {
|
|
218
|
-
case TYPE_PRIMITIVE:
|
|
219
|
-
return parsePrimitive();
|
|
220
|
-
case TYPE_ARRAY:
|
|
221
|
-
return parseArray();
|
|
222
|
-
case TYPE_OBJECT:
|
|
223
|
-
return parseObject();
|
|
224
|
-
case TYPE_STRING:
|
|
225
|
-
return parseString();
|
|
226
|
-
default:
|
|
227
|
-
throw new Error(`Unexpected type "${type}" at position ${pos}`);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return parseValue();
|
|
231
|
-
}
|
|
232
|
-
var readable = { stringify, parse };
|
|
233
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
234
|
-
0 && (module.exports = {
|
|
235
|
-
parse,
|
|
236
|
-
readable,
|
|
237
|
-
stringify
|
|
238
|
-
});
|