rubypants-0.6.0/ 0000755 0000041 0000041 00000000000 13017604664 013603 5 ustar www-data www-data rubypants-0.6.0/Rakefile 0000644 0000041 0000041 00000000176 13017604664 015254 0 ustar www-data www-data desc "Run all the tests"
task :default => [:test]
desc "Run all the tests"
task :test do
ruby 'test/rubypants_test.rb'
end
rubypants-0.6.0/Gemfile 0000644 0000041 0000041 00000000144 13017604664 015075 0 ustar www-data www-data source "https://rubygems.org"
gemspec
gem "rake"
gem "codecov", :require => false, :group => :test
rubypants-0.6.0/README.rdoc 0000644 0000041 0000041 00000007716 13017604664 015424 0 ustar www-data www-data = RubyPants: SmartyPants for Ruby
{}[https://rubygems.org/gems/rubypants]
{
}[https://travis-ci.org/jmcnevin/rubypants]
{
}[https://codecov.io/gh/jmcnevin/rubypants]
== Synopsis
RubyPants is a Ruby port of the smart-quotes library SmartyPants.
The original "SmartyPants" is a free web publishing plug-in for
Movable Type, Blosxom, and BBEdit that easily translates plain ASCII
punctuation characters into "smart" typographic punctuation HTML
entities.
== Description
RubyPants can perform the following transformations:
* Straight quotes (" and ') into "curly" quote
HTML entities
* Backticks-style quotes (``like this'') into "curly" quote
HTML entities
* Dashes (-- and ---) into en- and em-dash
entities
* Three consecutive dots (... or . . .) into an
ellipsis entity
This means you can write, edit, and save your posts using plain old
ASCII straight quotes, plain dashes, and plain dots, but your
published posts (and final HTML output) will appear with smart
quotes, em-dashes, and proper ellipses.
RubyPants does not modify characters within ,
, , , or
tag blocks. Typically, these tags are used to
display text where smart quotes and other "smart punctuation" would
not be appropriate, such as source code or example markup.
== Installation
gem install rubypants
Or, in your application's Gemfile:
gem 'rubypants'
== Example of Usage
RubyPants.new("String with 'dumb' quotes.").to_html
For additional options, consult the documention in
lib/rubypants/core.rb.
== Backslash Escapes
If you need to use literal straight quotes (or plain hyphens and
periods), RubyPants accepts the following backslash escape sequences
to force non-smart punctuation. It does so by transforming the
escape sequence into a decimal-encoded HTML entity:
\\ \" \' \. \- \`
This is useful, for example, when you want to use straight quotes as
foot and inch marks: 6'2" tall; a 17" iMac. (Use 6\'2\"
resp. 17\".)
== Algorithmic Shortcomings
One situation in which quotes will get curled the wrong way is when
apostrophes are used at the start of leading contractions. For
example:
'Twas the night before Christmas.
In the case above, RubyPants will turn the apostrophe into an
opening single-quote, when in fact it should be a closing one. I
don't think this problem can be solved in the general case--every
word processor I've tried gets this wrong as well. In such cases,
it's best to use the proper HTML entity for closing single-quotes
("’") by hand.
== Bugs
To file bug reports or feature requests, please create an issue in this gem's
GitHub repository.
If the bug involves quotes being curled the wrong way, please send
example text to illustrate.
== Authors
John Gruber did all of the hard work of writing this software in
Perl for Movable Type and almost all of this useful documentation.
Chad Miller ported it to Python to use with Pyblosxom.
Christian Neukirchen provided the Ruby port, as a general-purpose
library that follows the *Cloth API.
Jeremy McNevin posted this code to GitHub ages ago, but has recently
been trying to improve it where possible.
Aron Griffis made jekyll-pants[https://github.com/scampersand/jekyll-pants]
which depends on RubyPants, and consequently jumped in to help out with
issues and pull requests.
== Links
John Gruber :: http://daringfireball.net
SmartyPants :: http://daringfireball.net/projects/smartypants
Chad Miller :: http://web.chad.org
Christian Neukirchen :: http://kronavita.de/chris
Aron Griffis :: https://arongriffis.com
rubypants-0.6.0/.travis.yml 0000644 0000041 0000041 00000000753 13017604664 015721 0 ustar www-data www-data rvm:
- 2.0
- 2.1
- 2.2
- 2.3.0
- jruby
# Workaround for `NoMethodError: undefined method 'spec' for nil:NilClass`,
# see https://travis-ci.org/jmcnevin/rubypants/jobs/167182556
# and https://github.com/travis-ci/travis-ci/issues/5239
before_install:
- gem install bundler
# For now override the default `bundle exec rake` which fails because of an
# unresolved superclass mismatch in `core.rb` vs. `version.rb`. This should
# eventually be fixed in rubypants.
script:
- rake
rubypants-0.6.0/lib/ 0000755 0000041 0000041 00000000000 13017604664 014351 5 ustar www-data www-data rubypants-0.6.0/lib/rubypants.rb 0000644 0000041 0000041 00000000107 13017604664 016723 0 ustar www-data www-data require_relative 'rubypants/core'
require_relative 'rubypants/version'
rubypants-0.6.0/lib/rubypants/ 0000755 0000041 0000041 00000000000 13017604664 016400 5 ustar www-data www-data rubypants-0.6.0/lib/rubypants/version.rb 0000644 0000041 0000041 00000000050 13017604664 020405 0 ustar www-data www-data class RubyPants
VERSION = "0.6.0"
end
rubypants-0.6.0/lib/rubypants/core.rb 0000644 0000041 0000041 00000035352 13017604664 017665 0 ustar www-data www-data class RubyPants < String
# Create a new RubyPants instance with the text in +string+.
#
# Allowed elements in the options array:
#
# 0 :: do nothing
# 1 :: enable all, using only em-dash shortcuts
# 2 :: enable all, using old school en- and em-dash shortcuts (*default*)
# 3 :: enable all, using inverted old school en and em-dash shortcuts
# -1 :: stupefy (translate HTML entities to their ASCII-counterparts)
#
# If you don't like any of these defaults, you can pass symbols to change
# RubyPants' behavior:
#
# :quotes :: quotes
# :backticks :: backtick quotes (``double'' only)
# :allbackticks :: backtick quotes (``double'' and `single')
# :dashes :: dashes
# :oldschool :: old school dashes
# :inverted :: inverted old school dashes
# :ellipses :: ellipses
# :prevent_breaks :: use nbsp and word-joiner to avoid breaking
# before dashes and ellipses
# :named_entities :: used named entities instead of the default
# decimal entities (see below)
# :convertquotes :: convert " entities to
# "
# :stupefy :: translate RubyPants HTML entities
# to their ASCII counterparts.
#
# In addition, you can customize the HTML entities that will be injected by
# passing in a hash for the final argument. The defaults for these entities
# are as follows:
#
# :single_left_quote :: ‘
# :double_left_quote :: “
# :single_right_quote :: ’
# :double_right_quote :: ”
# :em_dash :: —
# :en_dash :: –
# :ellipsis :: …
# :html_quote :: "
# :non_breaking_space ::
# :word_joiner ::
#
# If the :named_entities option is used, the default entities are
# as follows:
#
# :single_left_quote :: ‘
# :double_left_quote :: “
# :single_right_quote :: ’
# :double_right_quote :: ”
# :em_dash :: —
# :en_dash :: –
# :ellipsis :: …
# :html_quote :: "
# :non_breaking_space ::
# :word_joiner ::
#
def initialize(string, options=[2], entities = {})
super string
@options = [*options]
@entities = default_entities
@entities.merge!(named_entities) if @options.include?(:named_entities)
@entities.merge!(entities)
end
# Apply SmartyPants transformations.
def to_html
do_quotes = do_backticks = do_dashes = do_ellipses = do_stupify = nil
convert_quotes = prevent_breaks = nil
if @options.include?(0)
# Do nothing.
return self
elsif @options.include?(1)
# Do everything, turn all options on.
do_quotes = do_backticks = do_ellipses = true
do_dashes = :normal
elsif @options.include?(2)
# Do everything, turn all options on, use old school dash shorthand.
do_quotes = do_backticks = do_ellipses = true
do_dashes = :oldschool
elsif @options.include?(3)
# Do everything, turn all options on, use inverted old school
# dash shorthand.
do_quotes = do_backticks = do_ellipses = true
do_dashes = :inverted
elsif @options.include?(-1)
do_stupefy = true
end
# Explicit flags override numeric flag groups.
do_quotes = true if @options.include?(:quotes)
do_backticks = true if @options.include?(:backticks)
do_backticks = :both if @options.include?(:allbackticks)
do_dashes = :normal if @options.include?(:dashes)
do_dashes = :oldschool if @options.include?(:oldschool)
do_dashes = :inverted if @options.include?(:inverted)
prevent_breaks = true if @options.include?(:prevent_breaks)
do_ellipses = true if @options.include?(:ellipses)
convert_quotes = true if @options.include?(:convertquotes)
do_stupefy = true if @options.include?(:stupefy)
# Parse the HTML
tokens = tokenize
# Keep track of when we're inside
or tags.
in_pre = nil
# Here is the result stored in.
result = ""
# This is a cheat, used to get some context for one-character
# tokens that consist of just a quote char. What we do is remember
# the last character of the previous text token, to use as context
# to curl single- character quote tokens correctly.
prev_token_last_char = nil
tokens.each do |token|
if token.first == :tag
result << token[1]
if token[1].end_with? '/>'
# ignore self-closing tags
elsif token[1] =~ %r!\A<(/?)(pre|code|kbd|script|style|math)[\s>]!
if $1 == '' && ! in_pre
in_pre = $2
elsif $1 == '/' && $2 == in_pre
in_pre = nil
end
end
else
t = token[1]
# Remember last char of this token before processing.
last_char = t[-1].chr
unless in_pre
t = process_escapes t
t.gsub!(/"/, '"') if convert_quotes
if do_dashes
t = educate_dashes t, prevent_breaks if do_dashes == :normal
t = educate_dashes_oldschool t, prevent_breaks if do_dashes == :oldschool
t = educate_dashes_inverted t, prevent_breaks if do_dashes == :inverted
end
t = educate_ellipses t, prevent_breaks if do_ellipses
# Note: backticks need to be processed before quotes.
if do_backticks
t = educate_backticks t
t = educate_single_backticks t if do_backticks == :both
end
if do_quotes
if t == "'"
# Special case: single-character ' token
if prev_token_last_char =~ /\S/
t = entity(:single_right_quote)
else
t = entity(:single_left_quote)
end
elsif t == '"'
# Special case: single-character " token
if prev_token_last_char =~ /\S/
t = entity(:double_right_quote)
else
t = entity(:double_left_quote)
end
else
# Normal case:
t = educate_quotes t
end
end
t = stupefy_entities t if do_stupefy
end
prev_token_last_char = last_char
result << t
end
end
# Done
result
end
protected
# Return the string, with after processing the following backslash
# escape sequences. This is useful if you want to force a "dumb" quote
# or other character to appear.
#
# Escaped are:
# \\ \" \' \. \- \`
#
def process_escapes(str)
str.
gsub('\\\\', '\').
gsub('\"', '"').
gsub("\\\'", ''').
gsub('\.', '.').
gsub('\-', '-').
gsub('\`', '`')
end
def self.n_of(n, x)
x = Regexp.escape(x)
/(?[[:space:]]*)#{patt}/
str.gsub(patt) do
spaces = if prevent_breaks && $~['spaces'].length > 0
entity(:non_breaking_space) # * $~['spaces'].length
elsif prevent_breaks
entity(:word_joiner)
else
$~['spaces']
end
spaces + repl
end
end
# Return the string, with each instance of "--" translated to an
# em-dash HTML entity.
#
def educate_dashes(str, prevent_breaks=false)
educate(str, DOUBLE_DASH, entity(:em_dash), prevent_breaks)
end
# Return the string, with each instance of "--" translated to an
# en-dash HTML entity, and each "---" translated to an
# em-dash HTML entity.
#
def educate_dashes_oldschool(str, prevent_breaks=false)
str = educate(str, TRIPLE_DASH, entity(:em_dash), prevent_breaks)
educate(str, DOUBLE_DASH, entity(:en_dash), prevent_breaks)
end
# Return the string, with each instance of "--" translated
# to an em-dash HTML entity, and each "---" translated to
# an en-dash HTML entity. Two reasons why: First, unlike the en- and
# em-dash syntax supported by +educate_dashes_oldschool+, it's
# compatible with existing entries written before SmartyPants 1.1,
# back when "--" was only used for em-dashes. Second,
# em-dashes are more common than en-dashes, and so it sort of makes
# sense that the shortcut should be shorter to type. (Thanks to
# Aaron Swartz for the idea.)
#
def educate_dashes_inverted(str, prevent_breaks=false)
str = educate(str, TRIPLE_DASH, entity(:en_dash), prevent_breaks)
educate(str, DOUBLE_DASH, entity(:em_dash), prevent_breaks)
end
# Return the string, with each instance of "..." translated
# to an ellipsis HTML entity. Also converts the case where there are
# spaces between the dots.
#
def educate_ellipses(str, prevent_breaks=false)
str = educate(str, RubyPants.n_of(3, '.'), entity(:ellipsis), prevent_breaks)
educate(str, /(?``backticks''"-style single quotes
# translated into HTML curly quote entities.
#
def educate_backticks(str)
str.
gsub("``", entity(:double_left_quote)).
gsub("''", entity(:double_right_quote))
end
# Return the string, with "`backticks'"-style single quotes
# translated into HTML curly quote entities.
#
def educate_single_backticks(str)
str.
gsub("`", entity(:single_left_quote)).
gsub("'", entity(:single_right_quote))
end
# Return the string, with "educated" curly quote HTML entities.
#
def educate_quotes(str)
punct_class = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]'
str = str.dup
# Special case if the very first character is a quote followed by
# punctuation at a non-word-break. Close the quotes by brute
# force:
str.gsub!(/^'(?=#{punct_class}\B)/,
entity(:single_right_quote))
str.gsub!(/^"(?=#{punct_class}\B)/,
entity(:double_right_quote))
# Special case for double sets of quotes, e.g.:
# He said, "'Quoted' words in a larger quote."
str.gsub!(/"'(?=\w)/,
"#{entity(:double_left_quote)}#{entity(:single_left_quote)}")
str.gsub!(/'"(?=\w)/,
"#{entity(:single_left_quote)}#{entity(:double_left_quote)}")
# Special case for decade abbreviations (the '80s):
str.gsub!(/'(?=\d\ds)/,
entity(:single_right_quote))
close_class = %![^\ \t\r\n\\[\{\(\-]!
dec_dashes = "#{entity(:en_dash)}|#{entity(:em_dash)}"
# Get most opening single quotes:
str.gsub!(/([[:space:]]| |--|&[mn]dash;|#{dec_dashes}|ȁ[34];)'(?=\w)/,
'\1' + entity(:single_left_quote))
# Single closing quotes:
str.gsub!(/(#{close_class})'/,
'\1' + entity(:single_right_quote))
str.gsub!(/'(\s|s\b|$)/,
entity(:single_right_quote) + '\1')
# Any remaining single quotes should be opening ones:
str.gsub!(/'/,
entity(:single_left_quote))
# Get most opening double quotes:
str.gsub!(/([[:space:]]| |--|&[mn]dash;|#{dec_dashes}|ȁ[34];)"(?=\w)/,
'\1' + entity(:double_left_quote))
# Double closing quotes:
str.gsub!(/(#{close_class})"/,
'\1' + entity(:double_right_quote))
str.gsub!(/"(\s|s\b|$)/,
entity(:double_right_quote) + '\1')
# Any remaining quotes should be opening ones:
str.gsub!(/"/,
entity(:double_left_quote))
str
end
# Return the string, with each RubyPants HTML entity translated to
# its ASCII counterpart.
#
# Note: This is not reversible (but exactly the same as in SmartyPants)
#
def stupefy_entities(str)
new_str = str.dup
{
:en_dash => '-',
:em_dash => '--',
:single_left_quote => "'",
:single_right_quote => "'",
:double_left_quote => '"',
:double_right_quote => '"',
:ellipsis => '...'
}.each do |k,v|
new_str.gsub!(/#{entity(k)}/, v)
end
new_str
end
# Return an array of the tokens comprising the string. Each token is
# either a tag (possibly with nested, tags contained therein, such
# as , or a run of text between
# tags. Each element of the array is a two-element array; the first
# is either :tag or :text; the second is the actual value.
#
# Based on the _tokenize() subroutine from Brad Choate's
# MTRegex plugin.
#
# This is actually the easier variant using tag_soup, as used by
# Chad Miller in the Python port of SmartyPants.
#
def tokenize
tag_soup = /([^<]*)(|<[^>]*>)/m
tokens = []
prev_end = 0
scan(tag_soup) do
tokens << [:text, $1] if $1 != ""
tokens << [:tag, $2]
prev_end = $~.end(0)
end
if prev_end < size
tokens << [:text, self[prev_end..-1]]
end
tokens
end
def default_entities
{
:single_left_quote => "‘",
:double_left_quote => "“",
:single_right_quote => "’",
:double_right_quote => "”",
:em_dash => "—",
:en_dash => "–",
:ellipsis => "…",
:html_quote => """,
:non_breaking_space => " ",
:word_joiner => "",
}
end
def named_entities
{
:single_left_quote => '‘',
:double_left_quote => "“",
:single_right_quote => "’",
:double_right_quote => "”",
:em_dash => "—",
:en_dash => "–",
:ellipsis => "…",
:html_quote => """,
:non_breaking_space => " ",
# :word_joiner => N/A,
}
end
def entity(key)
@entities[key]
end
end
rubypants-0.6.0/test/ 0000755 0000041 0000041 00000000000 13017604664 014562 5 ustar www-data www-data rubypants-0.6.0/test/helper.rb 0000644 0000041 0000041 00000000153 13017604664 016365 0 ustar www-data www-data require 'simplecov'
SimpleCov.start
require 'codecov'
SimpleCov.formatter = SimpleCov::Formatter::Codecov
rubypants-0.6.0/test/rubypants_test.rb 0000644 0000041 0000041 00000022640 13017604664 020201 0 ustar www-data www-data require_relative 'helper'
require 'minitest/autorun'
require_relative '../lib/rubypants'
# Test EVERYTHING against SmartyPants.pl output!
class RubyPantsTest < Minitest::Test
def assert_rp_equal(str, orig, options=[2], entities = {})
assert_equal orig, RubyPants.new(str, options, entities).to_html
end
def assert_verbatim(str)
assert_rp_equal str, str
end
def test_verbatim
assert_verbatim "foo!"
assert_verbatim "This is HTML"
assert_verbatim "This is HTML with tags>"
assert_verbatim <html
code
EOF
end
def test_quotes
assert_rp_equal '"A first example"', '“A first example”'
assert_rp_equal '"A first "nested" example"',
'“A first “nested” example”'
assert_rp_equal '".', '”.'
assert_rp_equal '"a', '“a'
assert_rp_equal "'.", '’.'
assert_rp_equal "'a", '‘a'
assert_rp_equal %{He said, "'Quoted' words in a larger quote."
},
"He said, “‘Quoted’ words in a larger quote.”
"
assert_rp_equal %{"I like the 70's"}, '“I like the 70’s”'
assert_rp_equal %{"I like the '70s"}, '“I like the ’70s”'
assert_rp_equal %{"I like the '70!"}, '“I like the ‘70!”'
assert_rp_equal 'pre"post', 'pre”post'
assert_rp_equal 'pre "post', 'pre “post'
assert_rp_equal 'pre "post', 'pre “post'
assert_rp_equal 'pre--"post', 'pre–“post'
assert_rp_equal 'pre--"!', 'pre–”!'
assert_rp_equal "pre'post", 'pre’post'
assert_rp_equal "pre 'post", 'pre ‘post'
assert_rp_equal "pre 'post", 'pre ‘post'
assert_rp_equal "pre--'post", 'pre–‘post'
assert_rp_equal "pre--'!", 'pre–’!'
assert_rp_equal "'", "‘"
assert_rp_equal "foo'", "foo’"
assert_rp_equal '"', "“"
assert_rp_equal 'foo"', "foo”"
assert_rp_equal "foo\u00a0\"bar\"", "foo\u00a0“bar”"
assert_rp_equal "foo\u00a0'bar'", "foo\u00a0‘bar’"
end
def test_dashes
assert_rp_equal "foo--bar", 'foo—bar', 1
assert_rp_equal "foo---bar", 'foo---bar', 1
assert_rp_equal "foo----bar", 'foo----bar', 1
assert_rp_equal "--foo--bar--quux--",
'—foo—bar—quux—', 1
assert_rp_equal "foo--bar", 'foo—bar', [1, :prevent_breaks]
assert_rp_equal "foo --bar", 'foo —bar', 1
assert_rp_equal "foo --bar", 'foo —bar', [1, :prevent_breaks]
assert_rp_equal "foo -- bar", 'foo — bar', [1, :prevent_breaks]
assert_rp_equal "foo --bar", 'foo —bar', [1, :prevent_breaks]
assert_rp_equal "foo--bar", 'foo–bar', 2
assert_rp_equal "foo---bar", 'foo—bar', 2
assert_rp_equal "foo----bar", 'foo----bar', 2
assert_rp_equal "--foo--bar--quux--",
'–foo–bar–quux–', 2
assert_rp_equal "foo--bar", 'foo–bar', [2, :prevent_breaks]
assert_rp_equal "foo --bar", 'foo –bar', 2
assert_rp_equal "foo --bar", 'foo –bar', [2, :prevent_breaks]
assert_rp_equal "foo -- bar", 'foo – bar', [2, :prevent_breaks]
assert_rp_equal "foo --bar", 'foo –bar', [2, :prevent_breaks]
assert_rp_equal "foo---bar", 'foo—bar', [2, :prevent_breaks]
assert_rp_equal "foo ---bar", 'foo —bar', 2
assert_rp_equal "foo ---bar", 'foo —bar', [2, :prevent_breaks]
assert_rp_equal "foo --- bar", 'foo — bar', [2, :prevent_breaks]
assert_rp_equal "foo ---bar", 'foo —bar', [2, :prevent_breaks]
assert_rp_equal "foo--bar", 'foo—bar', 3
assert_rp_equal "foo---bar", 'foo–bar', 3
assert_rp_equal "foo----bar", 'foo----bar', 3
assert_rp_equal "--foo--bar--quux--",
'—foo—bar—quux—', 3
assert_rp_equal "foo--bar", 'foo—bar', [3, :prevent_breaks]
assert_rp_equal "foo --bar", 'foo —bar', 3
assert_rp_equal "foo --bar", 'foo —bar', [3, :prevent_breaks]
assert_rp_equal "foo -- bar", 'foo — bar', [3, :prevent_breaks]
assert_rp_equal "foo --bar", 'foo —bar', [3, :prevent_breaks]
assert_rp_equal "foo---bar", 'foo–bar', [3, :prevent_breaks]
assert_rp_equal "foo ---bar", 'foo –bar', 3
assert_rp_equal "foo ---bar", 'foo –bar', [3, :prevent_breaks]
assert_rp_equal "foo --- bar", 'foo – bar', [3, :prevent_breaks]
assert_rp_equal "foo ---bar", 'foo –bar', [3, :prevent_breaks]
end
def test_html_comments
assert_verbatim ""
assert_verbatim ""
assert_verbatim ""
assert_rp_equal "----", '––'
end
def test_pre_tags
assert_verbatim "--
"
assert_verbatim "--
--
"
assert_rp_equal "----
", '–--
'
end
def test_ellipses
assert_rp_equal "foo..bar", 'foo..bar', [:ellipses]
assert_rp_equal "foo...bar", 'foo…bar', [:ellipses]
assert_rp_equal "foo....bar", 'foo....bar', [:ellipses]
# and with :prevent_breaks
assert_rp_equal "foo..bar", 'foo..bar', [:ellipses, :prevent_breaks]
assert_rp_equal "foo...bar", 'foo…bar', [:ellipses, :prevent_breaks]
assert_rp_equal "foo....bar", 'foo....bar', [:ellipses, :prevent_breaks]
# dots and spaces
assert_rp_equal "foo. . .bar", 'foo…bar', [:ellipses]
assert_rp_equal "foo . . . bar", 'foo … bar', [:ellipses]
assert_rp_equal "foo. . . .bar", 'foo. . . .bar', [:ellipses]
assert_rp_equal "foo . . . . bar", 'foo . . . . bar', [:ellipses]
# and with :prevent_breaks
assert_rp_equal "foo. . .bar", 'foo…bar', [:ellipses, :prevent_breaks]
assert_rp_equal "foo . . . bar", 'foo … bar', [:ellipses, :prevent_breaks]
assert_rp_equal "foo. . . .bar", 'foo. . . .bar', [:ellipses, :prevent_breaks]
assert_rp_equal "foo . . . . bar", 'foo . . . . bar', [:ellipses, :prevent_breaks]
# nasty ones
assert_rp_equal "foo. . ..bar", 'foo. . ..bar', [:ellipses]
assert_rp_equal "foo. . ...bar", 'foo. . …bar', [:ellipses]
assert_rp_equal "foo. . ....bar", 'foo. . ....bar', [:ellipses]
# and with :prevent_breaks
assert_rp_equal "foo. . ..bar", 'foo. . ..bar', [:ellipses, :prevent_breaks]
assert_rp_equal "foo. . ...bar", 'foo. . …bar', [:ellipses, :prevent_breaks]
assert_rp_equal "foo. . ....bar", 'foo. . ....bar', [:ellipses, :prevent_breaks]
end
def test_backticks
assert_rp_equal "pre``post", 'pre“post'
assert_rp_equal "pre ``post", 'pre “post'
assert_rp_equal "pre ``post", 'pre “post'
assert_rp_equal "pre--``post", 'pre–“post'
assert_rp_equal "pre--``!", 'pre–“!'
assert_rp_equal "pre''post", 'pre”post'
assert_rp_equal "pre ''post", 'pre ”post'
assert_rp_equal "pre ''post", 'pre ”post'
assert_rp_equal "pre--''post", 'pre–”post'
assert_rp_equal "pre--''!", 'pre–”!'
end
def test_single_backticks
o = [:oldschool, :allbackticks]
assert_rp_equal "`foo'", "‘foo’", o
assert_rp_equal "pre`post", 'pre‘post', o
assert_rp_equal "pre `post", 'pre ‘post', o
assert_rp_equal "pre `post", 'pre ‘post', o
assert_rp_equal "pre--`post", 'pre–‘post', o
assert_rp_equal "pre--`!", 'pre–‘!', o
assert_rp_equal "pre'post", 'pre’post', o
assert_rp_equal "pre 'post", 'pre ’post', o
assert_rp_equal "pre 'post", 'pre ’post', o
assert_rp_equal "pre--'post", 'pre–’post', o
assert_rp_equal "pre--'!", 'pre–’!', o
end
def test_stupefy
o = [:stupefy]
assert_rp_equal "He said, “‘Quoted’ words " +
"in a larger quote.”
",
%{He said, "'Quoted' words in a larger quote."
}, o
assert_rp_equal "– — ‘’ “” …",
%{- -- '' "" ...}, o
assert_rp_equal %{- -- '' "" ...}, %{- -- '' "" ...}, o
end
def test_process_escapes
assert_rp_equal %q{foo\bar}, "foo\\bar"
assert_rp_equal %q{foo\\\bar}, "foo\bar"
assert_rp_equal %q{foo\\\\\bar}, "foo\\\bar"
assert_rp_equal %q{foo\...bar}, "foo...bar"
assert_rp_equal %q{foo\.\.\.bar}, "foo...bar"
assert_rp_equal %q{foo\'bar}, "foo'bar"
assert_rp_equal %q{foo\"bar}, "foo"bar"
assert_rp_equal %q{foo\-bar}, "foo-bar"
assert_rp_equal %q{foo\`bar}, "foo`bar"
assert_rp_equal %q{foo\#bar}, "foo\\#bar"
assert_rp_equal %q{foo\*bar}, "foo\\*bar"
assert_rp_equal %q{foo\&bar}, "foo\\&bar"
end
def test_modified_entities
entities = {
:single_left_quote => 'SHAZAM',
:single_right_quote => 'POWZAP'
}
assert_rp_equal "Testing 'FOO!'", "Testing SHAZAMFOO!POWZAP", [2], entities
end
def test_named_entities
assert_rp_equal "Testing 'FOO!'", "Testing ‘FOO!’", [2, :named_entities]
end
end
rubypants-0.6.0/.gitignore 0000644 0000041 0000041 00000000015 13017604664 015567 0 ustar www-data www-data Gemfile.lock
rubypants-0.6.0/rubypants.gemspec 0000644 0000041 0000041 00000002202 13017604664 017173 0 ustar www-data www-data # -*- encoding: utf-8 -*-
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "rubypants/version"
Gem::Specification.new do |s|
s.name = 'rubypants'
s.version = RubyPants::VERSION
s.summary = "RubyPants is a Ruby port of the smart-quotes library SmartyPants."
s.description = <<-EOF
The original "SmartyPants" is a free web publishing plug-in for
Movable Type, Blosxom, and BBEdit that easily translates plain ASCII
punctuation characters into "smart" typographic punctuation HTML
entities.
EOF
s.authors = [
"John Gruber",
"Chad Miller",
"Christian Neukirchen",
"Jeremy McNevin",
"Aron Griffis"
]
s.email = 'jeremy@spokoino.net'
s.files = `git ls-files`.split($/)
s.test_files = s.files.grep(%r{^(test|spec|features)/})
s.require_paths = ["lib"]
s.homepage = 'https://github.com/jmcnevin/rubypants'
s.license = 'MIT'
s.add_development_dependency('minitest')
end
rubypants-0.6.0/LICENSE.rdoc 0000644 0000041 0000041 00000006141 13017604664 015540 0 ustar www-data www-data = Copyright and License
== Copyright
Ported by Christian Neukirchen
Copyright (C) 2004 Christian Neukirchen
Incorporates ideas, comments and documentation by Chad Miller
Copyright (C) 2004 Chad Miller
Original SmartyPants by John Gruber
Copyright (C) 2003 John Gruber
== SmartyPants license:
Copyright (c) 2003 John Gruber
(http://daringfireball.net)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name "SmartyPants" nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
This software is provided by the copyright holders and contributors
"as is" and any express or implied warranties, including, but not
limited to, the implied warranties of merchantability and fitness
for a particular purpose are disclaimed. In no event shall the
copyright owner or contributors be liable for any direct, indirect,
incidental, special, exemplary, or consequential damages (including,
but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however
caused and on any theory of liability, whether in contract, strict
liability, or tort (including negligence or otherwise) arising in
any way out of the use of this software, even if advised of the
possibility of such damage.
=== RubyPants license
RubyPants is a derivative work of SmartyPants and smartypants.py.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
This software is provided by the copyright holders and contributors
"as is" and any express or implied warranties, including, but not
limited to, the implied warranties of merchantability and fitness
for a particular purpose are disclaimed. In no event shall the
copyright owner or contributors be liable for any direct, indirect,
incidental, special, exemplary, or consequential damages (including,
but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however
caused and on any theory of liability, whether in contract, strict
liability, or tort (including negligence or otherwise) arising in
any way out of the use of this software, even if advised of the
possibility of such damage.