proscenium 0.1.0.alpha2-x86_64-linux → 0.1.0.alpha3-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 +158 -29
- data/bin/esbuild +0 -0
- data/bin/parcel_css +0 -0
- data/config/routes.rb +1 -1
- data/lib/proscenium/compilers/esbuild/compile_error.js +145 -0
- data/lib/proscenium/compilers/esbuild/css_plugin.js +76 -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 +38 -35
- data/lib/proscenium/compilers/esbuild/setup_plugin.js +23 -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 +60 -19
- data/lib/proscenium/helper.rb +2 -2
- data/lib/proscenium/middleware/base.rb +13 -3
- data/lib/proscenium/middleware/esbuild.rb +14 -0
- data/lib/proscenium/middleware/parcel_css.rb +30 -3
- data/lib/proscenium/middleware.rb +3 -0
- data/lib/proscenium/railtie.rb +16 -18
- data/lib/proscenium/runtime/component_manager/index.js +7 -7
- data/lib/proscenium/runtime/component_manager/{render_component.js → render_component.jsx} +9 -13
- data/lib/proscenium/version.rb +1 -1
- metadata +8 -14
- 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
@@ -1,35 +1,45 @@
|
|
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
6
|
const baseURL = new URL('file://')
|
10
|
-
const importKinds = ['import-statement', 'dynamic-import', 'require-call']
|
7
|
+
const importKinds = ['import-statement', 'dynamic-import', 'require-call', 'import-rule']
|
11
8
|
|
12
9
|
export default setup('resolve', (build, options) => {
|
13
|
-
const { runtimeDir } = options
|
10
|
+
const { runtimeDir, importMap } = options
|
14
11
|
const cwd = build.initialOptions.absWorkingDir
|
15
12
|
const runtimeCwdAlias = `${cwd}/proscenium-runtime`
|
16
|
-
const importMap = readImportMap()
|
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
32
|
if (args.path.startsWith('@proscenium/')) {
|
29
|
-
|
30
|
-
|
31
|
-
|
33
|
+
const result = { suffix: args.suffix }
|
34
|
+
|
35
|
+
if (args.queryParams?.has('bundle')) {
|
36
|
+
result.path = join(runtimeDir, `${args.path.replace(/^@proscenium/, '')}/index.js`)
|
37
|
+
} else {
|
38
|
+
result.path = `${args.path.replace(/^@proscenium/, '/proscenium-runtime')}/index.js`
|
39
|
+
result.external = true
|
32
40
|
}
|
41
|
+
|
42
|
+
return result
|
33
43
|
}
|
34
44
|
|
35
45
|
if (args.path.startsWith(runtimeCwdAlias)) {
|
@@ -43,7 +53,8 @@ export default setup('resolve', (build, options) => {
|
|
43
53
|
}
|
44
54
|
},
|
45
55
|
|
46
|
-
|
56
|
+
{
|
57
|
+
type: 'onLoad',
|
47
58
|
filter: /.*/,
|
48
59
|
namespace: 'importStylesheet',
|
49
60
|
callback(args) {
|
@@ -67,7 +78,7 @@ export default setup('resolve', (build, options) => {
|
|
67
78
|
return result
|
68
79
|
}
|
69
80
|
}
|
70
|
-
|
81
|
+
]
|
71
82
|
|
72
83
|
// Resolve the given `params.path` to a path relative to the Rails root.
|
73
84
|
//
|
@@ -76,7 +87,7 @@ export default setup('resolve', (build, options) => {
|
|
76
87
|
// './my_module' -> '/.../app/my_module.js'
|
77
88
|
// '/app/my_module' -> '/.../app/my_module.js'
|
78
89
|
async function unbundleImport(params) {
|
79
|
-
const result = { path: params.path }
|
90
|
+
const result = { path: params.path, suffix: params.suffix }
|
80
91
|
|
81
92
|
if (importMap) {
|
82
93
|
const { matched, resolvedImport } = resolveFromImportMap(params.path, importMap, baseURL)
|
@@ -108,7 +119,17 @@ export default setup('resolve', (build, options) => {
|
|
108
119
|
// throw `${resolveResult.errors[0].text} (resolveDir: ${cwd})`
|
109
120
|
}
|
110
121
|
|
111
|
-
|
122
|
+
// If bundle queryParam is defined, return the resolveResult.
|
123
|
+
if (params.queryParams?.has('bundle')) {
|
124
|
+
return { ...resolveResult, suffix: result.suffix }
|
125
|
+
}
|
126
|
+
|
127
|
+
if (resolveResult.path.startsWith(runtimeDir)) {
|
128
|
+
result.path = '/proscenium-runtime' + resolveResult.path.slice(runtimeDir.length)
|
129
|
+
} else {
|
130
|
+
result.path = resolveResult.path.slice(cwd.length)
|
131
|
+
}
|
132
|
+
|
112
133
|
result.sideEffects = resolveResult.sideEffects
|
113
134
|
|
114
135
|
if (
|
@@ -119,27 +140,9 @@ export default setup('resolve', (build, options) => {
|
|
119
140
|
// We're importing a CSS file from JS(X).
|
120
141
|
result.namespace = 'importStylesheet'
|
121
142
|
} else {
|
122
|
-
// Requested path is a bare module.
|
123
143
|
result.external = true
|
124
144
|
}
|
125
145
|
|
126
146
|
return result
|
127
147
|
}
|
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
148
|
})
|
142
|
-
|
143
|
-
function isBareModule(path) {
|
144
|
-
return !path.startsWith('.') && !path.startsWith('/')
|
145
|
-
}
|
@@ -1,35 +1,36 @@
|
|
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
|
-
|
12
|
+
options.debug &&
|
13
|
+
console.debug(`plugin(${pluginName}):onResolve`, params.path, { params })
|
12
14
|
|
13
|
-
|
14
|
-
const results = await callback(params)
|
15
|
-
options.debug &&
|
16
|
-
console.debug(`plugin(${pluginName}):onResolve`, params.path, { results })
|
15
|
+
const results = await callback(params)
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
}
|
17
|
+
options.debug &&
|
18
|
+
console.debug(`plugin(${pluginName}):onResolve`, params.path, { results })
|
21
19
|
|
22
|
-
|
23
|
-
|
20
|
+
return results
|
21
|
+
})
|
22
|
+
} else if (type === 'onLoad') {
|
23
|
+
build.onLoad({ filter, namespace }, async params => {
|
24
|
+
options.debug && console.debug(`plugin(${pluginName}):onLoad`, { params })
|
24
25
|
|
25
|
-
|
26
|
-
options.debug && console.debug(`plugin(${pluginName}):onLoad`, { params })
|
27
|
-
const results = callback(params)
|
28
|
-
options.debug && console.debug(`plugin(${pluginName}):onLoad`, { results })
|
26
|
+
const results = await callback(params)
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
options.debug && console.debug(`plugin(${pluginName}):onLoad`, { results })
|
29
|
+
|
30
|
+
return results
|
31
|
+
})
|
32
|
+
}
|
33
|
+
})
|
33
34
|
}
|
34
35
|
})
|
35
36
|
}
|
@@ -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
|
})
|
@@ -4,21 +4,37 @@ 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 { readImportMap } from './esbuild/import_map.js'
|
7
8
|
import envPlugin from './esbuild/env_plugin.js'
|
9
|
+
import cssPlugin from './esbuild/css_plugin.js'
|
8
10
|
import resolvePlugin from './esbuild/resolve_plugin.js'
|
9
11
|
import ArgumentError from './esbuild/argument_error.js'
|
12
|
+
import throwCompileError from './esbuild/compile_error.js'
|
10
13
|
|
11
14
|
if (import.meta.main) {
|
15
|
+
!Deno.env.get('RAILS_ENV') && Deno.env.set('RAILS_ENV', 'development')
|
16
|
+
|
12
17
|
const { _: paths, ...options } = parseArgs(Deno.args, {
|
13
|
-
string: ['root', 'runtime-dir'],
|
14
|
-
boolean: ['write'],
|
15
|
-
alias: {
|
18
|
+
string: ['root', 'runtime-dir', 'import-map'],
|
19
|
+
boolean: ['write', 'debug'],
|
20
|
+
alias: {
|
21
|
+
'runtime-dir': 'runtimeDir',
|
22
|
+
'import-map': 'importMap'
|
23
|
+
}
|
16
24
|
})
|
17
|
-
|
25
|
+
|
26
|
+
let result = await main(paths, options)
|
27
|
+
|
28
|
+
// `result` is an error object, so return to stderr as JSON, and an exit code of 1.
|
29
|
+
if (isPlainObject(result)) {
|
30
|
+
result = new TextEncoder().encode(`(${throwCompileError()})(${JSON.stringify(result)})`)
|
31
|
+
}
|
32
|
+
|
33
|
+
await writeAll(Deno.stdout, result)
|
18
34
|
}
|
19
35
|
|
20
36
|
async function main(paths = [], options = {}) {
|
21
|
-
const { root, write } = { write: false, ...options }
|
37
|
+
const { root, write, debug } = { write: false, ...options }
|
22
38
|
|
23
39
|
if (!Array.isArray(paths) || paths.length < 1) throw new ArgumentError('pathsRequired')
|
24
40
|
if (!root) throw new ArgumentError('rootRequired')
|
@@ -31,7 +47,9 @@ async function main(paths = [], options = {}) {
|
|
31
47
|
throw new ArgumentError('rootUnknown', { root })
|
32
48
|
}
|
33
49
|
|
34
|
-
const
|
50
|
+
const env = Deno.env.get('RAILS_ENV')
|
51
|
+
const isProd = env === 'production'
|
52
|
+
const isTest = env === 'test'
|
35
53
|
|
36
54
|
const entryPoints = new Set()
|
37
55
|
for (let i = 0; i < paths.length; i++) {
|
@@ -46,37 +64,60 @@ async function main(paths = [], options = {}) {
|
|
46
64
|
}
|
47
65
|
}
|
48
66
|
|
67
|
+
let importMap
|
68
|
+
try {
|
69
|
+
importMap = readImportMap(options.importMap, root)
|
70
|
+
} catch (error) {
|
71
|
+
return {
|
72
|
+
detail: error.stack,
|
73
|
+
text: `Cannot read/parse import map: ${error.message}`,
|
74
|
+
location: {
|
75
|
+
file: error.file
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
49
80
|
const runtimeDir = resolve(dirname(fromFileUrl(import.meta.url)), '../runtime')
|
50
81
|
|
51
82
|
const params = {
|
52
83
|
entryPoints: Array.from(entryPoints),
|
53
84
|
absWorkingDir: root,
|
54
|
-
logLevel: '
|
55
|
-
|
85
|
+
logLevel: 'silent',
|
86
|
+
logLimit: 1,
|
87
|
+
sourcemap: isTest ? false : isProd ? 'linked' : 'inline',
|
56
88
|
outdir: 'public/assets',
|
57
89
|
outbase: './',
|
58
90
|
format: 'esm',
|
59
|
-
|
60
|
-
|
91
|
+
jsx: 'automatic',
|
92
|
+
jsxDev: !isTest && !isProd,
|
61
93
|
minify: isProd,
|
62
94
|
bundle: true,
|
63
|
-
plugins: [envPlugin(), resolvePlugin({ runtimeDir, debug
|
64
|
-
inject: [join(runtimeDir, 'react_shim/index.js')],
|
95
|
+
plugins: [envPlugin(), resolvePlugin({ runtimeDir, importMap, debug }), cssPlugin({ debug })],
|
65
96
|
metafile: write,
|
66
97
|
write
|
67
98
|
}
|
68
99
|
|
100
|
+
let result
|
69
101
|
try {
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
return new TextEncoder().encode(JSON.stringify(result))
|
74
|
-
} else {
|
75
|
-
return result.outputFiles[0].contents
|
76
|
-
}
|
102
|
+
result = await build(params)
|
103
|
+
} catch (error) {
|
104
|
+
return { ...error.errors[0] }
|
77
105
|
} finally {
|
78
106
|
stop()
|
79
107
|
}
|
108
|
+
|
109
|
+
if (write) {
|
110
|
+
return new TextEncoder().encode(JSON.stringify(result))
|
111
|
+
} else {
|
112
|
+
return result.outputFiles[0].contents
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
export function isPlainObject(value) {
|
117
|
+
if (Object.prototype.toString.call(value) !== '[object Object]') return false
|
118
|
+
|
119
|
+
const prototype = Object.getPrototypeOf(value)
|
120
|
+
return prototype === null || prototype === Object.prototype
|
80
121
|
}
|
81
122
|
|
82
123
|
export default main
|
data/lib/proscenium/helper.rb
CHANGED
@@ -21,12 +21,12 @@ module Proscenium
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def proscenium_dev
|
24
|
-
return
|
24
|
+
return unless Proscenium.config.auto_reload
|
25
25
|
|
26
26
|
javascript_tag %(
|
27
27
|
import autoReload from '/proscenium-runtime/auto_reload.js';
|
28
28
|
autoReload('#{Proscenium::Railtie.websocket_mount_path}');
|
29
|
-
), type: 'module'
|
29
|
+
), type: 'module', defer: true
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -7,7 +7,9 @@ module Proscenium
|
|
7
7
|
class Base
|
8
8
|
include ActiveSupport::Benchmarkable
|
9
9
|
|
10
|
-
|
10
|
+
# Error when the result of the build returns an error. For example, when esbuild returns
|
11
|
+
# errors.
|
12
|
+
class CompileError < StandardError; end
|
11
13
|
|
12
14
|
def self.attempt(request)
|
13
15
|
new(request).renderable!&.attempt
|
@@ -57,15 +59,23 @@ module Proscenium
|
|
57
59
|
response.write content
|
58
60
|
response.content_type = content_type
|
59
61
|
response['X-Proscenium-Middleware'] = name
|
62
|
+
|
63
|
+
yield response if block_given?
|
64
|
+
|
60
65
|
response.finish
|
61
66
|
end
|
62
67
|
|
63
68
|
def build(cmd)
|
64
69
|
stdout, stderr, status = Open3.capture3(cmd)
|
65
70
|
|
66
|
-
|
71
|
+
unless status.success?
|
72
|
+
raise self.class::CompileError, stderr if status.exitstatus == 2
|
73
|
+
|
74
|
+
raise BuildError, stderr
|
75
|
+
end
|
76
|
+
|
67
77
|
unless stderr.empty?
|
68
|
-
raise "Proscenium build of #{name}:'#{@request.fullpath}' failed -- #{stderr}"
|
78
|
+
raise BuildError, "Proscenium build of #{name}:'#{@request.fullpath}' failed -- #{stderr}"
|
69
79
|
end
|
70
80
|
|
71
81
|
stdout
|
@@ -3,10 +3,24 @@
|
|
3
3
|
module Proscenium
|
4
4
|
class Middleware
|
5
5
|
class Esbuild < Base
|
6
|
+
class CompileError < StandardError
|
7
|
+
attr_reader :detail
|
8
|
+
|
9
|
+
def initialize(detail)
|
10
|
+
@detail = ActiveSupport::HashWithIndifferentAccess.new(Oj.load(detail, mode: :strict))
|
11
|
+
|
12
|
+
super "#{@detail[:text]} in #{@detail[:location][:file]}:#{@detail[:location][:line]}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
6
16
|
def attempt
|
7
17
|
benchmark :esbuild do
|
8
18
|
render_response build("#{cli} --root #{root} #{path}")
|
9
19
|
end
|
20
|
+
rescue CompileError => e
|
21
|
+
render_response "export default #{e.detail.to_json}" do |response|
|
22
|
+
response['X-Proscenium-Middleware'] = 'Esbuild::CompileError'
|
23
|
+
end
|
10
24
|
end
|
11
25
|
|
12
26
|
private
|
@@ -7,19 +7,46 @@ module Proscenium
|
|
7
7
|
class ParcelCss < Base
|
8
8
|
def attempt
|
9
9
|
benchmark :parcelcss do
|
10
|
-
|
11
|
-
render_response css_module? ? Oj.load(results, mode: :strict)['code'] : results
|
10
|
+
with_custom_media { |path| build path }
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
15
14
|
private
|
16
15
|
|
16
|
+
def with_custom_media
|
17
|
+
if custom_media?
|
18
|
+
Tempfile.create do |f|
|
19
|
+
contents = Pathname.new("#{root}#{@request.path}").read
|
20
|
+
f.write contents, "\n", custom_media_path.read
|
21
|
+
f.rewind
|
22
|
+
|
23
|
+
yield f.path
|
24
|
+
end
|
25
|
+
else
|
26
|
+
yield "#{root}#{@request.path}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def build(path)
|
31
|
+
results = super("#{cli} #{cli_options.join ' '} #{path}")
|
32
|
+
render_response css_module? ? Oj.load(results, mode: :strict)['code'] : results
|
33
|
+
end
|
34
|
+
|
35
|
+
def custom_media?
|
36
|
+
@custom_media ||= custom_media_path.exist?
|
37
|
+
end
|
38
|
+
|
39
|
+
def custom_media_path
|
40
|
+
@custom_media_path ||= Rails.root.join('lib', 'custom_media_queries.css')
|
41
|
+
end
|
42
|
+
|
17
43
|
def cli
|
18
44
|
Gem.bin_path 'proscenium', 'parcel_css'
|
19
45
|
end
|
20
46
|
|
21
47
|
def cli_options
|
22
|
-
options = ['--nesting', '--
|
48
|
+
options = ['--nesting', '--targets', "'>= 0.25%'"]
|
49
|
+
options << '--custom-media' if custom_media?
|
23
50
|
|
24
51
|
if css_module?
|
25
52
|
hash = Digest::SHA1.hexdigest(@request.path)[..7]
|
data/lib/proscenium/railtie.rb
CHANGED
@@ -13,15 +13,15 @@ module Proscenium
|
|
13
13
|
# See https://doc.deno.land/https://deno.land/std@0.145.0/path/mod.ts/~/globToRegExp
|
14
14
|
DEFAULT_GLOB_TYPES = {
|
15
15
|
esbuild: [
|
16
|
-
'
|
17
|
-
'
|
18
|
-
'app
|
19
|
-
],
|
20
|
-
parcelcss: [
|
21
|
-
'lib/**/*.css',
|
22
|
-
'app/components/**/*.css',
|
23
|
-
'app/views/**/*.css'
|
16
|
+
'config/**/*.{js,jsx,css}',
|
17
|
+
'lib/**/*.{js,jsx,css}',
|
18
|
+
'app/**/*.{js,jsx,css}'
|
24
19
|
]
|
20
|
+
# parcelcss: [
|
21
|
+
# 'config/**/*.css',
|
22
|
+
# 'lib/**/*.css',
|
23
|
+
# 'app/**/*.css'
|
24
|
+
# ]
|
25
25
|
}.freeze
|
26
26
|
|
27
27
|
class << self
|
@@ -34,18 +34,16 @@ module Proscenium
|
|
34
34
|
isolate_namespace Proscenium
|
35
35
|
|
36
36
|
config.proscenium = ActiveSupport::OrderedOptions.new
|
37
|
-
config.proscenium.listen_paths ||= %w[lib app]
|
38
|
-
config.proscenium.listen_extensions ||= /\.(css|jsx?)$/
|
39
37
|
config.proscenium.side_load = true
|
38
|
+
config.proscenium.auto_reload = Rails.env.development?
|
39
|
+
config.proscenium.auto_reload_paths ||= %w[lib app config]
|
40
|
+
config.proscenium.auto_reload_extensions ||= /\.(css|jsx?)$/
|
40
41
|
|
41
42
|
initializer 'proscenium.configuration' do |app|
|
42
43
|
options = app.config.proscenium
|
43
44
|
|
44
45
|
options.glob_types = DEFAULT_GLOB_TYPES if options.glob_types.blank?
|
45
|
-
|
46
|
-
options.auto_refresh = true if options.auto_refresh.nil?
|
47
|
-
options.listen = Rails.env.development? if options.listen.nil?
|
48
|
-
options.listen_paths.filter! { |path| Dir.exist? path }
|
46
|
+
options.auto_reload_paths.filter! { |path| Dir.exist? path }
|
49
47
|
options.cable_mount_path ||= '/proscenium-cable'
|
50
48
|
options.cable_logger ||= Rails.logger
|
51
49
|
end
|
@@ -73,10 +71,10 @@ module Proscenium
|
|
73
71
|
end
|
74
72
|
|
75
73
|
config.after_initialize do
|
76
|
-
next unless config.proscenium.
|
74
|
+
next unless config.proscenium.auto_reload
|
77
75
|
|
78
|
-
@listener = Listen.to(*config.proscenium.
|
79
|
-
only: config.proscenium.
|
76
|
+
@listener = Listen.to(*config.proscenium.auto_reload_paths,
|
77
|
+
only: config.proscenium.auto_reload_extensions) do |mod, add, rem|
|
80
78
|
Proscenium::Railtie.websocket&.broadcast('reload', {
|
81
79
|
modified: mod,
|
82
80
|
removed: rem,
|
@@ -94,7 +92,7 @@ module Proscenium
|
|
94
92
|
class << self
|
95
93
|
def websocket
|
96
94
|
return @websocket unless @websocket.nil?
|
97
|
-
return unless config.proscenium.
|
95
|
+
return unless config.proscenium.auto_reload
|
98
96
|
|
99
97
|
cable = ActionCable::Server::Configuration.new
|
100
98
|
cable.cable = { adapter: 'async' }.with_indifferent_access
|
@@ -1,18 +1,18 @@
|
|
1
1
|
/* eslint-disable no-console */
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
document.addEventListener('DOMContentLoaded', () => {
|
3
|
+
export async function init() {
|
6
4
|
const elements = document.querySelectorAll('[data-component]')
|
7
5
|
|
8
6
|
if (elements.length < 1) return
|
9
7
|
|
10
|
-
|
8
|
+
const { default: renderComponent } = await import(`./render_component`)
|
9
|
+
|
10
|
+
Array.from(elements, ele => {
|
11
11
|
const data = JSON.parse(ele.getAttribute('data-component'))
|
12
12
|
|
13
13
|
let isVisible = false
|
14
|
-
const observer = new IntersectionObserver(
|
15
|
-
entries.forEach(
|
14
|
+
const observer = new IntersectionObserver(entries => {
|
15
|
+
entries.forEach(entry => {
|
16
16
|
if (!isVisible && entry.isIntersecting) {
|
17
17
|
isVisible = true
|
18
18
|
observer.unobserve(ele)
|
@@ -24,4 +24,4 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
24
24
|
|
25
25
|
observer.observe(ele)
|
26
26
|
})
|
27
|
-
}
|
27
|
+
}
|
@@ -18,22 +18,18 @@ export default async function (ele, data) {
|
|
18
18
|
|
19
19
|
if (!contentLoader) return null
|
20
20
|
|
21
|
-
return
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
return (
|
22
|
+
<div
|
23
|
+
style={{ height: '100%' }}
|
24
|
+
dangerouslySetInnerHTML={{ __html: contentLoader.outerHTML }}
|
25
|
+
></div>
|
26
|
+
)
|
25
27
|
}
|
26
28
|
|
27
29
|
createRoot(ele).render(
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
fallback: /* @__PURE__ */ createElement(Fallback, {
|
32
|
-
contentLoader
|
33
|
-
})
|
34
|
-
},
|
35
|
-
createElement(component, data.props)
|
36
|
-
)
|
30
|
+
<Suspense fallback={<Fallback contentLoader={contentLoader} />}>
|
31
|
+
{createElement(component, data.props)}
|
32
|
+
</Suspense>
|
37
33
|
)
|
38
34
|
|
39
35
|
RAILS_ENV === 'development' && console.debug(`[REACT]`, `Rendered ${data.path.slice(1)}`)
|
data/lib/proscenium/version.rb
CHANGED