UNPKG

ngx-editor

Version:

Rich Text Editor for angular using ProseMirror

82 lines 13.9 kB
import { Component, Input } from '@angular/core'; import Icon from '../../../icons'; import { ToggleCommands } from '../MenuCommands'; import * as i0 from "@angular/core"; import * as i1 from "../../../pipes/sanitize/sanitize-html.pipe"; import * as i2 from "../../../editor.service"; import * as i3 from "@angular/common"; export class BubbleComponent { constructor(sanitizeHTML, ngxeService) { this.sanitizeHTML = sanitizeHTML; this.ngxeService = ngxeService; this.execulableItems = []; this.activeItems = []; this.toolbar = [ ['bold', 'italic', 'underline', 'strike'], ['ordered_list', 'bullet_list', 'blockquote', 'code'], ['align_left', 'align_center', 'align_right', 'align_justify'] ]; this.toggleCommands = [ 'bold', 'italic', 'underline', 'strike', 'ordered_list', 'bullet_list', 'blockquote', 'code', 'align_left', 'align_center', 'align_right', 'align_justify' ]; } get view() { return this.editor.view; } getIcon(name) { const icon = Icon.get(name); return this.sanitizeHTML.transform(icon); } getTitle(name) { return this.ngxeService.locals.get(name); } trackByIndex(index) { return index; } onClick(e, commandName) { e.preventDefault(); e.stopPropagation(); if (e.button !== 0) { return; } const { state, dispatch } = this.view; const command = ToggleCommands[commandName]; command.toggle()(state, dispatch); } update(view) { this.activeItems = []; this.execulableItems = []; const { state } = view; this.toggleCommands.forEach(toolbarItem => { const command = ToggleCommands[toolbarItem]; const isActive = command.isActive(state); if (isActive) { this.activeItems.push(toolbarItem); } const canExecute = command.canExecute(state); if (canExecute) { this.execulableItems.push(toolbarItem); } }); } ngOnInit() { this.updateSubscription = this.editor.update .subscribe((view) => { this.update(view); }); } ngOnDestroy() { this.updateSubscription.unsubscribe(); } } BubbleComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.0", ngImport: i0, type: BubbleComponent, deps: [{ token: i1.SanitizeHtmlPipe }, { token: i2.NgxEditorService }], target: i0.ɵɵFactoryTarget.Component }); BubbleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.0", type: BubbleComponent, selector: "ngx-bubble", inputs: { editor: "editor" }, ngImport: i0, template: "<ng-container *ngFor=\"let toolbarItem of toolbar; let lastToolbarItem = last; trackBy: trackByIndex\">\n <ng-container *ngFor=\"let item of toolbarItem; let lastItem = last; trackBy: trackByIndex\">\n <div class=\"NgxBubbleMenu__Icon\" [ngClass]=\"{'NgxBubbleMenu__Icon--Active': this.activeItems.includes(item),\n 'NgxEditor--Disabled': !this.execulableItems.includes(item)}\" (mousedown)=\"onClick($event, item)\"\n *ngIf=\"toggleCommands.includes(item)\" [title]=\"getTitle(item)\" [innerHTML]=\"getIcon(item)\">\n </div>\n <div class=\"NgxBubbleMenu__Seperator\" *ngIf=\"lastItem && !lastToolbarItem\"></div>\n </ng-container>\n</ng-container>\n", styles: ["*,*:before,*:after{box-sizing:border-box}:host{display:flex;background-color:#000;color:#fff;padding:5px;border-radius:4px}.NgxBubbleMenu__Icon{height:30px;width:30px;transition:.3s ease-in-out;border-radius:2px;display:flex;align-items:center;justify-content:center;color:#fff}.NgxBubbleMenu__Icon:hover{background-color:#636262}.NgxBubbleMenu__Icon+.NgxBubbleMenu__Icon{margin-left:5px}.NgxBubbleMenu__Icon.NgxBubbleMenu__Icon--Active{background-color:#fff;color:#000}.NgxBubbleMenu__Seperator{border-left:1px solid white;margin:0 5px}\n"], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.0", ngImport: i0, type: BubbleComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-bubble', template: "<ng-container *ngFor=\"let toolbarItem of toolbar; let lastToolbarItem = last; trackBy: trackByIndex\">\n <ng-container *ngFor=\"let item of toolbarItem; let lastItem = last; trackBy: trackByIndex\">\n <div class=\"NgxBubbleMenu__Icon\" [ngClass]=\"{'NgxBubbleMenu__Icon--Active': this.activeItems.includes(item),\n 'NgxEditor--Disabled': !this.execulableItems.includes(item)}\" (mousedown)=\"onClick($event, item)\"\n *ngIf=\"toggleCommands.includes(item)\" [title]=\"getTitle(item)\" [innerHTML]=\"getIcon(item)\">\n </div>\n <div class=\"NgxBubbleMenu__Seperator\" *ngIf=\"lastItem && !lastToolbarItem\"></div>\n </ng-container>\n</ng-container>\n", styles: ["*,*:before,*:after{box-sizing:border-box}:host{display:flex;background-color:#000;color:#fff;padding:5px;border-radius:4px}.NgxBubbleMenu__Icon{height:30px;width:30px;transition:.3s ease-in-out;border-radius:2px;display:flex;align-items:center;justify-content:center;color:#fff}.NgxBubbleMenu__Icon:hover{background-color:#636262}.NgxBubbleMenu__Icon+.NgxBubbleMenu__Icon{margin-left:5px}.NgxBubbleMenu__Icon.NgxBubbleMenu__Icon--Active{background-color:#fff;color:#000}.NgxBubbleMenu__Seperator{border-left:1px solid white;margin:0 5px}\n"] }] }], ctorParameters: function () { return [{ type: i1.SanitizeHtmlPipe }, { type: i2.NgxEditorService }]; }, propDecorators: { editor: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnViYmxlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1lZGl0b3Ivc3JjL2xpYi9tb2R1bGVzL21lbnUvYnViYmxlL2J1YmJsZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWRpdG9yL3NyYy9saWIvbW9kdWxlcy9tZW51L2J1YmJsZS9idWJibGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFBRSxLQUFLLEVBRWpCLE1BQU0sZUFBZSxDQUFDO0FBTXZCLE9BQU8sSUFBSSxNQUFNLGdCQUFnQixDQUFDO0FBR2xDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7QUFRakQsTUFBTSxPQUFPLGVBQWU7SUFDMUIsWUFBb0IsWUFBOEIsRUFBVSxXQUE2QjtRQUFyRSxpQkFBWSxHQUFaLFlBQVksQ0FBa0I7UUFBVSxnQkFBVyxHQUFYLFdBQVcsQ0FBa0I7UUFTekYsb0JBQWUsR0FBYyxFQUFFLENBQUM7UUFDaEMsZ0JBQVcsR0FBYyxFQUFFLENBQUM7UUFFNUIsWUFBTyxHQUFnQjtZQUNyQixDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQztZQUN6QyxDQUFDLGNBQWMsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQztZQUNyRCxDQUFDLFlBQVksRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLGVBQWUsQ0FBQztTQUMvRCxDQUFDO1FBRUYsbUJBQWMsR0FBYztZQUMxQixNQUFNLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxRQUFRO1lBQ3ZDLGNBQWMsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLE1BQU07WUFDbkQsWUFBWSxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsZUFBZTtTQUM3RCxDQUFDO0lBdEIyRixDQUFDO0lBRTlGLElBQVksSUFBSTtRQUNkLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7SUFDMUIsQ0FBQztJQW9CRCxPQUFPLENBQUMsSUFBYTtRQUNuQixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzVCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVELFFBQVEsQ0FBQyxJQUFZO1FBQ25CLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRCxZQUFZLENBQUMsS0FBYTtRQUN4QixPQUFPLEtBQUssQ0FBQTtJQUNkLENBQUM7SUFFRCxPQUFPLENBQUMsQ0FBYSxFQUFFLFdBQW9CO1FBQ3pDLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUNuQixDQUFDLENBQUMsZUFBZSxFQUFFLENBQUM7UUFFcEIsSUFBSSxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUNsQixPQUFPO1NBQ1I7UUFFRCxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFFdEMsTUFBTSxPQUFPLEdBQUcsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzVDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUVPLE1BQU0sQ0FBQyxJQUFnQjtRQUM3QixJQUFJLENBQUMsV0FBVyxHQUFHLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUUsQ0FBQztRQUMxQixNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDO1FBRXZCLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxFQUFFO1lBQ3hDLE1BQU0sT0FBTyxHQUFHLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUU1QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pDLElBQUksUUFBUSxFQUFFO2dCQUNaLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO2FBQ3BDO1lBRUQsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUU3QyxJQUFJLFVBQVUsRUFBRTtnQkFDZCxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQzthQUN4QztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNO2FBQ3pDLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEIsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUN4QyxDQUFDOzs0R0FsRlUsZUFBZTtnR0FBZixlQUFlLGdGQ3BCNUIsNnBCQVNBOzJGRFdhLGVBQWU7a0JBTDNCLFNBQVM7K0JBQ0UsWUFBWTtzSUFXYixNQUFNO3NCQUFkLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsIElucHV0LCBPbkRlc3Ryb3ksXG4gIE9uSW5pdFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFNhZmVIdG1sIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5pbXBvcnQgeyBFZGl0b3JWaWV3IH0gZnJvbSAncHJvc2VtaXJyb3Itdmlldyc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IEVkaXRvciBmcm9tICcuLi8uLi8uLi9FZGl0b3InO1xuaW1wb3J0IEljb24gZnJvbSAnLi4vLi4vLi4vaWNvbnMnO1xuaW1wb3J0IHsgVEJJdGVtcyB9IGZyb20gJy4uLy4uLy4uL3R5cGVzJztcbmltcG9ydCB7IFNhbml0aXplSHRtbFBpcGUgfSBmcm9tICcuLi8uLi8uLi9waXBlcy9zYW5pdGl6ZS9zYW5pdGl6ZS1odG1sLnBpcGUnO1xuaW1wb3J0IHsgVG9nZ2xlQ29tbWFuZHMgfSBmcm9tICcuLi9NZW51Q29tbWFuZHMnO1xuaW1wb3J0IHsgTmd4RWRpdG9yU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL2VkaXRvci5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWJ1YmJsZScsXG4gIHRlbXBsYXRlVXJsOiAnLi9idWJibGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9idWJibGUuY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBCdWJibGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgc2FuaXRpemVIVE1MOiBTYW5pdGl6ZUh0bWxQaXBlLCBwcml2YXRlIG5neGVTZXJ2aWNlOiBOZ3hFZGl0b3JTZXJ2aWNlKSB7IH1cblxuICBwcml2YXRlIGdldCB2aWV3KCk6IEVkaXRvclZpZXcge1xuICAgIHJldHVybiB0aGlzLmVkaXRvci52aWV3O1xuICB9XG5cbiAgQElucHV0KCkgZWRpdG9yOiBFZGl0b3I7XG5cbiAgcHJpdmF0ZSB1cGRhdGVTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgZXhlY3VsYWJsZUl0ZW1zOiBUQkl0ZW1zW10gPSBbXTtcbiAgYWN0aXZlSXRlbXM6IFRCSXRlbXNbXSA9IFtdO1xuXG4gIHRvb2xiYXI6IFRCSXRlbXNbXVtdID0gW1xuICAgIFsnYm9sZCcsICdpdGFsaWMnLCAndW5kZXJsaW5lJywgJ3N0cmlrZSddLFxuICAgIFsnb3JkZXJlZF9saXN0JywgJ2J1bGxldF9saXN0JywgJ2Jsb2NrcXVvdGUnLCAnY29kZSddLFxuICAgIFsnYWxpZ25fbGVmdCcsICdhbGlnbl9jZW50ZXInLCAnYWxpZ25fcmlnaHQnLCAnYWxpZ25fanVzdGlmeSddXG4gIF07XG5cbiAgdG9nZ2xlQ29tbWFuZHM6IFRCSXRlbXNbXSA9IFtcbiAgICAnYm9sZCcsICdpdGFsaWMnLCAndW5kZXJsaW5lJywgJ3N0cmlrZScsXG4gICAgJ29yZGVyZWRfbGlzdCcsICdidWxsZXRfbGlzdCcsICdibG9ja3F1b3RlJywgJ2NvZGUnLFxuICAgICdhbGlnbl9sZWZ0JywgJ2FsaWduX2NlbnRlcicsICdhbGlnbl9yaWdodCcsICdhbGlnbl9qdXN0aWZ5J1xuICBdO1xuXG4gIGdldEljb24obmFtZTogVEJJdGVtcyk6IFNhZmVIdG1sIHtcbiAgICBjb25zdCBpY29uID0gSWNvbi5nZXQobmFtZSk7XG4gICAgcmV0dXJuIHRoaXMuc2FuaXRpemVIVE1MLnRyYW5zZm9ybShpY29uKTtcbiAgfVxuXG4gIGdldFRpdGxlKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubmd4ZVNlcnZpY2UubG9jYWxzLmdldChuYW1lKTtcbiAgfVxuXG4gIHRyYWNrQnlJbmRleChpbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gaW5kZXhcbiAgfVxuXG4gIG9uQ2xpY2soZTogTW91c2VFdmVudCwgY29tbWFuZE5hbWU6IFRCSXRlbXMpOiB2b2lkIHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIGlmIChlLmJ1dHRvbiAhPT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHsgc3RhdGUsIGRpc3BhdGNoIH0gPSB0aGlzLnZpZXc7XG5cbiAgICBjb25zdCBjb21tYW5kID0gVG9nZ2xlQ29tbWFuZHNbY29tbWFuZE5hbWVdO1xuICAgIGNvbW1hbmQudG9nZ2xlKCkoc3RhdGUsIGRpc3BhdGNoKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlKHZpZXc6IEVkaXRvclZpZXcpOiB2b2lkIHtcbiAgICB0aGlzLmFjdGl2ZUl0ZW1zID0gW107XG4gICAgdGhpcy5leGVjdWxhYmxlSXRlbXMgPSBbXTtcbiAgICBjb25zdCB7IHN0YXRlIH0gPSB2aWV3O1xuXG4gICAgdGhpcy50b2dnbGVDb21tYW5kcy5mb3JFYWNoKHRvb2xiYXJJdGVtID0+IHtcbiAgICAgIGNvbnN0IGNvbW1hbmQgPSBUb2dnbGVDb21tYW5kc1t0b29sYmFySXRlbV07XG5cbiAgICAgIGNvbnN0IGlzQWN0aXZlID0gY29tbWFuZC5pc0FjdGl2ZShzdGF0ZSk7XG4gICAgICBpZiAoaXNBY3RpdmUpIHtcbiAgICAgICAgdGhpcy5hY3RpdmVJdGVtcy5wdXNoKHRvb2xiYXJJdGVtKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2FuRXhlY3V0ZSA9IGNvbW1hbmQuY2FuRXhlY3V0ZShzdGF0ZSk7XG5cbiAgICAgIGlmIChjYW5FeGVjdXRlKSB7XG4gICAgICAgIHRoaXMuZXhlY3VsYWJsZUl0ZW1zLnB1c2godG9vbGJhckl0ZW0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy51cGRhdGVTdWJzY3JpcHRpb24gPSB0aGlzLmVkaXRvci51cGRhdGVcbiAgICAgIC5zdWJzY3JpYmUoKHZpZXcpID0+IHtcbiAgICAgICAgdGhpcy51cGRhdGUodmlldyk7XG4gICAgICB9KTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMudXBkYXRlU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gIH1cbn1cbiIsIjxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IHRvb2xiYXJJdGVtIG9mIHRvb2xiYXI7IGxldCBsYXN0VG9vbGJhckl0ZW0gPSBsYXN0OyB0cmFja0J5OiB0cmFja0J5SW5kZXhcIj5cbiAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgaXRlbSBvZiB0b29sYmFySXRlbTsgbGV0IGxhc3RJdGVtID0gbGFzdDsgdHJhY2tCeTogdHJhY2tCeUluZGV4XCI+XG4gICAgPGRpdiBjbGFzcz1cIk5neEJ1YmJsZU1lbnVfX0ljb25cIiBbbmdDbGFzc109XCJ7J05neEJ1YmJsZU1lbnVfX0ljb24tLUFjdGl2ZSc6IHRoaXMuYWN0aXZlSXRlbXMuaW5jbHVkZXMoaXRlbSksXG4gICdOZ3hFZGl0b3ItLURpc2FibGVkJzogIXRoaXMuZXhlY3VsYWJsZUl0ZW1zLmluY2x1ZGVzKGl0ZW0pfVwiIChtb3VzZWRvd24pPVwib25DbGljaygkZXZlbnQsIGl0ZW0pXCJcbiAgICAgICpuZ0lmPVwidG9nZ2xlQ29tbWFuZHMuaW5jbHVkZXMoaXRlbSlcIiBbdGl0bGVdPVwiZ2V0VGl0bGUoaXRlbSlcIiBbaW5uZXJIVE1MXT1cImdldEljb24oaXRlbSlcIj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiTmd4QnViYmxlTWVudV9fU2VwZXJhdG9yXCIgKm5nSWY9XCJsYXN0SXRlbSAmJiAhbGFzdFRvb2xiYXJJdGVtXCI+PC9kaXY+XG4gIDwvbmctY29udGFpbmVyPlxuPC9uZy1jb250YWluZXI+XG4iXX0=