Skip to content

Commit c09162d

Browse files
(feat) improve property matching suggestion for array of object
1 parent ecba2d7 commit c09162d

File tree

2 files changed

+131
-69
lines changed

2 files changed

+131
-69
lines changed

src/components/suggestionBuilder.js

Lines changed: 130 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,83 @@ export const suggestions = [
1515
{
1616
'description': 'access a specific property',
1717
'value': '.',
18+
'setCarretAt': 1,
1819
'scopes': ['array', 'object']
1920
},
2021
{
2122
'description': 'search recursively for a property',
2223
'value': '..',
24+
'setCarretAt': 2,
2325
'scopes': ['array', 'object']
2426
},
27+
{
28+
'description': 'filter a collection',
29+
'value': '?()',
30+
'setCarretAt': 2,
31+
'scopes': ['[]']
32+
},
33+
{
34+
'description': 'filter a collection - by one of it`s item value',
35+
'value': '@.',
36+
'setCarretAt': 2,
37+
'scopes': ['?()', '===']
38+
},
39+
{
40+
'value': ' ',
41+
'setCarretAt': 1,
42+
'scopes': []
43+
},
44+
{
45+
'description': 'equals',
46+
'value': '===',
47+
'scopes': [' ']
48+
},
49+
{
50+
'description': 'lesser',
51+
'value': '<',
52+
'scopes': [' ']
53+
},
54+
{
55+
'description': 'lesser or equals',
56+
'value': '<=',
57+
'scopes': [' ']
58+
},
59+
{
60+
'description': 'greater',
61+
'value': '>',
62+
'scopes': [' ']
63+
},
64+
{
65+
'description': 'greater or equals',
66+
'value': '>=',
67+
'scopes': [' ']
68+
},
69+
{
70+
'description': 'and',
71+
'value': '&&',
72+
'scopes': [' ']
73+
},
74+
{
75+
'description': 'or',
76+
'value': '||',
77+
'scopes': [' ']
78+
},
2579
{
2680
'value': 'all_properties',
2781
'scopes': ['.']
2882
},
2983
{
30-
'value': 'all_properties_recursively',
31-
'scopes': ['..']
84+
'value': 'all_properties_of_parent_array',
85+
'scopes': ['@.']
3286
},
3387
{
34-
'description': 'filter a collection',
35-
'value': '?(@)',
36-
'setCarretAt': 3,
37-
'scopes': ['[]']
88+
'value': 'all_properties_recursively',
89+
'scopes': ['..']
3890
},
3991
{
4092
'description': 'select an item by it\'s index relatively to the size of the collection',
4193
'value': '(@.length-1)',
42-
'setCarretAt': 10,
94+
'setCarretAt': 12,
4395
'scopes': ['[]']
4496
},
4597
{
@@ -67,6 +119,9 @@ export const suggestions = [
67119

68120
export const getSuggestions = (jsonPath, caretPosition, jsonToTestAgainst) => {
69121
try {
122+
if (caretPosition !== jsonPath.length) {
123+
throw new Error('Force to eval options according to carret positions');
124+
}
70125
const filteredJson = jp.query(jsonToTestAgainst, jsonPath)[0];
71126
if (Array.isArray(filteredJson)) {
72127
return suggestions.filter(s => s.scopes.includes('array'));
@@ -83,38 +138,62 @@ export const getSuggestions = (jsonPath, caretPosition, jsonToTestAgainst) => {
83138
return [...additionalSuggestions.filter(s => s.value.includes(filterSuggestionJsonPath) && s.value !== filterSuggestionJsonPath), ...suggestions.filter(s => s.scopes.includes('object'))];
84139
}
85140
} catch (e) {
86-
const appliableScopes = suggestions.filter(s => jsonPath.endsWith(s.value));
141+
const appliableScopes = suggestions.filter(s => {
142+
if (typeof s.setCarretAt !== undefined) {
143+
const valueToBeBeforeCarret = s.value.substring(0, s.setCarretAt);
144+
const valueToBeAfterCarret = s.value.substring(s.setCarretAt);
145+
const jsonPathPartBeforeCarret = jsonPath.substring(0, caretPosition);
146+
const jsonPathPartAfterCarret = jsonPath.substring(caretPosition);
147+
148+
return jsonPathPartBeforeCarret.endsWith(valueToBeBeforeCarret) && jsonPathPartAfterCarret.startsWith(valueToBeAfterCarret);
149+
}
150+
151+
return jsonPath.endsWith(s.value);
152+
});
87153
return guessSuggestionsFromScopes(appliableScopes, caretPosition, jsonPath, jsonToTestAgainst);
88154
}
89155
};
90156

91157
const guessSuggestionsFromScopes = (scopes, carretPosition, jsonPath, jsonToTestAgainst) => {
92-
if (scopes.length > 0) {
158+
if (!scopes || scopes.length === 0) {
159+
return [];
160+
}
161+
162+
return flatten(scopes.map(appliableScope => {
93163
// Check if there is any conditions on carret position for appliableScope
94-
const appliableScope = scopes[scopes.length - 1];
95164
if (appliableScope.setCarretAt) {
96165
if (jsonPath.length - carretPosition === appliableScope.setCarretAt) {
97-
return suggestions.filter(s => s.scopes.includes(appliableScope.value));
166+
return flatten(evalAllProperties(
167+
suggestions.filter(s => s.scopes.includes(appliableScope.value)),
168+
carretPosition,
169+
jsonPath,
170+
jsonToTestAgainst
171+
)) || [];
98172
} else {
99-
return [];
173+
return flatten(evalAllProperties(
174+
suggestions.filter(s => s.scopes.includes(appliableScope.value)),
175+
carretPosition,
176+
jsonPath,
177+
jsonToTestAgainst
178+
)) || [];
100179
}
101180
} else {
102181
return flatten(evalAllProperties(
103182
suggestions.filter(s => s.scopes.includes(appliableScope.value)),
183+
carretPosition,
104184
jsonPath,
105185
jsonToTestAgainst
106186
));
107187
}
108-
} else {
109-
return [];
110-
}
188+
}));
111189
};
112190

113191
const flatten = (arr) => {
114192
return [].concat(...arr);
115193
};
116194

117-
export const evalAllProperties = (suggestions, jsonPath, jsonToTestAgainst) => {
195+
export const evalAllProperties = (suggestions, carretPosition, jsonPath, jsonToTestAgainst) => {
196+
//console.log({suggestions, carretPosition, jsonPath, jsonToTestAgainst})
118197
return suggestions.map(s => {
119198
if (s.value === 'all_properties') {
120199
const jsonPathToObject = jsonPath.substring(0, jsonPath.length - 1);
@@ -149,6 +228,28 @@ export const evalAllProperties = (suggestions, jsonPath, jsonToTestAgainst) => {
149228
// ignore error
150229
return [];
151230
}
231+
} else if (s.value === 'all_properties_of_parent_array') {
232+
//"$.d[1].df.f[?(@.t === 'tf' && @.{cursorHere}truc === 'd' && @.defined)]"
233+
// 1. split at cursor, take first part
234+
//"$.d[1].df.f[?(@.t === 'tf' && @."
235+
const splittedJsonPathAtCursor = jsonPath.substring(0, carretPosition);
236+
// 2. Search for last "[" index, then split at this index, take first part
237+
//"$.d[1].df.f"
238+
const lastIndexOfOpennedArray = splittedJsonPathAtCursor.lastIndexOf('[');
239+
const jsonPathToParentArray = splittedJsonPathAtCursor.substring(0, lastIndexOfOpennedArray);
240+
// 3. We then want to evaluate all unique properties in f array at first level
241+
try {
242+
const filteredJson = jp.query(jsonToTestAgainst, jsonPathToParentArray)[0];
243+
const properties = Array.from(new Set(getAllPropertiesAtFirstLevel(filteredJson)));
244+
return properties.map(p => ({
245+
value: p + ' ',
246+
setCarretAt: p.length-1,
247+
description: 'property',
248+
scopes: ['object']
249+
}));
250+
} catch(e) {
251+
return [];
252+
}
152253
} else {
153254
return s;
154255
}
@@ -169,4 +270,17 @@ const getAllPropertiesRecursively = (objectOrArray) => {
169270
} else {
170271
return null;
171272
}
273+
};
274+
275+
const getAllPropertiesAtFirstLevel = (objectOrArray) => {
276+
if (Array.isArray(objectOrArray)) {
277+
return flatten(objectOrArray.map(arrayEntry => {
278+
return getAllPropertiesAtFirstLevel(arrayEntry);
279+
})).filter(p => p !== null && typeof p !== 'undefined');
280+
} else if (typeof objectOrArray === 'object') {
281+
const keys = Object.keys(objectOrArray);
282+
return flatten(keys).filter(p => p !== null && typeof p !== 'undefined');
283+
} else {
284+
return null;
285+
}
172286
};

yarn.lock

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -808,10 +808,6 @@
808808
escape-string-regexp "^1.0.5"
809809
lodash.deburr "^4.1.0"
810810

811-
"@sphinxxxx/color-conversion@^2.1.1":
812-
version "2.1.1"
813-
resolved "https://registry.yarnpkg.com/@sphinxxxx/color-conversion/-/color-conversion-2.1.1.tgz#da281a9641eb3f699979432fe531bba520e3ffbb"
814-
815811
"@svgr/core@^2.2.0":
816812
version "2.2.0"
817813
resolved "https://registry.yarnpkg.com/@svgr/core/-/core-2.2.0.tgz#59219d92b4c372bb925c4ad3ebc66ccd04e9d5c3"
@@ -1123,7 +1119,7 @@ ajv-keywords@^3.0.0, ajv-keywords@^3.1.0:
11231119
version "3.2.0"
11241120
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a"
11251121

1126-
ajv@5.5.2, ajv@^5.0.0, ajv@^5.1.0, ajv@^5.1.5, ajv@^5.3.0:
1122+
ajv@^5.0.0, ajv@^5.1.0, ajv@^5.1.5, ajv@^5.3.0:
11271123
version "5.5.2"
11281124
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
11291125
dependencies:
@@ -2516,10 +2512,6 @@ brace-expansion@^1.0.0, brace-expansion@^1.1.7:
25162512
balanced-match "^1.0.0"
25172513
concat-map "0.0.1"
25182514

2519-
brace@0.11.1:
2520-
version "0.11.1"
2521-
resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58"
2522-
25232515
braces@^0.1.2:
25242516
version "0.1.5"
25252517
resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6"
@@ -4520,10 +4512,6 @@ double-ended-queue@^2.1.0-0:
45204512
version "2.1.0-0"
45214513
resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
45224514

4523-
drag-tracker@^1.0.0:
4524-
version "1.0.0"
4525-
resolved "https://registry.yarnpkg.com/drag-tracker/-/drag-tracker-1.0.0.tgz#9bd33d380bc3056db69bd5b3cf6e062fec58bd64"
4526-
45274515
duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2:
45284516
version "0.1.4"
45294517
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
@@ -7104,10 +7092,6 @@ istanbul@^0.4.0:
71047092
which "^1.1.1"
71057093
wordwrap "^1.0.0"
71067094

7107-
javascript-natural-sort@0.7.1:
7108-
version "0.7.1"
7109-
resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
7110-
71117095
javascript-stringify@^1.6.0:
71127096
version "1.6.0"
71137097
resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-1.6.0.tgz#142d111f3a6e3dae8f4a9afd77d45855b5a9cce3"
@@ -7132,10 +7116,6 @@ jison@0.4.13:
71327116
lex-parser "~0.1.3"
71337117
nomnom "1.5.2"
71347118

7135-
jmespath@0.15.0:
7136-
version "0.15.0"
7137-
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
7138-
71397119
js-base64@^2.1.8, js-base64@^2.1.9:
71407120
version "2.4.9"
71417121
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.9.tgz#748911fb04f48a60c4771b375cac45a80df11c03"
@@ -7249,10 +7229,6 @@ json-schema@0.2.3:
72497229
version "0.2.3"
72507230
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
72517231

7252-
json-source-map@0.4.0:
7253-
version "0.4.0"
7254-
resolved "https://registry.yarnpkg.com/json-source-map/-/json-source-map-0.4.0.tgz#eea837fe3ce2f2bfd5b13687779406354423c355"
7255-
72567232
json-stable-stringify-without-jsonify@^1.0.1:
72577233
version "1.0.1"
72587234
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
@@ -7275,19 +7251,6 @@ json5@^0.5.0, json5@^0.5.1:
72757251
version "0.5.1"
72767252
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
72777253

7278-
jsoneditor@^5.16.0:
7279-
version "5.24.5"
7280-
resolved "https://registry.yarnpkg.com/jsoneditor/-/jsoneditor-5.24.5.tgz#de8bd89349345b3d43c3fa421edab5ee211ba721"
7281-
dependencies:
7282-
ajv "5.5.2"
7283-
brace "0.11.1"
7284-
javascript-natural-sort "0.7.1"
7285-
jmespath "0.15.0"
7286-
json-source-map "0.4.0"
7287-
mobius1-selectr "2.4.2"
7288-
picomodal "3.0.0"
7289-
vanilla-picker "2.4.2"
7290-
72917254
jsonfile@^2.1.0:
72927255
version "2.4.0"
72937256
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
@@ -8289,10 +8252,6 @@ mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdi
82898252
dependencies:
82908253
minimist "0.0.8"
82918254

8292-
mobius1-selectr@2.4.2:
8293-
version "2.4.2"
8294-
resolved "https://registry.yarnpkg.com/mobius1-selectr/-/mobius1-selectr-2.4.2.tgz#b8a619c8a0ed6234590e5e5a9e979e15d9b4b89a"
8295-
82968255
mocha@4.1.0:
82978256
version "4.1.0"
82988257
resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794"
@@ -9359,10 +9318,6 @@ phantomjs-prebuilt@2.1.16, phantomjs-prebuilt@^2.1.7:
93599318
request-progress "^2.0.1"
93609319
which "^1.2.10"
93619320

9362-
picomodal@3.0.0:
9363-
version "3.0.0"
9364-
resolved "https://registry.yarnpkg.com/picomodal/-/picomodal-3.0.0.tgz#facd30f4fbf34a809c1e04ea525f004f399c0b82"
9365-
93669321
pify@^2.0.0:
93679322
version "2.3.0"
93689323
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@@ -12835,13 +12790,6 @@ value-equal@^0.4.0:
1283512790
version "0.4.0"
1283612791
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7"
1283712792

12838-
vanilla-picker@2.4.2:
12839-
version "2.4.2"
12840-
resolved "https://registry.yarnpkg.com/vanilla-picker/-/vanilla-picker-2.4.2.tgz#830f1d23934c5eb25fc7b1d667aa8c21260f041c"
12841-
dependencies:
12842-
"@sphinxxxx/color-conversion" "^2.1.1"
12843-
drag-tracker "^1.0.0"
12844-
1284512793
vary@^1.1.2, vary@~1.1.2:
1284612794
version "1.1.2"
1284712795
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"

0 commit comments

Comments
 (0)