exhibitionjs 0.24.0 → 0.25.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 +26 -24
- package/dist/ExhibitionMonacoEditor.d.ts +1 -0
- package/dist/ExhibitionPreview.d.ts +10 -2
- package/dist/TypeMap.d.ts +0 -9
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/selectors.d.ts +0 -1
- package/dist/types/PreviewWraplet.d.ts +8 -0
- package/package.json +1 -1
package/dist/Exhibition.d.ts
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
import { AbstractWraplet, Constructable, Core } from "wraplet";
|
|
2
|
-
import {
|
|
2
|
+
import { ExhibitionPreviewOptions } from "./ExhibitionPreview";
|
|
3
3
|
import { ExhibitionMonacoEditorOptions } from "./ExhibitionMonacoEditor";
|
|
4
4
|
import { DocumentAltererProviderWraplet } from "./types/DocumentAltererProviderWraplet";
|
|
5
5
|
import { KeyValueStorage } from "wraplet/storage";
|
|
6
|
-
import {
|
|
6
|
+
import { PreviewWraplet } from "./types/PreviewWraplet";
|
|
7
7
|
export type ExhibitionOptions = {
|
|
8
8
|
/**
|
|
9
9
|
* Selector for the element that triggers the update of the preview.
|
|
10
10
|
*/
|
|
11
11
|
updaterSelector?: string;
|
|
12
12
|
};
|
|
13
|
-
export type
|
|
13
|
+
export type ExhibitionInitOptions = {
|
|
14
14
|
init?: boolean;
|
|
15
15
|
updatePreview?: boolean;
|
|
16
16
|
};
|
|
17
|
-
export type
|
|
17
|
+
export type PreviewOptionsWrapper<O, IS_REQUIRED extends boolean = false> = IS_REQUIRED extends true ? {
|
|
18
|
+
previewOptions: O;
|
|
19
|
+
} : {
|
|
20
|
+
previewOptions?: O;
|
|
21
|
+
};
|
|
22
|
+
export type EditorsOptionsWrapper<O, IS_REQUIRED extends boolean = false> = IS_REQUIRED extends true ? {
|
|
23
|
+
editorsOptions: O;
|
|
24
|
+
} : {
|
|
25
|
+
editorsOptions?: O;
|
|
26
|
+
};
|
|
27
|
+
export type ExhibitionMapOptions<EO extends EditorsOptionsWrapper<unknown, boolean> | undefined = EditorsOptionsWrapper<ExhibitionMonacoEditorOptions, true>, PO extends PreviewOptionsWrapper<unknown, boolean> | undefined = PreviewOptionsWrapper<ExhibitionPreviewOptions>> = {
|
|
18
28
|
Class?: Constructable<DocumentAltererProviderWraplet>;
|
|
19
29
|
selectEditors?: boolean;
|
|
20
|
-
};
|
|
30
|
+
} & (EO extends undefined ? EditorsOptionsWrapper<ExhibitionMonacoEditorOptions, true> : EO) & (PO extends undefined ? PreviewOptionsWrapper<ExhibitionPreviewOptions> : PO);
|
|
21
31
|
declare const ExhibitionMap: {
|
|
22
32
|
editors: {
|
|
23
33
|
selector: string | undefined;
|
|
@@ -30,7 +40,8 @@ declare const ExhibitionMap: {
|
|
|
30
40
|
selector: string;
|
|
31
41
|
multiple: false;
|
|
32
42
|
required: true;
|
|
33
|
-
Class:
|
|
43
|
+
Class: Constructable<PreviewWraplet>;
|
|
44
|
+
args: unknown[];
|
|
34
45
|
};
|
|
35
46
|
};
|
|
36
47
|
export declare class Exhibition extends AbstractWraplet<HTMLElement, typeof ExhibitionMap> {
|
|
@@ -54,8 +65,8 @@ export declare class Exhibition extends AbstractWraplet<HTMLElement, typeof Exhi
|
|
|
54
65
|
/**
|
|
55
66
|
* Adds a simple DocumentAlterer to the preview.
|
|
56
67
|
*/
|
|
57
|
-
addPreviewAlterer
|
|
58
|
-
getPreview():
|
|
68
|
+
private addPreviewAlterer;
|
|
69
|
+
getPreview(): PreviewWraplet;
|
|
59
70
|
updatePreview(): Promise<void>;
|
|
60
71
|
/**
|
|
61
72
|
* Create multiple Exhibitions.
|
|
@@ -63,46 +74,37 @@ export declare class Exhibition extends AbstractWraplet<HTMLElement, typeof Exhi
|
|
|
63
74
|
* @param node Node to create Exhibitions on.
|
|
64
75
|
* @param map Map of dependencies for each Exhibition instance.
|
|
65
76
|
* @param options Options for Exhibition instances.
|
|
66
|
-
* @param
|
|
77
|
+
* @param initOptions Options related to the creation process of the Exhibitions.
|
|
67
78
|
* @param attribute Attribute to use for Exhibition instances.
|
|
68
79
|
*
|
|
69
80
|
* @returns Array of Exhibition instances.
|
|
70
81
|
*/
|
|
71
|
-
static createMultiple(node: ParentNode, map:
|
|
82
|
+
static createMultiple<M extends typeof ExhibitionMap = typeof ExhibitionMap>(node: ParentNode, map: M, options?: ExhibitionOptions, initOptions?: ExhibitionInitOptions, attribute?: string): Promise<Exhibition[]>;
|
|
72
83
|
/**
|
|
73
84
|
* Create a single Exhibition instance wrapping a given element.
|
|
74
85
|
*
|
|
75
86
|
* @param element Element to wrap.
|
|
76
87
|
* @param map Map of dependencies for the Exhibition instance.
|
|
77
88
|
* @param options Options for the Exhibition instance.
|
|
78
|
-
* @param
|
|
89
|
+
* @param initOptions Options related to the creation process of the Exhibitions.
|
|
79
90
|
*/
|
|
80
|
-
static create(element: HTMLElement, map:
|
|
91
|
+
static create<M extends typeof ExhibitionMap = typeof ExhibitionMap>(element: HTMLElement, map: M, options?: ExhibitionOptions, initOptions?: ExhibitionInitOptions): Promise<Exhibition>;
|
|
81
92
|
private static fillCreateOptionsWithDefaults;
|
|
82
93
|
/**
|
|
83
94
|
* Validate create options.
|
|
84
95
|
*/
|
|
85
|
-
private static
|
|
96
|
+
private static validateInitOptions;
|
|
86
97
|
/**
|
|
87
98
|
* Create options.
|
|
88
99
|
*/
|
|
89
100
|
private static applyCreateOptions;
|
|
90
|
-
/**
|
|
91
|
-
* Returns a dependency map with editors being instances of ExhibitionMonacoEditor.
|
|
92
|
-
*
|
|
93
|
-
* @param exhibitionMonacoEditorOptions
|
|
94
|
-
* MonacoEditorOptions to pass to the ExhibitionMonacoEditor.
|
|
95
|
-
* @param options
|
|
96
|
-
* Map options.
|
|
97
|
-
*/
|
|
98
|
-
static getMapWithMonacoEditor(exhibitionMonacoEditorOptions: ExhibitionMonacoEditorOptions, options?: Omit<ExhibitionMapOptions, "Class">): typeof ExhibitionMap;
|
|
99
101
|
/**
|
|
100
102
|
* Returns a generic dependecy map with an undefined editor class that has to be provided through
|
|
101
103
|
* the options.
|
|
102
104
|
*
|
|
103
|
-
* @param
|
|
105
|
+
* @param mapOptions
|
|
104
106
|
* Map options.
|
|
105
107
|
*/
|
|
106
|
-
static getMap(
|
|
108
|
+
static getMap<O extends ExhibitionMapOptions<EditorsOptionsWrapper<unknown, boolean>, PreviewOptionsWrapper<unknown, boolean>> = ExhibitionMapOptions>(mapOptions?: NoInfer<O>): typeof ExhibitionMap;
|
|
107
109
|
}
|
|
108
110
|
export {};
|
|
@@ -47,6 +47,7 @@ export declare class ExhibitionMonacoEditor extends AbstractWraplet<HTMLElement>
|
|
|
47
47
|
protected supportedNodeTypes(): readonly Constructable<HTMLElement>[];
|
|
48
48
|
initialize(): Promise<void>;
|
|
49
49
|
getPriority(): number;
|
|
50
|
+
private getMonacoInstance;
|
|
50
51
|
/**
|
|
51
52
|
* Returns the current value of the editor.
|
|
52
53
|
*/
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import { AbstractWraplet, Constructable } from "wraplet";
|
|
1
|
+
import { AbstractWraplet, Constructable, Core } from "wraplet";
|
|
2
2
|
import { DocumentAlterer } from "./types/DocumentAlterer";
|
|
3
|
-
|
|
3
|
+
import { KeyValueStorage } from "wraplet/storage";
|
|
4
|
+
import { PreviewWraplet } from "./types/PreviewWraplet";
|
|
5
|
+
export type ExhibitionPreviewOptions = {
|
|
6
|
+
updateHeight?: boolean;
|
|
7
|
+
updateHeightCallback?: (preview: ExhibitionPreview) => Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
export declare class ExhibitionPreview extends AbstractWraplet<HTMLIFrameElement> implements PreviewWraplet {
|
|
4
10
|
private alterers;
|
|
5
11
|
private currentBlobUrl;
|
|
12
|
+
private options;
|
|
13
|
+
constructor(core: Core<HTMLIFrameElement>, options?: ExhibitionPreviewOptions, optionsStorage?: KeyValueStorage<Partial<ExhibitionPreviewOptions>>);
|
|
6
14
|
protected supportedNodeTypes(): readonly Constructable<HTMLIFrameElement>[];
|
|
7
15
|
/**
|
|
8
16
|
* Adds a DocumentAlterer to the preview.
|
package/dist/TypeMap.d.ts
CHANGED
|
@@ -13,20 +13,11 @@ export declare const typeMap: {
|
|
|
13
13
|
readonly tag: "style";
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
|
-
export type LanguagesWithSingleTags = {
|
|
17
|
-
[K in ValueTypes]: (typeof typeMap)[K]["tag"] extends undefined ? never : (typeof typeMap)[K]["languages"][number];
|
|
18
|
-
}[ValueTypes];
|
|
19
16
|
export type TypeFromLanguage<L extends MonacoEditorLanguages> = {
|
|
20
17
|
[K in ValueTypes]: L extends (typeof typeMap)[K]["languages"][number] ? K : never;
|
|
21
18
|
}[ValueTypes];
|
|
22
|
-
export type TagFromLanguage<L extends MonacoEditorLanguages> = (typeof typeMap)[{
|
|
23
|
-
[K in ValueTypes]: L extends (typeof typeMap)[K]["languages"][number] ? K : never;
|
|
24
|
-
}[ValueTypes]]["tag"];
|
|
25
19
|
export type ValueTypes = keyof typeof typeMap;
|
|
26
20
|
export type MonacoEditorLanguages = (typeof typeMap)[ValueTypes]["languages"][number];
|
|
27
21
|
export declare function getTypeFromLanguage<T extends MonacoEditorLanguages>(language: T): TypeFromLanguage<T>;
|
|
28
22
|
export declare function getTagFromType<T extends ValueTypes>(type: T): (typeof typeMap)[T]["tag"];
|
|
29
|
-
export declare function isSingleTagValue(item: Partial<PreviewValue> & {
|
|
30
|
-
type: ValueTypes;
|
|
31
|
-
}): item is Extract<PreviewValue, IsSingleTag>;
|
|
32
23
|
export declare function isSingleTagType(type: ValueTypes): type is Extract<PreviewValue, IsSingleTag>["type"];
|
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:()=>B,ExhibitionMonacoEditor:()=>F,defaultOptionsAttribute:()=>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 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 A{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 I=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;[I]=!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 A(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 j=Symbol("KeyValueStorage");class P extends Error{}class T{storage;defaults;validators;[j]=!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 P(`Got an invalid value for the key ${String(t)}.`)}validateSetValue(t,e){if(!this.validators[t](e))throw new P(`Attempted to set an invalid value for the key ${String(t)}.`)}}class G{isPartial;defaults;validators;[j]=!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 P(`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 P("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 P(`No validator found for the value: ${e}`);if(this.validators[e]&&!this.validators[e](t[e]))throw new P(`Value for '${e}' has been discarded by the validator.`)}}validateValidators(t){for(const e in t)if("function"!=typeof t[e])throw new P(`Validator for ${e} is not a function.`)}}class N 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)}}const V={html:{languages:["html"],tag:void 0},js:{languages:["javascript","typescript"],tag:"script"},css:{languages:["css"],tag:"style"}};function k(t){for(const[e,i]of Object.entries(V))if(i.languages.includes(t))return e;throw new Error("Unknown language")}function $(t){return V[t].tag}function q(t){return Boolean($(t))}class F 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 N(!0,t.node,"data-js-options",{},{},{elementOptionsMerger:(t,i)=>(i.monacoEditorOptions={...t.monacoEditorOptions,...e.monacoEditorOptions,...i.monacoEditorOptions},{...t,...e,...i})});this.options=new T(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=F.trimDefaultValue(t.value),await this.options.set("monacoEditorOptions",t))}await this.validateOptions(),this.monaco=await this.options.get("monaco");const t=await this.options.get("monacoEditorCreator")||(async(t,e,i)=>F.createMonacoEditor(t,e,i));this.editor=await t(await this.options.get("monacoEditorOptions"),this.node,this.monaco)})()}getPriority(){return this.priority}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=k(i);if(q(n)){const e=$(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(!q(k(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 A(t,{});return new F(i,e)}}const U="data-js-options",H={editors:{selector:"[data-js-exhibition-editor]",multiple:!0,required:!1,Class:F,args:[]},preview:{selector:"iframe[data-js-exhibition-preview]",multiple:!1,required:!0,Class:class extends L{alterers=[];currentBlobUrl=null;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=()=>{setTimeout(()=>{this.updateHeight()},100),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}}}};class B extends L{status={isInitialized:!1,isDestroyed:!1,isGettingInitialized:!1,isGettingDestroyed:!1};options;constructor(t,e={},i){super(t);const s=i??new N(!0,this.node,"data-js-options",{},{updaterSelector:t=>"string"==typeof t});this.options=new T(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="data-js-exhibition"){s=this.fillCreateOptionsWithDefaults(s),this.validateCreateOptions(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.validateCreateOptions(s,e);const r=new A(t,e),n=new B(r,i);return await this.applyCreateOptions(n,s),n}static fillCreateOptionsWithDefaults(t){return{init:!0,updatePreview:!1,...t}}static validateCreateOptions(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 getMapWithMonacoEditor(t,e={}){const i={...e,Class:F},s=this.getMap(i);return s.editors.args=[t],s}static getMap(t){const e=H,i={selectEditors:!0,Class:F,...t};return e.editors.Class=i.Class,i.selectEditors||(e.editors.selector=void 0),e}}var _=exports;for(var R in e)_[R]=e[R];e.__esModule&&Object.defineProperty(_,"__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:()=>_,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 h extends Error{}function d(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&&d(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(d(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(!d(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(d(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 h&&!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 h(`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 j extends Error{}class T{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 j(`Got an invalid value for the key ${String(t)}.`)}validateSetValue(t,e){if(!this.validators[t](e))throw new j(`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 j(`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 j("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 j(`No validator found for the value: ${e}`);if(this.validators[e]&&!this.validators[e](t[e]))throw new j(`Value for '${e}' has been discarded by the validator.`)}}validateValidators(t){for(const e in t)if("function"!=typeof t[e])throw new j(`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 T(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 T(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 T(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),e.editors.Class instanceof H&&i.editorsOptions&&!i.editorsOptions.monaco)throw new Error("When using ExhibitionMonacoEditor as editors class, you must provide the 'monaco' option in the editors options.");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});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|