summaryrefslogtreecommitdiff
path: root/html/content/lib/plugins/plugins.js
diff options
context:
space:
mode:
authorGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-12 07:16:23 +0200
committerGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-12 07:16:23 +0200
commit7076343338ae3439f3c86f01144818abe8c31978 (patch)
tree794abb1e6b8f821091fd095341885496b6dad51d /html/content/lib/plugins/plugins.js
parent47cbb529f5723b246125ae083a193e11481b89ef (diff)
downloadclassroom-7076343338ae3439f3c86f01144818abe8c31978.tar.gz
classroom-7076343338ae3439f3c86f01144818abe8c31978.tar.bz2
classroom-7076343338ae3439f3c86f01144818abe8c31978.zip
add container helpers; constuct public directory-tree
Diffstat (limited to 'html/content/lib/plugins/plugins.js')
-rw-r--r--html/content/lib/plugins/plugins.js1130
1 files changed, 1130 insertions, 0 deletions
diff --git a/html/content/lib/plugins/plugins.js b/html/content/lib/plugins/plugins.js
new file mode 100644
index 0000000..c778ed2
--- /dev/null
+++ b/html/content/lib/plugins/plugins.js
@@ -0,0 +1,1130 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define('plugins', factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.plugins = factory());
+})(this, (function () { 'use strict';
+
+ function identity(x) {
+ return x;
+ }
+
+ function alwaysTrue(x) {
+ return true;
+ }
+
+ var config = {
+ preconfigure: identity,
+ filter: alwaysTrue,
+ observeDocument: true,
+ processInterval: 10,
+ idleTimeout: 10,
+ cleanupInterval: 10,
+ attributeNamePrefix: 'data-plugin',
+ lazyLoadRootMargin: '0px 0px 200px 0px',
+ lazyLoadAttribute: 'plugins-lazy',
+ shouldLazyLoad: function shouldLazyLoad(node, pluginOptions, lazyLoadAttribute) {
+ return pluginOptions.lazyLoad || node.getAttribute(lazyLoadAttribute) !== null;
+ },
+ ignoreAttribute: 'plugins-ignore'
+ };
+
+ var create = function create(system, extensions) {
+ var app = system.app;
+
+ var createInvoke = function createInvoke(instance) {
+ return function (f) {
+ return f(instance);
+ };
+ };
+
+ var uid = 0,
+ elementInstancesMap = null,
+ _instances = [];
+
+ var getOrCreateMap = function getOrCreateMap() {
+ if (!elementInstancesMap) {
+ elementInstancesMap = _instances.reduce(function (map, instance) {
+ var elm = instance.definition.element,
+ entry = map.get(elm);
+
+ if (typeof entry === 'undefined') {
+ entry = [];
+ }
+
+ entry.push(instance);
+ map.set(elm, entry);
+ return map;
+ }, new Map());
+ }
+
+ return elementInstancesMap;
+ };
+
+ var registerPlugin = function registerPlugin(context) {
+ var instance = createInstance(context);
+
+ _instances.push(instance);
+
+ var loaded = loadPlugin(instance);
+ extensions.forEach(function (extend) {
+ extend(instance, context, loaded);
+ });
+ loaded.then(function () {
+ elementInstancesMap = null;
+ });
+ loaded["catch"](function (err) {
+ console && console.warn("Plugin failed", err);
+ });
+ return loaded;
+ };
+
+ var createInstance = function createInstance(context) {
+ var instance = {
+ $$uid: ++uid,
+ $$state: {
+ tearDownHandlers: [],
+ disconnectHandlers: [],
+ connectHandlers: []
+ },
+ application: app,
+ definition: {
+ type: context.plugin,
+ options: context.options,
+ element: context.element,
+ alias: context.alias
+ },
+ onDestroy: function onDestroy(h) {
+ this.$$state.tearDownHandlers.push(h);
+ },
+ onDisconnect: function onDisconnect(h) {
+ this.$$state.disconnectHandlers.push(h);
+ },
+ onConnect: function onConnect(h) {
+ this.$$state.connectHandlers.push(h);
+ },
+ shouldKeepAlive: context.options && !!context.options.keepAlive,
+ loaded: false,
+ destroyed: false,
+ connected: false,
+ stateChangedAt: performance.now(),
+ configuration: context.configuration
+ };
+ return instance;
+ };
+
+ function discardInstance(instance) {
+ var i = _instances.length,
+ h;
+
+ while (i--) {
+ h = _instances[i];
+
+ if (instance === h) {
+ _instances.splice(i, 1);
+
+ break;
+ }
+ }
+ }
+
+ function disconnect(element) {
+ var map = getOrCreateMap();
+ var instances = map.get(element);
+
+ if (instances && instances.length) {
+ instances.forEach(function (instance) {
+ setConnected(instance, false);
+ });
+ }
+ }
+
+ function reconnect(element, pluginType) {
+ var map = getOrCreateMap();
+ var instances = map.get(element);
+
+ if (instances && instances.length) {
+ var instance = instances.find(function (i) {
+ return i.definition.type === pluginType;
+ });
+
+ if (instance) {
+ setConnected(instance, true);
+ return;
+ }
+ }
+
+ console && console.warn('Could not find a suitable stored plugin instance to reconnect', pluginType, element);
+ }
+
+ function setConnected(instance, connected) {
+ var handlers = connected ? instance.$$state.connectHandlers : instance.$$state.disconnectHandlers;
+
+ if (instance.connected !== connected) {
+ instance.connected = connected;
+ instance.stateChangedAt = performance.now();
+ handlers.forEach(createInvoke(instance));
+ }
+ }
+
+ function releaseInstance(instance) {
+ try {
+ instance.destroy && instance.destroy();
+ } catch (e) {
+ console && console.warn("Destroy function of '" + instance.definition.type + "' failed. Exception: " + e + ". Function: " + instance.destroy.toString() + "");
+ }
+
+ instance.$$state.tearDownHandlers.forEach(createInvoke(instance));
+ Object.keys(instance).forEach(function (key) {
+ instance[key] = null;
+ });
+ }
+
+ function destroy(shouldSkip) {
+ var result = _instances.reduce(function (state, instance) {
+ var type = instance.definition.type,
+ elm = instance.definition.element;
+
+ if (!instance.loaded || instance.shouldKeepAlive || instance.connected || shouldSkip && shouldSkip(instance)) {
+ state.instances.push(instance);
+ return state;
+ }
+
+ releaseInstance(instance);
+ var entry = state.released.get(elm);
+
+ if (typeof entry === 'undefined') {
+ entry = [];
+ }
+
+ entry.push(type);
+ state.released.set(elm, entry);
+ return state;
+ }, {
+ instances: [],
+ released: new Map()
+ });
+
+ if (result.released.size > 0) {
+ elementInstancesMap = null;
+ }
+
+ _instances = result.instances;
+ return result.released;
+ }
+
+ function loadPlugin(instance) {
+ var pluginType = instance.definition.type,
+ el = instance.definition.element;
+ return system.moduleLoader.load(pluginType, el).then(onLoad);
+
+ function onLoad(plugin) {
+ if (typeof plugin === 'undefined') {
+ discardInstance(instance);
+ instance = null;
+ return Promise.reject('plugin ' + pluginType + ' is undefined');
+ }
+
+ try {
+ return Promise.resolve(plugin.call(instance, el, instance.definition.options)).then(function (pluginApi) {
+ instance.loaded = instance.connected = true;
+ return {
+ instance: instance,
+ api: pluginApi
+ };
+ });
+ } catch (err) {
+ return Promise.reject(err);
+ }
+ }
+ }
+
+ var pluginManager = {
+ register: registerPlugin,
+ release: destroy,
+ disconnect: disconnect,
+ reconnect: reconnect,
+ elements: getOrCreateMap,
+ instances: function instances() {
+ return _instances;
+ },
+ inspect: function inspect() {
+ console.table(this.instances());
+ }
+ };
+ return pluginManager;
+ };
+
+ var pluginManagerFactory = {
+ create: create
+ };
+
+ function emitter(context, options) {
+ var _events = {},
+ o = options || {},
+ _constantEvents = {},
+ noop = function () {};
+
+ function invoke(handler, args) {
+ window.setTimeout(function () {
+ handler.apply(context, args);
+ });
+ }
+
+ function emit(event) {
+ var handlers = _events[event] || (_events[event] = []);
+
+ if (!handlers) {
+ return;
+ }
+
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ if (o.emitting) {
+ o.emitting({
+ event: event,
+ data: args,
+ context: context
+ });
+ }
+
+ for (var i = 0, l = handlers.length; i < l; i++) {
+ invoke(handlers[i], args);
+ }
+ }
+
+ function replay(event) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ _constantEvents[event] = args;
+ emit.apply(null, arguments);
+ }
+
+ function on(event, fn) {
+ if (_constantEvents[event]) {
+ invoke(fn, _constantEvents[event]);
+ return noop;
+ }
+
+ var handlers = _events[event] || (_events[event] = []);
+ handlers.push(fn);
+ return function () {
+ off(event, fn);
+ };
+ }
+
+ function off(event, fn) {
+ var handlers = _events[event],
+ i,
+ h,
+ l;
+
+ if (!handlers) {
+ return;
+ }
+
+ if (Array.isArray(event)) {
+ for (i = 0, l = event.length; i < l; i++) {
+ off(event[i], fn);
+ }
+
+ return;
+ }
+
+ i = handlers.length;
+
+ while (i--) {
+ h = handlers[i];
+
+ if (fn === h) {
+ handlers.splice(i, 1);
+ break;
+ }
+ }
+ }
+
+ function once(event, fn) {
+ var unsub = on(event, function () {
+ fn.apply(context, arguments);
+ unsub();
+ });
+ return unsub;
+ }
+
+ return {
+ on: on,
+ off: off,
+ emit: emit,
+ once: once,
+ replay: replay
+ };
+ }
+
+ function install$4(context) {
+ var scopes = new WeakMap();
+ var app = context.app;
+ app.acquire = acquire;
+ app.resolveScope = get;
+ app.scopes = getAll;
+
+ app.configureScope = function (name, element, registerFn) {
+ if (typeof element === "function") {
+ registerFn = element;
+ element = document.documentElement;
+ }
+
+ return configure(name, element, registerFn);
+ };
+
+ app.resolve = function (name, element) {
+ return this.resolveScope(name, element).then(function (scopeEntry) {
+ return scopeEntry.scope;
+ });
+ };
+
+ context.onCreate(function (instance, creationContext, definitionLoaded) {
+ configure((creationContext.alias || creationContext.plugin).toLowerCase(), instance.definition.element, function () {
+ return definitionLoaded;
+ });
+
+ instance.resolve = function (name, element) {
+ return this.resolveScope(name, element).then(function (scopeEntry) {
+ return scopeEntry.scope;
+ });
+ };
+
+ instance.resolveScope = function (name, element) {
+ return get(name, element || instance.definition.element);
+ };
+
+ instance.onDestroy(function () {
+ var elScopes = scopes.get(instance.definition.element),
+ elementExists = window.document.contains(instance.definition.element);
+
+ if (!elementExists) {
+ scopes["delete"](instance.definition.element);
+ } else {
+ delete elScopes[instance.definition.type];
+ }
+ });
+ });
+
+ function getAll() {
+ return scopes;
+ } //scope creation/configuration
+
+
+ function configure(name, element, provide) {
+ name = name.toLowerCase();
+ var elScopes = scopes.get(element),
+ scope = elScopes && elScopes[name];
+
+ if (!scope) {
+ if (!elScopes) {
+ elScopes = {};
+ scopes.set(element, elScopes);
+ }
+
+ var built = Promise.resolve(provide()).then(function (obj) {
+ if (obj && obj.api) {
+ Object.freeze(obj.api);
+ return obj;
+ } else {
+ return "***MISSING SCOPE***";
+ }
+ })["catch"](function (err) {
+ console && console.error("failed to load scope for plugin", name, err);
+ });
+ elScopes[name] = built.then(function (obj) {
+ if (element === window.document.documentElement) {
+ context.emitter.replay("scope_" + name + ":ready", obj.api, element, obj.instance);
+ }
+
+ return obj;
+ });
+ }
+ } //scope retrieval
+
+
+ function get(name, element) {
+ var scope;
+ name = name.toLowerCase();
+
+ while (!scope && element) {
+ var s = scopes.get(element);
+ scope = s && s[name];
+
+ if (!scope) {
+ element = element.parentElement;
+ }
+ }
+
+ if (scope) {
+ return scope.then(function (resolved) {
+ return {
+ host: element,
+ instance: resolved.instance,
+ scope: resolved.api
+ };
+ });
+ } else {
+ return Promise.reject("scope '" + name + "' not found");
+ }
+ } //retrieving global scopes
+
+
+ function acquire(scopes) {
+ var loadScopes;
+
+ if (typeof scopes === "string") {
+ return waitForScope(scopes);
+ }
+
+ loadScopes = scopes.map(function (s, i) {
+ return waitForScope(s);
+ });
+ return Promise.all(loadScopes).then(function (values) {
+ return scopes.reduce(function (resolved, prop, index) {
+ resolved[prop] = values[index];
+ return resolved;
+ }, {});
+ });
+
+ function waitForScope(s) {
+ s = s.toLowerCase();
+ return new Promise(function (resolve, reject) {
+ context.emitter.once("scope_" + s + ":ready", function (scope, element) {
+ resolve(scope);
+ });
+ });
+ }
+ }
+ }
+
+ function subscribe(method, eventsEmitter) {
+ return function (event, fn, eventSource) {
+ var plugin = this,
+ subs = plugin.$$state.subs,
+ unsub,
+ eventTarget = eventSource,
+ handler;
+
+ if (typeof fn !== "function" && typeof eventSource === "function") {
+ eventTarget = fn;
+ fn = eventSource;
+ }
+
+ if (eventTarget instanceof HTMLElement || eventTarget instanceof Window || eventTarget instanceof Document) {
+ handler = function handler() {
+ if (!plugin.connected) {
+ return;
+ }
+
+ fn.apply(this, arguments);
+
+ if (method === "once") {
+ unsub();
+ }
+ };
+
+ unsub = function unsub() {
+ eventTarget.removeEventListener(event, handler);
+ };
+
+ eventTarget.addEventListener(event, handler);
+ } else {
+ unsub = eventsEmitter[method](event, function () {
+ if (!plugin.connected) {
+ return;
+ }
+
+ fn.apply(plugin, arguments);
+ });
+ }
+
+ subs.push(unsub);
+ return function () {
+ unsub();
+ subs.splice(subs.indexOf(unsub), 1);
+ };
+ };
+ }
+
+ function install$3(context) {
+ var eventsEmitter = context.emitter;
+ context.app.on = eventsEmitter.on;
+ context.app.off = eventsEmitter.off;
+ context.app.once = eventsEmitter.once;
+ context.app.emit = eventsEmitter.emit;
+ context.app.replay = eventsEmitter.replay;
+ context.onCreate(function (instance) {
+ instance.$$state.subs = [];
+ instance.emit = eventsEmitter.emit;
+ instance.on = subscribe("on", eventsEmitter);
+ instance.once = subscribe("once", eventsEmitter);
+ instance.off = eventsEmitter.off;
+ instance.onDestroy(function () {
+ instance.$$state.subs.forEach(function (f) {
+ return f();
+ });
+ instance.$$state.subs = null;
+ });
+ });
+ }
+
+ var find = function find(selector, element) {
+ return element.querySelectorAll(selector);
+ };
+
+ function install$2(context) {
+ context.onCreate(function (instance) {
+ instance.find = function (key) {
+ var results = find("[data-ref='" + key + "']", this.definition.element);
+
+ if (results && results.length) {
+ return results[0];
+ }
+
+ return null;
+ }, instance.findAll = function (key) {
+ return find("[data-ref='" + key + "']", this.definition.element);
+ };
+ });
+ }
+
+ //logging factory for creating a simple configurable logger
+ function logger(name, options) {
+ options = options || {
+ trace: true,
+ debug: true,
+ error: true,
+ info: true
+ };
+
+ function logging(method) {
+ method = method || "info";
+ return function () {
+ if (options[method]) {
+ var args = [name, "=>"].concat(Array.prototype.slice.call(arguments));
+ console && console[method].apply(null, args);
+ }
+ };
+ }
+
+ return {
+ info: logging("info"),
+ debug: logging("debug"),
+ trace: logging("trace"),
+ error: logging("error")
+ };
+ }
+
+ var readConfig = function readConfig() {
+ var loggingConfigString = localStorage.getItem("plugins.configuration.logging");
+ return loggingConfigString && JSON.parse(loggingConfigString) || null;
+ };
+
+ function install$1(context) {
+ context.onInitialize(function (app) {
+ app.setLogging = function (options, reload) {
+ localStorage.setItem("plugins.configuration.logging", JSON.stringify(options));
+
+ if (reload) {
+ window.location.reload();
+ }
+ };
+ });
+ context.onCreate(function (instance, registrationCtx) {
+ registrationCtx.configuration.logging = readConfig() || {};
+ instance.logger = logger("Plugin-" + instance.definition.type + " (" + instance.$$uid + ")", registrationCtx.configuration.logging);
+ });
+ }
+
+ var _void = function _void() {}; //setTimeout - setInterval with managed timers
+
+
+ function schedule(fn, ms, times) {
+ var plugin = this,
+ timer,
+ fn = fn.bind(plugin),
+ release;
+
+ if (times === window.Infinity) {
+ release = createReleaser(plugin.$$state.intervals, function () {
+ window.clearInterval(timer);
+ });
+ timer = window.setInterval(function () {
+ if (plugin.connected && fn() === _void) {
+ release();
+ }
+ }, ms);
+ } else {
+ times = Math.max(times || 1, 1);
+ release = createReleaser(plugin.$$state.timers, function () {
+ window.clearTimeout(timer);
+ });
+ timer = window.setTimeout(function () {
+ release();
+
+ if (!plugin.connected || fn() !== _void && --times > 0) {
+ plugin.schedule(fn, ms, times);
+ }
+ }, ms);
+ }
+
+ return release;
+ }
+
+ function createReleaser(store, release) {
+ store.push(release);
+ return function () {
+ release();
+ store.splice(store.indexOf(release), 1);
+ };
+ }
+
+ function install(context) {
+ context.onCreate(function (instance) {
+ instance.$$state.timers = [];
+ instance.$$state.intervals = [];
+ instance.schedule = schedule.bind(instance);
+ instance["void"] = _void;
+ instance.onDestroy(function () {
+ instance.$$state.intervals.concat(instance.$$state.timers).forEach(function (f) {
+ return f();
+ });
+ });
+ });
+ }
+
+ function _typeof(obj) {
+ "@babel/helpers - typeof";
+
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+ _typeof = function (obj) {
+ return typeof obj;
+ };
+ } else {
+ _typeof = function (obj) {
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+ };
+ }
+
+ return _typeof(obj);
+ }
+
+ function createScanner(options) {
+
+ function parseNameToken(name) {
+ var token = {
+ name: name,
+ alias: null
+ },
+ index;
+
+ if ((index = name.indexOf(":")) !== -1) {
+ token.alias = name.substring(index + 1);
+ token.name = name.substring(0, index);
+ }
+
+ return token;
+ }
+
+ function pluginsAccessor(node) {
+ var attrs = node.attributes,
+ plugins = [],
+ attributeNamePrefix = options.attributeNamePrefix + "-";
+
+ for (var i = 0; i < node.attributes.length; i++) {
+ var attr = attrs[i];
+
+ if (attr.name.indexOf(attributeNamePrefix) === 0) {
+ var token = parseNameToken(attr.name.substring(attributeNamePrefix.length));
+ plugins.push({
+ node: node,
+ name: token.name,
+ alias: token.alias,
+ options: attr.value
+ });
+ }
+ }
+
+ return plugins;
+ }
+
+ function isElement(obj) {
+ //instanceof fails for elements that have been created by another document (iframe case)
+ //in that case we check other properties existing in all element nodes
+ return obj instanceof HTMLElement || _typeof(obj) === "object" && obj.nodeType === 1 && _typeof(obj.style) === "object" && _typeof(obj.ownerDocument) === "object";
+ }
+
+ function discoverPlugins(node, predicate) {
+ var collection = [];
+
+ if (!isElement(node)) {
+ return collection;
+ } // if (processed.has(node)) {
+ // return collection;
+ // }
+ // processed.add(node);
+
+
+ if (node.getAttribute(options.ignoreAttribute) !== null) {
+ return collection;
+ }
+
+ if (predicate && !predicate(node)) {
+ return collection;
+ }
+
+ var plugins = pluginsAccessor(node);
+
+ if (plugins.length) {
+ collection = plugins;
+ }
+
+ if (node.children) {
+ Array.prototype.forEach.call(node.children, function (e) {
+ collection = collection.concat(discoverPlugins(e, predicate));
+ });
+ }
+
+ return collection;
+ }
+
+ var scan = function scan(container) {
+ return discoverPlugins(container, options.filter);
+ };
+
+ return {
+ scan: scan //processed
+
+ };
+ }
+
+ function createProcessor(context, options) {
+ var onRegister = options.onRegister || function (ctx) {
+ return ctx;
+ };
+
+ var intersectionMargins = options.lazyLoadRootMargin || '0px 0px 200px 0px';
+ var shouldLazyLoad = options.shouldLazyLoad;
+ var deferred = new WeakMap();
+ var observer = new IntersectionObserver(function (entries, obs) {
+ entries.forEach(function (entry) {
+ var node = entry.target;
+
+ if (entry.isIntersecting && deferred.has(node)) {
+ var pluginsContexts = deferred.get(node);
+ pluginsContexts.forEach(function (ctx) {
+ registerContext(ctx);
+ });
+ deferred["delete"](node);
+ obs.unobserve(node);
+ }
+ });
+ }, {
+ rootMargin: intersectionMargins,
+ threshold: 0
+ });
+ var pendingForInitialization = [];
+
+ function processInit() {
+ var results = [];
+
+ if (pendingForInitialization.length) {
+ pendingForInitialization.reduce(function (acc, definition) {
+ acc.push(initialize(definition));
+ return acc;
+ }, results);
+ pendingForInitialization = [];
+ }
+
+ return results;
+ }
+
+ function setDeferred(node, pluginContext) {
+ var nodeDeferreds;
+
+ if (!deferred.has(node)) {
+ deferred.set(node, nodeDeferreds = []);
+ } else {
+ nodeDeferreds = deferred.get(node);
+ }
+
+ nodeDeferreds.push(pluginContext);
+ }
+
+ function initialize(definition) {
+ var node = definition.node,
+ name = definition.name,
+ initialized = node.initializedPlugins = node.initializedPlugins || {},
+ result;
+
+ if (typeof name === 'undefined') {
+ return Promise.resolve(true);
+ }
+
+ if (!initialized[name]) {
+ var pluginOptions = parseOptions(definition.options, node),
+ ctx = {
+ element: node,
+ alias: definition.alias,
+ plugin: name,
+ options: pluginOptions,
+ configuration: {}
+ };
+ initialized[name] = 'INIT';
+
+ if (shouldLazyLoad(node, pluginOptions, options.lazyLoadAttribute)) {
+ setDeferred(node, ctx);
+ observer.observe(node);
+ return Promise.resolve(true);
+ } else {
+ result = registerContext(ctx);
+ }
+
+ return result;
+ } else if (initialized[name] === 'ON') {
+ context.pluginManager.reconnect(node, name);
+ }
+
+ return Promise.resolve(true);
+ }
+
+ function registerContext(ctx) {
+ return Promise.resolve(onRegister(ctx)).then(function () {
+ return context.pluginManager.register(ctx);
+ }).then(function () {
+ ctx.element.initializedPlugins[ctx.plugin] = "ON";
+ });
+ }
+
+ function register(el, alias, pluginName, pluginConfiguration) {
+ var ctx = {
+ element: el,
+ alias: alias,
+ plugin: pluginName,
+ options: pluginConfiguration,
+ configuration: {}
+ };
+ return registerContext(ctx);
+ }
+
+ var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/;
+
+ function parseOptions(data, element) {
+ if (data === "true") {
+ return true;
+ }
+
+ if (data === "false") {
+ return false;
+ }
+
+ if (data === "null") {
+ return null;
+ } // Only convert to a number if it doesn't change the string
+
+
+ if (data === +data + "") {
+ return +data;
+ }
+
+ if (rbrace.test(data)) {
+ return tryParseJson(data, element);
+ }
+
+ return data;
+ }
+
+ function tryParseJson(json, element) {
+ try {
+ return JSON.parse(json);
+ } catch (err) {
+ console.warn(element, 'error during parsing of json', json, err);
+ return json;
+ }
+ }
+
+ var processTask;
+ return {
+ initialize: register,
+ process: function process(nodes) {
+ if (!pendingForInitialization.length) {
+ processTask = new Promise(function (resolve) {
+ window.setTimeout(function () {
+ Promise.all(processInit()).then(resolve);
+ }, options.processInterval);
+ });
+ }
+
+ nodes.forEach(function (node) {
+ context.emitter.emit("plugins:initializing", node);
+ var plugins = context.scanner.scan(node);
+ pendingForInitialization = pendingForInitialization.concat(plugins);
+ processTask.then(function () {
+ context.emitter.emit("plugins:loaded", node);
+ });
+ });
+ return processTask;
+ },
+ disconnect: function disconnect(nodes) {
+ var _this = this;
+
+ Array.prototype.forEach.call(nodes, function (element) {
+ context.pluginManager.disconnect(element); // context.scanner.processed.delete(element);
+ // var parent = element.parentElement;
+ // while (parent !== null) {
+ // context.scanner.processed["delete"](parent);
+ // parent = parent.parentElement;
+ // }
+
+ element.children && _this.disconnect(element.children);
+ });
+ },
+ cleanup: function cleanup() {
+ var now = performance.now();
+ var released = context.pluginManager.release(function (i) {
+ return i.stateChangedAt + options.idleTimeout * 1000 > now;
+ });
+ released.forEach(function (instances, element) {
+ instances.forEach(function (type) {
+ delete element.initializedPlugins[type]; //context.scanner.processed.delete(element);
+ });
+ });
+ }
+ };
+ }
+
+ function createObserver(context) {
+ var observer = new MutationObserver(function (mutations, obs) {
+ mutations.forEach(function (mutation, index) {
+ if (mutation.type === 'childList') {
+ processNodes(mutation.addedNodes, mutation.removedNodes);
+ }
+ });
+ });
+
+ function processNodes(added, removed) {
+ context.processor.process(added);
+ context.processor.disconnect(removed);
+ }
+
+ return {
+ start: function start(node) {
+ observer.observe(node, {
+ childList: true,
+ subtree: true
+ });
+ },
+ stop: function stop() {
+ observer.disconnect();
+ }
+ };
+ }
+
+ var setup = function setup(options) {
+ var componentInstallers = [install$4, install$3, install, install$2, install$1],
+ pluginsExtensions = [],
+ systemExtensions = [],
+ app = {
+ debug: false,
+ pluginManager: null
+ },
+ systemEmitter = emitter(app);
+ Object.keys(config).forEach(function (key) {
+ if (typeof options[key] === 'undefined') {
+ options[key] = config[key];
+ }
+ });
+ var context = {
+ moduleLoader: null,
+ onCreate: function onCreate(fn) {
+ pluginsExtensions.push(fn);
+ },
+ onInitialize: function onInitialize(fn) {
+ systemExtensions.push(fn);
+ },
+ emitter: systemEmitter,
+ app: app,
+ scanner: null,
+ processor: null,
+ observer: null,
+ pluginManager: null
+ };
+ context.scanner = createScanner(config);
+ context.processor = createProcessor(context, {
+ processInterval: config.processInterval,
+ idleTimeout: config.idleTimeout,
+ onRegister: config.preconfigure,
+ lazyLoadRootMargin: config.lazyLoadRootMargin,
+ lazyLoadAttribute: config.lazyLoadAttribute,
+ shouldLazyLoad: config.shouldLazyLoad
+ });
+ context.observer = createObserver(context);
+ componentInstallers.forEach(function (f) {
+ return f(context);
+ });
+ app.pluginManager = context.pluginManager = pluginManagerFactory.create(context, pluginsExtensions);
+ var initialized = false,
+ cleanTimer,
+ plugins = {};
+ return {
+ use: function use(install) {
+ install(context);
+ },
+ initialize: initialize
+ };
+
+ function enableCleanup() {
+ if (!cleanTimer) {
+ cleanTimer = window.setInterval(context.processor.cleanup, config.cleanupInterval);
+ }
+ }
+
+ function disableCleanup() {
+ window.clearInterval(cleanTimer);
+ cleanTimer = null;
+ }
+
+ function setupSystem() {
+ var api = {
+ enableCleanup: enableCleanup,
+ disableCleanup: disableCleanup,
+ observer: context.observer,
+ processor: context.processor,
+ application: app
+ };
+ systemExtensions.forEach(function (extend) {
+ extend(api);
+ });
+ return api;
+ }
+
+ function run() {
+ context.processor.process([document.querySelector("body")]);
+ enableCleanup();
+
+ if (config.observeDocument && context.observer) {
+ context.observer.start(document);
+ }
+ }
+
+ function initialize() {
+ if (initialized) {
+ return plugins;
+ }
+
+ initialized = true;
+ plugins = setupSystem();
+ run();
+ return plugins;
+ }
+ };
+
+ var main = {
+ setup: setup
+ };
+
+ return main;
+
+}));