typogruby 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
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