Last active
December 25, 2015 18:09
-
-
Save sj26/7018858 to your computer and use it in GitHub Desktop.
Fast HTML helpers using Nokogiri—pick and choose what you want
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Gem::Specification.new do |s| | |
s.name = 'nokogiri_html_helpers' | |
s.version = '0.1.4' | |
s.platform = Gem::Platform::RUBY | |
s.author = 'Samuel Cochran' | |
s.email = 'sj26@sj26.com' | |
s.homepage = 'https://gist.github.com/sj26/7018858' | |
s.summary = 'Fast HTML helpers using Nokogiri' | |
s.description = s.summary | |
s.license = 'MIT' | |
s.files = ['nokogiri_html_helpers.rb', 'strip_empty_block_html_helper.rb', 'truncate_html_helper.rb'] | |
s.test_files = ['strip_empty_block_html_helper_spec.rb', 'truncate_html_helper_spec.rb'] | |
s.require_path = '.' | |
s.add_dependency('nokogiri', ["~> 1.6.0"]) | |
s.add_development_dependency('rspec', ["~> 2.0"]) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module NokogiriHtmlHelpers | |
class Engine < Rails::Engine | |
def find_root_with_flag(*); File.expand_path("..", __FILE__); end | |
self.paths["app/helpers"] = "" | |
end if defined? Rails | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module StripEmptyBlockHtmlHelper | |
def strip_empty_block_html(html) | |
Nokogiri::HTML::DocumentFragment.parse(html).tap do |fragment| | |
fragment.traverse do |node| | |
if node.element? and node.description and node.description.block? and node.content.empty? | |
node.remove | |
end | |
end | |
end.to_html | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "./strip_empty_block_html_helper" | |
describe StripEmptyBlockHtmlHelper do | |
include StripEmptyBlockHtmlHelper | |
specify "It should remove empty block-level elements" do | |
strip_empty_block_html("<p>Thing</p><p><span><!-- img was here --></span></p><p>Stuff</p>").should == "<p>Thing</p><p>Stuff</p>" | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "nokogiri" | |
module TruncateHtmlHelper | |
def truncate_html(html, options={}, &block) | |
if html | |
length = options.fetch(:length, 30) | |
omission = options.fetch(:omission, "…") | |
omission &&= Nokogiri::HTML::DocumentFragment.parse(omission) | |
remaining = length | |
remaining -= omission.content.length if omission | |
fragment = Nokogiri::HTML::DocumentFragment.parse(html) | |
fragment.traverse do |node| | |
if node.text? or node.cdata? | |
remaining -= node.content.length | |
if remaining < 0 | |
node.content = node.content[0...remaining] | |
end | |
if node.content.empty? | |
node.remove | |
end | |
elsif node.element? and remaining <= 0 and not node.children.any? | |
node.remove | |
end | |
end | |
# If there's a block, use it instead of the omission | |
if block_given? && remaining < 0 | |
omission = Nokogiri::HTML::DocumentFragment.parse(capture(&block)) | |
end | |
# Add the omission only if we have truncated | |
if omission && remaining < 0 | |
last_child = fragment.children.last | |
# If the last element is block, level, tuck the omission inside | |
if last_child.element? and last_child.description and last_child.description.block? | |
last_child << omission | |
else | |
fragment << omission | |
end | |
end | |
fragment.to_html | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "./truncate_html_helper" | |
describe TruncateHtmlHelper do | |
include TruncateHtmlHelper | |
specify "basic truncation inside block-level element" do | |
truncate_html("<p>A <strong>thing</strong> which gets truncated.</p><p>With trailing elements</p>", length: 8).should == "<p>A <strong>thing</strong>…</p>" | |
end | |
specify "empty elements are preserved, but danglers are removed" do | |
truncate_html("<p>And<br>line<br>breaks<br>are<br>preserved.</p>", length: 8).should == "<p>And<br>line…</p>" | |
end | |
specify "omissions are outside inline elements" do | |
truncate_html("<strong>Thing</strong> and <em>stuff</em>", length: 6).should == "<strong>Thing</strong>…" | |
end | |
specify "default length is 30" do | |
truncate_html("a" * 50).should == "a" * 29 << "…" | |
end | |
specify "alternate omission text" do | |
truncate_html("<div>a<em>b</em>cdef</div>", length: 6, omission: "...").should == "<div>a<em>b</em>c...</div>" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment