html_to 0.7.2 → 1.1.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: 8dfe49b4c49b244fbaf07b43bad721e8c3fd589d1a72a34d0679fd5c598f04a2
4
- data.tar.gz: 70dc266086e67d001cda4976ba4d29bef8078823fb835b47e2b6b33aaa34a7dd
3
+ metadata.gz: cc490495133d2799e907b246a839a9645e81d0097a10006a851cbb8af8343a61
4
+ data.tar.gz: 46f2beb5850fe8975354763abdce67ea53b0f06bc65a6ed19d9c179cb329f547
5
5
  SHA512:
6
- metadata.gz: 943cc79185807aeea0482a83c053e4d414d02dd6cb79ae87fdf6c857455bd067056cf6b77cedd6c65a0c2ed66537b241dfe3f7e49b87636355f2d683138ed5a4
7
- data.tar.gz: 918beae4db7054acb2393dea07d9b1038d849c8d705751b4db31911ea2e33bf15bc1789bda65b4f87f0a5b90a1a5587c3bc7bd29ff062b4b7acbe3befe2dae8e
6
+ metadata.gz: daeaa75cc74b90d4ff4883c5475559d7b886fb81dcbdea084ae96d1b5fd159e962e1dcf442ad95dabdc3d0298f4f82b2f2bc2d2ac8e10bb70094f2cd0f40abbc
7
+ data.tar.gz: 9ab97a704bcc78d2274948916e8b382e7cb97a64775a37747ce7abe866564b5126e06cd09f1e56db53c9996c471ddfb1d1b82fead1a8ecf8d3583596b01fe3ba
@@ -0,0 +1,46 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment include:
10
+
11
+ * Using welcoming and inclusive language
12
+ * Being respectful of differing viewpoints and experiences
13
+ * Gracefully accepting constructive criticism
14
+ * Focusing on what is best for the community
15
+ * Showing empathy towards other community members
16
+
17
+ Examples of unacceptable behavior by participants include:
18
+
19
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
20
+ * Trolling, insulting/derogatory comments, and personal or political attacks
21
+ * Public or private harassment
22
+ * Publishing others' private information, such as a physical or electronic address, without explicit permission
23
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Our Responsibilities
26
+
27
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
+
29
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ ## Scope
32
+
33
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project author at vchekryzhov@ya.ru. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
+
39
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
+
41
+ ## Attribution
42
+
43
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44
+
45
+ [homepage]: http://contributor-covenant.org
46
+ [version]: http://contributor-covenant.org/version/1/4/
@@ -0,0 +1,14 @@
1
+ # Contributing
2
+
3
+ 1. [Fork the repository.][fork]
4
+ 2. [Create a topic branch.][branch]
5
+ 3. Implement your feature or bug fix.
6
+ 4. Don't forget to add specs and make sure they pass by running `rspec .`.
7
+ 5. Make sure your code complies with the style guide by running `rubocop`. `rubocop -a` can automatically fix most issues for you.
8
+ 6. If necessary, add documentation for your feature or bug fix.
9
+ 7. Commit and push your changes.
10
+ 8. [Submit a pull request.][pr]
11
+
12
+ [fork]: http://help.github.com/fork-a-repo/
13
+ [branch]: https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-branches
14
+ [pr]: https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests
@@ -0,0 +1,11 @@
1
+ ### Summary
2
+
3
+ Provide a general description of the code changes in your pull
4
+ request. Were there any bugs you had fixed? If so, mention them. If
5
+ these bugs have open GitHub issues, be sure to tag them here as well,
6
+ to keep the conversation linked together.
7
+
8
+ ### Other Information
9
+
10
+ If there's anything else that's important and relevant to your pull
11
+ request, mention that information here.
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+ ## 1.1.1
3
+ Added templates, added generators, updated Readme, updated dependencies
4
+ ## 1.0.1
5
+ Bug fixes. test refactor. Added integration tests
6
+ ## 1.0.0 (5-Sep-2023)
7
+ Added configuration via DSL. Added ability to generate few images on one model. Replaced carrierwave uploader to active storage. Added rspec.
8
+ ## 0.7.2 (12-May-2021)
9
+ * Fixing Issues
10
+ ## 0.7.0 (07-Apr-2021)
11
+ * Some Improves
12
+ ## 0.0.2 (05-Apr-2021)
13
+ * Fixing Issues
14
+ ## 0.0.1 (05-Apr-2021)
15
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
3
+
4
+ group :test do
5
+ gem 'database_cleaner-active_record'
6
+ gem 'image_processing'
7
+ gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
8
+
9
+ gem 'database_cleaner'
10
+ gem 'dotenv', '~> 2.5'
11
+ gem 'rails', '~> 7'
12
+ gem 'rake', '~> 13.0'
13
+ gem 'rspec', '~> 3.6'
14
+ gem 'rspec-rails', '~> 4.0'
15
+ gem 'sqlite3'
16
+ # rubocop dependencies...
17
+ gem 'rubocop', '~> 1.55'
18
+ gem 'rubocop-performance', '~> 1.18'
19
+ gem 'rubocop-rspec', '~> 2.22'
20
+ gem 'simplecov', '~> 0.16'
21
+ gem 'simplecov-cobertura'
22
+ gem 'vcr', '~> 6.0'
23
+ end
data/README.md CHANGED
@@ -1,77 +1,75 @@
1
- # html-to
2
- # install
3
- ``` ruby
4
- gem 'html_to'
5
- ```
6
- And also you need headless browser chrome
1
+ [![codecov](https://codecov.io/gh/Vchekryzhov/html-to/graph/badge.svg?token=27NK3S64MS)](https://codecov.io/gh/Vchekryzhov/html-to)
2
+ [![build](https://github.com/vchekryzhov/html-to/actions/workflows/ruby.yml/badge.svg)](https://github.com/vchekryzhov/html-to/actions/workflows/ruby.yml/badge.svg)
3
+ [![Gem Version](https://img.shields.io/gem/v/html_to.svg)](https://rubygems.org/gems/html_to)
4
+
5
+ # HtmlTo 🔥
6
+
7
+ HtmlTo is a gem for Rails that allows you to generate images from an HTML file.💡
8
+
9
+ ## 📋 Table of Contents
10
+
11
+ - [Installation](#Installation)🚀
12
+ - [Usage](#basic-usage) 📖
13
+ - [Advanced usage](#advanced-usage) 🧰
14
+
15
+
16
+ ## Installation
17
+
18
+ You need to have Chrome or Chromium installed 🛠️
19
+
7
20
 
8
21
  Ubuntu:
9
22
  ``` bash
10
23
  sudo apt install -y chromium-browser
11
24
  ```
12
-
13
25
  Debian:
14
26
  ```bash
15
27
  apt-get install chromium chromium-l10n
16
28
  ```
17
-
18
- # Get Started
19
- ### Prepare your model
20
- 1) do migrate string field for uploader
21
-
22
- and add start to your model, what you want use
23
- ``` ruby
24
- @@share_uploader = "share_image"
25
- @@share_template = 'share/post'
26
- include HtmlTo
29
+ add gem to your gemfile
30
+ ```ruby
31
+ gem 'html_to'
32
+ ```
33
+ copy example serializer with
34
+ ```bash
35
+ rails generate html_to:install
27
36
  ```
28
37
 
29
- ### creating template file
30
-
31
- you need create, on path ```@@share_template``` how example share/post will be ```app/views/share/post.html.erb```
32
-
33
- ######template file example:
34
- ``` html
35
- <!DOCTYPE html>
36
- <html lang="en">
37
- <head>
38
- <meta charset="UTF-8">
39
- <title>Title</title>
40
- <style>
41
-
42
- body {
43
- margin: 0;
44
- }
45
- .image {
46
- background-size: cover;
47
- position: absolute;
48
- float: left;
49
- top: 0px;
50
- width: 1200px;
51
- height: 630px;
52
- object-fit: y-repeat;
38
+ ### optional
39
+ for set path to chromium executable
40
+ ```ruby
41
+ #confg/initializers/html_to.rb
42
+ HtmlTo::Configuration.config do |config|
43
+ config.chromium_path = './path-to-executable'
44
+ end
45
+ ```
53
46
 
54
- }
55
- .description{
56
- position: absolute;
57
- font-size: 48px;
58
- z-index: 1;
59
- }
47
+ ## Basic usage
48
+ Add to your model 📖
60
49
 
61
- </style>
62
- </head>
63
- <body>
64
- <div class="root">
65
- <img class='image' src="https://images.unsplash.com/photo-1593642702821-c8da6771f0c6?ixid=MXwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1489&q=80">
66
- <p class="description">
67
- <%=obj.attributes%>
68
- </p>
69
- </div>
70
- </body>
71
- </html>
50
+ ```ruby
51
+ include HtmlTo
52
+ html_to HtmlToSerializer
53
+ ```
54
+ Now after save your model new image will generated and attached to ```meta_image``` in your model
72
55
 
56
+ ## Advanced usage
57
+ available options for customizations 🧰
58
+ ```ruby
59
+ html_to HtmlTo::DummySerializer, image_name: :my_image, template: :image
73
60
  ```
74
- In your template file you has access to your object via @obj
61
+ | option | descriotions | default |
62
+ |--------------------|--------------------------------------------|------------|
63
+ | `image_name` | name of attachment | meta_image |
64
+ | `template` | HTML template | circle |
65
+ | `synchronous` | Run image generation job not in background | false |
66
+ | `skip_auto_update` | skip auto update after save | false |
67
+ | `width` | width of image | 1200 |
68
+ | `height` | height of image | 630 |
75
69
 
76
- ###### Assets, font, etc
77
- Headless browser will be start from Rails public path, all local assets should be access in the public folder.
70
+ ### template customization
71
+ there are two templates available `circle` and `image` for copy to your project:
72
+ ```bash
73
+ rails generate html_to:copy_template
74
+ ```
75
+ you can add your own template to `app/views/html_to/*`
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require 'rake'
2
+ begin
3
+ require 'bundler/setup'
4
+ Bundler::GemHelper.install_tasks
5
+ rescue LoadError
6
+ puts 'although not required, bundler is recommended for running the tests'
7
+ end
8
+ task default: :spec
9
+ require 'rspec/core/rake_task'
10
+ RSpec::Core::RakeTask.new(:spec)
11
+
12
+ require 'rubocop/rake_task'
13
+ RuboCop::RakeTask.new do |task|
14
+ task.requires << 'rubocop-performance'
15
+ task.requires << 'rubocop-rspec'
16
+ end
data/html_to.gemspec CHANGED
@@ -1,16 +1,31 @@
1
- $:.push File.expand_path("../lib", __FILE__)
1
+ require File.expand_path('lib/html_to/version', __dir__)
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = 'html_to'
5
- s.version = '0.7.2'
6
- s.date = '2021-04-07'
7
- s.summary = 'Html-To transforms html to other format'
8
- s.description = 'Simple gem for transforms html page through chromium headless.'
9
- s.author = 'Chekryzhov Viktor'
10
- s.email = 'chekryzhov@charmerstudio.com'
11
- s.homepage = 'https://github.com/Vchekryzhov/html-to'
12
- s.license = 'MIT'
13
- s.files = `git ls-files`.split("\n")
14
- s.add_dependency 'sidekiq'
15
- s.add_dependency 'carrierwave'
4
+ s.name = 'html_to'
5
+ s.required_ruby_version = '>= 2.7'
6
+ s.version = HtmlTo::VERSION
7
+ s.summary = 'Html-To transforms html to image'
8
+ s.description = 'Simple gem for transforms html page through chromium headless to image.'
9
+ s.author = 'Chekryzhov Viktor'
10
+ s.email = 'vchekryzhov@ya.ru'
11
+ s.homepage = 'https://github.com/Vchekryzhov/html-to'
12
+ s.license = 'MIT'
13
+ s.files = Dir['README.md', 'LICENSE',
14
+ 'CHANGELOG.md', 'lib/**/*.rb',
15
+ 'lib/**/*.html.erb',
16
+ 'html_to.gemspec', '.github/*.md',
17
+ 'Gemfile', 'Rakefile']
18
+ s.extra_rdoc_files = ['README.md']
19
+
20
+ s.add_dependency 'activejob', '>= 5'
21
+ s.add_dependency 'activestorage', '>= 5'
22
+ s.add_dependency 'english'
23
+ s.add_dependency 'erb'
24
+
25
+ if ENV['TEST_RAILS_VERSION'].nil?
26
+ s.add_development_dependency 'rails', '~> 7.0.6'
27
+ else
28
+ s.add_development_dependency 'rails', ENV['TEST_RAILS_VERSION'].to_s
29
+ end
30
+ s.metadata['rubygems_mfa_required'] = 'false'
16
31
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module HtmlTo
6
+ module Generators
7
+ class CopyTemplateGenerator < Rails::Generators::Base
8
+ source_root File.expand_path('../../views/html_to', __dir__)
9
+
10
+ desc 'Copy templates'
11
+
12
+ def copy_initializer
13
+ copy_file 'image.html.erb', 'app/views/html_to/image.html.erb'
14
+ copy_file 'circle.html.erb', 'app/views/html_to/circle.html.erb'
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module HtmlTo
6
+ module Generators
7
+ class InstallGenerator < Rails::Generators::Base
8
+ source_root File.expand_path('./templates', __dir__)
9
+
10
+ desc 'Copy example of serializer to your app'
11
+
12
+ def copy_initializer
13
+ copy_file 'html_to_serializer.rb', 'app/serializers/html_to_serializer.rb'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ class HtmlToSerializer < HtmlTo::Serializer
2
+ # you can have access to serialized record via object
3
+
4
+ def title
5
+ 'object.title'
6
+ end
7
+
8
+ def background_image
9
+ 'https://images.unsplash.com/photo-1593642702821-c8da6771f0c6?ixid=MXwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&q=80'
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ require 'English'
2
+ module HtmlTo
3
+ module Chromium
4
+ def self.execute_path
5
+ if Configuration.chromium_path.present?
6
+ raise ArgumentError, "html_to error: not found chromium by path #{Configuration.chromium_path}" unless File.exist? Configuration.chromium_path
7
+
8
+ return Configuration.chromium_path
9
+ end
10
+
11
+ path = if /darwin/.match?(RbConfig::CONFIG['host_os'])
12
+ "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
13
+ elsif /linux/.match?(RbConfig::CONFIG['host_os'])
14
+ release = %x(lsb_release -i -s)
15
+ %x(which chromium-browser)
16
+ if release == "Debian\n"
17
+ which_path = %x(which chromium)
18
+ raise StandardError, "html_to error: You don't have chromium, please do apt install chromium" unless $CHILD_STATUS.success?
19
+
20
+ else
21
+ which_path = %x(which chromium-browser)
22
+ raise StandardError, "html_to error: You don't have chromium, please do apt install chromium-browser" unless $CHILD_STATUS.success?
23
+ end
24
+ which_path
25
+ else
26
+ raise StandardError, "html_to error host os don't detected"
27
+ end
28
+ raise StandardError, 'html_to error: chromium executable path not found' if path.blank?
29
+
30
+ path.delete("\n")
31
+ end
32
+
33
+ def self.version
34
+ %x(#{execute_path} --version)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ module HtmlTo
2
+ module Configuration
3
+ class << self
4
+ attr_accessor :chromium_path
5
+
6
+ def config
7
+ yield self
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,86 @@
1
+ require 'fileutils'
2
+ require_relative 'chromium'
3
+ require 'erb'
4
+
5
+ class HtmlTo::ImageGenerate
6
+ include HtmlTo::Chromium
7
+ def call(record, serializer, options)
8
+ generate_template(record, serializer, options[:template], options[:width], options[:height])
9
+ take_screenshot(options[:width], options[:height])
10
+ attach_image(record, options[:image_name])
11
+ rescue StandardError
12
+ raise
13
+ ensure
14
+ FileUtils.rm_f(html_file_path)
15
+ FileUtils.rm_f(optimize_screenshot) if optimize_screenshot
16
+ FileUtils.rm_f(screenshot_file_path)
17
+ end
18
+
19
+ def generate_template(record, serializer, template, width, height)
20
+ object = serializer.constantize.new(record)
21
+ html = File.open(template) do |f|
22
+ ERB.new(f.read).result(binding)
23
+ end
24
+ File.write(html_file_path, html)
25
+ end
26
+
27
+ def take_screenshot(width, height)
28
+ cmd = <<~BASH.chomp
29
+ #{HtmlTo::Chromium.execute_path} \
30
+ --headless \
31
+ --screenshot=#{screenshot_file_path} \
32
+ --window-size=#{width},#{height} \
33
+ --disable-gpu \
34
+ --disable-features=NetworkService #{html_file_path}
35
+ BASH
36
+
37
+ %x(#{cmd})
38
+ raise StandardError, "html_to error result = #{$CHILD_STATUS}; command = #{cmd}" unless chromium_run_success?
39
+ end
40
+
41
+ def attach_image(record, image_name)
42
+ record.html_to_skip_meta_image_generate = true
43
+ record.send(image_name).purge
44
+ record.send(image_name).attach(io: optimize_screenshot, filename: optimize_screenshot, content_type: 'image/png')
45
+ return unless optimize_screenshot
46
+
47
+ optimize_screenshot.close
48
+ end
49
+
50
+ def html_file_path
51
+ @html_file_path ||= Rails.root.join('tmp').join("#{SecureRandom.urlsafe_base64.downcase}.html")
52
+ end
53
+
54
+ def screenshot_file_path
55
+ @screenshot_file_path ||= Rails.root.join('tmp').join("#{SecureRandom.urlsafe_base64.downcase}.png")
56
+ end
57
+
58
+ def optimize_screenshot
59
+ return nil unless File.exist?(screenshot_file_path)
60
+
61
+ @optimize_screenshot ||= if image_processing_installed?
62
+ ImageProcessing::MiniMagick
63
+ .source(screenshot_file_path)
64
+ .convert('jpg')
65
+ .saver(quality: 85)
66
+ .call
67
+ else
68
+ File.open(screenshot_file_path)
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def chromium_run_success?
75
+ $CHILD_STATUS.success?
76
+ end
77
+
78
+ def image_processing_installed?
79
+ Gem::Specification.find_by_name('image_processing')
80
+ rescue Gem::LoadError
81
+ puts '[html-to] image will not processing because gem image_processing is not installed'
82
+ false
83
+ else
84
+ true
85
+ end
86
+ end
@@ -0,0 +1,13 @@
1
+ module HtmlTo
2
+ class MetaImageGenerateJob < ::ActiveJob::Base
3
+ queue_as :default
4
+ def perform(id, class_name, serializer, options)
5
+ record = class_name.constantize.find(id)
6
+ generator.call(record, serializer, options)
7
+ end
8
+
9
+ def generator
10
+ HtmlTo::ImageGenerate.new
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class HtmlTo::Serializer
2
+ attr_reader :object
3
+
4
+ def initialize(object)
5
+ @object = object
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ module HtmlTo
2
+ VERSION = '1.1.1'.freeze
3
+ public_constant :VERSION
4
+ end
data/lib/html_to.rb CHANGED
@@ -1,22 +1,143 @@
1
1
  module HtmlTo
2
- extend ActiveSupport::Concern
3
- require 'carrierwave'
4
- require 'html_to/html_headless.rb'
5
- require 'html_to/sharing_image_generate.rb'
6
- require 'html_to/share_uploader.rb'
7
- included do
8
- after_commit :share_image_generate, unless: :skip_share_image_generate
9
- attr_accessor :skip_share_image_generate
10
-
11
-
12
- raise 'Message from html_to: @@share_uploader not present' if class_variable_get(:@@share_uploader).nil?
13
- raise 'Message from html_to: @@share_template not present' if class_variable_get(:@@share_template).nil?
14
- raise "Message from html_to: share template file #{Rails.root.join('app/views').join(class_variable_get(:@@share_template)+'.html.erb')} not exist" if !File.exist?(Rails.root.join('app/views').join(class_variable_get(:@@share_template)+".html.erb"))
15
- mount_uploader class_variable_get(:@@share_uploader), -> { class_variable_get(:@@override_uploader) rescue HtmlTo::ShareUploader }.call
2
+ require_relative 'html_to/image_generate'
3
+ require_relative 'html_to/meta_image_generate_job'
4
+ require_relative 'html_to/configuration'
5
+ require_relative 'html_to/chromium'
6
+ require_relative 'html_to/serializer'
7
+ class HtmlToImageSettings
8
+ OPTIONS = %i[
9
+ template width height image_name
10
+ ].freeze
11
+ DEFAULT_OPTIONS = {
12
+ template: :circle,
13
+ width: 1200,
14
+ height: 630,
15
+ image_name: :meta_image
16
+ }.freeze
17
+ attr_reader(*OPTIONS, :serializer)
18
+
19
+ def initialize(klass, serializer, options, &block)
20
+ @klass = klass
21
+ @options = options
22
+ validate_options
23
+ @serializer = serializer.to_s
24
+ setup_options
25
+ instance_exec(&block) if block_given?
26
+ end
27
+
28
+ def validate_options
29
+ @options.each_key { |opt| raise ArgumentError, "html_to error #{opt} is unknown option" unless OPTIONS.include? opt }
30
+ end
31
+
32
+ def setup_options
33
+ OPTIONS.each do |k|
34
+ instance_variable_set("@#{k}", @options[k] || DEFAULT_OPTIONS[k])
35
+ end
36
+ find_template_path!
37
+ end
38
+
39
+ def additional_images
40
+ @additional_images || {}
41
+ end
42
+
43
+ def add_image(image_name, serializer, options = {})
44
+ @additional_images ||= {}
45
+ options[:image_name] = image_name
46
+ @klass.class_eval do
47
+ has_one_attached image_name
48
+ end
49
+ @additional_images[image_name] = HtmlToImageSettings.new(@klass, serializer, options)
50
+ end
51
+
52
+ def find_template_path!
53
+ user_template = Rails.root.join('app/views/html_to').join("#{template}.html.erb")
54
+ return user_template.to_s if File.file? user_template
55
+
56
+ gem_template = File.expand_path("views/html_to/#{template}.html.erb", __dir__)
57
+
58
+ return gem_template.to_s if File.file? gem_template
59
+
60
+ raise ArgumentError, "html_to error Template file not found #{user_template} #{gem_template} "
61
+ end
16
62
  end
63
+ class << self
64
+ attr_reader :included_in
17
65
 
18
- def share_image_generate
19
- SharingImageGenerate.perform_async(id, self.class.to_s)
66
+ def included(klass)
67
+ @included_in ||= []
68
+ @included_in << klass
69
+ @included_in.uniq!
70
+
71
+ klass.class_eval do
72
+ extend ClassMethods
73
+ include InstanceMethods
74
+ end
75
+ end
20
76
  end
21
77
 
78
+ module ClassMethods
79
+ def self.extended(base)
80
+ class << base
81
+ alias_method :create_meta_images!, :html_to_create_meta_images! unless method_defined? :create_meta_images!
82
+ end
83
+ base.cattr_accessor :html_to_image_settings
84
+ end
85
+
86
+ def html_to_create_meta_images!
87
+ all.each(&:html_to_create_meta_image!)
88
+ end
89
+
90
+ def html_to(serializer, options = {}, &block)
91
+ after_validation :html_to_mark_synchronous if options.delete(:synchronous) == true && respond_to?(:after_validation)
92
+ after_validation :html_to_mark_skip_meta_image_generate if options.delete(:skip_auto_update) == true && respond_to?(:after_validation)
93
+
94
+ self.html_to_image_settings = HtmlToImageSettings.new(self, serializer, options, &block)
95
+ class_eval do
96
+ has_one_attached options[:image_name] || html_to_image_settings.image_name
97
+ end
98
+ end
99
+ end
100
+
101
+ module InstanceMethods
102
+ def self.included(base)
103
+ base.attr_accessor :html_to_skip_meta_image_generate
104
+ base.instance_eval do
105
+ alias_method :create_meta_image!, :html_to_create_meta_image! unless method_defined? :create_meta_images!
106
+ end
107
+ base.after_commit :html_to_create_meta_image!, unless: :html_to_skip_meta_image_generate
108
+ end
109
+
110
+ def html_to_create_meta_image!
111
+ share_images_settings = [self.class.html_to_image_settings, *self.class.html_to_image_settings.additional_images.values].flatten
112
+ share_images_settings.each do |image_settings|
113
+ generator_args = [
114
+ id, self.class.name, image_settings.serializer, {
115
+ image_name: image_settings.image_name,
116
+ width: image_settings.width,
117
+ height: image_settings.height,
118
+ template: image_settings.find_template_path!
119
+ }
120
+ ]
121
+ if html_to_synchronous?
122
+ MetaImageGenerateJob.perform_now(*generator_args)
123
+ else
124
+ MetaImageGenerateJob.perform_later(*generator_args)
125
+ end
126
+ end
127
+ end
128
+
129
+ private
130
+
131
+ def html_to_mark_synchronous
132
+ @html_to_synchronous = true
133
+ end
134
+
135
+ def html_to_mark_skip_meta_image_generate
136
+ @html_to_skip_meta_image_generate = true
137
+ end
138
+
139
+ def html_to_synchronous?
140
+ @html_to_synchronous
141
+ end
142
+ end
22
143
  end
@@ -0,0 +1,46 @@
1
+
2
+ <html>
3
+ <body>
4
+ <div class="container">
5
+ <div>
6
+ <svg viewBox="0 0 100 100">
7
+ <defs>
8
+ <path id="circle"
9
+ d="
10
+ M 50, 50
11
+ m -37, 0
12
+ a 37,37 0 1,1 74,0
13
+ a 37,37 0 1,1 -74,0"/>
14
+ </defs>
15
+ <text font-size="18">
16
+ <textPath xlink:href="#circle">
17
+ <%= object.title %>
18
+ </textPath>
19
+ </text>
20
+ </svg>
21
+ </div>
22
+ </div>
23
+ </body>
24
+ <style>
25
+ svg {
26
+ fill: currentColor;
27
+ height: auto;
28
+ max-width: 66vmin;
29
+ transform-origin: center;
30
+ width: 100%;
31
+ }
32
+ .container {
33
+ display: flex;
34
+ justify-content: center;
35
+ align-items: center;
36
+ width: 1200px;
37
+ height: 630px;
38
+ }
39
+ body {
40
+ margin: 0;
41
+ }
42
+
43
+
44
+ </style>
45
+ </html>
46
+
@@ -0,0 +1,46 @@
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <title>Title</title>
5
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Martian Mono">
6
+ <style>
7
+
8
+ body {
9
+ margin: 0;
10
+ font-family: "Martian Mono", sans-serif;
11
+ }
12
+ .image {
13
+ width: <%=width%>px;
14
+ height: <%=height%>px;
15
+ position: absolute;
16
+ float: left;
17
+ object-fit: cover;
18
+ }
19
+ .description{
20
+ position: absolute;
21
+ color: white;
22
+ z-index: 1;
23
+ font-size: 72px;
24
+ margin-top: 10%;
25
+ margin-left: 5%;
26
+ }
27
+ .root{
28
+ background-color: black;
29
+ width: <%=width%>px;
30
+ height: <%=height%>px;
31
+ }
32
+ .image {
33
+ opacity: 0.5;
34
+ }
35
+
36
+ </style>
37
+ </head>
38
+ <body>
39
+ <div class="root">
40
+ <img class='image' src="<%=object.background_image %>" alt="img">
41
+ <p class="description">
42
+ <%=object.title%>
43
+ </p>
44
+ </div>
45
+ </body>
46
+ </html>
metadata CHANGED
@@ -1,17 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html_to
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chekryzhov Viktor
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-07 00:00:00.000000000 Z
11
+ date: 2023-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: sidekiq
14
+ name: activejob
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activestorage
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: english
15
43
  requirement: !ruby/object:Gem::Requirement
16
44
  requirements:
17
45
  - - ">="
@@ -25,7 +53,7 @@ dependencies:
25
53
  - !ruby/object:Gem::Version
26
54
  version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
- name: carrierwave
56
+ name: erb
29
57
  requirement: !ruby/object:Gem::Requirement
30
58
  requirements:
31
59
  - - ">="
@@ -38,26 +66,53 @@ dependencies:
38
66
  - - ">="
39
67
  - !ruby/object:Gem::Version
40
68
  version: '0'
41
- description: Simple gem for transforms html page through chromium headless.
42
- email: chekryzhov@charmerstudio.com
69
+ - !ruby/object:Gem::Dependency
70
+ name: rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 7.0.6
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 7.0.6
83
+ description: Simple gem for transforms html page through chromium headless to image.
84
+ email: vchekryzhov@ya.ru
43
85
  executables: []
44
86
  extensions: []
45
- extra_rdoc_files: []
87
+ extra_rdoc_files:
88
+ - README.md
46
89
  files:
47
- - ".gitignore"
90
+ - ".github/CODE_OF_CONDUCT.md"
91
+ - ".github/CONTRIBUTING.md"
92
+ - ".github/pull_request_template.md"
93
+ - CHANGELOG.md
94
+ - Gemfile
48
95
  - LICENSE
49
96
  - README.md
50
- - gemfile
97
+ - Rakefile
51
98
  - html_to.gemspec
99
+ - lib/generators/html_to/copy_template_generator.rb
100
+ - lib/generators/html_to/install_generator.rb
101
+ - lib/generators/html_to/templates/html_to_serializer.rb
52
102
  - lib/html_to.rb
53
- - lib/html_to/chromium_controll.rb
54
- - lib/html_to/html_headless.rb
55
- - lib/html_to/share_uploader.rb
56
- - lib/html_to/sharing_image_generate.rb
103
+ - lib/html_to/chromium.rb
104
+ - lib/html_to/configuration.rb
105
+ - lib/html_to/image_generate.rb
106
+ - lib/html_to/meta_image_generate_job.rb
107
+ - lib/html_to/serializer.rb
108
+ - lib/html_to/version.rb
109
+ - lib/views/html_to/circle.html.erb
110
+ - lib/views/html_to/image.html.erb
57
111
  homepage: https://github.com/Vchekryzhov/html-to
58
112
  licenses:
59
113
  - MIT
60
- metadata: {}
114
+ metadata:
115
+ rubygems_mfa_required: 'false'
61
116
  post_install_message:
62
117
  rdoc_options: []
63
118
  require_paths:
@@ -66,15 +121,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
66
121
  requirements:
67
122
  - - ">="
68
123
  - !ruby/object:Gem::Version
69
- version: '0'
124
+ version: '2.7'
70
125
  required_rubygems_version: !ruby/object:Gem::Requirement
71
126
  requirements:
72
127
  - - ">="
73
128
  - !ruby/object:Gem::Version
74
129
  version: '0'
75
130
  requirements: []
76
- rubygems_version: 3.1.2
131
+ rubygems_version: 3.1.6
77
132
  signing_key:
78
133
  specification_version: 4
79
- summary: Html-To transforms html to other format
134
+ summary: Html-To transforms html to image
80
135
  test_files: []
data/.gitignore DELETED
@@ -1,49 +0,0 @@
1
- *.rbc
2
- capybara-*.html
3
- .rspec
4
- /log
5
- /tmp
6
- /db/*.sqlite3
7
- /db/*.sqlite3-journal
8
- /public/system
9
- /coverage/
10
- /spec/tmp
11
- *.orig
12
- rerun.txt
13
- pickle-email-*.html
14
-
15
- # TODO Comment out this rule if you are OK with secrets being uploaded to the repo
16
- config/initializers/secret_token.rb
17
- config/master.key
18
-
19
- # Only include if you have production secrets in this file, which is no longer a Rails default
20
- # config/secrets.yml
21
-
22
- # dotenv
23
- # TODO Comment out this rule if environment variables can be committed
24
- .env
25
-
26
- ## Environment normalization:
27
- /.bundle
28
- /vendor/bundle
29
-
30
- # these should all be checked in to normalize the environment:
31
- # Gemfile.lock, .ruby-version, .ruby-gemset
32
-
33
- # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
- .rvmrc
35
-
36
- # if using bower-rails ignore default bower_components path bower.json files
37
- /vendor/assets/bower_components
38
- *.bowerrc
39
- bower.json
40
-
41
- # Ignore pow environment settings
42
- .powenv
43
-
44
- # Ignore Byebug command history file.
45
- .byebug_history
46
-
47
- # Ignore node_modules
48
- node_modules/
49
-
data/gemfile DELETED
@@ -1,3 +0,0 @@
1
- # Gemfile
2
- source 'https://rubygems.org'
3
- ruby '2.3.3'
@@ -1,20 +0,0 @@
1
- module HtmlTo::ChromiumControll
2
- def chrome
3
- if RbConfig::CONFIG['host_os'] =~ /darwin/
4
- "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
5
- elsif RbConfig::CONFIG['host_os'] =~ /linux/
6
- release = IO.popen("lsb_release -i -s").read
7
- if release == "Debian\n"
8
- `dpkg -s chromium`
9
- raise "html_to message: You don't have chromium, please do apt install chromium"if !$?.success?
10
- 'chromium'
11
- else
12
- `dpkg -s chromium-browser`
13
- raise "html_to message: You don't have chromium, please do apt install chromium"if !$?.success?
14
- 'chromium-browser'
15
- end
16
- else
17
- raise StandardError.new "host os don't detected"
18
- end
19
- end
20
- end
@@ -1,41 +0,0 @@
1
- class HtmlTo::HtmlHeadless
2
- require 'fileutils'
3
- require 'html_to/chromium_controll.rb'
4
- include HtmlTo::ChromiumControll
5
-
6
- def to_image(obj, width=1200, height=630)
7
-
8
- width = obj.class.class_variable_get(:@@html_to_width) if obj.class.class_variable_defined?(:@@html_to_width)
9
- height = obj.class.class_variable_get(:@@html_to_height) if obj.class.class_variable_defined?(:@@html_to_height)
10
-
11
- @template = File.read(Rails.root.join('app/views').join(obj.class.class_variable_get(:@@share_template)+".html.erb"))
12
- html = ERB.new(@template.html_safe).result(binding)
13
- File.open(html_file_path, 'w+') {|f| f.write(html) }
14
- begin
15
- cmd = "'#{chrome}'
16
- --headless
17
- --screenshot=#{screenshot_file_path}
18
- --window-size=#{width},#{height}
19
- --disable-gpu
20
- --disable-features=NetworkService #{html_file_path}".gsub("\n",' ')
21
- `#{cmd}`
22
- if $?.success?
23
- obj.skip_share_image_generate = true
24
- obj.send("#{obj.class.class_variable_get(:@@share_uploader)}=", File.open(screenshot_file_path))
25
- obj.save
26
- else
27
- raise "result = #{$?}; command = #{cmd}"
28
- end
29
- ensure
30
- FileUtils.rm(html_file_path)
31
- FileUtils.rm(screenshot_file_path)
32
- end
33
- end
34
-
35
- def html_file_path
36
- @path ||= Rails.public_path.join(SecureRandom.urlsafe_base64.downcase + ".html")
37
- end
38
- def screenshot_file_path
39
- @screenshot_file_path ||= Rails.public_path.join(SecureRandom.urlsafe_base64.downcase + ".png")
40
- end
41
- end
@@ -1,14 +0,0 @@
1
- class HtmlTo::ShareUploader < CarrierWave::Uploader::Base
2
- include CarrierWave::MiniMagick
3
-
4
- # raise 'Message from html_to: Rails.application.config.asset_host not present' if Rails.application.config.asset_host.nil?
5
-
6
- def store_dir
7
- "storage/#{model.class.base_class.name.underscore}/#{model.id}/share"
8
- end
9
-
10
- def url
11
- "#{Rails.application.config.asset_host}#{super}"
12
- end
13
- process resize_to_limit: [1200, 630]
14
- end
@@ -1,11 +0,0 @@
1
- class HtmlTo::SharingImageGenerate
2
- require 'erb'
3
- require 'sidekiq'
4
- include Sidekiq::Worker
5
- sidekiq_options queue: 'default'
6
-
7
- def perform(id, class_name)
8
- @obj = class_name.constantize.find(id)
9
- HtmlTo::HtmlHeadless.new.to_image(@obj)
10
- end
11
- end