proscenium 0.6.0-x86_64-darwin → 0.7.0-x86_64-darwin

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +128 -107
  3. data/bin/proscenium +0 -0
  4. data/bin/proscenium.h +109 -0
  5. data/config/routes.rb +0 -3
  6. data/lib/proscenium/css_module/class_names_resolver.rb +66 -0
  7. data/lib/proscenium/css_module/resolver.rb +76 -0
  8. data/lib/proscenium/css_module.rb +18 -39
  9. data/lib/proscenium/esbuild/golib.rb +97 -0
  10. data/lib/proscenium/esbuild.rb +32 -0
  11. data/lib/proscenium/helper.rb +0 -23
  12. data/lib/proscenium/log_subscriber.rb +26 -0
  13. data/lib/proscenium/middleware/base.rb +28 -36
  14. data/lib/proscenium/middleware/esbuild.rb +18 -44
  15. data/lib/proscenium/middleware/url.rb +1 -6
  16. data/lib/proscenium/middleware.rb +12 -16
  17. data/lib/proscenium/phlex/component_concerns.rb +27 -0
  18. data/lib/proscenium/phlex/page.rb +62 -0
  19. data/lib/proscenium/phlex/react_component.rb +52 -8
  20. data/lib/proscenium/phlex/resolve_css_modules.rb +67 -0
  21. data/lib/proscenium/phlex.rb +34 -33
  22. data/lib/proscenium/railtie.rb +41 -67
  23. data/lib/proscenium/side_load/ensure_loaded.rb +25 -0
  24. data/lib/proscenium/side_load/helper.rb +25 -0
  25. data/lib/proscenium/side_load/monkey.rb +48 -0
  26. data/lib/proscenium/side_load.rb +58 -52
  27. data/lib/proscenium/version.rb +1 -1
  28. data/lib/proscenium/view_component/react_component.rb +14 -0
  29. data/lib/proscenium/view_component.rb +28 -18
  30. data/lib/proscenium.rb +79 -2
  31. metadata +35 -75
  32. data/app/channels/proscenium/connection.rb +0 -13
  33. data/app/channels/proscenium/reload_channel.rb +0 -9
  34. data/bin/esbuild +0 -0
  35. data/bin/lightningcss +0 -0
  36. data/lib/proscenium/compiler.js +0 -84
  37. data/lib/proscenium/compilers/esbuild/argument_error.js +0 -24
  38. data/lib/proscenium/compilers/esbuild/compile_error.js +0 -148
  39. data/lib/proscenium/compilers/esbuild/css/postcss.js +0 -67
  40. data/lib/proscenium/compilers/esbuild/css_plugin.js +0 -172
  41. data/lib/proscenium/compilers/esbuild/env_plugin.js +0 -46
  42. data/lib/proscenium/compilers/esbuild/http_bundle_plugin.js +0 -53
  43. data/lib/proscenium/compilers/esbuild/import_map/parser.js +0 -178
  44. data/lib/proscenium/compilers/esbuild/import_map/read.js +0 -64
  45. data/lib/proscenium/compilers/esbuild/import_map/resolver.js +0 -95
  46. data/lib/proscenium/compilers/esbuild/import_map/utils.js +0 -25
  47. data/lib/proscenium/compilers/esbuild/resolve_plugin.js +0 -207
  48. data/lib/proscenium/compilers/esbuild/setup_plugin.js +0 -45
  49. data/lib/proscenium/compilers/esbuild/solidjs_plugin.js +0 -24
  50. data/lib/proscenium/compilers/esbuild.bench.js +0 -14
  51. data/lib/proscenium/compilers/esbuild.js +0 -179
  52. data/lib/proscenium/link_to_helper.rb +0 -40
  53. data/lib/proscenium/middleware/lightningcss.rb +0 -64
  54. data/lib/proscenium/middleware/outside_root.rb +0 -26
  55. data/lib/proscenium/middleware/runtime.rb +0 -22
  56. data/lib/proscenium/middleware/static.rb +0 -14
  57. data/lib/proscenium/phlex/component.rb +0 -9
  58. data/lib/proscenium/precompile.rb +0 -31
  59. data/lib/proscenium/runtime/auto_reload.js +0 -40
  60. data/lib/proscenium/runtime/react_shim/index.js +0 -1
  61. data/lib/proscenium/runtime/react_shim/package.json +0 -5
  62. data/lib/proscenium/utils.js +0 -12
  63. data/lib/tasks/assets.rake +0 -19
@@ -1,172 +0,0 @@
1
- import { crypto } from 'std/crypto/mod.ts'
2
- import { join, dirname, basename } from 'std/path/mod.ts'
3
-
4
- import { fileExists } from '../../utils.js'
5
- import postcss from './css/postcss.js'
6
- import setup from './setup_plugin.js'
7
-
8
- export default setup('css', async (build, options) => {
9
- const cwd = build.initialOptions.absWorkingDir
10
-
11
- let customMedia
12
- try {
13
- customMedia = await Deno.readTextFile(join(cwd, 'config', 'custom_media_queries.css'))
14
- } catch {
15
- // do nothing, as we don't require custom media.
16
- }
17
-
18
- return [
19
- {
20
- type: 'onLoad',
21
- filter: /\.css$/,
22
- namespace: 'file',
23
- async callback(args) {
24
- const hash = await digest(args.path.slice(cwd.length))
25
- const isCssModule = args.path.endsWith('.module.css')
26
-
27
- // If path is a CSS module, imported from JS, and a side-loaded ViewComponent stylesheet,
28
- // simply return a JS proxy of the class names. The stylesheet itself will have already been
29
- // side loaded. This avoids compiling the CSS all over again.
30
- if (isCssModule && args.pluginData?.importedFromJs && (await isViewComponent(args.path))) {
31
- return {
32
- resolveDir: cwd,
33
- loader: 'js',
34
- contents: cssModulesProxyTemplate(hash)
35
- }
36
- }
37
-
38
- let cmd = [
39
- options.lightningcssBin,
40
- '--nesting',
41
- '--error-recovery',
42
- args.pluginData?.importedFromJs && '--minify',
43
- '--targets',
44
- '>= 0.25%'
45
- ].filter(Boolean)
46
-
47
- // This will process the CSS with Postcss only if it needs to.
48
- let [tmpFile, contents] = await postcss(cwd, args.path)
49
-
50
- // As custom media are defined in their own file, we have to append the file contents to our
51
- // stylesheet, so that the custom media can be used.
52
- if (customMedia) {
53
- cmd.push('--custom-media')
54
-
55
- if (!tmpFile && !contents) {
56
- tmpFile = await Deno.makeTempFile()
57
- contents = await Deno.readTextFile(args.path)
58
- }
59
-
60
- contents += customMedia
61
- }
62
-
63
- if (tmpFile && contents) {
64
- await Deno.writeTextFile(tmpFile, contents)
65
- }
66
-
67
- if (isCssModule) {
68
- cmd = cmd.concat(['--css-modules', '--css-modules-pattern', `[local]${hash}`])
69
- }
70
-
71
- const p = Deno.run({
72
- cmd: [...cmd, tmpFile || args.path],
73
- stdout: 'piped',
74
- stderr: 'piped'
75
- })
76
-
77
- const { code } = await p.status()
78
- const rawOutput = await p.output()
79
- const rawError = await p.stderrOutput()
80
-
81
- // Even though Deno docs say that reading the outputs (above) closes their pipes, warnings
82
- // are raised during tests that the child process have not been closed. So we manually close
83
- // here.
84
- p.close()
85
-
86
- // Success!
87
- if (code === 0) {
88
- let contents = new TextDecoder().decode(rawOutput)
89
- if (isCssModule) {
90
- contents = JSON.parse(contents)
91
- }
92
-
93
- // If stylesheet is imported from JS, then we return JS code that appends the stylesheet
94
- // in a <style> in the <head> of the page, and if the stylesheet is a CSS module, it
95
- // exports a plain object of class names.
96
- if (args.pluginData?.importedFromJs) {
97
- const code = isCssModule ? contents.code : contents
98
- const mod = [
99
- `let e = document.querySelector('#_${hash}');`,
100
- 'if (!e) {',
101
- "e = document.createElement('style');",
102
- `e.id = '_${hash}';`,
103
- 'document.head.appendChild(e);',
104
- `e.appendChild(document.createTextNode(\`${code}\`));`,
105
- '}'
106
- ]
107
-
108
- if (isCssModule) {
109
- const classes = {}
110
- for (const key in contents.exports) {
111
- if (Object.hasOwnProperty.call(contents.exports, key)) {
112
- classes[key] = contents.exports[key].name
113
- }
114
- }
115
- mod.push(`export default ${JSON.stringify(classes)};`)
116
- }
117
-
118
- // We are importing from JS, so return the entire result from LightningCSS via the js
119
- // loader.
120
- return {
121
- resolveDir: cwd,
122
- loader: 'js',
123
- contents: mod.join('')
124
- }
125
- }
126
-
127
- return { loader: 'css', contents: isCssModule ? contents.code : contents }
128
- } else {
129
- const errorString = new TextDecoder().decode(rawError)
130
- throw errorString
131
- }
132
- }
133
- }
134
- ]
135
- })
136
-
137
- async function digest(value) {
138
- value = new TextEncoder().encode(value)
139
- const view = new DataView(await crypto.subtle.digest('SHA-1', value))
140
-
141
- let hexCodes = ''
142
- for (let index = 0; index < view.byteLength; index += 4) {
143
- hexCodes += view.getUint32(index).toString(16).padStart(8, '0')
144
- }
145
-
146
- return hexCodes.slice(0, 8)
147
- }
148
-
149
- async function isViewComponent(path) {
150
- const fileName = basename(path)
151
- const dirName = dirname(path)
152
-
153
- return (
154
- (fileName === 'component.module.css' && (await fileExists(join(dirName, 'component.rb')))) ||
155
- (fileName.endsWith('_component.module.css') &&
156
- (await fileExists(join(dirName, fileName.replace(/\.module\.css$/, '.rb')))))
157
- )
158
- }
159
-
160
- function cssModulesProxyTemplate(hash) {
161
- return [
162
- `export default new Proxy( {}, {`,
163
- ` get(target, prop, receiver) {`,
164
- ` if (prop in target || typeof prop === 'symbol') {`,
165
- ` return Reflect.get(target, prop, receiver)`,
166
- ` } else {`,
167
- ` return prop + '${hash}'`,
168
- ` }`,
169
- ` }`,
170
- `})`
171
- ].join('')
172
- }
@@ -1,46 +0,0 @@
1
- import setup from './setup_plugin.js'
2
-
3
- // Export environment variables as named exports only. You can also import from `env:ENV_VAR_NAME`,
4
- // which will return the value of the environment variable as the default export. This allows you to
5
- // safely import a variable regardless of its existence.
6
- export default setup('env', () => {
7
- return [
8
- {
9
- type: 'onResolve',
10
- filter: /^env(:.+)?$/,
11
- callback({ path }) {
12
- return { path, namespace: 'env' }
13
- }
14
- },
15
-
16
- {
17
- type: 'onLoad',
18
- filter: /.*/,
19
- namespace: 'env',
20
- callback({ path }) {
21
- if (path.includes(':')) {
22
- const name = Deno.env.get(path.split(':')[1])
23
-
24
- return {
25
- loader: 'js',
26
- contents: name ? `export default '${name}'` : `export default ${name}`
27
- }
28
- }
29
-
30
- const env = Deno.env.toObject()
31
- const contents = []
32
-
33
- for (const key in env) {
34
- if (Object.hasOwnProperty.call(env, key)) {
35
- contents.push(`export const ${key} = '${env[key]}'`)
36
- }
37
- }
38
-
39
- return {
40
- loader: 'js',
41
- contents: contents.join(';')
42
- }
43
- }
44
- }
45
- ]
46
- })
@@ -1,53 +0,0 @@
1
- import setup from './setup_plugin.js'
2
-
3
- export default setup('httpBundle', () => {
4
- return [
5
- {
6
- type: 'onResolve',
7
- filter: /^https?:\/\//,
8
- callback(args) {
9
- let queryParams, suffix
10
- if (args.path.includes('?')) {
11
- const [path, query] = args.path.split('?')
12
- queryParams = new URLSearchParams(query)
13
- suffix = `?${query}`
14
- args.path = path
15
- }
16
-
17
- if (queryParams?.has('bundle')) {
18
- return { path: args.path, namespace: 'httpBundle', suffix }
19
- } else {
20
- return { external: true }
21
- }
22
- }
23
- },
24
-
25
- // Intercept all import paths inside downloaded files and resolve them against the original URL.
26
- {
27
- type: 'onResolve',
28
- filter: /.*/,
29
- namespace: 'httpBundle',
30
- callback(args) {
31
- return {
32
- path: new URL(args.path, args.importer).toString(),
33
- namespace: 'httpBundle'
34
- }
35
- }
36
- },
37
-
38
- // Download and return the content.
39
- //
40
- // TODO: cache this!
41
- {
42
- type: 'onLoad',
43
- filter: /.*/,
44
- namespace: 'httpBundle',
45
- async callback(args) {
46
- const textResponse = await fetch(args.path)
47
- const contents = await textResponse.text()
48
-
49
- return { contents }
50
- }
51
- }
52
- ]
53
- })
@@ -1,178 +0,0 @@
1
- import { tryURLParse, tryURLLikeSpecifierParse } from './utils.js'
2
-
3
- /**
4
- * @param {ImportMap} input
5
- * @param {URL} baseURL
6
- * @returns {ParsedImportMap}
7
- */
8
- export function parse(input, baseURL) {
9
- if (!isJSONObject(input)) {
10
- throw new TypeError('Import map JSON must be an object.')
11
- }
12
-
13
- if (!(baseURL instanceof URL)) {
14
- throw new TypeError('Missing base URL or base URL is not a URL')
15
- }
16
-
17
- let sortedAndNormalizedImports = {}
18
- if ('imports' in input) {
19
- if (!input.imports || !isJSONObject(input.imports)) {
20
- throw new TypeError("Import map's imports value must be an object.")
21
- }
22
- sortedAndNormalizedImports = sortAndNormalizeSpecifierMap(input.imports, baseURL)
23
- }
24
-
25
- let sortedAndNormalizedScopes = {}
26
- if ('scopes' in input) {
27
- if (!input.scopes || !isJSONObject(input.scopes)) {
28
- throw new TypeError("Import map's scopes value must be an object.")
29
- }
30
- sortedAndNormalizedScopes = sortAndNormalizeScopes(input.scopes, baseURL)
31
- }
32
-
33
- const badTopLevelKeys = new Set(Object.keys(input))
34
- badTopLevelKeys.delete('imports')
35
- badTopLevelKeys.delete('scopes')
36
-
37
- for (const badKey of badTopLevelKeys) {
38
- throw new TypeError(
39
- `Invalid top-level key "${badKey}". Only "imports" and "scopes" can be present.`
40
- )
41
- }
42
-
43
- // Always have these two keys, and exactly these two keys, in the result.
44
- return {
45
- imports: sortedAndNormalizedImports,
46
- scopes: sortedAndNormalizedScopes
47
- }
48
- }
49
-
50
- /**
51
- * @param {string} input
52
- * @param {URL} baseURL
53
- * @returns {ParsedImportMap}
54
- */
55
- export function parseFromString(input, baseURL) {
56
- const importMap = JSON.parse(input)
57
- return parse(importMap, baseURL)
58
- }
59
-
60
- /**
61
- * @param {string} a
62
- * @param {string} b
63
- */
64
- function codeUnitCompare(a, b) {
65
- if (a > b) {
66
- return 1
67
- }
68
-
69
- if (b > a) {
70
- return -1
71
- }
72
-
73
- throw new Error('This should never be reached because this is only used on JSON object keys')
74
- }
75
-
76
- /**
77
- * @param {string} specifierKey
78
- * @param {URL} baseURL
79
- * @returns {string | undefined}
80
- */
81
- function normalizeSpecifierKey(specifierKey, baseURL) {
82
- // Ignore attempts to use the empty string as a specifier key
83
- if (specifierKey === '') {
84
- throw new TypeError(`Invalid empty string specifier key.`)
85
- }
86
-
87
- const url = tryURLLikeSpecifierParse(specifierKey, baseURL)
88
- if (url) return url.href
89
-
90
- return specifierKey
91
- }
92
-
93
- /**
94
- * @param {SpecifierMap} obj
95
- * @param {URL} baseURL
96
- * @returns {ParsedSpecifierMap}
97
- */
98
- function sortAndNormalizeSpecifierMap(obj, baseURL) {
99
- if (!isJSONObject(obj)) {
100
- throw new TypeError('Expect map to be a JSON object.')
101
- }
102
-
103
- const normalized = {}
104
-
105
- for (const [specifierKey, value] of Object.entries(obj)) {
106
- const normalizedSpecifierKey = normalizeSpecifierKey(specifierKey, baseURL)
107
- if (!normalizedSpecifierKey) continue
108
-
109
- if (typeof value !== 'string') {
110
- throw new TypeError(
111
- `Invalid address ${JSON.stringify(value)} for the specifier key "${specifierKey}". ` +
112
- `Addresses must be strings.`
113
- )
114
- }
115
-
116
- const addressURL = tryURLLikeSpecifierParse(value, baseURL)
117
- if (!addressURL) {
118
- // Support aliases.
119
- // console.warn(`Invalid address "${value}" for the specifier key "${specifierKey}".`)
120
- normalized[normalizedSpecifierKey] = value
121
- continue
122
- }
123
-
124
- if (specifierKey.endsWith('/') && !addressURL.href.endsWith('/')) {
125
- throw new TypeError(
126
- `Invalid address "${addressURL.href}" for package specifier key "${specifierKey}". ` +
127
- `Package addresses must end with "/".`
128
- )
129
- }
130
-
131
- normalized[normalizedSpecifierKey] = addressURL
132
- }
133
-
134
- const sortedAndNormalized = {}
135
- const sortedKeys = Object.keys(normalized).sort((a, b) => codeUnitCompare(b, a))
136
- for (const key of sortedKeys) {
137
- sortedAndNormalized[key] = normalized[key]
138
- }
139
-
140
- return sortedAndNormalized
141
- }
142
-
143
- /**
144
- * @param {ScopesMap} obj
145
- * @param {URL} baseURL
146
- */
147
- function sortAndNormalizeScopes(obj, baseURL) {
148
- const normalized = {}
149
- for (const [scopePrefix, potentialSpecifierMap] of Object.entries(obj)) {
150
- if (!isJSONObject(potentialSpecifierMap)) {
151
- throw new TypeError(`The value for the "${scopePrefix}" scope prefix must be an object.`)
152
- }
153
-
154
- const scopePrefixURL = tryURLParse(scopePrefix, baseURL)
155
- if (!scopePrefixURL) {
156
- throw new TypeError(`Invalid scope "${scopePrefix}" (parsed against base URL "${baseURL}").`)
157
- }
158
-
159
- const normalizedScopePrefix = scopePrefixURL.href
160
- normalized[normalizedScopePrefix] = sortAndNormalizeSpecifierMap(potentialSpecifierMap, baseURL)
161
- }
162
-
163
- const sortedAndNormalized = {}
164
- const sortedKeys = Object.keys(normalized).sort((a, b) => codeUnitCompare(b, a))
165
- for (const key of sortedKeys) {
166
- sortedAndNormalized[key] = normalized[key]
167
- }
168
-
169
- return sortedAndNormalized
170
- }
171
-
172
- /**
173
- * @param {*} value
174
- * @returns {value is object}
175
- */
176
- function isJSONObject(value) {
177
- return typeof value === 'object' && value != null && !Array.isArray(value)
178
- }
@@ -1,64 +0,0 @@
1
- //
2
- // Taken almost verbatim from https://github.com/open-wc/open-wc/tree/master/packages/import-maps-resolve
3
- // Slightly modified to support aliases.
4
- //
5
-
6
- import { join } from 'std/path/mod.ts'
7
- import { parseFromString } from './parser.js'
8
-
9
- const baseURL = new URL('file://')
10
-
11
- class ImportMapError extends Error {
12
- constructor(fileName, ...params) {
13
- super(...params)
14
-
15
- if (Error.captureStackTrace) {
16
- Error.captureStackTrace(this, ImportMapError)
17
- }
18
-
19
- this.name = 'ImportMapError'
20
- this.file = fileName
21
- }
22
- }
23
-
24
- export default function (fileName, rootDir) {
25
- let importMap
26
-
27
- if (fileName) {
28
- importMap = readFile(fileName, rootDir, true)
29
- } else {
30
- fileName = ['config/import_map.json', 'config/import_map.js'].find(f => {
31
- const result = readFile(f, rootDir)
32
- if (result) {
33
- importMap = result
34
- return true
35
- }
36
- })
37
- }
38
-
39
- return importMap
40
- }
41
-
42
- function readFile(file, rootDir, required = false) {
43
- let contents = null
44
-
45
- try {
46
- contents = Deno.readTextFileSync(join(rootDir, file))
47
- } catch (error) {
48
- if (required) {
49
- throw new ImportMapError(file, error.message, { cause: error })
50
- }
51
- }
52
-
53
- if (contents === null) return null
54
-
55
- try {
56
- if (file.endsWith('.js')) {
57
- contents = JSON.stringify(eval(contents)(Deno.env.get('RAILS_ENV')))
58
- }
59
-
60
- return parseFromString(contents, baseURL)
61
- } catch (error) {
62
- throw new ImportMapError(file, error.message, { cause: error })
63
- }
64
- }
@@ -1,95 +0,0 @@
1
- import { tryURLLikeSpecifierParse, tryURLParse } from './utils.js'
2
-
3
- /**
4
- * @param {string} specifier
5
- * @param {ParsedImportMap} parsedImportMap
6
- * @param {URL} scriptURL
7
- * @returns {{ resolvedImport: URL | null, matched: boolean }}
8
- */
9
- export default function (specifier, parsedImportMap, scriptURL) {
10
- const asURL = tryURLLikeSpecifierParse(specifier, scriptURL)
11
- const normalizedSpecifier = asURL ? asURL.href : specifier
12
- const scriptURLString = scriptURL.href
13
-
14
- for (const [scopePrefix, scopeImports] of Object.entries(parsedImportMap.scopes || {})) {
15
- if (
16
- scopePrefix === scriptURLString ||
17
- (scopePrefix.endsWith('/') && scriptURLString.startsWith(scopePrefix))
18
- ) {
19
- const scopeImportsMatch = resolveImportsMatch(normalizedSpecifier, scopeImports)
20
-
21
- if (scopeImportsMatch) {
22
- return { resolvedImport: scopeImportsMatch, matched: true }
23
- }
24
- }
25
- }
26
-
27
- const topLevelImportsMatch = resolveImportsMatch(
28
- normalizedSpecifier,
29
- parsedImportMap.imports || {}
30
- )
31
-
32
- if (topLevelImportsMatch) {
33
- return { resolvedImport: topLevelImportsMatch, matched: true }
34
- }
35
-
36
- // The specifier was able to be turned into a URL, but wasn't remapped into anything.
37
- if (asURL) {
38
- return { resolvedImport: asURL, matched: false }
39
- }
40
-
41
- return { resolvedImport: null, matched: false }
42
- }
43
-
44
- /**
45
- * @param {string} normalizedSpecifier
46
- * @param {ParsedSpecifierMap} specifierMap
47
- */
48
- function resolveImportsMatch(normalizedSpecifier, specifierMap) {
49
- for (const [specifierKey, resolutionResult] of Object.entries(specifierMap)) {
50
- // Exact-match case
51
- if (specifierKey === normalizedSpecifier) {
52
- if (!resolutionResult) {
53
- throw new TypeError(`Blocked by a null entry for "${specifierKey}"`)
54
- }
55
-
56
- if (!(resolutionResult instanceof URL)) {
57
- // Support aliases.
58
- // throw new TypeError(`Expected ${resolutionResult} to be a URL.`)
59
- }
60
-
61
- return resolutionResult
62
- }
63
-
64
- // Package prefix-match case
65
- if (specifierKey.endsWith('/') && normalizedSpecifier.startsWith(specifierKey)) {
66
- if (!resolutionResult) {
67
- throw new TypeError(`Blocked by a null entry for "${specifierKey}"`)
68
- }
69
-
70
- if (!(resolutionResult instanceof URL)) {
71
- throw new TypeError(`Expected ${resolutionResult} to be a URL.`)
72
- }
73
-
74
- const afterPrefix = normalizedSpecifier.substring(specifierKey.length)
75
-
76
- // Enforced by parsing
77
- if (!resolutionResult.href.endsWith('/')) {
78
- throw new TypeError(`Expected ${resolutionResult.href} to end with a '/'.`)
79
- }
80
-
81
- const url = tryURLParse(afterPrefix, resolutionResult)
82
- if (!url) {
83
- throw new TypeError(`Failed to resolve prefix-match relative URL for "${specifierKey}"`)
84
- }
85
-
86
- if (!(url instanceof URL)) {
87
- throw new TypeError(`Expected ${url} to be a URL.`)
88
- }
89
-
90
- return url
91
- }
92
- }
93
-
94
- return undefined
95
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * @param {string} string
3
- * @param {URL} [baseURL]
4
- * @returns {URL | undefined}
5
- */
6
- export function tryURLParse(string, baseURL) {
7
- try {
8
- return new URL(string, baseURL)
9
- } catch (e) {
10
- return undefined
11
- }
12
- }
13
-
14
- /**
15
- * @param {string} specifier
16
- * @param {URL} baseURL
17
- * @returns {URL | undefined}
18
- */
19
- export function tryURLLikeSpecifierParse(specifier, baseURL) {
20
- if (specifier.startsWith('/') || specifier.startsWith('./') || specifier.startsWith('../')) {
21
- return tryURLParse(specifier, baseURL)
22
- }
23
-
24
- return tryURLParse(specifier)
25
- }