@builder.io/react 2.0.3-8 → 2.0.4-1
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/CHANGELOG.md +4 -0
- package/README.md +2 -2
- package/dist/builder-react-lite.cjs.js +1 -1
- package/dist/builder-react-lite.cjs.js.map +1 -1
- package/dist/builder-react-lite.esm.js +1 -1
- package/dist/builder-react-lite.esm.js.map +1 -1
- package/dist/builder-react.browser.js +10 -1
- package/dist/builder-react.browser.js.map +1 -1
- package/dist/builder-react.cjs.js +1 -1
- package/dist/builder-react.cjs.js.map +1 -1
- package/dist/builder-react.es5.js +1 -1
- package/dist/builder-react.es5.js.map +1 -1
- package/dist/builder-react.unpkg.js +10 -1
- package/dist/builder-react.unpkg.js.map +1 -1
- package/dist/lib/package.json +1 -1
- package/dist/lib/src/blocks/Embed.js.map +1 -1
- package/dist/lib/src/components/builder-block.component.js +2 -5
- package/dist/lib/src/components/builder-block.component.js.map +1 -1
- package/dist/lib/src/components/builder-blocks.component.js.map +1 -1
- package/dist/lib/src/components/builder-component.component.js +14 -67
- package/dist/lib/src/components/builder-component.component.js.map +1 -1
- package/dist/lib/src/components/builder-content.component.js +8 -6
- package/dist/lib/src/components/builder-content.component.js.map +1 -1
- package/dist/lib/src/constants/device-sizes.constant.js.map +1 -1
- package/dist/lib/src/functions/apply-patch-with-mutation.js +1 -1
- package/dist/lib/src/functions/apply-patch-with-mutation.js.map +1 -1
- package/dist/lib/src/functions/apply-patch-with-mutation.test.js +54 -0
- package/dist/lib/src/functions/apply-patch-with-mutation.test.js.map +1 -0
- package/dist/types/src/blocks/Mutation.d.ts +0 -1
- package/dist/types/src/blocks/Slot.d.ts +0 -1
- package/dist/types/src/blocks/raw/RawText.d.ts +0 -1
- package/dist/types/src/functions/apply-patch-with-mutation.d.ts +2 -2
- package/dist/types/src/functions/apply-patch-with-mutation.test.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/builder-block.component.tsx +2 -5
- package/src/components/builder-blocks.component.tsx +1 -1
- package/src/components/builder-component.component.tsx +0 -53
- package/src/components/builder-content.component.tsx +9 -6
- package/src/functions/apply-patch-with-mutation.test.ts +55 -0
- package/src/functions/apply-patch-with-mutation.ts +5 -5
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var apply_patch_with_mutation_1 = require("./apply-patch-with-mutation");
|
|
4
|
+
describe('applyPatchWithMinimalMutationChain', function () {
|
|
5
|
+
test('Basic shallow update', function () {
|
|
6
|
+
var obj = {
|
|
7
|
+
foo: 'bar',
|
|
8
|
+
};
|
|
9
|
+
var patch = {
|
|
10
|
+
op: 'replace',
|
|
11
|
+
path: '/foo',
|
|
12
|
+
value: '60px',
|
|
13
|
+
};
|
|
14
|
+
var applied = (0, apply_patch_with_mutation_1.applyPatchWithMinimalMutationChain)(obj, patch);
|
|
15
|
+
expect(applied.foo).toBe('60px');
|
|
16
|
+
expect(applied).not.toBe(obj);
|
|
17
|
+
});
|
|
18
|
+
test('Deep object updates', function () {
|
|
19
|
+
var obj = {
|
|
20
|
+
foo: {
|
|
21
|
+
bar: true,
|
|
22
|
+
},
|
|
23
|
+
baz: {},
|
|
24
|
+
};
|
|
25
|
+
var patch = {
|
|
26
|
+
op: 'replace',
|
|
27
|
+
path: '/foo/bar',
|
|
28
|
+
value: '60px',
|
|
29
|
+
};
|
|
30
|
+
var applied = (0, apply_patch_with_mutation_1.applyPatchWithMinimalMutationChain)(obj, patch);
|
|
31
|
+
expect(applied.foo.bar).toBe('60px');
|
|
32
|
+
expect(applied).not.toBe(obj);
|
|
33
|
+
expect(applied.foo).not.toBe(obj.foo);
|
|
34
|
+
expect(applied.baz).toBe(obj.baz);
|
|
35
|
+
});
|
|
36
|
+
test('Deep array updates', function () {
|
|
37
|
+
var obj = {
|
|
38
|
+
foo: [{ bar: true }],
|
|
39
|
+
baz: {},
|
|
40
|
+
};
|
|
41
|
+
var patch = {
|
|
42
|
+
op: 'replace',
|
|
43
|
+
path: '/foo/0/bar',
|
|
44
|
+
value: '60px',
|
|
45
|
+
};
|
|
46
|
+
var applied = (0, apply_patch_with_mutation_1.applyPatchWithMinimalMutationChain)(obj, patch);
|
|
47
|
+
expect(applied.foo[0].bar).toBe('60px');
|
|
48
|
+
expect(applied).not.toBe(obj);
|
|
49
|
+
expect(applied.foo).not.toBe(obj.foo);
|
|
50
|
+
expect(applied.foo[0]).not.toBe(obj.foo[0]);
|
|
51
|
+
expect(applied.baz).toBe(obj.baz);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=apply-patch-with-mutation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-patch-with-mutation.test.js","sourceRoot":"","sources":["../../../../src/functions/apply-patch-with-mutation.test.ts"],"names":[],"mappings":";;AAAA,yEAAiF;AAEjF,QAAQ,CAAC,oCAAoC,EAAE;IAC7C,IAAI,CAAC,sBAAsB,EAAE;QAC3B,IAAM,GAAG,GAAG;YACV,GAAG,EAAE,KAAK;SACX,CAAC;QACF,IAAM,KAAK,GAAG;YACZ,EAAE,EAAE,SAAS;YACb,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,MAAM;SACL,CAAC;QACX,IAAM,OAAO,GAAG,IAAA,8DAAkC,EAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qBAAqB,EAAE;QAC1B,IAAM,GAAG,GAAG;YACV,GAAG,EAAE;gBACH,GAAG,EAAE,IAAI;aACV;YACD,GAAG,EAAE,EAAE;SACR,CAAC;QACF,IAAM,KAAK,GAAG;YACZ,EAAE,EAAE,SAAS;YACb,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,MAAM;SACL,CAAC;QACX,IAAM,OAAO,GAAG,IAAA,8DAAkC,EAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oBAAoB,EAAE;QACzB,IAAM,GAAG,GAAG;YACV,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;YACpB,GAAG,EAAE,EAAE;SACR,CAAC;QACF,IAAM,KAAK,GAAG;YACZ,EAAE,EAAE,SAAS;YACb,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,MAAM;SACL,CAAC;QAEX,IAAM,OAAO,GAAG,IAAA,8DAAkC,EAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare const applyPatchWithMinimalMutationChain: (obj:
|
|
1
|
+
export declare const applyPatchWithMinimalMutationChain: <T extends object>(obj: T, patch: {
|
|
2
2
|
path: string;
|
|
3
3
|
op: 'add' | 'remove' | 'replace';
|
|
4
4
|
value: any;
|
|
5
|
-
}, preserveRoot?: boolean) =>
|
|
5
|
+
}, preserveRoot?: boolean) => T;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -19,7 +19,6 @@ const kebabCaseToCamelCase = (str = '') =>
|
|
|
19
19
|
str.replace(/-([a-z])/g, match => match[1].toUpperCase());
|
|
20
20
|
|
|
21
21
|
const Device = { desktop: 0, tablet: 1, mobile: 2 };
|
|
22
|
-
const blocksMap: Record<string, BuilderElement> = {};
|
|
23
22
|
|
|
24
23
|
const voidElements = new Set([
|
|
25
24
|
'area',
|
|
@@ -136,7 +135,7 @@ export class BuilderBlock extends React.Component<
|
|
|
136
135
|
}
|
|
137
136
|
|
|
138
137
|
get block() {
|
|
139
|
-
return
|
|
138
|
+
return this.props.block;
|
|
140
139
|
}
|
|
141
140
|
|
|
142
141
|
get emotionCss() {
|
|
@@ -251,15 +250,13 @@ export class BuilderBlock extends React.Component<
|
|
|
251
250
|
if (location.href.includes('builder.debug=true')) {
|
|
252
251
|
this.eval('debugger');
|
|
253
252
|
}
|
|
254
|
-
let newBlock = { ...this.block };
|
|
255
253
|
for (const patch of patches) {
|
|
256
254
|
// TODO: soehow mark this.block as a new object,
|
|
257
255
|
// e.g. access it's parent hm. maybe do the listning mutations
|
|
258
256
|
// on hte parent element not the child (or rather
|
|
259
257
|
// send the message to the parent)
|
|
260
|
-
applyPatchWithMinimalMutationChain(
|
|
258
|
+
applyPatchWithMinimalMutationChain(this.props.block, patch, true);
|
|
261
259
|
}
|
|
262
|
-
blocksMap[this.props.block.id!] = newBlock;
|
|
263
260
|
this.setState({ updates: this.state.updates + 1 });
|
|
264
261
|
|
|
265
262
|
break;
|
|
@@ -98,30 +98,6 @@ const sizeMap = {
|
|
|
98
98
|
mobile: 'small',
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
-
function decorator(fn: Function) {
|
|
102
|
-
return function argReceiver(...fnArgs: any[]) {
|
|
103
|
-
// Check if the decorator is being called without arguments (ex `@foo methodName() {}`)
|
|
104
|
-
if (fnArgs.length === 3) {
|
|
105
|
-
const [target, key, descriptor] = fnArgs;
|
|
106
|
-
if (descriptor && (descriptor.value || descriptor.get)) {
|
|
107
|
-
fnArgs = [];
|
|
108
|
-
return descriptorChecker(target, key, descriptor);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return descriptorChecker;
|
|
113
|
-
|
|
114
|
-
// descriptorChecker determines whether a method or getter is being decorated
|
|
115
|
-
// and replaces the appropriate key with the decorated function.
|
|
116
|
-
function descriptorChecker(target: any, key: any, descriptor: any) {
|
|
117
|
-
const descriptorKey = descriptor.value ? 'value' : 'get';
|
|
118
|
-
return {
|
|
119
|
-
...descriptor,
|
|
120
|
-
[descriptorKey]: fn(descriptor[descriptorKey], ...fnArgs),
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
101
|
|
|
126
102
|
const fetchCache: { [key: string]: any } = {};
|
|
127
103
|
|
|
@@ -1264,7 +1240,6 @@ export class BuilderComponent extends React.Component<
|
|
|
1264
1240
|
this.notifyStateChange();
|
|
1265
1241
|
}
|
|
1266
1242
|
|
|
1267
|
-
// Unsubscribe all? TODO: maybe don't continuous fire when editing.....
|
|
1268
1243
|
if (this.props.contentLoaded) {
|
|
1269
1244
|
this.props.contentLoaded(data, content);
|
|
1270
1245
|
}
|
|
@@ -1274,12 +1249,6 @@ export class BuilderComponent extends React.Component<
|
|
|
1274
1249
|
data.state = {};
|
|
1275
1250
|
}
|
|
1276
1251
|
|
|
1277
|
-
// Maybe...
|
|
1278
|
-
// if (data.context) {
|
|
1279
|
-
// Object.assign(this.state.context, data.context)
|
|
1280
|
-
// }
|
|
1281
|
-
// TODO: may not want this... or make sure anything overriden
|
|
1282
|
-
// explitily sets to null
|
|
1283
1252
|
data.inputs.forEach((input: any) => {
|
|
1284
1253
|
if (input) {
|
|
1285
1254
|
if (
|
|
@@ -1380,8 +1349,6 @@ export class BuilderComponent extends React.Component<
|
|
|
1380
1349
|
for (const key in data.httpRequests) {
|
|
1381
1350
|
const url: string | undefined = data.httpRequests[key];
|
|
1382
1351
|
if (url && (!this.data[key] || Builder.isEditing)) {
|
|
1383
|
-
// TODO: if Builder.isEditing and url patches https://builder.io/api/v2/content/{editingModel}
|
|
1384
|
-
// Then use this.builder.get().subscribe(...)
|
|
1385
1352
|
if (Builder.isBrowser) {
|
|
1386
1353
|
const finalUrl = this.evalExpression(url);
|
|
1387
1354
|
if (Builder.isEditing && this.lastHttpRequests[key] === finalUrl) {
|
|
@@ -1391,17 +1358,6 @@ export class BuilderComponent extends React.Component<
|
|
|
1391
1358
|
const builderModelRe = /builder\.io\/api\/v2\/([^\/\?]+)/i;
|
|
1392
1359
|
const builderModelMatch = url.match(builderModelRe);
|
|
1393
1360
|
const model = builderModelMatch && builderModelMatch[1];
|
|
1394
|
-
if (false && Builder.isEditing && model && this.builder.editingModel === model) {
|
|
1395
|
-
this.handleRequest(key, finalUrl);
|
|
1396
|
-
// TODO: fix this
|
|
1397
|
-
// this.subscriptions.add(
|
|
1398
|
-
// this.builder.get(model).subscribe(data => {
|
|
1399
|
-
// this.state.update((state: any) => {
|
|
1400
|
-
// state[key] = data
|
|
1401
|
-
// })
|
|
1402
|
-
// })
|
|
1403
|
-
// )
|
|
1404
|
-
} else {
|
|
1405
1361
|
this.handleRequest(key, finalUrl);
|
|
1406
1362
|
const currentSubscription = this.httpSubscriptionPerKey[key];
|
|
1407
1363
|
if (currentSubscription) {
|
|
@@ -1418,20 +1374,11 @@ export class BuilderComponent extends React.Component<
|
|
|
1418
1374
|
}
|
|
1419
1375
|
}));
|
|
1420
1376
|
this.subscriptions.add(newSubscription);
|
|
1421
|
-
}
|
|
1422
1377
|
} else {
|
|
1423
1378
|
this.handleRequest(key, this.evalExpression(url));
|
|
1424
1379
|
}
|
|
1425
1380
|
}
|
|
1426
1381
|
}
|
|
1427
|
-
|
|
1428
|
-
// @DEPRECATED
|
|
1429
|
-
// for (const key in data.builderData) {
|
|
1430
|
-
// const url = data.builderData[key]
|
|
1431
|
-
// if (url && !this.data[key]) {
|
|
1432
|
-
// this.handleBuilderRequest(key, this.evalExpression(url))
|
|
1433
|
-
// }
|
|
1434
|
-
// }
|
|
1435
1382
|
}
|
|
1436
1383
|
}
|
|
1437
1384
|
};
|
|
@@ -91,7 +91,11 @@ export class BuilderContent<ContentType extends object = any> extends React.Comp
|
|
|
91
91
|
if (!options.key && this.props.content?.id && !Builder.isEditing && !Builder.isPreviewing) {
|
|
92
92
|
options.key = this.props.content.id;
|
|
93
93
|
}
|
|
94
|
-
if (
|
|
94
|
+
if (
|
|
95
|
+
this.props.content &&
|
|
96
|
+
!options.initialContent?.length &&
|
|
97
|
+
(this.props.inline || !Builder.isPreviewing)
|
|
98
|
+
) {
|
|
95
99
|
options.initialContent = [this.props.content];
|
|
96
100
|
}
|
|
97
101
|
|
|
@@ -136,17 +140,17 @@ export class BuilderContent<ContentType extends object = any> extends React.Comp
|
|
|
136
140
|
if (location.href.includes('builder.debug=true')) {
|
|
137
141
|
eval('debugger');
|
|
138
142
|
}
|
|
143
|
+
let newData = this.state.data as any;
|
|
139
144
|
for (const patch of patches) {
|
|
140
|
-
applyPatchWithMinimalMutationChain(
|
|
145
|
+
newData = applyPatchWithMinimalMutationChain(newData, patch, false);
|
|
141
146
|
}
|
|
142
147
|
this.setState({
|
|
143
148
|
updates: this.state.updates + 1,
|
|
144
|
-
data:
|
|
149
|
+
data: newData,
|
|
145
150
|
});
|
|
146
151
|
if (this.props.contentLoaded) {
|
|
147
|
-
this.props.contentLoaded(
|
|
152
|
+
this.props.contentLoaded(newData.data, this.state.data);
|
|
148
153
|
}
|
|
149
|
-
|
|
150
154
|
break;
|
|
151
155
|
}
|
|
152
156
|
}
|
|
@@ -186,7 +190,6 @@ export class BuilderContent<ContentType extends object = any> extends React.Comp
|
|
|
186
190
|
|
|
187
191
|
subscribeToContent() {
|
|
188
192
|
if (this.name !== '_inline') {
|
|
189
|
-
console.log(' here fetching content with ', this.options);
|
|
190
193
|
// TODO:... using targeting...? express.request hmmm
|
|
191
194
|
this.subscriptions.add(
|
|
192
195
|
builder.queueGetContent(this.name, this.options).subscribe(
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { applyPatchWithMinimalMutationChain } from './apply-patch-with-mutation';
|
|
2
|
+
|
|
3
|
+
describe('applyPatchWithMinimalMutationChain', () => {
|
|
4
|
+
test('Basic shallow update', () => {
|
|
5
|
+
const obj = {
|
|
6
|
+
foo: 'bar',
|
|
7
|
+
};
|
|
8
|
+
const patch = {
|
|
9
|
+
op: 'replace',
|
|
10
|
+
path: '/foo',
|
|
11
|
+
value: '60px',
|
|
12
|
+
} as const;
|
|
13
|
+
const applied = applyPatchWithMinimalMutationChain(obj, patch);
|
|
14
|
+
expect(applied.foo).toBe('60px');
|
|
15
|
+
expect(applied).not.toBe(obj);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('Deep object updates', () => {
|
|
19
|
+
const obj = {
|
|
20
|
+
foo: {
|
|
21
|
+
bar: true,
|
|
22
|
+
},
|
|
23
|
+
baz: {},
|
|
24
|
+
};
|
|
25
|
+
const patch = {
|
|
26
|
+
op: 'replace',
|
|
27
|
+
path: '/foo/bar',
|
|
28
|
+
value: '60px',
|
|
29
|
+
} as const;
|
|
30
|
+
const applied = applyPatchWithMinimalMutationChain(obj, patch);
|
|
31
|
+
expect(applied.foo.bar).toBe('60px');
|
|
32
|
+
expect(applied).not.toBe(obj);
|
|
33
|
+
expect(applied.foo).not.toBe(obj.foo);
|
|
34
|
+
expect(applied.baz).toBe(obj.baz);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('Deep array updates', () => {
|
|
38
|
+
const obj = {
|
|
39
|
+
foo: [{ bar: true }],
|
|
40
|
+
baz: {},
|
|
41
|
+
};
|
|
42
|
+
const patch = {
|
|
43
|
+
op: 'replace',
|
|
44
|
+
path: '/foo/0/bar',
|
|
45
|
+
value: '60px',
|
|
46
|
+
} as const;
|
|
47
|
+
|
|
48
|
+
const applied = applyPatchWithMinimalMutationChain(obj, patch);
|
|
49
|
+
expect(applied.foo[0].bar).toBe('60px');
|
|
50
|
+
expect(applied).not.toBe(obj);
|
|
51
|
+
expect(applied.foo).not.toBe(obj.foo);
|
|
52
|
+
expect(applied.foo[0]).not.toBe(obj.foo[0]);
|
|
53
|
+
expect(applied.baz).toBe(obj.baz);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export const applyPatchWithMinimalMutationChain = (
|
|
2
|
-
obj:
|
|
1
|
+
export const applyPatchWithMinimalMutationChain = <T extends object>(
|
|
2
|
+
obj: T,
|
|
3
3
|
patch: { path: string; op: 'add' | 'remove' | 'replace'; value: any },
|
|
4
|
-
preserveRoot =
|
|
5
|
-
) => {
|
|
4
|
+
preserveRoot = false
|
|
5
|
+
): T => {
|
|
6
6
|
if (Object(obj) !== obj) {
|
|
7
7
|
return obj;
|
|
8
8
|
}
|
|
@@ -13,7 +13,7 @@ export const applyPatchWithMinimalMutationChain = (
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const newObj = preserveRoot ? obj : { ...obj };
|
|
16
|
-
let objPart = newObj;
|
|
16
|
+
let objPart = newObj as any;
|
|
17
17
|
for (let i = 0; i < pathArr.length; i++) {
|
|
18
18
|
const isLast = i === pathArr.length - 1;
|
|
19
19
|
const property = pathArr[i];
|