proscenium 0.1.0.alpha2-x86_64-linux → 0.1.0.alpha4-x86_64-linux
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 +216 -32
- data/app/components/react_component.rb +10 -3
- data/bin/esbuild +0 -0
- data/bin/lightningcss +0 -0
- data/config/routes.rb +1 -1
- data/lib/proscenium/compilers/esbuild/compile_error.js +147 -0
- data/lib/proscenium/compilers/esbuild/css/postcss.js +67 -0
- data/lib/proscenium/compilers/esbuild/css_plugin.js +176 -0
- data/lib/proscenium/compilers/esbuild/env_plugin.js +6 -4
- data/lib/proscenium/compilers/esbuild/http_bundle_plugin.js +53 -0
- data/lib/proscenium/compilers/esbuild/import_map.js +59 -0
- data/lib/proscenium/compilers/esbuild/resolve_plugin.js +67 -65
- data/lib/proscenium/compilers/esbuild/setup_plugin.js +32 -22
- data/lib/proscenium/{cli → compilers}/esbuild/solidjs_plugin.js +5 -4
- data/lib/proscenium/compilers/esbuild.bench.js +7 -3
- data/lib/proscenium/compilers/esbuild.js +93 -19
- data/lib/proscenium/css_module.rb +48 -6
- data/lib/proscenium/helper.rb +5 -3
- data/lib/proscenium/middleware/base.rb +13 -3
- data/lib/proscenium/middleware/esbuild.rb +17 -1
- data/lib/proscenium/middleware/lightningcss.rb +64 -0
- data/lib/proscenium/middleware.rb +7 -19
- data/lib/proscenium/phlex.rb +36 -0
- data/lib/proscenium/railtie.rb +10 -20
- data/lib/proscenium/runtime/auto_reload.js +3 -3
- data/lib/proscenium/side_load.rb +14 -40
- data/lib/proscenium/utils.js +8 -0
- data/lib/proscenium/version.rb +1 -1
- data/lib/proscenium/view_component.rb +5 -1
- data/lib/proscenium.rb +1 -0
- metadata +27 -19
- data/bin/parcel_css +0 -0
- data/lib/proscenium/cli/argument_error.js +0 -24
- data/lib/proscenium/cli/builders/index.js +0 -1
- data/lib/proscenium/cli/builders/javascript.js +0 -45
- data/lib/proscenium/cli/builders/react.js +0 -60
- data/lib/proscenium/cli/builders/solid.js +0 -46
- data/lib/proscenium/cli/esbuild/env_plugin.js +0 -21
- data/lib/proscenium/cli/esbuild/resolve_plugin.js +0 -136
- data/lib/proscenium/cli/js_builder.js +0 -194
- data/lib/proscenium/cli/solid.js +0 -15
- data/lib/proscenium/cli/utils.js +0 -93
- data/lib/proscenium/middleware/parcel_css.rb +0 -37
- data/lib/proscenium/runtime/component_manager/index.js +0 -27
- data/lib/proscenium/runtime/component_manager/render_component.js +0 -40
- data/lib/proscenium/runtime/import_css.js +0 -46
@@ -0,0 +1,176 @@
|
|
1
|
+
import { crypto } from 'std/crypto/mod.ts'
|
2
|
+
import { join, resolve, dirname, basename, fromFileUrl } 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 => {
|
9
|
+
const cwd = build.initialOptions.absWorkingDir
|
10
|
+
const lightningcssBin = resolve(
|
11
|
+
dirname(fromFileUrl(import.meta.url)),
|
12
|
+
'../../../../bin/lightningcss'
|
13
|
+
)
|
14
|
+
|
15
|
+
let customMedia
|
16
|
+
try {
|
17
|
+
customMedia = await Deno.readTextFile(join(cwd, 'config', 'custom_media_queries.css'))
|
18
|
+
} catch {
|
19
|
+
// do nothing, as we don't require custom media.
|
20
|
+
}
|
21
|
+
|
22
|
+
return [
|
23
|
+
{
|
24
|
+
type: 'onLoad',
|
25
|
+
filter: /\.css$/,
|
26
|
+
namespace: 'file',
|
27
|
+
async callback(args) {
|
28
|
+
const hash = await digest(args.path.slice(cwd.length))
|
29
|
+
const isCssModule = args.path.endsWith('.module.css')
|
30
|
+
|
31
|
+
// If path is a CSS module, imported from JS, and a side-loaded ViewComponent stylesheet,
|
32
|
+
// simply return a JS proxy of the class names. The stylesheet itself will have already been
|
33
|
+
// side loaded. This avoids compiling the CSS all over again.
|
34
|
+
if (isCssModule && args.pluginData?.importedFromJs && (await isViewComponent(args.path))) {
|
35
|
+
return {
|
36
|
+
resolveDir: cwd,
|
37
|
+
loader: 'js',
|
38
|
+
contents: cssModulesProxyTemplate(hash)
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
let cmd = [
|
43
|
+
lightningcssBin,
|
44
|
+
'--nesting',
|
45
|
+
'--error-recovery',
|
46
|
+
args.pluginData?.importedFromJs && '--minify',
|
47
|
+
'--targets',
|
48
|
+
'>= 0.25%'
|
49
|
+
].filter(Boolean)
|
50
|
+
|
51
|
+
// This will process the CSS with Postcss only if it needs to.
|
52
|
+
let [tmpFile, contents] = await postcss(cwd, args.path)
|
53
|
+
|
54
|
+
// As custom media are defined in their own file, we have to append the file contents to our
|
55
|
+
// stylesheet, so that the custom media can be used.
|
56
|
+
if (customMedia) {
|
57
|
+
cmd.push('--custom-media')
|
58
|
+
|
59
|
+
if (!tmpFile && !contents) {
|
60
|
+
tmpFile = await Deno.makeTempFile()
|
61
|
+
contents = await Deno.readTextFile(args.path)
|
62
|
+
}
|
63
|
+
|
64
|
+
contents += customMedia
|
65
|
+
}
|
66
|
+
|
67
|
+
if (tmpFile && contents) {
|
68
|
+
await Deno.writeTextFile(tmpFile, contents)
|
69
|
+
}
|
70
|
+
|
71
|
+
if (isCssModule) {
|
72
|
+
cmd = cmd.concat(['--css-modules', '--css-modules-pattern', `[local]${hash}`])
|
73
|
+
}
|
74
|
+
|
75
|
+
const p = Deno.run({
|
76
|
+
cmd: [...cmd, tmpFile || args.path],
|
77
|
+
stdout: 'piped',
|
78
|
+
stderr: 'piped'
|
79
|
+
})
|
80
|
+
|
81
|
+
const { code } = await p.status()
|
82
|
+
const rawOutput = await p.output()
|
83
|
+
const rawError = await p.stderrOutput()
|
84
|
+
|
85
|
+
// Even though Deno docs say that reading the outputs (above) closes their pipes, warnings
|
86
|
+
// are raised during tests that the child process have not been closed. So we manually close
|
87
|
+
// here.
|
88
|
+
p.close()
|
89
|
+
|
90
|
+
// Success!
|
91
|
+
if (code === 0) {
|
92
|
+
let contents = new TextDecoder().decode(rawOutput)
|
93
|
+
if (isCssModule) {
|
94
|
+
contents = JSON.parse(contents)
|
95
|
+
}
|
96
|
+
|
97
|
+
// If stylesheet is imported from JS, then we return JS code that appends the stylesheet
|
98
|
+
// in a <style> in the <head> of the page, and if the stylesheet is a CSS module, it
|
99
|
+
// exports a plain object of class names.
|
100
|
+
if (args.pluginData?.importedFromJs) {
|
101
|
+
const code = isCssModule ? contents.code : contents
|
102
|
+
const mod = [
|
103
|
+
`let e = document.querySelector('#_${hash}');`,
|
104
|
+
'if (!e) {',
|
105
|
+
"e = document.createElement('style');",
|
106
|
+
`e.id = '_${hash}';`,
|
107
|
+
'document.head.appendChild(e);',
|
108
|
+
`e.appendChild(document.createTextNode(\`${code}\`));`,
|
109
|
+
'}'
|
110
|
+
]
|
111
|
+
|
112
|
+
if (isCssModule) {
|
113
|
+
const classes = {}
|
114
|
+
for (const key in contents.exports) {
|
115
|
+
if (Object.hasOwnProperty.call(contents.exports, key)) {
|
116
|
+
classes[key] = contents.exports[key].name
|
117
|
+
}
|
118
|
+
}
|
119
|
+
mod.push(`export default ${JSON.stringify(classes)};`)
|
120
|
+
}
|
121
|
+
|
122
|
+
// We are importing from JS, so return the entire result from LightningCSS via the js
|
123
|
+
// loader.
|
124
|
+
return {
|
125
|
+
resolveDir: cwd,
|
126
|
+
loader: 'js',
|
127
|
+
contents: mod.join('')
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
return { loader: 'css', contents: isCssModule ? contents.code : contents }
|
132
|
+
} else {
|
133
|
+
const errorString = new TextDecoder().decode(rawError)
|
134
|
+
throw errorString
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
]
|
139
|
+
})
|
140
|
+
|
141
|
+
async function digest(value) {
|
142
|
+
value = new TextEncoder().encode(value)
|
143
|
+
const view = new DataView(await crypto.subtle.digest('SHA-1', value))
|
144
|
+
|
145
|
+
let hexCodes = ''
|
146
|
+
for (let index = 0; index < view.byteLength; index += 4) {
|
147
|
+
hexCodes += view.getUint32(index).toString(16).padStart(8, '0')
|
148
|
+
}
|
149
|
+
|
150
|
+
return hexCodes.slice(0, 8)
|
151
|
+
}
|
152
|
+
|
153
|
+
async function isViewComponent(path) {
|
154
|
+
const fileName = basename(path)
|
155
|
+
const dirName = dirname(path)
|
156
|
+
|
157
|
+
return (
|
158
|
+
(fileName === 'component.module.css' && (await fileExists(join(dirName, 'component.rb')))) ||
|
159
|
+
(fileName.endsWith('_component.module.css') &&
|
160
|
+
(await fileExists(join(dirName, fileName.replace(/\.module\.css$/, '.rb')))))
|
161
|
+
)
|
162
|
+
}
|
163
|
+
|
164
|
+
function cssModulesProxyTemplate(hash) {
|
165
|
+
return [
|
166
|
+
`export default new Proxy( {}, {`,
|
167
|
+
` get(target, prop, receiver) {`,
|
168
|
+
` if (prop in target || typeof prop === 'symbol') {`,
|
169
|
+
` return Reflect.get(target, prop, receiver)`,
|
170
|
+
` } else {`,
|
171
|
+
` return prop + '${hash}'`,
|
172
|
+
` }`,
|
173
|
+
` }`,
|
174
|
+
`})`
|
175
|
+
].join('')
|
176
|
+
}
|
@@ -1,15 +1,17 @@
|
|
1
1
|
import setup from './setup_plugin.js'
|
2
2
|
|
3
3
|
export default setup('env', () => {
|
4
|
-
return
|
5
|
-
|
4
|
+
return [
|
5
|
+
{
|
6
|
+
type: 'onResolve',
|
6
7
|
filter: /^env$/,
|
7
8
|
callback({ path }) {
|
8
9
|
return { path, namespace: 'env' }
|
9
10
|
}
|
10
11
|
},
|
11
12
|
|
12
|
-
|
13
|
+
{
|
14
|
+
type: 'onLoad',
|
13
15
|
filter: /.*/,
|
14
16
|
namespace: 'env',
|
15
17
|
callback() {
|
@@ -17,5 +19,5 @@ export default setup('env', () => {
|
|
17
19
|
return { loader: 'json', contents: JSON.stringify(env) }
|
18
20
|
}
|
19
21
|
}
|
20
|
-
|
22
|
+
]
|
21
23
|
})
|
@@ -0,0 +1,53 @@
|
|
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
|
+
})
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import { join } from 'std/path/mod.ts'
|
2
|
+
import { parseFromString } from 'import-maps/resolve'
|
3
|
+
|
4
|
+
const baseURL = new URL('file://')
|
5
|
+
|
6
|
+
class ImportMapError extends Error {
|
7
|
+
constructor(fileName, ...params) {
|
8
|
+
super(...params)
|
9
|
+
|
10
|
+
if (Error.captureStackTrace) {
|
11
|
+
Error.captureStackTrace(this, ImportMapError)
|
12
|
+
}
|
13
|
+
|
14
|
+
this.name = 'ImportMapError'
|
15
|
+
this.file = fileName
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
export function readImportMap(fileName, rootDir) {
|
20
|
+
let importMap
|
21
|
+
|
22
|
+
if (fileName) {
|
23
|
+
importMap = readFile(fileName, rootDir, true)
|
24
|
+
} else {
|
25
|
+
fileName = ['config/import_map.json', 'config/import_map.js'].find(f => {
|
26
|
+
const result = readFile(f, rootDir)
|
27
|
+
if (result) {
|
28
|
+
importMap = result
|
29
|
+
return true
|
30
|
+
}
|
31
|
+
})
|
32
|
+
}
|
33
|
+
|
34
|
+
return importMap
|
35
|
+
}
|
36
|
+
|
37
|
+
function readFile(file, rootDir, required = false) {
|
38
|
+
let contents = null
|
39
|
+
|
40
|
+
try {
|
41
|
+
contents = Deno.readTextFileSync(join(rootDir, file))
|
42
|
+
} catch (error) {
|
43
|
+
if (required) {
|
44
|
+
throw new ImportMapError(file, error.message, { cause: error })
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
if (contents === null) return null
|
49
|
+
|
50
|
+
try {
|
51
|
+
if (file.endsWith('.js')) {
|
52
|
+
contents = JSON.stringify(eval(contents)(Deno.env.get('RAILS_ENV')))
|
53
|
+
}
|
54
|
+
|
55
|
+
return parseFromString(contents, baseURL)
|
56
|
+
} catch (error) {
|
57
|
+
throw new ImportMapError(file, error.message, { cause: error })
|
58
|
+
}
|
59
|
+
}
|
@@ -1,36 +1,50 @@
|
|
1
1
|
import { join, resolve } from 'std/path/mod.ts'
|
2
|
-
import {
|
3
|
-
parseFromString as parseImportMap,
|
4
|
-
resolve as resolveFromImportMap
|
5
|
-
} from 'import-maps/resolve'
|
2
|
+
import { resolve as resolveFromImportMap } from 'import-maps/resolve'
|
6
3
|
|
7
4
|
import setup from './setup_plugin.js'
|
8
5
|
|
9
|
-
const
|
10
|
-
const importKinds = ['import-statement', 'dynamic-import', 'require-call']
|
6
|
+
const importKinds = ['import-statement', 'dynamic-import', 'require-call', 'import-rule']
|
11
7
|
|
12
8
|
export default setup('resolve', (build, options) => {
|
13
|
-
const { runtimeDir } = options
|
9
|
+
const { runtimeDir, importMap } = options
|
14
10
|
const cwd = build.initialOptions.absWorkingDir
|
15
11
|
const runtimeCwdAlias = `${cwd}/proscenium-runtime`
|
16
|
-
|
12
|
+
let bundled = false
|
17
13
|
|
18
|
-
return
|
19
|
-
|
14
|
+
return [
|
15
|
+
{
|
16
|
+
type: 'onResolve',
|
20
17
|
filter: /.*/,
|
21
18
|
async callback(args) {
|
22
|
-
|
19
|
+
if (args.path.includes('?')) {
|
20
|
+
const [path, query] = args.path.split('?')
|
21
|
+
args.path = path
|
22
|
+
args.suffix = `?${query}`
|
23
|
+
args.queryParams = new URLSearchParams(query)
|
24
|
+
}
|
25
|
+
|
26
|
+
// Mark remote modules as external.
|
23
27
|
if (args.path.startsWith('http://') || args.path.startsWith('https://')) {
|
24
28
|
return { external: true }
|
25
29
|
}
|
26
30
|
|
27
31
|
// Proscenium runtime
|
28
|
-
if (args.path.startsWith('@proscenium/')) {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
}
|
32
|
+
// if (args.path.startsWith('@proscenium/')) {
|
33
|
+
// const result = { suffix: args.suffix }
|
34
|
+
|
35
|
+
// if (args.queryParams?.has('bundle-all')) {
|
36
|
+
// bundled = true
|
37
|
+
// }
|
38
|
+
|
39
|
+
// if (bundled || args.queryParams?.has('bundle')) {
|
40
|
+
// result.path = join(runtimeDir, `${args.path.replace(/^@proscenium/, '')}/index.js`)
|
41
|
+
// } else {
|
42
|
+
// result.path = `${args.path.replace(/^@proscenium/, '/proscenium-runtime')}/index.js`
|
43
|
+
// result.external = true
|
44
|
+
// }
|
45
|
+
|
46
|
+
// return result
|
47
|
+
// }
|
34
48
|
|
35
49
|
if (args.path.startsWith(runtimeCwdAlias)) {
|
36
50
|
return { path: join(runtimeDir, args.path.slice(runtimeCwdAlias.length)) }
|
@@ -41,33 +55,8 @@ export default setup('resolve', (build, options) => {
|
|
41
55
|
return await unbundleImport(args)
|
42
56
|
}
|
43
57
|
}
|
44
|
-
},
|
45
|
-
|
46
|
-
onLoad: {
|
47
|
-
filter: /.*/,
|
48
|
-
namespace: 'importStylesheet',
|
49
|
-
callback(args) {
|
50
|
-
const result = {
|
51
|
-
resolveDir: cwd,
|
52
|
-
loader: 'js'
|
53
|
-
}
|
54
|
-
|
55
|
-
if (args.path.endsWith('.module.css')) {
|
56
|
-
result.contents = `
|
57
|
-
import { importCssModule } from '/proscenium-runtime/import_css.js'
|
58
|
-
export default await importCssModule('${args.path}')
|
59
|
-
`
|
60
|
-
} else {
|
61
|
-
result.contents = `
|
62
|
-
import { appendStylesheet } from '/proscenium-runtime/import_css.js'
|
63
|
-
appendStylesheet('${args.path}')
|
64
|
-
`
|
65
|
-
}
|
66
|
-
|
67
|
-
return result
|
68
|
-
}
|
69
58
|
}
|
70
|
-
|
59
|
+
]
|
71
60
|
|
72
61
|
// Resolve the given `params.path` to a path relative to the Rails root.
|
73
62
|
//
|
@@ -76,10 +65,12 @@ export default setup('resolve', (build, options) => {
|
|
76
65
|
// './my_module' -> '/.../app/my_module.js'
|
77
66
|
// '/app/my_module' -> '/.../app/my_module.js'
|
78
67
|
async function unbundleImport(params) {
|
79
|
-
const result = { path: params.path }
|
68
|
+
const result = { path: params.path, suffix: params.suffix }
|
80
69
|
|
81
70
|
if (importMap) {
|
71
|
+
const baseURL = new URL(params.importer.slice(cwd.length), 'file://')
|
82
72
|
const { matched, resolvedImport } = resolveFromImportMap(params.path, importMap, baseURL)
|
73
|
+
|
83
74
|
if (matched) {
|
84
75
|
if (resolvedImport.protocol === 'file:') {
|
85
76
|
params.path = resolvedImport.pathname
|
@@ -97,18 +88,43 @@ export default setup('resolve', (build, options) => {
|
|
97
88
|
// Resolve the path using esbuild's internal resolution. This allows us to import node packages
|
98
89
|
// and extension-less paths without custom code, as esbuild with resolve them for us.
|
99
90
|
const resolveResult = await build.resolve(result.path, {
|
100
|
-
resolveDir
|
91
|
+
// If path is a bare module (node_modules), and resolveDir is the Proscenium runtime dir, then
|
92
|
+
// use `cwd` as the `resolveDir`, otherwise pass it through as is. This ensures that nested
|
93
|
+
// node_modules are resolved correctly.
|
94
|
+
resolveDir:
|
95
|
+
isBareModule(result.path) && params.resolveDir.startsWith(runtimeDir)
|
96
|
+
? cwd
|
97
|
+
: params.resolveDir,
|
101
98
|
pluginData: {
|
102
99
|
// We use this property later on, as we should ignore this resolution call.
|
103
100
|
isResolvingPath: true
|
104
101
|
}
|
105
102
|
})
|
106
103
|
|
107
|
-
if
|
108
|
-
|
104
|
+
// Simple return the resolved result if we have an error. Usually happens when module is not
|
105
|
+
// found.
|
106
|
+
if (resolveResult.errors.length > 0) return resolveResult
|
107
|
+
|
108
|
+
// If 'bundle-all' queryParam is defined, return the resolveResult.
|
109
|
+
if (bundled || params.queryParams?.has('bundle-all')) {
|
110
|
+
bundled = true
|
111
|
+
return { ...resolveResult, suffix: '?bundle-all' }
|
112
|
+
}
|
113
|
+
|
114
|
+
// If 'bundle' queryParam is defined, return the resolveResult.
|
115
|
+
if (params.queryParams?.has('bundle')) {
|
116
|
+
return { ...resolveResult, suffix: '?bundle' }
|
117
|
+
}
|
118
|
+
|
119
|
+
if (resolveResult.path.startsWith(runtimeDir)) {
|
120
|
+
result.path = '/proscenium-runtime' + resolveResult.path.slice(runtimeDir.length)
|
121
|
+
} else if (!resolveResult.path.startsWith(cwd)) {
|
122
|
+
// If resolved path does not start with cwd, then it is most likely linked, so bundle it.
|
123
|
+
return { ...resolveResult, suffix: '?bundle' }
|
124
|
+
} else {
|
125
|
+
result.path = resolveResult.path.slice(cwd.length)
|
109
126
|
}
|
110
127
|
|
111
|
-
result.path = resolveResult.path.slice(cwd.length)
|
112
128
|
result.sideEffects = resolveResult.sideEffects
|
113
129
|
|
114
130
|
if (
|
@@ -117,29 +133,15 @@ export default setup('resolve', (build, options) => {
|
|
117
133
|
/\.jsx?$/.test(params.importer)
|
118
134
|
) {
|
119
135
|
// We're importing a CSS file from JS(X).
|
120
|
-
|
136
|
+
return { ...resolveResult, pluginData: { importedFromJs: true } }
|
121
137
|
} else {
|
122
|
-
// Requested path is a bare module.
|
123
138
|
result.external = true
|
124
139
|
}
|
125
140
|
|
126
141
|
return result
|
127
142
|
}
|
128
|
-
|
129
|
-
function readImportMap() {
|
130
|
-
const file = join(cwd, 'config', 'import_map.json')
|
131
|
-
let source
|
132
|
-
|
133
|
-
try {
|
134
|
-
source = Deno.readTextFileSync(file)
|
135
|
-
} catch {
|
136
|
-
return null
|
137
|
-
}
|
138
|
-
|
139
|
-
return parseImportMap(source, baseURL)
|
140
|
-
}
|
141
143
|
})
|
142
144
|
|
143
|
-
function isBareModule(
|
144
|
-
return !
|
145
|
+
function isBareModule(mod) {
|
146
|
+
return !mod.startsWith('/') && !mod.startsWith('.')
|
145
147
|
}
|
@@ -1,35 +1,45 @@
|
|
1
1
|
export default (pluginName, pluginFn) => {
|
2
2
|
return (options = {}) => ({
|
3
3
|
name: pluginName,
|
4
|
-
setup(build) {
|
5
|
-
const
|
4
|
+
async setup(build) {
|
5
|
+
const callbacks = await pluginFn(build, options)
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
callbacks.forEach(({ type, callback, filter, namespace }) => {
|
8
|
+
if (type === 'onResolve') {
|
9
|
+
build.onResolve({ filter, namespace }, async params => {
|
10
|
+
if (params.pluginData?.isResolvingPath) return
|
9
11
|
|
10
|
-
|
11
|
-
if (params.pluginData?.isResolvingPath) return
|
12
|
+
let results
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
if (options.debug) {
|
15
|
+
console.debug()
|
16
|
+
console.group(`plugin(${pluginName}):onResolve`, { filter, namespace })
|
17
|
+
console.debug('params:', params)
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
try {
|
20
|
+
results = await callback(params)
|
21
|
+
console.debug('results:', results)
|
22
|
+
} finally {
|
23
|
+
console.groupEnd()
|
24
|
+
}
|
25
|
+
} else {
|
26
|
+
results = await callback(params)
|
27
|
+
}
|
21
28
|
|
22
|
-
|
23
|
-
|
29
|
+
return results
|
30
|
+
})
|
31
|
+
} else if (type === 'onLoad') {
|
32
|
+
build.onLoad({ filter, namespace }, async params => {
|
33
|
+
options.debug && console.debug(`plugin(${pluginName}):onLoad`, { params })
|
24
34
|
|
25
|
-
|
26
|
-
options.debug && console.debug(`plugin(${pluginName}):onLoad`, { params })
|
27
|
-
const results = callback(params)
|
28
|
-
options.debug && console.debug(`plugin(${pluginName}):onLoad`, { results })
|
35
|
+
const results = await callback(params)
|
29
36
|
|
30
|
-
|
31
|
-
|
32
|
-
|
37
|
+
options.debug && console.debug(`plugin(${pluginName}):onLoad`, { results })
|
38
|
+
|
39
|
+
return results
|
40
|
+
})
|
41
|
+
}
|
42
|
+
})
|
33
43
|
}
|
34
44
|
})
|
35
45
|
}
|
@@ -2,11 +2,12 @@ import { basename } from 'std/path/mod.ts'
|
|
2
2
|
import { transformAsync } from '@babel/core'
|
3
3
|
import solid from 'babel-preset-solid'
|
4
4
|
|
5
|
-
import { setup } from '
|
5
|
+
import { setup } from './setup_plugin.js'
|
6
6
|
|
7
7
|
export default setup('solidjs', () => {
|
8
|
-
return
|
9
|
-
|
8
|
+
return [
|
9
|
+
{
|
10
|
+
type: 'onLoad',
|
10
11
|
filter: /\.jsx$/,
|
11
12
|
async callback(args) {
|
12
13
|
const source = await Deno.readTextFile(args.path)
|
@@ -19,5 +20,5 @@ export default setup('solidjs', () => {
|
|
19
20
|
return { contents: code, loader: 'js' }
|
20
21
|
}
|
21
22
|
}
|
22
|
-
|
23
|
+
]
|
23
24
|
})
|
@@ -2,8 +2,12 @@ import { join } from 'std/path/mod.ts'
|
|
2
2
|
|
3
3
|
import compile from './esbuild.js'
|
4
4
|
|
5
|
-
const
|
5
|
+
const root = join(Deno.cwd(), 'test', 'internal')
|
6
6
|
|
7
|
-
Deno.bench('esbuild', async () => {
|
8
|
-
await compile(
|
7
|
+
Deno.bench('esbuild js', async () => {
|
8
|
+
await compile(['lib/foo.js'], { root })
|
9
|
+
})
|
10
|
+
|
11
|
+
Deno.bench('esbuild css', async () => {
|
12
|
+
await compile(['lib/foo.css'], { root })
|
9
13
|
})
|