From 385b0b6a9c4de4f7deb67fd3abf50bbc06e62b60 Mon Sep 17 00:00:00 2001 From: wangcch Date: Tue, 4 Mar 2025 23:14:19 +0800 Subject: [PATCH] feat(store): resourceLinks to custom cdn --- src/monaco/env.ts | 24 ++++++++++++++++++++++-- src/monaco/vue.worker.ts | 38 +++++++++++++++++++++++++++++++++++--- src/output/Sandbox.vue | 5 +++++ src/output/srcdoc.html | 10 ++++------ src/store.ts | 28 +++++++++++++++++++++++++++- 5 files changed, 93 insertions(+), 12 deletions(-) diff --git a/src/monaco/env.ts b/src/monaco/env.ts index 8074bba9..b434ec96 100644 --- a/src/monaco/env.ts +++ b/src/monaco/env.ts @@ -122,6 +122,10 @@ export interface WorkerMessage { event: 'init' tsVersion: string tsLocale?: string + pkgDirUrl?: string + pkgFileTextUrl?: string + pkgLatestVersionUrl?: string + typescriptLib?: string } export function loadMonacoEnv(store: Store) { @@ -135,11 +139,27 @@ export function loadMonacoEnv(store: Store) { resolve() } }) - worker.postMessage({ + + const { + pkgDirUrl, + pkgFileTextUrl, + pkgLatestVersionUrl: pkgVersionLatestUrl, + typescriptLib, + } = store.resourceLinks || {} + + const message: WorkerMessage = { event: 'init', tsVersion: store.typescriptVersion, tsLocale: store.locale, - } satisfies WorkerMessage) + pkgDirUrl: pkgDirUrl ? String(pkgDirUrl) : undefined, + pkgFileTextUrl: pkgFileTextUrl ? String(pkgFileTextUrl) : undefined, + pkgLatestVersionUrl: pkgVersionLatestUrl + ? String(pkgVersionLatestUrl) + : undefined, + typescriptLib: typescriptLib ? String(typescriptLib) : undefined, + } + + worker.postMessage(message) }) await init return worker diff --git a/src/monaco/vue.worker.ts b/src/monaco/vue.worker.ts index d61870ca..61867043 100644 --- a/src/monaco/vue.worker.ts +++ b/src/monaco/vue.worker.ts @@ -23,13 +23,35 @@ export interface CreateData { dependencies: Record } +function createFunc(func?: string) { + if (func && typeof func === 'string') { + return Function(`return ${func}`)() + } + return undefined +} + let ts: typeof import('typescript') let locale: string | undefined +let resourceLinks: Record< + keyof Pick< + WorkerMessage, + 'pkgDirUrl' | 'pkgFileTextUrl' | 'pkgLatestVersionUrl' + >, + ((...args: any[]) => string) | undefined +> self.onmessage = async (msg: MessageEvent) => { if (msg.data?.event === 'init') { locale = msg.data.tsLocale - ts = await importTsFromCdn(msg.data.tsVersion) + ts = await importTsFromCdn( + msg.data.tsVersion, + createFunc(msg.data.typescriptLib), + ) + resourceLinks = { + pkgDirUrl: createFunc(msg.data.pkgDirUrl), + pkgFileTextUrl: createFunc(msg.data.pkgFileTextUrl), + pkgLatestVersionUrl: createFunc(msg.data.pkgLatestVersionUrl), + } self.postMessage('inited') return } @@ -61,6 +83,11 @@ self.onmessage = async (msg: MessageEvent) => { content, ) }, + { + getPackageDirectoryUrl: resourceLinks.pkgDirUrl, + getPackageFileTextUrl: resourceLinks.pkgFileTextUrl, + getPackageLatestVersionUrl: resourceLinks.pkgLatestVersionUrl, + }, ), } @@ -98,10 +125,15 @@ self.onmessage = async (msg: MessageEvent) => { ) } -async function importTsFromCdn(tsVersion: string) { +async function importTsFromCdn( + tsVersion: string, + getTsCdn?: (version?: string) => string, +) { const _module = globalThis.module ;(globalThis as any).module = { exports: {} } - const tsUrl = `https://cdn.jsdelivr.net/npm/typescript@${tsVersion}/lib/typescript.js` + const tsUrl = + getTsCdn?.(tsVersion) || + `https://cdn.jsdelivr.net/npm/typescript@${tsVersion}/lib/typescript.js` await import(/* @vite-ignore */ tsUrl) const ts = globalThis.module.exports globalThis.module = _module diff --git a/src/output/Sandbox.vue b/src/output/Sandbox.vue index eba9c688..43977c99 100644 --- a/src/output/Sandbox.vue +++ b/src/output/Sandbox.vue @@ -128,6 +128,11 @@ function createSandbox() { //, previewOptions.value?.placeholderHTML || '', ) + .replace( + //, + store.value.resourceLinks?.esModuleShims || + 'https://cdn.jsdelivr.net/npm/es-module-shims@1.5.18/dist/es-module-shims.wasm.js', + ) sandbox.srcdoc = sandboxSrc containerRef.value?.appendChild(sandbox) diff --git a/src/output/srcdoc.html b/src/output/srcdoc.html index 189c19ca..407bbd91 100644 --- a/src/output/srcdoc.html +++ b/src/output/srcdoc.html @@ -6,8 +6,9 @@ color-scheme: dark; } body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, + Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } @@ -361,10 +362,7 @@ - + diff --git a/src/store.ts b/src/store.ts index 2508b679..5a690e8a 100644 --- a/src/store.ts +++ b/src/store.ts @@ -48,6 +48,7 @@ export function useStore( typescriptVersion = ref('latest'), dependencyVersion = ref(Object.create(null)), reloadLanguageTools = ref(), + resourceLinks = undefined, }: Partial = {}, serializedState?: string, ): ReplStore { @@ -92,7 +93,9 @@ export function useStore( vueVersion, async (version) => { if (version) { - const compilerUrl = `https://cdn.jsdelivr.net/npm/@vue/compiler-sfc@${version}/dist/compiler-sfc.esm-browser.js` + const compilerUrl = + resourceLinks?.value?.vueCompilerUrl?.(version) || + `https://cdn.jsdelivr.net/npm/@vue/compiler-sfc@${version}/dist/compiler-sfc.esm-browser.js` loading.value = true compiler.value = await import(/* @vite-ignore */ compilerUrl).finally( () => (loading.value = false), @@ -389,6 +392,8 @@ export function useStore( deserialize, getFiles, setFiles, + + resourceLinks, }) return store } @@ -414,6 +419,21 @@ export interface SFCOptions { template?: Partial } +export type ResourceLinkConfigs = { + esModuleShims?: string + vueCompilerUrl?: (version: string) => string + typescriptLib?: (version: string) => string + // for monaco + pkgLatestVersionUrl?: (pkgName: string) => string + pkgDirUrl?: (pkgName: string, pkgVersion: string, pkgPath: string) => string + pkgFileTextUrl?: ( + path: string, + pkgName: string, + pkgVersion: string | undefined, + pkgPath: string, + ) => string +} + export type StoreState = ToRefs<{ files: Record activeFilename: string @@ -440,6 +460,9 @@ export type StoreState = ToRefs<{ /** \{ dependencyName: version \} */ dependencyVersion: Record reloadLanguageTools?: (() => void) | undefined + + /** Custom online resources */ + resourceLinks?: ResourceLinkConfigs }> export interface ReplStore extends UnwrapRef { @@ -463,6 +486,8 @@ export interface ReplStore extends UnwrapRef { deserialize(serializedState: string, checkBuiltinImportMap?: boolean): void getFiles(): Record setFiles(newFiles: Record, mainFile?: string): Promise + /** Custom online resources */ + resourceLinks?: ResourceLinkConfigs } export type Store = Pick< @@ -487,6 +512,7 @@ export type Store = Pick< | 'renameFile' | 'getImportMap' | 'getTsConfig' + | 'resourceLinks' > export class File {