porous 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 605209154f6a44bc2c7a84934bf661de4c721a2a5ed5f3b9c21556064ac1672e
4
- data.tar.gz: 27eb154e0be5f0b524e723355c1544541b26207f36e49eb372cea7d06e24cdd5
3
+ metadata.gz: 87c6a954ddaf691739b880123048bf3345ece37389404d7a1c7163b27119c0ac
4
+ data.tar.gz: d13c2be795c751e8eb6095e0642560065e4815ff04ac17ffd7605e1092d775ba
5
5
  SHA512:
6
- metadata.gz: f4244bbc93b9c53b55e486d52420653ce8ffd5ee5e8d642b91e25aafc439ea2c48b5622c84167083b93c05ef424f5ea2b5964b7a4696665e92ffab68d13a43b9
7
- data.tar.gz: 58e28a76335c29b19f57c8b68e9c1c6bd00136b753025b230bcabf4a041a872e0efe8a8ebf233a15c7249de018662f4de9c240b27c10701989faeb71231bc866
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 HTTP polling and browser refresh)
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 server
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. Hot-reloading will be improved once WebSockets support is implemented.
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 some example "apps" using Porous you can navigate to the examples folder and in any folder run:
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 server
59
+ $ porous dev
60
60
 
61
61
  ## Development
62
62
 
@@ -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
@@ -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
- transpile
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
@@ -6,42 +6,42 @@ module Porous
6
6
 
7
7
  namespace :server
8
8
 
9
- desc 'server [OPTIONS]', 'Starts Porous server'
10
- method_option :port,
11
- aliases: :p,
12
- type: :numeric,
13
- default: 9292,
14
- desc: 'The port Porous will listen on'
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
- method_option :host,
17
- aliases: :h,
18
- type: :string,
19
- default: 'localhost',
20
- desc: 'The host address Porous will bind to'
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
- MONITORING = %w[components pages].freeze
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
- def server
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 +1,2 @@
1
1
  static/dist
2
+ ssl
@@ -1,7 +1,21 @@
1
1
  # <%= config[:project_name] %>
2
2
 
3
+ ## Development
4
+
3
5
  ```sh
4
- $ porous run
6
+ $ porous dev
5
7
  ```
6
8
 
7
- Go to [http://localhost:8080/](http://localhost:8080/)
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
- svg role: 'img', width: '24', height: '24', class: 'w-5 h-5', viewBox: '0 0 24 24', fill: 'currentColor',
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Porous
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.1'
5
5
  end
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 'listen'
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
@@ -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[svg path].freeze
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)
@@ -37,7 +37,7 @@ module Porous
37
37
 
38
38
  def render!
39
39
  if Browser::AnimationFrame.supported?
40
- animation_frame do
40
+ Browser::AnimationFrame.new $window do
41
41
  @root_component.render_if_root
42
42
  end
43
43
  else
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.2.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-18 00:00:00.000000000 Z
11
+ date: 2024-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: listen
14
+ name: agoo
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.0'
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: '3.0'
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