typogruby 1.0.5 → 1.0.6

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.
data/README.md CHANGED
@@ -47,6 +47,14 @@ This will output the contents of your file with all filters applied. Use `typogr
47
47
 
48
48
  ## Changelog
49
49
 
50
+ ### 1.0.6
51
+
52
+ * Bugfix: ignore inline javascript
53
+
54
+ ### 1.0.5
55
+
56
+ * Manage gem dependencies using Bundler
57
+
50
58
  ### 1.0.4
51
59
 
52
60
  * Bugfix: no longer regard combination of digits and periods as caps.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.5
1
+ 1.0.6
data/lib/typogruby.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rubypants'
2
+ require 'digest/md5'
2
3
 
3
4
  # A collection of simple helpers for improving web
4
5
  # typograhy. Based on TypographyHelper by Luke Hartman and Typogrify.
@@ -54,8 +55,11 @@ module Typogruby
54
55
  # @return [String] input text with ampersands wrapped
55
56
  def amp(text)
56
57
  # $1 is an excluded HTML tag, $2 is the part before the caps and $3 is the amp match
57
- text.gsub(/<(code|pre).+?<\/\1>|(\s|&nbsp;)&(?:amp;|#38;)?(\s|&nbsp;)/) {|str|
58
- $1 ? str : $2 + '<span class="amp">&amp;</span>' + $3 }.gsub(/(\w+)="(.*?)<span class="amp">&amp;<\/span>(.*?)"/, '\1="\2&amp;\3"')
58
+ ignore_scripts(text) do |t|
59
+ t.gsub(/<(code|pre).+?<\/\1>|(\s|&nbsp;)&(?:amp;|#38;)?(\s|&nbsp;)/) { |str|
60
+ $1 ? str : $2 + '<span class="amp">&amp;</span>' + $3
61
+ }.gsub(/(\w+)="(.*?)<span class="amp">&amp;<\/span>(.*?)"/, '\1="\2&amp;\3"')
62
+ end
59
63
  end
60
64
 
61
65
  # replaces space(s) before the last word (or tag before the last word)
@@ -102,14 +106,16 @@ module Typogruby
102
106
  # @param [String] text input text
103
107
  # @return [String] input text with non-breaking spaces inserted
104
108
  def widont(text)
105
- text.gsub(%r{
106
- ((?:</?(?:a|em|span|strong|i|b)[^>]*>)|[^<>\s]) # must be proceeded by an approved inline opening or closing tag or a nontag/nonspace
107
- \s+ # the space to replace
108
- (([^<>\s]+) # must be flollowed by non-tag non-space characters
109
- \s* # optional white space!
110
- (</(a|em|span|strong|i|b)>\s*)* # optional closing inline tags with optional white space after each
111
- ((</(p|h[1-6]|li|dt|dd)>)|$)) # end with a closing p, h1-6, li or the end of the string
112
- }x) { |match| $1 + (match.include?('&nbsp;') ? ' ' : '&nbsp;') + $2 } # Make sure to not add another nbsp before one already there
109
+ ignore_scripts(text) do |t|
110
+ t.gsub(%r{
111
+ ((?:</?(?:a|em|span|strong|i|b)[^>]*>)|[^<>\s]) # must be proceeded by an approved inline opening or closing tag or a nontag/nonspace
112
+ \s+ # the space to replace
113
+ (([^<>\s]+) # must be flollowed by non-tag non-space characters
114
+ \s* # optional white space!
115
+ (</(a|em|span|strong|i|b)>\s*)* # optional closing inline tags with optional white space after each
116
+ ((</(p|h[1-6]|li|dt|dd)>)|$)) # end with a closing p, h1-6, li or the end of the string
117
+ }x) { |match| $1 + (match.include?('&nbsp;') ? ' ' : '&nbsp;') + $2 } # Make sure to not add another nbsp before one already there
118
+ end
113
119
  end
114
120
 
115
121
  # surrounds two or more consecutive captial letters, perhaps with interspersed digits and periods
@@ -132,15 +138,17 @@ module Typogruby
132
138
  # @param [String] text input text
133
139
  # @return [String] input text with caps wrapped
134
140
  def caps(text)
135
- # $1 is an excluded HTML tag, $2 is the part before the caps and $3 is the caps match
136
- text.gsub(/<(?i)(code|pre)(?-i).+?<(?i)\/\1(?-i)>|(\s|&nbsp;|^|'|"|>)([A-Z\d][A-Z\d\.']{1,})(?!\w)/) do |str|
137
- excluded, before, caps = $1, $2, $3
138
- if excluded
139
- str
140
- elsif $3 =~ /^[\d\.]+$/
141
- before + caps
142
- else
143
- before + '<span class="caps">' + caps + '</span>'
141
+ ignore_scripts(text) do |t|
142
+ # $1 is an excluded HTML tag, $2 is the part before the caps and $3 is the caps match
143
+ t.gsub(/<(?i)(code|pre)(?-i).+?<(?i)\/\1(?-i)>|(\s|&nbsp;|^|'|"|>)([A-Z\d][A-Z\d\.']{1,})(?!\w)/) do |str|
144
+ excluded, before, caps = $1, $2, $3
145
+ if excluded
146
+ str
147
+ elsif $3 =~ /^[\d\.]+$/
148
+ before + caps
149
+ else
150
+ before + '<span class="caps">' + caps + '</span>'
151
+ end
144
152
  end
145
153
  end
146
154
  end
@@ -167,7 +175,9 @@ module Typogruby
167
175
  # @return [String] input text with initial quotes wrapped
168
176
  def initial_quotes(text)
169
177
  # $1 is the initial part of the string, $2 is the quote or entitity, and $3 is the double quote
170
- text.gsub(/((?:<(?:h[1-6]|p|li|dt|dd)[^>]*>|^)\s*(?:<(?:a|em|strong|span)[^>]*>)?)('|&#8216;|&lsquo;|("|&#8220;|&ldquo;))/) {$1 + "<span class=\"#{'d' if $3}quo\">#{$2}</span>"}
178
+ ignore_scripts(text) do |t|
179
+ t.gsub(/((?:<(?:h[1-6]|p|li|dt|dd)[^>]*>|^)\s*(?:<(?:a|em|strong|span)[^>]*>)?)('|&#8216;|&lsquo;|("|&#8220;|&ldquo;))/) {$1 + "<span class=\"#{'d' if $3}quo\">#{$2}</span>"}
180
+ end
171
181
  end
172
182
 
173
183
  # main function to do all the functions from the method
@@ -177,5 +187,26 @@ module Typogruby
177
187
  initial_quotes(caps(smartypants(widont(amp(text)))))
178
188
  end
179
189
 
190
+ private
191
+
192
+ # Hackish text filter that will make sure our text filters leave inline
193
+ # javascript alone without resorting to a full-blown HTML parser.
194
+ #
195
+ # The idea is simple: every text filter is applied as a block to this
196
+ # method. This will preprocess the text and replace any inline scripts
197
+ # with a MD5 hash of its entire contents. Then the filter is called,
198
+ # and then the hashes are replaced back with their original content.
199
+ def ignore_scripts(text)
200
+ @ignored_scripts = {}
201
+ modified_text = text.gsub(/<script[^>]*>.*?<\/script>/mi) do |script|
202
+ hash = Digest::MD5.hexdigest(script)
203
+ @ignored_scripts[hash] = script
204
+ hash
205
+ end
206
+ yield(modified_text).gsub(/#{@ignored_scripts.keys.join('|')}/) do |h|
207
+ @ignored_scripts.delete(h)
208
+ end
209
+ end
210
+
180
211
  extend self
181
212
  end
@@ -12,6 +12,7 @@ class TestTypogruby < Test::Unit::TestCase
12
12
  def test_should_ignore_special_amps
13
13
  assert_equal 'One <span class="amp">&amp;</span> two', amp('One <span class="amp">&amp;</span> two')
14
14
  assert_equal '&ldquo;this&rdquo; <span class="amp">&amp;</span> <a href="/?that&amp;test">that</a>', amp('&ldquo;this&rdquo; & <a href="/?that&amp;test">that</a>')
15
+ assert_equal %Q{<script>\nvar x = "FOO & BAR";\n</script>"}, initial_quotes(%Q{<script>\nvar x = "FOO & BAR";\n</script>"})
15
16
  end
16
17
 
17
18
  def test_should_ignore_standalone_amps_in_attributes
@@ -28,6 +29,7 @@ class TestTypogruby < Test::Unit::TestCase
28
29
  assert_equal '<Pre>CAPS</PRE> with odd tag names <span class="caps">CAPS</span>', caps("<Pre>CAPS</PRE> with odd tag names CAPS")
29
30
  assert_equal 'A message from <span class="caps">2KU2</span> with digits', caps("A message from 2KU2 with digits")
30
31
  assert_equal 'Dotted caps followed by spaces should never include them in the wrap <span class="caps">D.O.T.</span> like so.', caps("Dotted caps followed by spaces should never include them in the wrap D.O.T. like so.")
32
+ assert_equal %Q{<script>\nvar x = "FOO BAR and BAZ";\n</script>"}, initial_quotes(%Q{<script>\nvar x = "FOO BAR and BAZ";\n</script>"})
31
33
  end
32
34
 
33
35
  def test_should_not_break_caps_with_apostrophes
@@ -43,6 +45,10 @@ class TestTypogruby < Test::Unit::TestCase
43
45
  assert_equal '<span class="quo">&lsquo;</span>With manual quotes&rsquo;', initial_quotes('&lsquo;With manual quotes&rsquo;')
44
46
  end
45
47
 
48
+ def test_should_not_replace_quotes_in_scripts
49
+ assert_equal %Q{<script>\nvar x = "foo" +\n"bar";\n</script>"}, initial_quotes(%Q{<script>\nvar x = "foo" +\n"bar";\n</script>"})
50
+ end
51
+
46
52
  def test_should_apply_smartypants
47
53
  assert_equal 'The &#8220;Green&#8221; man', smartypants('The "Green" man')
48
54
  end
@@ -76,6 +82,7 @@ class TestTypogruby < Test::Unit::TestCase
76
82
  def test_should_ignore_widows_in_special_tags
77
83
  assert_equal '<div>Divs get no love!</div>', widont('<div>Divs get no love!</div>')
78
84
  assert_equal '<pre>Neither do PREs</pre>', widont('<pre>Neither do PREs</pre>')
85
+ assert_equal "<script>\nreturn window;\n</script>", widont("<script>\nreturn window;\n</script>")
79
86
  assert_equal '<div><p>But divs with paragraphs&nbsp;do!</p></div>', widont('<div><p>But divs with paragraphs do!</p></div>')
80
87
  end
81
88
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typogruby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 5
10
- version: 1.0.5
9
+ - 6
10
+ version: 1.0.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - Arjan van der Gaag
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-10 00:00:00 +02:00
18
+ date: 2010-08-17 00:00:00 +02:00
19
19
  default_executable: typogruby
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency