@@ -32,34 +32,38 @@ export function stringifySearch(
3232}
3333
3434export function parseSearch ( searchString : string ) : Record < string , unknown > {
35- const urlSearchParams = new URLSearchParams ( searchString )
3635 const searchRecord : Record < string , string | boolean > = { }
3736 const filters : Filter [ ] = [ ]
3837 const labels : FilterClauseLabels = { }
39- urlSearchParams . forEach ( ( value , key ) => {
38+
39+ for ( const param of searchString . startsWith ( '?' )
40+ ? searchString . slice ( 1 ) . split ( '&' )
41+ : searchString . split ( '&' ) ) {
42+ const [ key , rawValue ] = param . split ( '=' )
4043 switch ( key ) {
4144 case FILTER_URL_PARAM_NAME : {
42- const filter = parseFilter ( value )
45+ const filter = parseFilter ( rawValue )
4346 if ( filter . length === 3 && filter [ 2 ] . length ) {
4447 filters . push ( filter )
4548 }
4649 break
4750 }
4851 case LABEL_URL_PARAM_NAME : {
49- const [ labelKey , labelValue ] = parseLabelsEntry ( value )
52+ const [ labelKey , labelValue ] = parseLabelsEntry ( rawValue )
5053 if ( labelKey . length && labelValue . length ) {
5154 labels [ labelKey ] = labelValue
5255 }
5356 break
5457 }
5558 default : {
56- const parsedValue = parseSimpleSearchEntry ( value )
59+ const parsedValue = parseSimpleSearchEntry ( rawValue )
5760 if ( parsedValue !== null ) {
58- searchRecord [ key ] = parsedValue
61+ searchRecord [ decodeURIComponent ( key ) ] = parsedValue
5962 }
6063 }
6164 }
62- } )
65+ }
66+
6367 return {
6468 ...searchRecord ,
6569 ...( filters . length && { filters } ) ,
@@ -79,14 +83,13 @@ export function serializeLabelsEntry([labelKey, labelValue]: [string, string]) {
7983}
8084
8185/**
82- * Parses the output of @see serializeLabelsEntry back to labels object entry,
83- * once it has gone through URL decoding via new URLSearchParams(location.search).
86+ * Parses the output of @see serializeLabelsEntry back to labels object entry.
8487 */
8588export function parseLabelsEntry (
8689 labelKeyValueString : string
8790) : [ string , string ] {
8891 const [ key , value ] = labelKeyValueString . split ( ',' )
89- return [ key , value ]
92+ return [ decodeURIComponent ( key ) , decodeURIComponent ( value ) ]
9093}
9194
9295/**
@@ -96,8 +99,8 @@ export function parseLabelsEntry(
9699 */
97100export function serializeFilter ( [ operator , dimension , clauses ] : Filter ) {
98101 const serializedFilter = [
99- operator ,
100- dimension ,
102+ encodeURIComponentPermissive ( operator , ':/' ) ,
103+ encodeURIComponentPermissive ( dimension , ':/' ) ,
101104 ...clauses . map ( ( clause ) =>
102105 encodeURIComponentPermissive ( clause . toString ( ) , ':/' )
103106 )
@@ -106,17 +109,23 @@ export function serializeFilter([operator, dimension, clauses]: Filter) {
106109}
107110
108111/**
109- * Parses the output of @see serializeFilter back to filters array item,
110- * once it has gone through URL decoding via new URLSearchParams(location.search).
112+ * Parses the output of @see serializeFilter back to filters array item.
111113 */
112114export function parseFilter ( filterString : string ) : Filter {
113115 const [ operator , dimension , ...unparsedClauses ] = filterString . split ( ',' )
114- return [ operator , dimension , unparsedClauses ]
116+ return [
117+ decodeURIComponent ( operator ) ,
118+ decodeURIComponent ( dimension ) ,
119+ unparsedClauses . map ( decodeURIComponent )
120+ ]
115121}
116122
117123/**
118124 * Encodes for URL simple search param values.
125+ * Encodes numbers and number-like strings as indistinguishable strings. Parse treats them as strings.
126+ * Encodes booleans and strings "true" and "false" as indistinguishable strings. Parse treats these as booleans.
119127 * Unifies unhandleable complex search entries like undefined, null, objects and arrays as undefined.
128+ * Complex URL params must be handled separately.
120129 */
121130export function serializeSimpleSearchEntry ( [ key , value ] : [ string , unknown ] ) : [
122131 string ,
@@ -132,8 +141,7 @@ export function serializeSimpleSearchEntry([key, value]: [string, unknown]): [
132141}
133142
134143/**
135- * Parses output of @see serializeSimpleSearchEntry,
136- * once it has gone through URL decoding via new URLSearchParams(location.search)
144+ * Parses output of @see serializeSimpleSearchEntry.
137145 */
138146export function parseSimpleSearchEntry (
139147 searchParamValue : string
@@ -144,7 +152,7 @@ export function parseSimpleSearchEntry(
144152 if ( searchParamValue === 'false' ) {
145153 return false
146154 }
147- return searchParamValue
155+ return decodeURIComponent ( searchParamValue )
148156}
149157
150158export function encodeURIComponentPermissive (
0 commit comments