Skip to content

Commit 0d78fe6

Browse files
committed
add support for isArrayInsertion
1 parent 54d7cfd commit 0d78fe6

File tree

3 files changed

+59
-17
lines changed

3 files changed

+59
-17
lines changed

src/impl/edit.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function removeProperty(text: string, path: JSONPath, formattingOptions:
1212
return setProperty(text, path, void 0, formattingOptions);
1313
}
1414

15-
export function setProperty(text: string, originalPath: JSONPath, value: any, formattingOptions: FormattingOptions, getInsertionIndex?: (properties: string[]) => number): Edit[] {
15+
export function setProperty(text: string, originalPath: JSONPath, value: any, formattingOptions: FormattingOptions, getInsertionIndex?: (properties: string[]) => number, isArrayInsertion: boolean = false): Edit[] {
1616
let path = originalPath.slice()
1717
let errors: ParseError[] = [];
1818
let root = parseTree(text, errors);
@@ -114,13 +114,25 @@ export function setProperty(text: string, originalPath: JSONPath, value: any, fo
114114
edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: '' };
115115
}
116116
return withFormatting(text, edit, formattingOptions);
117-
} else if (value !== void 0 && parent.children.length > lastSegment) {
118-
let modifyIndex = lastSegment;
119-
let toModify = parent.children[modifyIndex];
120-
let newProperty = `${JSON.stringify(value)}`;
121-
return withFormatting(text, { offset: toModify.offset, length: toModify.length, content: newProperty }, formattingOptions);
117+
} else if (value !== void 0) {
118+
let edit: Edit;
119+
const newProperty = `${JSON.stringify(value)}`;
120+
121+
if (!isArrayInsertion && parent.children.length > lastSegment) {
122+
let toModify = parent.children[lastSegment];
123+
124+
edit = { offset: toModify.offset, length: toModify.length, content: newProperty }
125+
} else if (parent.children.length === 0 || lastSegment === 0) {
126+
edit = { offset: parent.offset + 1, length: 0, content: parent.children.length === 0 ? newProperty : newProperty + ',' };
127+
} else {
128+
const index = lastSegment > parent.children.length ? parent.children.length : lastSegment;
129+
const previous = parent.children[index - 1];
130+
edit = { offset: previous.offset + previous.length, length: 0, content: ',' + newProperty };
131+
}
132+
133+
return withFormatting(text, edit, formattingOptions);
122134
} else {
123-
throw new Error(`Can not ${value === void 0 ? 'remove' : 'modify'} Array index ${insertIndex} as length is not sufficient`);
135+
throw new Error(`Can not ${value === void 0 ? 'remove' : (isArrayInsertion ? 'insert' : 'modify')} Array index ${insertIndex} as length is not sufficient`);
124136
}
125137
} else {
126138
throw new Error(`Can not add ${typeof lastSegment !== 'number' ? 'index' : 'property'} to parent of type ${parent.type}`);

src/main.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,11 @@ export interface ModificationOptions {
353353
* Formatting options
354354
*/
355355
formattingOptions: FormattingOptions;
356+
/**
357+
* Default false. If `JSONPath` refers to an index of an array and {@property isArrayInsertion} is `true`, then
358+
* {@function modify} will insert a new item at that location instead of overwriting its contents.
359+
*/
360+
isArrayInsertion?: boolean;
356361
/**
357362
* Optional function to define the insertion index given an existing list of properties.
358363
*/
@@ -375,7 +380,7 @@ export interface ModificationOptions {
375380
* To apply edits to an input, you can use `applyEdits`.
376381
*/
377382
export function modify(text: string, path: JSONPath, value: any, options: ModificationOptions): Edit[] {
378-
return edit.setProperty(text, path, value, options.formattingOptions, options.getInsertionIndex);
383+
return edit.setProperty(text, path, value, options.formattingOptions, options.getInsertionIndex, options.isArrayInsertion);
379384
}
380385

381386
/**

src/test/edit.test.ts

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,22 +133,47 @@ suite('JSON - edits', () => {
133133
edits = setProperty(content, ['x', 2], 4, formatterOptions);
134134
assertEdit(content, edits, '{\n "x": [1, 2, 4],\n "y": 0\n}');
135135

136-
let message = "allowed setProperty to set array item outside of bounds";
137-
try {
138-
setProperty(content, ['x', 3], 3, formatterOptions)
139-
throw new Error(message);
140-
} catch(e) {
141-
assert(e && e.message !== message);
142-
}
136+
edits = setProperty(content, ['x', 3], 3, formatterOptions)
137+
assertEdit(content, edits, '{\n "x": [\n 1,\n 2,\n 3,\n 3\n ],\n "y": 0\n}');
138+
});
139+
140+
test('insert item at 0; isArrayInsertion = true', () => {
141+
let content = '[\n 2,\n 3\n]';
142+
let edits = setProperty(content, [0], 1, formatterOptions, undefined, true);
143+
assertEdit(content, edits, '[\n 1,\n 2,\n 3\n]');
144+
});
145+
146+
test('insert item at 0 in empty array', () => {
147+
let content = '[\n]';
148+
let edits = setProperty(content, [0], 1, formatterOptions);
149+
assertEdit(content, edits, '[\n 1\n]');
150+
});
151+
152+
test('insert item at an index; isArrayInsertion = true', () => {
153+
let content = '[\n 1,\n 3\n]';
154+
let edits = setProperty(content, [1], 2, formatterOptions, undefined, true);
155+
assertEdit(content, edits, '[\n 1,\n 2,\n 3\n]');
156+
});
157+
158+
test('insert item at an index in empty array', () => {
159+
let content = '[\n]';
160+
let edits = setProperty(content, [1], 1, formatterOptions);
161+
assertEdit(content, edits, '[\n 1\n]');
162+
});
163+
164+
test('insert item at end index', () => {
165+
let content = '[\n 1,\n 2\n]';
166+
let edits = setProperty(content, [2], 3, formatterOptions);
167+
assertEdit(content, edits, '[\n 1,\n 2,\n 3\n]');
143168
});
144169

145-
test('insert item to empty array', () => {
170+
test('insert item at end to empty array', () => {
146171
let content = '[\n]';
147172
let edits = setProperty(content, [-1], 'bar', formatterOptions);
148173
assertEdit(content, edits, '[\n "bar"\n]');
149174
});
150175

151-
test('insert item', () => {
176+
test('insert item at end', () => {
152177
let content = '[\n 1,\n 2\n]';
153178
let edits = setProperty(content, [-1], 'bar', formatterOptions);
154179
assertEdit(content, edits, '[\n 1,\n 2,\n "bar"\n]');

0 commit comments

Comments
 (0)