rubypants 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8dc4efc96c1fe85653d5cfb4f6d0291a94edcdbc
4
- data.tar.gz: b17cda053df199efe900caed483404b903345f9c
2
+ SHA256:
3
+ metadata.gz: 766f0400e12ec2e5bb64917568fcf5dba1b7fdf7e31632c62144602e0b1bd674
4
+ data.tar.gz: 87de02ec38116b4d9d179e80f958f608101565a9724f63a751e7efb642dab7ff
5
5
  SHA512:
6
- metadata.gz: eaebe94dfee7f1ef9295910593ff64e0b10a5147ab96e802e7ce98031a15ee4e6c78ae7ee45ccadccaeb30d2c86d96692a2625733bb6e3f7edcda3ecd995c1a6
7
- data.tar.gz: 3eabe14d2d081f67239047c29d7d71e93025622cdd3f562b1f3fd2b83a26cddea359e2fbc8a20d3f9ca9f0c855c12c4fe3f76e16442e6f2898a6dc346f2e6f4e
6
+ metadata.gz: 543191639285ce9c53716b19fcbfa72dd6b14e96f53cb88b87a62f5cf4446725ceeb384c6ea3c7767c97409195d7e5cb11c8694d06eb93545284b230b2407bf0
7
+ data.tar.gz: ed420062908b83fa18c96bb8048870095350f4d9b45ac2294939a9265f775c04a1aa4c5d7e40ed8b3bee741a013103be0bf218e4d18e4e0e59dbbe3eb6cd2fc0
@@ -1,8 +1,7 @@
1
1
  rvm:
2
- - 2.0
3
- - 2.1
4
- - 2.2
5
- - 2.3.0
2
+ - 2.4
3
+ - 2.5
4
+ - 2.6
6
5
  - jruby
7
6
 
8
7
  # Workaround for `NoMethodError: undefined method 'spec' for nil:NilClass`,
@@ -70,12 +70,23 @@ class RubyPants < String
70
70
 
71
71
  @options = [*options]
72
72
  @entities = default_entities
73
- @entities.merge!(named_entities) if @options.include?(: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) if @options.include?(: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 if @options.include?(:quotes)
106
- do_backticks = true if @options.include?(:backticks)
107
- do_backticks = :both if @options.include?(:allbackticks)
108
- do_dashes = :normal if @options.include?(:dashes)
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 if @options.include?(:inverted)
111
- prevent_breaks = true if @options.include?(:prevent_breaks)
112
- do_ellipses = true if @options.include?(:ellipses)
113
- convert_quotes = true if @options.include?(:convertquotes)
114
- do_stupefy = true if @options.include?(:stupefy)
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] =~ %r!\A<(/?)(pre|code|kbd|script|style|math)[\s>]!
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!(/&quot;/, '"') if convert_quotes
163
+ t.gsub!('&quot;', '"') if convert_quotes
153
164
 
154
165
  if do_dashes
155
- t = educate_dashes t, prevent_breaks if do_dashes == :normal
156
- t = educate_dashes_oldschool t, prevent_breaks if do_dashes == :oldschool
157
- t = educate_dashes_inverted t, prevent_breaks if do_dashes == :inverted
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 if do_ellipses
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 if do_backticks == :both
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 =~ /\S/
172
- t = entity(:single_right_quote)
182
+ if prev_token_last_char =~ NON_WHITESPACE_CHARS
183
+ t = @single_right_quote
173
184
  else
174
- t = entity(:single_left_quote)
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 =~ /\S/
179
- t = entity(:double_right_quote)
189
+ if prev_token_last_char =~ NON_WHITESPACE_CHARS
190
+ t = @double_right_quote
180
191
  else
181
- t = entity(:double_left_quote)
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 if do_stupefy
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, entity(:em_dash), prevent_breaks)
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, entity(:em_dash), prevent_breaks)
262
- educate(str, DOUBLE_DASH, entity(:en_dash), prevent_breaks)
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, entity(:en_dash), prevent_breaks)
277
- educate(str, DOUBLE_DASH, entity(:em_dash), prevent_breaks)
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, RubyPants.n_of(3, '.'), entity(:ellipsis), prevent_breaks)
286
- educate(str, /(?<!\.|\.[[:space:]])\.[[:space:]]\.[[:space:]]\.(?!\.|[[:space:]]\.)/,
287
- entity(:ellipsis), prevent_breaks)
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("``", entity(:double_left_quote)).
296
- gsub("''", entity(:double_right_quote))
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("`", entity(:single_left_quote)).
305
- gsub("'", entity(:single_right_quote))
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!(/^'(?=#{punct_class}\B)/,
319
- entity(:single_right_quote))
320
- str.gsub!(/^"(?=#{punct_class}\B)/,
321
- entity(:double_right_quote))
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!(/"'(?=\w)/,
326
- "#{entity(:double_left_quote)}#{entity(:single_left_quote)}")
327
- str.gsub!(/'"(?=\w)/,
328
- "#{entity(:single_left_quote)}#{entity(:double_left_quote)}")
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!(/'(?=\d\ds)/,
332
- entity(:single_right_quote))
358
+ str.gsub!(DECADE_ABBR_CASE,
359
+ @single_right_quote)
333
360
 
334
- close_class = %![^\ \t\r\n\\[\{\(\-]!
335
- dec_dashes = "#{entity(:en_dash)}|#{entity(:em_dash)}"
361
+ dec_dashes = "#{@en_dash}|#{@em_dash}"
362
+ quote_precedent = "[[:space:]]|&nbsp;|--|&[mn]dash;|#{dec_dashes}|&#x201[34];"
336
363
 
337
364
  # Get most opening single quotes:
338
- str.gsub!(/([[:space:]]|&nbsp;|--|&[mn]dash;|#{dec_dashes}|&#x201[34];)'(?=\w)/,
339
- '\1' + entity(:single_left_quote))
365
+ str.gsub!(/(#{quote_precedent})'(?=\w)/,
366
+ '\1' + @single_left_quote)
340
367
 
341
368
  # Single closing quotes:
342
- str.gsub!(/(#{close_class})'/,
343
- '\1' + entity(:single_right_quote))
344
- str.gsub!(/'(\s|s\b|$)/,
345
- entity(:single_right_quote) + '\1')
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
- entity(:single_left_quote))
375
+ str.gsub!("'",
376
+ @single_left_quote)
350
377
 
351
378
  # Get most opening double quotes:
352
- str.gsub!(/([[:space:]]|&nbsp;|--|&[mn]dash;|#{dec_dashes}|&#x201[34];)"(?=\w)/,
353
- '\1' + entity(:double_left_quote))
379
+ str.gsub!(/(#{quote_precedent})"(?=\w)/,
380
+ '\1' + @double_left_quote)
354
381
 
355
382
  # Double closing quotes:
356
- str.gsub!(/(#{close_class})"/,
357
- '\1' + entity(:double_right_quote))
358
- str.gsub!(/"(\s|s\b|$)/,
359
- entity(:double_right_quote) + '\1')
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
- entity(:double_left_quote))
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!(/#{entity(k)}/, v)
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(tag_soup) do
411
- tokens << [:text, $1] if $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
@@ -1,3 +1,3 @@
1
1
  module RubyPantsVersion
2
- VERSION = "0.7.0"
2
+ VERSION = "0.7.1"
3
3
  end
@@ -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&#8230;bar', [:ellipses]
161
+ refute_rp_equal "foo . . . bar", 'foo &#8230; 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&#8288;&#8230;bar', [:ellipses, :prevent_breaks]
166
+ refute_rp_equal "foo . . . bar", 'foo&nbsp;&#8230; 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&#8230;bar', [:ellipses]
172
+ refute_rp_equal "foo\n.\n.\n.\nbar", "foo\n&#8230;\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&#8288;&#8230;bar", [:ellipses, :prevent_breaks]
177
+ refute_rp_equal "foo\n.\n.\n.\nbar", "foo&nbsp;&#8230;\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. . &#8230;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.0
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: 2018-02-26 00:00:00.000000000 Z
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
- rubyforge_project:
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.