porous 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +17 -1
- data/CHANGELOG.md +4 -0
- data/README.md +2 -2
- data/Rakefile +3 -3
- data/exe/porous +2 -0
- data/lib/porous/cli/build.rb +2 -0
- data/lib/porous/cli/new.rb +2 -0
- data/lib/porous/cli/server.rb +3 -3
- data/lib/porous/cli/template/pages/home.rb +8 -4
- data/lib/porous/cli.rb +2 -0
- data/lib/porous/component/class_methods.rb +2 -0
- data/lib/porous/component/render.rb +3 -2
- data/lib/porous/component/virtual.rb +2 -0
- data/lib/porous/component.rb +2 -1
- data/lib/porous/injection.rb +8 -6
- data/lib/porous/page.rb +3 -1
- data/lib/porous/router.rb +20 -11
- data/lib/porous/routes.rb +12 -4
- data/lib/porous/server.rb +52 -27
- data/lib/porous/version.rb +1 -1
- data/lib/porous.rb +3 -1
- data/lib/virtual_dom/dom.rb +12 -8
- data/lib/virtual_dom/virtual_node.rb +3 -1
- data/opal/porous/browser.rb +2 -0
- data/opal/porous/component/class_methods.rb +2 -0
- data/opal/porous/component/render.rb +26 -23
- data/opal/porous/component/virtual.rb +2 -0
- data/opal/porous/component.rb +2 -0
- data/opal/porous/injection.rb +8 -8
- data/opal/porous.rb +2 -0
- metadata +12 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b55c1eaf688f84af5c848e212ab0f5686ca6d6f270a0ef68d35846824af0d716
|
4
|
+
data.tar.gz: 4ca350f60c41896911dba97cd62ec05437ede55ae11d0a6c1fd0e3a68a09281e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a434473bf2ee80768ed88e729ecec2287af5a2596521e4fdb1857e82cff861eaeeba84ac9be5b6afba41340f6de543a7c57e1382e4a6d6e19e85960f0e6ea0c6
|
7
|
+
data.tar.gz: 5ddf2319739891025fac39dfc34d50a379f2403139f6171d95d2488eabf621b22dacad1266c9151af35242dff02210aef15ccc350d3b9f1c782c0c2d585f7a8b
|
data/.rubocop.yml
CHANGED
@@ -1,13 +1,29 @@
|
|
1
1
|
AllCops:
|
2
2
|
TargetRubyVersion: 3.0
|
3
|
+
NewCops: enable
|
3
4
|
|
4
5
|
Style/StringLiterals:
|
5
6
|
Enabled: true
|
6
|
-
EnforcedStyle:
|
7
|
+
EnforcedStyle: single_quotes
|
7
8
|
|
8
9
|
Style/StringLiteralsInInterpolation:
|
9
10
|
Enabled: true
|
10
11
|
EnforcedStyle: double_quotes
|
11
12
|
|
13
|
+
Style/Documentation:
|
14
|
+
Enabled: false
|
15
|
+
|
12
16
|
Layout/LineLength:
|
13
17
|
Max: 120
|
18
|
+
|
19
|
+
Metrics/BlockLength:
|
20
|
+
AllowedMethods:
|
21
|
+
- render
|
22
|
+
Metrics/MethodLength:
|
23
|
+
Max: 15
|
24
|
+
AllowedMethods:
|
25
|
+
- render
|
26
|
+
|
27
|
+
require:
|
28
|
+
- rubocop-rake
|
29
|
+
- rubocop-rspec
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -40,7 +40,7 @@ To start a new Porous project simply `gem install porous` using whichever Ruby e
|
|
40
40
|
|
41
41
|
$ porous server
|
42
42
|
|
43
|
-
By default Porous will run at `loclahost:9292`. Now you can edit `pages/home.rb` or add more pages.
|
43
|
+
By default Porous will run at `loclahost:9292`. Now you can edit `pages/home.rb` or add more pages. Files you modify will be reloaded so you can simply refresh the page in your browser. Hot-reloading will be coming later once WebSockets support is implemented.
|
44
44
|
|
45
45
|
### Running examples
|
46
46
|
|
@@ -66,4 +66,4 @@ Everyone interacting in the Porous project's codebases, issue trackers, chat roo
|
|
66
66
|
|
67
67
|
## Acknowledgements
|
68
68
|
|
69
|
-
|
69
|
+
I'd like to thank Michał Kalbarczyk ([fazibear](https://github.com/fazibear)) for his work done on [Inesita](https://github.com/inesita-rb/inesita) and his [VirtualDOM wrapper](https://github.com/fazibear/opal-virtual-dom) which served as the starting point for my implementation of Porous.
|
data/Rakefile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
5
|
|
6
6
|
RSpec::Core::RakeTask.new(:spec)
|
7
7
|
|
8
|
-
require
|
8
|
+
require 'rubocop/rake_task'
|
9
9
|
|
10
10
|
RuboCop::RakeTask.new
|
11
11
|
|
data/exe/porous
CHANGED
data/lib/porous/cli/build.rb
CHANGED
data/lib/porous/cli/new.rb
CHANGED
data/lib/porous/cli/server.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Porous
|
2
4
|
class CLI < Thor
|
3
5
|
check_unknown_options!
|
@@ -18,9 +20,7 @@ module Porous
|
|
18
20
|
desc: 'The host address Porous will bind to'
|
19
21
|
|
20
22
|
def server
|
21
|
-
Rackup::Server.start environment: 'development', builder:
|
22
|
-
run Porous::Server.new
|
23
|
-
BUILDER
|
23
|
+
Rackup::Server.start environment: 'development', builder: 'run Porous::Server.new'
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -1,15 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Home
|
2
4
|
include Porous::Page
|
3
5
|
include Porous::Component
|
4
6
|
|
5
7
|
def route = '/'
|
6
8
|
|
9
|
+
# rubocop:disable Metrics, Layout/LineLength
|
7
10
|
def render
|
8
11
|
div class: 'container p-8 mx-auto lg:h-full xl:px-0 flex flex-wrap' do
|
9
12
|
div class: 'flex items-center w-full lg:w-1/2' do
|
10
13
|
div class: 'max-w-2xl mb-8' do
|
11
14
|
h1 class: 'text-4xl font-bold leading-snug tracking-tight text-gray-800 lg:text-4xl lg:leading-tight xl:text-6xl xl:leading-tight dark:text-white' do
|
12
|
-
span class:
|
15
|
+
span class: 'bg-gradient-to-br from-pink-500 to-violet-500 bg-clip-text text-transparent box-decoration-clone' do
|
13
16
|
text 'Welcome to Porous!'
|
14
17
|
end
|
15
18
|
end
|
@@ -19,10 +22,10 @@ class Home
|
|
19
22
|
|
20
23
|
div class: 'flex flex-col items-start space-y-3 sm:space-x-4 sm:space-y-0 sm:items-center sm:flex-row' do
|
21
24
|
a href: 'https://github.com/exastencil/porous', target: '_blank', rel: 'noopener',
|
22
|
-
class:
|
25
|
+
class: 'group relative inline-flex h-12 items-center justify-center overflow-hidden rounded-md bg-indigo-600 px-6 font-medium text-neutral-200 transition hover:scale-110' do
|
23
26
|
span 'Get Started'
|
24
|
-
div class:
|
25
|
-
div class:
|
27
|
+
div class: 'absolute inset-0 flex h-full w-full justify-center [transform:skew(-12deg)_translateX(-100%)] group-hover:duration-1000 group-hover:[transform:skew(-12deg)_translateX(100%)]' do
|
28
|
+
div class: 'relative h-full w-8 bg-white/20'
|
26
29
|
end
|
27
30
|
end
|
28
31
|
a href: 'https://github.com/exastencil/porous', target: '_blank', rel: 'noopener',
|
@@ -45,4 +48,5 @@ class Home
|
|
45
48
|
end
|
46
49
|
end
|
47
50
|
end
|
51
|
+
# rubocop:enable Metrics, Layout/LineLength
|
48
52
|
end
|
data/lib/porous/cli.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Porous
|
2
4
|
module Component
|
3
5
|
module Render
|
@@ -5,8 +7,7 @@ module Porous
|
|
5
7
|
raise Error, "Implement #render in #{self.class} component"
|
6
8
|
end
|
7
9
|
|
8
|
-
def before_render
|
9
|
-
end
|
10
|
+
def before_render; end
|
10
11
|
|
11
12
|
def render_virtual_dom
|
12
13
|
before_render
|
data/lib/porous/component.rb
CHANGED
data/lib/porous/injection.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Porous
|
2
4
|
module Injection
|
3
5
|
def init; end
|
@@ -21,15 +23,15 @@ module Porous
|
|
21
23
|
def init_injections
|
22
24
|
@injections ||= {}
|
23
25
|
self.class.injections.each do |name, clazz|
|
24
|
-
|
25
|
-
@injections[name] = clazz
|
26
|
-
.new
|
27
|
-
.with_root_component(@root_component)
|
28
|
-
else
|
26
|
+
unless clazz.included_modules.include?(Porous::Injection)
|
29
27
|
raise Error, "Invalid #{clazz} class, should mixin Porous::Injection"
|
30
28
|
end
|
29
|
+
|
30
|
+
@injections[name] = clazz
|
31
|
+
.new
|
32
|
+
.with_root_component(@root_component)
|
31
33
|
end
|
32
|
-
@injections.
|
34
|
+
@injections.each_value do |instance|
|
33
35
|
instance.inject
|
34
36
|
instance.init
|
35
37
|
end
|
data/lib/porous/page.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Porous
|
2
4
|
module Page
|
3
5
|
# Define the route according to the Router::Routes rules
|
4
6
|
def route!
|
5
7
|
path = route
|
6
|
-
@
|
8
|
+
@route ||= Routes.new.tap do |routes|
|
7
9
|
routes.route path, to: self.class
|
8
10
|
end
|
9
11
|
end
|
data/lib/porous/router.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Porous
|
2
|
-
|
4
|
+
class Router
|
3
5
|
include Porous::Component
|
4
6
|
|
5
7
|
attr_reader :params
|
@@ -23,6 +25,10 @@ module Porous
|
|
23
25
|
parse_url_params
|
24
26
|
end
|
25
27
|
|
28
|
+
def routes
|
29
|
+
@routes.routes
|
30
|
+
end
|
31
|
+
|
26
32
|
def self.included(base)
|
27
33
|
base.extend(Porous::Component::ClassMethods)
|
28
34
|
end
|
@@ -34,7 +40,8 @@ module Porous
|
|
34
40
|
|
35
41
|
return @route = route
|
36
42
|
end
|
37
|
-
|
43
|
+
available_routes = @routes.routes.map { |r| " #{r[:path]} => #{r[:component]}" }.join
|
44
|
+
raise InvalidRouteError, "Unknown route for: #{path}\n\nAvailable routes:\n\n#{available_routes}"
|
38
45
|
end
|
39
46
|
|
40
47
|
def find_component(route)
|
@@ -50,9 +57,9 @@ module Porous
|
|
50
57
|
def call_on_enter_callback(route)
|
51
58
|
return unless route[:on_enter]
|
52
59
|
|
53
|
-
|
54
|
-
|
55
|
-
|
60
|
+
return unless route[:on_enter].respond_to?(:call)
|
61
|
+
|
62
|
+
route[:on_enter].call
|
56
63
|
end
|
57
64
|
|
58
65
|
def go_to(path)
|
@@ -66,14 +73,16 @@ module Porous
|
|
66
73
|
|
67
74
|
def parse_url_params
|
68
75
|
@params = component_url_params
|
69
|
-
query
|
76
|
+
return if query.empty?
|
77
|
+
|
78
|
+
query[1..].split('&').each do |param|
|
70
79
|
key, value = param.split('=')
|
71
80
|
@params[key] = value
|
72
|
-
end
|
81
|
+
end
|
73
82
|
end
|
74
83
|
|
75
84
|
def component_url_params
|
76
|
-
|
85
|
+
@route[:params].zip(path.match(@route[:regex])[1..]).to_h
|
77
86
|
end
|
78
87
|
|
79
88
|
def url_for(name, params = nil)
|
@@ -104,9 +113,9 @@ module Porous
|
|
104
113
|
|
105
114
|
def url_with_params(route, params)
|
106
115
|
path = route[:path]
|
107
|
-
params
|
108
|
-
path = path.gsub(":#{key}",
|
109
|
-
end
|
116
|
+
params&.each do |key, value|
|
117
|
+
path = path.gsub(":#{key}", value.to_s)
|
118
|
+
end
|
110
119
|
path
|
111
120
|
end
|
112
121
|
end
|
data/lib/porous/routes.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Porous
|
2
4
|
class Routes
|
3
5
|
attr_reader :routes
|
@@ -7,8 +9,9 @@ module Porous
|
|
7
9
|
@routes = []
|
8
10
|
end
|
9
11
|
|
12
|
+
# rubocop:disable Metrics/AbcSize
|
10
13
|
def route(*params, &block)
|
11
|
-
path = params.first.gsub(
|
14
|
+
path = params.first.gsub(%r{^/}, '')
|
12
15
|
path = @parent ? "#{@parent}/#{path}" : "/#{path}"
|
13
16
|
|
14
17
|
add_subroutes(path, &block) if block_given?
|
@@ -19,12 +22,15 @@ module Porous
|
|
19
22
|
add_route(params.last[:as], path, params.last[:to], params.last[:props], params.last[:on_enter])
|
20
23
|
end
|
21
24
|
end
|
25
|
+
# rubocop:enable Metrics/AbcSize
|
22
26
|
|
23
27
|
def validate_component(component)
|
24
28
|
raise Error, 'Component not exists' unless component
|
25
29
|
|
30
|
+
return if component.include?(Porous::Component)
|
31
|
+
|
26
32
|
raise Error,
|
27
|
-
"Invalid #{component} class, should mixin Porous::Component"
|
33
|
+
"Invalid #{component} class, should mixin Porous::Component"
|
28
34
|
end
|
29
35
|
|
30
36
|
def add_redirect(path, redirect_to)
|
@@ -51,6 +57,7 @@ module Porous
|
|
51
57
|
@routes += subroutes.routes
|
52
58
|
end
|
53
59
|
|
60
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
54
61
|
def build_params_and_regex(path)
|
55
62
|
regex = ['^']
|
56
63
|
params = []
|
@@ -62,10 +69,10 @@ module Porous
|
|
62
69
|
regex << '\/'
|
63
70
|
case part[0]
|
64
71
|
when ':'
|
65
|
-
params << part[1
|
72
|
+
params << part[1..]
|
66
73
|
regex << '([^\/]+)'
|
67
74
|
when '*'
|
68
|
-
params << part[1
|
75
|
+
params << part[1..]
|
69
76
|
regex << '(.*)'
|
70
77
|
break
|
71
78
|
else
|
@@ -78,6 +85,7 @@ module Porous
|
|
78
85
|
params: params
|
79
86
|
}
|
80
87
|
end
|
88
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
81
89
|
|
82
90
|
def combine(other)
|
83
91
|
@routes += other.routes
|
data/lib/porous/server.rb
CHANGED
@@ -1,41 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Porous
|
2
|
-
class
|
3
|
-
|
4
|
-
include Porous::Router
|
5
|
-
end
|
4
|
+
class Application
|
5
|
+
include Porous::Component
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
head do
|
13
|
-
title do
|
14
|
-
text props[:title]
|
15
|
-
end
|
16
|
-
meta charset: 'UTF-8'
|
17
|
-
meta name: 'viewport', content: 'width=device-width, initial-scale=1.0'
|
18
|
-
script src: 'https://cdn.tailwindcss.com'
|
7
|
+
def render
|
8
|
+
html do
|
9
|
+
head do
|
10
|
+
title do
|
11
|
+
text props[:title]
|
19
12
|
end
|
13
|
+
meta charset: 'UTF-8'
|
14
|
+
meta name: 'viewport', content: 'width=device-width, initial-scale=1.0'
|
15
|
+
script src: 'https://cdn.tailwindcss.com'
|
16
|
+
end
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
body class: 'bg-gray-50 dark:bg-gray-900' do
|
19
|
+
component Porous::Router, props: { path: props[:path], query: props[:query] }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Server
|
26
|
+
MONITORING = %w[components pages].freeze
|
27
|
+
|
28
|
+
def initialize(*_args)
|
29
|
+
@queue = Queue.new
|
30
|
+
start_live_reload
|
31
|
+
setup_rack_app
|
32
|
+
end
|
33
|
+
|
34
|
+
def start_live_reload
|
35
|
+
MONITORING.each { |path| FileUtils.mkdir_p path }
|
36
|
+
opts = {
|
37
|
+
only: /\.rb$/,
|
38
|
+
relative: true
|
39
|
+
}
|
40
|
+
@listener = Listen.to(*MONITORING, opts) do |modified, added, _removed|
|
41
|
+
(modified + added).each do |file|
|
42
|
+
load File.expand_path("#{Dir.pwd}/#{file}")
|
24
43
|
end
|
44
|
+
setup_rack_app
|
25
45
|
end
|
46
|
+
@listener.start
|
47
|
+
at_exit { @listener.stop }
|
26
48
|
end
|
27
49
|
|
28
|
-
def
|
50
|
+
def setup_rack_app
|
29
51
|
@rack = Rack::Builder.new do
|
30
52
|
use Rack::Static, urls: ['/static']
|
31
53
|
run do |env|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
54
|
+
# Build a router to check for a valid route
|
55
|
+
Porous::Router.new path: env['PATH_INFO'], query: env['QUERY_STRING']
|
56
|
+
[200, { 'content-type' => 'text/html' },
|
57
|
+
[Application.new(title: 'Porous Web', path: env['PATH_INFO'], query: env['QUERY_STRING']).to_s]]
|
58
|
+
rescue Porous::InvalidRouteError => e
|
59
|
+
[404, { 'content-type' => 'text/plain' },
|
60
|
+
["404 Page not found\n", e.message]]
|
61
|
+
rescue Porous::Error => e
|
62
|
+
[500, { 'content-type' => 'text/plain' },
|
63
|
+
["500 Internal Server Error\n", e.message]]
|
39
64
|
end
|
40
65
|
end
|
41
66
|
end
|
data/lib/porous/version.rb
CHANGED
data/lib/porous.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'opal'
|
4
4
|
require 'opal-browser'
|
5
|
-
Opal.append_path File.expand_path('
|
5
|
+
Opal.append_path File.expand_path('../opal', __dir__)
|
6
6
|
|
7
7
|
require 'opal-virtual-dom'
|
8
8
|
require 'listen'
|
@@ -27,4 +27,6 @@ end
|
|
27
27
|
require 'porous/server'
|
28
28
|
|
29
29
|
module Porous
|
30
|
+
class Error < StandardError; end
|
31
|
+
class InvalidRouteError < Error; end
|
30
32
|
end
|
data/lib/virtual_dom/dom.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module VirtualDOM
|
2
4
|
module DOM
|
3
|
-
HTML_TAGS = %w
|
5
|
+
HTML_TAGS = %w[a abbr address area article aside audio b base bdi bdo big blockquote body br
|
4
6
|
button canvas caption cite code col colgroup data datalist dd del details dfn
|
5
7
|
dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
|
6
8
|
h6 head header hr html i iframe img input ins kbd keygen label legend li link
|
7
9
|
main map mark menu menuitem meta meter nav noscript object ol optgroup option
|
8
10
|
output p param picture pre progress q rp rt ruby s samp script section select
|
9
11
|
small source span strong style sub summary sup table tbody td textarea tfoot th
|
10
|
-
thead time title tr track u ul var video wbr
|
12
|
+
thead time title tr track u ul var video wbr].freeze
|
11
13
|
|
12
|
-
SVG_TAGS = %w
|
14
|
+
SVG_TAGS = %w[svg path].freeze
|
13
15
|
|
14
16
|
(HTML_TAGS + SVG_TAGS).each do |tag|
|
15
17
|
define_method tag do |params = {}, &block|
|
@@ -38,7 +40,8 @@ module VirtualDOM
|
|
38
40
|
self
|
39
41
|
end
|
40
42
|
|
41
|
-
|
43
|
+
# rubocop:disable Style/MissingRespondToMissing, Metrics/MethodLength, Metrics/AbcSize
|
44
|
+
def method_missing(klass, params = {}, &block)
|
42
45
|
return unless @__last_virtual_node__
|
43
46
|
return unless @__virtual_nodes__
|
44
47
|
|
@@ -51,28 +54,29 @@ module VirtualDOM
|
|
51
54
|
end
|
52
55
|
|
53
56
|
class_params = @__last_virtual_node__.params.delete(:className)
|
54
|
-
method_params = if
|
57
|
+
method_params = if klass.end_with?('!')
|
55
58
|
{ id: clazz[0..-2],
|
56
59
|
class: merge_string(class_params, params[:class]) }
|
57
60
|
else
|
58
|
-
{ class: merge_string(class_params, params[:class],
|
61
|
+
{ class: merge_string(class_params, params[:class], klass.gsub('_', '-').gsub('--', '_')) }
|
59
62
|
end
|
60
63
|
params = @__last_virtual_node__.params.merge(params).merge(method_params)
|
61
64
|
process_tag(@__last_virtual_node__.name, params, block, children)
|
62
65
|
end
|
66
|
+
# rubocop:enable Style/MissingRespondToMissing, Metrics/MethodLength, Metrics/AbcSize
|
63
67
|
|
64
68
|
def merge_string(*params)
|
65
69
|
arr = []
|
66
70
|
params.each do |string|
|
67
71
|
next unless string
|
68
72
|
|
69
|
-
arr << string.split
|
73
|
+
arr << string.split
|
70
74
|
end
|
71
75
|
arr.join(' ')
|
72
76
|
end
|
73
77
|
|
74
78
|
def process_params(params)
|
75
|
-
params.dup.
|
79
|
+
params.dup.each_key do |k|
|
76
80
|
case k
|
77
81
|
when 'for'
|
78
82
|
params['htmlFor'] = params.delete('for')
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module VirtualDOM
|
2
4
|
class VirtualNode
|
3
5
|
attr_reader :name, :params, :children
|
@@ -15,7 +17,7 @@ module VirtualDOM
|
|
15
17
|
def to_s_params
|
16
18
|
return unless @params.any?
|
17
19
|
|
18
|
-
|
20
|
+
" #{@params.map { |k, v| "#{k}=\"#{v}\"" }.join(" ")}"
|
19
21
|
end
|
20
22
|
|
21
23
|
def to_s_children
|
data/opal/porous/browser.rb
CHANGED
@@ -1,27 +1,30 @@
|
|
1
|
-
|
2
|
-
module Component
|
3
|
-
module Render
|
4
|
-
def render
|
5
|
-
raise Error, "Implement #render in #{self.class} component"
|
6
|
-
end
|
1
|
+
# frozen_string_literal: true
|
7
2
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
3
|
+
module Porous
|
4
|
+
module Component
|
5
|
+
module Render
|
6
|
+
def render
|
7
|
+
raise Error, "Implement #render in #{self.class} component"
|
8
|
+
end
|
15
9
|
|
16
|
-
|
10
|
+
def render_if_root
|
11
|
+
return unless @virtual_dom && @root_node
|
17
12
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
13
|
+
new_virtual_dom = render_virtual_dom
|
14
|
+
diff = VirtualDOM.diff @virtual_dom, new_virtual_dom
|
15
|
+
VirtualDOM.patch @root_node, diff
|
16
|
+
@virtual_dom = new_virtual_dom
|
17
|
+
end
|
18
|
+
|
19
|
+
def before_render; end
|
20
|
+
|
21
|
+
def render_virtual_dom
|
22
|
+
before_render
|
23
|
+
@cache_component_counter = 0
|
24
|
+
@__virtual_nodes__ = []
|
25
|
+
render
|
26
|
+
to_vnode
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
27
30
|
end
|
data/opal/porous/component.rb
CHANGED
data/opal/porous/injection.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Porous
|
2
4
|
module Injection
|
3
5
|
def init; end
|
@@ -20,16 +22,14 @@ module Porous
|
|
20
22
|
|
21
23
|
def init_injections
|
22
24
|
@injections ||= {}
|
23
|
-
self.class.injections.each do |name,
|
24
|
-
|
25
|
-
|
26
|
-
.new
|
27
|
-
.with_root_component(@root_component)
|
28
|
-
else
|
29
|
-
raise Error, "Invalid #{clazz} class, should mixin Porous::Injection"
|
25
|
+
self.class.injections.each do |name, klass|
|
26
|
+
unless klass.included_modules.include?(Porous::Injection)
|
27
|
+
raise Error, "Invalid #{klass} class, should mixin Porous::Injection"
|
30
28
|
end
|
29
|
+
|
30
|
+
@injections[name] = klass.new.with_root_component(@root_component)
|
31
31
|
end
|
32
|
-
@injections.
|
32
|
+
@injections.each_value do |instance|
|
33
33
|
instance.inject
|
34
34
|
instance.init
|
35
35
|
end
|
data/opal/porous.rb
CHANGED
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.1.
|
4
|
+
version: 0.1.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-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: listen
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '3.0'
|
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: '3.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: opal-browser
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,89 +53,33 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.6.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rackup
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '1
|
61
|
+
version: '2.1'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '1
|
68
|
+
version: '2.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: thor
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '3
|
75
|
+
version: '1.3'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '3
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rake
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '13.0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '13.0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: rspec
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '3.2'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '3.2'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: rubocop
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '1.21'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '1.21'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: solargraph
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - "~>"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: 0.50.0
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: 0.50.0
|
82
|
+
version: '1.3'
|
139
83
|
description: Highly opinionated web engine (not a framework!) that can be scripted
|
140
84
|
with Ruby.
|
141
85
|
email:
|
@@ -190,6 +134,7 @@ metadata:
|
|
190
134
|
homepage_uri: https://github.com/exastencil/porous
|
191
135
|
source_code_uri: https://github.com/exastencil/porous
|
192
136
|
changelog_uri: https://github.com/exastencil/porous/blob/main/CHANGELOG.md
|
137
|
+
rubygems_mfa_required: 'true'
|
193
138
|
post_install_message:
|
194
139
|
rdoc_options: []
|
195
140
|
require_paths:
|