phlex-sinatra 0.2.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0e0c3d6038f57d3a01b5abb0172d1598a0edb08d46e455dede38da9ad708560
4
- data.tar.gz: 6e5025677940fc22ed1830405646c18d4d441f8125a4c37f3179d8c8e735a354
3
+ metadata.gz: a78afcc1302f4df83e718925f4dd189fd6270a83f6a0bd1a3fd14c480e15131e
4
+ data.tar.gz: 3337dfdb6dc398e901222b50c1b51fb480070204298b406c486238b4c0c8a58c
5
5
  SHA512:
6
- metadata.gz: e94e93fbb09a9b6043667f8139cc515a4d6b5302f3459b5216d4f900d471579b4621716e1734d4dd38ead39788074c6442ed3f0c46ce63e7aa9faa4868bb4cda
7
- data.tar.gz: 5026ea9e6f0af3ae2b064dc475d441e85b6753e49e37ef1e57f6aca00d3d7e15feb8a6eb188a6939eff70c0dae7ff1fa4db8447f3cd2a6c512a9212273ef4a4e
6
+ metadata.gz: ddc9255d6c867f6bd67c349df61e05c0bc79af68a3ede5be8217bee8ae42b6b6f08c40064f43d956eec2ab82007742608d948b071c3efe448c3ca1196c1a626a
7
+ data.tar.gz: 62e813a5c2523581b1eecc0fd3b02549d698454433f49618b5b3500684fc7fad8018b7a90d245b80711ce80bb98b4b8091cfdfe8ce8dc2c0fd26b7d2610fa6c6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## Version 0.4.0 - 2024-09-10
2
+
3
+ - Add support for wrapping a Phlex view in a layout. Pass `layout: true` to use Sinatra's default layout or specify the view by passing a symbol. Defaults to ERB and other Sinatra templating languages can be specified via the `layout_engine:` keyword.
4
+
5
+ ## Version 0.3.0 - 2023-12-13
6
+
7
+ - Add support for streaming a view. Pass `stream: true` to the `#phlex` helper so Phlex will use Sinatra's streaming capability.
8
+
1
9
  ## Version 0.2.0 - 2023-04-24
2
10
 
3
11
  - Allow passing a `content_type:` kwarg to the `#phlex` helper so it behaves like Sinatra's other template helpers (defaults to `:html` – or `:svg` for a `Phlex::SVG` instance).
data/Gemfile CHANGED
@@ -5,6 +5,9 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in phlex-sinatra.gemspec
6
6
  gemspec
7
7
 
8
+ gem 'capybara'
9
+ gem 'haml'
10
+ gem 'puma'
8
11
  gem 'rack-test'
9
12
  gem 'rake'
10
13
  gem 'rspec'
data/README.md CHANGED
@@ -24,7 +24,7 @@ You can now use Sinatra's `url()` helper method directly and its other methods (
24
24
 
25
25
  ```ruby
26
26
  class MyView < Phlex::HTML
27
- def template
27
+ def view_template
28
28
  h1 { 'Phlex / Sinatra integration' }
29
29
  p {
30
30
  a(href: url('/foo', false)) { 'link to foo' }
@@ -42,7 +42,92 @@ get '/foo' do
42
42
  end
43
43
  ```
44
44
 
45
- ## Why?
45
+ ## Layout
46
+
47
+ If your entire view layer uses Phlex then layout will be a part of your component structure but maybe you've got an existing non-Phlex layout or you don't want to use Phlex for _everything_, in which case standard Sinatra layouts are supported.
48
+
49
+ Pass `layout: true` to wrap the Phlex output with Sinatra's default layout -- a file named "layout.erb" in the configured views directory (ERB is the default) -- or pass a symbol to specify the file:
50
+
51
+ ```ruby
52
+ get '/foo' do
53
+ # This Phlex view will be wrapped by `views/my_layout.erb`.
54
+ phlex MyView.new, layout: :my_layout
55
+ end
56
+ ```
57
+
58
+ Other [Sinatra templating languages](https://sinatrarb.com/intro.html#available-template-languages) can be specified via the `layout_engine` keyword:
59
+
60
+ ```ruby
61
+ get '/foo' do
62
+ # This Phlex view will be wrapped by `views/layout.haml`.
63
+ phlex MyView.new, layout: true, layout_engine: :haml
64
+ end
65
+ ```
66
+
67
+ ## Using Phlex in other templates
68
+
69
+ It's also possible to call `phlex` from within other views, for instance an ERB template:
70
+
71
+ ```erb
72
+ <%= phlex MyView.new %>
73
+ ```
74
+
75
+ A `layout` can also be passed:
76
+
77
+ ```erb
78
+ <%= phlex MyView.new, layout: :wrapper %>
79
+ ```
80
+
81
+ ## Streaming
82
+
83
+ Streaming a Phlex view can be enabled by passing `stream: true` which will cause Phlex to automatically write to the response after the closing `</head>` and buffer the remaining content:
84
+
85
+ ```ruby
86
+ get '/foo' do
87
+ phlex MyView.new, stream: true
88
+ end
89
+ ```
90
+
91
+ Even with no further intervention this small change means that the browser will receive the complete `<head>` as quickly as possible and can start fetching and processing its external resources while waiting for the rest of the page to download.
92
+
93
+ You can also manually flush the contents of the buffer at any point using Phlex's `#flush` method:
94
+
95
+ ```ruby
96
+ class Layout < Phlex::HTML
97
+ def view_template(&block)
98
+ doctype
99
+ html {
100
+ head {
101
+ # All the usual stuff: links to external stylesheets and JavaScript etc.
102
+ }
103
+ # Phlex will automatically flush to the response at this point which will
104
+ # benefit all pages that opt in to streaming.
105
+ body {
106
+ # Standard site header and navigation.
107
+ render Header.new
108
+
109
+ yield_content(&block)
110
+ }
111
+ }
112
+ end
113
+ end
114
+
115
+ class MyView < Phlex::HTML
116
+ def view_template
117
+ render Layout.new {
118
+ # Knowing that this page can take a while to generate we can choose to
119
+ # flush here so the browser can render the site header while downloading
120
+ # the rest of the page - which should help minimise the First Contentful
121
+ # Paint metric.
122
+ flush
123
+
124
+ # The rest of the big long page...
125
+ }
126
+ end
127
+ end
128
+ ```
129
+
130
+ ## Why do I need Sinatra's `url()` helper?
46
131
 
47
132
  It might not seem obvious at first why you'd use `url()` at all given that you mostly just pass the string you want to output and then probably `false` so the scheme/host isn't included.
48
133
 
@@ -54,7 +139,7 @@ There are a couple of reasons:
54
139
 
55
140
  2. **Awareness that the app is being served from a subdirectory**
56
141
 
57
- This isn't something you encounter very often in a standard Sinatra app but you hit it quite quickly if you're using [Parklife](https://github.com/benpickles/parklife) to generate a static build which you host on GitHub Pages – which is exactly what prompted me to write this integration.
142
+ This isn't something you encounter very often in a standard Sinatra app but you hit it quite quickly if you're using [Parklife](https://github.com/benpickles/parklife) to generate a static build hosted on GitHub Pages – which is exactly what prompted me to write this integration.
58
143
 
59
144
  In this case by using the `url()` helper you won’t have to change anything when switching between serving the app from `/` in development and hosting it at `/my-repository/` in production – internal links to other pages/stylesheets/etc will always be correct regardless.
60
145
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Phlex
4
4
  module Sinatra
5
- VERSION = '0.2.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
data/lib/phlex-sinatra.rb CHANGED
@@ -6,6 +6,7 @@ require_relative 'phlex/sinatra/version'
6
6
  module Phlex
7
7
  module Sinatra
8
8
  Error = Class.new(StandardError)
9
+ IncompatibleOptionError = Class.new(Error)
9
10
 
10
11
  class TypeError < Error
11
12
  MAX_SIZE = 32
@@ -37,13 +38,39 @@ end
37
38
 
38
39
  module Sinatra
39
40
  module Templates
40
- def phlex(obj, content_type: nil)
41
+ def phlex(
42
+ obj,
43
+ content_type: nil,
44
+ layout: false,
45
+ layout_engine: :erb,
46
+ stream: false
47
+ )
41
48
  raise Phlex::Sinatra::TypeError.new(obj) unless obj.is_a?(Phlex::SGML)
42
49
 
43
- content_type ||= :svg if obj.is_a?(Phlex::SVG)
50
+ content_type ||= :svg if obj.is_a?(Phlex::SVG) && !layout
44
51
  self.content_type(content_type) if content_type
45
52
 
46
- obj.call(view_context: self)
53
+ # Copy Sinatra's behaviour and interpret layout=true as meaning "use the
54
+ # default layout" - uses an internal Sinatra instance variable :s
55
+ layout = @default_layout if layout == true
56
+
57
+ if stream
58
+ raise Phlex::Sinatra::IncompatibleOptionError.new(
59
+ 'streaming is not compatible with layout'
60
+ ) if layout
61
+
62
+ self.stream do |out|
63
+ obj.call(out, view_context: self)
64
+ end
65
+ else
66
+ output = obj.call(view_context: self)
67
+
68
+ if layout
69
+ render(layout_engine, layout, { layout: false }) { output }
70
+ else
71
+ output
72
+ end
73
+ end
47
74
  end
48
75
  end
49
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlex-sinatra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Pickles
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-24 00:00:00.000000000 Z
11
+ date: 2024-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: phlex
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 1.7.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: '0'
26
+ version: 1.7.0
27
27
  description: A Phlex adapter for Sinatra
28
28
  email:
29
29
  - spideryoung@gmail.com
@@ -64,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
64
  - !ruby/object:Gem::Version
65
65
  version: '0'
66
66
  requirements: []
67
- rubygems_version: 3.4.6
67
+ rubygems_version: 3.5.17
68
68
  signing_key:
69
69
  specification_version: 4
70
70
  summary: A Phlex adapter for Sinatra