angular6-json-schema-form
Version:
Angular JSON Schema Form builder
606 lines • 99.8 kB
JavaScript
import * as tslib_1 from "tslib";
import cloneDeep from 'lodash-es/cloneDeep';
import Ajv from 'ajv';
import jsonDraft6 from 'ajv/lib/refs/json-schema-draft-06.json';
import { buildFormGroup, buildFormGroupTemplate, formatFormData, getControl } from './shared/form-group.functions';
import { buildLayout, getLayoutNode } from './shared/layout.functions';
import { buildSchemaFromData, buildSchemaFromLayout, removeRecursiveReferences } from './shared/json-schema.functions';
import { enValidationMessages } from './locale/en-validation-messages';
import { frValidationMessages } from './locale/fr-validation-messages';
import { zhValidationMessages } from './locale/zh-validation-messages';
import { fixTitle, forEach, hasOwn, toTitleCase } from './shared/utility.functions';
import { hasValue, isArray, isDefined, isEmpty, isObject } from './shared/validator.functions';
import { Injectable } from '@angular/core';
import { JsonPointer } from './shared/jsonpointer.functions';
import { Subject } from 'rxjs';
let JsonSchemaFormService = class JsonSchemaFormService {
constructor() {
this.JsonFormCompatibility = false;
this.ReactJsonSchemaFormCompatibility = false;
this.AngularSchemaFormCompatibility = false;
this.tpldata = {};
this.ajvOptions = { allErrors: true, jsonPointers: true, unknownFormats: 'ignore' };
this.ajv = new Ajv(this.ajvOptions); // AJV: Another JSON Schema Validator
this.validateFormData = null; // Compiled AJV function to validate active form's schema
this.formValues = {}; // Internal form data (may not have correct types)
this.data = {}; // Output form data (formValues, formatted with correct data types)
this.schema = {}; // Internal JSON Schema
this.layout = []; // Internal form layout
this.formGroupTemplate = {}; // Template used to create formGroup
this.formGroup = null; // Angular formGroup, which powers the reactive form
this.framework = null; // Active framework component
this.validData = null; // Valid form data (or null) (=== isValid ? data : null)
this.isValid = null; // Is current form data valid?
this.ajvErrors = null; // Ajv errors for current data
this.validationErrors = null; // Any validation errors for current data
this.dataErrors = new Map(); //
this.formValueSubscription = null; // Subscription to formGroup.valueChanges observable (for un- and re-subscribing)
this.dataChanges = new Subject(); // Form data observable
this.isValidChanges = new Subject(); // isValid observable
this.validationErrorChanges = new Subject(); // validationErrors observable
this.arrayMap = new Map(); // Maps arrays in data object and number of tuple values
this.dataMap = new Map(); // Maps paths in form data to schema and formGroup paths
this.dataRecursiveRefMap = new Map(); // Maps recursive reference points in form data
this.schemaRecursiveRefMap = new Map(); // Maps recursive reference points in schema
this.schemaRefLibrary = {}; // Library of schemas for resolving schema $refs
this.layoutRefLibrary = { '': null }; // Library of layout nodes for adding to form
this.templateRefLibrary = {}; // Library of formGroup templates for adding to form
this.hasRootReference = false; // Does the form include a recursive reference to itself?
this.language = 'en-US'; // Does the form include a recursive reference to itself?
// Default global form options
this.defaultFormOptions = {
autocomplete: true,
addSubmit: 'auto',
// for addSubmit: true = always, false = never,
// 'auto' = only if layout is undefined (form is built from schema alone)
debug: false,
disableInvalidSubmit: true,
formDisabled: false,
formReadonly: false,
fieldsRequired: false,
framework: 'no-framework',
loadExternalAssets: false,
pristine: { errors: true, success: true },
supressPropertyTitles: false,
setSchemaDefaults: 'auto',
// true = always set (unless overridden by layout default or formValues)
// false = never set
// 'auto' = set in addable components, and everywhere if formValues not set
setLayoutDefaults: 'auto',
// true = always set (unless overridden by formValues)
// false = never set
// 'auto' = set in addable components, and everywhere if formValues not set
validateOnRender: 'auto',
// true = validate all fields immediately
// false = only validate fields after they are touched by user
// 'auto' = validate fields with values immediately, empty fields after they are touched
widgets: {},
defautWidgetOptions: {
listItems: 1,
addable: true,
orderable: true,
removable: true,
enableErrorState: true,
// disableErrorState: false, // Don't apply 'has-error' class when field fails validation?
enableSuccessState: true,
// disableSuccessState: false, // Don't apply 'has-success' class when field validates?
feedback: false,
feedbackOnRender: false,
notitle: false,
disabled: false,
readonly: false,
returnEmptyFields: true,
validationMessages: {} // set by setLanguage()
},
};
this.setLanguage(this.language);
this.ajv.addMetaSchema(jsonDraft6);
}
setLanguage(language = 'en-US') {
this.language = language;
const languageValidationMessages = {
fr: frValidationMessages,
en: enValidationMessages,
zh: zhValidationMessages
};
const languageCode = language.slice(0, 2);
const validationMessages = languageValidationMessages[languageCode];
this.defaultFormOptions.defautWidgetOptions.validationMessages =
cloneDeep(validationMessages);
}
getData() { return this.data; }
getSchema() { return this.schema; }
getLayout() { return this.layout; }
resetAllValues() {
this.JsonFormCompatibility = false;
this.ReactJsonSchemaFormCompatibility = false;
this.AngularSchemaFormCompatibility = false;
this.tpldata = {};
this.validateFormData = null;
this.formValues = {};
this.schema = {};
this.layout = [];
this.formGroupTemplate = {};
this.formGroup = null;
this.framework = null;
this.data = {};
this.validData = null;
this.isValid = null;
this.validationErrors = null;
this.arrayMap = new Map();
this.dataMap = new Map();
this.dataRecursiveRefMap = new Map();
this.schemaRecursiveRefMap = new Map();
this.layoutRefLibrary = {};
this.schemaRefLibrary = {};
this.templateRefLibrary = {};
this.formOptions = cloneDeep(this.defaultFormOptions);
}
/**
* 'buildRemoteError' function
*
* Example errors:
* {
* last_name: [ {
* message: 'Last name must by start with capital letter.',
* code: 'capital_letter'
* } ],
* email: [ {
* message: 'Email must be from example.com domain.',
* code: 'special_domain'
* }, {
* message: 'Email must contain an @ symbol.',
* code: 'at_symbol'
* } ]
* }
* //{ErrorMessages} errors
*/
buildRemoteError(errors) {
forEach(errors, (value, key) => {
if (key in this.formGroup.controls) {
for (const error of value) {
const err = {};
err[error['code']] = error['message'];
this.formGroup.get(key).setErrors(err, { emitEvent: true });
}
}
});
}
validateData(newValue, updateSubscriptions = true) {
// Format raw form data to correct data types
this.data = formatFormData(newValue, this.dataMap, this.dataRecursiveRefMap, this.arrayMap, this.formOptions.returnEmptyFields);
this.isValid = this.validateFormData(this.data);
this.validData = this.isValid ? this.data : null;
const compileErrors = errors => {
const compiledErrors = {};
(errors || []).forEach(error => {
if (!compiledErrors[error.dataPath]) {
compiledErrors[error.dataPath] = [];
}
compiledErrors[error.dataPath].push(error.message);
});
return compiledErrors;
};
this.ajvErrors = this.validateFormData.errors;
this.validationErrors = compileErrors(this.validateFormData.errors);
if (updateSubscriptions) {
this.dataChanges.next(this.data);
this.isValidChanges.next(this.isValid);
this.validationErrorChanges.next(this.ajvErrors);
}
}
buildFormGroupTemplate(formValues = null, setValues = true) {
this.formGroupTemplate = buildFormGroupTemplate(this, formValues, setValues);
}
buildFormGroup() {
this.formGroup = buildFormGroup(this.formGroupTemplate);
if (this.formGroup) {
this.compileAjvSchema();
this.validateData(this.formGroup.value);
// Set up observables to emit data and validation info when form data changes
if (this.formValueSubscription) {
this.formValueSubscription.unsubscribe();
}
this.formValueSubscription = this.formGroup.valueChanges
.subscribe(formValue => this.validateData(formValue));
}
}
buildLayout(widgetLibrary) {
this.layout = buildLayout(this, widgetLibrary);
}
setOptions(newOptions) {
if (isObject(newOptions)) {
const addOptions = cloneDeep(newOptions);
// Backward compatibility for 'defaultOptions' (renamed 'defautWidgetOptions')
if (isObject(addOptions.defaultOptions)) {
Object.assign(this.formOptions.defautWidgetOptions, addOptions.defaultOptions);
delete addOptions.defaultOptions;
}
if (isObject(addOptions.defautWidgetOptions)) {
Object.assign(this.formOptions.defautWidgetOptions, addOptions.defautWidgetOptions);
delete addOptions.defautWidgetOptions;
}
Object.assign(this.formOptions, addOptions);
// convert disableErrorState / disableSuccessState to enable...
const globalDefaults = this.formOptions.defautWidgetOptions;
['ErrorState', 'SuccessState']
.filter(suffix => hasOwn(globalDefaults, 'disable' + suffix))
.forEach(suffix => {
globalDefaults['enable' + suffix] = !globalDefaults['disable' + suffix];
delete globalDefaults['disable' + suffix];
});
}
}
compileAjvSchema() {
if (!this.validateFormData) {
// if 'ui:order' exists in properties, move it to root before compiling with ajv
if (Array.isArray(this.schema.properties['ui:order'])) {
this.schema['ui:order'] = this.schema.properties['ui:order'];
delete this.schema.properties['ui:order'];
}
this.ajv.removeSchema(this.schema);
this.validateFormData = this.ajv.compile(this.schema);
}
}
buildSchemaFromData(data, requireAllFields = false) {
if (data) {
return buildSchemaFromData(data, requireAllFields);
}
this.schema = buildSchemaFromData(this.formValues, requireAllFields);
}
buildSchemaFromLayout(layout) {
if (layout) {
return buildSchemaFromLayout(layout);
}
this.schema = buildSchemaFromLayout(this.layout);
}
setTpldata(newTpldata = {}) {
this.tpldata = newTpldata;
}
parseText(text = '', value = {}, values = {}, key = null) {
if (!text || !/{{.+?}}/.test(text)) {
return text;
}
return text.replace(/{{(.+?)}}/g, (...a) => this.parseExpression(a[1], value, values, key, this.tpldata));
}
parseExpression(expression = '', value = {}, values = {}, key = null, tpldata = null) {
if (typeof expression !== 'string') {
return '';
}
const index = typeof key === 'number' ? (key + 1) + '' : (key || '');
expression = expression.trim();
if ((expression[0] === '\'' || expression[0] === '"') &&
expression[0] === expression[expression.length - 1] &&
expression.slice(1, expression.length - 1).indexOf(expression[0]) === -1) {
return expression.slice(1, expression.length - 1);
}
if (expression === 'idx' || expression === '$index') {
return index;
}
if (expression === 'value' && !hasOwn(values, 'value')) {
return value;
}
if (['"', '\'', ' ', '||', '&&', '+'].every(delim => expression.indexOf(delim) === -1)) {
const pointer = JsonPointer.parseObjectPath(expression);
return pointer[0] === 'value' && JsonPointer.has(value, pointer.slice(1)) ?
JsonPointer.get(value, pointer.slice(1)) :
pointer[0] === 'values' && JsonPointer.has(values, pointer.slice(1)) ?
JsonPointer.get(values, pointer.slice(1)) :
pointer[0] === 'tpldata' && JsonPointer.has(tpldata, pointer.slice(1)) ?
JsonPointer.get(tpldata, pointer.slice(1)) :
JsonPointer.has(values, pointer) ? JsonPointer.get(values, pointer) : '';
}
if (expression.indexOf('[idx]') > -1) {
expression = expression.replace(/\[idx\]/g, index);
}
if (expression.indexOf('[$index]') > -1) {
expression = expression.replace(/\[$index\]/g, index);
}
// TODO: Improve expression evaluation by parsing quoted strings first
// let expressionArray = expression.match(/([^"']+|"[^"]+"|'[^']+')/g);
if (expression.indexOf('||') > -1) {
return expression.split('||').reduce((all, term) => all || this.parseExpression(term, value, values, key, tpldata), '');
}
if (expression.indexOf('&&') > -1) {
return expression.split('&&').reduce((all, term) => all && this.parseExpression(term, value, values, key, tpldata), ' ').trim();
}
if (expression.indexOf('+') > -1) {
return expression.split('+')
.map(term => this.parseExpression(term, value, values, key, tpldata))
.join('');
}
return '';
}
setArrayItemTitle(parentCtx = {}, childNode = null, index = null) {
const parentNode = parentCtx.layoutNode;
const parentValues = this.getFormControlValue(parentCtx);
const isArrayItem = (parentNode.type || '').slice(-5) === 'array' && isArray(parentValues);
const text = JsonPointer.getFirst(isArrayItem && childNode.type !== '$ref' ? [
[childNode, '/options/legend'],
[childNode, '/options/title'],
[parentNode, '/options/title'],
[parentNode, '/options/legend'],
] : [
[childNode, '/options/title'],
[childNode, '/options/legend'],
[parentNode, '/options/title'],
[parentNode, '/options/legend']
]);
if (!text) {
return text;
}
const childValue = isArray(parentValues) && index < parentValues.length ?
parentValues[index] : parentValues;
return this.parseText(text, childValue, parentValues, index);
}
setItemTitle(ctx) {
return !ctx.options.title && /^(\d+|-)$/.test(ctx.layoutNode.name) ?
null :
this.parseText(ctx.options.title || toTitleCase(ctx.layoutNode.name), this.getFormControlValue(this), (this.getFormControlGroup(this) || {}).value, ctx.dataIndex[ctx.dataIndex.length - 1]);
}
evaluateCondition(layoutNode, dataIndex) {
const arrayIndex = dataIndex && dataIndex[dataIndex.length - 1];
let result = true;
if (hasValue((layoutNode.options || {}).condition)) {
if (typeof layoutNode.options.condition === 'string') {
let pointer = layoutNode.options.condition;
if (hasValue(arrayIndex)) {
pointer = pointer.replace('[arrayIndex]', `[${arrayIndex}]`);
}
pointer = JsonPointer.parseObjectPath(pointer);
result = !!JsonPointer.get(this.data, pointer);
if (!result && pointer[0] === 'model') {
result = !!JsonPointer.get({ model: this.data }, pointer);
}
}
else if (typeof layoutNode.options.condition === 'function') {
result = layoutNode.options.condition(this.data);
}
else if (typeof layoutNode.options.condition.functionBody === 'string') {
try {
const dynFn = new Function('model', 'arrayIndices', layoutNode.options.condition.functionBody);
result = dynFn(this.data, dataIndex);
}
catch (e) {
result = true;
console.error('condition functionBody errored out on evaluation: ' + layoutNode.options.condition.functionBody);
}
}
}
return result;
}
initializeControl(ctx, bind = true) {
if (!isObject(ctx)) {
return false;
}
if (isEmpty(ctx.options)) {
ctx.options = !isEmpty((ctx.layoutNode || {}).options) ?
ctx.layoutNode.options : cloneDeep(this.formOptions);
}
ctx.formControl = this.getFormControl(ctx);
ctx.boundControl = bind && !!ctx.formControl;
if (ctx.formControl) {
ctx.controlName = this.getFormControlName(ctx);
ctx.controlValue = ctx.formControl.value;
ctx.controlDisabled = ctx.formControl.disabled;
ctx.options.errorMessage = ctx.formControl.status === 'VALID' ? null :
this.formatErrors(ctx.formControl.errors, ctx.options.validationMessages);
ctx.options.showErrors = this.formOptions.validateOnRender === true ||
(this.formOptions.validateOnRender === 'auto' && hasValue(ctx.controlValue));
ctx.formControl.statusChanges.subscribe(status => ctx.options.errorMessage = status === 'VALID' ? null :
this.formatErrors(ctx.formControl.errors, ctx.options.validationMessages));
ctx.formControl.valueChanges.subscribe(value => {
if (!!value) {
ctx.controlValue = value;
}
});
}
else {
ctx.controlName = ctx.layoutNode.name;
ctx.controlValue = ctx.layoutNode.value || null;
const dataPointer = this.getDataPointer(ctx);
if (bind && dataPointer) {
console.error(`warning: control "${dataPointer}" is not bound to the Angular FormGroup.`);
}
}
return ctx.boundControl;
}
formatErrors(errors, validationMessages = {}) {
if (isEmpty(errors)) {
return null;
}
if (!isObject(validationMessages)) {
validationMessages = {};
}
const addSpaces = string => string[0].toUpperCase() + (string.slice(1) || '')
.replace(/([a-z])([A-Z])/g, '$1 $2').replace(/_/g, ' ');
const formatError = (error) => typeof error === 'object' ?
Object.keys(error).map(key => error[key] === true ? addSpaces(key) :
error[key] === false ? 'Not ' + addSpaces(key) :
addSpaces(key) + ': ' + formatError(error[key])).join(', ') :
addSpaces(error.toString());
const messages = [];
return Object.keys(errors)
// Hide 'required' error, unless it is the only one
.filter(errorKey => errorKey !== 'required' || Object.keys(errors).length === 1)
.map(errorKey =>
// If validationMessages is a string, return it
typeof validationMessages === 'string' ? validationMessages :
// If custom error message is a function, return function result
typeof validationMessages[errorKey] === 'function' ?
validationMessages[errorKey](errors[errorKey]) :
// If custom error message is a string, replace placeholders and return
typeof validationMessages[errorKey] === 'string' ?
// Does error message have any {{property}} placeholders?
!/{{.+?}}/.test(validationMessages[errorKey]) ?
validationMessages[errorKey] :
// Replace {{property}} placeholders with values
Object.keys(errors[errorKey])
.reduce((errorMessage, errorProperty) => errorMessage.replace(new RegExp('{{' + errorProperty + '}}', 'g'), errors[errorKey][errorProperty]), validationMessages[errorKey]) :
// If no custom error message, return formatted error data instead
addSpaces(errorKey) + ' Error: ' + formatError(errors[errorKey])).join('<br>');
}
updateValue(ctx, value) {
// Set value of current control
ctx.controlValue = value;
if (ctx.boundControl) {
ctx.formControl.setValue(value);
ctx.formControl.markAsDirty();
}
ctx.layoutNode.value = value;
// Set values of any related controls in copyValueTo array
if (isArray(ctx.options.copyValueTo)) {
for (const item of ctx.options.copyValueTo) {
const targetControl = getControl(this.formGroup, item);
if (isObject(targetControl) && typeof targetControl.setValue === 'function') {
targetControl.setValue(value);
targetControl.markAsDirty();
}
}
}
}
updateArrayCheckboxList(ctx, checkboxList) {
const formArray = this.getFormControl(ctx);
// Remove all existing items
while (formArray.value.length) {
formArray.removeAt(0);
}
// Re-add an item for each checked box
const refPointer = removeRecursiveReferences(ctx.layoutNode.dataPointer + '/-', this.dataRecursiveRefMap, this.arrayMap);
for (const checkboxItem of checkboxList) {
if (checkboxItem.checked) {
const newFormControl = buildFormGroup(this.templateRefLibrary[refPointer]);
newFormControl.setValue(checkboxItem.value);
formArray.push(newFormControl);
}
}
formArray.markAsDirty();
}
getFormControl(ctx) {
if (!ctx.layoutNode || !isDefined(ctx.layoutNode.dataPointer) ||
ctx.layoutNode.type === '$ref') {
return null;
}
return getControl(this.formGroup, this.getDataPointer(ctx));
}
getFormControlValue(ctx) {
if (!ctx.layoutNode || !isDefined(ctx.layoutNode.dataPointer) ||
ctx.layoutNode.type === '$ref') {
return null;
}
const control = getControl(this.formGroup, this.getDataPointer(ctx));
return control ? control.value : null;
}
getFormControlGroup(ctx) {
if (!ctx.layoutNode || !isDefined(ctx.layoutNode.dataPointer)) {
return null;
}
return getControl(this.formGroup, this.getDataPointer(ctx), true);
}
getFormControlName(ctx) {
if (!ctx.layoutNode || !isDefined(ctx.layoutNode.dataPointer) || !hasValue(ctx.dataIndex)) {
return null;
}
return JsonPointer.toKey(this.getDataPointer(ctx));
}
getLayoutArray(ctx) {
return JsonPointer.get(this.layout, this.getLayoutPointer(ctx), 0, -1);
}
getParentNode(ctx) {
return JsonPointer.get(this.layout, this.getLayoutPointer(ctx), 0, -2);
}
getDataPointer(ctx) {
if (!ctx.layoutNode || !isDefined(ctx.layoutNode.dataPointer) || !hasValue(ctx.dataIndex)) {
return null;
}
return JsonPointer.toIndexedPointer(ctx.layoutNode.dataPointer, ctx.dataIndex, this.arrayMap);
}
getLayoutPointer(ctx) {
if (!hasValue(ctx.layoutIndex)) {
return null;
}
return '/' + ctx.layoutIndex.join('/items/');
}
isControlBound(ctx) {
if (!ctx.layoutNode || !isDefined(ctx.layoutNode.dataPointer) || !hasValue(ctx.dataIndex)) {
return false;
}
const controlGroup = this.getFormControlGroup(ctx);
const name = this.getFormControlName(ctx);
return controlGroup ? hasOwn(controlGroup.controls, name) : false;
}
addItem(ctx, name) {
if (!ctx.layoutNode || !isDefined(ctx.layoutNode.$ref) ||
!hasValue(ctx.dataIndex) || !hasValue(ctx.layoutIndex)) {
return false;
}
// Create a new Angular form control from a template in templateRefLibrary
const newFormGroup = buildFormGroup(this.templateRefLibrary[ctx.layoutNode.$ref]);
// Add the new form control to the parent formArray or formGroup
if (ctx.layoutNode.arrayItem) { // Add new array item to formArray
this.getFormControlGroup(ctx).push(newFormGroup);
}
else { // Add new $ref item to formGroup
this.getFormControlGroup(ctx)
.addControl(name || this.getFormControlName(ctx), newFormGroup);
}
// Copy a new layoutNode from layoutRefLibrary
const newLayoutNode = getLayoutNode(ctx.layoutNode, this);
newLayoutNode.arrayItem = ctx.layoutNode.arrayItem;
if (ctx.layoutNode.arrayItemType) {
newLayoutNode.arrayItemType = ctx.layoutNode.arrayItemType;
}
else {
delete newLayoutNode.arrayItemType;
}
if (name) {
newLayoutNode.name = name;
newLayoutNode.dataPointer += '/' + JsonPointer.escape(name);
newLayoutNode.options.title = fixTitle(name);
}
// Add the new layoutNode to the form layout
JsonPointer.insert(this.layout, this.getLayoutPointer(ctx), newLayoutNode);
return true;
}
moveArrayItem(ctx, oldIndex, newIndex) {
if (!ctx.layoutNode || !isDefined(ctx.layoutNode.dataPointer) ||
!hasValue(ctx.dataIndex) || !hasValue(ctx.layoutIndex) ||
!isDefined(oldIndex) || !isDefined(newIndex) || oldIndex === newIndex) {
return false;
}
// Move item in the formArray
const formArray = this.getFormControlGroup(ctx);
const arrayItem = formArray.at(oldIndex);
formArray.removeAt(oldIndex);
formArray.insert(newIndex, arrayItem);
formArray.updateValueAndValidity();
// Move layout item
const layoutArray = this.getLayoutArray(ctx);
layoutArray.splice(newIndex, 0, layoutArray.splice(oldIndex, 1)[0]);
return true;
}
removeItem(ctx) {
if (!ctx.layoutNode || !isDefined(ctx.layoutNode.dataPointer) ||
!hasValue(ctx.dataIndex) || !hasValue(ctx.layoutIndex)) {
return false;
}
// Remove the Angular form control from the parent formArray or formGroup
if (ctx.layoutNode.arrayItem) { // Remove array item from formArray
this.getFormControlGroup(ctx)
.removeAt(ctx.dataIndex[ctx.dataIndex.length - 1]);
}
else { // Remove $ref item from formGroup
this.getFormControlGroup(ctx)
.removeControl(this.getFormControlName(ctx));
}
// Remove layoutNode from layout
JsonPointer.remove(this.layout, this.getLayoutPointer(ctx));
return true;
}
};
JsonSchemaFormService = tslib_1.__decorate([
Injectable(),
tslib_1.__metadata("design:paramtypes", [])
], JsonSchemaFormService);
export { JsonSchemaFormService };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbi1zY2hlbWEtZm9ybS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vYW5ndWxhcjYtanNvbi1zY2hlbWEtZm9ybS8iLCJzb3VyY2VzIjpbImxpYi9qc29uLXNjaGVtYS1mb3JtLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sU0FBUyxNQUFNLHFCQUFxQixDQUFDO0FBQzVDLE9BQU8sR0FBRyxNQUFNLEtBQUssQ0FBQztBQUN0QixPQUFPLFVBQVUsTUFBTSx3Q0FBd0MsQ0FBQztBQUVoRSxPQUFPLEVBQ0wsY0FBYyxFQUNkLHNCQUFzQixFQUN0QixjQUFjLEVBQ2QsVUFBVSxFQUNULE1BQU0sK0JBQStCLENBQUM7QUFDekMsT0FBTyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN2RSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN2SCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN2RSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN2RSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN2RSxPQUFPLEVBQ0wsUUFBUSxFQUNSLE9BQU8sRUFDUCxNQUFNLEVBQ04sV0FBVyxFQUNWLE1BQU0sNEJBQTRCLENBQUM7QUFDdEMsT0FBTyxFQUNMLFFBQVEsRUFDUixPQUFPLEVBQ1AsU0FBUyxFQUNULE9BQU8sRUFDUCxRQUFRLEVBQ1AsTUFBTSw4QkFBOEIsQ0FBQztBQUN4QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM3RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBYS9CLElBQWEscUJBQXFCLEdBQWxD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