porous 0.2.0 → 0.3.1
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/CHANGELOG.md +28 -1
- data/README.md +9 -9
- data/lib/porous/application.rb +2 -2
- data/lib/porous/cli/build.rb +3 -40
- data/lib/porous/cli/dev.rb +44 -0
- data/lib/porous/cli/server.rb +33 -33
- data/lib/porous/cli/template/.gitignore.tt +1 -0
- data/lib/porous/cli/template/README.md.tt +16 -2
- data/lib/porous/cli/template/pages/home.rb +1 -5
- data/lib/porous/cli/template/static/github.svg +4 -0
- data/lib/porous/cli.rb +5 -0
- data/lib/porous/server/application.rb +28 -0
- data/lib/porous/server/builder.rb +59 -0
- data/lib/porous/server/connect.rb +18 -0
- data/lib/porous/server/socket.rb +39 -0
- data/lib/porous/version.rb +1 -1
- data/lib/porous.rb +1 -2
- data/lib/virtual_dom/dom.rb +3 -2
- data/opal/porous/injection.rb +1 -1
- data/opal/porous.rb +15 -9
- metadata +11 -6
- data/lib/porous/server.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87c6a954ddaf691739b880123048bf3345ece37389404d7a1c7163b27119c0ac
|
4
|
+
data.tar.gz: d13c2be795c751e8eb6095e0642560065e4815ff04ac17ffd7605e1092d775ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84e53a85958c58e66417eeadc77fd35332ac0f30b7b59eaef49e39ebeb1cc83d8f3dc906d848c40eb1f4ca08604e36d06efc6b72de0427911a185f705278ce95
|
7
|
+
data.tar.gz: 7e42e43664d2329d25f47999bddf7e0c28cbd2ccd36c69ce81e4e94a4e6894a5c905bc5f9ddce41b0ce6770f5f116c369b48c6d2622135e8b2e32221e7d1a6d5
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,34 @@
|
|
1
1
|
## [Planned]
|
2
2
|
|
3
|
+
- Data Abstraction Layer / Object Relational Model
|
4
|
+
- Event Model
|
5
|
+
- Plugin / Extension system
|
6
|
+
|
7
|
+
- Frontend Extensions
|
8
|
+
- Tailwind CSS (tailwind-cli)
|
9
|
+
|
10
|
+
- Persistence Extensions
|
11
|
+
- Memory (default)
|
12
|
+
- Disk (file)
|
13
|
+
- Databases (SQLite, PostgreSQL)
|
14
|
+
|
15
|
+
## [Unreleased]
|
16
|
+
|
17
|
+
## [0.3.1] - 24 February 2024
|
18
|
+
|
19
|
+
- Production Mode
|
20
|
+
- `porous build production`
|
21
|
+
- `porous server`
|
22
|
+
- Needs `ssl/cert.pem` and `ssl/key.pem`
|
23
|
+
- Binds on :80 and :443
|
24
|
+
- Development Mode
|
25
|
+
- `porous dev`
|
26
|
+
- Binds on :9292
|
27
|
+
- Serves favicon from `static/favicon.svg`
|
28
|
+
|
29
|
+
## [0.3.0] - 22 February 2024
|
30
|
+
|
3
31
|
- WebSockets support
|
4
|
-
- Production mode
|
5
32
|
|
6
33
|
## [0.2.0] - 18 February 2024
|
7
34
|
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# 🧽 Porous
|
2
2
|
|
3
|
-
Porous is a web engine that uses isomorphic Ruby components to build a Progressive Web App. Its use is analogous to a web framework, but the approach is entirely different. You write only
|
3
|
+
Porous is a web engine that uses isomorphic Ruby components to build a Progressive Web App. Its use is analogous to a web framework, but the approach is entirely different. You write *only* the code that is *unique to your application* and the engine takes care of the rest!
|
4
4
|
|
5
|
-
This project is a work-in-progress and is not yet even in the Proof of Concept phase. However, if you are interested in a full-stack, everything included solution, that only requires you to use one language (that is arguably easy and enjoyable to write) then feel free to follow this project.
|
5
|
+
This project is a **work-in-progress** and is not yet even in the Proof of Concept phase. However, if you are interested in a full-stack, everything included solution, that only requires you to use one language (that is arguably easy and enjoyable to write) then feel free to follow this project.
|
6
6
|
|
7
7
|
The closest thing to this I could find was [Volt](https://github.com/voltrb/volt) or [Silica](https://github.com/youchan/silica), neither of which are active or match the overall development flow I'm looking for.
|
8
8
|
|
@@ -12,7 +12,7 @@ The closest thing to this I could find was [Volt](https://github.com/voltrb/volt
|
|
12
12
|
- 🖥️ Server-side rendering (server responds with the entire initial page populated for SEO)
|
13
13
|
- 💻 Client-side rendering (application bundle is served and interactions and subsequent pages are rendered client-side)
|
14
14
|
- 🌄 Serves static files (from `static` folder)
|
15
|
-
- 🔥 Hot reloading (via
|
15
|
+
- 🔥 Hot reloading (via WebSocket push and browser refresh)
|
16
16
|
|
17
17
|
## Design
|
18
18
|
|
@@ -42,21 +42,21 @@ Porous is not a framework. You don't build an application with it as a dependenc
|
|
42
42
|
|
43
43
|
## Usage
|
44
44
|
|
45
|
-
Porous is still pre-alpha and so is not ready for usage yet, but the general idea is that you would define your application's entities, pages, components and events in Ruby scripts structured in a specific way. Then you would simply run `porous` while pointing it to that folder and it will spin up a Rack-compatible web server for you to use.
|
45
|
+
Porous is still pre-alpha and so is not ready for usage yet, but the general idea is that you would define your application's entities, pages, components and events in Ruby scripts structured in a specific way. Then you would simply run `porous server` while pointing it to that folder and it will spin up a Rack-compatible web server for you to use.
|
46
46
|
|
47
47
|
> ⚠️ Expect any and all APIs to change radically until version 1.0! Hence why it won't be documented or properly tested until things settle to a more stable state.
|
48
48
|
|
49
|
-
To start a new Porous project simply `gem install porous` using whichever Ruby environment you want to use (Ruby 3.0+). Then change to that directory and run:
|
49
|
+
To start a new Porous project simply `gem install porous` using whichever Ruby environment you want to use (Ruby 3.0+) and then `porous new` with your project name. Then change to that directory and run:
|
50
50
|
|
51
|
-
$ porous
|
51
|
+
$ porous dev
|
52
52
|
|
53
|
-
By default Porous will run at `localhost:9292`. Now you can edit `pages/home.rb` or add more pages. Files you modify will be hot-reloaded so you can simply open the page in your browser and edit the file.
|
53
|
+
By default Porous will run at `localhost:9292`. Now you can edit `pages/home.rb` or add more pages. Files you modify will be hot-reloaded, so you can simply open the page in your browser and edit the file.
|
54
54
|
|
55
55
|
### Running examples
|
56
56
|
|
57
|
-
To test out
|
57
|
+
To test out an example application using Porous you can clone the [Porous website](https://github.com/exastencil/porous.dev) and in that directory:
|
58
58
|
|
59
|
-
$ porous
|
59
|
+
$ porous dev
|
60
60
|
|
61
61
|
## Development
|
62
62
|
|
data/lib/porous/application.rb
CHANGED
@@ -18,9 +18,9 @@ module Porous
|
|
18
18
|
end
|
19
19
|
meta name: 'description', content: props[:description] if props[:description]
|
20
20
|
|
21
|
-
script src: '/static/dist/application.js'
|
22
|
-
script src: '/static/dist/reload.js'
|
21
|
+
script src: '/static/dist/application.js', id: 'application'
|
23
22
|
script src: 'https://cdn.tailwindcss.com'
|
23
|
+
link rel: 'icon', href: '/static/favicon.svg'
|
24
24
|
end
|
25
25
|
|
26
26
|
body class: 'bg-gray-50 dark:bg-gray-900' do
|
data/lib/porous/cli/build.rb
CHANGED
@@ -12,47 +12,10 @@ module Porous
|
|
12
12
|
true
|
13
13
|
end
|
14
14
|
|
15
|
-
desc 'build', 'Build static assets'
|
16
|
-
def build
|
15
|
+
desc 'build ENV', 'Build static assets for environment (default: development)'
|
16
|
+
def build(env = :development)
|
17
17
|
empty_directory 'static/dist', verbose: false, force: options[:force]
|
18
|
-
|
19
|
-
live_reload
|
18
|
+
Porous::Server::Builder.new(env.to_sym).build
|
20
19
|
end
|
21
|
-
|
22
|
-
# rubocop:disable Metrics/BlockLength
|
23
|
-
no_commands do
|
24
|
-
def transpile
|
25
|
-
components = Dir.glob(File.join('{components,pages}', '**', '*.rb')).map do |relative_path|
|
26
|
-
"require '#{relative_path}'"
|
27
|
-
end
|
28
|
-
build_string = "require 'porous'; #{components.join ";"}".gsub '.rb', ''
|
29
|
-
builder = Opal::Builder.new
|
30
|
-
builder.build_str build_string, '(inline)'
|
31
|
-
File.binwrite "#{Dir.pwd}/static/dist/application.js", builder.to_s
|
32
|
-
end
|
33
|
-
|
34
|
-
# rubocop:disable Metrics/MethodLength
|
35
|
-
def live_reload
|
36
|
-
timestamp = Time.now.to_i.to_s
|
37
|
-
File.write "#{Dir.pwd}/static/dist/timestamp", timestamp
|
38
|
-
builder = Opal::Builder.new
|
39
|
-
script = <<-BROWSER
|
40
|
-
$document.ready do
|
41
|
-
every 0.1 do
|
42
|
-
Browser::HTTP.get('/static/dist/timestamp').then do |response|
|
43
|
-
return unless response.success?
|
44
|
-
timestamp = response.text.to_i
|
45
|
-
TIMESTAMP ||= timestamp
|
46
|
-
$document.location.reload if TIMESTAMP < timestamp
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
BROWSER
|
51
|
-
builder.build_str script, '(inline)'
|
52
|
-
File.binwrite "#{Dir.pwd}/static/dist/reload.js", builder.to_s
|
53
|
-
end
|
54
|
-
# rubocop:enable Metrics/MethodLength
|
55
|
-
end
|
56
|
-
# rubocop:enable Metrics/BlockLength
|
57
20
|
end
|
58
21
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Porous
|
4
|
+
class CLI < Thor
|
5
|
+
check_unknown_options!
|
6
|
+
|
7
|
+
namespace :dev
|
8
|
+
|
9
|
+
desc 'dev', 'Starts a Porous development server'
|
10
|
+
def dev # rubocop:todo Metrics/MethodLength, Metrics/AbcSize
|
11
|
+
empty_directory 'static/dist', verbose: false, force: options[:force]
|
12
|
+
|
13
|
+
Agoo::Log.configure(
|
14
|
+
dir: '',
|
15
|
+
console: true,
|
16
|
+
classic: true,
|
17
|
+
colorize: true,
|
18
|
+
states: {
|
19
|
+
INFO: true,
|
20
|
+
DEBUG: false,
|
21
|
+
connect: false,
|
22
|
+
request: false,
|
23
|
+
response: false,
|
24
|
+
eval: true,
|
25
|
+
push: true
|
26
|
+
}
|
27
|
+
)
|
28
|
+
|
29
|
+
Agoo::Server.init 9292, Dir.pwd, thread_count: 1
|
30
|
+
Agoo::Server.use Rack::ContentLength
|
31
|
+
Agoo::Server.use Rack::Static, urls: ['/static']
|
32
|
+
Agoo::Server.use Rack::ShowExceptions
|
33
|
+
|
34
|
+
# Socket Communication
|
35
|
+
$socket ||= Porous::Server::Socket.new
|
36
|
+
Agoo::Server.handle nil, '/connect', Porous::Server::Connect.new
|
37
|
+
# Server-Side Rendering
|
38
|
+
Agoo::Server.handle nil, '**', Porous::Server::Application.new
|
39
|
+
Agoo::Server.start
|
40
|
+
# Live Reload Builder
|
41
|
+
Server::Builder.new.build.start
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/porous/cli/server.rb
CHANGED
@@ -6,42 +6,42 @@ module Porous
|
|
6
6
|
|
7
7
|
namespace :server
|
8
8
|
|
9
|
-
desc 'server [OPTIONS]', 'Starts Porous server'
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
desc 'server [OPTIONS]', 'Starts Porous server in production mode'
|
10
|
+
def server # rubocop:todo Metrics/MethodLength
|
11
|
+
Agoo::Log.configure(dir: '',
|
12
|
+
console: true,
|
13
|
+
classic: true,
|
14
|
+
colorize: true,
|
15
|
+
states: {
|
16
|
+
INFO: true,
|
17
|
+
DEBUG: false,
|
18
|
+
connect: true,
|
19
|
+
request: true,
|
20
|
+
response: false,
|
21
|
+
eval: false,
|
22
|
+
push: false
|
23
|
+
})
|
15
24
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
25
|
+
Agoo::Server.init(
|
26
|
+
80, '.',
|
27
|
+
thread_count: 0,
|
28
|
+
ssl_cert: 'ssl/cert.pem',
|
29
|
+
ssl_key: 'ssl/key.pem',
|
30
|
+
bind: [
|
31
|
+
'http://127.0.0.1:80',
|
32
|
+
'https://127.0.0.1:443'
|
33
|
+
]
|
34
|
+
)
|
35
|
+
Agoo::Server.use Rack::ContentLength
|
36
|
+
Agoo::Server.use Rack::Static, urls: ['/static']
|
21
37
|
|
22
|
-
|
38
|
+
# Socket Communication
|
39
|
+
$socket ||= Porous::Server::Socket.new
|
40
|
+
Agoo::Server.handle nil, '/connect', Porous::Server::Connect.new
|
41
|
+
# Server-Side Rendering
|
42
|
+
Agoo::Server.handle nil, '**', Porous::Server::Application.new
|
23
43
|
|
24
|
-
|
25
|
-
MONITORING.each { |path| FileUtils.mkdir_p path }
|
26
|
-
build
|
27
|
-
start_live_reload
|
28
|
-
Rackup::Server.start environment: 'none', app: Porous::Server.new
|
29
|
-
end
|
30
|
-
|
31
|
-
no_commands do
|
32
|
-
def start_live_reload
|
33
|
-
opts = { only: /\.rb$/, relative: true }
|
34
|
-
@listener = Listen.to(*MONITORING, opts) do |modified, added, _removed|
|
35
|
-
# Load for server
|
36
|
-
(modified + added).each do |file|
|
37
|
-
load File.expand_path("#{Dir.pwd}/#{file}")
|
38
|
-
end
|
39
|
-
# Rebuild for browser
|
40
|
-
Thread.new { build }
|
41
|
-
end
|
42
|
-
@listener.start
|
43
|
-
at_exit { @listener.stop }
|
44
|
-
end
|
44
|
+
Agoo::Server.start
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -1,7 +1,21 @@
|
|
1
1
|
# <%= config[:project_name] %>
|
2
2
|
|
3
|
+
## Development
|
4
|
+
|
3
5
|
```sh
|
4
|
-
$ porous
|
6
|
+
$ porous dev
|
5
7
|
```
|
6
8
|
|
7
|
-
Go to [http://localhost:
|
9
|
+
Go to [http://localhost:9292/](http://localhost:9292/)
|
10
|
+
|
11
|
+
## Production
|
12
|
+
|
13
|
+
Place your SSL certificate in `ssl`:
|
14
|
+
|
15
|
+
- `ssl/cert.pem`
|
16
|
+
- `ssl/key.pem`
|
17
|
+
|
18
|
+
```sh
|
19
|
+
$ porous build production
|
20
|
+
$ porous server
|
21
|
+
```
|
@@ -32,11 +32,7 @@ class Home
|
|
32
32
|
end
|
33
33
|
a href: 'https://github.com/exastencil/porous', target: '_blank', rel: 'noopener',
|
34
34
|
class: 'flex items-center space-x-2 text-gray-500 dark:text-gray-400' do
|
35
|
-
|
36
|
-
xmlns: 'http://www.w3.org/2000/svg' do
|
37
|
-
title 'GitHub'
|
38
|
-
path d: 'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'
|
39
|
-
end
|
35
|
+
img class: 'w-8 h-8 text-gray-500', src: '/static/github.svg'
|
40
36
|
span 'View on GitHub'
|
41
37
|
end
|
42
38
|
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg role="img" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<title>GitHub logo</title>
|
3
|
+
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"></path>
|
4
|
+
</svg>
|
data/lib/porous/cli.rb
CHANGED
@@ -3,10 +3,15 @@
|
|
3
3
|
require 'thor'
|
4
4
|
|
5
5
|
require 'porous'
|
6
|
+
require 'porous/server/builder'
|
7
|
+
require 'porous/server/socket'
|
8
|
+
require 'porous/server/connect'
|
9
|
+
require 'porous/server/application'
|
6
10
|
|
7
11
|
require 'rack'
|
8
12
|
require 'rackup/server'
|
9
13
|
|
10
14
|
require 'porous/cli/build'
|
15
|
+
require 'porous/cli/dev'
|
11
16
|
require 'porous/cli/new'
|
12
17
|
require 'porous/cli/server'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Porous
|
4
|
+
module Server
|
5
|
+
class Application
|
6
|
+
MONITORING = %w[components pages].freeze
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
router = Porous::Router.new path: env['PATH_INFO'], query: env['QUERY_STRING']
|
10
|
+
route = router.find_route
|
11
|
+
page = route[:component].new(route[:params])
|
12
|
+
|
13
|
+
[200, { 'content-type' => 'text/html' }, [
|
14
|
+
Porous::Application.new(
|
15
|
+
title: page.page_title,
|
16
|
+
description: page.page_description,
|
17
|
+
path: env['PATH_INFO'],
|
18
|
+
query: env['QUERY_STRING']
|
19
|
+
).to_s
|
20
|
+
]]
|
21
|
+
rescue Porous::InvalidRouteError => e
|
22
|
+
[404, { 'content-type' => 'text/plain' }, ["404 Page not found\n", e.message]]
|
23
|
+
rescue Porous::Error => e
|
24
|
+
[500, { 'content-type' => 'text/plain' }, ["500 Internal Server Error\n", e.message]]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'opal/builder_scheduler/sequential'
|
4
|
+
|
5
|
+
module Porous
|
6
|
+
module Server
|
7
|
+
class Builder
|
8
|
+
def initialize(environment = :development)
|
9
|
+
@environment = environment
|
10
|
+
@build_queue = Queue.new
|
11
|
+
@last_build = nil
|
12
|
+
@latest_change = Dir.glob(File.join('**', '*.rb')).map { |f| File.mtime f }.max
|
13
|
+
end
|
14
|
+
|
15
|
+
def build
|
16
|
+
components = Dir.glob(File.join('**', '*.rb')).map do |relative_path|
|
17
|
+
modified = File.mtime relative_path
|
18
|
+
@latest_change = modified if modified > @latest_change
|
19
|
+
"require '#{relative_path}'"
|
20
|
+
end
|
21
|
+
build_string = "require 'porous'; #{components.join ";"}; ".gsub '.rb', ''
|
22
|
+
build_string << inject_socket_connection
|
23
|
+
builder = Opal::Builder.new scheduler: Opal::BuilderScheduler::Sequential, cache: false
|
24
|
+
builder.build_str build_string, '(inline)'
|
25
|
+
File.binwrite "#{Dir.pwd}/static/dist/application.js", builder.to_s
|
26
|
+
@last_build = Time.now
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
# rubocop:disable Metrics/AbcSize
|
31
|
+
def start
|
32
|
+
loop do
|
33
|
+
sleep 0.25
|
34
|
+
next unless @build_queue.empty?
|
35
|
+
|
36
|
+
modified = Dir.glob(File.join('**', '*.rb')).map { |f| File.mtime f }.max
|
37
|
+
next unless modified > @last_build
|
38
|
+
|
39
|
+
@build_queue.push modified
|
40
|
+
# Load for server
|
41
|
+
Dir.glob(File.join('**', '*.rb')).map { |f| load File.expand_path("#{Dir.pwd}/#{f}") }
|
42
|
+
|
43
|
+
# Rebuild for browser
|
44
|
+
Thread.new { build }.join
|
45
|
+
|
46
|
+
# Notify clients
|
47
|
+
$socket&.public 'build', @last_build.inspect
|
48
|
+
@build_queue.clear
|
49
|
+
end
|
50
|
+
end
|
51
|
+
# rubocop:enable Metrics/AbcSize
|
52
|
+
|
53
|
+
def inject_socket_connection
|
54
|
+
uri = @environment == :production ? 'wss://localhost/connect' : 'ws://localhost:9292/connect'
|
55
|
+
"$connection = '#{uri}'; "
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Porous
|
4
|
+
module Server
|
5
|
+
class Connect
|
6
|
+
# Only used for WebSocket or SSE upgrades.
|
7
|
+
def call(env)
|
8
|
+
if env['rack.upgrade?'].nil?
|
9
|
+
[404, {}, []]
|
10
|
+
else
|
11
|
+
$socket ||= Socket.new
|
12
|
+
env['rack.upgrade'] = $socket
|
13
|
+
[200, {}, []]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Porous
|
4
|
+
module Server
|
5
|
+
class Socket
|
6
|
+
def initialize
|
7
|
+
@clients = []
|
8
|
+
@mutex = Mutex.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_open(client)
|
12
|
+
@mutex.synchronize do
|
13
|
+
@clients << client
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_close(client)
|
18
|
+
@mutex.synchronize do
|
19
|
+
@clients.delete(client)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_drained(_client); end
|
24
|
+
|
25
|
+
def on_message(client, data)
|
26
|
+
client.write("Handler says #{data}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def public(channel, message)
|
30
|
+
output = "#{channel}|#{message}"
|
31
|
+
@mutex.synchronize do
|
32
|
+
@clients.each do |c|
|
33
|
+
c.write output
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/porous/version.rb
CHANGED
data/lib/porous.rb
CHANGED
@@ -7,7 +7,7 @@ require 'opal-virtual-dom'
|
|
7
7
|
Opal.append_path File.expand_path('../opal', __dir__)
|
8
8
|
Opal.append_path File.expand_path(Dir.pwd)
|
9
9
|
|
10
|
-
require '
|
10
|
+
require 'agoo'
|
11
11
|
|
12
12
|
require 'porous/version'
|
13
13
|
|
@@ -27,7 +27,6 @@ Dir.glob(File.join('{components,pages}', '**', '*.rb')).each do |relative_path|
|
|
27
27
|
end
|
28
28
|
|
29
29
|
require 'porous/application'
|
30
|
-
require 'porous/server' unless RUBY_ENGINE == 'opal'
|
31
30
|
|
32
31
|
module Porous
|
33
32
|
class Error < StandardError; end
|
data/lib/virtual_dom/dom.rb
CHANGED
@@ -11,8 +11,9 @@ module VirtualDOM
|
|
11
11
|
small source span strong style sub summary sup table tbody td textarea tfoot th
|
12
12
|
thead time title tr track u ul var video wbr].freeze
|
13
13
|
|
14
|
-
SVG_TAGS = %w[
|
15
|
-
|
14
|
+
SVG_TAGS = %w[animate animateMotion animateTransform circle clipPath defs desc ellipse filter
|
15
|
+
foreignObject g image line linearGradient marker mask metadata mpath path pattern
|
16
|
+
polygon polyline radialGradient rect set stop svg switch symbol textPath tspan use view].freeze
|
16
17
|
(HTML_TAGS + SVG_TAGS).each do |tag|
|
17
18
|
define_method tag do |params = {}, &block|
|
18
19
|
if params.is_a?(String)
|
data/opal/porous/injection.rb
CHANGED
data/opal/porous.rb
CHANGED
@@ -11,15 +11,6 @@ require 'console'
|
|
11
11
|
require 'virtual_dom'
|
12
12
|
require 'virtual_dom/support/browser'
|
13
13
|
|
14
|
-
VirtualDOM::DOM::HTML_TAGS = %w[a abbr address area article aside audio b base bdi bdo big blockquote body br
|
15
|
-
button canvas caption cite code col colgroup data datalist dd del details dfn
|
16
|
-
dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
|
17
|
-
h6 head header hr html i iframe img input ins kbd keygen label legend li link
|
18
|
-
main map mark menu menuitem meta meter nav noscript object ol optgroup option
|
19
|
-
output p param picture pre progress q rp rt ruby s samp script section select
|
20
|
-
small source span strong style sub summary sup table tbody td textarea tfoot th
|
21
|
-
thead time title tr track u ul var video wbr svg path].freeze
|
22
|
-
|
23
14
|
require 'porous/injection'
|
24
15
|
require 'porous/component/class_methods'
|
25
16
|
require 'porous/component/render'
|
@@ -38,4 +29,19 @@ end
|
|
38
29
|
|
39
30
|
$document.ready do
|
40
31
|
Porous::Application.mount_to($document.body)
|
32
|
+
Browser::Socket.new $connection do
|
33
|
+
on :open do |_e|
|
34
|
+
$console.info 'Connected to server!'
|
35
|
+
end
|
36
|
+
|
37
|
+
on :message do |e|
|
38
|
+
channel, content = e.data.split '|'
|
39
|
+
case channel
|
40
|
+
when 'build'
|
41
|
+
$document.location.reload unless content == 'started'
|
42
|
+
else
|
43
|
+
$console.log e.data
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
41
47
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: porous
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Exa Stencil
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: agoo
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.15'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2.15'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: opal-browser
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,11 +102,13 @@ files:
|
|
102
102
|
- lib/porous/application.rb
|
103
103
|
- lib/porous/cli.rb
|
104
104
|
- lib/porous/cli/build.rb
|
105
|
+
- lib/porous/cli/dev.rb
|
105
106
|
- lib/porous/cli/new.rb
|
106
107
|
- lib/porous/cli/server.rb
|
107
108
|
- lib/porous/cli/template/.gitignore.tt
|
108
109
|
- lib/porous/cli/template/README.md.tt
|
109
110
|
- lib/porous/cli/template/pages/home.rb
|
111
|
+
- lib/porous/cli/template/static/github.svg
|
110
112
|
- lib/porous/cli/template/static/hero.png
|
111
113
|
- lib/porous/component.rb
|
112
114
|
- lib/porous/component/class_methods.rb
|
@@ -117,7 +119,10 @@ files:
|
|
117
119
|
- lib/porous/page.rb
|
118
120
|
- lib/porous/router.rb
|
119
121
|
- lib/porous/routes.rb
|
120
|
-
- lib/porous/server.rb
|
122
|
+
- lib/porous/server/application.rb
|
123
|
+
- lib/porous/server/builder.rb
|
124
|
+
- lib/porous/server/connect.rb
|
125
|
+
- lib/porous/server/socket.rb
|
121
126
|
- lib/porous/version.rb
|
122
127
|
- lib/virtual_dom/dom.rb
|
123
128
|
- lib/virtual_dom/virtual_node.rb
|
data/lib/porous/server.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Porous
|
4
|
-
class Server
|
5
|
-
def initialize(*_args)
|
6
|
-
setup_rack_app
|
7
|
-
end
|
8
|
-
|
9
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
10
|
-
def setup_rack_app
|
11
|
-
@rack = Rack::Builder.new do
|
12
|
-
use Rack::ContentLength
|
13
|
-
use Rack::Static, urls: ['/static']
|
14
|
-
use Rack::CommonLogger
|
15
|
-
use Rack::ShowExceptions
|
16
|
-
use Rack::Lint
|
17
|
-
use Rack::TempfileReaper
|
18
|
-
|
19
|
-
run do |env|
|
20
|
-
router = Porous::Router.new path: env['PATH_INFO'], query: env['QUERY_STRING']
|
21
|
-
route = router.find_route
|
22
|
-
page = route[:component].new(route[:params])
|
23
|
-
|
24
|
-
[200, { 'content-type' => 'text/html' }, [
|
25
|
-
Porous::Application.new(
|
26
|
-
title: page.page_title,
|
27
|
-
description: page.page_description,
|
28
|
-
path: env['PATH_INFO'],
|
29
|
-
query: env['QUERY_STRING']
|
30
|
-
).to_s
|
31
|
-
]]
|
32
|
-
rescue Porous::InvalidRouteError => e
|
33
|
-
[404, { 'content-type' => 'text/plain' }, ["404 Page not found\n", e.message]]
|
34
|
-
rescue Porous::Error => e
|
35
|
-
[500, { 'content-type' => 'text/plain' }, ["500 Internal Server Error\n", e.message]]
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
40
|
-
|
41
|
-
def call(*args)
|
42
|
-
@rack.call(*args)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|