Skip to content

Commit

Permalink
Extract logic to classes
Browse files Browse the repository at this point in the history
  • Loading branch information
ahangarha committed Jul 2, 2023
1 parent 95afc56 commit a531bfc
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 31 deletions.
45 changes: 14 additions & 31 deletions lib/bidify.rb
Original file line number Diff line number Diff line change
@@ -1,43 +1,26 @@
# frozen_string_literal: true

require 'nokogiri'
require 'bidify/html_string_bidifier'

# Bidify applies `dir="auto"` to the given html string
# == Bidify module
#
# ### Example:
# The namespace and helper methods for bidiying HTML contents
#
# bidified_html = Bidify.bidify(regular_html)
# == Example:
#
# bidified_html = Bidify.bidify_html_string(regular_html)
module Bidify
@bidifiable_tags = %w[div h1 h2 h3 h4 h5 h6 p ul ol blockquote]
DEFAULT_BIDIFIABLE_TAGS = %w[div h1 h2 h3 h4 h5 h6 p ul ol blockquote].freeze

class << self
###
# bidify applies dir="auto" to the given html string
def bidify(input_html)
html_node = Nokogiri::HTML.fragment(input_html)
bidify_recursively(html_node, { root: true })

html_node.to_s
end

private

def bidify_recursively(html_node, options = {})
seen_the_first_bidifiable_element = false

html_node.children.each do |child_node|
bidify_recursively(child_node)

if (options[:root] || seen_the_first_bidifiable_element) && @bidifiable_tags.include?(child_node.name)
child_node.set_attribute('dir', 'auto')
end

seen_the_first_bidifiable_element = true if actual_content?(child_node)
end
end

def actual_content?(node)
node.element? || (node.text? && !node.blank?)
# Applies dir="auto" to the given html string with default configuration
#
# @param [String] html_string a stringified HTML content
# @return [String] Bidified version of the input string
#
def bidify_html_string(html_string)
Bidify::HtmlStringBidifier.new.apply(html_string)
end
end
end
38 changes: 38 additions & 0 deletions lib/bidify/bidifier.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true

module Bidify
# Super class for custom bidifiers
class Bidifier
def initialize
configure
end

def apply
raise NotImplementedError
end

private

def configure
@bidifiable_tags = DEFAULT_BIDIFIABLE_TAGS.dup
end

def bidify_recursively(html_node, options = {})
seen_the_first_bidifiable_element = false

html_node.children.each do |child_node|
bidify_recursively(child_node)

if (options[:root] || seen_the_first_bidifiable_element) && @bidifiable_tags.include?(child_node.name)
child_node.set_attribute('dir', 'auto')
end

seen_the_first_bidifiable_element = true if actual_content?(child_node)
end
end

def actual_content?(node)
node.element? || (node.text? && !node.blank?)
end
end
end
31 changes: 31 additions & 0 deletions lib/bidify/html_string_bidifier.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require 'nokogiri'
require_relative 'bidifier'

module Bidify
###
# Bidifying html input as string
#
# == Example Usage
#
# Here's an example of how to use the class:
#
# bidifier = HtmlStringBidifier.new
# bidifier.apply("<p>text</p>")
#
class HtmlStringBidifier < Bidifier
###
# Applies dir="auto" to the given html string with default configuration
#
# @param [String] html_string a stringified HTML content
# @return [String] Bidified version of the input string
#
def apply(html_input)
html_node = Nokogiri::HTML.fragment(html_input)
bidify_recursively(html_node, { root: true })

html_node.to_s
end
end
end

0 comments on commit a531bfc

Please sign in to comment.