rubypants 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.travis.yml +3 -4
- data/lib/rubypants.rb +99 -72
- data/lib/version.rb +1 -1
- data/test/rubypants_test.rb +26 -0
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 766f0400e12ec2e5bb64917568fcf5dba1b7fdf7e31632c62144602e0b1bd674
|
4
|
+
data.tar.gz: 87de02ec38116b4d9d179e80f958f608101565a9724f63a751e7efb642dab7ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 543191639285ce9c53716b19fcbfa72dd6b14e96f53cb88b87a62f5cf4446725ceeb384c6ea3c7767c97409195d7e5cb11c8694d06eb93545284b230b2407bf0
|
7
|
+
data.tar.gz: ed420062908b83fa18c96bb8048870095350f4d9b45ac2294939a9265f775c04a1aa4c5d7e40ed8b3bee741a013103be0bf218e4d18e4e0e59dbbe3eb6cd2fc0
|
data/.travis.yml
CHANGED
data/lib/rubypants.rb
CHANGED
@@ -70,12 +70,23 @@ class RubyPants < String
|
|
70
70
|
|
71
71
|
@options = [*options]
|
72
72
|
@entities = default_entities
|
73
|
-
@entities.merge!(named_entities)
|
73
|
+
@entities.merge!(named_entities) if @options.include?(:named_entities)
|
74
74
|
@entities.merge!(character_entities) if @options.include?(:character_entities)
|
75
|
-
@entities.merge!(character_spaces)
|
75
|
+
@entities.merge!(character_spaces) if @options.include?(:character_spaces)
|
76
76
|
@entities.merge!(entities)
|
77
|
+
|
78
|
+
@single_left_quote = @entities[:single_left_quote]
|
79
|
+
@single_right_quote = @entities[:single_right_quote]
|
80
|
+
@double_left_quote = @entities[:double_left_quote]
|
81
|
+
@double_right_quote = @entities[:double_right_quote]
|
82
|
+
@ellipsis = @entities[:ellipsis]
|
83
|
+
@em_dash = @entities[:em_dash]
|
84
|
+
@en_dash = @entities[:en_dash]
|
77
85
|
end
|
78
86
|
|
87
|
+
SPECIAL_HTML_TAGS = %r!\A<(/?)(pre|code|kbd|script|style|math)[\s>]!
|
88
|
+
NON_WHITESPACE_CHARS = /\S/
|
89
|
+
|
79
90
|
# Apply SmartyPants transformations.
|
80
91
|
def to_html
|
81
92
|
do_quotes = do_backticks = do_dashes = do_ellipses = do_stupify = nil
|
@@ -102,16 +113,16 @@ class RubyPants < String
|
|
102
113
|
end
|
103
114
|
|
104
115
|
# Explicit flags override numeric flag groups.
|
105
|
-
do_quotes = true
|
106
|
-
do_backticks = true
|
107
|
-
do_backticks = :both
|
108
|
-
do_dashes = :normal
|
116
|
+
do_quotes = true if @options.include?(:quotes)
|
117
|
+
do_backticks = true if @options.include?(:backticks)
|
118
|
+
do_backticks = :both if @options.include?(:allbackticks)
|
119
|
+
do_dashes = :normal if @options.include?(:dashes)
|
109
120
|
do_dashes = :oldschool if @options.include?(:oldschool)
|
110
|
-
do_dashes = :inverted
|
111
|
-
prevent_breaks = true
|
112
|
-
do_ellipses = true
|
113
|
-
convert_quotes = true
|
114
|
-
do_stupefy = true
|
121
|
+
do_dashes = :inverted if @options.include?(:inverted)
|
122
|
+
prevent_breaks = true if @options.include?(:prevent_breaks)
|
123
|
+
do_ellipses = true if @options.include?(:ellipses)
|
124
|
+
convert_quotes = true if @options.include?(:convertquotes)
|
125
|
+
do_stupefy = true if @options.include?(:stupefy)
|
115
126
|
|
116
127
|
# Parse the HTML
|
117
128
|
tokens = tokenize
|
@@ -133,7 +144,7 @@ class RubyPants < String
|
|
133
144
|
result << token[1]
|
134
145
|
if token[1].end_with? '/>'
|
135
146
|
# ignore self-closing tags
|
136
|
-
elsif token[1] =~
|
147
|
+
elsif token[1] =~ SPECIAL_HTML_TAGS
|
137
148
|
if $1 == '' && ! in_pre
|
138
149
|
in_pre = $2
|
139
150
|
elsif $1 == '/' && $2 == in_pre
|
@@ -149,36 +160,36 @@ class RubyPants < String
|
|
149
160
|
unless in_pre
|
150
161
|
t = process_escapes t
|
151
162
|
|
152
|
-
t.gsub!(
|
163
|
+
t.gsub!('"', '"') if convert_quotes
|
153
164
|
|
154
165
|
if do_dashes
|
155
|
-
t = educate_dashes t, prevent_breaks
|
156
|
-
t = educate_dashes_oldschool t, prevent_breaks
|
157
|
-
t = educate_dashes_inverted t, prevent_breaks
|
166
|
+
t = educate_dashes t, prevent_breaks if do_dashes == :normal
|
167
|
+
t = educate_dashes_oldschool t, prevent_breaks if do_dashes == :oldschool
|
168
|
+
t = educate_dashes_inverted t, prevent_breaks if do_dashes == :inverted
|
158
169
|
end
|
159
170
|
|
160
|
-
t = educate_ellipses t, prevent_breaks
|
171
|
+
t = educate_ellipses t, prevent_breaks if do_ellipses
|
161
172
|
|
162
173
|
# Note: backticks need to be processed before quotes.
|
163
174
|
if do_backticks
|
164
175
|
t = educate_backticks t
|
165
|
-
t = educate_single_backticks t
|
176
|
+
t = educate_single_backticks t if do_backticks == :both
|
166
177
|
end
|
167
178
|
|
168
179
|
if do_quotes
|
169
180
|
if t == "'"
|
170
181
|
# Special case: single-character ' token
|
171
|
-
if prev_token_last_char =~
|
172
|
-
t =
|
182
|
+
if prev_token_last_char =~ NON_WHITESPACE_CHARS
|
183
|
+
t = @single_right_quote
|
173
184
|
else
|
174
|
-
t =
|
185
|
+
t = @single_left_quote
|
175
186
|
end
|
176
187
|
elsif t == '"'
|
177
188
|
# Special case: single-character " token
|
178
|
-
if prev_token_last_char =~
|
179
|
-
t =
|
189
|
+
if prev_token_last_char =~ NON_WHITESPACE_CHARS
|
190
|
+
t = @double_right_quote
|
180
191
|
else
|
181
|
-
t =
|
192
|
+
t = @double_left_quote
|
182
193
|
end
|
183
194
|
else
|
184
195
|
# Normal case:
|
@@ -186,7 +197,7 @@ class RubyPants < String
|
|
186
197
|
end
|
187
198
|
end
|
188
199
|
|
189
|
-
t = stupefy_entities t
|
200
|
+
t = stupefy_entities t if do_stupefy
|
190
201
|
end
|
191
202
|
|
192
203
|
prev_token_last_char = last_char
|
@@ -227,6 +238,7 @@ class RubyPants < String
|
|
227
238
|
|
228
239
|
DOUBLE_DASH = n_of(2, '-')
|
229
240
|
TRIPLE_DASH = n_of(3, '-')
|
241
|
+
TRIPLE_DOTS = n_of(3, '.')
|
230
242
|
|
231
243
|
# Return +str+ replacing all +patt+ with +repl+. If +prevent_breaks+ is true,
|
232
244
|
# then replace spaces preceding +patt+ with a non-breaking space, and if there
|
@@ -250,7 +262,7 @@ class RubyPants < String
|
|
250
262
|
# em-dash HTML entity.
|
251
263
|
#
|
252
264
|
def educate_dashes(str, prevent_breaks=false)
|
253
|
-
educate(str, DOUBLE_DASH,
|
265
|
+
educate(str, DOUBLE_DASH, @em_dash, prevent_breaks)
|
254
266
|
end
|
255
267
|
|
256
268
|
# Return the string, with each instance of "<tt>--</tt>" translated to an
|
@@ -258,8 +270,8 @@ class RubyPants < String
|
|
258
270
|
# em-dash HTML entity.
|
259
271
|
#
|
260
272
|
def educate_dashes_oldschool(str, prevent_breaks=false)
|
261
|
-
str = educate(str, TRIPLE_DASH,
|
262
|
-
educate(str, DOUBLE_DASH,
|
273
|
+
str = educate(str, TRIPLE_DASH, @em_dash, prevent_breaks)
|
274
|
+
educate(str, DOUBLE_DASH, @en_dash, prevent_breaks)
|
263
275
|
end
|
264
276
|
|
265
277
|
# Return the string, with each instance of "<tt>--</tt>" translated
|
@@ -273,18 +285,20 @@ class RubyPants < String
|
|
273
285
|
# Aaron Swartz for the idea.)
|
274
286
|
#
|
275
287
|
def educate_dashes_inverted(str, prevent_breaks=false)
|
276
|
-
str = educate(str, TRIPLE_DASH,
|
277
|
-
educate(str, DOUBLE_DASH,
|
288
|
+
str = educate(str, TRIPLE_DASH, @en_dash, prevent_breaks)
|
289
|
+
educate(str, DOUBLE_DASH, @em_dash, prevent_breaks)
|
278
290
|
end
|
279
291
|
|
292
|
+
SPACED_ELLIPSIS_PATTERN = /(?<!\.|\.[ ])\.[ ]\.[ ]\.(?!\.|[ ]\.)/
|
293
|
+
|
280
294
|
# Return the string, with each instance of "<tt>...</tt>" translated
|
281
295
|
# to an ellipsis HTML entity. Also converts the case where there are
|
282
296
|
# spaces between the dots.
|
283
297
|
#
|
284
298
|
def educate_ellipses(str, prevent_breaks=false)
|
285
|
-
str = educate(str,
|
286
|
-
educate(str,
|
287
|
-
|
299
|
+
str = educate(str, TRIPLE_DOTS, @ellipsis, prevent_breaks)
|
300
|
+
educate(str, SPACED_ELLIPSIS_PATTERN,
|
301
|
+
@ellipsis, prevent_breaks)
|
288
302
|
end
|
289
303
|
|
290
304
|
# Return the string, with "<tt>``backticks''</tt>"-style single quotes
|
@@ -292,8 +306,8 @@ class RubyPants < String
|
|
292
306
|
#
|
293
307
|
def educate_backticks(str)
|
294
308
|
str.
|
295
|
-
gsub("``",
|
296
|
-
gsub("''",
|
309
|
+
gsub("``", @double_left_quote).
|
310
|
+
gsub("''", @double_right_quote)
|
297
311
|
end
|
298
312
|
|
299
313
|
# Return the string, with "<tt>`backticks'</tt>"-style single quotes
|
@@ -301,66 +315,79 @@ class RubyPants < String
|
|
301
315
|
#
|
302
316
|
def educate_single_backticks(str)
|
303
317
|
str.
|
304
|
-
gsub("`",
|
305
|
-
gsub("'",
|
318
|
+
gsub("`", @single_left_quote).
|
319
|
+
gsub("'", @single_right_quote)
|
306
320
|
end
|
307
321
|
|
322
|
+
PUNCT_CLASS = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]'.freeze
|
323
|
+
SNGL_QUOT_PUNCT_CASE = /^'(?=#{PUNCT_CLASS}\B)/
|
324
|
+
DBLE_QUOT_PUNCT_CASE = /^"(?=#{PUNCT_CLASS}\B)/
|
325
|
+
|
326
|
+
STARTS_MIXED_QUOTS_WITH_SNGL = /'"(?=\w)/
|
327
|
+
STARTS_MIXED_QUOTS_WITH_DBLE = /"'(?=\w)/
|
328
|
+
|
329
|
+
DECADE_ABBR_CASE = /'(?=\d\ds)/
|
330
|
+
|
331
|
+
CLOSE_CLASS = '[^\ \t\r\n\\[\{\(\-]'.freeze
|
332
|
+
CHAR_LEADS_SNGL_QUOTE = /(#{CLOSE_CLASS})'/
|
333
|
+
WHITESPACE_TRAILS_SNGL_QUOTE = /'(\s|s\b|$)/
|
334
|
+
CHAR_LEADS_DBLE_QUOTE = /(#{CLOSE_CLASS})"/
|
335
|
+
WHITESPACE_TRAILS_DBLE_QUOTE = /"(\s|s\b|$)/
|
336
|
+
|
308
337
|
# Return the string, with "educated" curly quote HTML entities.
|
309
338
|
#
|
310
339
|
def educate_quotes(str)
|
311
|
-
punct_class = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]'
|
312
|
-
|
313
340
|
str = str.dup
|
314
341
|
|
315
342
|
# Special case if the very first character is a quote followed by
|
316
343
|
# punctuation at a non-word-break. Close the quotes by brute
|
317
344
|
# force:
|
318
|
-
str.gsub!(
|
319
|
-
|
320
|
-
str.gsub!(
|
321
|
-
|
345
|
+
str.gsub!(SNGL_QUOT_PUNCT_CASE,
|
346
|
+
@single_right_quote)
|
347
|
+
str.gsub!(DBLE_QUOT_PUNCT_CASE,
|
348
|
+
@double_right_quote)
|
322
349
|
|
323
350
|
# Special case for double sets of quotes, e.g.:
|
324
351
|
# <p>He said, "'Quoted' words in a larger quote."</p>
|
325
|
-
str.gsub!(
|
326
|
-
"#{
|
327
|
-
str.gsub!(
|
328
|
-
"#{
|
352
|
+
str.gsub!(STARTS_MIXED_QUOTS_WITH_DBLE,
|
353
|
+
"#{@double_left_quote}#{@single_left_quote}")
|
354
|
+
str.gsub!(STARTS_MIXED_QUOTS_WITH_SNGL,
|
355
|
+
"#{@single_left_quote}#{@double_left_quote}")
|
329
356
|
|
330
357
|
# Special case for decade abbreviations (the '80s):
|
331
|
-
str.gsub!(
|
332
|
-
|
358
|
+
str.gsub!(DECADE_ABBR_CASE,
|
359
|
+
@single_right_quote)
|
333
360
|
|
334
|
-
|
335
|
-
|
361
|
+
dec_dashes = "#{@en_dash}|#{@em_dash}"
|
362
|
+
quote_precedent = "[[:space:]]| |--|&[mn]dash;|#{dec_dashes}|ȁ[34];"
|
336
363
|
|
337
364
|
# Get most opening single quotes:
|
338
|
-
str.gsub!(/(
|
339
|
-
'\1' +
|
365
|
+
str.gsub!(/(#{quote_precedent})'(?=\w)/,
|
366
|
+
'\1' + @single_left_quote)
|
340
367
|
|
341
368
|
# Single closing quotes:
|
342
|
-
str.gsub!(
|
343
|
-
'\1' +
|
344
|
-
str.gsub!(
|
345
|
-
|
369
|
+
str.gsub!(CHAR_LEADS_SNGL_QUOTE,
|
370
|
+
'\1' + @single_right_quote)
|
371
|
+
str.gsub!(WHITESPACE_TRAILS_SNGL_QUOTE,
|
372
|
+
@single_right_quote + '\1')
|
346
373
|
|
347
374
|
# Any remaining single quotes should be opening ones:
|
348
|
-
str.gsub!(
|
349
|
-
|
375
|
+
str.gsub!("'",
|
376
|
+
@single_left_quote)
|
350
377
|
|
351
378
|
# Get most opening double quotes:
|
352
|
-
str.gsub!(/(
|
353
|
-
'\1' +
|
379
|
+
str.gsub!(/(#{quote_precedent})"(?=\w)/,
|
380
|
+
'\1' + @double_left_quote)
|
354
381
|
|
355
382
|
# Double closing quotes:
|
356
|
-
str.gsub!(
|
357
|
-
'\1' +
|
358
|
-
str.gsub!(
|
359
|
-
|
383
|
+
str.gsub!(CHAR_LEADS_DBLE_QUOTE,
|
384
|
+
'\1' + @double_right_quote)
|
385
|
+
str.gsub!(WHITESPACE_TRAILS_DBLE_QUOTE,
|
386
|
+
@double_right_quote + '\1')
|
360
387
|
|
361
388
|
# Any remaining quotes should be opening ones:
|
362
|
-
str.gsub!(
|
363
|
-
|
389
|
+
str.gsub!('"',
|
390
|
+
@double_left_quote)
|
364
391
|
|
365
392
|
str
|
366
393
|
end
|
@@ -382,12 +409,14 @@ class RubyPants < String
|
|
382
409
|
:double_right_quote => '"',
|
383
410
|
:ellipsis => '...'
|
384
411
|
}.each do |k,v|
|
385
|
-
new_str.gsub!(
|
412
|
+
new_str.gsub!(entity(k).to_s, v)
|
386
413
|
end
|
387
414
|
|
388
415
|
new_str
|
389
416
|
end
|
390
417
|
|
418
|
+
TAG_SOUP = /([^<]*)(<!--.*?-->|<[^>]*>)/m
|
419
|
+
|
391
420
|
# Return an array of the tokens comprising the string. Each token is
|
392
421
|
# either a tag (possibly with nested, tags contained therein, such
|
393
422
|
# as <tt><a href="<MTFoo>"></tt>, or a run of text between
|
@@ -401,14 +430,12 @@ class RubyPants < String
|
|
401
430
|
# Chad Miller in the Python port of SmartyPants.
|
402
431
|
#
|
403
432
|
def tokenize
|
404
|
-
tag_soup = /([^<]*)(<!--.*?-->|<[^>]*>)/m
|
405
|
-
|
406
433
|
tokens = []
|
407
434
|
|
408
435
|
prev_end = 0
|
409
436
|
|
410
|
-
scan(
|
411
|
-
tokens << [:text, $1]
|
437
|
+
scan(TAG_SOUP) do
|
438
|
+
tokens << [:text, $1] if $1 != ""
|
412
439
|
tokens << [:tag, $2]
|
413
440
|
prev_end = $~.end(0)
|
414
441
|
end
|
data/lib/version.rb
CHANGED
data/test/rubypants_test.rb
CHANGED
@@ -11,6 +11,10 @@ class RubyPantsTest < Minitest::Test
|
|
11
11
|
assert_equal orig, RubyPants.new(str, options, entities).to_html
|
12
12
|
end
|
13
13
|
|
14
|
+
def refute_rp_equal(str, orig, options=[2], entities = {})
|
15
|
+
refute_equal orig, RubyPants.new(str, options, entities).to_html
|
16
|
+
end
|
17
|
+
|
14
18
|
def assert_verbatim(str)
|
15
19
|
assert_rp_equal str, str
|
16
20
|
end
|
@@ -152,6 +156,28 @@ EOF
|
|
152
156
|
assert_rp_equal "foo. . . .bar", 'foo. . . .bar', [:ellipses, :prevent_breaks]
|
153
157
|
assert_rp_equal "foo . . . . bar", 'foo . . . . bar', [:ellipses, :prevent_breaks]
|
154
158
|
|
159
|
+
# dots and tab-spaces
|
160
|
+
refute_rp_equal "foo. . .bar", 'foo…bar', [:ellipses]
|
161
|
+
refute_rp_equal "foo . . . bar", 'foo … bar', [:ellipses]
|
162
|
+
assert_rp_equal "foo. . . .bar", 'foo. . . .bar', [:ellipses]
|
163
|
+
assert_rp_equal "foo . . . . bar", 'foo . . . . bar', [:ellipses]
|
164
|
+
# and with :prevent_breaks
|
165
|
+
refute_rp_equal "foo. . .bar", 'foo⁠…bar', [:ellipses, :prevent_breaks]
|
166
|
+
refute_rp_equal "foo . . . bar", 'foo … bar', [:ellipses, :prevent_breaks]
|
167
|
+
assert_rp_equal "foo. . . .bar", 'foo. . . .bar', [:ellipses, :prevent_breaks]
|
168
|
+
assert_rp_equal "foo . . . . bar", 'foo . . . . bar', [:ellipses, :prevent_breaks]
|
169
|
+
|
170
|
+
# dots and line-breaks
|
171
|
+
refute_rp_equal "foo.\n.\n.bar", 'foo…bar', [:ellipses]
|
172
|
+
refute_rp_equal "foo\n.\n.\n.\nbar", "foo\n…\nbar", [:ellipses]
|
173
|
+
assert_rp_equal "foo.\n.\n.\n.bar", "foo.\n.\n.\n.bar", [:ellipses]
|
174
|
+
assert_rp_equal "foo\n.\n.\n.\n.\nbar", "foo\n.\n.\n.\n.\nbar", [:ellipses]
|
175
|
+
# and with :prevent_breaks
|
176
|
+
refute_rp_equal "foo.\n.\n.bar", "foo⁠…bar", [:ellipses, :prevent_breaks]
|
177
|
+
refute_rp_equal "foo\n.\n.\n.\nbar", "foo …\nbar", [:ellipses, :prevent_breaks]
|
178
|
+
assert_rp_equal "foo.\n.\n.\n.bar", "foo.\n.\n.\n.bar", [:ellipses, :prevent_breaks]
|
179
|
+
assert_rp_equal "foo\n.\n.\n.\n.\nbar", "foo\n.\n.\n.\n.\nbar", [:ellipses, :prevent_breaks]
|
180
|
+
|
155
181
|
# nasty ones
|
156
182
|
assert_rp_equal "foo. . ..bar", 'foo. . ..bar', [:ellipses]
|
157
183
|
assert_rp_equal "foo. . ...bar", 'foo. . …bar', [:ellipses]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubypants
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Gruber
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2019-12-30 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: minitest
|
@@ -68,8 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
70
|
requirements: []
|
71
|
-
|
72
|
-
rubygems_version: 2.6.13
|
71
|
+
rubygems_version: 3.0.3
|
73
72
|
signing_key:
|
74
73
|
specification_version: 4
|
75
74
|
summary: RubyPants is a Ruby port of the smart-quotes library SmartyPants.
|