diff --git a/ts/editable/editable-container.ts b/ts/editable/editable-container.ts index 68f06a14a..645006b7a 100644 --- a/ts/editable/editable-container.ts +++ b/ts/editable/editable-container.ts @@ -5,10 +5,41 @@ @typescript-eslint/no-non-null-assertion: "off", */ +function loadStyleLink(container: Node, href: string): Promise { + const rootStyle = document.createElement("link"); + rootStyle.setAttribute("rel", "stylesheet"); + rootStyle.setAttribute("href", href); + + let styleResolve: () => void; + const stylePromise = new Promise((resolve) => (styleResolve = resolve)); + + rootStyle.addEventListener("load", () => styleResolve()); + container.appendChild(rootStyle); + + return stylePromise; +} + +function loadStyleTag(container: Node): [HTMLStyleElement, Promise] { + const style = document.createElement("style"); + style.setAttribute("rel", "stylesheet"); + + let styleResolve: () => void; + const stylePromise = new Promise((resolve) => (styleResolve = resolve)); + + style.addEventListener("load", () => styleResolve()); + container.appendChild(style); + + return [style, stylePromise]; +} + export class EditableContainer extends HTMLDivElement { baseStyle: HTMLStyleElement; + imageStyle: HTMLStyleElement; + + imagePromise: Promise; + stylePromise: Promise; + baseRule?: CSSStyleRule; - imageStyle?: HTMLStyleElement; constructor() { super(); @@ -18,15 +49,19 @@ export class EditableContainer extends HTMLDivElement { this.classList.add("night-mode"); } - const rootStyle = document.createElement("link"); - rootStyle.setAttribute("rel", "stylesheet"); - rootStyle.setAttribute("href", "./_anki/css/editable-build.css"); - shadow.appendChild(rootStyle); + const rootPromise = loadStyleLink(shadow, "./_anki/css/editable-build.css"); + const [baseStyle, basePromise] = loadStyleTag(shadow); + const [imageStyle, imagePromise] = loadStyleTag(shadow); - this.baseStyle = document.createElement("style"); - this.baseStyle.setAttribute("rel", "stylesheet"); - this.baseStyle.id = "baseStyle"; - shadow.appendChild(this.baseStyle); + this.baseStyle = baseStyle; + this.imageStyle = imageStyle; + + this.imagePromise = imagePromise; + this.stylePromise = Promise.all([ + rootPromise, + basePromise, + imagePromise, + ]) as unknown as Promise; } connectedCallback(): void { diff --git a/ts/editor/editing-area.ts b/ts/editor/editing-area.ts index c2d36cd30..88cd1028c 100644 --- a/ts/editor/editing-area.ts +++ b/ts/editor/editing-area.ts @@ -39,12 +39,7 @@ export class EditingArea extends HTMLDivElement { is: "anki-editable-container", }) as EditableContainer; - const imageStyle = document.createElement("style"); - imageStyle.setAttribute("rel", "stylesheet"); - imageStyle.id = "imageHandleStyle"; - this.editable = document.createElement("anki-editable") as Editable; - this.editableContainer.shadowRoot!.appendChild(imageStyle); this.editableContainer.shadowRoot!.appendChild(this.editable); this.appendChild(this.editableContainer); @@ -55,18 +50,18 @@ export class EditingArea extends HTMLDivElement { ); let imageHandleResolve: (value: ImageHandle) => void; - this.imageHandle = new Promise((resolve) => { - imageHandleResolve = resolve; - }); + this.imageHandle = new Promise( + (resolve) => (imageHandleResolve = resolve) + ); - imageStyle.addEventListener("load", () => + this.editableContainer.imagePromise.then(() => imageHandleResolve( new ImageHandle({ target: this, anchor: this.editableContainer, props: { container: this.editable, - sheet: imageStyle.sheet, + sheet: this.editableContainer.imageStyle.sheet, }, context, } as any) @@ -105,6 +100,7 @@ export class EditingArea extends HTMLDivElement { set fieldHTML(content: string) { this.imageHandle.then(() => { let result = content; + for (const component of decoratedComponents) { result = component.toUndecorated(result); } @@ -149,8 +145,10 @@ export class EditingArea extends HTMLDivElement { } initialize(color: string, content: string): void { - this.setBaseColor(color); - this.fieldHTML = content; + this.editableContainer.stylePromise.then(() => { + this.setBaseColor(color); + this.fieldHTML = content; + }); } setBaseColor(color: string): void {