From b60ab5e8c9dbfa3f27ae354f546214ced47b3cc5 Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Mon, 20 Oct 2025 22:33:55 +0100 Subject: [PATCH 1/2] Add Monaco styles to shadow-wrapped Imagine widget in Console --- src/lib/studio/monaco-style-manager.ts | 94 ++++++++++++++++++++++++++ src/lib/studio/studio-widget.ts | 4 +- 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/lib/studio/monaco-style-manager.ts diff --git a/src/lib/studio/monaco-style-manager.ts b/src/lib/studio/monaco-style-manager.ts new file mode 100644 index 0000000000..7a60b77165 --- /dev/null +++ b/src/lib/studio/monaco-style-manager.ts @@ -0,0 +1,94 @@ +const MONACO_STYLE_ATTRIBUTE = 'data-appwrite-studio-monaco-style'; + +const MONACO_STYLE_SELECTORS = [ + 'link[rel="stylesheet"][data-name^="vs/"]', + 'style[data-name^="vs/"]', + 'link[rel="stylesheet"][href*="monaco-editor"]' +] as const; + +let monacoStyleObserver: MutationObserver | null = null; + +function collectMonacoStyleNodes(): Element[] { + if (typeof document === 'undefined') { + return []; + } + + const nodes: Element[] = []; + for (const selector of MONACO_STYLE_SELECTORS) { + document.head?.querySelectorAll(selector).forEach((node) => { + nodes.push(node); + }); + } + return nodes; +} + +function getMonacoStyleKey(node: Element): string | null { + const tag = node.tagName.toLowerCase(); + const dataName = node.getAttribute('data-name'); + if (dataName) { + return `${tag}:${dataName}`; + } + + const id = node.getAttribute('id'); + if (id) { + return `${tag}#${id}`; + } + + if (node instanceof HTMLLinkElement && node.href) { + return `${tag}:${node.href}`; + } + + if (node instanceof HTMLStyleElement && node.textContent) { + let hash = 0; + for (let index = 0; index < node.textContent.length; index += 1) { + hash = (hash << 5) - hash + node.textContent.charCodeAt(index); + hash |= 0; + } + return `${tag}:text-${hash}`; + } + + return null; +} + +function syncMonacoStyles(shadow: ShadowRoot) { + if (typeof document === 'undefined') { + return; + } + + const existingKeys = new Set( + Array.from( + shadow.querySelectorAll(`[${MONACO_STYLE_ATTRIBUTE}]`) + ).map((existing) => existing.getAttribute(MONACO_STYLE_ATTRIBUTE) ?? '') + ); + + for (const node of collectMonacoStyleNodes()) { + const key = getMonacoStyleKey(node); + if (!key || existingKeys.has(key)) { + continue; + } + + const clone = node.cloneNode(true) as HTMLElement; + clone.setAttribute(MONACO_STYLE_ATTRIBUTE, key); + shadow.appendChild(clone); + existingKeys.add(key); + } +} + +export function ensureMonacoStyles(shadow: ShadowRoot) { + syncMonacoStyles(shadow); + + if ( + monacoStyleObserver || + typeof MutationObserver === 'undefined' || + typeof document === 'undefined' + ) { + return; + } + + monacoStyleObserver = new MutationObserver(() => { + syncMonacoStyles(shadow); + }); + + monacoStyleObserver.observe(document.head, { childList: true }); +} + diff --git a/src/lib/studio/studio-widget.ts b/src/lib/studio/studio-widget.ts index 376169dc9a..4b35bd353b 100644 --- a/src/lib/studio/studio-widget.ts +++ b/src/lib/studio/studio-widget.ts @@ -5,12 +5,12 @@ import { app } from '$lib/stores/app'; import { get } from 'svelte/store'; import { goto } from '$app/navigation'; import { resolve } from '$app/paths'; +import { ensureMonacoStyles } from './monaco-style-manager'; const COMPONENT_SELECTOR = 'imagine-web-components-wrapper[data-appwrite-studio]'; const STYLE_ATTRIBUTE = 'data-appwrite-studio-style'; const BLOCK_START_BASE_OFFSET = 48; const INLINE_START_BASE_OFFSET = 8; - let component: HTMLElement | null = null; let configInitialized = false; let routingInitialized = false; @@ -79,6 +79,7 @@ function injectStyles(node: HTMLElement, attempt = 0) { } if (shadow.querySelector(`link[${STYLE_ATTRIBUTE}]`)) { + ensureMonacoStyles(shadow); return; } @@ -87,6 +88,7 @@ function injectStyles(node: HTMLElement, attempt = 0) { link.href = ImagineCss; link.setAttribute(STYLE_ATTRIBUTE, 'true'); shadow.prepend(link); + ensureMonacoStyles(shadow); }) .catch(() => { /* no-op */ From f1fd8c19c68363cee99da7f43179d6862a7e243a Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 17 Nov 2025 22:34:55 +0400 Subject: [PATCH 2/2] Format dockerize-profiles workflow and fix newline - Align dockerize-profiles workflow indentation and step blocks - Restore trailing newline in monaco-style-manager.ts --- .github/workflows/dockerize-profiles.yml | 84 ++++++++++++------------ src/lib/studio/monaco-style-manager.ts | 2 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/.github/workflows/dockerize-profiles.yml b/.github/workflows/dockerize-profiles.yml index 8e09a234a4..aafa95f324 100644 --- a/.github/workflows/dockerize-profiles.yml +++ b/.github/workflows/dockerize-profiles.yml @@ -1,49 +1,49 @@ name: Dockerize Profiles on: - push: - branches: [feat-profiles] - pull_request: - types: [opened, synchronize, reopened] - branches: [feat-profiles] - workflow_dispatch: + push: + branches: [feat-profiles] + pull_request: + types: [opened, synchronize, reopened] + branches: [feat-profiles] + workflow_dispatch: jobs: - dockerize-profiles: - runs-on: ubuntu-latest - - steps: - - name: Checkout the repo - uses: actions/checkout@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ vars.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + dockerize-profiles: + runs-on: ubuntu-latest - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 - with: - images: appwrite/console-profiles - tags: | - type=ref,event=branch,prefix=branch- - type=ref,event=pr - type=sha,prefix=sha- - type=raw,value=gh-${{ github.run_id}} - flavor: | - latest=false + steps: + - name: Checkout the repo + uses: actions/checkout@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push Docker image - id: push - uses: docker/build-push-action@v6 - with: - context: . - push: true - platforms: linux/amd64,linux/arm64 - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: appwrite/console-profiles + tags: | + type=ref,event=branch,prefix=branch- + type=ref,event=pr + type=sha,prefix=sha- + type=raw,value=gh-${{ github.run_id}} + flavor: | + latest=false + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/src/lib/studio/monaco-style-manager.ts b/src/lib/studio/monaco-style-manager.ts index c10c825539..3f71f8fe47 100644 --- a/src/lib/studio/monaco-style-manager.ts +++ b/src/lib/studio/monaco-style-manager.ts @@ -50,4 +50,4 @@ export function ensureMonacoStyles(shadow: ShadowRoot) { }); monacoStyleObserver.observe(document.head, { childList: true }); -} \ No newline at end of file +}