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 +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
|