diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml new file mode 100644 index 0000000..9fdb3d1 --- /dev/null +++ b/.github/workflows/rubocop.yml @@ -0,0 +1,24 @@ +name: RuboCop + +on: + pull_request: + +permissions: + contents: read + +jobs: + rubocop: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + # rmagick compiles against ImageMagick during bundle install + - name: Install ImageMagick headers + run: sudo apt-get update && sudo apt-get install -y libmagickwand-dev + + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + + - name: Run RuboCop + run: bundle exec rubocop diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..94fb538 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,7 @@ +AllCops: + TargetRubyVersion: 4.0 + NewCops: enable + SuggestExtensions: false + +Style/StringLiterals: + EnforcedStyle: double_quotes diff --git a/.ruby-version b/.ruby-version index 15a2799..fcdb2e1 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.0 +4.0.0 diff --git a/Gemfile b/Gemfile index 1415146..cb0319b 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,11 @@ +# frozen_string_literal: true + source "https://rubygems.org" +gem "csv" gem "rmagick" gem "rubyzip" -gem "csv" + +group :development do + gem "rubocop", require: false +end diff --git a/Gemfile.lock b/Gemfile.lock index 8918779..00adc82 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,22 +1,54 @@ GEM remote: https://rubygems.org/ specs: + ast (2.4.3) csv (3.2.8) + json (3.0.2) + language_server-protocol (3.17.0.6) + lint_roller (1.1.0) observer (0.1.2) + parallel (2.2.0) + parser (3.3.12.0) + ast (~> 2.4.1) + racc pkg-config (1.5.6) + prism (1.9.0) + racc (1.8.1) + rainbow (3.1.1) + regexp_parser (2.13.1) rmagick (6.0.0) observer (~> 0.1) pkg-config (~> 1.4) + rubocop (1.91.0) + json (>= 2.3) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) + parallel (>= 1.10) + parser (>= 3.3.0.2) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.49.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.50.0) + parser (>= 3.3.7.2) + prism (~> 1.7) + ruby-progressbar (1.13.0) rubyzip (3.4.0) + unicode-display_width (3.3.0) + unicode-emoji (~> 4.3) + unicode-emoji (4.3.0) PLATFORMS arm64-darwin-23 ruby + x86_64-linux DEPENDENCIES csv rmagick + rubocop rubyzip BUNDLED WITH - 2.5.7 + 4.0.21 diff --git a/README.md b/README.md index 5cd260c..62608e3 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Takes a Gleam export of media and adds captions with the owner. # Step 0: Install required tools ## Step 0.1: -Install Ruby, Bundler. I use [rbenv](https://github.com/rbenv/rbenv) to install Ruby 3.3.0 specifically. +Install Ruby, Bundler. I use [rbenv](https://github.com/rbenv/rbenv) to install Ruby 4.0.0 specifically. ## Step 0.2: Run `bundle install` diff --git a/run.rb b/run.rb index f5ab7a3..fb28f46 100755 --- a/run.rb +++ b/run.rb @@ -1,8 +1,51 @@ +# frozen_string_literal: true + require "rmagick" require "zip" require "csv" -include Magick +CAPTION_PADDING = 26 + +def text_draw(font_size) + draw = Magick::Draw.new + draw.pointsize = font_size + draw +end + +def wrap_text(draw, image, text, max_width) + return text if draw.get_type_metrics(image, text).width <= max_width + + text.split.each_with_object([""]) do |word, lines| + test_line = "#{lines.last}#{word} " + if draw.get_type_metrics(image, test_line).width > max_width + lines << "#{word} " + else + lines[-1] = test_line + end + end.join("\n") +end + +def draw_background(image, height) + draw = Magick::Draw.new + draw.fill = "#000000" + draw.fill_opacity(0.3) + draw.rectangle(0, image.rows - height, image.columns, image.rows) + draw.draw(image) +end + +def draw_lines(image, text, font_size, line_height, first_line_y) + draw = text_draw(font_size) + current_y = first_line_y + text.each_line do |line| + draw.fill_opacity(1) + draw.fill = "#ffffff" + + text_x = ((image.columns - draw.get_type_metrics(image, line).width) / 2) + CAPTION_PADDING + draw.annotate(image, 0, 0, text_x, current_y, line.strip) + current_y += line_height + end + draw.draw(image) +end zip_filename = ARGV[0] @@ -21,7 +64,7 @@ puts "Extracting files from #{zip_filename}..." Zip::File.open(zip_filename) do |zip_file| zip_file.each do |entry| - filename = entry.name.gsub(/.*\//, "") + filename = entry.name.gsub(%r{.*/}, "") puts "Extracting #{filename}..." next if filename == "" @@ -30,14 +73,14 @@ extract_path = File.join(extracted_dir, filename) begin entry.extract(extract_path) - rescue Zip::DestinationFileExistsError => e + rescue Zip::DestinationFileExistsError puts "Already existed." next end end end -csv_file = files.select {|f| f[/\.csv$/] }.last +csv_file = files.select { |f| f[/\.csv$/] }.last csv = CSV.open(File.join(extracted_dir, csv_file), headers: true) @@ -47,66 +90,25 @@ handle = row["Social Handle"] file_name = row["File name"] - caption = "#{text} - #{name} #{('(' + handle + ')') if handle}©" + caption = "#{text} - #{name} #{"(#{handle})" if handle}©" puts "Captioning... #{file_name} with #{caption}" image = Magick::ImageList.new(File.join(extracted_dir, file_name)).first - draw = Magick::Draw.new - - caption_padding = 26 font_size = image.rows / 30.0 line_height = font_size + 10 + max_text_width = image.columns - (CAPTION_PADDING * 2) - draw.pointsize = font_size - max_text_width = image.columns - (caption_padding * 2) - - metrics = draw.get_type_metrics(image, caption) - if metrics.width > max_text_width - words = caption.split(' ') - wrapped_text = '' - line = '' - words.each do |word| - test_line = line + word + ' ' - test_metrics = draw.get_type_metrics(image, test_line) - if test_metrics.width > max_text_width - wrapped_text += line + "\n" - line = word + ' ' - else - line = test_line - end - end - wrapped_text += line - else - wrapped_text = caption - end + wrapped_text = wrap_text(text_draw(font_size), image, caption, max_text_width) rows_of_text = wrapped_text.split("\n").count + caption_height = (rows_of_text * line_height) + (CAPTION_PADDING * 2) - caption_height = (rows_of_text * line_height) + (caption_padding * 2) rectangle_y = image.rows - caption_height + first_line_y = rectangle_y + CAPTION_PADDING + (line_height / 2) + (line_height / 4) # Fudge factor - draw.fill = '#000000' - draw.fill_opacity(0.3) - draw.rectangle(0, image.rows - caption_height, image.columns, image.rows) - draw.draw(image) - - draw = Magick::Draw.new - draw.pointsize = font_size - - current_y = rectangle_y + caption_padding + (line_height / 2) + (line_height / 4) # Fudge factor - wrapped_text.each_line do |line| - draw.fill_opacity(1) - draw.fill = "#ffffff" - - line_metrics = draw.get_type_metrics(image, line) - text_x = ((image.columns - line_metrics.width) / 2) + caption_padding - - draw.annotate(image, 0, 0, text_x, current_y, line.strip) - current_y += line_height - end - - draw.draw(image) + draw_background(image, caption_height) + draw_lines(image, wrapped_text, font_size, line_height, first_line_y) image.write(File.join(output_dir, file_name)) end