Skip to content

Commit 7a659ff

Browse files
ci-bothsy822
authored andcommitted
update explaination
1 parent 51b6306 commit 7a659ff

File tree

4 files changed

+29
-5
lines changed

4 files changed

+29
-5
lines changed

apps/remix-ide/src/app/editor/editor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ export default class Editor extends Plugin {
283283
console.log(`[DIAGNOSE-LIBS] Files added. Total extra libs now: ${Object.keys(tsDefaults.getExtraLibs()).length}.`)
284284
}
285285

286-
// Called on every editor content change to parse import statements and trigger type loading.
286+
// [2/4] The conductor, called on every editor content change to parse 'import' statements and trigger the type loading process.
287287
async _onChange (file) {
288288
this.triggerEvent('didChangeFile', [file])
289289

apps/remix-ide/src/app/editor/type-fetcher.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { Monaco } from '@monaco-editor/react'
22

3+
// A type representing a single type file (.d.ts) to be added to the Monaco editor, containing its virtual path and content.
34
type Library = { filePath: string; content: string }
5+
6+
// A type defining the minimum required fields from a package.json for type loading.
47
type PackageJson = {
58
name?: string
69
version?: string
@@ -19,6 +22,7 @@ function isRelative(p: string): boolean {
1922
return p.startsWith('./') || p.startsWith('../') || p.startsWith('/')
2023
}
2124

25+
// Extracts the base package name from an import path (e.g., 'viem/chains' -> 'viem').
2226
function normalizeBareSpecifier(p: string): string {
2327
if (!p) return p
2428
if (p.startsWith('@')) return p.split('/').slice(0, 2).join('/')
@@ -32,6 +36,7 @@ function toTypesScopedName(pkg: string): string {
3236
return '@types/' + pkg
3337
}
3438

39+
// Converts a CDN URL to a virtual file system path used by the Monaco editor.
3540
function toVirtual(url: string): string {
3641
return url.replace(CDN_BASE, VIRTUAL_BASE)
3742
}
@@ -46,13 +51,15 @@ async function fetchJson<T = any>(url: string): Promise<T> {
4651
return res.json()
4752
}
4853

49-
// Guesses potential type definition file (.d.ts) paths from a JS file path.
54+
// Guesses a list of potential TypeScript Definition file (.d.ts) paths from a given JS-like file path.
55+
// For example, 'index.js' is converted to 'index.d.ts', 'index.ts', 'index/index.d.ts', etc.
5056
function guessDtsFromJs(jsPath: string): string[] {
5157
const base = stripJsLike(jsPath)
5258
return [`${base}.d.ts`, `${base}.ts`, `${base}/index.d.ts`, `${base}/index.ts`]
5359
}
5460

55-
// Analyzes the 'exports' field of package.json to create a map of subpaths to their type file URLs.
61+
// Analyzes the 'exports' field of a package.json to create a map of subpath entry points to their corresponding type definition file URLs.
62+
// This map is crucial for correctly resolving subpath imports like 'viem' vs. 'viem/chains'.
5663
function buildExportTypeMap(pkgName: string, pkgJson: PackageJson): Record<string, string[]> {
5764
const map: Record<string, string[]> = {}
5865
const base = `${CDN_BASE}${pkgName}/`
@@ -78,6 +85,8 @@ function buildExportTypeMap(pkgName: string, pkgJson: PackageJson): Record<strin
7885
return map
7986
}
8087

88+
// Given an array of candidate URLs, this function tries to fetch each one sequentially and returns the content of the first successful request.
89+
// This is used to find the correct file from the list of possibilities generated by 'guessDtsFromJs'.
8190
async function tryFetchOne(urls: string[]): Promise<ResolveResult | null> {
8291
for (const u of [...new Set(urls)]) {
8392
try {
@@ -121,13 +130,13 @@ async function crawl(entryUrl: string, pkgName: string, visited: Set<string>, en
121130
return out
122131
}
123132

124-
// Main function for the type loading process. Fetches type files for a package and all its dependencies.
133+
// [3/4] The core service that, upon request from 'editor.ts', fetches type definitions (.d.ts) for NPM packages from a CDN.
125134
export async function startTypeLoadingProcess(packageName: string): Promise<{ mainVirtualPath: string; libs: Library[]; subpathMap: Record<string, string> } | void> {
126135
const visitedPackages = new Set<string>()
127136
const collected: Library[] = []
128137
const subpathMap: Record<string, string> = {}
129138

130-
// An inner function that recursively loads packages.
139+
// The core inner function that recursively loads a package and its dependencies.
131140
async function loadPackage(pkgNameToLoad: string) {
132141
if (visitedPackages.has(pkgNameToLoad)) return
133142
visitedPackages.add(pkgNameToLoad)

apps/remix-ide/src/app/plugins/script-runner-bridge.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,28 @@ const configFileName = 'remix.config.json'
2828
let baseUrl = 'https://remix-project-org.github.io/script-runner-generator'
2929
const customBuildUrl = 'http://localhost:4000/build' // this will be used when the server is ready
3030

31+
// A helper function that transforms ESM 'import' syntax into a format executable in the browser when 'Run Script' is triggered.
3132
function transformScriptForRuntime(scriptContent: string): string {
33+
// Injects a helper function for dynamic imports at the top of the script.
3234
const dynamicImportHelper = `const dynamicImport = (p) => new Function(\`return import('https://cdn.jsdelivr.net/npm/\${p}/+esm')\`)();\n`
3335

36+
// Transforms 'import { member } from "pkg"' into 'const { member } = await dynamicImport("pkg")'.
3437
let transformed = scriptContent.replace(
3538
/import\s+({[\s\S]*?})\s+from\s+['"]([^'"]+)['"]/g,
3639
'const $1 = await dynamicImport("$2");'
3740
)
41+
// Transforms 'import Default from "pkg"'.
3842
transformed = transformed.replace(
3943
/import\s+([\w\d_$]+)\s+from\s+['"]([^'"]+)['"]/g,
4044
'const $1 = (await dynamicImport("$2")).default;'
4145
)
46+
// Transforms 'import * as name from "pkg"'.
4247
transformed = transformed.replace(
4348
/import\s+\*\s+as\s+([\w\d_$]+)\s+from\s+['"]([^'"]+)['"]/g,
4449
'const $1 = await dynamicImport("$2");'
4550
)
4651

52+
// Wraps the entire script in an async IIFE (Immediately Invoked Function Expression) to support top-level await.
4753
return `${dynamicImportHelper}\n(async () => {\n try {\n${transformed}\n } catch (e) { console.error('Error executing script:', e); }\n})();`
4854
}
4955

@@ -216,6 +222,8 @@ export class ScriptRunnerBridgePlugin extends Plugin {
216222
}
217223
try {
218224
this.setIsLoading(this.activeConfig.name, true)
225+
226+
// Transforms the script into an executable format using the function defined above.
219227
const transformedScript = transformScriptForRuntime(script)
220228

221229
console.log('--- [ScriptRunner] Original Script ---')

libs/remix-ui/editor/src/lib/providers/tsCompletionProvider.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@ interface TsCompletionInfo {
77
}[]
88
}
99

10+
// [1/4] This class provides TypeScript/JavaScript autocompletion features to the Monaco editor.
1011
export class RemixTSCompletionProvider implements monacoTypes.languages.CompletionItemProvider {
1112
monaco: any
1213

1314
constructor(monaco: any) {
1415
this.monaco = monaco
1516
}
1617

18+
// Defines trigger characters for autocompletion (e.g., suggesting object members after typing '.').
1719
triggerCharacters = ['.', '"', "'", '/', '@']
1820

21+
// The main function called by the Monaco editor as the user types.
1922
async provideCompletionItems(model: monacoTypes.editor.ITextModel, position: monacoTypes.Position, context: monacoTypes.languages.CompletionContext): Promise<monacoTypes.languages.CompletionList | undefined> {
2023
const word = model.getWordUntilPosition(position)
2124
const range = {
@@ -26,6 +29,8 @@ export class RemixTSCompletionProvider implements monacoTypes.languages.Completi
2629
}
2730

2831
try {
32+
// [4/4] It fetches type information loaded by the editor plugin ('editor.ts') via 'type-fetcher.ts',
33+
// using Monaco's built-in TypeScript Worker to generate an autocompletion list.
2934
const worker = await this.monaco.languages.typescript.getTypeScriptWorker()
3035
const client = await worker(model.uri)
3136
const completions: TsCompletionInfo = await client.getCompletionsAtPosition(
@@ -37,6 +42,7 @@ export class RemixTSCompletionProvider implements monacoTypes.languages.Completi
3742
return { suggestions: []}
3843
}
3944

45+
// Converts the suggestion list from the TypeScript Worker into a format that the Monaco editor can understand.
4046
const suggestions = completions.entries.map(entry => {
4147
return {
4248
label: entry.name,
@@ -53,6 +59,7 @@ export class RemixTSCompletionProvider implements monacoTypes.languages.Completi
5359
}
5460
}
5561

62+
// Maps TypeScript's 'CompletionItemKind' string to Monaco's numeric Enum value.
5663
private mapTsCompletionKindToMonaco(kind: string): monacoTypes.languages.CompletionItemKind {
5764
const { CompletionItemKind } = this.monaco.languages
5865
switch (kind) {

0 commit comments

Comments
 (0)