UNPKG

@dotglitch/ngx-common

Version:

Angular components and utilities that are commonly used.

851 lines (839 loc) 34.4 kB
import * as i0 from '@angular/core'; import { EventEmitter, HostListener, Input, Output, Component } from '@angular/core'; import { debounceTime } from 'rxjs'; import * as path from 'path-browserify'; class DependencyParser { constructor() { this.REGEX_NODE_MODULE = /^node:([\w\W\/]+)$/; } // https://github.com/lukasbach/monaco-editor-auto-typings/commit/fc046e7d9a2abbb5121ad8ab25195d8c1c277416 parseDependencies(source, parent) { const importRegex = /import *.+ *from *['"](?<importPath>.+?)['"]/g; const dynamicImportRegex = /await import ?\(['"](?<importPath>.+?)['"]\)/g; const cjsRequireRegex = /require *\(['"](?<importPath>.+?)['"]\)/g; const matches = [ ...source.matchAll(importRegex), ...source.matchAll(dynamicImportRegex), ...source.matchAll(cjsRequireRegex) ]; const importPaths = matches.map(match => match.groups?.['importPath']); const result = importPaths.map(imp => this.resolvePath(imp, parent)); return result; } resolvePath(importPath, parent) { const nodeImport = importPath.match(this.REGEX_NODE_MODULE); if (nodeImport) { return { kind: 'relative-in-package', packageName: '@types/node', importPath: `${nodeImport[1]}.d.ts`, sourcePath: '', }; } if (typeof parent === 'string') { if (importPath.startsWith('.')) { return { kind: 'relative', importPath, sourcePath: parent, }; } else if (importPath.startsWith('@')) { const segments = importPath.split('/'); return { kind: 'package', packageName: `${segments[0]}/${segments[1]}`, importPath: segments.slice(2).join('/'), }; } else { const segments = importPath.split('/'); return { kind: 'package', packageName: segments[0], importPath: segments.slice(1).join('/'), }; } } else { switch (parent.kind) { case 'package': throw Error('TODO?'); case 'relative': throw Error('TODO2?'); case 'relative-in-package': if (importPath.startsWith('.')) { return { kind: 'relative-in-package', packageName: parent.packageName, sourcePath: path.join(parent.sourcePath, parent.importPath), importPath: importPath, }; } else if (importPath.startsWith('@')) { const segments = importPath.split('/'); return { kind: 'package', packageName: `${segments[0]}/${segments[1]}`, importPath: segments.slice(2).join('/'), }; } else { const segments = importPath.split('/'); return { kind: 'package', packageName: segments[0], importPath: segments.slice(1).join('/'), }; } } } return null; } } const invokeUpdate = (progress, options) => { let textual = `${progress.type}: `; switch (progress.type) { case 'CodeChanged': textual += ``; break; case 'ResolveNewImports': textual += ``; break; // case 'DetectedImport': // textual += `at "${progress.source}" the import "${progress.importPath}" was detected`; // break; // case 'CompletedImport': // textual += `at "${progress.source}" the import "${progress.importPath}" was completed`; // break; case 'LookedUpTypeFile': textual += `"${progress.path}" was ${progress.success ? 'sucessfully' : 'not sucessfully'} looked up`; break; case 'AttemptedLookUpFile': textual += `"${progress.path}" was ${progress.success ? 'sucessfully' : 'not sucessfully'} attempted to looked up`; // What in the hell is this grammar? break; case 'LookedUpPackage': textual += `package.json for package "${progress.package}" was ${progress.success ? 'sucessfully' : 'not sucessfully'} looked up${progress.definitelyTyped ? ' (found in definitely typed repo)' : ''}`; break; case 'LoadedFromCache': textual += `"${progress.importPath}" was loaded from cache`; break; case 'StoredToCache': textual += `"${progress.importPath}" was stored to cache`; break; } if (textual.endsWith(': ')) { textual = textual.slice(undefined, -2); } options.onUpdate?.(progress, textual); }; class RecursionDepth { constructor(options, fileRecursionDepth = 0, packageRecursionDepth = 0) { this.options = options; this.fileRecursionDepth = fileRecursionDepth; this.packageRecursionDepth = packageRecursionDepth; } nextPackage() { return new RecursionDepth(this.options, this.fileRecursionDepth, this.packageRecursionDepth + 1); } nextFile() { return new RecursionDepth(this.options, this.fileRecursionDepth + 1, this.packageRecursionDepth); } same() { return new RecursionDepth(this.options, this.fileRecursionDepth, this.packageRecursionDepth); } shouldStop() { return ((this.options.fileRecursionDepth > 0 && this.fileRecursionDepth >= this.options.fileRecursionDepth) || (this.options.packageRecursionDepth > 0 && this.packageRecursionDepth >= this.options.packageRecursionDepth)); } } const importResourcePathToString = (p) => { switch (p.kind) { case 'package': return path.join(p.packageName, p.importPath ?? '', 'package.json'); case 'relative': return path.join(p.sourcePath, p.importPath); case 'relative-in-package': return path.join(p.packageName, p.sourcePath, p.importPath); case 'bruteforce': throw new Error("Not Implemented"); } }; class UnpkgSourceResolver { static async resolvePackageJson(packageName, version, subPath) { return await this.resolveFile(`https://unpkg.com/${packageName}${version ? `@${version}` : ''}${subPath ? `/${subPath}` : ''}/package.json`); } static async resolveSourceFile(packageName, version, path) { return await this.resolveFile(`https://unpkg.com/${packageName}${version ? `@${version}` : ''}/${path}`); } static async resolveFile(url) { const res = await fetch(url, { method: 'GET' }); if (res.ok) { return await res.text(); } else if (res.status === 404) { return ''; } else { throw Error(`Error other than 404 while fetching from Unpkg at ${url}`); } } } class ImportResolver { constructor(options) { this.options = options; this.loadedFiles = []; this.dependencyParser = new DependencyParser(); this.cache = options.sourceCache; this.newImportsResolved = false; this.monaco = options.monaco; if (options.preloadPackages && options.versions) { this.versions = options.versions; for (const [packageName, version] of Object.entries(options.versions)) { this.resolveImport({ kind: 'package', packageName: packageName, importPath: '', }, new RecursionDepth(this.options)).catch(e => { console.error(e); }); } } } wereNewImportsResolved() { return this.newImportsResolved; } resetNewImportsResolved() { this.newImportsResolved = false; } async resolveImportsInFile(source, parent, depth) { if (depth.shouldStop()) { return; } const imports = this.dependencyParser.parseDependencies(source, parent); for (const importCall of imports) { try { await this.resolveImport(importCall, depth); } catch (e) { if (this.options.onError) { this.options.onError?.(e.message ?? e); } else { console.error(e); } } } } async resolveImport(importResource, depth) { const hash = this.hashImportResourcePath(importResource); if (this.loadedFiles.includes(hash)) { return; } this.loadedFiles.push(hash); console.log("resolveImport", importResource, depth); // Ignore these package imports as they are well-known to be pointless. if (importResource.kind == "package" && importResource.packageName == "require") return null; switch (importResource.kind) { case 'package': const packageRelativeImport = await this.resolveImportFromPackageRoot(importResource); if (packageRelativeImport) { return await this.resolveImportInPackage(packageRelativeImport, depth.nextPackage().nextFile()); } break; case 'relative': throw Error('Not implemented yet'); case 'relative-in-package': return await this.resolveImportInPackage(importResource, depth.nextFile()); case 'bruteforce': { } } } async resolveImportInPackage(importResource, depth) { console.log("resolveImportInPackage", importResource, depth); const contents = await this.loadSourceFileContents(importResource); if (contents) { const { source, at } = contents; this.createModel(source, this.monaco.Uri.parse(this.options.fileRootPath + path.join(`node_modules/${importResource.packageName}`, at))); await this.resolveImportsInFile(source, { kind: 'relative-in-package', packageName: importResource.packageName, sourcePath: path.dirname(at), importPath: '', }, depth); } } async resolveImportFromPackageRoot(importResource) { console.log("resolveImportFromPackageRoot", importResource); const failedProgressUpdate = { type: 'LookedUpPackage', package: importResource.packageName, definitelyTyped: false, success: false, }; if (this.options.onlySpecifiedPackages) { if (!this.versions?.[importResource.packageName] && !this.versions?.['@types/' + importResource.packageName]) { invokeUpdate(failedProgressUpdate, this.options); return null; } } const doesPkgJsonHasSubpath = importResource.importPath?.length ?? 0 > 0; let pkgJsonSubpath = doesPkgJsonHasSubpath ? `/${importResource.importPath}` : ''; let pkgJson = await this.resolvePackageJson(importResource.packageName, this.versions?.[importResource.packageName], doesPkgJsonHasSubpath ? importResource.importPath : undefined); if (!pkgJson && doesPkgJsonHasSubpath) { pkgJson = await this.resolvePackageJson(importResource.packageName, this.versions?.[importResource.packageName]); pkgJsonSubpath = ''; } if (!pkgJson) return invokeUpdate(failedProgressUpdate, this.options); const pkg = JSON.parse(pkgJson); console.log("package meta", pkg); if (pkg.typings || pkg.types) { const typings = pkg.typings || pkg.types; this.createModel(pkgJson, this.monaco.Uri.parse(`${this.options.fileRootPath}node_modules/${importResource.packageName}${pkgJsonSubpath}/package.json`)); invokeUpdate({ type: 'LookedUpPackage', package: importResource.packageName, definitelyTyped: false, success: true, }, this.options); this.setVersion(importResource.packageName, pkg.version); return { kind: 'relative-in-package', packageName: importResource.packageName, sourcePath: '', importPath: path.join(importResource.importPath ?? '', typings.startsWith('./') ? typings.slice(2) : typings), }; } else { const typingPackageName = `@types/${importResource.packageName.startsWith('@') ? importResource.packageName.slice(1).replace(/\//, '__') : importResource.packageName}`; const pkgJsonTypings = await this.resolvePackageJson(typingPackageName, this.versions?.[typingPackageName]); if (!pkgJsonTypings) return invokeUpdate(failedProgressUpdate, this.options); const pkg = JSON.parse(pkgJsonTypings); if (!pkg.typings && !pkg.types) { const files = await fetch("https://www.npmjs.com/package/@dt-esa/dynatrace-api-client/v/2.2.6/index", { method: "get" }).then(e => e.json()); const typingFiles = Object.entries(files.files).map(([key, val]) => val); invokeUpdate({ type: 'LookedUpPackage', package: typingPackageName, definitelyTyped: true, success: true, }, this.options); return { kind: 'bruteforce', packageName: typingPackageName, typingFiles, }; return; // return invokeUpdate(failedProgressUpdate, this.options); } const typings = pkg.typings || pkg.types; this.createModel(pkgJsonTypings, this.monaco.Uri.parse(`${this.options.fileRootPath}node_modules/${typingPackageName}/package.json`)); invokeUpdate({ type: 'LookedUpPackage', package: typingPackageName, definitelyTyped: true, success: true, }, this.options); this.setVersion(typingPackageName, pkg.version); return { kind: 'relative-in-package', packageName: typingPackageName, sourcePath: '', importPath: path.join(importResource.importPath ?? '', typings.startsWith('./') ? typings.slice(2) : typings), }; } } async loadSourceFileContents(importResource) { const progressUpdatePath = path.join(importResource.packageName, importResource.sourcePath, importResource.importPath); const failedProgressUpdate = { type: 'LookedUpTypeFile', path: progressUpdatePath, definitelyTyped: false, success: false, }; const pkgName = importResource.packageName; const version = this.getVersion(importResource.packageName); let appends = ['.d.ts', '/index.d.ts', '.ts', '.tsx', '/index.ts', '/index.tsx']; if (appends.map(append => importResource.importPath.endsWith(append)).reduce((a, b) => a || b, false)) { const source = await this.resolveSourceFile(pkgName, version, path.join(importResource.sourcePath, importResource.importPath)); if (source) { return { source, at: path.join(importResource.sourcePath, importResource.importPath) }; } } else { for (const append of appends) { const fullPath = path.join(importResource.sourcePath, importResource.importPath) + append; const source = await this.resolveSourceFile(pkgName, version, fullPath); invokeUpdate({ type: 'AttemptedLookUpFile', path: path.join(pkgName, fullPath), success: !!source, }, this.options); if (source) { invokeUpdate({ type: 'LookedUpTypeFile', path: path.join(pkgName, fullPath), success: true, }, this.options); return { source, at: fullPath }; } } } const pkgJson = await this.resolvePackageJson(pkgName, version, path.join(importResource.sourcePath, importResource.importPath)); if (pkgJson) { const { types } = JSON.parse(pkgJson); if (types) { const fullPath = path.join(importResource.sourcePath, importResource.importPath, types); const source = await this.resolveSourceFile(pkgName, version, fullPath); if (source) { invokeUpdate({ type: 'LookedUpTypeFile', path: path.join(pkgName, fullPath), success: true, }, this.options); return { source, at: fullPath }; } } } invokeUpdate(failedProgressUpdate, this.options); return null; } getVersion(packageName) { return this.versions?.[packageName]; } setVersions(versions) { this.versions = versions; this.options.onUpdateVersions?.(versions); // TODO reload packages whose version has changed } setVersion(packageName, version) { this.setVersions({ ...this.versions, [packageName]: version, }); } createModel(source, uri) { uri = uri.with({ path: uri.path.replace('@types/', '') }); if (!this.monaco.editor.getModel(uri)) { this.monaco.editor.createModel(source, 'typescript', uri); this.newImportsResolved = true; } } hashImportResourcePath(p) { return importResourcePathToString(p); } async resolvePackageJson(packageName, version, subPath) { const uri = path.join(packageName + (version ? `@${version}` : ''), subPath ?? '', 'package.json'); let isAvailable = false; let content = undefined; if (this.cache.isFileAvailable) { isAvailable = await this.cache.isFileAvailable(uri); } else { content = await this.cache.getFile(uri); isAvailable = content !== undefined; } if (isAvailable) { return content ?? (await this.cache.getFile(uri)); } else { console.log("recursing resolvePackageJson", packageName, version, subPath); content = await UnpkgSourceResolver.resolvePackageJson(packageName, version, subPath); if (content) { this.cache.storeFile(uri, content); } return content; } } async resolveSourceFile(packageName, version, filePath) { const uri = path.join(packageName + (version ? `@${version}` : ''), filePath); let isAvailable = false; let content = undefined; if (this.cache.isFileAvailable) { isAvailable = await this.cache.isFileAvailable(uri); } else { content = await this.cache.getFile(uri); isAvailable = content !== undefined; } if (isAvailable) { invokeUpdate({ type: 'LoadedFromCache', importPath: uri, }, this.options); return content ?? (await this.cache.getFile(uri)); } else { content = await UnpkgSourceResolver.resolveSourceFile(packageName, version, filePath); if (content) { invokeUpdate({ type: 'StoredToCache', importPath: uri, }, this.options); this.cache.storeFile(uri, content); } return content; } } } class DummySourceCache { getFile(uri) { return undefined; } async isFileAvailable(uri) { return false; } storeFile(uri, content) { return undefined; } clear() { return undefined; } } // https://github.com/lukasbach/monaco-editor-auto-typings class MonacoAutoTypeImporter { constructor(editor, options) { this.editor = editor; this.options = options; this.disposables = []; this.importResolver = new ImportResolver(options); const changeModelDisposable = editor.onDidChangeModelContent(e => { this.debouncedResolveContents(); }); this.disposables.push(changeModelDisposable); this.resolveContents(); if (!options.dontAdaptEditorOptions) { options.monaco.languages.typescript.typescriptDefaults.setCompilerOptions({ ...options.monaco.languages.typescript.typescriptDefaults.getCompilerOptions(), moduleResolution: options.monaco.languages.typescript.ModuleResolutionKind.NodeJs, allowSyntheticDefaultImports: true, rootDir: options.fileRootPath, }); } } static async create(editor, options) { if (options?.shareCache && options.sourceCache && !MonacoAutoTypeImporter.sharedCache) { MonacoAutoTypeImporter.sharedCache = options.sourceCache; } const monacoInstance = options?.monaco ?? window['monaco']; if (!monacoInstance) { throw new Error('monacoInstance not found, you can specify the monaco instance via options.monaco'); } return new MonacoAutoTypeImporter(editor, { fileRootPath: 'inmemory://model/', onlySpecifiedPackages: false, preloadPackages: false, shareCache: false, dontAdaptEditorOptions: false, dontRefreshModelValueAfterResolvement: false, sourceCache: MonacoAutoTypeImporter.sharedCache ?? new DummySourceCache(), debounceDuration: 4000, fileRecursionDepth: 10, packageRecursionDepth: 3, ...options, monaco: monacoInstance, }); } dispose() { this.disposables.forEach(d => d.dispose()); } setVersions(versions) { this.importResolver.setVersions(versions); this.options.versions = versions; } async clearCache() { await this.options.sourceCache.clear(); } debouncedResolveContents() { if (this.isResolving) { return; } invokeUpdate({ type: 'CodeChanged' }, this.options); if (this.options.debounceDuration <= 0) { this.resolveContents(); } else { if (this.debounceTimer !== undefined) { clearTimeout(this.debounceTimer); } this.debounceTimer = setTimeout(async () => { await this.resolveContents(); this.debounceTimer = undefined; }, this.options.debounceDuration); } } async resolveContents() { this.isResolving = true; invokeUpdate({ type: 'ResolveNewImports' }, this.options); const model = this.editor.getModel(); // This can happen when the editor is disposed before all typings // are installed. if (!model) { throw Error('No model'); } const content = model.getLinesContent(); try { await this.importResolver.resolveImportsInFile(content.join('\n'), path.dirname(model.uri.toString()), new RecursionDepth(this.options)); } catch (e) { if (this.options.onError) { this.options.onError(e.message ?? e); } else { throw e; } } if (this.importResolver.wereNewImportsResolved()) { if (!this.options.dontRefreshModelValueAfterResolvement) { const currentPosition = this.editor.getPosition(); model.setValue(model.getValue()); if (currentPosition) { this.editor.setPosition(currentPosition); } } this.importResolver.resetNewImportsResolved(); } this.isResolving = false; } } let Monaco; class MonacoEditorComponent { set code(value) { if (value == this._code) return; if (typeof value != "string") throw new TypeError("Value must be of type string"); this._code = value; this.editor?.setValue(this.code); } ; get code() { return this._code?.trim(); } set language(value) { this._language = { 'ts': "typescript", 'html': 'xml', 'scss': 'css' }[value] || value || "auto"; } get language() { return this._language; } get settings() { return { ...this.restSettings, theme: this.theme, language: this.language, tabSize: this.tabSize, readOnly: this.readOnly, fontFamily: this.fontFamily, fontSize: this.fontSize, automaticLayout: this.automaticLayout, scrollBeyondLastLine: this.scrollBeyondLastLine, colorDecorators: this.colorDecorators, folding: this.folding, scrollBeyondLastColumn: this.scrollBeyondLastColumn, minimap: this.minimap, scrollbar: this.scrollbar, smoothScrolling: this.smoothScrolling, mouseWheelScrollSensitivity: this.mouseWheelScrollSensitivity, lineNumbers: this.lineNumbers }; } constructor(viewContainer) { this.viewContainer = viewContainer; this.isDirty = false; this.codeChange = new EventEmitter(); this.onCodeType = new EventEmitter(); this.typeDebounce = this.onCodeType.pipe(debounceTime(100)); this.installationLocation = "/lib/monaco/vs"; this.tabSize = 2; this.readOnly = false; this.theme = "vs-dark"; this.fontFamily = "Droid Sans Mono"; this.fontSize = 14; this.automaticLayout = true; this.colorDecorators = true; this.folding = true; this.minimapEnabled = true; this.minimap = { enabled: true }; this.scrollbar = { alwaysConsumeMouseWheel: false, // scrollByPage: true }; this.smoothScrolling = true; this.mouseWheelScrollSensitivity = 2; this.scrollBeyondLastLine = false; this.scrollBeyondLastColumn = 0; this.lineNumbers = "on"; this.restSettings = {}; this.resize = () => { this.editor?.layout(); }; this._sub = this.typeDebounce.subscribe(t => { this.codeChange.next(this._code = this.editor.getValue()); }); } ngOnInit() { InstallMonacoUMD(this.installationLocation); } ngOnChanges(changes) { // If we changed anything OTHER than code, reload the editor if (Object.keys(changes).length > 1 || !changes['code']) { if (this.editor) { this.editor?.dispose(); this.createEditor(); } } if (changes['theme']) window['monaco']?.editor.setTheme(this.theme); } async ngAfterViewInit() { await InstallMonacoUMD(); this.createEditor(); } ngOnDestroy() { this.editor?.dispose(); this._sub?.unsubscribe(); } createEditor() { if (this.customLanguage) { this.customLanguage.init(window['monaco']); } let editor = this.editor = window['monaco'].editor.create(this.viewContainer?.element?.nativeElement, this.settings); // const autoTypings = await MonacoAutoTypeImporter.create(editor, { monaco: Monaco, }); this.configureLanguageSupport(); if (this.code) { editor.setValue(this.code); } editor.getModel().onDidChangeContent(() => this.onCodeType.emit()); } configureLanguageSupport() { } download() { const code = this.editor.getValue(); let blob = new Blob([code], { type: 'text/log' }); let elm = document.createElement('a'); let blobURL = URL.createObjectURL(blob); // Set the data values. elm.href = blobURL; elm.download = this.filename; document.body.appendChild(elm); elm.click(); document.body.removeChild(elm); elm.remove(); URL.revokeObjectURL(blobURL); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MonacoEditorComponent, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: MonacoEditorComponent, isStandalone: true, selector: "ngx-monaco-editor", inputs: { code: "code", customLanguage: "customLanguage", language: "language", installationLocation: "installationLocation", tabSize: "tabSize", readOnly: "readOnly", theme: "theme", fontFamily: "fontFamily", fontSize: "fontSize", automaticLayout: "automaticLayout", colorDecorators: "colorDecorators", folding: "folding", minimapEnabled: "minimapEnabled", minimap: "minimap", scrollbar: "scrollbar", smoothScrolling: "smoothScrolling", mouseWheelScrollSensitivity: "mouseWheelScrollSensitivity", scrollBeyondLastLine: "scrollBeyondLastLine", scrollBeyondLastColumn: "scrollBeyondLastColumn", lineNumbers: "lineNumbers", restSettings: "restSettings" }, outputs: { codeChange: "codeChange" }, host: { listeners: { "window:resize": "resize($event)" } }, usesOnChanges: true, ngImport: i0, template: '', isInline: true, styles: [":host{display:block;height:100%;max-height:100vh;max-width:100vw}\n"] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MonacoEditorComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-monaco-editor', template: '', standalone: true, styles: [":host{display:block;height:100%;max-height:100vh;max-width:100vw}\n"] }] }], ctorParameters: () => [{ type: i0.ViewContainerRef }], propDecorators: { code: [{ type: Input }], codeChange: [{ type: Output }], customLanguage: [{ type: Input }], language: [{ type: Input }], installationLocation: [{ type: Input }], tabSize: [{ type: Input }], readOnly: [{ type: Input }], theme: [{ type: Input }], fontFamily: [{ type: Input }], fontSize: [{ type: Input }], automaticLayout: [{ type: Input }], colorDecorators: [{ type: Input }], folding: [{ type: Input }], minimapEnabled: [{ type: Input }], minimap: [{ type: Input }], scrollbar: [{ type: Input }], smoothScrolling: [{ type: Input }], mouseWheelScrollSensitivity: [{ type: Input }], scrollBeyondLastLine: [{ type: Input }], scrollBeyondLastColumn: [{ type: Input }], lineNumbers: [{ type: Input }], restSettings: [{ type: Input }], resize: [{ type: HostListener, args: ['window:resize', ['$event']] }] } }); const InstallMonacoUMD = async (path) => { if (window['monaco']) return window['monaco']; // Prevent duplicate injection const scriptEls = document.querySelectorAll('body>script[monaco][defer][src]'); // Only perform installation if a path is specified. if (path && scriptEls.length == 0) { // Monaco has a UMD loader that requires this // Merge with any pre-existing global require objects. if (!window['require']) window['require'] = {}; if (!window['require']['paths']) window['require']['paths'] = {}; if (path.endsWith('/')) path = path.slice(0, -1); window['require']['paths'].vs = path; const monacoFiles = [ 'loader.js', 'editor/editor.main.nls.js', 'editor/editor.main.js', ]; for (let i = 0; i < monacoFiles.length; i++) { const script = document.createElement("script"); script.setAttribute("monaco", ""); script.setAttribute("defer", ""); script.setAttribute("src", path + '/' + monacoFiles[i]); document.body.append(script); } } // Return a promise that will resolve when monaco finishes loading return await new Promise((res, rej) => { let count = 0; let i = window.setInterval(() => { count++; if (window['monaco'] != undefined) { window.clearInterval(i); res(true); } else if (count >= 100) { window.clearInterval(i); res(false); } }, 100); }); }; /** * Generated bundle index. Do not edit. */ export { InstallMonacoUMD, MonacoEditorComponent }; //# sourceMappingURL=dotglitch-ngx-common-monaco-editor.mjs.map