himg 0.0.4 → 0.0.5

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: 1e2af1a8848987b76777bf3aed2c0dfc3254e2486aab89e816e2751cb00ec10f
4
- data.tar.gz: d4e71ff28a851c19ccc36403997cf2965e082f8267852f25a4efd704d4f96fa9
3
+ metadata.gz: 1bd4c145135ae494ac36cefa1aade53d31d5314e54ce582126c76484115815f7
4
+ data.tar.gz: f631474fc095ea589af509e8c27e0386efb102868b225bad5be708d10e0b682a
5
5
  SHA512:
6
- metadata.gz: 3706e38ff13df4d57636bbb10bd58994d666454b5b2fbcd9dfbbdd5fe31a78ab13e7c768f56b8d188b8752a648eca6653452c7044eda88c7927ad89be61489c9
7
- data.tar.gz: 33c0de522e5ff80866457b88263540532a561ebc7fd0740649d08f3861370824456f7cc98f4d94b5e07ff28f02cc58706c716ed564f6bac0586676e6c4495d93
6
+ metadata.gz: c666c9444a47522f1843e34c3c065ee06e15d2995a5cbe0a537ab17acb96bfdb08414735c5c468ea47609169739f37bda38c4e74a745f12b643c45a1eaa1ded8
7
+ data.tar.gz: e629137b2de381bf1ed7f5cf5d6caa694372172056e9f1c7c80d6d879011641162ecf486863e51147349133ef1a2e189c13b13406d19bbd0971c9f3d9926d810
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.0.5] - 2025-04-22
4
+
5
+ - Can configure `render himg: ""` with options including `width:`, `height:`,
6
+ `truncate:` and `verbose:`.
7
+ - Can use `himg_config` helper methods at controller level and action level
8
+ to set `@_himg_config`, which can then be passed to the renderer with
9
+ `render himg: "<!DOCTYPE html>", config: himg_config` as an alternative to
10
+ specifying config options individually to `ActionController::Rendering#render`.
11
+ - `himg_config` helpers can also be used to control the configuration of
12
+ template based default render, when not calling render manually within the
13
+ controller. This works because the template handler can access `@_himg_config`.
14
+ - Can use string width / height with Himg.render
15
+ - Disable detailed log timings by default. Can re-enable with verbose: true.
16
+ There is still some logging from blitz-net#fetch for http requests and for
17
+ blitz-html::DocumentHtmlParser#finish on unexpected tokens.
18
+
3
19
  ## [0.0.4] - 2025-04-22
4
20
 
5
21
  - Allow `width`, `height` and `truncate` to be passed to the render function.
data/Cargo.lock CHANGED
@@ -1065,7 +1065,7 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
1065
1065
 
1066
1066
  [[package]]
1067
1067
  name = "himg"
1068
- version = "0.0.4"
1068
+ version = "0.0.5"
1069
1069
  dependencies = [
1070
1070
  "blitz-dom",
1071
1071
  "blitz-html",
data/README.md CHANGED
@@ -16,7 +16,6 @@ In Rails this will mean you can process user.himg.erb to display an image includ
16
16
  4. Network requests can be made: don't use this library with untrusted inputs.
17
17
  5. file:// URLs are resolved: this could expose files on your computer.
18
18
  6. Native extensions are not yet being published for different os/arch
19
- 7. Verbose logging is hardcoded
20
19
 
21
20
  ## Installation
22
21
 
@@ -37,11 +36,13 @@ gem install himg
37
36
  ### Ruby
38
37
 
39
38
  ```ruby
40
- png = Himg.render("<html bgcolor='blue'></html>")
39
+ png = Himg.render("<!DOCTYPE html><body style='background:blue;'></body>")
40
+ File.open("blue.png", "wb"){|f| f.write(png) }
41
41
  ```
42
42
 
43
43
  ```ruby
44
- png = Himg.render("<h1>Hi</h1>", width: 24, height: 24, truncate: false)
44
+ png = Himg.render("<!DOCTYPE html><h1>Snapshot</h1>", width: 89, height: 5, truncate: false)
45
+ File.open("dynamic_height.png", "wb"){|f| f.write(png) }
45
46
  ```
46
47
 
47
48
  ### Rails
@@ -62,13 +63,46 @@ Once you've added a view template for your resource, you can use it to generate
62
63
  <meta property="og:image" content="<%= user_url(@user.username, format: :png) %>" />
63
64
  ```
64
65
 
65
- ### Advanced Rails Usage
66
+ ### Configuration Options
66
67
 
67
- A :himg template handler is registered and will be called by rails' `default_render` method automatically when the corresponding view is found. This can be `show.himg` for a static image, or `show.himg.erb` to use variables from the controller.
68
+ Options: `width`, `height`, `verbose`, `truncate`.
69
+
70
+ ### Passing options to a Rails view template
71
+
72
+ Options can be set at a controller level using the `himg_config` helper method:
73
+ ```ruby
74
+ class UsersController < ActionController::Base
75
+ himg_config(verbose: true)
76
+ end
77
+ ```
78
+
79
+ These can be overridden at a view level:
80
+ ```ruby
81
+ class UsersController < ActionController::Base
82
+ def show
83
+ himg_config(width: params[:w]) if params[:w]
84
+
85
+ @user = User.new
86
+ end
87
+ ```
88
+
89
+ ### Rails manual render
68
90
 
69
91
  If you prefer you could also use `render himg: "<div>My Data</div>"` instead, but should be careful with untrusted input if constructing HTML manually.
70
92
 
71
- To be explicit in the controler you can also use `respond_to` style:
93
+ Options can then be passed directly to the manual render:
94
+ ```ruby
95
+ render himg: '<!DOCTYPE html>', truncate: false
96
+ ```
97
+
98
+ Alternatively you can pass in options which have been set with `himg_config`:
99
+ ```ruby
100
+ render himg: '<!DOCTYPE html>', config: himg_config
101
+ ```
102
+
103
+ ### Rails `respond_to`
104
+
105
+ To be explicit in the controller you can also use `respond_to` style:
72
106
 
73
107
  ```ruby
74
108
  respond_to do |format|
@@ -77,6 +111,7 @@ respond_to do |format|
77
111
  end
78
112
  ```
79
113
 
114
+ You can also use this combined with a manual render:
80
115
  ```ruby
81
116
  respond_to do |format|
82
117
  format.html
@@ -85,6 +120,16 @@ respond_to do |format|
85
120
  end
86
121
  ```
87
122
 
123
+ ### How it works
124
+
125
+ No browser, just basics!
126
+
127
+ Himg calls through to the amazing blitz library, which uses Stylo to parse the CSS, servo/html5ever to parse the HTML, fetches network resources, builds a scene graph and hands over to vello to render an image.
128
+
129
+ Interaction between Ruby & Rust is done with the help of `magnus`, `rb_sys` and lots of glue code from the `oxidize-rb` team.
130
+
131
+ To play nicely with Rails a template handler is registered, which Rails' `default_render` method automatically calls when the corresponding view is found. This can be `show.himg` for a static image, or `show.himg.erb` to use variables from the controller. Additionally a Renderer is available with `render himg: 'content'` in case a view template is not needed.
132
+
88
133
  ### Run directly from the command line to output an image
89
134
 
90
135
  ```bash
data/ext/himg/Cargo.toml CHANGED
@@ -1,7 +1,7 @@
1
1
  [package]
2
2
  name = "himg"
3
3
  description = "ruby bindings to expose a blitz html->png pipeline"
4
- version = "0.0.4"
4
+ version = "0.0.5"
5
5
  edition = "2024"
6
6
  authors = ["James Edwards-Jones <git@jamedjo.co.uk>"]
7
7
  license = "MIT"
@@ -21,7 +21,7 @@ async fn main() {
21
21
 
22
22
  // Fetch HTML from path
23
23
  let html = std::fs::read_to_string(&path_string).unwrap();
24
- logger.log("Fetched HTML");
24
+ logger.log("Read HTML");
25
25
 
26
26
  // Configure viewport dimensions
27
27
  let options = Options {
@@ -31,20 +31,21 @@ async fn main() {
31
31
  hidpi_scale: 1.0,
32
32
  },
33
33
  truncate: false,
34
+ verbose: true,
34
35
  color_scheme: ColorScheme::Light,
35
36
  allow_net_requests: true, //TODO: Implement using this
36
37
  };
37
38
 
38
39
  // Render to Image
39
40
  let base_url = format!("file://{}", path_string.clone());
40
- let buffer = html_to_image(&html, Some(base_url), options, &mut logger).await;
41
+ let render_output = html_to_image(&html, Some(base_url), options, &mut logger).await;
41
42
 
42
43
  // Determine output path, and open a file at that path.
43
44
  let out_path = compute_filename(&path_string);
44
45
  let mut file = File::create(&out_path).unwrap();
45
46
 
46
47
  // Encode buffer as PNG and write it to a file
47
- write_png(&mut file, &buffer, options.image_size.scaled_width(), options.image_size.scaled_height()).unwrap();
48
+ write_png(&mut file, &render_output.buffer, render_output.image_size.scaled_width(), render_output.image_size.scaled_height()).unwrap();
48
49
  logger.log("Wrote out png");
49
50
 
50
51
  logger.log_total_time("\nDone");
@@ -76,7 +76,9 @@ pub async fn html_to_image(
76
76
  };
77
77
  logger.log("Calculated render dimensions from document");
78
78
 
79
- println!("Screenshot is ({}x{})",render_size.scaled_width(), render_size.scaled_height());
79
+ if options.verbose {
80
+ println!("Screenshot is ({}x{})",render_size.scaled_width(), render_size.scaled_height());
81
+ }
80
82
 
81
83
  // Render document to RGBA buffer
82
84
  let buffer = render_to_buffer(
data/ext/himg/src/lib.rs CHANGED
@@ -6,9 +6,11 @@ pub mod writer;
6
6
  pub mod logger;
7
7
 
8
8
  pub use renderer::render_blocking;
9
+ pub use image_size::ImageSize;
10
+ pub use options::Options;
11
+ pub use html_to_image::html_to_image;
12
+ pub use writer::write_png;
9
13
 
10
- use crate::image_size::ImageSize;
11
- use crate::options::Options;
12
14
  use blitz_traits::ColorScheme;
13
15
  use magnus::{function, prelude::*, ExceptionClass, Error, Ruby, RString, RHash};
14
16
 
@@ -28,6 +30,7 @@ impl Options {
28
30
  hidpi_scale: 1.0,
29
31
  },
30
32
  truncate: Self::get_option(hash, "truncate", true)?,
33
+ verbose: Self::get_option(hash, "verbose", false)?,
31
34
  color_scheme: ColorScheme::Light,
32
35
  allow_net_requests: true, //TODO: Implement using this
33
36
  };
@@ -8,4 +8,5 @@ pub struct Options {
8
8
  pub color_scheme: ColorScheme,
9
9
  pub allow_net_requests: bool,
10
10
  pub truncate: bool,
11
+ pub verbose: bool,
11
12
  }
@@ -1,7 +1,7 @@
1
1
  use crate::html_to_image::html_to_image;
2
2
  use crate::options::Options;
3
3
  use crate::writer::write_png;
4
- use crate::logger::{TimedLogger};
4
+ use crate::logger::{Logger, NullLogger, TimedLogger};
5
5
 
6
6
  pub fn render_blocking(html: String, options: Options) -> Result<Vec<u8>, std::io::Error> {
7
7
  let runtime = tokio::runtime::Runtime::new()?;
@@ -11,12 +11,16 @@ pub fn render_blocking(html: String, options: Options) -> Result<Vec<u8>, std::i
11
11
 
12
12
  // render_to_bytes, render_to_string, render_to_file, render_to_io
13
13
  pub async fn render(html: String, options: Options) -> Result<Vec<u8>, std::io::Error> {
14
- let mut logger = TimedLogger::init();
14
+ let mut logger: Box<dyn Logger> = if options.verbose {
15
+ Box::new(TimedLogger::init())
16
+ } else {
17
+ Box::new(NullLogger{})
18
+ };
15
19
 
16
20
  // Render to Image
17
21
  //let base_url = format!("file://{}", path_string.clone());
18
22
  let base_url = None;
19
- let render_output = html_to_image(&html, base_url, options, &mut logger).await;
23
+ let render_output = html_to_image(&html, base_url, options, &mut *logger).await;
20
24
 
21
25
  // Determine output path, and open a file at that path.
22
26
  let mut output_buffer: Vec<u8> = Vec::new();
@@ -0,0 +1,31 @@
1
+ module Himg
2
+ class Railtie
3
+ module ControllerConfig
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before_action :_apply_himg_config
8
+ end
9
+
10
+ class_methods do
11
+ def himg_config(options = {})
12
+ @_himg_global_config ||= {}
13
+ @_himg_global_config.merge!(options)
14
+ end
15
+
16
+ def _himg_global_config
17
+ @_himg_global_config&.dup || {}
18
+ end
19
+ end
20
+
21
+ def himg_config(options = {})
22
+ @_himg_config.merge!(options)
23
+ @_himg_config
24
+ end
25
+
26
+ def _apply_himg_config
27
+ @_himg_config = self.class._himg_global_config
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,7 +4,7 @@ module Himg
4
4
  class TemplateHandler
5
5
  def self.call(_template, source)
6
6
  <<-CODE
7
- Himg.render(#{source.inspect})
7
+ Himg.render(#{source.inspect}, **@_himg_config)
8
8
  CODE
9
9
  end
10
10
  end
@@ -21,7 +21,7 @@ module Himg
21
21
  output = begin
22
22
  #{preprocessed_view_code}
23
23
  end
24
- Himg.render(output)
24
+ Himg.render(output, **@_himg_config)
25
25
  CODE
26
26
  end
27
27
  end
data/lib/himg/railtie.rb CHANGED
@@ -29,10 +29,21 @@ module Himg
29
29
  end
30
30
 
31
31
  initializer "himg.controller_renderer" do
32
- ActionController::Renderers.add :himg do |obj, _options|
33
- png_data = Himg.render(obj)
32
+ ActionController::Renderers.add :himg do |obj, options = {}|
33
+ configured_options = options[:config] || {}
34
+ direct_options = options.symbolize_keys.slice(*Himg::RENDER_OPTIONS)
35
+ merged_options = configured_options.merge(direct_options)
36
+
37
+ png_data = Himg.render(obj, **merged_options)
34
38
  send_data png_data, type: "image/png", disposition: "inline"
35
39
  end
36
40
  end
41
+
42
+ initializer 'himg.controller_config' do
43
+ require "himg/railtie/controller_config"
44
+ ActiveSupport.on_load(:action_controller) do
45
+ include Himg::Railtie::ControllerConfig
46
+ end
47
+ end
37
48
  end
38
49
  end
data/lib/himg/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Himg
4
- VERSION = "0.0.4"
4
+ VERSION = "0.0.5"
5
5
  end
data/lib/himg.rb CHANGED
@@ -16,9 +16,10 @@ end
16
16
  #
17
17
  # Converts HTML to an Image for a minimal subset of HTML and CSS
18
18
  module Himg
19
+ RENDER_OPTIONS = %i[width height truncate verbose].freeze
19
20
  class Error < StandardError; end
20
21
 
21
- def self.render(html, width: 720, height: 405, truncate: true)
22
- render_to_string(html, "width" => width, "height" => height, "truncate" => truncate)
22
+ def self.render(html, width: 720, height: 405, truncate: true, verbose: false)
23
+ render_to_string(html, "width" => width.to_i, "height" => height.to_i, "truncate" => truncate, "verbose" => verbose)
23
24
  end
24
25
  end
data/sig/himg.rbs CHANGED
@@ -1,8 +1,16 @@
1
1
  module Himg
2
2
  VERSION: String
3
3
 
4
- class Renderer
5
- def initialize: (Integer width, Integer height) -> void
6
- def render: (String html) -> String
4
+ class Error < StandardError
7
5
  end
6
+
7
+ def self.render: (
8
+ String html,
9
+ ?width: Integer,
10
+ ?height: Integer,
11
+ ?truncate: bool,
12
+ ?verbose: bool
13
+ ) -> String
14
+
15
+ def self.render_to_string: (String html, Hash[string, untyped] options) -> String
8
16
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: himg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Edwards-Jones
@@ -196,6 +196,7 @@ files:
196
196
  - gemfiles/rails_8.gemfile.lock
197
197
  - lib/himg.rb
198
198
  - lib/himg/railtie.rb
199
+ - lib/himg/railtie/controller_config.rb
199
200
  - lib/himg/railtie/template_handler.rb
200
201
  - lib/himg/version.rb
201
202
  - sig/himg.rbs