exhibitionjs 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Exhibition.d.ts +34 -24
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/utils.d.ts +1 -0
- package/package.json +5 -5
package/dist/Exhibition.d.ts
CHANGED
|
@@ -14,21 +14,34 @@ export type ExhibitionInitOptions = {
|
|
|
14
14
|
init?: boolean;
|
|
15
15
|
updatePreview?: boolean;
|
|
16
16
|
};
|
|
17
|
-
export type
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
export type MapConfiguration = {
|
|
18
|
+
editors: {
|
|
19
|
+
selector?: string;
|
|
20
|
+
Class: Constructable<DocumentAltererProviderWraplet>;
|
|
21
|
+
args?: unknown[];
|
|
22
|
+
};
|
|
23
|
+
preview: {
|
|
24
|
+
selector?: string;
|
|
25
|
+
Class: Constructable<PreviewWraplet>;
|
|
26
|
+
args?: unknown[];
|
|
27
|
+
};
|
|
21
28
|
};
|
|
22
|
-
export type
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
export type DefaultMapConfiguration = {
|
|
30
|
+
editors: {
|
|
31
|
+
selector?: string;
|
|
32
|
+
options: ExhibitionMonacoEditorOptions;
|
|
33
|
+
optionsStorage?: KeyValueStorage<Partial<ExhibitionMonacoEditorOptions>>;
|
|
34
|
+
};
|
|
35
|
+
preview?: {
|
|
36
|
+
selector?: string;
|
|
37
|
+
options?: ExhibitionPreviewOptions;
|
|
38
|
+
optionsStorage?: KeyValueStorage<ExhibitionPreviewOptions>;
|
|
39
|
+
};
|
|
26
40
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
declare const ExhibitionMap: {
|
|
41
|
+
/**
|
|
42
|
+
* This is a factory function that creates a new map each time it's run.
|
|
43
|
+
*/
|
|
44
|
+
declare function createMap(configuration: MapConfiguration): {
|
|
32
45
|
editors: {
|
|
33
46
|
selector: string | undefined;
|
|
34
47
|
multiple: true;
|
|
@@ -37,17 +50,17 @@ declare const ExhibitionMap: {
|
|
|
37
50
|
args: unknown[];
|
|
38
51
|
};
|
|
39
52
|
preview: {
|
|
40
|
-
selector: string;
|
|
53
|
+
selector: string | undefined;
|
|
41
54
|
multiple: false;
|
|
42
55
|
required: true;
|
|
43
56
|
Class: Constructable<PreviewWraplet>;
|
|
44
57
|
args: unknown[];
|
|
45
58
|
};
|
|
46
59
|
};
|
|
47
|
-
export declare class Exhibition extends AbstractWraplet<HTMLElement, typeof
|
|
60
|
+
export declare class Exhibition extends AbstractWraplet<HTMLElement, ReturnType<typeof createMap>> {
|
|
48
61
|
private status;
|
|
49
62
|
private options;
|
|
50
|
-
constructor(core: Core<HTMLElement, typeof
|
|
63
|
+
constructor(core: Core<HTMLElement, ReturnType<typeof createMap>>, options?: ExhibitionOptions, optionsStorage?: KeyValueStorage<Partial<ExhibitionOptions>>);
|
|
51
64
|
protected supportedNodeTypes(): readonly Constructable<HTMLElement>[];
|
|
52
65
|
initialize(): Promise<void>;
|
|
53
66
|
/**
|
|
@@ -79,7 +92,7 @@ export declare class Exhibition extends AbstractWraplet<HTMLElement, typeof Exhi
|
|
|
79
92
|
*
|
|
80
93
|
* @returns Array of Exhibition instances.
|
|
81
94
|
*/
|
|
82
|
-
static createMultiple<M extends typeof
|
|
95
|
+
static createMultiple<M extends ReturnType<typeof createMap> = ReturnType<typeof createMap>>(node: ParentNode, map: M, options?: ExhibitionOptions, initOptions?: ExhibitionInitOptions, attribute?: string): Promise<Exhibition[]>;
|
|
83
96
|
/**
|
|
84
97
|
* Create a single Exhibition instance wrapping a given element.
|
|
85
98
|
*
|
|
@@ -88,7 +101,7 @@ export declare class Exhibition extends AbstractWraplet<HTMLElement, typeof Exhi
|
|
|
88
101
|
* @param options Options for the Exhibition instance.
|
|
89
102
|
* @param initOptions Options related to the creation process of the Exhibitions.
|
|
90
103
|
*/
|
|
91
|
-
static create<M extends typeof
|
|
104
|
+
static create<M extends ReturnType<typeof createMap> = ReturnType<typeof createMap>>(element: HTMLElement, map: M, options?: ExhibitionOptions, initOptions?: ExhibitionInitOptions): Promise<Exhibition>;
|
|
92
105
|
private static fillCreateOptionsWithDefaults;
|
|
93
106
|
/**
|
|
94
107
|
* Validate create options.
|
|
@@ -99,12 +112,9 @@ export declare class Exhibition extends AbstractWraplet<HTMLElement, typeof Exhi
|
|
|
99
112
|
*/
|
|
100
113
|
private static applyCreateOptions;
|
|
101
114
|
/**
|
|
102
|
-
*
|
|
103
|
-
* the options.
|
|
104
|
-
*
|
|
105
|
-
* @param mapOptions
|
|
106
|
-
* Map options.
|
|
115
|
+
* Creates a default, preconfigured, map for Exhibition.
|
|
107
116
|
*/
|
|
108
|
-
static getMap
|
|
117
|
+
static getMap(configuration: DefaultMapConfiguration): ReturnType<typeof createMap>;
|
|
118
|
+
static getCustomizedMap(configuration: MapConfiguration): ReturnType<typeof createMap>;
|
|
109
119
|
}
|
|
110
120
|
export {};
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Exhibition:()=>_,ExhibitionMonacoEditor:()=>H,ExhibitionPreview:()=>N,exhibitionDefaultAttribute:()=>U});class i extends Error{}class s extends Error{}class r extends Error{}class n extends Error{}class a extends Error{}class o extends Error{}class l extends Error{}class d extends Error{}function h(t){return Object.getPrototypeOf(t)===Object.prototype}const c=(t,e)=>"object"==typeof t&&null!==t&&!0===t[e],u=Symbol("WrapletSet");function p(t){return c(t,u)}class f extends Set{find(t){const e=[];for(const i of this)t(i)&&e.push(i);return e}findOne(t){for(const e of this)if(t(e))return e;return null}getOrdered(t){return Array.from(this).sort((e,i)=>t(e)-t(i))}}const w=Symbol("WrapletSetReadonly");class g extends f{[w]=!0;[u]=!0}const y=Symbol("Core"),m=Symbol("NodeTreeParent");function b(t){return{args:[],destructible:!0,map:{},coreOptions:{},...t}}function v(t){const e={};for(const i in t){const s=t[i];e[i]=b(s);const r=s.map;r&&h(r)&&(e[i].map=v(r))}return e}const C=Symbol("DynamicMap");function E(t){return c(t,C)}class O{fullMap;startingPath;currentMap=null;path;currentPath=[];constructor(t,e=[],i=!0){this.path=e,this.startingPath=e,this.fullMap=v(t),i&&(this.currentMap=this.resolve(this.path))}getStartingMap(){return this.resolve(this.startingPath)}getCurrentMap(){return this.currentMap&&this.currentPath==this.path||(this.currentMap=this.resolve(this.path),this.currentPath=this.path),this.currentMap}findMap(t){let e=this.fullMap;for(const i of t){if(!e[i])throw new Error(`Invalid path: ${this.path.join(".")} . No such definition.`);const s=e[i].map;if(h(s))e=s;else{if(!E(s))throw new Error("Invalid map type.");e=s.create(this.clone(t,!1))}}return e}up(t,e=!0){if(!this.pathExists([...this.path,t]))throw new Error("Map doesn't exist.");this.path.push(t),e&&(this.currentMap=this.resolve(this.path))}pathExists(t){let e=this.fullMap;for(const i of t){if(!Object.hasOwn(e,i))return!1;const t=e[i].map;if(E(t))return!0;if(!h(t))throw new Error("Invalid map type.");e=t}return!0}down(t=!0){if(0===this.path.length)throw new Error("At the root already.");this.path.pop(),t&&(this.currentMap=this.resolve(this.path))}clone(t,e=!0){return new O(this.fullMap,t,e)}resolve(t){return this.findMap(t)}}const M=Symbol("ArgCreator");function D(t,e){const i=new e(t.element,t.map,t.initOptions);return new t.Class(i,...t.args)}class I{node;[y]=!0;[m]=!0;childrenAreInstantiated=!1;statusWritable={isDestroyed:!1,isGettingDestroyed:!1,isInitialized:!1,isGettingInitialized:!1};get status(){return this.statusWritable}mapWrapper;instantiatedChildren={};destroyChildListeners=[];instantiateChildListeners=[];listeners=[];wrapletCreator=D;constructor(t,e,i={}){if(this.node=t,!(t instanceof Node))throw new Error("The node provided to the Core is not a valid node.");if(h(e))this.mapWrapper=new O(e);else{if(!(e instanceof O))throw new s("The map provided to the Core is not a valid map.");this.mapWrapper=e}this.processInitOptions(i),this.instantiatedChildren={}}async initializeChildren(){this.statusWritable.isGettingInitialized=!0;const t=Object.values(this.instantiatedChildren).flatMap(t=>t?p(t)?Array.from(t):[t]:[]);await Promise.all(t.map(t=>t.wraplet.initialize())),this.statusWritable.isInitialized=!0,this.statusWritable.isGettingInitialized=!1,this.statusWritable.isGettingDestroyed&&await this.destroy()}get map(){return this.mapWrapper.getStartingMap()}instantiateChildren(){const t=this.instantiatedChildren;if("function"==typeof this.node.querySelectorAll){for(const e in this.map){const i=this.map[e],s=i.multiple,r=this.mapWrapper.clone([...this.mapWrapper.path,e]);this.validateMapItem(e,i),t[e]=s?this.instantiateMultipleWrapletsChild(i,r,this.node,e):this.instantiateSingleWrapletChild(i,r,this.node,e)}this.childrenAreInstantiated||(this.instantiatedChildren=this.wrapChildren(t),this.childrenAreInstantiated=!0)}else for(const t in this.map){const e=this.map[t];this.validateMapItemForNonParent(t,e)}}async syncChildren(){this.instantiateChildren(),await this.initializeChildren()}getNodeTreeChildren(){const t=[];for(const e of Object.values(this.children))if(null!==e)if(p(e))for(const i of e)t.push(i);else t.push(e);return t.filter(t=>{let e=!1;return t.wraplet.accessNode(t=>{e=this.node.contains(t)}),e})}findExistingWraplet(t,e){if(void 0===this.instantiatedChildren||!this.instantiatedChildren[t])return null;const i=this.instantiatedChildren[t];if(this.map[t].multiple){if(!p(i))throw new l("Internal logic error. Expected a WrapletSet.");const t=i.find(t=>{let i=!1;return t.wraplet.accessNode(t=>{t===e&&(i=!0)}),i});if(0===t.length)return null;if(t.length>1)throw new l("Internal logic error. Multiple instances wrapping the same element found in the core.");return t[0]}return i}instantiateSingleWrapletChild(t,e,i,s){if(!t.selector)return null;const r=t.selector,n=this.findChildren(r,i);if(this.validateElements(s,n,t),0===n.length)return null;if(n.length>1)throw new a(`${this.constructor.name}: More than one element was found for the "${s}" child. Selector used: "${r}".`);const o=n[0];return this.instantiateWrapletItem(s,t,e,o)}instantiateWrapletItem(t,e,i,s){const r=this.findExistingWraplet(t,s);if(r)return r;const n={id:t,Class:e.Class,element:s,map:i,initOptions:e.coreOptions,args:e.args};n.args=n.args.map(t=>c(t,M)?t.createArg(n):t);let a=null;try{a=this.wrapletCreator(n,this.constructor)}catch(i){if(i instanceof d&&!e.required)return console.warn(`${i.message} Skipping instantiation of the "${t}" child.`),null;throw i}this.prepareIndividualWraplet(t,a);for(const e of this.instantiateChildListeners)e(a,t);return a}instantiateMultipleWrapletsChild(t,e,i,s){const r=t.selector;if(!r)return new g;const n=this.findChildren(r,i);this.validateElements(s,n,t);const a=this.instantiatedChildren&&this.instantiatedChildren[s]?this.instantiatedChildren[s]:new g;for(const i of n){if(this.findExistingWraplet(s,i))continue;const r=this.instantiateWrapletItem(s,t,e,i);r&&a.add(r)}return a}addDestroyChildListener(t){this.destroyChildListeners.push(t)}addInstantiateChildListener(t){this.instantiateChildListeners.push(t)}setWrapletCreator(t){this.wrapletCreator=t}prepareIndividualWraplet(t,e){e.wraplet.addDestroyListener(e=>{this.removeChild(e,t);for(const i of this.destroyChildListeners)i(e,t)})}async destroy(){if(this.statusWritable.isDestroyed)throw new o("Children are already destroyed.");if(this.statusWritable.isGettingDestroyed=!0,!this.statusWritable.isGettingInitialized){if(!this.statusWritable.isInitialized)return this.statusWritable.isDestroyed=!0,void(this.statusWritable.isGettingDestroyed=!1);for(const t of this.listeners){const e=t.node,i=t.eventName,s=t.callback,r=t.options;e.removeEventListener(i,s,r)}this.listeners.length=0,await this.destroyChildren(),this.statusWritable.isInitialized=!1,this.statusWritable.isDestroyed=!0,this.statusWritable.isGettingDestroyed=!1}}findChildren(t,e){return"string"==typeof t?((t,e)=>Array.from(e.querySelectorAll(t)))(t,e):t(e)}addEventListener(t,e,i,s){this.listeners.push({node:t,eventName:e,callback:i,options:s}),t.addEventListener(e,i,s)}get children(){if(!this.childrenAreInstantiated)throw new n("Wraplet is not yet fully initialized. You can fetch partial children with the 'uninitializedChildren' property.");return this.instantiatedChildren}removeChild(t,e){if(p(this.instantiatedChildren[e])){if(!this.instantiatedChildren[e].delete(t))throw new l("Internal logic error. Destroyed child couldn't be removed because it's not among the children.")}else{if(this.map[e].required&&!this.statusWritable.isGettingDestroyed)throw new r("Required child has been destroyed.");if(null===this.instantiatedChildren[e])throw new l("Internal logic error. Destroyed child couldn't be removed because it's already null.");this.instantiatedChildren[e]=null}}validateMapItem(t,e){const i=e.selector,r=e.required;if(!i&&r)throw new s(`${this.constructor.name}: Child "${t}" cannot at the same be required and have no selector.`)}validateMapItemForNonParent(t,e){if(e.required)throw new s(`Dependency "${t}" error: If the node provided cannot have children, there should be no required children.`)}validateElements(t,e,s){if(0===e.length&&s.required)throw new i(`${this.constructor.name}: Couldn't find a node for the wraplet "${t}". Selector used: "${s.selector}".`)}wrapChildren(t){return new Proxy(t,{get:function(t,e){if(!(e in t))throw new Error(`Child '${e}' has not been found.`);return t[e]}})}defaultInitOptions(){return{instantiateChildListeners:[],destroyChildListeners:[]}}processInitOptions(t){const e=Object.assign(this.defaultInitOptions(),t);for(const t of e.instantiateChildListeners)this.instantiateChildListeners.push(t);for(const t of e.destroyChildListeners)this.destroyChildListeners.push(t)}async destroyChildren(){for(const[t,e]of Object.entries(this.children))if(e&&this.map[t].destructible)if(p(e))for(const t of e)await t.wraplet.destroy();else await e.wraplet.destroy()}}const A=Symbol("Wraplet"),S=Symbol("Groupable");function z(t,e){return async function(){if(!(t.status||this&&this.status))throw new Error("Cannot initialize without status available.");const i=t.status||this.status;await async function(t,e){return!t.isInitialized&&(t.isGettingInitialized=!0,await e.initializeChildren(),!0)}(i,t.core)&&(e&&await e(),await async function(t,e){t.isInitialized=!0,t.isGettingInitialized=!1,t.isGettingDestroyed&&await e()}(i,t.destroyCallback))}}function W(t,e){return async function(){if(!(t.status||this&&this.status))throw new Error("Cannot destroy without status available.");const i=t.status||this.status;await async function(t,e,i,s){if(t.isDestroyed)return!1;if(t.isGettingDestroyed=!0,t.isGettingInitialized)return!1;if(!t.isInitialized)return t.isDestroyed=!0,t.isGettingDestroyed=!1,!1;await e.destroy();for(const t of s)await t(i);return!0}(i,t.core,t.wraplet,t.destroyListeners)&&(e&&await e(),await async function(t){t.isGettingDestroyed=!1,t.isInitialized=!1,t.isDestroyed=!0}(i))}}class L{core;[A]=!0;[S]=!0;[m]=!0;destroyListeners=[];wraplet;constructor(t){if(this.core=t,!c(t,y))throw new Error("AbstractWraplet requires a Core instance.");const e=this.supportedNodeTypes();if(null!==e&&!e.find(e=>t.node instanceof e))throw new d(`Node type ${t.node.constructor.name} is not supported by the ${this.constructor.name} wraplet.`);t.addDestroyChildListener(this.onChildDestroy.bind(this)),t.addInstantiateChildListener(this.onChildInstantiate.bind(this)),t.instantiateChildren(),this.wraplet=(t=>{let e=t.groupExtractor||(t=>{if(t instanceof Element){const e=t.getAttribute("data-js-wraplet-groupable");if(e)return e.split(",")}return[]});return Object.assign((t=>{const e=[],i={},s=t.destroyListeners||[],r=t.destroyCallback||W({core:t.core,wraplet:t.wraplet,destroyListeners:s}).bind(i);i.destroy=r;const n=t.initializeCallback||z({core:t.core,destroyCallback:i.destroy}).bind(i);return Object.assign(i,{__nodeAccessors:e,status:{isGettingInitialized:!1,isDestroyed:!1,isInitialized:!1,isGettingDestroyed:!1},addDestroyListener:t=>{s.push(t)},initialize:n,destroy:r,accessNode:i=>{e.push(i),i(t.core.node)}})})(t),{getNodeTreeChildren:()=>t.core.getNodeTreeChildren(),setGroupsExtractor:t=>{e=t},getGroups:()=>e(t.core.node)})})({core:this.core,wraplet:this,destroyListeners:this.destroyListeners})}get children(){return this.core.children}onChildDestroy(t,e){}get node(){return this.core.node}onChildInstantiate(t,e){}supportedNodeTypes(){return null}supportedNodeTypesGuard(t){return t}isChildInstance(t,e,i=null){return e===(i||e)&&t instanceof this.core.map[e].Class}static createCore(t,e){return new I(t,e)}static createWraplets(t,e,i,s=[]){if(this===L)throw new Error("You cannot instantiate an abstract class.");const r=[];if(t instanceof Element&&t.hasAttribute(i)){const i=this.createCore(t,e);r.push(new this(i,...s))}const n=t.querySelectorAll(`[${i}]`);for(const t of n){const i=this.createCore(t,e);r.push(new this(i,...s))}return r}}function x(t,e){if(!t.status&&(t.destroy||t.initialize))throw new Error("Cannot customize lifecycle callbacks without providing status. This is because all callbacks have to share the same status.");return Object.assign(e,t)}const P=Symbol("KeyValueStorage");class T extends Error{}class j{storage;defaults;validators;[P]=!0;constructor(t,e,i){this.storage=t,this.defaults=e,this.validators=i}async has(t){return await this.storage.has(t)}async get(t){const e=await this.storage.get(t);return void 0!==e?(this.validateGetValue(t,e),e):this.defaults[t]}async getMultiple(t){const e={...await this.storage.getMultiple(t)};for(const i of t)void 0===e[i]&&(e[i]=this.defaults[i]);return e}async getAll(){const t={...await this.storage.getAll()};for(const e of Object.keys(this.defaults))void 0===t[e]&&(t[e]=this.defaults[e]);return t}async set(t,e){this.validateSetValue(t,e),await this.storage.set(t,e)}async setMultiple(t){for(const e in t)this.validateSetValue(e,t[e]);await this.storage.setMultiple(t)}async setAll(t){for(const e in t)this.validateSetValue(e,t[e]);await this.storage.setAll(t)}async delete(t){await this.storage.delete(t)}async deleteMultiple(t){await this.storage.deleteMultiple(t)}async deleteAll(){await this.storage.deleteAll()}validateGetValue(t,e){if(!this.validators[t](e))throw new T(`Got an invalid value for the key ${String(t)}.`)}validateSetValue(t,e){if(!this.validators[t](e))throw new T(`Attempted to set an invalid value for the key ${String(t)}.`)}}class G{isPartial;defaults;validators;[P]=!0;data=null;options;constructor(t,e,i,s={}){this.isPartial=t,this.defaults=e,this.validators=i,this.validateValidators(i),this.options={keepFresh:!0,elementOptionsMerger:(t,e)=>({...t,...e}),...s}}async has(t){return t in await this.getAll()}async get(t){return(await this.getAll())[t]}async getMultiple(t){const e=await this.getAll();return t.reduce((t,i)=>(t[i]=e[i],t),{})}async getAll(){return this.options.keepFresh&&await this.refresh(),this.data||await this.refresh(),this.data}async set(t,e){if(this.validators[t]&&!this.validators[t](e))throw new T(`Attempted to set an invalid value for the key ${String(t)}.`);const i=await this.getValue(),s=JSON.parse(i);s[t]=e,await this.setAll(s)}async setMultiple(t){const e=await this.getAll();await this.setAll({...e,...t})}async setAll(t){await this.setValue(t)}async delete(t){const e=await this.getAll();t in e&&(delete e[t],await this.setValue(e))}async deleteMultiple(t){const e=await this.getAll();for(const i of t)delete e[i];await this.setAll(e)}async deleteAll(){await this.deleteAllValues(),await this.refresh()}async refresh(){this.data=await this.fetchFreshData()}async fetchFreshData(){const t=await this.getValue();if("{"!==t.charAt(0))throw new T("Data has to be defined as an object.");const e=JSON.parse(t);return this.validateData(e),this.options.elementOptionsMerger(this.defaults,e)}validateData(t){for(const e in t){if(!this.isPartial&&!this.validators[e])throw new T(`No validator found for the value: ${e}`);if(this.validators[e]&&!this.validators[e](t[e]))throw new T(`Value for '${e}' has been discarded by the validator.`)}}validateValidators(t){for(const e in t)if("function"!=typeof t[e])throw new T(`Validator for ${e} is not a function.`)}}class k extends G{element;attribute;defaults;validators;constructor(t,e,i,s,r,n={}){super(t,s,r,n),this.element=e,this.attribute=i,this.defaults=s,this.validators=r}async getValue(){return this.element.getAttribute(this.attribute)||"{}"}async setValue(t){this.element.setAttribute(this.attribute,JSON.stringify(t))}async deleteAllValues(){this.element.removeAttribute(this.attribute)}}class N extends L{alterers=[];currentBlobUrl=null;options;constructor(t,e={},i){super(t);const s={updateHeight:!0,updateHeightCallback:async t=>{setTimeout(()=>{t.updateHeight()},100)}},r=i||new k(!0,t.node,"data-js-options",{},{});this.options=new j(r,{...s,...e},{updateHeight:t=>"boolean"==typeof t,updateHeightCallback:t=>"function"==typeof t})}supportedNodeTypes(){return super.supportedNodeTypesGuard([HTMLIFrameElement])}addDocumentAlterer(t,e=0){this.hasDocumentAlterer(t)||this.alterers.push({callback:t,priority:e})}hasDocumentAlterer(t){return this.alterers.some(e=>e.callback===t)}removeDocumentAlterer(t){this.alterers=this.alterers.filter(e=>e.callback!==t)}async update(){const t=document.implementation.createHTMLDocument();this.alterers.sort((t,e)=>e.priority-t.priority);for(const e of this.alterers)await e.callback(t);this.currentBlobUrl&&URL.revokeObjectURL(this.currentBlobUrl);const e="<!DOCTYPE html>\n"+t.documentElement.outerHTML,i=new Blob([e],{type:"text/html;charset=utf-8"});this.currentBlobUrl=URL.createObjectURL(i),this.node.src=this.currentBlobUrl,this.node.onload=async()=>{await this.options.get("updateHeight")||await(await this.options.get("updateHeightCallback"))(this),this.node.onload=null}}updateHeight(){const t=this.getIFrameWindow(),e=this.getIFrameDocument().querySelector("html");if(!e)return;const i=t.getComputedStyle(e),s=parseFloat(i.marginTop)+parseFloat(i.marginBottom),r=Math.ceil(e.offsetHeight+s);this.node.height=r+"px"}getIFrameDocument(){const t=this.node.contentDocument;if(!t)throw new Error("IFrame document is not available.");return t}getIFrameWindow(){const t=this.node.contentWindow;if(!t)throw new Error("IFrame window is not available.");return t}}const V={html:{languages:["html"],tag:void 0},js:{languages:["javascript","typescript"],tag:"script"},css:{languages:["css"],tag:"style"}};function $(t){for(const[e,i]of Object.entries(V))if(i.languages.includes(t))return e;throw new Error("Unknown language")}function q(t){return V[t].tag}function F(t){return Boolean(q(t))}class H extends L{monaco=null;editor=null;options;status={isInitialized:!1,isDestroyed:!1,isGettingInitialized:!1,isGettingDestroyed:!1};priority=0;monacoEditorOptions=null;constructor(t,e,i){super(t),this.alterDocument=this.alterDocument.bind(this);const s={location:"body",priority:0,trimDefaultValue:!0,monacoEditorOptions:{}},r={location:t=>"string"==typeof t&&["head","body"].includes(t),priority:t=>Number.isInteger(t),tagAttributes:t=>"object"==typeof t,trimDefaultValue:t=>"boolean"==typeof t,monacoEditorCreator:t=>"function"==typeof t,monaco:t=>"object"==typeof t,monacoEditorOptions:()=>!0};e.monacoEditorOptions={...s.monacoEditorOptions,...e.monacoEditorOptions};const n=i||new k(!0,t.node,"data-js-options",{},{},{elementOptionsMerger:(t,i)=>(i.monacoEditorOptions={...t.monacoEditorOptions,...e.monacoEditorOptions,...i.monacoEditorOptions},{...t,...e,...i})});this.options=new j(n,{...s,...e},r),this.wraplet=x({status:this.status,initialize:this.initialize.bind(this),destroy:this.destroy.bind(this)},this.wraplet)}supportedNodeTypes(){return super.supportedNodeTypesGuard([HTMLElement])}async initialize(){return z({core:this.core,destroyCallback:this.destroy,status:this.status},async()=>{if(this.status.isInitialized)throw new Error("ExhibitionMonacoEditor is already initialized");if(this.priority=await this.options.get("priority"),this.monacoEditorOptions=await this.options.get("monacoEditorOptions"),await this.options.get("trimDefaultValue")){const t=await this.options.get("monacoEditorOptions");t.value&&(t.value=H.trimDefaultValue(t.value),await this.options.set("monacoEditorOptions",t))}await this.validateOptions(),this.monaco=await this.getMonacoInstance();const t=await this.options.get("monacoEditorCreator")||(async(t,e,i)=>H.createMonacoEditor(t,e,i));this.editor=await t(await this.options.get("monacoEditorOptions"),this.node,this.monaco)})()}getPriority(){return this.priority}async getMonacoInstance(){const t=await this.options.get("monaco");if(!t)throw new Error("Monaco instance is not available");return t}getValue(){return this.getEditor().getValue()}async alterDocument(t){const e=this.monaco;if(!e)throw new Error("Monaco instance is not available. Is wraplet initialized?");const i=this.getLanguage(),s="typescript"===i?await this.getTSValueAsJS(e):this.getValue(),r=await this.options.get("location"),n=$(i);if(F(n)){const e=q(n),i=await this.options.get("tagAttributes")??{},a=t.createElement(e);for(const[t,e]of Object.entries(i))a.setAttribute(t,e);return a.innerHTML=s,void t[r].appendChild(a)}t[r].innerHTML+=s}getDocumentAlterer(){return this.alterDocument}async validateOptions(){if(!(await this.options.get("monacoEditorOptions")).language)throw new Error("Missing language in monacoOptions");if(!F($(this.getLanguage()))&&await this.options.get("tagAttributes"))throw new Error("'tagAttributes' option is only allowed for single tag types")}getEditor(){if(!this.editor)throw new Error("Editor is not initialized");return this.editor}async getTSValueAsJS(t){const e=this.getEditor().getModel();if(!e)throw new Error("Model is not available");t.languages.typescript.typescriptDefaults.setEagerModelSync(!0);const i=e.uri;if("file"!==i.scheme)throw new Error(`Model must use file:// URI, got: ${i.toString()}`);const s=async(e=10)=>{try{return await t.languages.typescript.getTypeScriptWorker()}catch(t){if("TypeScript not registered!"!==t)throw t;return e<=0?null:(await new Promise(t=>setTimeout(t,200)),s(e-1))}},r=await s();if(!r)throw new Error("Timeout: Could not get TypeScript worker");const n=await r(i);for(let t=0;t<20;t++)try{await n.getSemanticDiagnostics(i.toString());break}catch(t){if(/Could not find source file/.test(String(t))){await new Promise(t=>setTimeout(t,250));continue}throw t}const{outputFiles:a}=await n.getEmitOutput(i.toString());if(!a.length)throw new Error("No JS output produced");return a[0].text}getLanguage(){const t=this.monacoEditorOptions;if(!t)throw new Error("Monaco options are not available. Is wraplet initialized?");if(!t.language)throw new Error("Missing language in monacoOptions");return t.language}static trimDefaultValue(t){const e=t.split("\n"),i=e.find(t=>t.trim().length>0);if(!i)return t.trim();const s=i.search(/\S|$/);return e.map(t=>t.length>=s&&""===t.substring(0,s).trim()?t.substring(s):t).join("\n").trim()}async destroy(){return W({core:this.core,wraplet:this,destroyListeners:this.destroyListeners,status:this.status},async()=>{this.editor?.dispose()})()}static createMonacoEditor(t={},e,i){const s=t.language;if(!s)throw new Error("Missing language in editorOptions");const r=this.createMonacoModel(i,s,t.value||"");return i.editor.create(e,{...t,model:r})}static createMonacoModel(t,e,i){const s=Math.random().toString(36).substring(2,15);return t.editor.createModel(i,e,t.Uri.parse(`file:///${e}-${s}.ts`))}static create(t,e){const i=new I(t,{});return new H(i,e)}}const U="data-js-exhibition",B={editors:{selector:"[data-js-exhibition-editor]",multiple:!0,required:!1,Class:H,args:[]},preview:{selector:"iframe[data-js-exhibition-preview]",multiple:!1,required:!0,Class:N,args:[]}};class _ extends L{status={isInitialized:!1,isDestroyed:!1,isGettingInitialized:!1,isGettingDestroyed:!1};options;constructor(t,e={},i){super(t);const s=i??new k(!0,this.node,"data-js-options",{},{updaterSelector:t=>"string"==typeof t});this.options=new j(s,{updaterSelector:"[data-js-exhibition-updater]",...e},{updaterSelector:t=>"string"==typeof t}),this.wraplet=x({status:this.status,initialize:this.initialize.bind(this)},this.wraplet)}supportedNodeTypes(){return super.supportedNodeTypesGuard([HTMLElement])}async initialize(){return z({core:this.core,status:this.status,destroyCallback:this.wraplet.destroy},async()=>{if(this.status.isInitialized)throw new Error("Exhibition is already initialized");for(const t of this.children.editors)t.wraplet.status.isInitialized||t.wraplet.status.isGettingInitialized||await t.wraplet.initialize(),this.children.preview.hasDocumentAlterer(t.getDocumentAlterer())||this.addPreviewAlterer(t.getDocumentAlterer(),t.getPriority());const t=this.node.querySelectorAll(await this.options.get("updaterSelector"));for(const e of t)this.core.addEventListener(e,"click",()=>{this.updatePreview()})})()}addEditor(t){this.children.editors.add(t),this.children.preview.addDocumentAlterer(t.getDocumentAlterer())}removeEditor(t){this.children.editors.delete(t),this.children.preview.removeDocumentAlterer(t.getDocumentAlterer())}hasEditor(t){return this.children.editors.has(t)}addPreviewAlterer(t,e=0){this.children.preview.addDocumentAlterer(t,e)}getPreview(){return this.children.preview}async updatePreview(){await this.children.preview.update()}static async createMultiple(t,e,i={},s={},r=U){s=this.fillCreateOptionsWithDefaults(s),this.validateInitOptions(s,e);const n=this.createWraplets(t,e,r,[i]);for(const t of n)await this.applyCreateOptions(t,s);return n}static async create(t,e,i={},s={}){s=this.fillCreateOptionsWithDefaults(s),this.validateInitOptions(s,e);const r=new I(t,e),n=new _(r,i);return await this.applyCreateOptions(n,s),n}static fillCreateOptionsWithDefaults(t){return{init:!0,updatePreview:!1,...t}}static validateInitOptions(t,e){if(t.init&&void 0===e.editors.selector)throw new Error("Cannot initialize exhibition with undefined editors.selector");if(!t.init&&t.updatePreview)throw new Error("Cannot update preview without initializing exhibitions first")}static async applyCreateOptions(t,e={}){if(!e.init&&e.updatePreview)throw new Error("'updatePreview' option cannot be enabled without the 'init' one because updating preview requires initialization.");e.init&&await t.initialize(),e.updatePreview&&await t.updatePreview()}static getMap(t){const e=B,i={selectEditors:!0,Class:void 0,editorsOptions:{},previewOptions:{},...t};if(i.Class&&(e.editors.Class=i.Class),i.selectEditors&&e.editors.Class instanceof H&&(!i.editorsOptions||!i.editorsOptions.monaco))throw new Error("When selecting ExhibitionMonacoEditor instances, you must provide the 'monaco' option in the editors options. To avoid this error, disable 'selectEditors' or provide the 'monaco' option.");return i.selectEditors||(e.editors.selector=void 0),i.previewOptions&&e.preview.args.push(i.previewOptions),i.editorsOptions&&e.editors.args.push(i.editorsOptions),e}}var R=exports;for(var J in e)R[J]=e[J];e.__esModule&&Object.defineProperty(R,"__esModule",{value:!0});
|
|
1
|
+
var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Exhibition:()=>R,ExhibitionMonacoEditor:()=>U,ExhibitionPreview:()=>N,exhibitionDefaultAttribute:()=>B});class i extends Error{}class s extends Error{}class r extends Error{}class n extends Error{}class a extends Error{}class o extends Error{}class l extends Error{}class d extends Error{}function h(t){return Object.getPrototypeOf(t)===Object.prototype}const c=(t,e)=>"object"==typeof t&&null!==t&&!0===t[e],u=Symbol("WrapletSet");function p(t){return c(t,u)}class w extends Set{find(t){const e=[];for(const i of this)t(i)&&e.push(i);return e}findOne(t){for(const e of this)if(t(e))return e;return null}getOrdered(t){return Array.from(this).sort((e,i)=>t(e)-t(i))}}const f=Symbol("WrapletSetReadonly");class g extends w{[f]=!0;[u]=!0}const y=Symbol("Core"),m=Symbol("NodeTreeParent");function b(t){return{args:[],destructible:!0,map:{},coreOptions:{},...t}}function v(t){const e={};for(const i in t){const s=t[i];e[i]=b(s);const r=s.map;r&&h(r)&&(e[i].map=v(r))}return e}const C=Symbol("DynamicMap");function E(t){return c(t,C)}class M{fullMap;startingPath;currentMap=null;path;currentPath=[];constructor(t,e=[],i=!0){this.path=e,this.startingPath=e,this.fullMap=v(t),i&&(this.currentMap=this.resolve(this.path))}getStartingMap(){return this.resolve(this.startingPath)}getCurrentMap(){return this.currentMap&&this.currentPath==this.path||(this.currentMap=this.resolve(this.path),this.currentPath=this.path),this.currentMap}findMap(t){let e=this.fullMap;for(const i of t){if(!e[i])throw new Error(`Invalid path: ${this.path.join(".")} . No such definition.`);const s=e[i].map;if(h(s))e=s;else{if(!E(s))throw new Error("Invalid map type.");e=s.create(this.clone(t,!1))}}return e}up(t,e=!0){if(!this.pathExists([...this.path,t]))throw new Error("Map doesn't exist.");this.path.push(t),e&&(this.currentMap=this.resolve(this.path))}pathExists(t){let e=this.fullMap;for(const i of t){if(!Object.hasOwn(e,i))return!1;const t=e[i].map;if(E(t))return!0;if(!h(t))throw new Error("Invalid map type.");e=t}return!0}down(t=!0){if(0===this.path.length)throw new Error("At the root already.");this.path.pop(),t&&(this.currentMap=this.resolve(this.path))}clone(t,e=!0){return new M(this.fullMap,t,e)}resolve(t){return this.findMap(t)}}const O=Symbol("ArgCreator");function D(t,e){const i=new e(t.element,t.map,t.initOptions);return new t.Class(i,...t.args)}class I{node;[y]=!0;[m]=!0;childrenAreInstantiated=!1;statusWritable={isDestroyed:!1,isGettingDestroyed:!1,isInitialized:!1,isGettingInitialized:!1};get status(){return this.statusWritable}mapWrapper;instantiatedChildren={};destroyChildListeners=[];instantiateChildListeners=[];listeners=[];wrapletCreator=D;constructor(t,e,i={}){if(this.node=t,!(t instanceof Node))throw new Error("The node provided to the Core is not a valid node.");if(h(e))this.mapWrapper=new M(e);else{if(!(e instanceof M))throw new s("The map provided to the Core is not a valid map.");this.mapWrapper=e}this.processInitOptions(i),this.instantiatedChildren={}}async initializeChildren(){this.statusWritable.isGettingInitialized=!0;const t=Object.values(this.instantiatedChildren).flatMap(t=>t?p(t)?Array.from(t):[t]:[]);await Promise.all(t.map(t=>t.wraplet.initialize())),this.statusWritable.isInitialized=!0,this.statusWritable.isGettingInitialized=!1,this.statusWritable.isGettingDestroyed&&await this.destroy()}get map(){return this.mapWrapper.getStartingMap()}instantiateChildren(){const t=this.instantiatedChildren;if("function"==typeof this.node.querySelectorAll){for(const e in this.map){const i=this.map[e],s=i.multiple,r=this.mapWrapper.clone([...this.mapWrapper.path,e]);this.validateMapItem(e,i),t[e]=s?this.instantiateMultipleWrapletsChild(i,r,this.node,e):this.instantiateSingleWrapletChild(i,r,this.node,e)}this.childrenAreInstantiated||(this.instantiatedChildren=this.wrapChildren(t),this.childrenAreInstantiated=!0)}else for(const t in this.map){const e=this.map[t];this.validateMapItemForNonParent(t,e)}}async syncChildren(){this.instantiateChildren(),await this.initializeChildren()}getNodeTreeChildren(){const t=[];for(const e of Object.values(this.children))if(null!==e)if(p(e))for(const i of e)t.push(i);else t.push(e);return t.filter(t=>{let e=!1;return t.wraplet.accessNode(t=>{e=this.node.contains(t)}),e})}findExistingWraplet(t,e){if(void 0===this.instantiatedChildren||!this.instantiatedChildren[t])return null;const i=this.instantiatedChildren[t];if(this.map[t].multiple){if(!p(i))throw new l("Internal logic error. Expected a WrapletSet.");const t=i.find(t=>{let i=!1;return t.wraplet.accessNode(t=>{t===e&&(i=!0)}),i});if(0===t.length)return null;if(t.length>1)throw new l("Internal logic error. Multiple instances wrapping the same element found in the core.");return t[0]}return i}instantiateSingleWrapletChild(t,e,i,s){if(!t.selector)return null;const r=t.selector,n=this.findChildren(r,i);if(this.validateElements(s,n,t),0===n.length)return null;if(n.length>1)throw new a(`${this.constructor.name}: More than one element was found for the "${s}" child. Selector used: "${r}".`);const o=n[0];return this.instantiateWrapletItem(s,t,e,o)}instantiateWrapletItem(t,e,i,s){const r=this.findExistingWraplet(t,s);if(r)return r;const n={id:t,Class:e.Class,element:s,map:i,initOptions:e.coreOptions,args:e.args};n.args=n.args.map(t=>c(t,O)?t.createArg(n):t);let a=null;try{a=this.wrapletCreator(n,this.constructor)}catch(i){if(i instanceof d&&!e.required)return console.warn(`${i.message} Skipping instantiation of the "${t}" child.`),null;throw i}this.prepareIndividualWraplet(t,a);for(const e of this.instantiateChildListeners)e(a,t);return a}instantiateMultipleWrapletsChild(t,e,i,s){const r=t.selector;if(!r)return new g;const n=this.findChildren(r,i);this.validateElements(s,n,t);const a=this.instantiatedChildren&&this.instantiatedChildren[s]?this.instantiatedChildren[s]:new g;for(const i of n){if(this.findExistingWraplet(s,i))continue;const r=this.instantiateWrapletItem(s,t,e,i);r&&a.add(r)}return a}addDestroyChildListener(t){this.destroyChildListeners.push(t)}addInstantiateChildListener(t){this.instantiateChildListeners.push(t)}setWrapletCreator(t){this.wrapletCreator=t}prepareIndividualWraplet(t,e){e.wraplet.addDestroyListener(e=>{this.removeChild(e,t);for(const i of this.destroyChildListeners)i(e,t)})}async destroy(){if(this.statusWritable.isDestroyed)throw new o("Children are already destroyed.");if(this.statusWritable.isGettingDestroyed=!0,!this.statusWritable.isGettingInitialized){if(!this.statusWritable.isInitialized)return this.statusWritable.isDestroyed=!0,void(this.statusWritable.isGettingDestroyed=!1);for(const t of this.listeners){const e=t.node,i=t.eventName,s=t.callback,r=t.options;e.removeEventListener(i,s,r)}this.listeners.length=0,await this.destroyChildren(),this.statusWritable.isInitialized=!1,this.statusWritable.isDestroyed=!0,this.statusWritable.isGettingDestroyed=!1}}findChildren(t,e){return"string"==typeof t?((t,e)=>Array.from(e.querySelectorAll(t)))(t,e):t(e)}addEventListener(t,e,i,s){this.listeners.push({node:t,eventName:e,callback:i,options:s}),t.addEventListener(e,i,s)}get children(){if(!this.childrenAreInstantiated)throw new n("Wraplet is not yet fully initialized. You can fetch partial children with the 'uninitializedChildren' property.");return this.instantiatedChildren}removeChild(t,e){if(p(this.instantiatedChildren[e])){if(!this.instantiatedChildren[e].delete(t))throw new l("Internal logic error. Destroyed child couldn't be removed because it's not among the children.")}else{if(this.map[e].required&&!this.statusWritable.isGettingDestroyed)throw new r("Required child has been destroyed.");if(null===this.instantiatedChildren[e])throw new l("Internal logic error. Destroyed child couldn't be removed because it's already null.");this.instantiatedChildren[e]=null}}validateMapItem(t,e){const i=e.selector,r=e.required;if(!i&&r)throw new s(`${this.constructor.name}: Child "${t}" cannot at the same be required and have no selector.`)}validateMapItemForNonParent(t,e){if(e.required)throw new s(`Dependency "${t}" error: If the node provided cannot have children, there should be no required children.`)}validateElements(t,e,s){if(0===e.length&&s.required)throw new i(`${this.constructor.name}: Couldn't find a node for the wraplet "${t}". Selector used: "${s.selector}".`)}wrapChildren(t){return new Proxy(t,{get:function(t,e){if(!(e in t))throw new Error(`Child '${e}' has not been found.`);return t[e]}})}defaultInitOptions(){return{instantiateChildListeners:[],destroyChildListeners:[]}}processInitOptions(t){const e=Object.assign(this.defaultInitOptions(),t);for(const t of e.instantiateChildListeners)this.instantiateChildListeners.push(t);for(const t of e.destroyChildListeners)this.destroyChildListeners.push(t)}async destroyChildren(){for(const[t,e]of Object.entries(this.children))if(e&&this.map[t].destructible)if(p(e))for(const t of e)await t.wraplet.destroy();else await e.wraplet.destroy()}}const S=Symbol("Wraplet"),A=Symbol("Groupable");function z(t,e){return async function(){if(!(t.status||this&&this.status))throw new Error("Cannot initialize without status available.");const i=t.status||this.status;await async function(t,e){return!t.isInitialized&&(t.isGettingInitialized=!0,await e.initializeChildren(),!0)}(i,t.core)&&(e&&await e(),await async function(t,e){t.isInitialized=!0,t.isGettingInitialized=!1,t.isGettingDestroyed&&await e()}(i,t.destroyCallback))}}function W(t,e){return async function(){if(!(t.status||this&&this.status))throw new Error("Cannot destroy without status available.");const i=t.status||this.status;await async function(t,e,i,s){if(t.isDestroyed)return!1;if(t.isGettingDestroyed=!0,t.isGettingInitialized)return!1;if(!t.isInitialized)return t.isDestroyed=!0,t.isGettingDestroyed=!1,!1;await e.destroy();for(const t of s)await t(i);return!0}(i,t.core,t.wraplet,t.destroyListeners)&&(e&&await e(),await async function(t){t.isGettingDestroyed=!1,t.isInitialized=!1,t.isDestroyed=!0}(i))}}class L{core;[S]=!0;[A]=!0;[m]=!0;destroyListeners=[];wraplet;constructor(t){if(this.core=t,!c(t,y))throw new Error("AbstractWraplet requires a Core instance.");const e=this.supportedNodeTypes();if(null!==e&&!e.find(e=>t.node instanceof e))throw new d(`Node type ${t.node.constructor.name} is not supported by the ${this.constructor.name} wraplet.`);var i;t.addDestroyChildListener(this.onChildDestroy.bind(this)),t.addInstantiateChildListener(this.onChildInstantiate.bind(this)),t.instantiateChildren(),(i=this.node).wraplets||(i.wraplets=new g),i.wraplets.add(this),this.destroyListeners.push(async()=>{!function(t,e){!!e.wraplets&&e.wraplets.delete(t)}(this,this.node)}),this.wraplet=(t=>{let e=t.groupExtractor||(t=>{if(t instanceof Element){const e=t.getAttribute("data-js-wraplet-groupable");if(e)return e.split(",")}return[]});return Object.assign((t=>{const e=[],i={},s=t.destroyListeners||[],r=t.destroyCallback||W({core:t.core,wraplet:t.wraplet,destroyListeners:s}).bind(i);i.destroy=r;const n=t.initializeCallback||z({core:t.core,destroyCallback:i.destroy}).bind(i);return Object.assign(i,{__nodeAccessors:e,status:{isGettingInitialized:!1,isDestroyed:!1,isInitialized:!1,isGettingDestroyed:!1},addDestroyListener:t=>{s.push(t)},initialize:n,destroy:r,accessNode:i=>{e.push(i),i(t.core.node)}})})(t),{getNodeTreeChildren:()=>t.core.getNodeTreeChildren(),setGroupsExtractor:t=>{e=t},getGroups:()=>e(t.core.node)})})({core:this.core,wraplet:this,destroyListeners:this.destroyListeners})}get children(){return this.core.children}onChildDestroy(t,e){}get node(){return this.core.node}onChildInstantiate(t,e){}supportedNodeTypes(){return null}supportedNodeTypesGuard(t){return t}isChildInstance(t,e,i=null){return e===(i||e)&&t instanceof this.core.map[e].Class}static createCore(t,e){return new I(t,e)}static createWraplets(t,e,i,s=[]){if(this===L)throw new Error("You cannot instantiate an abstract class.");const r=[];if(t instanceof Element&&t.hasAttribute(i)){const i=this.createCore(t,e);r.push(new this(i,...s))}const n=t.querySelectorAll(`[${i}]`);for(const t of n){const i=this.createCore(t,e);r.push(new this(i,...s))}return r}}function x(t,e){if(!t.status&&(t.destroy||t.initialize))throw new Error("Cannot customize lifecycle callbacks without providing status. This is because all callbacks have to share the same status.");return Object.assign(e,t)}const P=Symbol("KeyValueStorage");function j(t){return(t=>"object"==typeof t&&null!==t&&!0===t[P])(t)}class T extends Error{}class G{storage;defaults;validators;[P]=!0;constructor(t,e,i){this.storage=t,this.defaults=e,this.validators=i}async has(t){return await this.storage.has(t)}async get(t){const e=await this.storage.get(t);return void 0!==e?(this.validateGetValue(t,e),e):this.defaults[t]}async getMultiple(t){const e={...await this.storage.getMultiple(t)};for(const i of t)void 0===e[i]&&(e[i]=this.defaults[i]);return e}async getAll(){const t={...await this.storage.getAll()};for(const e of Object.keys(this.defaults))void 0===t[e]&&(t[e]=this.defaults[e]);return t}async set(t,e){this.validateSetValue(t,e),await this.storage.set(t,e)}async setMultiple(t){for(const e in t)this.validateSetValue(e,t[e]);await this.storage.setMultiple(t)}async setAll(t){for(const e in t)this.validateSetValue(e,t[e]);await this.storage.setAll(t)}async delete(t){await this.storage.delete(t)}async deleteMultiple(t){await this.storage.deleteMultiple(t)}async deleteAll(){await this.storage.deleteAll()}validateGetValue(t,e){if(!this.validators[t](e))throw new T(`Got an invalid value for the key ${String(t)}.`)}validateSetValue(t,e){if(!this.validators[t](e))throw new T(`Attempted to set an invalid value for the key ${String(t)}.`)}}class V{isPartial;defaults;validators;[P]=!0;data=null;options;constructor(t,e,i,s={}){this.isPartial=t,this.defaults=e,this.validators=i,this.validateValidators(i),this.options={keepFresh:!0,elementOptionsMerger:(t,e)=>({...t,...e}),...s}}async has(t){return t in await this.getAll()}async get(t){return(await this.getAll())[t]}async getMultiple(t){const e=await this.getAll();return t.reduce((t,i)=>(t[i]=e[i],t),{})}async getAll(){return this.options.keepFresh&&await this.refresh(),this.data||await this.refresh(),this.data}async set(t,e){if(this.validators[t]&&!this.validators[t](e))throw new T(`Attempted to set an invalid value for the key ${String(t)}.`);const i=await this.getValue(),s=JSON.parse(i);s[t]=e,await this.setAll(s)}async setMultiple(t){const e=await this.getAll();await this.setAll({...e,...t})}async setAll(t){await this.setValue(t)}async delete(t){const e=await this.getAll();t in e&&(delete e[t],await this.setValue(e))}async deleteMultiple(t){const e=await this.getAll();for(const i of t)delete e[i];await this.setAll(e)}async deleteAll(){await this.deleteAllValues(),await this.refresh()}async refresh(){this.data=await this.fetchFreshData()}async fetchFreshData(){const t=await this.getValue();if("{"!==t.charAt(0))throw new T("Data has to be defined as an object.");const e=JSON.parse(t);return this.validateData(e),this.options.elementOptionsMerger(this.defaults,e)}validateData(t){for(const e in t){if(!this.isPartial&&!this.validators[e])throw new T(`No validator found for the value: ${e}`);if(this.validators[e]&&!this.validators[e](t[e]))throw new T(`Value for '${e}' has been discarded by the validator.`)}}validateValidators(t){for(const e in t)if("function"!=typeof t[e])throw new T(`Validator for ${e} is not a function.`)}}class k extends V{element;attribute;defaults;validators;constructor(t,e,i,s,r,n={}){super(t,s,r,n),this.element=e,this.attribute=i,this.defaults=s,this.validators=r}async getValue(){return this.element.getAttribute(this.attribute)||"{}"}async setValue(t){this.element.setAttribute(this.attribute,JSON.stringify(t))}async deleteAllValues(){this.element.removeAttribute(this.attribute)}}class N extends L{alterers=[];currentBlobUrl=null;options;constructor(t,e,i){if(super(t),void 0!==i&&!j(i))throw new Error("Provided optionsStorage must be a KeyValueStorage");const s={updateHeight:!0,updateHeightCallback:async t=>{setTimeout(()=>{t.updateHeight()},100)}},r=i||new k(!0,t.node,"data-js-options",{},{});this.options=new G(r,{...s,...e},{updateHeight:t=>"boolean"==typeof t,updateHeightCallback:t=>"function"==typeof t})}supportedNodeTypes(){return super.supportedNodeTypesGuard([HTMLIFrameElement])}addDocumentAlterer(t,e=0){this.hasDocumentAlterer(t)||this.alterers.push({callback:t,priority:e})}hasDocumentAlterer(t){return this.alterers.some(e=>e.callback===t)}removeDocumentAlterer(t){this.alterers=this.alterers.filter(e=>e.callback!==t)}async update(){const t=document.implementation.createHTMLDocument();this.alterers.sort((t,e)=>e.priority-t.priority);for(const e of this.alterers)await e.callback(t);this.currentBlobUrl&&URL.revokeObjectURL(this.currentBlobUrl);const e="<!DOCTYPE html>\n"+t.documentElement.outerHTML,i=new Blob([e],{type:"text/html;charset=utf-8"});this.currentBlobUrl=URL.createObjectURL(i),this.node.src=this.currentBlobUrl,this.node.onload=async()=>{await this.options.get("updateHeight")||await(await this.options.get("updateHeightCallback"))(this),this.node.onload=null}}updateHeight(){const t=this.getIFrameWindow(),e=this.getIFrameDocument().querySelector("html");if(!e)return;const i=t.getComputedStyle(e),s=parseFloat(i.marginTop)+parseFloat(i.marginBottom),r=Math.ceil(e.offsetHeight+s);this.node.height=r+"px"}getIFrameDocument(){const t=this.node.contentDocument;if(!t)throw new Error("IFrame document is not available.");return t}getIFrameWindow(){const t=this.node.contentWindow;if(!t)throw new Error("IFrame window is not available.");return t}}const $={html:{languages:["html"],tag:void 0},js:{languages:["javascript","typescript"],tag:"script"},css:{languages:["css"],tag:"style"}};function q(t){for(const[e,i]of Object.entries($))if(i.languages.includes(t))return e;throw new Error("Unknown language")}function F(t){return $[t].tag}function H(t){return Boolean(F(t))}class U extends L{monaco=null;editor=null;options;status={isInitialized:!1,isDestroyed:!1,isGettingInitialized:!1,isGettingDestroyed:!1};priority=0;monacoEditorOptions=null;constructor(t,e,i){if(super(t),void 0!==i&&!j(i))throw new Error("Provided optionsStorage must be a KeyValueStorage");this.alterDocument=this.alterDocument.bind(this);const s={location:"body",priority:0,trimDefaultValue:!0,monacoEditorOptions:{}},r={location:t=>"string"==typeof t&&["head","body"].includes(t),priority:t=>Number.isInteger(t),tagAttributes:t=>"object"==typeof t,trimDefaultValue:t=>"boolean"==typeof t,monacoEditorCreator:t=>"function"==typeof t,monaco:t=>"object"==typeof t,monacoEditorOptions:()=>!0};e.monacoEditorOptions={...s.monacoEditorOptions,...e.monacoEditorOptions};const n=i||new k(!0,t.node,"data-js-options",{},{},{elementOptionsMerger:(t,i)=>(i.monacoEditorOptions={...t.monacoEditorOptions,...e.monacoEditorOptions,...i.monacoEditorOptions},{...t,...e,...i})});this.options=new G(n,{...s,...e},r),this.wraplet=x({status:this.status,initialize:this.initialize.bind(this),destroy:this.destroy.bind(this)},this.wraplet)}supportedNodeTypes(){return super.supportedNodeTypesGuard([HTMLElement])}async initialize(){return z({core:this.core,destroyCallback:this.destroy,status:this.status},async()=>{if(this.status.isInitialized)throw new Error("ExhibitionMonacoEditor is already initialized");if(this.priority=await this.options.get("priority"),this.monacoEditorOptions=await this.options.get("monacoEditorOptions"),await this.options.get("trimDefaultValue")){const t=await this.options.get("monacoEditorOptions");t.value&&(t.value=U.trimDefaultValue(t.value),await this.options.set("monacoEditorOptions",t))}await this.validateOptions(),this.monaco=await this.getMonacoInstance();const t=await this.options.get("monacoEditorCreator")||(async(t,e,i)=>U.createMonacoEditor(t,e,i));this.editor=await t(await this.options.get("monacoEditorOptions"),this.node,this.monaco)})()}getPriority(){return this.priority}async getMonacoInstance(){const t=await this.options.get("monaco");if(!t)throw new Error("Monaco instance is not available");return t}getValue(){return this.getEditor().getValue()}async alterDocument(t){const e=this.monaco;if(!e)throw new Error("Monaco instance is not available. Is wraplet initialized?");const i=this.getLanguage(),s="typescript"===i?await this.getTSValueAsJS(e):this.getValue(),r=await this.options.get("location"),n=q(i);if(H(n)){const e=F(n),i=await this.options.get("tagAttributes")??{},a=t.createElement(e);for(const[t,e]of Object.entries(i))a.setAttribute(t,e);return a.innerHTML=s,void t[r].appendChild(a)}t[r].innerHTML+=s}getDocumentAlterer(){return this.alterDocument}async validateOptions(){if(!(await this.options.get("monacoEditorOptions")).language)throw new Error("Missing language in monacoOptions");if(!H(q(this.getLanguage()))&&await this.options.get("tagAttributes"))throw new Error("'tagAttributes' option is only allowed for single tag types")}getEditor(){if(!this.editor)throw new Error("Editor is not initialized");return this.editor}async getTSValueAsJS(t){const e=this.getEditor().getModel();if(!e)throw new Error("Model is not available");t.languages.typescript.typescriptDefaults.setEagerModelSync(!0);const i=e.uri;if("file"!==i.scheme)throw new Error(`Model must use file:// URI, got: ${i.toString()}`);const s=async(e=10)=>{try{return await t.languages.typescript.getTypeScriptWorker()}catch(t){if("TypeScript not registered!"!==t)throw t;return e<=0?null:(await new Promise(t=>setTimeout(t,200)),s(e-1))}},r=await s();if(!r)throw new Error("Timeout: Could not get TypeScript worker");const n=await r(i);for(let t=0;t<20;t++)try{await n.getSemanticDiagnostics(i.toString());break}catch(t){if(/Could not find source file/.test(String(t))){await new Promise(t=>setTimeout(t,250));continue}throw t}const{outputFiles:a}=await n.getEmitOutput(i.toString());if(!a.length)throw new Error("No JS output produced");return a[0].text}getLanguage(){const t=this.monacoEditorOptions;if(!t)throw new Error("Monaco options are not available. Is wraplet initialized?");if(!t.language)throw new Error("Missing language in monacoOptions");return t.language}static trimDefaultValue(t){const e=t.split("\n"),i=e.find(t=>t.trim().length>0);if(!i)return t.trim();const s=i.search(/\S|$/);return e.map(t=>t.length>=s&&""===t.substring(0,s).trim()?t.substring(s):t).join("\n").trim()}async destroy(){return W({core:this.core,wraplet:this,destroyListeners:this.destroyListeners,status:this.status},async()=>{this.editor?.dispose()})()}static createMonacoEditor(t={},e,i){const s=t.language;if(!s)throw new Error("Missing language in editorOptions");const r=this.createMonacoModel(i,s,t.value||"");return i.editor.create(e,{...t,model:r})}static createMonacoModel(t,e,i){const s=Math.random().toString(36).substring(2,15);return t.editor.createModel(i,e,t.Uri.parse(`file:///${e}-${s}.ts`))}static create(t,e){const i=new I(t,{});return new U(i,e)}}const B="data-js-exhibition";function _(t){return{editors:{selector:t.editors.selector,multiple:!0,required:!1,Class:t.editors.Class,args:t.editors.args||[]},preview:{selector:t.preview.selector,multiple:!1,required:!0,Class:t.preview.Class,args:t.preview.args||[]}}}class R extends L{status={isInitialized:!1,isDestroyed:!1,isGettingInitialized:!1,isGettingDestroyed:!1};options;constructor(t,e={},i){if(super(t),void 0!==i&&!j(i))throw new Error("Provided optionsStorage must be a KeyValueStorage");const s=i??new k(!0,this.node,"data-js-options",{},{updaterSelector:t=>"string"==typeof t});this.options=new G(s,{updaterSelector:"[data-js-exhibition-updater]",...e},{updaterSelector:t=>"string"==typeof t}),this.wraplet=x({status:this.status,initialize:this.initialize.bind(this)},this.wraplet)}supportedNodeTypes(){return super.supportedNodeTypesGuard([HTMLElement])}async initialize(){return z({core:this.core,status:this.status,destroyCallback:this.wraplet.destroy},async()=>{if(this.status.isInitialized)throw new Error("Exhibition is already initialized");for(const t of this.children.editors)t.wraplet.status.isInitialized||t.wraplet.status.isGettingInitialized||await t.wraplet.initialize(),this.children.preview.hasDocumentAlterer(t.getDocumentAlterer())||this.addPreviewAlterer(t.getDocumentAlterer(),t.getPriority());const t=this.node.querySelectorAll(await this.options.get("updaterSelector"));for(const e of t)this.core.addEventListener(e,"click",()=>{this.updatePreview()})})()}addEditor(t){this.children.editors.add(t),this.children.preview.addDocumentAlterer(t.getDocumentAlterer())}removeEditor(t){this.children.editors.delete(t),this.children.preview.removeDocumentAlterer(t.getDocumentAlterer())}hasEditor(t){return this.children.editors.has(t)}addPreviewAlterer(t,e=0){this.children.preview.addDocumentAlterer(t,e)}getPreview(){return this.children.preview}async updatePreview(){await this.children.preview.update()}static async createMultiple(t,e,i={},s={},r=B){s=this.fillCreateOptionsWithDefaults(s),this.validateInitOptions(s,e);const n=this.createWraplets(t,e,r,[i]);for(const t of n)await this.applyCreateOptions(t,s);return n}static async create(t,e,i={},s={}){s=this.fillCreateOptionsWithDefaults(s),this.validateInitOptions(s,e);const r=new I(t,e),n=new R(r,i);return await this.applyCreateOptions(n,s),n}static fillCreateOptionsWithDefaults(t){return{init:!0,updatePreview:!1,...t}}static validateInitOptions(t,e){if(t.init&&void 0===e.editors.selector)throw new Error("Cannot initialize exhibition with undefined editors.selector");if(!t.init&&t.updatePreview)throw new Error("Cannot update preview without initializing exhibitions first")}static async applyCreateOptions(t,e={}){if(!e.init&&e.updatePreview)throw new Error("'updatePreview' option cannot be enabled without the 'init' one because updating preview requires initialization.");e.init&&await t.initialize(),e.updatePreview&&await t.updatePreview()}static getMap(t){if(!t)throw new Error("Configuration must be provided.");const e=_({editors:{selector:null===t.editors.selector?void 0:"[data-js-exhibition-editor]",Class:U,args:[t.editors?.options,t.editors?.optionsStorage]},preview:{selector:null===t.preview?.selector?void 0:"iframe[data-js-exhibition-preview]",Class:N,args:[t.preview?.options,t.preview?.optionsStorage]}});if(null===t.editors.selector&&e.editors.Class instanceof U&&(!t.editors.options||!t.editors.options.monaco))throw new Error("When selecting ExhibitionMonacoEditor instances, you must provide the 'monaco' option in the editors options. To avoid this error, set 'disableSelector' or provide the 'monaco' option.");return e}static getCustomizedMap(t){if(!t)throw new Error("Configuration must be provided.");return _(t)}}var J=exports;for(var K in e)J[K]=e[K];e.__esModule&&Object.defineProperty(J,"__esModule",{value:!0});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|