From 7076343338ae3439f3c86f01144818abe8c31978 Mon Sep 17 00:00:00 2001 From: George Halkiadakis Date: Sun, 12 Mar 2023 07:16:23 +0200 Subject: add container helpers; constuct public directory-tree --- html/content/lib/plugins/plugins.js | 1130 +++++++++++++++++++++++++++++ html/content/lib/plugins/plugins.min.js | 1 + html/content/lib/plugins/plugins.setup.js | 178 +++++ 3 files changed, 1309 insertions(+) create mode 100644 html/content/lib/plugins/plugins.js create mode 100644 html/content/lib/plugins/plugins.min.js create mode 100644 html/content/lib/plugins/plugins.setup.js (limited to 'html/content/lib/plugins') 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; + +})); diff --git a/html/content/lib/plugins/plugins.min.js b/html/content/lib/plugins/plugins.min.js new file mode 100644 index 0000000..81cb4f3 --- /dev/null +++ b/html/content/lib/plugins/plugins.min.js @@ -0,0 +1 @@ +!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define('plugins',e):(n="undefined"!=typeof globalThis?globalThis:n||self).plugins=e()}(this,(function(){"use strict";var n={preconfigure:function(n){return n},filter:function(n){return!0},observeDocument:!0,processInterval:10,idleTimeout:10,cleanupInterval:10,attributeNamePrefix:"data-plugin",lazyLoadRootMargin:"0px 0px 200px 0px",lazyLoadAttribute:"plugins-lazy",shouldLazyLoad:function(n,e,t){return e.lazyLoad||null!==n.getAttribute(t)},ignoreAttribute:"plugins-ignore"},e=function(n,e){var t=n.app,o=function(n){return function(e){return e(n)}},r=0,i=null,u=[],c=function(){return i||(i=u.reduce((function(n,e){var t=e.definition.element,o=n.get(t);return void 0===o&&(o=[]),o.push(e),n.set(t,o),n}),new Map)),i},a=function(n){return{$$uid:++r,$$state:{tearDownHandlers:[],disconnectHandlers:[],connectHandlers:[]},application:t,definition:{type:n.plugin,options:n.options,element:n.element,alias:n.alias},onDestroy:function(n){this.$$state.tearDownHandlers.push(n)},onDisconnect:function(n){this.$$state.disconnectHandlers.push(n)},onConnect:function(n){this.$$state.connectHandlers.push(n)},shouldKeepAlive:n.options&&!!n.options.keepAlive,loaded:!1,destroyed:!1,connected:!1,stateChangedAt:performance.now(),configuration:n.configuration}};function s(n,e){var t=e?n.$$state.connectHandlers:n.$$state.disconnectHandlers;n.connected!==e&&(n.connected=e,n.stateChangedAt=performance.now(),t.forEach(o(n)))}return{register:function(t){var o=a(t);u.push(o);var r=function(e){var t=e.definition.type,o=e.definition.element;return n.moduleLoader.load(t,o).then(r);function r(n){if(void 0===n)return function(n){var e=u.length;for(;e--;)if(n===u[e]){u.splice(e,1);break}}(e),e=null,Promise.reject("plugin "+t+" is undefined");try{return Promise.resolve(n.call(e,o,e.definition.options)).then((function(n){return e.loaded=e.connected=!0,{instance:e,api:n}}))}catch(n){return Promise.reject(n)}}}(o);return e.forEach((function(n){n(o,t,r)})),r.then((function(){i=null})),r.catch((function(n){console&&console.warn("Plugin failed",n)})),r},release:function(n){var e=u.reduce((function(e,t){var r=t.definition.type,i=t.definition.element;if(!t.loaded||t.shouldKeepAlive||t.connected||n&&n(t))return e.instances.push(t),e;!function(n){try{n.destroy&&n.destroy()}catch(e){console&&console.warn("Destroy function of '"+n.definition.type+"' failed. Exception: "+e+". Function: "+n.destroy.toString())}n.$$state.tearDownHandlers.forEach(o(n)),Object.keys(n).forEach((function(e){n[e]=null}))}(t);var u=e.released.get(i);return void 0===u&&(u=[]),u.push(r),e.released.set(i,u),e}),{instances:[],released:new Map});return e.released.size>0&&(i=null),u=e.instances,e.released},disconnect:function(n){var e=c().get(n);e&&e.length&&e.forEach((function(n){s(n,!1)}))},reconnect:function(n,e){var t=c().get(n);if(t&&t.length){var o=t.find((function(n){return n.definition.type===e}));if(o)return void s(o,!0)}console&&console.warn("Could not find a suitable stored plugin instance to reconnect",e,n)},elements:c,instances:function(){return u},inspect:function(){console.table(this.instances())}}};function t(n){var e=new WeakMap,t=n.app;function o(t,o,r){t=t.toLowerCase();var i=e.get(o);if(!(i&&i[t])){i||(i={},e.set(o,i));var u=Promise.resolve(r()).then((function(n){return n&&n.api?(Object.freeze(n.api),n):"***MISSING SCOPE***"})).catch((function(n){console&&console.error("failed to load scope for plugin",t,n)}));i[t]=u.then((function(e){return o===window.document.documentElement&&n.emitter.replay("scope_"+t+":ready",e.api,o,e.instance),e}))}}function r(n,t){var o;for(n=n.toLowerCase();!o&&t;){var r=e.get(t);(o=r&&r[n])||(t=t.parentElement)}return o?o.then((function(n){return{host:t,instance:n.instance,scope:n.api}})):Promise.reject("scope '"+n+"' not found")}t.acquire=function(e){var t;if("string"==typeof e)return o(e);return t=e.map((function(n,e){return o(n)})),Promise.all(t).then((function(n){return e.reduce((function(e,t,o){return e[t]=n[o],e}),{})}));function o(e){return e=e.toLowerCase(),new Promise((function(t,o){n.emitter.once("scope_"+e+":ready",(function(n,e){t(n)}))}))}},t.resolveScope=r,t.scopes=function(){return e},t.configureScope=function(n,e,t){return"function"==typeof e&&(t=e,e=document.documentElement),o(n,e,t)},t.resolve=function(n,e){return this.resolveScope(n,e).then((function(n){return n.scope}))},n.onCreate((function(n,t,i){o((t.alias||t.plugin).toLowerCase(),n.definition.element,(function(){return i})),n.resolve=function(n,e){return this.resolveScope(n,e).then((function(n){return n.scope}))},n.resolveScope=function(e,t){return r(e,t||n.definition.element)},n.onDestroy((function(){var t=e.get(n.definition.element);window.document.contains(n.definition.element)?delete t[n.definition.type]:e.delete(n.definition.element)}))}))}function o(n,e){return function(t,o,r){var i,u,c=this,a=c.$$state.subs,s=r;return"function"!=typeof o&&"function"==typeof r&&(s=o,o=r),s instanceof HTMLElement||s instanceof Window||s instanceof Document?(u=function(){c.connected&&(o.apply(this,arguments),"once"===n&&i())},i=function(){s.removeEventListener(t,u)},s.addEventListener(t,u)):i=e[n](t,(function(){c.connected&&o.apply(c,arguments)})),a.push(i),function(){i(),a.splice(a.indexOf(i),1)}}}function r(n){var e=n.emitter;n.app.on=e.on,n.app.off=e.off,n.app.once=e.once,n.app.emit=e.emit,n.app.replay=e.replay,n.onCreate((function(n){n.$$state.subs=[],n.emit=e.emit,n.on=o("on",e),n.once=o("once",e),n.off=e.off,n.onDestroy((function(){n.$$state.subs.forEach((function(n){return n()})),n.$$state.subs=null}))}))}var i=function(n,e){return e.querySelectorAll(n)};function u(n){n.onCreate((function(n){n.find=function(n){var e=i("[data-ref='"+n+"']",this.definition.element);return e&&e.length?e[0]:null},n.findAll=function(n){return i("[data-ref='"+n+"']",this.definition.element)}}))}function c(n){n.onInitialize((function(n){n.setLogging=function(n,e){localStorage.setItem("plugins.configuration.logging",JSON.stringify(n)),e&&window.location.reload()}})),n.onCreate((function(n,e){var t;e.configuration.logging=(t=localStorage.getItem("plugins.configuration.logging"))&&JSON.parse(t)||null||{},n.logger=function(n,e){function t(t){return t=t||"info",function(){if(e[t]){var o=[n,"=>"].concat(Array.prototype.slice.call(arguments));console&&console[t].apply(null,o)}}}return e=e||{trace:!0,debug:!0,error:!0,info:!0},{info:t("info"),debug:t("debug"),trace:t("trace"),error:t("error")}}("Plugin-"+n.definition.type+" ("+n.$$uid+")",e.configuration.logging)}))}var a=function(){};function s(n,e,t){var o,r,i=this;n=n.bind(i);return t===window.Infinity?(r=l(i.$$state.intervals,(function(){window.clearInterval(o)})),o=window.setInterval((function(){i.connected&&n()===a&&r()}),e)):(t=Math.max(t||1,1),r=l(i.$$state.timers,(function(){window.clearTimeout(o)})),o=window.setTimeout((function(){r(),(!i.connected||n()!==a&&--t>0)&&i.schedule(n,e,t)}),e)),r}function l(n,e){return n.push(e),function(){e(),n.splice(n.indexOf(e),1)}}function f(n){n.onCreate((function(n){n.$$state.timers=[],n.$$state.intervals=[],n.schedule=s.bind(n),n.void=a,n.onDestroy((function(){n.$$state.intervals.concat(n.$$state.timers).forEach((function(n){return n()}))}))}))}function d(n){return(d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(n){return typeof n}:function(n){return n&&"function"==typeof Symbol&&n.constructor===Symbol&&n!==Symbol.prototype?"symbol":typeof n})(n)}function p(n){function e(n){var e,t={name:n,alias:null};return-1!==(e=n.indexOf(":"))&&(t.alias=n.substring(e+1),t.name=n.substring(0,e)),t}function t(o,r){var i,u=[];if(!((i=o)instanceof HTMLElement||"object"===d(i)&&1===i.nodeType&&"object"===d(i.style)&&"object"===d(i.ownerDocument)))return u;if(null!==o.getAttribute(n.ignoreAttribute))return u;if(r&&!r(o))return u;var c=function(t){for(var o=t.attributes,r=[],i=n.attributeNamePrefix+"-",u=0;ut})).forEach((function(n,e){n.forEach((function(n){delete e.initializedPlugins[n]}))}))}}}function v(n){var e=new MutationObserver((function(e,t){e.forEach((function(e,t){var o,r;"childList"===e.type&&(o=e.addedNodes,r=e.removedNodes,n.processor.process(o),n.processor.disconnect(r))}))}));return{start:function(n){e.observe(n,{childList:!0,subtree:!0})},stop:function(){e.disconnect()}}}return{setup:function(o){var i=[t,r,f,u,c],a=[],s=[],l={debug:!1,pluginManager:null},d=function(n,e){var t={},o=e||{},r={},i=function(){};function u(e,t){window.setTimeout((function(){e.apply(n,t)}))}function c(e){var r=t[e]||(t[e]=[]);if(r){var i=Array.prototype.slice.call(arguments,1);o.emitting&&o.emitting({event:e,data:i,context:n});for(var c=0,a=r.length;c