|
|
|
/*
|
|
|
|
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
|
|
|
|
if you want to view the source visit the plugins github repository
|
|
|
|
*/
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var obsidian = require('obsidian');
|
|
|
|
|
|
|
|
/*! *****************************************************************************
|
|
|
|
Copyright (c) Microsoft Corporation.
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
purpose with or without fee is hereby granted.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
|
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
|
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
|
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
|
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
***************************************************************************** */
|
|
|
|
|
|
|
|
function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
|
|
|
|
|
|
function createCommonjsModule(fn) {
|
|
|
|
var module = { exports: {} };
|
|
|
|
return fn(module, module.exports), module.exports;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* global define */
|
|
|
|
|
|
|
|
var compareVersions = createCommonjsModule(function (module, exports) {
|
|
|
|
(function (root, factory) {
|
|
|
|
/* istanbul ignore next */
|
|
|
|
{
|
|
|
|
module.exports = factory();
|
|
|
|
}
|
|
|
|
}(commonjsGlobal, function () {
|
|
|
|
|
|
|
|
var semver = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
|
|
|
|
|
|
|
|
function indexOrEnd(str, q) {
|
|
|
|
return str.indexOf(q) === -1 ? str.length : str.indexOf(q);
|
|
|
|
}
|
|
|
|
|
|
|
|
function split(v) {
|
|
|
|
var c = v.replace(/^v/, '').replace(/\+.*$/, '');
|
|
|
|
var patchIndex = indexOrEnd(c, '-');
|
|
|
|
var arr = c.substring(0, patchIndex).split('.');
|
|
|
|
arr.push(c.substring(patchIndex + 1));
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
function tryParse(v) {
|
|
|
|
return isNaN(Number(v)) ? v : Number(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
function validate(version) {
|
|
|
|
if (typeof version !== 'string') {
|
|
|
|
throw new TypeError('Invalid argument expected string');
|
|
|
|
}
|
|
|
|
if (!semver.test(version)) {
|
|
|
|
throw new Error('Invalid argument not valid semver (\''+version+'\' received)');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function compareVersions(v1, v2) {
|
|
|
|
[v1, v2].forEach(validate);
|
|
|
|
|
|
|
|
var s1 = split(v1);
|
|
|
|
var s2 = split(v2);
|
|
|
|
|
|
|
|
for (var i = 0; i < Math.max(s1.length - 1, s2.length - 1); i++) {
|
|
|
|
var n1 = parseInt(s1[i] || 0, 10);
|
|
|
|
var n2 = parseInt(s2[i] || 0, 10);
|
|
|
|
|
|
|
|
if (n1 > n2) return 1;
|
|
|
|
if (n2 > n1) return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
var sp1 = s1[s1.length - 1];
|
|
|
|
var sp2 = s2[s2.length - 1];
|
|
|
|
|
|
|
|
if (sp1 && sp2) {
|
|
|
|
var p1 = sp1.split('.').map(tryParse);
|
|
|
|
var p2 = sp2.split('.').map(tryParse);
|
|
|
|
|
|
|
|
for (i = 0; i < Math.max(p1.length, p2.length); i++) {
|
|
|
|
if (p1[i] === undefined || typeof p2[i] === 'string' && typeof p1[i] === 'number') return -1;
|
|
|
|
if (p2[i] === undefined || typeof p1[i] === 'string' && typeof p2[i] === 'number') return 1;
|
|
|
|
|
|
|
|
if (p1[i] > p2[i]) return 1;
|
|
|
|
if (p2[i] > p1[i]) return -1;
|
|
|
|
}
|
|
|
|
} else if (sp1 || sp2) {
|
|
|
|
return sp1 ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
var allowedOperators = [
|
|
|
|
'>',
|
|
|
|
'>=',
|
|
|
|
'=',
|
|
|
|
'<',
|
|
|
|
'<='
|
|
|
|
];
|
|
|
|
|
|
|
|
var operatorResMap = {
|
|
|
|
'>': [1],
|
|
|
|
'>=': [0, 1],
|
|
|
|
'=': [0],
|
|
|
|
'<=': [-1, 0],
|
|
|
|
'<': [-1]
|
|
|
|
};
|
|
|
|
|
|
|
|
function validateOperator(op) {
|
|
|
|
if (typeof op !== 'string') {
|
|
|
|
throw new TypeError('Invalid operator type, expected string but got ' + typeof op);
|
|
|
|
}
|
|
|
|
if (allowedOperators.indexOf(op) === -1) {
|
|
|
|
throw new TypeError('Invalid operator, expected one of ' + allowedOperators.join('|'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
compareVersions.validate = function(version) {
|
|
|
|
return typeof version === 'string' && semver.test(version);
|
|
|
|
};
|
|
|
|
|
|
|
|
compareVersions.compare = function (v1, v2, operator) {
|
|
|
|
// Validate operator
|
|
|
|
validateOperator(operator);
|
|
|
|
|
|
|
|
// since result of compareVersions can only be -1 or 0 or 1
|
|
|
|
// a simple map can be used to replace switch
|
|
|
|
var res = compareVersions(v1, v2);
|
|
|
|
return operatorResMap[operator].indexOf(res) > -1;
|
|
|
|
};
|
|
|
|
|
|
|
|
return compareVersions;
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
const DEFAULT_SETTINGS = {
|
|
|
|
jsFiles: '',
|
|
|
|
jsFolder: '',
|
|
|
|
};
|
|
|
|
class CustomJS extends obsidian.Plugin {
|
|
|
|
onload() {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
console.log('Loading CustomJS');
|
|
|
|
yield this.loadSettings();
|
|
|
|
this.registerEvent(this.app.vault.on('modify', this.reloadIfNeeded, this));
|
|
|
|
// @ts-ignore
|
|
|
|
window.forceLoadCustomJS = () => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
yield this.loadClasses();
|
|
|
|
});
|
|
|
|
this.app.workspace.onLayoutReady(() => {
|
|
|
|
this.loadClasses();
|
|
|
|
});
|
|
|
|
this.addSettingTab(new CustomJSSettingsTab(this.app, this));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
onunload() {
|
|
|
|
// @ts-ignore
|
|
|
|
delete window.customJS;
|
|
|
|
}
|
|
|
|
reloadIfNeeded(f) {
|
|
|
|
var _a, _b, _c, _d, _e;
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
if (f.path.endsWith('.js')) {
|
|
|
|
yield this.loadClasses();
|
|
|
|
// reload dataviewjs blocks if installed & version >= 0.4.11
|
|
|
|
if (this.app.plugins.enabledPlugins.has("dataview")) {
|
|
|
|
// @ts-ignore
|
|
|
|
const version = (_b = (_a = this.app.plugins.plugins) === null || _a === void 0 ? void 0 : _a.dataview) === null || _b === void 0 ? void 0 : _b.manifest.version;
|
|
|
|
if (compareVersions(version, '0.4.11') < 0)
|
|
|
|
return;
|
|
|
|
(_e = (_d = (_c = this.app.plugins.plugins.dataview) === null || _c === void 0 ? void 0 : _c.api) === null || _d === void 0 ? void 0 : _d.index) === null || _e === void 0 ? void 0 : _e.touch();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
loadSettings() {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
const settings = yield this.loadData();
|
|
|
|
this.settings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), settings);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
saveSettings() {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
yield this.saveData(this.settings);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
evalFile(f, customjs) {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
try {
|
|
|
|
const file = yield this.app.vault.adapter.read(f);
|
|
|
|
const def = eval('(' + file + ')');
|
|
|
|
const cls = new def();
|
|
|
|
customjs[cls.constructor.name] = cls;
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
console.error(`CustomJS couldn\'t import ${f}`);
|
|
|
|
console.error(e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
loadClasses() {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
const customjs = {};
|
|
|
|
const filesToLoad = [];
|
|
|
|
// Get individual paths
|
|
|
|
if (this.settings.jsFiles != '') {
|
|
|
|
const individualFiles = this.settings.jsFiles.split(',').map(s => s.trim()).sort();
|
|
|
|
for (const f of individualFiles) {
|
|
|
|
if (f != '' && f.endsWith('.js')) {
|
|
|
|
filesToLoad.push(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Get paths in folder
|
|
|
|
if (this.settings.jsFolder != '') {
|
|
|
|
const prefix = this.settings.jsFolder;
|
|
|
|
const files = this.app.vault.getFiles();
|
|
|
|
const scripts = files.filter(f => f.path.startsWith(prefix) && f.path.endsWith('.js'));
|
|
|
|
for (const s of scripts) {
|
|
|
|
if (s.path != '' && s.path.endsWith('.js')) {
|
|
|
|
filesToLoad.push(s.path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.sortByFileName(filesToLoad);
|
|
|
|
// load all scripts
|
|
|
|
for (const f of filesToLoad) {
|
|
|
|
yield this.evalFile(f, customjs);
|
|
|
|
}
|
|
|
|
// @ts-ignore
|
|
|
|
window.customJS = customjs;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
sortByFileName(files) {
|
|
|
|
files.sort((a, b) => {
|
|
|
|
const nameA = a.split('/').last();
|
|
|
|
const nameB = b.split('/').last();
|
|
|
|
return nameA.localeCompare(nameB);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
class CustomJSSettingsTab extends obsidian.PluginSettingTab {
|
|
|
|
constructor(app, plugin) {
|
|
|
|
super(app, plugin);
|
|
|
|
this.plugin = plugin;
|
|
|
|
}
|
|
|
|
display() {
|
|
|
|
let { containerEl } = this;
|
|
|
|
containerEl.empty();
|
|
|
|
containerEl.createEl('h2', { text: 'CustomJS' });
|
|
|
|
// individual files
|
|
|
|
new obsidian.Setting(containerEl)
|
|
|
|
.setName('Individual files')
|
|
|
|
.setDesc('Comma-separated list of files to load')
|
|
|
|
.addText(text => text
|
|
|
|
.setPlaceholder('jsfile1.js,jsfile2.js')
|
|
|
|
.setValue(this.plugin.settings.jsFiles)
|
|
|
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
this.plugin.settings.jsFiles = value;
|
|
|
|
yield this.plugin.saveSettings();
|
|
|
|
yield this.plugin.loadClasses();
|
|
|
|
})));
|
|
|
|
// folder
|
|
|
|
new obsidian.Setting(containerEl)
|
|
|
|
.setName('Folder')
|
|
|
|
.setDesc('Path to folder containing JS files to load')
|
|
|
|
.addText(text => text
|
|
|
|
.setPlaceholder('js/scripts')
|
|
|
|
.setValue(this.plugin.settings.jsFolder)
|
|
|
|
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
this.plugin.settings.jsFolder = value;
|
|
|
|
yield this.plugin.saveSettings();
|
|
|
|
yield this.plugin.loadClasses();
|
|
|
|
})));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = CustomJS;
|
|
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsiLi4vbm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIi4uL25vZGVfbW9kdWxlcy9jb21wYXJlLXZlcnNpb25zL2luZGV4LmpzIiwiLi4vbWFpbi50cyJdLCJzb3VyY2VzQ29udGVudCI6bnVsbCwibmFtZXMiOlsidGhpcyIsIlBsdWdpbiIsIlBsdWdpblNldHRpbmdUYWIiLCJTZXR0aW5nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBdURBO0FBQ08sU0FBUyxTQUFTLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFO0FBQzdELElBQUksU0FBUyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsT0FBTyxLQUFLLFlBQVksQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFO0FBQ2hILElBQUksT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFO0FBQy9ELFFBQVEsU0FBUyxTQUFTLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUNuRyxRQUFRLFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUN0RyxRQUFRLFNBQVMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRTtBQUN0SCxRQUFRLElBQUksQ0FBQyxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxVQUFVLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUM5RSxLQUFLLENBQUMsQ0FBQztBQUNQOzs7Ozs7Ozs7Ozs7QUM1RUEsQ0FBQyxVQUFVLElBQUksRUFBRSxPQUFPLEVBQUU7QUFDMUI7QUFDQSxFQUUwQztBQUMxQyxJQUFJLGlCQUFpQixPQUFPLEVBQUUsQ0FBQztBQUMvQixHQUVHO0FBQ0gsQ0FBQyxDQUFDQSxjQUFJLEVBQUUsWUFBWTtBQUNwQjtBQUNBLEVBQUUsSUFBSSxNQUFNLEdBQUcsb0lBQW9JLENBQUM7QUFDcEo7QUFDQSxFQUFFLFNBQVMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUU7QUFDOUIsSUFBSSxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQy9ELEdBQUc7QUFDSDtBQUNBLEVBQUUsU0FBUyxLQUFLLENBQUMsQ0FBQyxFQUFFO0FBQ3BCLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNyRCxJQUFJLElBQUksVUFBVSxHQUFHLFVBQVUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDeEMsSUFBSSxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDcEQsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDMUMsSUFBSSxPQUFPLEdBQUcsQ0FBQztBQUNmLEdBQUc7QUFDSDtBQUNBLEVBQUUsU0FBUyxRQUFRLENBQUMsQ0FBQyxFQUFFO0FBQ3ZCLElBQUksT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUM1QyxHQUFHO0FBQ0g7QUFDQSxFQUFFLFNBQVMsUUFBUSxDQUFDLE9BQU8sRUFBRTtBQUM3QixJQUFJLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFO0FBQ3JDLE1BQU0sTUFBTSxJQUFJLFNBQVMsQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO0FBQzlELEtBQUs7QUFDTCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFO0FBQy9CLE1BQU0sTUFBTSxJQUFJLEtBQUssQ0FBQyx1Q0FBdUMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7QUFDdEYsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBLEVBQUUsU0FBUyxlQUFlLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRTtBQUNuQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUMvQjtBQUNBLElBQUksSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3ZCLElBQUksSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3ZCO0FBQ0EsSUFBSSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0FBQ3JFLE1BQU0sSUFBSSxFQUFFLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDeEMsTUFBTSxJQUFJLEVBQUUsR0FBRyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUN4QztBQUN
|