UNPKG

ngx-object-diff

Version:

An Angular 2+ library to compare and show object differences.

464 lines (457 loc) 14.4 kB
import { SecurityContext, Injectable, ɵɵdefineInjectable, ɵɵinject, Component, Input, NgModule } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; /** * @fileoverview added by tsickle * Generated from: lib/ngx-object-diff.service.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class NgxObjectDiffService { /** * @param {?} sanitizer */ constructor(sanitizer) { this.sanitizer = sanitizer; this.openChar = '{'; this.closeChar = '}'; } /* service methods */ /** * @param {?} char * @return {?} */ setOpenChar(char) { this.openChar = char; } /** * @param {?} char * @return {?} */ setCloseChar(char) { this.closeChar = char; } /** * diff between object a and b * @param {?} a * @param {?} b * @param {?=} shallow * @param {?=} isOwn * @return {?} */ diff(a, b, shallow, isOwn) { if (a === b) { return this.equalObj(a); } /** @type {?} */ let diffValue = {}; /** @type {?} */ let equal = true; for (let key in a) { if ((!isOwn && key in b) || (isOwn && typeof b != 'undefined' && b.hasOwnProperty(key))) { if (a[key] === b[key]) { diffValue[key] = this.equalObj(a[key]); } else { if (!shallow && this.isValidAttr(a[key], b[key])) { /** @type {?} */ let valueDiff = this.diff(a[key], b[key], shallow, isOwn); if (valueDiff.changed == 'equal') { diffValue[key] = this.equalObj(a[key]); } else { equal = false; diffValue[key] = valueDiff; } } else { equal = false; diffValue[key] = { changed: 'primitive change', removed: a[key], added: b[key] }; } } } else { equal = false; diffValue[key] = { changed: 'removed', value: a[key] }; } } for (let key in b) { if ((!isOwn && !(key in a)) || (isOwn && typeof a != 'undefined' && !a.hasOwnProperty(key))) { equal = false; diffValue[key] = { changed: 'added', value: b[key] }; } } if (equal) { return this.equalObj(a); } else { return { changed: 'object change', value: diffValue }; } } /** * compare and build the difference of two objects taking only its own properties into account * @param {?} a * @param {?} b * @param {?=} shallow * @return {?} */ diffOwnProperties(a, b, shallow) { return this.diff(a, b, shallow, true); } /** * Convert to a readable xml/html Json structure * @param {?} changes * @param {?=} shallow * @return {?} */ toJsonView(changes, shallow) { return this.formatToJsonXMLString(changes, shallow); } /** * Convert to a readable xml/html Json structure * @param {?} object * @param {?=} shallow * @return {?} */ objToJsonView(object, shallow) { return this.formatObjToJsonXMLString(object, shallow); } /** * Convert to a readable xml/html Json structure * @param {?} changes * @param {?=} shallow * @return {?} */ toJsonDiffView(changes, shallow) { return this.formatChangesToXMLString(changes, shallow); } /** * Convert to a readable xml/html Json structure * Convert to a readable xml/html Json structure * @private * @param {?} obj * @param {?} shallow * @return {?} */ formatObjToJsonXMLString(obj, shallow) { return this.sanitizer.bypassSecurityTrustHtml(this.inspect(obj, shallow)); } /** * Convert to a readable xml/html Json structure * @private * @param {?} changes * @param {?=} shallow * @return {?} */ formatToJsonXMLString(changes, shallow) { /** @type {?} */ let properties = []; /** @type {?} */ let diff = changes.value; if (changes.changed == 'equal') { return this.sanitizer.sanitize(SecurityContext.HTML, this.sanitizer.bypassSecurityTrustHtml(this.inspect(diff, shallow))); } for (let key in diff) { properties.push(this.formatChange(key, diff[key], shallow)); } return this.sanitizer.sanitize(SecurityContext.HTML, this.sanitizer.bypassSecurityTrustHtml('<span>' + this.openChar + '</span>\n<div class="diff-level">' + properties.join('<span>,</span>\n') + '\n</div><span>' + this.closeChar + '</span>')); } /** * @private * @param {?} changes * @param {?=} shallow * @return {?} */ formatChangesToXMLString(changes, shallow) { /** @type {?} */ var properties = []; if (changes.changed == 'equal') { return ''; } /** @type {?} */ var diff = changes.value; for (var key in diff) { /** @type {?} */ var changed = diff[key].changed; if (changed !== 'equal') properties.push(this.formatChange(key, diff[key], shallow, true)); } return this.sanitizer.sanitize(SecurityContext.HTML, this.sanitizer.bypassSecurityTrustHtml('<span>' + this.openChar + '</span>\n<div class="diff-level">' + properties.join('<span>,</span>\n') + '\n</div><span>' + this.closeChar + '</span>')); } /** * @private * @param {?} key * @param {?} diffItem * @param {?} shallow * @param {?=} diffOnly * @return {?} */ formatChange(key, diffItem, shallow, diffOnly) { /** @type {?} */ var changed = diffItem.changed; /** @type {?} */ var property; switch (changed) { case 'equal': property = (this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>' + this.inspect(diffItem.value)); break; case 'removed': property = ('<del class="diff">' + this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>' + this.inspect(diffItem.value) + '</del>'); break; case 'added': property = ('<ins class="diff">' + this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>' + this.inspect(diffItem.value) + '</ins>'); break; case 'primitive change': /** @type {?} */ var prefix = this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>'; property = ('<del class="diff diff-key">' + prefix + this.inspect(diffItem.removed) + '</del><span>,</span>\n' + '<ins class="diff diff-key">' + prefix + this.inspect(diffItem.added) + '</ins>'); break; case 'object change': property = shallow ? '' : (this.stringifyObjectKey(key) + '<span>: </span>' + (diffOnly ? this.formatChangesToXMLString(diffItem) : this.formatToJsonXMLString(diffItem))); break; } return property; } /** * @private * @param {?} obj * @param {?=} shallow * @return {?} */ inspect(obj, shallow) { return this._inspect('', obj, shallow); } /** * @see http://jsperf.com/continuation-passing-style/3 * @private * @param {?} accumulator * @param {?} obj * @param {?=} shallow * @return {?} */ _inspect(accumulator, obj, shallow) { switch (typeof obj) { case 'object': if (!obj) { accumulator += 'null'; break; } if (shallow) { accumulator += '[object]'; break; } /** @type {?} */ let keys = Object.keys(obj); /** @type {?} */ let length = keys.length; if (length === 0) { accumulator += '<span>' + this.openChar + this.closeChar + '</span>'; } else { accumulator += '<span>' + this.openChar + '</span>\n<div class="diff-level">'; for (let i = 0; i < length; i++) { /** @type {?} */ let key = keys[i]; accumulator = this._inspect(accumulator + this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>', obj[key]); if (i < length - 1) { accumulator += '<span>,</span>\n'; } } accumulator += '\n</div><span>' + this.closeChar + '</span>'; } break; case 'string': accumulator += JSON.stringify(this.escapeHTML(obj)); break; case 'undefined': accumulator += 'undefined'; break; default: accumulator += this.escapeHTML(String(obj)); break; } return accumulator; } /** * @private * @param {?} key * @return {?} */ stringifyObjectKey(key) { return /^[a-z0-9_$]*$/i.test(key) ? key : JSON.stringify(key); } /** * @private * @param {?} string * @return {?} */ escapeHTML(string) { return string.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'); } /** * @private * @param {?} obj * @return {?} */ equalObj(obj) { return { changed: 'equal', value: obj }; } /** * @private * @param {?} a * @param {?} b * @return {?} */ isValidAttr(a, b) { /** @type {?} */ let typeA = typeof a; /** @type {?} */ let typeB = typeof b; return (a && b && (typeA == 'object' || typeA == 'function') && (typeB == 'object' || typeB == 'function')); } } NgxObjectDiffService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ NgxObjectDiffService.ctorParameters = () => [ { type: DomSanitizer } ]; /** @nocollapse */ NgxObjectDiffService.ngInjectableDef = ɵɵdefineInjectable({ factory: function NgxObjectDiffService_Factory() { return new NgxObjectDiffService(ɵɵinject(DomSanitizer)); }, token: NgxObjectDiffService, providedIn: "root" }); if (false) { /** * @type {?} * @private */ NgxObjectDiffService.prototype.openChar; /** * @type {?} * @private */ NgxObjectDiffService.prototype.closeChar; /** * @type {?} * @private */ NgxObjectDiffService.prototype.sanitizer; } /** * @fileoverview added by tsickle * Generated from: lib/ngx-object-diff.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class NgxObjectDiffComponent { } NgxObjectDiffComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-object-diff', template: ` <pre [innerHTML]="obj"></pre> `, styles: [` pre{ display: block; padding: 9.5px; margin: 0 0 10px; font-size: 13px; line-height: 1.428571429; color: #333; word-break: break-all; word-wrap: break-word; background-color: #f5f5f5; border: 1px solid #ccc; border-radius: 4px; } :host >>> .diff { display: inline-block; } :host >>> .diff-level { margin-left: 1.6em; } :host >>> .diff-holder { color: #666; margin: 0; } :host >>> .diff-holder span { color: #AAA; } :host >>> del.diff { text-decoration: none; color: #b30000; background: #fadad7; } :host >>> ins.diff { background: #eaf2c2; color: #406619; text-decoration: none; } :host >>> del.diff-key { border: 1px solid #f8a4a4; } :host >>> ins.diff-key { border: 1px solid #a3ce4c; margin-top: -1px; position: relative; } :host >>> ins.diff span { color: #AABF40; } :host >>> del.diff span { color: #EE8177; } `] }] } ]; NgxObjectDiffComponent.propDecorators = { obj: [{ type: Input }] }; if (false) { /** @type {?} */ NgxObjectDiffComponent.prototype.obj; } /** * @fileoverview added by tsickle * Generated from: lib/ngx-object-diff.module.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class NgxObjectDiffModule { } NgxObjectDiffModule.decorators = [ { type: NgModule, args: [{ declarations: [NgxObjectDiffComponent], imports: [], providers: [NgxObjectDiffService], exports: [NgxObjectDiffComponent] },] } ]; /** * @fileoverview added by tsickle * Generated from: public-api.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * Generated from: ngx-object-diff.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { NgxObjectDiffComponent, NgxObjectDiffModule, NgxObjectDiffService }; //# sourceMappingURL=ngx-object-diff.js.map