Commit 85c377d1 authored by David Sveningsson's avatar David Sveningsson

fix(meta): deep merge during inheritance

fixes #72
parent 8833a0fc
Pipeline #129007657 passed with stages
in 9 minutes and 35 seconds
......@@ -452,6 +452,64 @@ describe("MetaTable", () => {
);
});
it("should merge objects", () => {
expect.assertions(2);
const table = new MetaTable();
table.loadFromObject({
foo: {
attributes: {
a: ["1"],
b: ["1"],
c: ["1"],
},
},
bar: {
inherit: "foo",
attributes: {
b: ["2"],
c: null,
},
},
});
table.loadFromObject({
foo: {
attributes: {
a: ["2"],
b: null,
},
},
});
const foo = table.getMetaFor("foo");
const bar = table.getMetaFor("bar");
expect(foo).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"a": Array [
"2",
],
"c": Array [
"1",
],
},
"tagName": "foo",
}
`);
expect(bar).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"a": Array [
"1",
],
"b": Array [
"2",
],
},
"inherit": "foo",
"tagName": "bar",
}
`);
});
it("should throw error when extending missing element", () => {
expect.assertions(1);
const table = new MetaTable();
......
......@@ -37,6 +37,10 @@ function clone(src: any): any {
return JSON.parse(JSON.stringify(src));
}
function overwriteMerge<T>(a: T[], b: T[]): T[] {
return b;
}
/**
* AJV keyword "regexp" to validate the type to be a regular expression.
* Injects errors with the "type" keyword to give the same output.
......@@ -177,7 +181,6 @@ export class MetaTable {
}
private addEntry(tagName: string, entry: MetaData): void {
const defaultEntry = {};
let parent = this.elements[tagName] || {};
/* handle inheritance */
......@@ -192,9 +195,11 @@ export class MetaTable {
}
/* merge all sources together */
const expanded: MetaElement = Object.assign(defaultEntry, parent, entry, {
tagName,
}) as MetaElement;
const expanded: MetaElement = deepmerge(
parent,
{ ...entry, tagName },
{ arrayMerge: overwriteMerge }
);
expandRegex(expanded);
this.elements[tagName] = expanded;
......@@ -267,7 +272,11 @@ function expandRegexValue(value: string | RegExp): string | RegExp {
function expandRegex(entry: MetaElement): void {
if (!entry.attributes) return;
for (const [name, values] of Object.entries(entry.attributes)) {
entry.attributes[name] = values.map(expandRegexValue);
if (values) {
entry.attributes[name] = values.map(expandRegexValue);
} else {
delete entry.attributes[name];
}
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment