porous 0.1.0 → 0.2.0
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/.rubocop.yml +20 -1
- data/CHANGELOG.md +14 -5
- data/README.md +16 -6
- data/Rakefile +3 -3
- data/exe/porous +2 -0
- data/lib/porous/application.rb +33 -0
- data/lib/porous/cli/build.rb +39 -3
- data/lib/porous/cli/new.rb +2 -0
- data/lib/porous/cli/server.rb +25 -4
- data/lib/porous/cli/template/pages/home.rb +11 -5
- 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 -8
- data/lib/porous/logger.rb +9 -0
- data/lib/porous/page.rb +6 -1
- data/lib/porous/router.rb +22 -13
- data/lib/porous/routes.rb +12 -4
- data/lib/porous/server.rb +29 -31
- data/lib/porous/version.rb +1 -1
- data/lib/porous.rb +8 -3
- data/lib/virtual_dom/dom.rb +13 -9
- data/lib/virtual_dom/virtual_node.rb +3 -1
- data/opal/porous/application.rb +15 -0
- data/opal/porous/component/class_methods.rb +5 -3
- data/opal/porous/component/render.rb +26 -23
- data/opal/porous/component/virtual.rb +2 -0
- data/opal/porous/component.rb +3 -1
- data/opal/porous/injection.rb +13 -9
- data/opal/porous/page.rb +16 -0
- data/opal/porous/router.rb +153 -0
- data/opal/porous/routes.rb +94 -0
- data/opal/porous.rb +31 -0
- metadata +18 -68
- data/opal/porous/browser.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 605209154f6a44bc2c7a84934bf661de4c721a2a5ed5f3b9c21556064ac1672e
|
4
|
+
data.tar.gz: 27eb154e0be5f0b524e723355c1544541b26207f36e49eb372cea7d06e24cdd5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4244bbc93b9c53b55e486d52420653ce8ffd5ee5e8d642b91e25aafc439ea2c48b5622c84167083b93c05ef424f5ea2b5964b7a4696665e92ffab68d13a43b9
|
7
|
+
data.tar.gz: 58e28a76335c29b19f57c8b68e9c1c6bd00136b753025b230bcabf4a041a872e0efe8a8ebf233a15c7249de018662f4de9c240b27c10701989faeb71231bc866
|
data/.rubocop.yml
CHANGED
@@ -1,13 +1,32 @@
|
|
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
|
+
|
16
|
+
Style/GlobalVars:
|
17
|
+
Enabled: false
|
18
|
+
|
12
19
|
Layout/LineLength:
|
13
20
|
Max: 120
|
21
|
+
|
22
|
+
Metrics/BlockLength:
|
23
|
+
AllowedMethods:
|
24
|
+
- render
|
25
|
+
Metrics/MethodLength:
|
26
|
+
Max: 15
|
27
|
+
AllowedMethods:
|
28
|
+
- render
|
29
|
+
|
30
|
+
require:
|
31
|
+
- rubocop-rake
|
32
|
+
- rubocop-rspec
|
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,21 @@
|
|
1
1
|
## [Planned]
|
2
2
|
|
3
|
-
-
|
4
|
-
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
- WebSockets support
|
4
|
+
- Production mode
|
5
|
+
|
6
|
+
## [0.2.0] - 18 February 2024
|
7
|
+
|
8
|
+
- Server-side hot reloading (browser reloads on changes)
|
9
|
+
- Dynamic page metadata (title and description)
|
10
|
+
- Less noisy logging (silence logging for Rack::Static)
|
11
|
+
- Client-side component rendering (sans SVG support)
|
12
|
+
- Client-side routing / navigation
|
8
13
|
- Client-side hot reloading
|
9
14
|
|
15
|
+
## [0.1.1] - 17 February 2024
|
16
|
+
|
17
|
+
- Server-side reloading (server requests reflect changes)
|
18
|
+
|
10
19
|
## [0.1.0] - 15 February 2024
|
11
20
|
|
12
21
|
- `porous server` to run apps
|
data/README.md
CHANGED
@@ -1,11 +1,19 @@
|
|
1
|
-
# Porous
|
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.
|
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
|
4
4
|
|
5
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
|
|
9
|
+
## Current Features
|
10
|
+
|
11
|
+
- 🙅 No bundled runtime (only code unique to your app needs to be in your repository)
|
12
|
+
- 🖥️ Server-side rendering (server responds with the entire initial page populated for SEO)
|
13
|
+
- 💻 Client-side rendering (application bundle is served and interactions and subsequent pages are rendered client-side)
|
14
|
+
- 🌄 Serves static files (from `static` folder)
|
15
|
+
- 🔥 Hot reloading (via HTTP polling and browser refresh)
|
16
|
+
|
9
17
|
## Design
|
10
18
|
|
11
19
|
Applications are composed of `Page`s which are in turn composed of `Component`s. Data is persisted as `Entity`s in configurable store options (memory, disk, database). Client-server communication occurs as `Event`s over WebSockets.
|
@@ -16,7 +24,7 @@ A page is conceptually similar to what would be rendered when visiting a specifi
|
|
16
24
|
|
17
25
|
### Components
|
18
26
|
|
19
|
-
A component is any composable unit of code responsible for rendering markup, potentially based on some state. This is somewhat equivalent to Web Components, in that it can also have some behaviour attached. But it can also simply be
|
27
|
+
A component is any composable unit of code responsible for rendering markup, potentially based on some state. This is somewhat equivalent to Web Components, in that it can also have some behaviour attached. But it can also simply be used to remove code duplication. Essentially any markup that has behaviour attached or would otherwise create code duplication should probably be in Components.
|
20
28
|
|
21
29
|
### Entities
|
22
30
|
|
@@ -36,11 +44,13 @@ Porous is not a framework. You don't build an application with it as a dependenc
|
|
36
44
|
|
37
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.
|
38
46
|
|
39
|
-
|
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
|
+
|
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:
|
40
50
|
|
41
51
|
$ porous server
|
42
52
|
|
43
|
-
By default Porous will run at `
|
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. Hot-reloading will be improved once WebSockets support is implemented.
|
44
54
|
|
45
55
|
### Running examples
|
46
56
|
|
@@ -66,4 +76,4 @@ Everyone interacting in the Porous project's codebases, issue trackers, chat roo
|
|
66
76
|
|
67
77
|
## Acknowledgements
|
68
78
|
|
69
|
-
|
79
|
+
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. While my final approach may deviate significantly from theirs, having code to review and a workable starting point was invaluable.
|
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
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Porous
|
4
|
+
class Application
|
5
|
+
include Porous::Component
|
6
|
+
|
7
|
+
# rubocop:disable Metrics/AbcSize
|
8
|
+
def render
|
9
|
+
html do
|
10
|
+
head do
|
11
|
+
meta charset: 'UTF-8'
|
12
|
+
meta name: 'viewport', content: 'width=device-width, initial-scale=1.0'
|
13
|
+
|
14
|
+
if props[:title]
|
15
|
+
title do
|
16
|
+
text props[:title]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
meta name: 'description', content: props[:description] if props[:description]
|
20
|
+
|
21
|
+
script src: '/static/dist/application.js'
|
22
|
+
script src: '/static/dist/reload.js'
|
23
|
+
script src: 'https://cdn.tailwindcss.com'
|
24
|
+
end
|
25
|
+
|
26
|
+
body class: 'bg-gray-50 dark:bg-gray-900' do
|
27
|
+
component Porous::Router, props: { path: props[:path], query: props[:query] }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
# rubocop:enable Metrics/AbcSize
|
32
|
+
end
|
33
|
+
end
|
data/lib/porous/cli/build.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Porous
|
2
4
|
class CLI < Thor
|
3
5
|
include Thor::Actions
|
@@ -6,17 +8,51 @@ module Porous
|
|
6
8
|
|
7
9
|
namespace :build
|
8
10
|
|
9
|
-
|
11
|
+
def self.exit_on_failure?
|
12
|
+
true
|
13
|
+
end
|
10
14
|
|
15
|
+
desc 'build', 'Build static assets'
|
11
16
|
def build
|
12
|
-
empty_directory 'static/dist', force: options[:force]
|
17
|
+
empty_directory 'static/dist', verbose: false, force: options[:force]
|
13
18
|
transpile
|
19
|
+
live_reload
|
14
20
|
end
|
15
21
|
|
22
|
+
# rubocop:disable Metrics/BlockLength
|
16
23
|
no_commands do
|
17
24
|
def transpile
|
18
|
-
|
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
|
19
53
|
end
|
54
|
+
# rubocop:enable Metrics/MethodLength
|
20
55
|
end
|
56
|
+
# rubocop:enable Metrics/BlockLength
|
21
57
|
end
|
22
58
|
end
|
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!
|
@@ -14,13 +16,32 @@ module Porous
|
|
14
16
|
method_option :host,
|
15
17
|
aliases: :h,
|
16
18
|
type: :string,
|
17
|
-
default: '
|
19
|
+
default: 'localhost',
|
18
20
|
desc: 'The host address Porous will bind to'
|
19
21
|
|
22
|
+
MONITORING = %w[components pages].freeze
|
23
|
+
|
20
24
|
def server
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
24
45
|
end
|
25
46
|
end
|
26
47
|
end
|
@@ -1,15 +1,20 @@
|
|
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 = '/'
|
8
|
+
def page_title = 'Porous Web | Home'
|
9
|
+
def page_description = 'Landing page generated by Porous'
|
6
10
|
|
11
|
+
# rubocop:disable Metrics, Layout/LineLength
|
7
12
|
def render
|
8
13
|
div class: 'container p-8 mx-auto lg:h-full xl:px-0 flex flex-wrap' do
|
9
14
|
div class: 'flex items-center w-full lg:w-1/2' do
|
10
15
|
div class: 'max-w-2xl mb-8' do
|
11
16
|
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:
|
17
|
+
span class: 'bg-gradient-to-br from-pink-500 to-violet-500 bg-clip-text text-transparent box-decoration-clone' do
|
13
18
|
text 'Welcome to Porous!'
|
14
19
|
end
|
15
20
|
end
|
@@ -19,10 +24,10 @@ class Home
|
|
19
24
|
|
20
25
|
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
26
|
a href: 'https://github.com/exastencil/porous', target: '_blank', rel: 'noopener',
|
22
|
-
class:
|
23
|
-
span 'Get Started'
|
24
|
-
div class:
|
25
|
-
div class:
|
27
|
+
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
|
28
|
+
span 'Get Started 🧽'
|
29
|
+
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
|
30
|
+
div class: 'relative h-full w-8 bg-white/20'
|
26
31
|
end
|
27
32
|
end
|
28
33
|
a href: 'https://github.com/exastencil/porous', target: '_blank', rel: 'noopener',
|
@@ -45,4 +50,5 @@ class Home
|
|
45
50
|
end
|
46
51
|
end
|
47
52
|
end
|
53
|
+
# rubocop:enable Metrics, Layout/LineLength
|
48
54
|
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
|
@@ -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/lib/porous/page.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
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
|
12
|
+
|
13
|
+
def page_title = 'Porous Web'
|
14
|
+
def page_description = nil
|
10
15
|
end
|
11
16
|
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)
|
@@ -91,11 +100,11 @@ module Porous
|
|
91
100
|
end
|
92
101
|
|
93
102
|
def query
|
94
|
-
@props ? @props[:query] : ''
|
103
|
+
@props ? @props[:query] : ''
|
95
104
|
end
|
96
105
|
|
97
106
|
def path
|
98
|
-
@props ? @props[:path] : '/'
|
107
|
+
@props ? @props[:path] : '/'
|
99
108
|
end
|
100
109
|
|
101
110
|
def current_url?(name)
|
@@ -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
|