Merge theme deeply

This commit is contained in:
Roman Hotsiy 2017-11-22 14:00:42 +02:00
parent 0bd8c66090
commit ed13bb0528
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
3 changed files with 56 additions and 3 deletions

View File

@ -1,5 +1,5 @@
import { ThemeInterface } from '../theme';
import { isNumeric } from '../utils/helpers';
import { isNumeric, mergeObjects } from '../utils/helpers';
import defaultTheme from '../theme';
export interface RedocRawOptions {
@ -33,7 +33,7 @@ export class RedocNormalizedOptions {
untrustedSpec: boolean;
constructor(raw: RedocRawOptions) {
this.theme = { ...(raw.theme || {}), ...defaultTheme }; // todo: merge deep
this.theme = mergeObjects({} as any, raw.theme || {}, defaultTheme);
this.scrollYOffset = RedocNormalizedOptions.normalizeScrollYOffset(raw.scrollYOffset);
this.hideHostname = RedocNormalizedOptions.normalizeHideHostname(raw.hideHostname);
this.expandResponses = RedocNormalizedOptions.normalizeExpandResponses(raw.expandResponses);

View File

@ -1,4 +1,4 @@
import { mapWithLast, appendToMdHeading } from '../helpers';
import { mapWithLast, appendToMdHeading, mergeObjects } from '../helpers';
describe('Utils', () => {
describe('helpers', () => {
@ -38,5 +38,24 @@ describe('Utils', () => {
const val = appendToMdHeading('', 'Authentication', '<test>');
expect(val).toEqual('# Authentication\n\n<test>');
});
describe('mergeObjects', () => {
test('should merge Objects and all nested Ones', () => {
const obj1 = { a: { a1: 'A1' }, c: 'C', d: {} };
const obj2 = { a: { a2: 'A2' }, b: { b1: 'B1' }, d: null };
const obj3 = { a: { a1: 'A1', a2: 'A2' }, b: { b1: 'B1' }, c: 'C', d: null };
expect(mergeObjects({}, obj1, obj2)).toEqual(obj3);
});
test('should behave like Object.assign on the top level', () => {
const obj1 = { a: { a1: 'A1' }, c: 'C' };
const obj2 = { a: undefined, b: { b1: 'B1' } };
expect(mergeObjects({}, obj1, obj2)).toEqual(Object.assign({}, obj1, obj2));
});
test('should not merge array values, just override', () => {
const obj1 = { a: ['A', 'B'] };
const obj2 = { a: ['C'], b: ['D'] };
expect(mergeObjects({}, obj1, obj2)).toEqual({ a: ['C'], b: ['D'] });
});
});
});
});

View File

@ -80,3 +80,37 @@ export function appendToMdHeading(md: string, heading: string, content: string)
return `${md}${br}# ${heading}\n\n${content}`;
}
}
// credits https://stackoverflow.com/a/46973278/1749888
export const mergeObjects = <T extends object = object>(target: T, ...sources: T[]): T => {
if (!sources.length) {
return target;
}
const source = sources.shift();
if (source === undefined) {
return target;
}
if (isMergebleObject(target) && isMergebleObject(source)) {
Object.keys(source).forEach(function(key: string) {
if (isMergebleObject(source[key])) {
if (!target[key]) {
target[key] = {};
}
mergeObjects(target[key], source[key]);
} else {
target[key] = source[key];
}
});
}
return mergeObjects(target, ...sources);
};
const isObject = (item: any): boolean => {
return item !== null && typeof item === 'object';
};
const isMergebleObject = (item): boolean => {
return isObject(item) && !Array.isArray(item);
};