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 +8 -0
- data/VERSION +1 -1
- data/lib/typogruby.rb +51 -20
- data/test/test_typogruby.rb +7 -0
- metadata +4 -4
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.
|
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
|
58
|
-
|
58
|
+
ignore_scripts(text) do |t|
|
59
|
+
t.gsub(/<(code|pre).+?<\/\1>|(\s| )&(?:amp;|#38;)?(\s| )/) { |str|
|
60
|
+
$1 ? str : $2 + '<span class="amp">&</span>' + $3
|
61
|
+
}.gsub(/(\w+)="(.*?)<span class="amp">&<\/span>(.*?)"/, '\1="\2&\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
|
106
|
-
(
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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?(' ') ? ' ' : ' ') + $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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
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| |^|'|"|>)([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
|
178
|
+
ignore_scripts(text) do |t|
|
179
|
+
t.gsub(/((?:<(?:h[1-6]|p|li|dt|dd)[^>]*>|^)\s*(?:<(?:a|em|strong|span)[^>]*>)?)('|‘|‘|("|“|“))/) {$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
|
data/test/test_typogruby.rb
CHANGED
@@ -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">&</span> two', amp('One <span class="amp">&</span> two')
|
14
14
|
assert_equal '“this” <span class="amp">&</span> <a href="/?that&test">that</a>', amp('“this” & <a href="/?that&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">‘</span>With manual quotes’', initial_quotes('‘With manual quotes’')
|
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 “Green” 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 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:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
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-
|
18
|
+
date: 2010-08-17 00:00:00 +02:00
|
19
19
|
default_executable: typogruby
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|