UNPKG

ngx-quill

Version:

Angular components for the easy use of the QuillJS richt text editor.

682 lines (679 loc) 90.8 kB
import { DOCUMENT, isPlatformServer, CommonModule } from '@angular/common'; import { DomSanitizer } from '@angular/platform-browser'; import { ChangeDetectorRef, Component, Directive, ElementRef, EventEmitter, forwardRef, inject, Input, NgZone, Output, PLATFORM_ID, Renderer2, SecurityContext, ViewEncapsulation } from '@angular/core'; import { fromEvent, Subscription } from 'rxjs'; import { debounceTime, mergeMap } from 'rxjs/operators'; import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms'; import { defaultModules } from 'ngx-quill/config'; import { getFormat } from './helpers'; import { QuillService } from './quill.service'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; class QuillEditorBase { constructor() { this.required = false; this.customToolbarPosition = 'top'; this.styles = null; this.strict = true; this.customOptions = []; this.customModules = []; this.preserveWhitespace = false; this.trimOnValidation = false; this.compareValues = false; this.filterNull = false; /* https://github.com/KillerCodeMonkey/ngx-quill/issues/1257 - fix null value set provide default empty value by default null e.g. defaultEmptyValue="" - empty string <quill-editor defaultEmptyValue="" formControlName="message" ></quill-editor> */ this.defaultEmptyValue = null; this.onEditorCreated = new EventEmitter(); this.onEditorChanged = new EventEmitter(); this.onContentChanged = new EventEmitter(); this.onSelectionChanged = new EventEmitter(); this.onFocus = new EventEmitter(); this.onBlur = new EventEmitter(); this.onNativeFocus = new EventEmitter(); this.onNativeBlur = new EventEmitter(); this.disabled = false; // used to store initial value before ViewInit this.preserve = false; this.toolbarPosition = 'top'; this.subscription = null; this.quillSubscription = null; this.elementRef = inject(ElementRef); this.document = inject(DOCUMENT); this.cd = inject(ChangeDetectorRef); this.domSanitizer = inject(DomSanitizer); this.platformId = inject(PLATFORM_ID); this.renderer = inject(Renderer2); this.zone = inject(NgZone); this.service = inject(QuillService); this.valueGetter = (quillEditor, editorElement) => { let html = editorElement.querySelector('.ql-editor').innerHTML; if (html === '<p><br></p>' || html === '<div><br></div>') { html = this.defaultEmptyValue; } let modelValue = html; const format = getFormat(this.format, this.service.config.format); if (format === 'text') { modelValue = quillEditor.getText(); } else if (format === 'object') { modelValue = quillEditor.getContents(); } else if (format === 'json') { try { modelValue = JSON.stringify(quillEditor.getContents()); } catch (e) { modelValue = quillEditor.getText(); } } return modelValue; }; this.valueSetter = (quillEditor, value) => { const format = getFormat(this.format, this.service.config.format); if (format === 'html') { const sanitize = [true, false].includes(this.sanitize) ? this.sanitize : (this.service.config.sanitize || false); if (sanitize) { value = this.domSanitizer.sanitize(SecurityContext.HTML, value); } return quillEditor.clipboard.convert(value); } else if (format === 'json') { try { return JSON.parse(value); } catch (e) { return [{ insert: value }]; } } return value; }; this.selectionChangeHandler = (range, oldRange, source) => { const shouldTriggerOnModelTouched = !range && !!this.onModelTouched; // only emit changes when there's any listener if (!this.onBlur.observed && !this.onFocus.observed && !this.onSelectionChanged.observed && !shouldTriggerOnModelTouched) { return; } this.zone.run(() => { if (range === null) { this.onBlur.emit({ editor: this.quillEditor, source }); } else if (oldRange === null) { this.onFocus.emit({ editor: this.quillEditor, source }); } this.onSelectionChanged.emit({ editor: this.quillEditor, oldRange, range, source }); if (shouldTriggerOnModelTouched) { this.onModelTouched(); } this.cd.markForCheck(); }); }; this.textChangeHandler = (delta, oldDelta, source) => { // only emit changes emitted by user interactions const text = this.quillEditor.getText(); const content = this.quillEditor.getContents(); let html = this.editorElem.querySelector('.ql-editor').innerHTML; if (html === '<p><br></p>' || html === '<div><br></div>') { html = this.defaultEmptyValue; } const trackChanges = this.trackChanges || this.service.config.trackChanges; const shouldTriggerOnModelChange = (source === 'user' || trackChanges && trackChanges === 'all') && !!this.onModelChange; // only emit changes when there's any listener if (!this.onContentChanged.observed && !shouldTriggerOnModelChange) { return; } this.zone.run(() => { if (shouldTriggerOnModelChange) { this.onModelChange(this.valueGetter(this.quillEditor, this.editorElem)); } this.onContentChanged.emit({ content, delta, editor: this.quillEditor, html, oldDelta, source, text }); this.cd.markForCheck(); }); }; // eslint-disable-next-line max-len this.editorChangeHandler = (event, current, old, source) => { // only emit changes when there's any listener if (!this.onEditorChanged.observed) { return; } // only emit changes emitted by user interactions if (event === 'text-change') { const text = this.quillEditor.getText(); const content = this.quillEditor.getContents(); let html = this.editorElem.querySelector('.ql-editor').innerHTML; if (html === '<p><br></p>' || html === '<div><br></div>') { html = this.defaultEmptyValue; } this.zone.run(() => { this.onEditorChanged.emit({ content, delta: current, editor: this.quillEditor, event, html, oldDelta: old, source, text }); this.cd.markForCheck(); }); } else { this.zone.run(() => { this.onEditorChanged.emit({ editor: this.quillEditor, event, oldRange: old, range: current, source }); this.cd.markForCheck(); }); } }; } static normalizeClassNames(classes) { const classList = classes.trim().split(' '); return classList.reduce((prev, cur) => { const trimmed = cur.trim(); if (trimmed) { prev.push(trimmed); } return prev; }, []); } ngOnInit() { this.preserve = this.preserveWhitespace; this.toolbarPosition = this.customToolbarPosition; } ngAfterViewInit() { if (isPlatformServer(this.platformId)) { return; } // The `quill-editor` component might be destroyed before the `quill` chunk is loaded and its code is executed // this will lead to runtime exceptions, since the code will be executed on DOM nodes that don't exist within the tree. this.quillSubscription = this.service.getQuill().pipe(mergeMap((Quill) => { const promises = [this.service.registerCustomModules(Quill, this.customModules)]; const beforeRender = this.beforeRender ?? this.service.config.beforeRender; if (beforeRender) { promises.push(beforeRender()); } return Promise.all(promises).then(() => Quill); })).subscribe(Quill => { this.editorElem = this.elementRef.nativeElement.querySelector('[quill-editor-element]'); const toolbarElem = this.elementRef.nativeElement.querySelector('[quill-editor-toolbar]'); const modules = Object.assign({}, this.modules || this.service.config.modules); if (toolbarElem) { modules.toolbar = toolbarElem; } else if (modules.toolbar === undefined) { modules.toolbar = defaultModules.toolbar; } let placeholder = this.placeholder !== undefined ? this.placeholder : this.service.config.placeholder; if (placeholder === undefined) { placeholder = 'Insert text here ...'; } if (this.styles) { Object.keys(this.styles).forEach((key) => { this.renderer.setStyle(this.editorElem, key, this.styles[key]); }); } if (this.classes) { this.addClasses(this.classes); } this.customOptions.forEach((customOption) => { const newCustomOption = Quill.import(customOption.import); newCustomOption.whitelist = customOption.whitelist; Quill.register(newCustomOption, true); }); let bounds = this.bounds && this.bounds === 'self' ? this.editorElem : this.bounds; if (!bounds) { bounds = this.service.config.bounds ? this.service.config.bounds : this.document.body; } let debug = this.debug; if (!debug && debug !== false && this.service.config.debug) { debug = this.service.config.debug; } let readOnly = this.readOnly; if (!readOnly && this.readOnly !== false) { readOnly = this.service.config.readOnly !== undefined ? this.service.config.readOnly : false; } let defaultEmptyValue = this.defaultEmptyValue; // eslint-disable-next-line no-prototype-builtins if (this.service.config.hasOwnProperty('defaultEmptyValue')) { defaultEmptyValue = this.service.config.defaultEmptyValue; } let scrollingContainer = this.scrollingContainer; if (!scrollingContainer && this.scrollingContainer !== null) { scrollingContainer = this.service.config.scrollingContainer === null || this.service.config.scrollingContainer ? this.service.config.scrollingContainer : null; } let formats = this.formats; if (!formats && formats === undefined) { formats = this.service.config.formats ? [...this.service.config.formats] : (this.service.config.formats === null ? null : undefined); } this.zone.runOutsideAngular(() => { this.quillEditor = new Quill(this.editorElem, { bounds, debug: debug, formats: formats, modules, placeholder, readOnly, defaultEmptyValue, scrollingContainer: scrollingContainer, strict: this.strict, theme: this.theme || (this.service.config.theme ? this.service.config.theme : 'snow') }); if (this.onNativeBlur.observed) { // https://github.com/quilljs/quill/issues/2186#issuecomment-533401328 this.quillEditor.scroll.domNode.addEventListener('blur', () => this.onNativeBlur.next({ editor: this.quillEditor, source: 'dom' })); // https://github.com/quilljs/quill/issues/2186#issuecomment-803257538 this.quillEditor.getModule('toolbar').container.addEventListener('mousedown', (e) => e.preventDefault()); } if (this.onNativeFocus.observed) { this.quillEditor.scroll.domNode.addEventListener('focus', () => this.onNativeFocus.next({ editor: this.quillEditor, source: 'dom' })); } // Set optional link placeholder, Quill has no native API for it so using workaround if (this.linkPlaceholder) { const tooltip = this.quillEditor?.theme?.tooltip; const input = tooltip?.root?.querySelector('input[data-link]'); if (input?.dataset) { input.dataset.link = this.linkPlaceholder; } } }); if (this.content) { const format = getFormat(this.format, this.service.config.format); if (format === 'text') { this.quillEditor.setText(this.content, 'silent'); } else { const newValue = this.valueSetter(this.quillEditor, this.content); this.quillEditor.setContents(newValue, 'silent'); } this.quillEditor.getModule('history').clear(); } // initialize disabled status based on this.disabled as default value this.setDisabledState(); this.addQuillEventListeners(); // The `requestAnimationFrame` triggers change detection. There's no sense to invoke the `requestAnimationFrame` if anyone is // listening to the `onEditorCreated` event inside the template, for instance `<quill-view (onEditorCreated)="...">`. if (!this.onEditorCreated.observed && !this.onValidatorChanged) { return; } // The `requestAnimationFrame` will trigger change detection and `onEditorCreated` will also call `markDirty()` // internally, since Angular wraps template event listeners into `listener` instruction. We're using the `requestAnimationFrame` // to prevent the frame drop and avoid `ExpressionChangedAfterItHasBeenCheckedError` error. requestAnimationFrame(() => { if (this.onValidatorChanged) { this.onValidatorChanged(); } this.onEditorCreated.emit(this.quillEditor); this.onEditorCreated.complete(); }); }); } ngOnDestroy() { this.dispose(); this.quillSubscription?.unsubscribe(); this.quillSubscription = null; } ngOnChanges(changes) { if (!this.quillEditor) { return; } /* eslint-disable @typescript-eslint/dot-notation */ if (changes.readOnly) { this.quillEditor.enable(!changes.readOnly.currentValue); } if (changes.placeholder) { this.quillEditor.root.dataset.placeholder = changes.placeholder.currentValue; } if (changes.defaultEmptyValue) { this.quillEditor.root.dataset.defaultEmptyValue = changes.defaultEmptyValue.currentValue; } if (changes.styles) { const currentStyling = changes.styles.currentValue; const previousStyling = changes.styles.previousValue; if (previousStyling) { Object.keys(previousStyling).forEach((key) => { this.renderer.removeStyle(this.editorElem, key); }); } if (currentStyling) { Object.keys(currentStyling).forEach((key) => { this.renderer.setStyle(this.editorElem, key, this.styles[key]); }); } } if (changes.classes) { const currentClasses = changes.classes.currentValue; const previousClasses = changes.classes.previousValue; if (previousClasses) { this.removeClasses(previousClasses); } if (currentClasses) { this.addClasses(currentClasses); } } // We'd want to re-apply event listeners if the `debounceTime` binding changes to apply the // `debounceTime` operator or vice-versa remove it. if (changes.debounceTime) { this.addQuillEventListeners(); } /* eslint-enable @typescript-eslint/dot-notation */ } addClasses(classList) { QuillEditorBase.normalizeClassNames(classList).forEach((c) => { this.renderer.addClass(this.editorElem, c); }); } removeClasses(classList) { QuillEditorBase.normalizeClassNames(classList).forEach((c) => { this.renderer.removeClass(this.editorElem, c); }); } writeValue(currentValue) { // optional fix for https://github.com/angular/angular/issues/14988 if (this.filterNull && currentValue === null) { return; } this.content = currentValue; if (!this.quillEditor) { return; } const format = getFormat(this.format, this.service.config.format); const newValue = this.valueSetter(this.quillEditor, currentValue); if (this.compareValues) { const currentEditorValue = this.quillEditor.getContents(); if (JSON.stringify(currentEditorValue) === JSON.stringify(newValue)) { return; } } if (currentValue) { if (format === 'text') { this.quillEditor.setText(currentValue); } else { this.quillEditor.setContents(newValue); } return; } this.quillEditor.setText(''); } setDisabledState(isDisabled = this.disabled) { // store initial value to set appropriate disabled status after ViewInit this.disabled = isDisabled; if (this.quillEditor) { if (isDisabled) { this.quillEditor.disable(); this.renderer.setAttribute(this.elementRef.nativeElement, 'disabled', 'disabled'); } else { if (!this.readOnly) { this.quillEditor.enable(); } this.renderer.removeAttribute(this.elementRef.nativeElement, 'disabled'); } } } registerOnChange(fn) { this.onModelChange = fn; } registerOnTouched(fn) { this.onModelTouched = fn; } registerOnValidatorChange(fn) { this.onValidatorChanged = fn; } validate() { if (!this.quillEditor) { return null; } const err = {}; let valid = true; const text = this.quillEditor.getText(); // trim text if wanted + handle special case that an empty editor contains a new line const textLength = this.trimOnValidation ? text.trim().length : (text.length === 1 && text.trim().length === 0 ? 0 : text.length - 1); const deltaOperations = this.quillEditor.getContents().ops; const onlyEmptyOperation = deltaOperations && deltaOperations.length === 1 && ['\n', ''].includes(deltaOperations[0].insert); if (this.minLength && textLength && textLength < this.minLength) { err.minLengthError = { given: textLength, minLength: this.minLength }; valid = false; } if (this.maxLength && textLength > this.maxLength) { err.maxLengthError = { given: textLength, maxLength: this.maxLength }; valid = false; } if (this.required && !textLength && onlyEmptyOperation) { err.requiredError = { empty: true }; valid = false; } return valid ? null : err; } addQuillEventListeners() { this.dispose(); // We have to enter the `<root>` zone when adding event listeners, so `debounceTime` will spawn the // `AsyncAction` there w/o triggering change detections. We still re-enter the Angular's zone through // `zone.run` when we emit an event to the parent component. this.zone.runOutsideAngular(() => { this.subscription = new Subscription(); this.subscription.add( // mark model as touched if editor lost focus fromEvent(this.quillEditor, 'selection-change').subscribe(([range, oldRange, source]) => { this.selectionChangeHandler(range, oldRange, source); })); // The `fromEvent` supports passing JQuery-style event targets, the editor has `on` and `off` methods which // will be invoked upon subscription and teardown. let textChange$ = fromEvent(this.quillEditor, 'text-change'); let editorChange$ = fromEvent(this.quillEditor, 'editor-change'); if (typeof this.debounceTime === 'number') { textChange$ = textChange$.pipe(debounceTime(this.debounceTime)); editorChange$ = editorChange$.pipe(debounceTime(this.debounceTime)); } this.subscription.add( // update model if text changes textChange$.subscribe(([delta, oldDelta, source]) => { this.textChangeHandler(delta, oldDelta, source); })); this.subscription.add( // triggered if selection or text changed editorChange$.subscribe(([event, current, old, source]) => { this.editorChangeHandler(event, current, old, source); })); }); } dispose() { if (this.subscription !== null) { this.subscription.unsubscribe(); this.subscription = null; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: QuillEditorBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.5", type: QuillEditorBase, inputs: { format: "format", theme: "theme", modules: "modules", debug: "debug", readOnly: "readOnly", placeholder: "placeholder", maxLength: "maxLength", minLength: "minLength", required: "required", formats: "formats", customToolbarPosition: "customToolbarPosition", sanitize: "sanitize", beforeRender: "beforeRender", styles: "styles", strict: "strict", scrollingContainer: "scrollingContainer", bounds: "bounds", customOptions: "customOptions", customModules: "customModules", trackChanges: "trackChanges", preserveWhitespace: "preserveWhitespace", classes: "classes", trimOnValidation: "trimOnValidation", linkPlaceholder: "linkPlaceholder", compareValues: "compareValues", filterNull: "filterNull", debounceTime: "debounceTime", defaultEmptyValue: "defaultEmptyValue", valueGetter: "valueGetter", valueSetter: "valueSetter" }, outputs: { onEditorCreated: "onEditorCreated", onEditorChanged: "onEditorChanged", onContentChanged: "onContentChanged", onSelectionChanged: "onSelectionChanged", onFocus: "onFocus", onBlur: "onBlur", onNativeFocus: "onNativeFocus", onNativeBlur: "onNativeBlur" }, usesOnChanges: true, ngImport: i0 }); } } export { QuillEditorBase }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: QuillEditorBase, decorators: [{ type: Directive }], propDecorators: { format: [{ type: Input }], theme: [{ type: Input }], modules: [{ type: Input }], debug: [{ type: Input }], readOnly: [{ type: Input }], placeholder: [{ type: Input }], maxLength: [{ type: Input }], minLength: [{ type: Input }], required: [{ type: Input }], formats: [{ type: Input }], customToolbarPosition: [{ type: Input }], sanitize: [{ type: Input }], beforeRender: [{ type: Input }], styles: [{ type: Input }], strict: [{ type: Input }], scrollingContainer: [{ type: Input }], bounds: [{ type: Input }], customOptions: [{ type: Input }], customModules: [{ type: Input }], trackChanges: [{ type: Input }], preserveWhitespace: [{ type: Input }], classes: [{ type: Input }], trimOnValidation: [{ type: Input }], linkPlaceholder: [{ type: Input }], compareValues: [{ type: Input }], filterNull: [{ type: Input }], debounceTime: [{ type: Input }], defaultEmptyValue: [{ type: Input }], onEditorCreated: [{ type: Output }], onEditorChanged: [{ type: Output }], onContentChanged: [{ type: Output }], onSelectionChanged: [{ type: Output }], onFocus: [{ type: Output }], onBlur: [{ type: Output }], onNativeFocus: [{ type: Output }], onNativeBlur: [{ type: Output }], valueGetter: [{ type: Input }], valueSetter: [{ type: Input }] } }); class QuillEditorComponent extends QuillEditorBase { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: QuillEditorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.5", type: QuillEditorComponent, isStandalone: true, selector: "quill-editor", providers: [ { multi: true, provide: NG_VALUE_ACCESSOR, // eslint-disable-next-line @typescript-eslint/no-use-before-define useExisting: forwardRef(() => QuillEditorComponent) }, { multi: true, provide: NG_VALIDATORS, // eslint-disable-next-line @typescript-eslint/no-use-before-define useExisting: forwardRef(() => QuillEditorComponent) } ], usesInheritance: true, ngImport: i0, template: ` <ng-template [ngIf]="toolbarPosition !== 'top'"> <pre quill-editor-element *ngIf="preserve; else noPreserveTpl"></pre> </ng-template> <ng-content select="[quill-editor-toolbar]"></ng-content> <ng-template [ngIf]="toolbarPosition === 'top'"> <pre quill-editor-element *ngIf="preserve; else noPreserveTpl"></pre> </ng-template> <ng-template #noPreserveTpl> <div quill-editor-element></div> </ng-template> `, isInline: true, styles: [":host{display:inline-block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); } } export { QuillEditorComponent }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: QuillEditorComponent, decorators: [{ type: Component, args: [{ encapsulation: ViewEncapsulation.Emulated, providers: [ { multi: true, provide: NG_VALUE_ACCESSOR, // eslint-disable-next-line @typescript-eslint/no-use-before-define useExisting: forwardRef(() => QuillEditorComponent) }, { multi: true, provide: NG_VALIDATORS, // eslint-disable-next-line @typescript-eslint/no-use-before-define useExisting: forwardRef(() => QuillEditorComponent) } ], selector: 'quill-editor', template: ` <ng-template [ngIf]="toolbarPosition !== 'top'"> <pre quill-editor-element *ngIf="preserve; else noPreserveTpl"></pre> </ng-template> <ng-content select="[quill-editor-toolbar]"></ng-content> <ng-template [ngIf]="toolbarPosition === 'top'"> <pre quill-editor-element *ngIf="preserve; else noPreserveTpl"></pre> </ng-template> <ng-template #noPreserveTpl> <div quill-editor-element></div> </ng-template> `, standalone: true, imports: [CommonModule], styles: [":host{display:inline-block}\n"] }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVpbGwtZWRpdG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1xdWlsbC9zcmMvbGliL3F1aWxsLWVkaXRvci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUMxRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUE7QUFJeEQsT0FBTyxFQUVMLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osVUFBVSxFQUNWLE1BQU0sRUFDTixLQUFLLEVBQ0wsTUFBTSxFQUlOLE1BQU0sRUFDTixXQUFXLEVBQ1gsU0FBUyxFQUNULGVBQWUsRUFFZixpQkFBaUIsRUFDbEIsTUFBTSxlQUFlLENBQUE7QUFDdEIsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUE7QUFDOUMsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUV2RCxPQUFPLEVBQXdCLGFBQWEsRUFBRSxpQkFBaUIsRUFBYSxNQUFNLGdCQUFnQixDQUFBO0FBRWxHLE9BQU8sRUFBRSxjQUFjLEVBQTRDLE1BQU0sa0JBQWtCLENBQUE7QUFFM0YsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUNyQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUE7OztBQXFDOUMsTUFFc0IsZUFBZTtJQUZyQztRQVdXLGFBQVEsR0FBRyxLQUFLLENBQUE7UUFFaEIsMEJBQXFCLEdBQXFCLEtBQUssQ0FBQTtRQUcvQyxXQUFNLEdBQVEsSUFBSSxDQUFBO1FBQ2xCLFdBQU0sR0FBRyxJQUFJLENBQUE7UUFHYixrQkFBYSxHQUFtQixFQUFFLENBQUE7UUFD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