1const jsDocPrefix = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/'; 2 3const jsDataStructuresUrl = `${jsDocPrefix}Data_structures`; 4const jsPrimitives = { 5 boolean: 'Boolean', 6 integer: 'Number', // Not a primitive, used for clarification. 7 null: 'Null', 8 number: 'Number', 9 string: 'String', 10 symbol: 'Symbol', 11 undefined: 'Undefined' 12}; 13 14const jsGlobalObjectsUrl = `${jsDocPrefix}Reference/Global_Objects/`; 15const jsGlobalTypes = [ 16 'Array', 'ArrayBuffer', 'DataView', 'Date', 'Error', 17 'EvalError', 'Function', 'Map', 'Object', 'Promise', 'RangeError', 18 'ReferenceError', 'RegExp', 'Set', 'SharedArrayBuffer', 'SyntaxError', 19 'TypeError', 'TypedArray', 'URIError', 'Uint8Array', 20]; 21 22const customTypesMap = { 23 'any': `${jsDataStructuresUrl}#Data_types`, 24 25 'this': `${jsDocPrefix}Reference/Operators/this`, 26 27 'AbortController': 'globals.html#globals_class_abortcontroller', 28 'AbortSignal': 'globals.html#globals_class_abortsignal', 29 30 'ArrayBufferView': 31 'https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView', 32 33 'AsyncIterator': 'https://tc39.github.io/ecma262/#sec-asynciterator-interface', 34 35 'AsyncIterable': 'https://tc39.github.io/ecma262/#sec-asynciterable-interface', 36 37 'bigint': `${jsDocPrefix}Reference/Global_Objects/BigInt`, 38 'WebAssembly.Instance': 39 `${jsDocPrefix}Reference/Global_Objects/WebAssembly/Instance`, 40 41 'Blob': 'buffer.html#buffer_class_blob', 42 43 'Iterable': 44 `${jsDocPrefix}Reference/Iteration_protocols#The_iterable_protocol`, 45 'Iterator': 46 `${jsDocPrefix}Reference/Iteration_protocols#The_iterator_protocol`, 47 48 'Module Namespace Object': 49 'https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects', 50 51 'AsyncHook': 'async_hooks.html#async_hooks_async_hooks_createhook_callbacks', 52 'AsyncResource': 'async_hooks.html#async_hooks_class_asyncresource', 53 54 'brotli options': 'zlib.html#zlib_class_brotlioptions', 55 56 'Buffer': 'buffer.html#buffer_class_buffer', 57 58 'ChildProcess': 'child_process.html#child_process_class_childprocess', 59 60 'cluster.Worker': 'cluster.html#cluster_class_worker', 61 62 'Cipher': 'crypto.html#crypto_class_cipher', 63 'Decipher': 'crypto.html#crypto_class_decipher', 64 'DiffieHellman': 'crypto.html#crypto_class_diffiehellman', 65 'DiffieHellmanGroup': 'crypto.html#crypto_class_diffiehellmangroup', 66 'ECDH': 'crypto.html#crypto_class_ecdh', 67 'Hash': 'crypto.html#crypto_class_hash', 68 'Hmac': 'crypto.html#crypto_class_hmac', 69 'KeyObject': 'crypto.html#crypto_class_keyobject', 70 'Sign': 'crypto.html#crypto_class_sign', 71 'Verify': 'crypto.html#crypto_class_verify', 72 'crypto.constants': 'crypto.html#crypto_crypto_constants_1', 73 74 'dgram.Socket': 'dgram.html#dgram_class_dgram_socket', 75 76 'Channel': 'diagnostics_channel.html#diagnostics_channel_class_channel', 77 78 'Domain': 'domain.html#domain_class_domain', 79 80 'errors.Error': 'errors.html#errors_class_error', 81 82 'import.meta': 'esm.html#esm_import_meta', 83 84 'EventEmitter': 'events.html#events_class_eventemitter', 85 'EventTarget': 'events.html#events_class_eventtarget', 86 'Event': 'events.html#events_class_event', 87 'EventListener': 'events.html#events_event_listener', 88 89 'FileHandle': 'fs.html#fs_class_filehandle', 90 'fs.Dir': 'fs.html#fs_class_fs_dir', 91 'fs.Dirent': 'fs.html#fs_class_fs_dirent', 92 'fs.FSWatcher': 'fs.html#fs_class_fs_fswatcher', 93 'fs.ReadStream': 'fs.html#fs_class_fs_readstream', 94 'fs.Stats': 'fs.html#fs_class_fs_stats', 95 'fs.StatWatcher': 'fs.html#fs_class_fs_statwatcher', 96 'fs.WriteStream': 'fs.html#fs_class_fs_writestream', 97 98 'http.Agent': 'http.html#http_class_http_agent', 99 'http.ClientRequest': 'http.html#http_class_http_clientrequest', 100 'http.IncomingMessage': 'http.html#http_class_http_incomingmessage', 101 'http.Server': 'http.html#http_class_http_server', 102 'http.ServerResponse': 'http.html#http_class_http_serverresponse', 103 104 'ClientHttp2Session': 'http2.html#http2_class_clienthttp2session', 105 'ClientHttp2Stream': 'http2.html#http2_class_clienthttp2stream', 106 'HTTP/2 Headers Object': 'http2.html#http2_headers_object', 107 'HTTP/2 Settings Object': 'http2.html#http2_settings_object', 108 'http2.Http2ServerRequest': 'http2.html#http2_class_http2_http2serverrequest', 109 'http2.Http2ServerResponse': 110 'http2.html#http2_class_http2_http2serverresponse', 111 'Http2SecureServer': 'http2.html#http2_class_http2secureserver', 112 'Http2Server': 'http2.html#http2_class_http2server', 113 'Http2Session': 'http2.html#http2_class_http2session', 114 'Http2Stream': 'http2.html#http2_class_http2stream', 115 'ServerHttp2Stream': 'http2.html#http2_class_serverhttp2stream', 116 117 'https.Server': 'https.html#https_class_https_server', 118 119 'module': 'modules.html#modules_the_module_object', 120 121 'module.SourceMap': 122 'module.html#module_class_module_sourcemap', 123 124 'require': 'modules.html#modules_require_id', 125 126 'Handle': 'net.html#net_server_listen_handle_backlog_callback', 127 'net.BlockList': 'net.html#net_class_net_blocklist', 128 'net.Server': 'net.html#net_class_net_server', 129 'net.Socket': 'net.html#net_class_net_socket', 130 'net.SocketAddress': 'net.html#net_class_net_socketaddress', 131 132 'NodeEventTarget': 133 'events.html#events_class_nodeeventtarget', 134 135 'os.constants.dlopen': 'os.html#os_dlopen_constants', 136 137 'Histogram': 'perf_hooks.html#perf_hooks_class_histogram', 138 'IntervalHistogram': 139 'perf_hooks.html#perf_hooks_class_intervalhistogram_extends_histogram', 140 'RecordableHistogram': 141 'perf_hooks.html#perf_hooks_class_recordablehistogram_extends_histogram', 142 'PerformanceEntry': 'perf_hooks.html#perf_hooks_class_performanceentry', 143 'PerformanceNodeTiming': 144 'perf_hooks.html#perf_hooks_class_performancenodetiming', 145 'PerformanceObserver': 146 'perf_hooks.html#perf_hooks_class_perf_hooks_performanceobserver', 147 'PerformanceObserverEntryList': 148 'perf_hooks.html#perf_hooks_class_performanceobserverentrylist', 149 150 'readline.Interface': 'readline.html#readline_class_interface', 151 152 'repl.REPLServer': 'repl.html#repl_class_replserver', 153 154 'Stream': 'stream.html#stream_stream', 155 'stream.Duplex': 'stream.html#stream_class_stream_duplex', 156 'stream.Readable': 'stream.html#stream_class_stream_readable', 157 'stream.Transform': 'stream.html#stream_class_stream_transform', 158 'stream.Writable': 'stream.html#stream_class_stream_writable', 159 160 'Immediate': 'timers.html#timers_class_immediate', 161 'Timeout': 'timers.html#timers_class_timeout', 162 'Timer': 'timers.html#timers_timers', 163 164 'tls.SecureContext': 'tls.html#tls_tls_createsecurecontext_options', 165 'tls.Server': 'tls.html#tls_class_tls_server', 166 'tls.TLSSocket': 'tls.html#tls_class_tls_tlssocket', 167 168 'Tracing': 'tracing.html#tracing_tracing_object', 169 170 'URL': 'url.html#url_the_whatwg_url_api', 171 'URLSearchParams': 'url.html#url_class_urlsearchparams', 172 173 'vm.Module': 'vm.html#vm_class_vm_module', 174 'vm.Script': 'vm.html#vm_class_vm_script', 175 'vm.SourceTextModule': 'vm.html#vm_class_vm_sourcetextmodule', 176 177 'MessagePort': 'worker_threads.html#worker_threads_class_messageport', 178 'Worker': 'worker_threads.html#worker_threads_class_worker', 179 180 'zlib options': 'zlib.html#zlib_class_options', 181}; 182 183const arrayPart = /(?:\[])+$/; 184 185export function toLink(typeInput) { 186 const typeLinks = []; 187 typeInput = typeInput.replace('{', '').replace('}', ''); 188 const typeTexts = typeInput.split('|'); 189 190 typeTexts.forEach((typeText) => { 191 typeText = typeText.trim(); 192 if (typeText) { 193 let typeUrl; 194 195 // To support type[], type[][] etc., we store the full string 196 // and use the bracket-less version to lookup the type URL. 197 const typeTextFull = typeText; 198 typeText = typeText.replace(arrayPart, ''); 199 200 const primitive = jsPrimitives[typeText]; 201 202 if (primitive !== undefined) { 203 typeUrl = `${jsDataStructuresUrl}#${primitive}_type`; 204 } else if (jsGlobalTypes.includes(typeText)) { 205 typeUrl = `${jsGlobalObjectsUrl}${typeText}`; 206 } else { 207 typeUrl = customTypesMap[typeText]; 208 } 209 210 if (typeUrl) { 211 typeLinks.push( 212 `<a href="${typeUrl}" class="type"><${typeTextFull}></a>`); 213 } else { 214 throw new Error( 215 `Unrecognized type: '${typeTextFull}'.\n` + 216 `Please, edit the type or update '${import.meta.url}'.` 217 ); 218 } 219 } else { 220 throw new Error(`Empty type slot: ${typeInput}`); 221 } 222 }); 223 224 return typeLinks.length ? typeLinks.join(' | ') : typeInput; 225} 226