proscenium 0.5.0-x86_64-darwin → 0.6.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.
- checksums.yaml +4 -4
- data/README.md +16 -1
- data/bin/esbuild +0 -0
- data/lib/proscenium/compilers/esbuild/css/postcss.js +2 -2
- data/lib/proscenium/compilers/esbuild/import_map/parser.js +178 -0
- data/lib/proscenium/compilers/esbuild/{import_map.js → import_map/read.js} +7 -2
- data/lib/proscenium/compilers/esbuild/import_map/resolver.js +95 -0
- data/lib/proscenium/compilers/esbuild/import_map/utils.js +25 -0
- data/lib/proscenium/compilers/esbuild/resolve_plugin.js +14 -12
- data/lib/proscenium/compilers/esbuild.js +1 -1
- data/lib/proscenium/utils.js +4 -0
- data/lib/proscenium/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87f97093007fdb59a8a3d34075e2570f6871c63bb404d3263fb3b21fd25d6a4e
|
4
|
+
data.tar.gz: c6a5f64992acaa9bff23de20ae9c317db60c504fa2f62d00e8bbab991b430892
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3519fae0fb5c95d5cc50dbce5e665cdbef81c484236605ecbe7ea18f16a9803c65ba70051d33296bd7ea3ae2e4d9f1e32b7cf502467b985a9f3f607af749fea5
|
7
|
+
data.tar.gz: 351f524bbb591d39ebf823d9939932511da63d61e971f604c2660f64ca1dd3635a2ae6935064cad359a8fd1336859b77e98fd9598d95492d2c23bb36e2f7f635
|
data/README.md
CHANGED
@@ -117,7 +117,10 @@ as you could end up swallowing everything, resulting in a very large file.
|
|
117
117
|
## Import Map
|
118
118
|
|
119
119
|
Import map for both JS and CSS is supported out of the box, and works with no regard to the browser
|
120
|
-
version being used.
|
120
|
+
version being used. This is because the import map is parsed and resolved by Proscenium on the
|
121
|
+
server.
|
122
|
+
|
123
|
+
Just create `config/import_map.json`:
|
121
124
|
|
122
125
|
```json
|
123
126
|
{
|
@@ -157,6 +160,18 @@ env => ({
|
|
157
160
|
})
|
158
161
|
```
|
159
162
|
|
163
|
+
### Aliasing
|
164
|
+
|
165
|
+
You can also use the import map to define aliases:
|
166
|
+
|
167
|
+
```json
|
168
|
+
{
|
169
|
+
"imports": {
|
170
|
+
"react": "preact/compact",
|
171
|
+
}
|
172
|
+
}
|
173
|
+
```
|
174
|
+
|
160
175
|
## Side Loading
|
161
176
|
|
162
177
|
Proscenium has built in support for automatically side loading JS and CSS with your views and
|
data/bin/esbuild
CHANGED
Binary file
|
@@ -1,12 +1,12 @@
|
|
1
1
|
import { expandGlob } from 'std/fs/mod.ts'
|
2
|
-
import postcss
|
2
|
+
import postcss from 'postcss'
|
3
3
|
|
4
4
|
export default async (root, path) => {
|
5
5
|
let tmpFile
|
6
6
|
let contents
|
7
7
|
|
8
8
|
const mixinFiles = []
|
9
|
-
for await (const file of expandGlob(
|
9
|
+
for await (const file of expandGlob('lib/**/*.mixin.css', { root, globstar: true })) {
|
10
10
|
mixinFiles.push(file.path)
|
11
11
|
}
|
12
12
|
|
@@ -0,0 +1,178 @@
|
|
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,5 +1,10 @@
|
|
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
|
+
|
1
6
|
import { join } from 'std/path/mod.ts'
|
2
|
-
import { parseFromString } from '
|
7
|
+
import { parseFromString } from './parser.js'
|
3
8
|
|
4
9
|
const baseURL = new URL('file://')
|
5
10
|
|
@@ -16,7 +21,7 @@ class ImportMapError extends Error {
|
|
16
21
|
}
|
17
22
|
}
|
18
23
|
|
19
|
-
export function
|
24
|
+
export default function (fileName, rootDir) {
|
20
25
|
let importMap
|
21
26
|
|
22
27
|
if (fileName) {
|
@@ -0,0 +1,95 @@
|
|
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
|
+
}
|
@@ -0,0 +1,25 @@
|
|
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
|
+
}
|
@@ -1,8 +1,9 @@
|
|
1
1
|
import { join, resolve } from 'std/path/mod.ts'
|
2
|
-
import
|
2
|
+
import resolveFromImportMap from './import_map/resolver.js'
|
3
3
|
import { cache } from 'cache'
|
4
4
|
|
5
5
|
import setup from './setup_plugin.js'
|
6
|
+
import { isBareModule } from '../../utils.js'
|
6
7
|
|
7
8
|
const importKinds = ['import-statement', 'dynamic-import', 'require-call', 'import-rule']
|
8
9
|
|
@@ -108,16 +109,21 @@ export default setup('resolve', (build, options) => {
|
|
108
109
|
}
|
109
110
|
|
110
111
|
const { matched, resolvedImport } = resolveFromImportMap(params.path, importMap, baseURL)
|
112
|
+
// console.log({ importMap, matched, resolvedImport })
|
111
113
|
|
112
114
|
if (matched) {
|
113
|
-
if (resolvedImport
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
115
|
+
if (resolvedImport instanceof URL) {
|
116
|
+
if (resolvedImport.protocol === 'file:') {
|
117
|
+
params.path = resolvedImport.pathname
|
118
|
+
} else {
|
119
|
+
if (params.importer.endsWith('.css')) {
|
120
|
+
return { path: resolvedImport.href, external: true }
|
121
|
+
}
|
122
|
+
|
123
|
+
return { path: `/url:${encodeURIComponent(resolvedImport.href)}`, external: true }
|
118
124
|
}
|
119
|
-
|
120
|
-
|
125
|
+
} else {
|
126
|
+
result.path = resolvedImport
|
121
127
|
}
|
122
128
|
}
|
123
129
|
}
|
@@ -199,7 +205,3 @@ export default setup('resolve', (build, options) => {
|
|
199
205
|
return result
|
200
206
|
}
|
201
207
|
})
|
202
|
-
|
203
|
-
function isBareModule(mod) {
|
204
|
-
return !mod.startsWith('/') && !mod.startsWith('.')
|
205
|
-
}
|
@@ -4,7 +4,7 @@ import { expandGlob } from 'std/fs/mod.ts'
|
|
4
4
|
import { join, isGlob, resolve, dirname, fromFileUrl } from 'std/path/mod.ts'
|
5
5
|
import { build, stop } from 'esbuild'
|
6
6
|
|
7
|
-
import
|
7
|
+
import readImportMap from './esbuild/import_map/read.js'
|
8
8
|
import envPlugin from './esbuild/env_plugin.js'
|
9
9
|
import cssPlugin from './esbuild/css_plugin.js'
|
10
10
|
import resolvePlugin from './esbuild/resolve_plugin.js'
|
data/lib/proscenium/utils.js
CHANGED
data/lib/proscenium/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: proscenium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: x86_64-darwin
|
6
6
|
authors:
|
7
7
|
- Joel Moss
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actioncable
|
@@ -167,7 +167,10 @@ files:
|
|
167
167
|
- lib/proscenium/compilers/esbuild/css_plugin.js
|
168
168
|
- lib/proscenium/compilers/esbuild/env_plugin.js
|
169
169
|
- lib/proscenium/compilers/esbuild/http_bundle_plugin.js
|
170
|
-
- lib/proscenium/compilers/esbuild/import_map.js
|
170
|
+
- lib/proscenium/compilers/esbuild/import_map/parser.js
|
171
|
+
- lib/proscenium/compilers/esbuild/import_map/read.js
|
172
|
+
- lib/proscenium/compilers/esbuild/import_map/resolver.js
|
173
|
+
- lib/proscenium/compilers/esbuild/import_map/utils.js
|
171
174
|
- lib/proscenium/compilers/esbuild/resolve_plugin.js
|
172
175
|
- lib/proscenium/compilers/esbuild/setup_plugin.js
|
173
176
|
- lib/proscenium/compilers/esbuild/solidjs_plugin.js
|