@dotglitch/ngx-common
Version:
Angular components and utilities that are commonly used.
1 lines • 72.7 kB
Source Map (JSON)
{"version":3,"file":"dotglitch-ngx-common-monaco-editor.mjs","sources":["../../packages/common/monaco-editor/ts-type-resolver/dependency-parser.ts","../../packages/common/monaco-editor/ts-type-resolver/update-emitter.ts","../../packages/common/monaco-editor/ts-type-resolver/recursion-depth.ts","../../packages/common/monaco-editor/ts-type-resolver/types.ts","../../packages/common/monaco-editor/ts-type-resolver/unpkg-source-resolver.ts","../../packages/common/monaco-editor/ts-type-resolver/import-resolver.ts","../../packages/common/monaco-editor/ts-type-resolver/dummy-source-cache.ts","../../packages/common/monaco-editor/ts-type-resolver/main.ts","../../packages/common/monaco-editor/monaco-editor.component.ts","../../packages/common/monaco-editor/dotglitch-ngx-common-monaco-editor.ts"],"sourcesContent":["import * as path from 'path-browserify';\nimport { ImportResourcePath } from './types';\n\nexport class DependencyParser {\n private REGEX_NODE_MODULE = /^node:([\\w\\W\\/]+)$/;\n\n // https://github.com/lukasbach/monaco-editor-auto-typings/commit/fc046e7d9a2abbb5121ad8ab25195d8c1c277416\n public parseDependencies(source: string, parent: ImportResourcePath | string): ImportResourcePath[] {\n const importRegex = /import *.+ *from *['\"](?<importPath>.+?)['\"]/g;\n const dynamicImportRegex = /await import ?\\(['\"](?<importPath>.+?)['\"]\\)/g;\n const cjsRequireRegex = /require *\\(['\"](?<importPath>.+?)['\"]\\)/g;\n\n const matches = [\n ...source.matchAll(importRegex),\n ...source.matchAll(dynamicImportRegex),\n ...source.matchAll(cjsRequireRegex)\n ];\n const importPaths = matches.map(match => match.groups?.['importPath']);\n const result = importPaths.map(imp => this.resolvePath(imp, parent));\n\n return result\n }\n\n private resolvePath(importPath: string, parent: ImportResourcePath | string): ImportResourcePath {\n const nodeImport = importPath.match(this.REGEX_NODE_MODULE);\n if (nodeImport) {\n return {\n kind: 'relative-in-package',\n packageName: '@types/node',\n importPath: `${nodeImport[1]}.d.ts`,\n sourcePath: '',\n };\n }\n\n if (typeof parent === 'string') {\n if (importPath.startsWith('.')) {\n return {\n kind: 'relative',\n importPath,\n sourcePath: parent,\n };\n }\n else if (importPath.startsWith('@')) {\n const segments = importPath.split('/');\n return {\n kind: 'package',\n packageName: `${segments[0]}/${segments[1]}`,\n importPath: segments.slice(2).join('/'),\n };\n }\n else {\n const segments = importPath.split('/');\n return {\n kind: 'package',\n packageName: segments[0],\n importPath: segments.slice(1).join('/'),\n };\n }\n }\n else {\n switch (parent.kind) {\n case 'package':\n throw Error('TODO?');\n case 'relative':\n throw Error('TODO2?');\n case 'relative-in-package':\n if (importPath.startsWith('.')) {\n return {\n kind: 'relative-in-package',\n packageName: parent.packageName,\n sourcePath: path.join(parent.sourcePath, parent.importPath),\n importPath: importPath,\n };\n }\n else if (importPath.startsWith('@')) {\n const segments = importPath.split('/');\n return {\n kind: 'package',\n packageName: `${segments[0]}/${segments[1]}`,\n importPath: segments.slice(2).join('/'),\n };\n }\n else {\n const segments = importPath.split('/');\n return {\n kind: 'package',\n packageName: segments[0],\n importPath: segments.slice(1).join('/'),\n };\n }\n }\n }\n return null;\n }\n}\n","import { ProgressUpdate, Options } from './types';\n\nexport const invokeUpdate = (progress: ProgressUpdate, options: Options) => {\n let textual = `${progress.type}: `;\n\n switch (progress.type) {\n case 'CodeChanged':\n textual += ``;\n break;\n case 'ResolveNewImports':\n textual += ``;\n break;\n // case 'DetectedImport':\n // textual += `at \"${progress.source}\" the import \"${progress.importPath}\" was detected`;\n // break;\n // case 'CompletedImport':\n // textual += `at \"${progress.source}\" the import \"${progress.importPath}\" was completed`;\n // break;\n case 'LookedUpTypeFile':\n textual += `\"${progress.path}\" was ${progress.success ? 'sucessfully' : 'not sucessfully'} looked up`;\n break;\n case 'AttemptedLookUpFile':\n textual += `\"${progress.path}\" was ${\n progress.success ? 'sucessfully' : 'not sucessfully'\n } attempted to looked up`; // What in the hell is this grammar?\n break;\n case 'LookedUpPackage':\n textual += `package.json for package \"${progress.package}\" was ${\n progress.success ? 'sucessfully' : 'not sucessfully'\n } looked up${progress.definitelyTyped ? ' (found in definitely typed repo)' : ''}`;\n break;\n case 'LoadedFromCache':\n textual += `\"${progress.importPath}\" was loaded from cache`;\n break;\n case 'StoredToCache':\n textual += `\"${progress.importPath}\" was stored to cache`;\n break;\n }\n\n if (textual.endsWith(': ')) {\n textual = textual.slice(undefined, -2);\n }\n\n options.onUpdate?.(progress, textual);\n};\n","import { Options } from './types';\n\nexport class RecursionDepth {\n constructor(private options: Options, private fileRecursionDepth = 0, private packageRecursionDepth = 0) {}\n\n public nextPackage() {\n return new RecursionDepth(this.options, this.fileRecursionDepth, this.packageRecursionDepth + 1);\n }\n\n public nextFile() {\n return new RecursionDepth(this.options, this.fileRecursionDepth + 1, this.packageRecursionDepth);\n }\n\n public same() {\n return new RecursionDepth(this.options, this.fileRecursionDepth, this.packageRecursionDepth);\n }\n\n public shouldStop() {\n return (\n (this.options.fileRecursionDepth > 0 && this.fileRecursionDepth >= this.options.fileRecursionDepth) ||\n (this.options.packageRecursionDepth > 0 && this.packageRecursionDepth >= this.options.packageRecursionDepth)\n );\n }\n}\n","import type * as monaco from 'monaco-editor';\nimport * as path from 'path-browserify';\n\nexport interface SourceCache {\n isFileAvailable?: (uri: string) => Promise<boolean>;\n storeFile: (uri: string, content: string) => Promise<void>;\n getFile: (uri: string) => Promise<string | undefined>;\n clear: () => Promise<void>;\n}\n\nexport type ProgressUpdate =\n | {\n type: 'CodeChanged';\n }\n | {\n type: 'ResolveNewImports';\n }\n | {\n type: 'LookedUpTypeFile';\n path: string;\n success: boolean;\n }\n | {\n type: 'AttemptedLookUpFile';\n path: string;\n success: boolean;\n }\n | {\n type: 'LookedUpPackage';\n package: string;\n definitelyTyped: boolean;\n success: boolean;\n }\n | {\n type: 'LoadedFromCache';\n importPath: string;\n }\n | {\n type: 'StoredToCache';\n importPath: string;\n };\n\n\n\nexport interface Options {\n /**\n * Share source cache between multiple editor instances by storing\n * the cache in a static property.\n *\n * Defaults to false.\n */\n shareCache: boolean;\n\n /**\n * Only use packages specified in the `versions` property.\n *\n * Defaults to false.\n */\n onlySpecifiedPackages: boolean;\n\n /**\n * Load typings from prespecified versions when initializing. Versions\n * need to be specified in the ``versions`` option.\n *\n * Defaults to false.\n */\n preloadPackages: boolean;\n\n /**\n * Updates compiler options to defaults suitable for auto-loaded\n * declarations, specifically by setting ``moduleResolution`` to\n * ``NodeJs`` and ``allowSyntheticDefaultImports`` to true.\n * Other options are not changed. Set this property to true to\n * disable this behaviour.\n *\n * Defaults to false.\n */\n dontAdaptEditorOptions: boolean;\n\n /**\n * After typings were resolved and injected into monaco, auto-typings\n * updates the value of the current model to trigger a refresh in\n * monaco's typing logic, so that it uses the injected typings.\n */\n dontRefreshModelValueAfterResolvement: boolean;\n\n /**\n * Prespecified package versions. If a package is loaded whose\n * name is specified in this object, it will load with the exact\n * version specified in the object.\n *\n * Example:\n *\n * ```json\n * {\n * \"@types/react\": \"17.0.0\",\n * \"csstype\": \"3.0.5\"\n * }\n * ```\n *\n * Setting the option ``onlySpecifiedPackages`` to true makes this\n * property act as a whitelist for packages.\n *\n * Setting the option ``preloadPackages`` makes the packages specified\n * in this property load directly after initializing the auto-loader.\n */\n versions?: { [packageName: string]: string; };\n\n /**\n * If a new package was loaded, its name and version is added to the\n * version object, and this method is called with the updated object.\n * @param versions updated versions object.\n */\n onUpdateVersions?: (versions: { [packageName: string]: string; }) => void;\n\n /**\n * Supply a cache where declaration files and package.json files are\n * cached to. Supply an instance of {@link LocalStorageCache} to cache\n * files to localStorage.\n */\n sourceCache: SourceCache;\n\n /**\n * The root directory where your edited files are. Must end with\n * a slash. The default is suitable unless you change the default\n * URI of files loaded in the editor.\n *\n * Defaults to \"inmemory://model/\"\n */\n fileRootPath: string;\n\n /**\n * Debounces code reanalyzing after user has changed the editor contents\n * by the specified amount. Set to zero to disable. Value provided in\n * milliseconds.\n *\n * Defaults to 4000, i.e. 4 seconds.\n */\n debounceDuration: number;\n\n /**\n * Maximum recursion depth for recursing packages. Determines how many\n * nested package declarations are loaded. For example, if ``packageRecursionDepth``\n * has the value 2, the code in the monaco editor references packages ``A1``, ``A2``\n * and ``A3``, package ``A1`` references package ``B1`` and ``B1`` references ``C1``,\n * then packages ``A1``, ``A2``, ``A3`` and ``B1`` are loaded. Set to zero to\n * disable.\n *\n * Defaults to 3.\n */\n packageRecursionDepth: number;\n\n /**\n * Maximum recursion depth for recursing files. Determines how many\n * nested file declarations are loaded. The same as ``packageRecursionDepth``,\n * but for individual files. Set to zero to disable.\n *\n * Defaults to 10.\n */\n fileRecursionDepth: number;\n\n /**\n * Called after progress updates like loaded declarations or events.\n * @param update detailed event object containing update infos.\n * @param textual a textual representation of the update for debugging.\n */\n onUpdate?: (update: ProgressUpdate, textual: string) => void;\n\n /**\n * Called if errors occur.\n * @param error a textual representation of the error.\n */\n onError?: (error: string) => void;\n /**\n * instance of monaco editor\n */\n monaco: typeof monaco;\n}\n\n\nexport interface ImportResourcePathPackage {\n kind: 'package';\n packageName: string;\n importPath?: string;\n}\n\nexport interface ImportResourcePathRelative {\n kind: 'relative';\n importPath: string;\n sourcePath: string;\n}\n\nexport interface ImportResourcePathRelativeInPackage {\n kind: 'relative-in-package';\n packageName: string;\n importPath: string;\n sourcePath: string;\n}\n\nexport interface ImportResourceBruteForce {\n kind: 'bruteforce';\n packageName: string;\n typingFiles: any[];\n}\n\nexport type ImportResourcePath =\n | ImportResourcePathPackage\n | ImportResourcePathRelative\n | ImportResourcePathRelativeInPackage\n | ImportResourceBruteForce;\n\nexport const importResourcePathToString = (p: ImportResourcePath) => {\n switch (p.kind) {\n case 'package':\n return path.join(p.packageName, p.importPath ?? '', 'package.json');\n case 'relative':\n return path.join(p.sourcePath, p.importPath);\n case 'relative-in-package':\n return path.join(p.packageName, p.sourcePath, p.importPath);\n case 'bruteforce':\n throw new Error(\"Not Implemented\");\n }\n};\n","\nexport class UnpkgSourceResolver {\n public static async resolvePackageJson(\n packageName: string,\n version: string | undefined,\n subPath: string | undefined\n ): Promise<string | undefined> {\n return await this.resolveFile(\n `https://unpkg.com/${packageName}${version ? `@${version}` : ''}${subPath ? `/${subPath}` : ''}/package.json`\n );\n }\n\n public static async resolveSourceFile(\n packageName: string,\n version: string | undefined,\n path: string\n ): Promise<string | undefined> {\n return await this.resolveFile(`https://unpkg.com/${packageName}${version ? `@${version}` : ''}/${path}`);\n }\n\n private static async resolveFile(url: string) {\n const res = await fetch(url, { method: 'GET' });\n\n if (res.ok) {\n return await res.text();\n }\n else if (res.status === 404) {\n return '';\n }\n else {\n throw Error(`Error other than 404 while fetching from Unpkg at ${url}`);\n }\n }\n}\n","import type * as monaco from 'monaco-editor';\nimport { DependencyParser } from './dependency-parser';\nimport * as path from 'path-browserify';\nimport { invokeUpdate } from './update-emitter';\nimport { RecursionDepth } from './recursion-depth';\nimport { ImportResourcePath, ImportResourcePathPackage, ImportResourcePathRelativeInPackage, Options, SourceCache, importResourcePathToString } from './types';\nimport { UnpkgSourceResolver } from './unpkg-source-resolver';\n\nexport class ImportResolver {\n private loadedFiles: string[];\n private dependencyParser: DependencyParser;\n private cache: SourceCache;\n private versions?: { [packageName: string]: string };\n private newImportsResolved: boolean;\n private monaco: typeof monaco;\n\n constructor(private options: Options) {\n this.loadedFiles = [];\n this.dependencyParser = new DependencyParser();\n this.cache = options.sourceCache;\n this.newImportsResolved = false;\n this.monaco = options.monaco!;\n\n if (options.preloadPackages && options.versions) {\n this.versions = options.versions;\n for (const [packageName, version] of Object.entries(options.versions)) {\n this.resolveImport(\n {\n kind: 'package',\n packageName: packageName,\n importPath: '',\n },\n new RecursionDepth(this.options)\n ).catch(e => {\n console.error(e);\n });\n }\n }\n }\n\n public wereNewImportsResolved() {\n return this.newImportsResolved;\n }\n\n public resetNewImportsResolved() {\n this.newImportsResolved = false;\n }\n\n public async resolveImportsInFile(source: string, parent: string | ImportResourcePath, depth: RecursionDepth) {\n if (depth.shouldStop()) {\n return;\n }\n\n const imports = this.dependencyParser.parseDependencies(source, parent);\n for (const importCall of imports) {\n try {\n await this.resolveImport(importCall, depth);\n }\n catch (e) {\n if (this.options.onError) {\n this.options.onError?.((e as Error).message ?? e);\n }\n else {\n console.error(e);\n }\n }\n }\n }\n\n private async resolveImport(importResource: ImportResourcePath, depth: RecursionDepth) {\n const hash = this.hashImportResourcePath(importResource);\n if (this.loadedFiles.includes(hash)) {\n return;\n }\n\n this.loadedFiles.push(hash);\n console.log(\"resolveImport\", importResource, depth);\n\n // Ignore these package imports as they are well-known to be pointless.\n if (importResource.kind == \"package\" && importResource.packageName == \"require\")\n return null;\n\n switch (importResource.kind) {\n case 'package':\n const packageRelativeImport = await this.resolveImportFromPackageRoot(importResource);\n if (packageRelativeImport) {\n return await this.resolveImportInPackage(packageRelativeImport, depth.nextPackage().nextFile());\n }\n break;\n case 'relative':\n throw Error('Not implemented yet');\n case 'relative-in-package':\n return await this.resolveImportInPackage(importResource, depth.nextFile());\n case 'bruteforce': {\n\n }\n }\n }\n\n private async resolveImportInPackage(importResource: ImportResourcePathRelativeInPackage, depth: RecursionDepth) {\n console.log(\"resolveImportInPackage\", importResource, depth);\n\n const contents = await this.loadSourceFileContents(importResource);\n\n if (contents) {\n const { source, at } = contents;\n this.createModel(\n source,\n this.monaco.Uri.parse(this.options.fileRootPath + path.join(`node_modules/${importResource.packageName}`, at))\n );\n\n await this.resolveImportsInFile(\n source,\n {\n kind: 'relative-in-package',\n packageName: importResource.packageName,\n sourcePath: path.dirname(at),\n importPath: '',\n },\n depth\n );\n }\n }\n\n private async resolveImportFromPackageRoot(\n importResource: ImportResourcePathPackage\n ): Promise<ImportResourcePathRelativeInPackage | void> {\n console.log(\"resolveImportFromPackageRoot\", importResource);\n\n const failedProgressUpdate = {\n type: 'LookedUpPackage',\n package: importResource.packageName,\n definitelyTyped: false,\n success: false,\n } as const;\n\n if (this.options.onlySpecifiedPackages) {\n if (!this.versions?.[importResource.packageName] && !this.versions?.['@types/' + importResource.packageName]) {\n invokeUpdate(failedProgressUpdate, this.options);\n return null;\n }\n }\n\n const doesPkgJsonHasSubpath = importResource.importPath?.length ?? 0 > 0;\n let pkgJsonSubpath = doesPkgJsonHasSubpath ? `/${importResource.importPath}` : '';\n let pkgJson = await this.resolvePackageJson(\n importResource.packageName,\n this.versions?.[importResource.packageName],\n doesPkgJsonHasSubpath ? importResource.importPath : undefined\n );\n\n if (!pkgJson && doesPkgJsonHasSubpath) {\n pkgJson = await this.resolvePackageJson(importResource.packageName, this.versions?.[importResource.packageName]);\n pkgJsonSubpath = '';\n }\n\n if (!pkgJson) return invokeUpdate(failedProgressUpdate, this.options);\n\n const pkg = JSON.parse(pkgJson);\n\n console.log(\"package meta\", pkg);\n\n if (pkg.typings || pkg.types) {\n const typings = pkg.typings || pkg.types;\n this.createModel(\n pkgJson,\n this.monaco.Uri.parse(\n `${this.options.fileRootPath}node_modules/${importResource.packageName}${pkgJsonSubpath}/package.json`\n )\n );\n\n invokeUpdate(\n {\n type: 'LookedUpPackage',\n package: importResource.packageName,\n definitelyTyped: false,\n success: true,\n },\n this.options\n );\n this.setVersion(importResource.packageName, pkg.version);\n\n return {\n kind: 'relative-in-package',\n packageName: importResource.packageName,\n sourcePath: '',\n importPath: path.join(importResource.importPath ?? '', typings.startsWith('./') ? typings.slice(2) : typings),\n };\n }\n else {\n\n const typingPackageName = `@types/${\n importResource.packageName.startsWith('@')\n ? importResource.packageName.slice(1).replace(/\\//, '__')\n : importResource.packageName\n }`;\n\n const pkgJsonTypings = await this.resolvePackageJson(typingPackageName, this.versions?.[typingPackageName]);\n\n if (!pkgJsonTypings)\n return invokeUpdate(failedProgressUpdate, this.options);\n\n const pkg = JSON.parse(pkgJsonTypings);\n\n if (!pkg.typings && !pkg.types) {\n const files: {\n fileCount: number,\n files: {\n [key: string]: {\n size: number,\n hex: string,\n type: \"File\",\n isBinary: \"true\" | \"false\",\n path: string,\n contentType: string\n }\n },\n integrity: string,\n shasum: string,\n totalSize: number\n } = await fetch(\"https://www.npmjs.com/package/@dt-esa/dynatrace-api-client/v/2.2.6/index\", {\n method: \"get\"\n }).then(e => e.json());\n\n const typingFiles = Object.entries(files.files).map(([key, val]) => val);\n\n invokeUpdate(\n {\n type: 'LookedUpPackage',\n package: typingPackageName,\n definitelyTyped: true,\n success: true,\n },\n this.options\n );\n\n return {\n kind: 'bruteforce',\n packageName: typingPackageName,\n typingFiles,\n } as any;\n\n return;\n // return invokeUpdate(failedProgressUpdate, this.options);\n }\n\n const typings = pkg.typings || pkg.types;\n this.createModel(\n pkgJsonTypings,\n this.monaco.Uri.parse(`${this.options.fileRootPath}node_modules/${typingPackageName}/package.json`)\n );\n\n invokeUpdate(\n {\n type: 'LookedUpPackage',\n package: typingPackageName,\n definitelyTyped: true,\n success: true,\n },\n this.options\n );\n this.setVersion(typingPackageName, pkg.version);\n\n return {\n kind: 'relative-in-package',\n packageName: typingPackageName,\n sourcePath: '',\n importPath: path.join(\n importResource.importPath ?? '',\n typings.startsWith('./') ? typings.slice(2) : typings\n ),\n };\n }\n }\n\n private async loadSourceFileContents(\n importResource: ImportResourcePathRelativeInPackage\n ): Promise<{ source: string; at: string } | null> {\n const progressUpdatePath = path.join(\n importResource.packageName,\n importResource.sourcePath,\n importResource.importPath\n );\n\n const failedProgressUpdate = {\n type: 'LookedUpTypeFile',\n path: progressUpdatePath,\n definitelyTyped: false,\n success: false,\n } as const;\n\n const pkgName = importResource.packageName;\n const version = this.getVersion(importResource.packageName);\n\n let appends = ['.d.ts', '/index.d.ts', '.ts', '.tsx', '/index.ts', '/index.tsx'];\n\n if (appends.map(append => importResource.importPath.endsWith(append)).reduce((a, b) => a || b, false)) {\n const source = await this.resolveSourceFile(\n pkgName,\n version,\n path.join(importResource.sourcePath, importResource.importPath)\n );\n if (source) {\n return { source, at: path.join(importResource.sourcePath, importResource.importPath) };\n }\n }\n else {\n for (const append of appends) {\n const fullPath = path.join(importResource.sourcePath, importResource.importPath) + append;\n const source = await this.resolveSourceFile(pkgName, version, fullPath);\n invokeUpdate(\n {\n type: 'AttemptedLookUpFile',\n path: path.join(pkgName, fullPath),\n success: !!source,\n },\n this.options\n );\n if (source) {\n invokeUpdate(\n {\n type: 'LookedUpTypeFile',\n path: path.join(pkgName, fullPath),\n success: true,\n },\n this.options\n );\n return { source, at: fullPath };\n }\n }\n }\n\n const pkgJson = await this.resolvePackageJson(\n pkgName,\n version,\n path.join(importResource.sourcePath, importResource.importPath)\n );\n\n if (pkgJson) {\n const { types } = JSON.parse(pkgJson);\n if (types) {\n const fullPath = path.join(importResource.sourcePath, importResource.importPath, types);\n const source = await this.resolveSourceFile(pkgName, version, fullPath);\n if (source) {\n invokeUpdate(\n {\n type: 'LookedUpTypeFile',\n path: path.join(pkgName, fullPath),\n success: true,\n },\n this.options\n );\n return { source, at: fullPath };\n }\n }\n }\n\n invokeUpdate(failedProgressUpdate, this.options);\n return null;\n }\n\n private getVersion(packageName: string) {\n return this.versions?.[packageName];\n }\n\n public setVersions(versions: { [packageName: string]: string }) {\n this.versions = versions;\n this.options.onUpdateVersions?.(versions);\n // TODO reload packages whose version has changed\n }\n\n private setVersion(packageName: string, version: string) {\n this.setVersions({\n ...this.versions,\n [packageName]: version,\n });\n }\n\n private createModel(source: string, uri: monaco.Uri) {\n uri = uri.with({ path: uri.path.replace('@types/', '') });\n if (!this.monaco.editor.getModel(uri)) {\n this.monaco.editor.createModel(source, 'typescript', uri);\n this.newImportsResolved = true;\n }\n }\n\n private hashImportResourcePath(p: ImportResourcePath) {\n return importResourcePathToString(p);\n }\n\n private async resolvePackageJson(\n packageName: string,\n version?: string,\n subPath?: string\n ): Promise<string | undefined> {\n\n const uri = path.join(packageName + (version ? `@${version}` : ''), subPath ?? '', 'package.json');\n let isAvailable = false;\n let content: string | undefined = undefined;\n\n if (this.cache.isFileAvailable) {\n isAvailable = await this.cache.isFileAvailable(uri);\n }\n else {\n content = await this.cache.getFile(uri);\n isAvailable = content !== undefined;\n }\n\n if (isAvailable) {\n return content ?? (await this.cache.getFile(uri));\n }\n else {\n console.log(\"recursing resolvePackageJson\", packageName, version, subPath)\n content = await UnpkgSourceResolver.resolvePackageJson(packageName, version, subPath);\n if (content) {\n this.cache.storeFile(uri, content);\n }\n return content;\n }\n }\n\n private async resolveSourceFile(\n packageName: string,\n version: string | undefined,\n filePath: string\n ): Promise<string | undefined> {\n\n const uri = path.join(packageName + (version ? `@${version}` : ''), filePath);\n let isAvailable = false;\n let content: string | undefined = undefined;\n\n if (this.cache.isFileAvailable) {\n isAvailable = await this.cache.isFileAvailable(uri);\n }\n else {\n content = await this.cache.getFile(uri);\n isAvailable = content !== undefined;\n }\n\n if (isAvailable) {\n invokeUpdate(\n {\n type: 'LoadedFromCache',\n importPath: uri,\n },\n this.options\n );\n return content ?? (await this.cache.getFile(uri));\n }\n else {\n content = await UnpkgSourceResolver.resolveSourceFile(packageName, version, filePath);\n if (content) {\n invokeUpdate(\n {\n type: 'StoredToCache',\n importPath: uri,\n },\n this.options\n );\n this.cache.storeFile(uri, content);\n }\n return content;\n }\n }\n}\n","import { SourceCache } from './types';\n\nexport class DummySourceCache implements SourceCache {\n public getFile(uri: string): Promise<string | undefined> {\n return undefined;\n }\n\n public async isFileAvailable(uri: string): Promise<boolean> {\n return false;\n }\n\n public storeFile(uri: string, content: string): Promise<void> {\n return undefined;\n }\n\n public clear(): Promise<void> {\n return undefined;\n }\n}\n","import { ImportResolver } from './import-resolver';\nimport * as path from 'path-browserify';\nimport type * as monaco from 'monaco-editor';\nimport { invokeUpdate } from './update-emitter';\nimport { RecursionDepth } from './recursion-depth';\nimport { Options, SourceCache } from './types';\nimport { DummySourceCache } from './dummy-source-cache';\n\ntype Editor = monaco.editor.ICodeEditor | monaco.editor.IStandaloneCodeEditor;\n\n// https://github.com/lukasbach/monaco-editor-auto-typings\nexport class MonacoAutoTypeImporter implements monaco.IDisposable {\n private static sharedCache?: SourceCache;\n private importResolver: ImportResolver;\n private debounceTimer?: number;\n private isResolving?: boolean;\n private disposables: monaco.IDisposable[] = [];\n\n public constructor(private editor: Editor, private options: Options) {\n this.importResolver = new ImportResolver(options);\n\n const changeModelDisposable = editor.onDidChangeModelContent(e => {\n this.debouncedResolveContents();\n });\n this.disposables.push(changeModelDisposable);\n this.resolveContents();\n\n if (!options.dontAdaptEditorOptions) {\n options.monaco.languages.typescript.typescriptDefaults.setCompilerOptions({\n ...options.monaco.languages.typescript.typescriptDefaults.getCompilerOptions(),\n moduleResolution: options.monaco.languages.typescript.ModuleResolutionKind.NodeJs,\n allowSyntheticDefaultImports: true,\n rootDir: options.fileRootPath,\n });\n }\n }\n\n public static async create(editor: Editor, options?: Partial<Options>): Promise<MonacoAutoTypeImporter> {\n if (options?.shareCache && options.sourceCache && !MonacoAutoTypeImporter.sharedCache) {\n MonacoAutoTypeImporter.sharedCache = options.sourceCache;\n }\n\n const monacoInstance = options?.monaco ?? window['monaco'];\n\n if (!monacoInstance) {\n throw new Error('monacoInstance not found, you can specify the monaco instance via options.monaco');\n }\n\n return new MonacoAutoTypeImporter(editor, {\n fileRootPath: 'inmemory://model/',\n onlySpecifiedPackages: false,\n preloadPackages: false,\n shareCache: false,\n dontAdaptEditorOptions: false,\n dontRefreshModelValueAfterResolvement: false,\n sourceCache: MonacoAutoTypeImporter.sharedCache ?? new DummySourceCache(),\n debounceDuration: 4000,\n fileRecursionDepth: 10,\n packageRecursionDepth: 3,\n ...options,\n monaco: monacoInstance,\n });\n }\n\n public dispose() {\n this.disposables.forEach(d => d.dispose())\n }\n\n public setVersions(versions: { [packageName: string]: string }) {\n this.importResolver.setVersions(versions);\n this.options.versions = versions;\n }\n\n public async clearCache() {\n await this.options.sourceCache.clear();\n }\n\n private debouncedResolveContents() {\n if (this.isResolving) {\n return;\n }\n\n invokeUpdate({ type: 'CodeChanged' }, this.options);\n\n if (this.options.debounceDuration <= 0) {\n this.resolveContents();\n }\n else {\n if (this.debounceTimer !== undefined) {\n clearTimeout(this.debounceTimer);\n }\n this.debounceTimer = setTimeout(async () => {\n await this.resolveContents();\n this.debounceTimer = undefined;\n }, this.options.debounceDuration) as any;\n }\n }\n\n private async resolveContents() {\n this.isResolving = true;\n invokeUpdate({ type: 'ResolveNewImports' }, this.options);\n\n const model = this.editor.getModel();\n // This can happen when the editor is disposed before all typings\n // are installed.\n if (!model) {\n throw Error('No model');\n }\n\n const content = model.getLinesContent();\n\n try {\n await this.importResolver.resolveImportsInFile(\n content.join('\\n'),\n path.dirname(model.uri.toString()),\n new RecursionDepth(this.options)\n );\n }\n catch (e) {\n if (this.options.onError) {\n this.options.onError((e as Error).message ?? e);\n }\n else {\n throw e;\n }\n }\n\n if (this.importResolver.wereNewImportsResolved()) {\n if (!this.options.dontRefreshModelValueAfterResolvement) {\n const currentPosition = this.editor.getPosition();\n model.setValue(model.getValue());\n if (currentPosition) {\n this.editor.setPosition(currentPosition);\n }\n }\n this.importResolver.resetNewImportsResolved();\n }\n\n this.isResolving = false;\n }\n}\n","import { AfterViewInit, Component, EventEmitter, HostListener, Input, OnDestroy, Output, SimpleChanges, ViewContainerRef } from '@angular/core';\r\n\r\nimport * as MonacoEditor from 'monaco-editor';\r\nimport { debounceTime } from 'rxjs';\r\nimport { MonacoAutoTypeImporter } from './ts-type-resolver/main';\r\n\r\nlet Monaco: typeof MonacoEditor;\r\n\r\n@Component({\r\n selector: 'ngx-monaco-editor',\r\n template: '',\r\n styles: [`\r\n:host {\r\n display: block;\r\n height: 100%;\r\n max-height: 100vh;\r\n max-width: 100vw;\r\n}\r\n `],\r\n standalone: true\r\n})\r\nexport class MonacoEditorComponent implements AfterViewInit, OnDestroy {\r\n isDirty = false;\r\n editor: MonacoEditor.editor.IStandaloneCodeEditor;\r\n filename: string;\r\n\r\n private _code: string;\r\n @Input() set code(value: string) {\r\n if (value == this._code)\r\n return;\r\n if (typeof value != \"string\")\r\n throw new TypeError(\"Value must be of type string\");\r\n\r\n this._code = value;\r\n this.editor?.setValue(this.code);\r\n };\r\n get code() { return this._code?.trim(); }\r\n @Output() codeChange = new EventEmitter<string>();\r\n private onCodeType = new EventEmitter<string>();\r\n private typeDebounce = this.onCodeType.pipe(debounceTime(100));\r\n\r\n @Input() customLanguage: { init: Function; };\r\n\r\n\r\n private _language: string;\r\n @Input() set language(value: string) {\r\n this._language = {\r\n 'ts': \"typescript\",\r\n 'html': 'xml',\r\n 'scss': 'css'\r\n }[value] || value || \"auto\";\r\n }\r\n get language() { return this._language; }\r\n\r\n @Input() installationLocation = \"/lib/monaco/vs\";\r\n\r\n\r\n @Input() tabSize = 2;\r\n @Input() readOnly = false;\r\n @Input() theme = \"vs-dark\";\r\n @Input() fontFamily = \"Droid Sans Mono\";\r\n @Input() fontSize = 14;\r\n\r\n @Input() automaticLayout = true;\r\n @Input() colorDecorators = true;\r\n @Input() folding = true;\r\n\r\n @Input() minimapEnabled = true;\r\n @Input() minimap: MonacoEditor.editor.IEditorMinimapOptions = {\r\n enabled: true\r\n };\r\n @Input() scrollbar: MonacoEditor.editor.IEditorScrollbarOptions = {\r\n alwaysConsumeMouseWheel: false,\r\n // scrollByPage: true\r\n };\r\n @Input() smoothScrolling = true;\r\n @Input() mouseWheelScrollSensitivity = 2;\r\n @Input() scrollBeyondLastLine = false;\r\n @Input() scrollBeyondLastColumn = 0;\r\n\r\n @Input() lineNumbers: MonacoEditor.editor.LineNumbersType = \"on\";\r\n\r\n @Input() restSettings: MonacoEditor.editor.IStandaloneEditorConstructionOptions = {};\r\n\r\n get settings() {\r\n return {\r\n ...this.restSettings,\r\n theme: this.theme,\r\n language: this.language,\r\n tabSize: this.tabSize,\r\n readOnly: this.readOnly,\r\n fontFamily: this.fontFamily,\r\n fontSize: this.fontSize,\r\n automaticLayout: this.automaticLayout,\r\n scrollBeyondLastLine: this.scrollBeyondLastLine,\r\n colorDecorators: this.colorDecorators,\r\n folding: this.folding,\r\n scrollBeyondLastColumn: this.scrollBeyondLastColumn,\r\n minimap: this.minimap,\r\n scrollbar: this.scrollbar,\r\n smoothScrolling: this.smoothScrolling,\r\n mouseWheelScrollSensitivity: this.mouseWheelScrollSensitivity,\r\n lineNumbers: this.lineNumbers\r\n } as MonacoEditor.editor.IStandaloneEditorConstructionOptions;\r\n }\r\n\r\n private _sub;\r\n constructor(private viewContainer: ViewContainerRef) {\r\n\r\n this._sub = this.typeDebounce.subscribe(t => {\r\n this.codeChange.next(this._code = this.editor.getValue());\r\n });\r\n }\r\n\r\n ngOnInit() {\r\n InstallMonacoUMD(this.installationLocation);\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n // If we changed anything OTHER than code, reload the editor\r\n if (Object.keys(changes).length > 1 || !changes['code']) {\r\n if (this.editor) {\r\n this.editor?.dispose();\r\n this.createEditor();\r\n }\r\n }\r\n if (changes['theme'])\r\n window['monaco']?.editor.setTheme(this.theme);\r\n }\r\n\r\n async ngAfterViewInit() {\r\n await InstallMonacoUMD();\r\n\r\n this.createEditor();\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.editor?.dispose();\r\n this._sub?.unsubscribe();\r\n }\r\n\r\n private createEditor() {\r\n if (this.customLanguage) {\r\n this.customLanguage.init(window['monaco']);\r\n }\r\n\r\n let editor = this.editor = window['monaco'].editor.create(\r\n this.viewContainer?.element?.nativeElement,\r\n this.settings as any\r\n );\r\n\r\n // const autoTypings = await\r\n MonacoAutoTypeImporter.create(editor, {\r\n monaco: Monaco,\r\n });\r\n\r\n this.configureLanguageSupport();\r\n\r\n if (this.code) {\r\n editor.setValue(this.code);\r\n }\r\n\r\n editor.getModel().onDidChangeContent(() => this.onCodeType.emit());\r\n }\r\n\r\n private configureLanguageSupport() {\r\n\r\n }\r\n\r\n download() {\r\n const code = this.editor.getValue();\r\n\r\n let blob = new Blob([code], { type: 'text/log' });\r\n let elm = document.createElement('a');\r\n let blobURL = URL.createObjectURL(blob);\r\n\r\n // Set the data values.\r\n elm.href = blobURL;\r\n elm.download = this.filename;\r\n\r\n document.body.appendChild(elm);\r\n elm.click();\r\n\r\n document.body.removeChild(elm);\r\n elm.remove();\r\n\r\n URL.revokeObjectURL(blobURL);\r\n }\r\n\r\n @HostListener('window:resize', ['$event'])\r\n resize = (): void => {\r\n this.editor?.layout();\r\n };\r\n}\r\n\r\nexport const InstallMonacoUMD = async (path?: string) => {\r\n if (window['monaco']) return window['monaco'];\r\n\r\n // Prevent duplicate injection\r\n const scriptEls = document.querySelectorAll('body>script[monaco][defer][src]');\r\n\r\n // Only perform installation if a path is specified.\r\n if (path && scriptEls.length == 0) {\r\n // Monaco has a UMD loader that requires this\r\n // Merge with any pre-existing global require objects.\r\n if (!window['require']) window['require'] = {} as any;\r\n if (!window['require']['paths']) window['require']['paths'] = {};\r\n\r\n if (path.endsWith('/'))\r\n path = path.slice(0, -1);\r\n\r\n window['require']['paths'].vs = path;\r\n\r\n const monacoFiles = [\r\n 'loader.js',\r\n 'editor/editor.main.nls.js',\r\n 'editor/editor.main.js',\r\n ];\r\n\r\n for (let i = 0; i < monacoFiles.length; i++) {\r\n const script = document.createElement(\"script\");\r\n script.setAttribute(\"monaco\", \"\");\r\n script.setAttribute(\"defer\", \"\");\r\n script.setAttribute(\"src\", path + '/' + monacoFiles[i]);\r\n document.body.append(script);\r\n }\r\n }\r\n\r\n // Return a promise that will resolve when monaco finishes loading\r\n return await new Promise((res, rej) => {\r\n let count = 0;\r\n let i = window.setInterval(() => {\r\n count++;\r\n\r\n if (window['monaco'] != undefined) {\r\n window.clearInterval(i);\r\n res(true);\r\n }\r\n else if (count >= 100) {\r\n window.clearInterval(i);\r\n res(false);\r\n }\r\n }, 100);\r\n });\r\n};\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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