Skip to content

Commit 2fb6596

Browse files
authored
fix(query): decode unicode params (#1871)
1 parent 5ae5480 commit 2fb6596

File tree

4 files changed

+30
-21
lines changed

4 files changed

+30
-21
lines changed

src/runtime/utils/json.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,7 @@ export function jsonStringify (value: any) {
1111
* This function is equivalent to `JSON.parse`, but it also handles RegExp objects.
1212
*/
1313
export function jsonParse (value: string) {
14-
return JSON.parse(value, (key, value) => {
15-
const withOperator = (typeof value === 'string' && value.match(/^--([A-Z]+) (.+)$/)) || []
16-
17-
// Transforms RegExp string representation back to RegExp objects.
18-
if (withOperator[1] === 'REGEX') {
19-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#advanced_searching_with_flags
20-
const regex = withOperator[2].match(/\/(.*)\/([dgimsuy]*)$/)
21-
return regex ? new RegExp(regex[1], regex[2] || '') : value
22-
}
23-
24-
// Decode URI encoded path
25-
if (key === '_path') {
26-
return decodeURI(value)
27-
}
28-
29-
return value
30-
})
14+
return JSON.parse(value, regExpReviver)
3115
}
3216

3317
/**
@@ -39,3 +23,18 @@ function regExpReplacer (_key: string, value: any) {
3923
}
4024
return value
4125
}
26+
27+
/**
28+
* A function that transforms RegExp string representation back to RegExp objects.
29+
*/
30+
function regExpReviver (_key: string, value: any) {
31+
const withOperator = (typeof value === 'string' && value.match(/^--([A-Z]+) (.+)$/)) || []
32+
33+
if (withOperator[1] === 'REGEX') {
34+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#advanced_searching_with_flags
35+
const regex = withOperator[2].match(/\/(.*)\/([dgimsuy]*)$/)
36+
return regex ? new RegExp(regex[1], regex[2] || '') : value
37+
}
38+
39+
return value
40+
}

src/runtime/utils/query.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export const getContentQuery = (event: H3Event): QueryBuilderParams => {
4444

4545
// Using /api/_content/query/:qid?_params=....
4646
if (qid && query._params) {
47-
memory[qid] = parseJSONQueryParams(query._params)
47+
memory[qid] = parseJSONQueryParams(decodeURIComponent(query._params))
4848

4949
if (memory[qid].where && !Array.isArray(memory[qid].where)) {
5050
memory[qid].where = [memory[qid].where as any as QueryBuilderWhere]
@@ -58,7 +58,7 @@ export const getContentQuery = (event: H3Event): QueryBuilderParams => {
5858

5959
// Using /api/_content/query?_params={{JSON_FORMAT}}
6060
if (query._params) {
61-
return parseJSONQueryParams(query._params)
61+
return parseJSONQueryParams(decodeURIComponent(query._params))
6262
}
6363

6464
// Using /api/_content/query?path=...&only=...

test/basic.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('Basic usage', async () => {
3333
})
3434

3535
test('Japanese path', async () => {
36-
const html = await $fetch('/こんにちは')
36+
const html = await $fetch('/' + encodeURIComponent('こんにちは'))
3737
expect(html).contains('🎨 こんにちは')
3838
})
3939

test/features/content-query.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const testContentQuery = () => {
2121
params: { _params: JSON.stringify(params) }
2222
})
2323

24-
const ids = docs.map(doc => doc._id)
24+
const ids = docs.map((doc: any) => doc._id)
2525

2626
assert(ids.length > 0)
2727
assert(ids.includes('content:index.md'))
@@ -61,6 +61,16 @@ export const testContentQuery = () => {
6161
expect(content).includes('$$$$')
6262
})
6363

64+
test('find `_path` and explude `index`', async () => {
65+
const content = await $fetch('/features/query-content?prefix=&path=/cats&where={"_path":{"$ne":"/cats"}}')
66+
67+
expect(content).not.includes('cats:index.md')
68+
expect(content).includes('cats:_dir.yml')
69+
expect(content).includes('cats:bombay.md')
70+
expect(content).includes('cats:persian.md')
71+
expect(content).includes('cats:ragdoll.md')
72+
})
73+
6474
// test `queryContent( PREFIX ).findOne()`
6575
test('exact match foo/bar found', async () => {
6676
const content = await $fetch('/features/query-content?path=/prefix/foo/bar&findOne=1')

0 commit comments

Comments
 (0)