| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Text::SmartyPants; |
|
2
|
27
|
|
|
27
|
|
10484
|
use strict; |
|
|
27
|
|
|
|
|
67
|
|
|
|
27
|
|
|
|
|
866
|
|
|
3
|
27
|
|
|
27
|
|
140
|
use vars qw($VERSION); |
|
|
27
|
|
|
|
|
56
|
|
|
|
27
|
|
|
|
|
47348
|
|
|
4
|
|
|
|
|
|
|
$VERSION = "1.3"; |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# Configurable variables: |
|
7
|
|
|
|
|
|
|
my $smartypants_attr = "1"; |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# 1 => "--" for em-dashes; no en-dash support |
|
10
|
|
|
|
|
|
|
# 2 => "---" for em-dashes; "--" for en-dashes |
|
11
|
|
|
|
|
|
|
# 3 => "--" for em-dashes; "---" for en-dashes |
|
12
|
|
|
|
|
|
|
# See docs for more configuration options. |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# Globals: |
|
15
|
|
|
|
|
|
|
my $tags_to_skip = qr!<(/?)(?:pre|code|kbd|script)[\s>]!; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 Methods |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head2 process |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
Do the bulk of the conversion work. |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=cut |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub process { |
|
26
|
36
|
50
|
|
36
|
1
|
171
|
shift if ( $_[0] eq __PACKAGE__ ); # oops, called in OOP fashion. |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Paramaters: |
|
29
|
36
|
|
|
|
|
82
|
my $text = shift; # text to be parsed |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# value of the smart_quotes="" attribute. Default to 'everything on' |
|
32
|
36
|
|
50
|
|
|
195
|
my $attr = shift || '1'; |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Options to specify which transformations to make: |
|
35
|
36
|
|
|
|
|
93
|
my ( $do_quotes, $do_backticks, $do_dashes, $do_ellipses, $do_stupefy ); |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# should we translate " entities into normal quotes? |
|
38
|
36
|
|
|
|
|
79
|
my $convert_quot = 0; |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# Parse attributes: |
|
41
|
|
|
|
|
|
|
# 0 : do nothing |
|
42
|
|
|
|
|
|
|
# 1 : set all |
|
43
|
|
|
|
|
|
|
# 2 : set all, using old school en- and em- dash shortcuts |
|
44
|
|
|
|
|
|
|
# 3 : set all, using inverted old school en and em- dash shortcuts |
|
45
|
|
|
|
|
|
|
# |
|
46
|
|
|
|
|
|
|
# q : quotes |
|
47
|
|
|
|
|
|
|
# b : backtick quotes (``double'' only) |
|
48
|
|
|
|
|
|
|
# B : backtick quotes (``double'' and `single') |
|
49
|
|
|
|
|
|
|
# d : dashes |
|
50
|
|
|
|
|
|
|
# D : old school dashes |
|
51
|
|
|
|
|
|
|
# i : inverted old school dashes |
|
52
|
|
|
|
|
|
|
# e : ellipses |
|
53
|
|
|
|
|
|
|
# w : convert " entities to " for Dreamweaver users |
|
54
|
|
|
|
|
|
|
|
|
55
|
36
|
50
|
|
|
|
160
|
if ( $attr eq "0" ) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# Do nothing. |
|
58
|
0
|
|
|
|
|
0
|
return $text; |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
elsif ( $attr eq "1" ) { |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Do everything, turn all options on. |
|
63
|
36
|
|
|
|
|
72
|
$do_quotes = 1; |
|
64
|
36
|
|
|
|
|
65
|
$do_backticks = 1; |
|
65
|
36
|
|
|
|
|
65
|
$do_dashes = 1; |
|
66
|
36
|
|
|
|
|
61
|
$do_ellipses = 1; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
elsif ( $attr eq "2" ) { |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# Do everything, turn all options on, use old school dash shorthand. |
|
71
|
0
|
|
|
|
|
0
|
$do_quotes = 1; |
|
72
|
0
|
|
|
|
|
0
|
$do_backticks = 1; |
|
73
|
0
|
|
|
|
|
0
|
$do_dashes = 2; |
|
74
|
0
|
|
|
|
|
0
|
$do_ellipses = 1; |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
elsif ( $attr eq "3" ) { |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# Do everything, turn all options on, use inverted old school dash shorthand. |
|
79
|
0
|
|
|
|
|
0
|
$do_quotes = 1; |
|
80
|
0
|
|
|
|
|
0
|
$do_backticks = 1; |
|
81
|
0
|
|
|
|
|
0
|
$do_dashes = 3; |
|
82
|
0
|
|
|
|
|
0
|
$do_ellipses = 1; |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
elsif ( $attr eq "-1" ) { |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# Special "stupefy" mode. |
|
87
|
0
|
|
|
|
|
0
|
$do_stupefy = 1; |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
else { |
|
90
|
0
|
|
|
|
|
0
|
my @chars = split( //, $attr ); |
|
91
|
0
|
|
|
|
|
0
|
foreach my $c (@chars) { |
|
92
|
0
|
0
|
|
|
|
0
|
if ( $c eq "q" ) { $do_quotes = 1; } |
|
|
0
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
93
|
0
|
|
|
|
|
0
|
elsif ( $c eq "b" ) { $do_backticks = 1; } |
|
94
|
0
|
|
|
|
|
0
|
elsif ( $c eq "B" ) { $do_backticks = 2; } |
|
95
|
0
|
|
|
|
|
0
|
elsif ( $c eq "d" ) { $do_dashes = 1; } |
|
96
|
0
|
|
|
|
|
0
|
elsif ( $c eq "D" ) { $do_dashes = 2; } |
|
97
|
0
|
|
|
|
|
0
|
elsif ( $c eq "i" ) { $do_dashes = 3; } |
|
98
|
0
|
|
|
|
|
0
|
elsif ( $c eq "e" ) { $do_ellipses = 1; } |
|
99
|
0
|
|
|
|
|
0
|
elsif ( $c eq "w" ) { $convert_quot = 1; } |
|
100
|
|
|
|
|
|
|
else { |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# Unknown attribute option, ignore. |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
} |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
|
|
107
|
36
|
|
33
|
|
|
217
|
my $tokens ||= _tokenize($text); |
|
108
|
36
|
|
|
|
|
80
|
my $result = ''; |
|
109
|
36
|
|
|
|
|
79
|
my $in_pre = 0; # Keep track of when we're inside <pre> or <code> tags. |
|
110
|
|
|
|
|
|
|
|
|
111
|
36
|
|
|
|
|
71
|
my $prev_token_last_char = ""; # This is a cheat, used to get some context |
|
112
|
|
|
|
|
|
|
# for one-character tokens that consist of |
|
113
|
|
|
|
|
|
|
# just a quote char. What we do is remember |
|
114
|
|
|
|
|
|
|
# the last character of the previous text |
|
115
|
|
|
|
|
|
|
# token, to use as context to curl single- |
|
116
|
|
|
|
|
|
|
# character quote tokens correctly. |
|
117
|
|
|
|
|
|
|
|
|
118
|
36
|
|
|
|
|
101
|
foreach my $cur_token (@$tokens) { |
|
119
|
400
|
100
|
|
|
|
812
|
if ( $cur_token->[0] eq "tag" ) { |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# Don't mess with quotes inside tags. |
|
122
|
244
|
|
|
|
|
387
|
$result .= $cur_token->[1]; |
|
123
|
244
|
100
|
|
|
|
1018
|
if ( $cur_token->[1] =~ m/$tags_to_skip/ ) { |
|
124
|
39
|
100
|
66
|
|
|
232
|
$in_pre = defined $1 && $1 eq '/' ? 0 : 1; |
|
125
|
|
|
|
|
|
|
} |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
else { |
|
128
|
156
|
|
|
|
|
253
|
my $t = $cur_token->[1]; |
|
129
|
156
|
|
|
|
|
274
|
my $last_char = substr( $t, -1 ); # Remember last char of this token before processing. |
|
130
|
156
|
100
|
|
|
|
357
|
if ( !$in_pre ) { |
|
131
|
92
|
|
|
|
|
181
|
$t = ProcessEscapes($t); |
|
132
|
|
|
|
|
|
|
|
|
133
|
92
|
50
|
|
|
|
199
|
if ($convert_quot) { |
|
134
|
0
|
|
|
|
|
0
|
$t =~ s/"/"/g; |
|
135
|
|
|
|
|
|
|
} |
|
136
|
|
|
|
|
|
|
|
|
137
|
92
|
50
|
|
|
|
213
|
if ($do_dashes) { |
|
138
|
92
|
50
|
|
|
|
250
|
$t = EducateDashes($t) if ( $do_dashes == 1 ); |
|
139
|
92
|
50
|
|
|
|
195
|
$t = EducateDashesOldSchool($t) if ( $do_dashes == 2 ); |
|
140
|
92
|
50
|
|
|
|
189
|
$t = EducateDashesOldSchoolInverted($t) if ( $do_dashes == 3 ); |
|
141
|
|
|
|
|
|
|
} |
|
142
|
|
|
|
|
|
|
|
|
143
|
92
|
50
|
|
|
|
237
|
$t = EducateEllipses($t) if $do_ellipses; |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# Notes: backticks need to be processed before quotes. |
|
146
|
92
|
50
|
|
|
|
190
|
if ($do_backticks) { |
|
147
|
92
|
|
|
|
|
161
|
$t = EducateBackticks($t); |
|
148
|
92
|
50
|
|
|
|
200
|
$t = EducateSingleBackticks($t) if ( $do_backticks == 2 ); |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
|
|
151
|
92
|
50
|
|
|
|
182
|
if ($do_quotes) { |
|
152
|
92
|
50
|
|
|
|
232
|
if ( $t eq q/'/ ) { |
|
|
|
50
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# Special case: single-character ' token |
|
155
|
0
|
0
|
|
|
|
0
|
if ( $prev_token_last_char =~ m/\S/ ) { |
|
156
|
0
|
|
|
|
|
0
|
$t = "’"; |
|
157
|
|
|
|
|
|
|
} |
|
158
|
|
|
|
|
|
|
else { |
|
159
|
0
|
|
|
|
|
0
|
$t = "‘"; |
|
160
|
|
|
|
|
|
|
} |
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
elsif ( $t eq q/"/ ) { |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# Special case: single-character " token |
|
165
|
0
|
0
|
|
|
|
0
|
if ( $prev_token_last_char =~ m/\S/ ) { |
|
166
|
0
|
|
|
|
|
0
|
$t = "”"; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
else { |
|
169
|
0
|
|
|
|
|
0
|
$t = "“"; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
else { |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# Normal case: |
|
175
|
92
|
|
|
|
|
167
|
$t = EducateQuotes($t); |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
|
|
179
|
92
|
50
|
|
|
|
208
|
$t = StupefyEntities($t) if $do_stupefy; |
|
180
|
|
|
|
|
|
|
} |
|
181
|
156
|
|
|
|
|
239
|
$prev_token_last_char = $last_char; |
|
182
|
156
|
|
|
|
|
306
|
$result .= $t; |
|
183
|
|
|
|
|
|
|
} |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
36
|
|
|
|
|
216
|
return $result; |
|
187
|
|
|
|
|
|
|
} |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=head2 SmartQuotes |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
Quotes to entities. |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=cut |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
sub SmartQuotes { |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
# Paramaters: |
|
198
|
0
|
|
|
0
|
1
|
0
|
my $text = shift; # text to be parsed |
|
199
|
0
|
|
|
|
|
0
|
my $attr = shift; # value of the smart_quotes="" attribute |
|
200
|
|
|
|
|
|
|
|
|
201
|
0
|
|
|
|
|
0
|
my $do_backticks; # should we educate ``backticks'' -style quotes? |
|
202
|
|
|
|
|
|
|
|
|
203
|
0
|
0
|
|
|
|
0
|
if ( $attr == 0 ) { |
|
|
|
0
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# do nothing; |
|
206
|
0
|
|
|
|
|
0
|
return $text; |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
elsif ( $attr == 2 ) { |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
# smarten ``backticks'' -style quotes |
|
211
|
0
|
|
|
|
|
0
|
$do_backticks = 1; |
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
else { |
|
214
|
0
|
|
|
|
|
0
|
$do_backticks = 0; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
# Special case to handle quotes at the very end of $text when preceded by |
|
218
|
|
|
|
|
|
|
# an HTML tag. Add a space to give the quote education algorithm a bit of |
|
219
|
|
|
|
|
|
|
# context, so that it can guess correctly that it's a closing quote: |
|
220
|
0
|
|
|
|
|
0
|
my $add_extra_space = 0; |
|
221
|
0
|
0
|
|
|
|
0
|
if ( $text =~ m/>['"]\z/ ) { |
|
222
|
0
|
|
|
|
|
0
|
$add_extra_space = 1; # Remember, so we can trim the extra space later. |
|
223
|
0
|
|
|
|
|
0
|
$text .= " "; |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
0
|
|
0
|
|
|
0
|
my $tokens ||= _tokenize($text); |
|
227
|
0
|
|
|
|
|
0
|
my $result = ''; |
|
228
|
0
|
|
|
|
|
0
|
my $in_pre = 0; # Keep track of when we're inside <pre> or <code> tags |
|
229
|
|
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
0
|
my $prev_token_last_char = ""; # This is a cheat, used to get some context |
|
231
|
|
|
|
|
|
|
# for one-character tokens that consist of |
|
232
|
|
|
|
|
|
|
# just a quote char. What we do is remember |
|
233
|
|
|
|
|
|
|
# the last character of the previous text |
|
234
|
|
|
|
|
|
|
# token, to use as context to curl single- |
|
235
|
|
|
|
|
|
|
# character quote tokens correctly. |
|
236
|
|
|
|
|
|
|
|
|
237
|
0
|
|
|
|
|
0
|
foreach my $cur_token (@$tokens) { |
|
238
|
0
|
0
|
|
|
|
0
|
if ( $cur_token->[0] eq "tag" ) { |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
# Don't mess with quotes inside tags |
|
241
|
0
|
|
|
|
|
0
|
$result .= $cur_token->[1]; |
|
242
|
0
|
0
|
|
|
|
0
|
if ( $cur_token->[1] =~ m/$tags_to_skip/ ) { |
|
243
|
0
|
0
|
0
|
|
|
0
|
$in_pre = defined $1 && $1 eq '/' ? 0 : 1; |
|
244
|
|
|
|
|
|
|
} |
|
245
|
|
|
|
|
|
|
} |
|
246
|
|
|
|
|
|
|
else { |
|
247
|
0
|
|
|
|
|
0
|
my $t = $cur_token->[1]; |
|
248
|
0
|
|
|
|
|
0
|
my $last_char = substr( $t, -1 ); # Remember last char of this token before processing. |
|
249
|
0
|
0
|
|
|
|
0
|
if ( !$in_pre ) { |
|
250
|
0
|
|
|
|
|
0
|
$t = ProcessEscapes($t); |
|
251
|
0
|
0
|
|
|
|
0
|
if ($do_backticks) { |
|
252
|
0
|
|
|
|
|
0
|
$t = EducateBackticks($t); |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
0
|
0
|
|
|
|
0
|
if ( $t eq q/'/ ) { |
|
|
|
0
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# Special case: single-character ' token |
|
258
|
0
|
0
|
|
|
|
0
|
if ( $prev_token_last_char =~ m/\S/ ) { |
|
259
|
0
|
|
|
|
|
0
|
$t = "’"; |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
else { |
|
262
|
0
|
|
|
|
|
0
|
$t = "‘"; |
|
263
|
|
|
|
|
|
|
} |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
elsif ( $t eq q/"/ ) { |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# Special case: single-character " token |
|
268
|
0
|
0
|
|
|
|
0
|
if ( $prev_token_last_char =~ m/\S/ ) { |
|
269
|
0
|
|
|
|
|
0
|
$t = "”"; |
|
270
|
|
|
|
|
|
|
} |
|
271
|
|
|
|
|
|
|
else { |
|
272
|
0
|
|
|
|
|
0
|
$t = "“"; |
|
273
|
|
|
|
|
|
|
} |
|
274
|
|
|
|
|
|
|
} |
|
275
|
|
|
|
|
|
|
else { |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Normal case: |
|
278
|
0
|
|
|
|
|
0
|
$t = EducateQuotes($t); |
|
279
|
|
|
|
|
|
|
} |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
} |
|
282
|
0
|
|
|
|
|
0
|
$prev_token_last_char = $last_char; |
|
283
|
0
|
|
|
|
|
0
|
$result .= $t; |
|
284
|
|
|
|
|
|
|
} |
|
285
|
|
|
|
|
|
|
} |
|
286
|
|
|
|
|
|
|
|
|
287
|
0
|
0
|
|
|
|
0
|
if ($add_extra_space) { |
|
288
|
0
|
|
|
|
|
0
|
$result =~ s/ \z//; # Trim trailing space if we added one earlier. |
|
289
|
|
|
|
|
|
|
} |
|
290
|
0
|
|
|
|
|
0
|
return $result; |
|
291
|
|
|
|
|
|
|
} |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head2 SmartDashes |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Call the individual dash conversion to entities functions. |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=cut |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub SmartDashes { |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# Paramaters: |
|
302
|
0
|
|
|
0
|
1
|
0
|
my $text = shift; # text to be parsed |
|
303
|
0
|
|
|
|
|
0
|
my $attr = shift; # value of the smart_dashes="" attribute |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# reference to the subroutine to use for dash education, default to EducateDashes: |
|
306
|
0
|
|
|
|
|
0
|
my $dash_sub_ref = \&EducateDashes; |
|
307
|
|
|
|
|
|
|
|
|
308
|
0
|
0
|
|
|
|
0
|
if ( $attr == 0 ) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
# do nothing; |
|
311
|
0
|
|
|
|
|
0
|
return $text; |
|
312
|
|
|
|
|
|
|
} |
|
313
|
|
|
|
|
|
|
elsif ( $attr == 2 ) { |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# use old smart dash shortcuts, "--" for en, "---" for em |
|
316
|
0
|
|
|
|
|
0
|
$dash_sub_ref = \&EducateDashesOldSchool; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
elsif ( $attr == 3 ) { |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# inverse of 2, "--" for em, "---" for en |
|
321
|
0
|
|
|
|
|
0
|
$dash_sub_ref = \&EducateDashesOldSchoolInverted; |
|
322
|
|
|
|
|
|
|
} |
|
323
|
|
|
|
|
|
|
|
|
324
|
0
|
|
|
|
|
0
|
my $tokens; |
|
325
|
0
|
|
0
|
|
|
0
|
$tokens ||= _tokenize($text); |
|
326
|
|
|
|
|
|
|
|
|
327
|
0
|
|
|
|
|
0
|
my $result = ''; |
|
328
|
0
|
|
|
|
|
0
|
my $in_pre = 0; # Keep track of when we're inside <pre> or <code> tags |
|
329
|
0
|
|
|
|
|
0
|
foreach my $cur_token (@$tokens) { |
|
330
|
0
|
0
|
|
|
|
0
|
if ( $cur_token->[0] eq "tag" ) { |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# Don't mess with quotes inside tags |
|
333
|
0
|
|
|
|
|
0
|
$result .= $cur_token->[1]; |
|
334
|
0
|
0
|
|
|
|
0
|
if ( $cur_token->[1] =~ m/$tags_to_skip/ ) { |
|
335
|
0
|
0
|
0
|
|
|
0
|
$in_pre = defined $1 && $1 eq '/' ? 0 : 1; |
|
336
|
|
|
|
|
|
|
} |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
else { |
|
339
|
0
|
|
|
|
|
0
|
my $t = $cur_token->[1]; |
|
340
|
0
|
0
|
|
|
|
0
|
if ( !$in_pre ) { |
|
341
|
0
|
|
|
|
|
0
|
$t = ProcessEscapes($t); |
|
342
|
0
|
|
|
|
|
0
|
$t = $dash_sub_ref->($t); |
|
343
|
|
|
|
|
|
|
} |
|
344
|
0
|
|
|
|
|
0
|
$result .= $t; |
|
345
|
|
|
|
|
|
|
} |
|
346
|
|
|
|
|
|
|
} |
|
347
|
0
|
|
|
|
|
0
|
return $result; |
|
348
|
|
|
|
|
|
|
} |
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
=head2 SmartEllipses |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
Call the individual ellipse conversion to entities functions. |
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=cut |
|
355
|
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub SmartEllipses { |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
# Paramaters: |
|
359
|
0
|
|
|
0
|
1
|
0
|
my $text = shift; # text to be parsed |
|
360
|
0
|
|
|
|
|
0
|
my $attr = shift; # value of the smart_ellipses="" attribute |
|
361
|
|
|
|
|
|
|
|
|
362
|
0
|
0
|
|
|
|
0
|
if ( $attr == 0 ) { |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# do nothing; |
|
365
|
0
|
|
|
|
|
0
|
return $text; |
|
366
|
|
|
|
|
|
|
} |
|
367
|
|
|
|
|
|
|
|
|
368
|
0
|
|
|
|
|
0
|
my $tokens; |
|
369
|
0
|
|
0
|
|
|
0
|
$tokens ||= _tokenize($text); |
|
370
|
|
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
0
|
my $result = ''; |
|
372
|
0
|
|
|
|
|
0
|
my $in_pre = 0; # Keep track of when we're inside <pre> or <code> tags |
|
373
|
0
|
|
|
|
|
0
|
foreach my $cur_token (@$tokens) { |
|
374
|
0
|
0
|
|
|
|
0
|
if ( $cur_token->[0] eq "tag" ) { |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
# Don't mess with quotes inside tags |
|
377
|
0
|
|
|
|
|
0
|
$result .= $cur_token->[1]; |
|
378
|
0
|
0
|
|
|
|
0
|
if ( $cur_token->[1] =~ m/$tags_to_skip/ ) { |
|
379
|
0
|
0
|
0
|
|
|
0
|
$in_pre = defined $1 && $1 eq '/' ? 0 : 1; |
|
380
|
|
|
|
|
|
|
} |
|
381
|
|
|
|
|
|
|
} |
|
382
|
|
|
|
|
|
|
else { |
|
383
|
0
|
|
|
|
|
0
|
my $t = $cur_token->[1]; |
|
384
|
0
|
0
|
|
|
|
0
|
if ( !$in_pre ) { |
|
385
|
0
|
|
|
|
|
0
|
$t = ProcessEscapes($t); |
|
386
|
0
|
|
|
|
|
0
|
$t = EducateEllipses($t); |
|
387
|
|
|
|
|
|
|
} |
|
388
|
0
|
|
|
|
|
0
|
$result .= $t; |
|
389
|
|
|
|
|
|
|
} |
|
390
|
|
|
|
|
|
|
} |
|
391
|
0
|
|
|
|
|
0
|
return $result; |
|
392
|
|
|
|
|
|
|
} |
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
=head2 EducateQuotes |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
Parameter: String. |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
Returns: The string, with "educated" curly quote HTML entities. |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
Example input: "Isn't this fun?" |
|
401
|
|
|
|
|
|
|
Example output: “Isn’t this fun?” |
|
402
|
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
=cut |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
sub EducateQuotes { |
|
406
|
92
|
|
|
92
|
1
|
156
|
local $_ = shift; |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
# Tell perl not to gripe when we use $1 in substitutions, |
|
409
|
|
|
|
|
|
|
# even when it's undefined. Use $^W instead of "no warnings" |
|
410
|
|
|
|
|
|
|
# for compatibility with Perl 5.005: |
|
411
|
92
|
|
|
|
|
226
|
local $^W = 0; |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
# Make our own "punctuation" character class, because the POSIX-style |
|
414
|
|
|
|
|
|
|
# [:PUNCT:] is only available in Perl 5.6 or later: |
|
415
|
92
|
|
|
|
|
240
|
my $punct_class = qr/[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]/; |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
# Special case if the very first character is a quote |
|
418
|
|
|
|
|
|
|
# followed by punctuation at a non-word-break. Close the quotes by brute force: |
|
419
|
92
|
|
|
|
|
302
|
s/^'(?=$punct_class\B)/’/; |
|
420
|
92
|
|
|
|
|
257
|
s/^"(?=$punct_class\B)/”/; |
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
# Special case for double sets of quotes, e.g.: |
|
423
|
|
|
|
|
|
|
# <p>He said, "'Quoted' words in a larger quote."</p> |
|
424
|
92
|
|
|
|
|
153
|
s/"'(?=\w)/“‘/g; |
|
425
|
92
|
|
|
|
|
139
|
s/'"(?=\w)/‘“/g; |
|
426
|
|
|
|
|
|
|
|
|
427
|
92
|
|
|
|
|
176
|
my $close_class = qr![^\ \t\r\n\[\{\(]!; |
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
# Single closing quotes: |
|
430
|
92
|
|
|
|
|
317
|
s { |
|
431
|
|
|
|
|
|
|
($close_class)? |
|
432
|
|
|
|
|
|
|
' |
|
433
|
|
|
|
|
|
|
(?(1)| # If $1 captured, then do nothing; |
|
434
|
|
|
|
|
|
|
(?=\s | s\b) # otherwise, positive lookahead for a whitespace |
|
435
|
|
|
|
|
|
|
) # char or an 's' at a word ending position. This |
|
436
|
|
|
|
|
|
|
# is a special case to handle something like: |
|
437
|
|
|
|
|
|
|
# "<i>Custer</i>'s Last Stand." |
|
438
|
|
|
|
|
|
|
} {$1’}xgi; |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
# Single opening quotes: |
|
441
|
92
|
|
|
|
|
146
|
s/'/‘/g; |
|
442
|
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# Double closing quotes: |
|
444
|
92
|
|
|
|
|
257
|
s { |
|
445
|
|
|
|
|
|
|
($close_class)? |
|
446
|
|
|
|
|
|
|
" |
|
447
|
|
|
|
|
|
|
(?(1)|(?=\s)) # If $1 captured, then do nothing; |
|
448
|
|
|
|
|
|
|
# if not, then make sure the next char is whitespace. |
|
449
|
|
|
|
|
|
|
} {$1”}xg; |
|
450
|
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
# Double opening quotes: |
|
452
|
92
|
|
|
|
|
145
|
s/"/“/g; |
|
453
|
|
|
|
|
|
|
|
|
454
|
92
|
|
|
|
|
257
|
return $_; |
|
455
|
|
|
|
|
|
|
} |
|
456
|
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=head2 EducateBackticks |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
Replace double (back)ticks w/ HTML entities. |
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
=cut |
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
sub EducateBackticks { |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
# |
|
466
|
|
|
|
|
|
|
# Parameter: String. |
|
467
|
|
|
|
|
|
|
# Returns: The string, with ``backticks'' -style double quotes |
|
468
|
|
|
|
|
|
|
# translated into HTML curly quote entities. |
|
469
|
|
|
|
|
|
|
# |
|
470
|
|
|
|
|
|
|
# Example input: ``Isn't this fun?'' |
|
471
|
|
|
|
|
|
|
# Example output: “Isn't this fun?” |
|
472
|
|
|
|
|
|
|
# |
|
473
|
|
|
|
|
|
|
|
|
474
|
92
|
|
|
92
|
1
|
149
|
local $_ = shift; |
|
475
|
92
|
|
|
|
|
148
|
s/``/“/g; |
|
476
|
92
|
|
|
|
|
150
|
s/''/”/g; |
|
477
|
92
|
|
|
|
|
150
|
return $_; |
|
478
|
|
|
|
|
|
|
} |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=head2 EducateSingleBackticks |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
Replace single (back)ticks w/ HTML entities. |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
=cut |
|
485
|
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
sub EducateSingleBackticks { |
|
487
|
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
# |
|
489
|
|
|
|
|
|
|
# Parameter: String. |
|
490
|
|
|
|
|
|
|
# Returns: The string, with `backticks' -style single quotes |
|
491
|
|
|
|
|
|
|
# translated into HTML curly quote entities. |
|
492
|
|
|
|
|
|
|
# |
|
493
|
|
|
|
|
|
|
# Example input: `Isn't this fun?' |
|
494
|
|
|
|
|
|
|
# Example output: ‘Isn’t this fun?’ |
|
495
|
|
|
|
|
|
|
# |
|
496
|
|
|
|
|
|
|
|
|
497
|
0
|
|
|
0
|
1
|
0
|
local $_ = shift; |
|
498
|
0
|
|
|
|
|
0
|
s/`/‘/g; |
|
499
|
0
|
|
|
|
|
0
|
s/'/’/g; |
|
500
|
0
|
|
|
|
|
0
|
return $_; |
|
501
|
|
|
|
|
|
|
} |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=head2 EducateDashes |
|
504
|
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
Dashes to HTML entity |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
Parameter: String. |
|
508
|
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
Returns: The string, with each instance of "--" translated to |
|
510
|
|
|
|
|
|
|
an em-dash HTML entity. |
|
511
|
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
=cut |
|
513
|
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
sub EducateDashes { |
|
515
|
|
|
|
|
|
|
|
|
516
|
92
|
|
|
92
|
1
|
160
|
local $_ = shift; |
|
517
|
92
|
|
|
|
|
136
|
s/--/—/g; |
|
518
|
92
|
|
|
|
|
161
|
return $_; |
|
519
|
|
|
|
|
|
|
} |
|
520
|
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
=head2 EducateDashesOldSchool |
|
522
|
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
Dashes to entities. |
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
Parameter: String. |
|
527
|
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
Returns: The string, with each instance of "--" translated to |
|
529
|
|
|
|
|
|
|
an en-dash HTML entity, and each "---" translated to |
|
530
|
|
|
|
|
|
|
an em-dash HTML entity. |
|
531
|
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=cut |
|
534
|
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
sub EducateDashesOldSchool { |
|
536
|
|
|
|
|
|
|
|
|
537
|
0
|
|
|
0
|
1
|
0
|
local $_ = shift; |
|
538
|
0
|
|
|
|
|
0
|
s/---/—/g; # em |
|
539
|
0
|
|
|
|
|
0
|
s/--/–/g; # en |
|
540
|
0
|
|
|
|
|
0
|
return $_; |
|
541
|
|
|
|
|
|
|
} |
|
542
|
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
=head2 EducateDashesOldSchoolInverted |
|
544
|
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
Parameter: String. |
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
Returns: The string, with each instance of "--" translated to |
|
549
|
|
|
|
|
|
|
an em-dash HTML entity, and each "---" translated to |
|
550
|
|
|
|
|
|
|
an en-dash HTML entity. Two reasons why: First, unlike the |
|
551
|
|
|
|
|
|
|
en- and em-dash syntax supported by |
|
552
|
|
|
|
|
|
|
EducateDashesOldSchool(), it's compatible with existing |
|
553
|
|
|
|
|
|
|
entries written before SmartyPants 1.1, back when "--" was |
|
554
|
|
|
|
|
|
|
only used for em-dashes. Second, em-dashes are more |
|
555
|
|
|
|
|
|
|
common than en-dashes, and so it sort of makes sense that |
|
556
|
|
|
|
|
|
|
the shortcut should be shorter to type. (Thanks to Aaron |
|
557
|
|
|
|
|
|
|
Swartz for the idea.) |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
=cut |
|
561
|
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
sub EducateDashesOldSchoolInverted { |
|
563
|
|
|
|
|
|
|
|
|
564
|
0
|
|
|
0
|
1
|
0
|
local $_ = shift; |
|
565
|
0
|
|
|
|
|
0
|
s/---/–/g; # en |
|
566
|
0
|
|
|
|
|
0
|
s/--/—/g; # em |
|
567
|
0
|
|
|
|
|
0
|
return $_; |
|
568
|
|
|
|
|
|
|
} |
|
569
|
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=head2 EducateEllipses |
|
571
|
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
Parameter: String. |
|
573
|
|
|
|
|
|
|
Returns: The string, with each instance of "..." translated to |
|
574
|
|
|
|
|
|
|
an ellipsis HTML entity. |
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
Example input: Huh...? |
|
577
|
|
|
|
|
|
|
Example output: Huh…? |
|
578
|
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
=cut |
|
580
|
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
sub EducateEllipses { |
|
582
|
|
|
|
|
|
|
|
|
583
|
92
|
|
|
92
|
1
|
138
|
local $_ = shift; |
|
584
|
92
|
|
|
|
|
151
|
s/\.\.\./…/g; |
|
585
|
92
|
|
|
|
|
151
|
return $_; |
|
586
|
|
|
|
|
|
|
} |
|
587
|
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=head2 StupefyEntities |
|
589
|
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
Parameter: String. |
|
591
|
|
|
|
|
|
|
Returns: The string, with each SmartyPants HTML entity translated to |
|
592
|
|
|
|
|
|
|
its ASCII counterpart. |
|
593
|
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
Example input: “Hello — world.” |
|
595
|
|
|
|
|
|
|
Example output: "Hello -- world." |
|
596
|
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
=cut |
|
598
|
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
sub StupefyEntities { |
|
600
|
|
|
|
|
|
|
|
|
601
|
0
|
|
|
0
|
1
|
0
|
local $_ = shift; |
|
602
|
|
|
|
|
|
|
|
|
603
|
0
|
|
|
|
|
0
|
s/–/-/g; # en-dash |
|
604
|
0
|
|
|
|
|
0
|
s/—/--/g; # em-dash |
|
605
|
|
|
|
|
|
|
|
|
606
|
0
|
|
|
|
|
0
|
s/‘/'/g; # open single quote |
|
607
|
0
|
|
|
|
|
0
|
s/’/'/g; # close single quote |
|
608
|
|
|
|
|
|
|
|
|
609
|
0
|
|
|
|
|
0
|
s/“/"/g; # open double quote |
|
610
|
0
|
|
|
|
|
0
|
s/”/"/g; # close double quote |
|
611
|
|
|
|
|
|
|
|
|
612
|
0
|
|
|
|
|
0
|
s/…/.../g; # ellipsis |
|
613
|
|
|
|
|
|
|
|
|
614
|
0
|
|
|
|
|
0
|
return $_; |
|
615
|
|
|
|
|
|
|
} |
|
616
|
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
=head2 SmartyPantsVersion |
|
618
|
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
Return the version of SmartyPants. |
|
620
|
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
=cut |
|
622
|
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
sub SmartyPantsVersion { |
|
624
|
0
|
|
|
0
|
1
|
0
|
return $VERSION; |
|
625
|
|
|
|
|
|
|
} |
|
626
|
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
=head2 ProcessEscapes |
|
628
|
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
Parameter: String. |
|
630
|
|
|
|
|
|
|
Returns: The string, with after processing the following backslash |
|
631
|
|
|
|
|
|
|
escape sequences. This is useful if you want to force a "dumb" |
|
632
|
|
|
|
|
|
|
quote or other character to appear. |
|
633
|
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
Escape Value |
|
635
|
|
|
|
|
|
|
------ ----- |
|
636
|
|
|
|
|
|
|
\\ \ |
|
637
|
|
|
|
|
|
|
\" " |
|
638
|
|
|
|
|
|
|
\' ' |
|
639
|
|
|
|
|
|
|
\. . |
|
640
|
|
|
|
|
|
|
\- - |
|
641
|
|
|
|
|
|
|
\` ` |
|
642
|
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
=cut |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
sub ProcessEscapes { |
|
646
|
|
|
|
|
|
|
|
|
647
|
92
|
|
|
92
|
1
|
154
|
local $_ = shift; |
|
648
|
|
|
|
|
|
|
|
|
649
|
92
|
|
|
|
|
156
|
s! \\\\ !\!gx; |
|
650
|
92
|
|
|
|
|
135
|
s! \\" !"!gx; |
|
651
|
92
|
|
|
|
|
130
|
s! \\' !'!gx; |
|
652
|
92
|
|
|
|
|
138
|
s! \\\. !.!gx; |
|
653
|
92
|
|
|
|
|
135
|
s! \\- !-!gx; |
|
654
|
92
|
|
|
|
|
138
|
s! \\` !`!gx; |
|
655
|
|
|
|
|
|
|
|
|
656
|
92
|
|
|
|
|
163
|
return $_; |
|
657
|
|
|
|
|
|
|
} |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
sub _tokenize { |
|
660
|
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
# |
|
662
|
|
|
|
|
|
|
# Parameter: String containing HTML markup. |
|
663
|
|
|
|
|
|
|
# Returns: Reference to an array of the tokens comprising the input |
|
664
|
|
|
|
|
|
|
# string. Each token is either a tag (possibly with nested, |
|
665
|
|
|
|
|
|
|
# tags contained therein, such as <a href="<MTFoo>">, or a |
|
666
|
|
|
|
|
|
|
# run of text between tags. Each element of the array is a |
|
667
|
|
|
|
|
|
|
# two-element array; the first is either 'tag' or 'text'; |
|
668
|
|
|
|
|
|
|
# the second is the actual value. |
|
669
|
|
|
|
|
|
|
# |
|
670
|
|
|
|
|
|
|
# |
|
671
|
|
|
|
|
|
|
# Based on the _tokenize() subroutine from Brad Choate's MTRegex plugin. |
|
672
|
|
|
|
|
|
|
# <http://www.bradchoate.com/past/mtregex.php> |
|
673
|
|
|
|
|
|
|
# |
|
674
|
|
|
|
|
|
|
|
|
675
|
36
|
|
|
36
|
|
72
|
my $str = shift; |
|
676
|
|
|
|
|
|
|
|
|
677
|
36
|
|
|
|
|
65
|
my $pos = 0; |
|
678
|
36
|
|
|
|
|
74
|
my $len = length $str; |
|
679
|
36
|
|
|
|
|
74
|
my @tokens; |
|
680
|
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
# pattern to match balanced nested <> pairs, up to two levels deep: |
|
682
|
36
|
|
|
|
|
141
|
my $nested_angles = qr/<(?:[^<>]|<[^<>]*>)*>/; |
|
683
|
|
|
|
|
|
|
|
|
684
|
36
|
|
|
|
|
367
|
while ( $str =~ m/($nested_angles)/gs ) { |
|
685
|
244
|
|
|
|
|
481
|
my $whole_tag = $1; |
|
686
|
244
|
|
|
|
|
355
|
my $sec_start = pos $str; |
|
687
|
244
|
|
|
|
|
354
|
my $tag_start = $sec_start - length $whole_tag; |
|
688
|
244
|
100
|
|
|
|
513
|
if ( $pos < $tag_start ) { |
|
689
|
152
|
|
|
|
|
378
|
push @tokens, [ 'text', substr( $str, $pos, $tag_start - $pos ) ]; |
|
690
|
|
|
|
|
|
|
} |
|
691
|
244
|
|
|
|
|
547
|
push @tokens, [ 'tag', $whole_tag ]; |
|
692
|
244
|
|
|
|
|
1257
|
$pos = pos $str; |
|
693
|
|
|
|
|
|
|
} |
|
694
|
36
|
100
|
|
|
|
121
|
push @tokens, [ 'text', substr( $str, $pos, $len - $pos ) ] if $pos < $len; |
|
695
|
36
|
|
|
|
|
165
|
\@tokens; |
|
696
|
|
|
|
|
|
|
} |
|
697
|
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
1; |
|
699
|
|
|
|
|
|
|
__END__ |
|
700
|
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
=pod |
|
703
|
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
=head1 Name |
|
705
|
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
Text::SmartyPants - cute little punctuation assistant |
|
707
|
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
=head1 Synopsis |
|
709
|
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
SmartyPants is a free web publishing plug-in for Movable Type, Blosxom, |
|
711
|
|
|
|
|
|
|
and BBEdit that easily translates plain ASCII punctuation characters |
|
712
|
|
|
|
|
|
|
into "smart" typographic punctuation HTML entities. |
|
713
|
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
=head1 Description |
|
716
|
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
SmartyPants can perform the following transformations: |
|
718
|
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
=over 4 |
|
720
|
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
=item * |
|
722
|
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
Straight quotes ( " and ' ) into "curly" quote HTML entities |
|
724
|
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
=item * |
|
726
|
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
Backticks-style quotes (``like this'') into "curly" quote HTML entities |
|
728
|
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
=item * |
|
730
|
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
Dashes (C<--> and C<--->) into en- and em-dash entities |
|
732
|
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
=item * |
|
734
|
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
Three consecutive dots (C<...>) into an ellipsis entity |
|
736
|
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
=back |
|
738
|
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
This means you can write, edit, and save your posts using plain old |
|
740
|
|
|
|
|
|
|
ASCII straight quotes, plain dashes, and plain dots, but your published |
|
741
|
|
|
|
|
|
|
posts (and final HTML output) will appear with smart quotes, em-dashes, |
|
742
|
|
|
|
|
|
|
and proper ellipses. |
|
743
|
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
SmartyPants is a combination plug-in -- the same file works with Movable |
|
745
|
|
|
|
|
|
|
Type, Blosxom, and BBEdit. It can also be used from a Unix-style |
|
746
|
|
|
|
|
|
|
command-line. Version requirements and installation instructions for |
|
747
|
|
|
|
|
|
|
each of these tools can be found in the corresponding sub-section under |
|
748
|
|
|
|
|
|
|
"Installation", below. |
|
749
|
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
SmartyPants does not modify characters within C<< <pre> >>, C<< <code> |
|
751
|
|
|
|
|
|
|
>>, C<< <kbd> >>, or C<< <script> >> tag blocks. Typically, these tags |
|
752
|
|
|
|
|
|
|
are used to display text where smart quotes and other "smart |
|
753
|
|
|
|
|
|
|
punctuation" would not be appropriate, such as source code or example |
|
754
|
|
|
|
|
|
|
markup. |
|
755
|
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
=head2 Backslash Escapes |
|
758
|
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
If you need to use literal straight quotes (or plain hyphens and |
|
760
|
|
|
|
|
|
|
periods), SmartyPants accepts the following backslash escape sequences |
|
761
|
|
|
|
|
|
|
to force non-smart punctuation. It does so by transforming the escape |
|
762
|
|
|
|
|
|
|
sequence into a decimal-encoded HTML entity: |
|
763
|
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
Escape Value Character |
|
765
|
|
|
|
|
|
|
------ ----- --------- |
|
766
|
|
|
|
|
|
|
\\ \ \ |
|
767
|
|
|
|
|
|
|
\" " " |
|
768
|
|
|
|
|
|
|
\' ' ' |
|
769
|
|
|
|
|
|
|
\. . . |
|
770
|
|
|
|
|
|
|
\- - - |
|
771
|
|
|
|
|
|
|
\` ` ` |
|
772
|
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
This is useful, for example, when you want to use straight quotes as |
|
774
|
|
|
|
|
|
|
foot and inch marks: 6'2" tall; a 17" iMac. |
|
775
|
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
=head2 MT-Textile Integration |
|
778
|
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
Movable Type users should also note that SmartyPants can work in |
|
780
|
|
|
|
|
|
|
conjunction with Brad Choate's MT-Textile plug-in: |
|
781
|
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
http://bradchoate.com/past/mttextile.php |
|
783
|
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
MT-Textile is a port of Dean Allen's original Textile project to Perl |
|
785
|
|
|
|
|
|
|
and Movable Type. MT-Textile by itself only translates Textile markup |
|
786
|
|
|
|
|
|
|
to HTML. However, if SmartyPants is also installed, MT-Textile will |
|
787
|
|
|
|
|
|
|
call on SmartyPants to educate quotes, dashes, and ellipses, |
|
788
|
|
|
|
|
|
|
automatically. Using SmartyPants in conjunction with MT-Textile |
|
789
|
|
|
|
|
|
|
requires no modifications to your Movable Type templates. |
|
790
|
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
Textile is Dean Allen's "humane web text generator", an easy-to-write |
|
792
|
|
|
|
|
|
|
and easy-to-read shorthand for writing text for the web. An online |
|
793
|
|
|
|
|
|
|
Textile web application is available at Mr. Allen's site: |
|
794
|
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
http://textism.com/tools/textile/ |
|
796
|
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
=head1 Installation |
|
799
|
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
=head2 Movable Type |
|
801
|
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
SmartyPants works with Movable Type version 2.5 or later. |
|
803
|
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
=over 4 |
|
805
|
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
=item 1. |
|
807
|
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
Copy the "SmartyPants.pl" file into your Movable Type "plugins" directory. |
|
809
|
|
|
|
|
|
|
The "plugins" directory should be in the same directory as "mt.cgi"; if it |
|
810
|
|
|
|
|
|
|
doesn't already exist, use your FTP program to create it. Your |
|
811
|
|
|
|
|
|
|
installation should look like this: |
|
812
|
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
(mt home)/plugins/SmartyPants.pl |
|
814
|
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
=item 2. |
|
816
|
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
If you're using SmartyPants with Brad Choate's MT-Textile, you're done. |
|
818
|
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
If not, to activate SmartyPants on your weblog, you need to edit your MT |
|
820
|
|
|
|
|
|
|
templates. The easiest way is to add the C<smarty_pants> attribute to |
|
821
|
|
|
|
|
|
|
each MT template tag whose contents you wish to apply SmartyPants' |
|
822
|
|
|
|
|
|
|
transformations. Obvious tags would include C<MTEntryTitle>, |
|
823
|
|
|
|
|
|
|
C<MTEntryBody>, and C<MTEntryMore>. SmartyPants should work within any |
|
824
|
|
|
|
|
|
|
MT content tag. |
|
825
|
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
For example, to apply SmartyPants to your entry titles: |
|
828
|
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
<$MTEntryTitle smarty_pants="1"$> |
|
830
|
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
The value passed to C<smarty_pants> specifies the way SmartyPants works. |
|
832
|
|
|
|
|
|
|
See "Options", below, for full details on all of the supported options. |
|
833
|
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
=back |
|
835
|
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
=head2 Blosxom |
|
838
|
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
SmartyPants works with Blosxom version 2.0 or later. |
|
840
|
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
=over 4 |
|
842
|
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
=item 1. |
|
844
|
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
Rename the "SmartyPants.pl" plug-in to "SmartyPants" (case is |
|
846
|
|
|
|
|
|
|
important). Movable Type requires plug-ins to have a ".pl" extension; |
|
847
|
|
|
|
|
|
|
Blosxom forbids it (at least as of this writing). |
|
848
|
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
=item 2. |
|
850
|
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
Copy the "SmartyPants" plug-in file to your Blosxom plug-ins folder. If |
|
852
|
|
|
|
|
|
|
you're not sure where your Blosxom plug-ins folder is, see the Blosxom |
|
853
|
|
|
|
|
|
|
documentation for information. |
|
854
|
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
=item 3. |
|
856
|
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
That's it. The entries in your weblog should now automatically have |
|
858
|
|
|
|
|
|
|
SmartyPants' default transformations applied. |
|
859
|
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
=item 4. |
|
861
|
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
If you wish to configure SmartyPants' behavior, open the "SmartyPants" |
|
863
|
|
|
|
|
|
|
plug-in, and edit the value of the C<$smartypants_attr> configuration |
|
864
|
|
|
|
|
|
|
variable, located near the top of the script. The default value is 1; |
|
865
|
|
|
|
|
|
|
see "Options", below, for the full list of supported values. |
|
866
|
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
=back |
|
868
|
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
=head2 BBEdit |
|
871
|
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
SmartyPants works with BBEdit 6.1 or later on Mac OS X; and BBEdit 5.1 |
|
873
|
|
|
|
|
|
|
or later on Mac OS 9 or earlier (provided you have MacPerl |
|
874
|
|
|
|
|
|
|
installed). |
|
875
|
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
=over 4 |
|
877
|
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
=item 1. |
|
879
|
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
Copy the "SmartyPants.pl" file to appropriate filters folder in your |
|
881
|
|
|
|
|
|
|
"BBEdit Support" folder. On Mac OS X, this should be: |
|
882
|
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
BBEdit Support:Unix Support:Unix Filters: |
|
884
|
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
On Mac OS 9 or earlier, this should be: |
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
BBEdit Support:MacPerl Support: Perl Filters: |
|
888
|
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
See the BBEdit documentation for more details on the location of these |
|
890
|
|
|
|
|
|
|
folders. |
|
891
|
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
You can rename "SmartyPants.pl" to whatever you wish. |
|
893
|
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
=item 2. |
|
895
|
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
That's it. To use SmartyPants, select some text in a BBEdit document, |
|
897
|
|
|
|
|
|
|
then choose SmartyPants from the Filters sub-menu or the Filters |
|
898
|
|
|
|
|
|
|
floating palette. On Mac OS 9, the Filters sub-menu is in the "Camel" |
|
899
|
|
|
|
|
|
|
menu; on Mac OS X, it is in the "#!" menu. |
|
900
|
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
=item 3. |
|
902
|
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
If you wish to configure SmartyPants' behavior, open the SmartyPants |
|
904
|
|
|
|
|
|
|
file and edit the value of the C<$smartypants_attr> configuration |
|
905
|
|
|
|
|
|
|
variable, located near the top of the script. The default value is 1; |
|
906
|
|
|
|
|
|
|
see "Options", below, for the full list of supported values. |
|
907
|
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
=back |
|
909
|
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
=head1 Options |
|
912
|
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
=head2 smarty_pants |
|
914
|
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
For MT users, the C<smarty_pants> template tag attribute is where you |
|
916
|
|
|
|
|
|
|
specify configuration options. For Blosxom and BBEdit users, settings |
|
917
|
|
|
|
|
|
|
are specified by editing the value of the C<$smartypants_attr> variable |
|
918
|
|
|
|
|
|
|
in the script itself. |
|
919
|
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
Numeric values are the easiest way to configure SmartyPants' behavior: |
|
921
|
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
=over 4 |
|
923
|
|
|
|
|
|
|
|
|
924
|
|
|
|
|
|
|
=item B<"0"> |
|
925
|
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
Suppress all transformations. (Do nothing.) |
|
927
|
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
=item B<"1"> |
|
929
|
|
|
|
|
|
|
|
|
930
|
|
|
|
|
|
|
Performs default SmartyPants transformations: quotes (including |
|
931
|
|
|
|
|
|
|
``backticks'' -style), em-dashes, and ellipses. "--" (dash dash) is used |
|
932
|
|
|
|
|
|
|
to signify an em-dash; there is no support for en-dashes. |
|
933
|
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
=item B<"2"> |
|
935
|
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
Same as smarty_pants="1", except that it uses the old-school typewriter |
|
937
|
|
|
|
|
|
|
shorthand for dashes: "--" (dash dash) for en-dashes, "---" (dash dash dash) |
|
938
|
|
|
|
|
|
|
for em-dashes. |
|
939
|
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
=item B<"3"> |
|
941
|
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
Same as smarty_pants="2", but inverts the shorthand for dashes: "--" |
|
943
|
|
|
|
|
|
|
(dash dash) for em-dashes, and "---" (dash dash dash) for en-dashes. |
|
944
|
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
=item B<"-1"> |
|
946
|
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
Stupefy mode. Reverses the SmartyPants transformation process, turning the |
|
948
|
|
|
|
|
|
|
HTML entities produced by SmartyPants into their ASCII equivalents. E.g. |
|
949
|
|
|
|
|
|
|
"“" is turned into a simple double-quote ("), "—" is turned |
|
950
|
|
|
|
|
|
|
into two dashes, etc. This is useful if you are using SmartyPants from |
|
951
|
|
|
|
|
|
|
Brad Choate's MT-Textile text filter, but wish to suppress smart |
|
952
|
|
|
|
|
|
|
punctuation in specific MT templates, such as RSS feeds. Text filters do |
|
953
|
|
|
|
|
|
|
their work before templates are processed; but you can use |
|
954
|
|
|
|
|
|
|
smarty_pants="-1" to reverse the transformations in specific templates. |
|
955
|
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
=back |
|
957
|
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
The following single-character attribute values can be combined to toggle |
|
960
|
|
|
|
|
|
|
individual transformations from within the smarty_pants attribute. For |
|
961
|
|
|
|
|
|
|
example, to educate normal quotes and em-dashes, but not ellipses or |
|
962
|
|
|
|
|
|
|
``backticks'' -style quotes: |
|
963
|
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
<$MTFoo smarty_pants="qd"$> |
|
965
|
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
=over 4 |
|
967
|
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
=item B<"q"> |
|
969
|
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
Educates normal quote characters: (") and ('). |
|
971
|
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
=item B<"b"> |
|
973
|
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
Educates ``backticks'' -style double quotes. |
|
975
|
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
=item B<"B"> |
|
977
|
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
Educates ``backticks'' -style double quotes and `single' quotes. |
|
979
|
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
=item B<"d"> |
|
981
|
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
Educates em-dashes. |
|
983
|
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
=item B<"D"> |
|
985
|
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
Educates em-dashes and en-dashes, using old-school typewriter shorthand: |
|
987
|
|
|
|
|
|
|
(dash dash) for en-dashes, (dash dash dash) for em-dashes. |
|
988
|
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
=item B<"i"> |
|
990
|
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
Educates em-dashes and en-dashes, using inverted old-school typewriter |
|
992
|
|
|
|
|
|
|
shorthand: (dash dash) for em-dashes, (dash dash dash) for en-dashes. |
|
993
|
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
=item B<"e"> |
|
995
|
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
Educates ellipses. |
|
997
|
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
=item B<"w"> |
|
999
|
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
Translates any instance of C<"> into a normal double-quote character. |
|
1001
|
|
|
|
|
|
|
This should be of no interest to most people, but of particular interest |
|
1002
|
|
|
|
|
|
|
to anyone who writes their posts using Dreamweaver, as Dreamweaver |
|
1003
|
|
|
|
|
|
|
inexplicably uses this entity to represent a literal double-quote |
|
1004
|
|
|
|
|
|
|
character. SmartyPants only educates normal quotes, not entities (because |
|
1005
|
|
|
|
|
|
|
ordinarily, entities are used for the explicit purpose of representing the |
|
1006
|
|
|
|
|
|
|
specific character they represent). The "w" option must be used in |
|
1007
|
|
|
|
|
|
|
conjunction with one (or both) of the other quote options ("q" or "b"). |
|
1008
|
|
|
|
|
|
|
Thus, if you wish to apply all SmartyPants transformations (quotes, en- |
|
1009
|
|
|
|
|
|
|
and em-dashes, and ellipses) and also translate C<"> entities into |
|
1010
|
|
|
|
|
|
|
regular quotes so SmartyPants can educate them, you should pass the |
|
1011
|
|
|
|
|
|
|
following to the smarty_pants attribute: |
|
1012
|
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
<$MTFoo smarty_pants="qDew"$> |
|
1014
|
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
For Blosxom and BBEdit users, set: |
|
1016
|
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
my $smartypants_attr = "qDew"; |
|
1018
|
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
=back |
|
1020
|
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
=head2 Deprecated MT Attributes |
|
1023
|
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
The following Movable Type attributes are supported only for |
|
1025
|
|
|
|
|
|
|
compatibility with older versions of SmartyPants. They are obsoleted by |
|
1026
|
|
|
|
|
|
|
the C<smarty_pants> attribute, which offers more control than these |
|
1027
|
|
|
|
|
|
|
individual attributes. If you're setting up SmartyPants for the first |
|
1028
|
|
|
|
|
|
|
time, you should use the C<SmartyPants> attribute instead. |
|
1029
|
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
Blosxom and BBEdit users should simply ignore this section. |
|
1031
|
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
=head3 smart_quotes |
|
1033
|
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
The smart_quotes attribute accepts the following values: |
|
1035
|
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
=over 4 |
|
1037
|
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
=item B<"0"> |
|
1039
|
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
Suppress all quote education. (Do nothing.) |
|
1041
|
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
=item B<"1"> |
|
1043
|
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
Default behavior. Educates normal quote characters: (") and ('). |
|
1045
|
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
=item B<"2"> |
|
1047
|
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
Educate ``backticks'' -style double quotes (in addition to educating |
|
1049
|
|
|
|
|
|
|
regular quotes). Transforms each instance of two consecutive backtick |
|
1050
|
|
|
|
|
|
|
characters (C<``>) into an opening double-quote, and each instance of two |
|
1051
|
|
|
|
|
|
|
consecutive apostrophes (C<''>) into a closing double-quote. |
|
1052
|
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
=back |
|
1054
|
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
=head3 smart_dashes |
|
1057
|
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
The smart_dashes attribute accepts the following values: |
|
1059
|
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
=over 4 |
|
1061
|
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
=item B<"0"> |
|
1063
|
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
Suppress dash education. (Do nothing.) |
|
1065
|
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
=item B<"1"> |
|
1067
|
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
Default behavior. Transforms each instance of "--" (dash dash) into an |
|
1069
|
|
|
|
|
|
|
HTML entity-encoded em-dash. |
|
1070
|
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
=item B<"2"> |
|
1072
|
|
|
|
|
|
|
|
|
1073
|
|
|
|
|
|
|
Educates both en- and em-dashes, using the old-school typewriter |
|
1074
|
|
|
|
|
|
|
shorthand for dashes. Each instance of "--" (dash dash) is turned into |
|
1075
|
|
|
|
|
|
|
an HTML entity-encoded en-dash; each instance of "---" (dash dash dash) |
|
1076
|
|
|
|
|
|
|
is turned into an em-dash. |
|
1077
|
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
=item B<"3"> |
|
1079
|
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
Same as smart_dashes="2", but inverts the shorthand, using "--" (dash |
|
1081
|
|
|
|
|
|
|
dash) for em-dashes, and "---" (dash dash dash) for en-dashes. Although |
|
1082
|
|
|
|
|
|
|
somewhat counterintuitive in that the longer shortcut is used for the |
|
1083
|
|
|
|
|
|
|
shorter dash, this syntax is backwards compatible with SmartyPants 1.0's |
|
1084
|
|
|
|
|
|
|
original syntax, which used (dash dash) for em-dashes. |
|
1085
|
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
=back |
|
1088
|
|
|
|
|
|
|
|
|
1089
|
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
=head3 smart_ellipses |
|
1091
|
|
|
|
|
|
|
|
|
1092
|
|
|
|
|
|
|
The smart_ellipses attribute accepts the following values: |
|
1093
|
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
=over 4 |
|
1095
|
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
=item B<"0"> |
|
1097
|
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
Suppress ellipsis education. (Do nothing.) |
|
1099
|
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
=item B<"1"> |
|
1101
|
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
Default behavior. Transforms each instance of "..." (dot dot dot) into |
|
1103
|
|
|
|
|
|
|
an HTML entity-encoded ellipsis. If there are four consecutive dots, |
|
1104
|
|
|
|
|
|
|
SmartyPants assumes this means "full stop" followed by "ellipsis". |
|
1105
|
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
=back |
|
1107
|
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
=head2 Version Info Tag |
|
1110
|
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
If you include this tag in a Movable Type template: |
|
1112
|
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
<$MTSmartyPantsVersion$> |
|
1114
|
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
it will be replaced with a string representing the version number of the |
|
1116
|
|
|
|
|
|
|
installed version of SmartyPants, e.g. "1.2". |
|
1117
|
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
=head1 Caveats |
|
1120
|
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
=head2 Why You Might Not Want to Use Smart Quotes in Your Weblog |
|
1122
|
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
For one thing, you might not care. |
|
1124
|
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
Most normal, mentally stable individuals do not take notice of proper |
|
1126
|
|
|
|
|
|
|
typographic punctuation. Many design and typography nerds, however, break |
|
1127
|
|
|
|
|
|
|
out in a nasty rash when they encounter, say, a restaurant sign that uses |
|
1128
|
|
|
|
|
|
|
a straight apostrophe to spell "Joe's". |
|
1129
|
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
If you're the sort of person who just doesn't care, you might well want to |
|
1131
|
|
|
|
|
|
|
continue not caring. Using straight quotes -- and sticking to the 7-bit |
|
1132
|
|
|
|
|
|
|
ASCII character set in general -- is certainly a simpler way to live. |
|
1133
|
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
Even if you I<do> care about accurate typography, you still might want to |
|
1135
|
|
|
|
|
|
|
think twice before educating the quote characters in your weblog. One side |
|
1136
|
|
|
|
|
|
|
effect of publishing curly quote HTML entities is that it makes your |
|
1137
|
|
|
|
|
|
|
weblog a bit harder for others to quote from using copy-and-paste. What |
|
1138
|
|
|
|
|
|
|
happens is that when someone copies text from your blog, the copied text |
|
1139
|
|
|
|
|
|
|
contains the 8-bit curly quote characters (as well as the 8-bit characters |
|
1140
|
|
|
|
|
|
|
for em-dashes and ellipses, if you use these options). These characters |
|
1141
|
|
|
|
|
|
|
are not standard across different text encoding methods, which is why they |
|
1142
|
|
|
|
|
|
|
need to be encoded as HTML entities. |
|
1143
|
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
People copying text from your weblog, however, may not notice that you're |
|
1145
|
|
|
|
|
|
|
using curly quotes, and they'll go ahead and paste the unencoded 8-bit |
|
1146
|
|
|
|
|
|
|
characters copied from their browser into an email message or their own |
|
1147
|
|
|
|
|
|
|
weblog. When pasted as raw "smart quotes", these characters are likely to |
|
1148
|
|
|
|
|
|
|
get mangled beyond recognition. |
|
1149
|
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
That said, my own opinion is that any decent text editor or email client |
|
1151
|
|
|
|
|
|
|
makes it easy to stupefy smart quote characters into their 7-bit |
|
1152
|
|
|
|
|
|
|
equivalents, and I don't consider it my problem if you're using an |
|
1153
|
|
|
|
|
|
|
indecent text editor or email client. |
|
1154
|
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
=head2 Algorithmic Shortcomings |
|
1157
|
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
One situation in which quotes will get curled the wrong way is when |
|
1159
|
|
|
|
|
|
|
apostrophes are used at the start of leading contractions. For example: |
|
1160
|
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
the '80s |
|
1162
|
|
|
|
|
|
|
'Twas the night before Christmas. |
|
1163
|
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
In both cases above, SmartyPants will turn the apostrophes into opening |
|
1165
|
|
|
|
|
|
|
single-quotes, when in fact they should be closing ones. I don't think |
|
1166
|
|
|
|
|
|
|
this problem can be solved in the general case -- every word processor |
|
1167
|
|
|
|
|
|
|
I've tried gets this wrong as well. In such cases, it's best to use the |
|
1168
|
|
|
|
|
|
|
proper HTML entity for closing single-quotes (C<’>) by hand. |
|
1169
|
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
(I should also note that my personal style is to abbreviate decades like |
|
1171
|
|
|
|
|
|
|
this: |
|
1172
|
|
|
|
|
|
|
|
|
1173
|
|
|
|
|
|
|
the 80's |
|
1174
|
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
so admittedly, I'm not all that interested in solving this problem.) |
|
1176
|
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
=head1 Bugs |
|
1179
|
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
To file bug reports or feature requests (other than topics listed in the |
|
1181
|
|
|
|
|
|
|
Caveats section above) please send email to: |
|
1182
|
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
smartypants@daringfireball.net |
|
1184
|
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
If the bug involves quotes being curled the wrong way, please send example |
|
1186
|
|
|
|
|
|
|
text to illustrate. |
|
1187
|
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
=head1 See Also |
|
1190
|
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
This plug-in effectively obsoletes the technique documented here: |
|
1192
|
|
|
|
|
|
|
|
|
1193
|
|
|
|
|
|
|
http://daringfireball.net/2002/08/movable_type_smart_quote_devilry.html |
|
1194
|
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
However, the above instructions may still be of interest if for some |
|
1196
|
|
|
|
|
|
|
reason you are still running an older version of Movable Type. |
|
1197
|
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
=head1 Version History |
|
1200
|
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
1.0: Wed Nov 13, 2002 |
|
1202
|
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
Initial release. |
|
1204
|
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
1.1: Wed Feb 5, 2003 |
|
1207
|
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
+ The smart_dashes template attribute now offers an option to |
|
1209
|
|
|
|
|
|
|
use "--" for *en* dashes, and "---" for *em* dashes. |
|
1210
|
|
|
|
|
|
|
|
|
1211
|
|
|
|
|
|
|
+ The default smart_dashes behavior now simply translates "--" |
|
1212
|
|
|
|
|
|
|
(dash dash) into an em-dash. Previously, it would look for |
|
1213
|
|
|
|
|
|
|
" -- " (space dash dash space), which was dumb, since many |
|
1214
|
|
|
|
|
|
|
people do not use spaces around their em dashes. |
|
1215
|
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
+ Using the smarty_pants attribute with a value of "2" will |
|
1217
|
|
|
|
|
|
|
do the same thing as smarty_pants="1", with one difference: |
|
1218
|
|
|
|
|
|
|
it will use the new shortcuts for en- and em-dashes. |
|
1219
|
|
|
|
|
|
|
|
|
1220
|
|
|
|
|
|
|
+ Closing quotes (single and double) were incorrectly curled in |
|
1221
|
|
|
|
|
|
|
situations like this: |
|
1222
|
|
|
|
|
|
|
"<a>foo</a>", |
|
1223
|
|
|
|
|
|
|
where the comma could be just about any punctuation character. |
|
1224
|
|
|
|
|
|
|
Fixed. |
|
1225
|
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
+ Added <kbd> to the list of tags in which text shouldn't be |
|
1227
|
|
|
|
|
|
|
educated. |
|
1228
|
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
|
|
1230
|
|
|
|
|
|
|
1.2: Thu Feb 27, 2003 |
|
1231
|
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
+ SmartyPants is now a combination plug-in, supporting both |
|
1233
|
|
|
|
|
|
|
Movable Type (2.5 or later) and Blosxom (2.0 or later). |
|
1234
|
|
|
|
|
|
|
It also works as a BBEdit text filter and standalone |
|
1235
|
|
|
|
|
|
|
command-line Perl program. Thanks to Rael Dornfest for the |
|
1236
|
|
|
|
|
|
|
initial Blosxom port (and for the excellent Blosxom plug-in |
|
1237
|
|
|
|
|
|
|
API). |
|
1238
|
|
|
|
|
|
|
|
|
1239
|
|
|
|
|
|
|
+ SmartyPants now accepts the following backslash escapes, |
|
1240
|
|
|
|
|
|
|
to force non-smart punctuation. It does so by transforming |
|
1241
|
|
|
|
|
|
|
the escape sequence into a decimal-encoded HTML entity: |
|
1242
|
|
|
|
|
|
|
|
|
1243
|
|
|
|
|
|
|
Escape Value Character |
|
1244
|
|
|
|
|
|
|
------ ----- --------- |
|
1245
|
|
|
|
|
|
|
\\ \ \ |
|
1246
|
|
|
|
|
|
|
\" " " |
|
1247
|
|
|
|
|
|
|
\' ' ' |
|
1248
|
|
|
|
|
|
|
\. . . |
|
1249
|
|
|
|
|
|
|
\- - - |
|
1250
|
|
|
|
|
|
|
\` ` ` |
|
1251
|
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
Note that this could produce different results than previous |
|
1253
|
|
|
|
|
|
|
versions of SmartyPants, if for some reason you have an article |
|
1254
|
|
|
|
|
|
|
containing one or more of these sequences. (Thanks to Charles |
|
1255
|
|
|
|
|
|
|
Wiltgen for the suggestion.) |
|
1256
|
|
|
|
|
|
|
|
|
1257
|
|
|
|
|
|
|
+ Added a new option to support inverted en- and em-dash notation: |
|
1258
|
|
|
|
|
|
|
"--" for em-dashes, "---" for en-dashes. This is compatible with |
|
1259
|
|
|
|
|
|
|
SmartyPants' original "--" syntax for em-dashes, but also allows |
|
1260
|
|
|
|
|
|
|
you to specify en-dashes. It can be invoked by using |
|
1261
|
|
|
|
|
|
|
smart_dashes="3", smarty_pants="3", or smarty_pants="i". |
|
1262
|
|
|
|
|
|
|
(Suggested by Aaron Swartz.) |
|
1263
|
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
+ Added a new option to automatically convert " entities into |
|
1265
|
|
|
|
|
|
|
regular double-quotes before sending text to EducateQuotes() for |
|
1266
|
|
|
|
|
|
|
processing. This is mainly for the benefit of people who write |
|
1267
|
|
|
|
|
|
|
posts using Dreamweaver, which substitutes this entity for any |
|
1268
|
|
|
|
|
|
|
literal quote char. The one and only way to invoke this option |
|
1269
|
|
|
|
|
|
|
is to use the letter shortcuts for the smarty_pants attribute; |
|
1270
|
|
|
|
|
|
|
the shortcut for this option is "w" (for Dream_w_eaver). |
|
1271
|
|
|
|
|
|
|
(Suggested by Jonathon Delacour.) |
|
1272
|
|
|
|
|
|
|
|
|
1273
|
|
|
|
|
|
|
+ Added <script> to the list of tags in which SmartyPants doesn't |
|
1274
|
|
|
|
|
|
|
touch the contents. |
|
1275
|
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
+ Fixed a very subtle bug that would occur if a quote was the very |
|
1277
|
|
|
|
|
|
|
last character in a body of text, preceded immediately by a tag. |
|
1278
|
|
|
|
|
|
|
Lacking any context, previous versions of SmartyPants would turn |
|
1279
|
|
|
|
|
|
|
this into an opening quote mark. It's now correctly turned into |
|
1280
|
|
|
|
|
|
|
a closing one. |
|
1281
|
|
|
|
|
|
|
|
|
1282
|
|
|
|
|
|
|
+ Opening quotes were being curled the wrong way when the |
|
1283
|
|
|
|
|
|
|
subsequent character was punctuation. E.g.: "a '.foo' file". |
|
1284
|
|
|
|
|
|
|
Fixed. |
|
1285
|
|
|
|
|
|
|
|
|
1286
|
|
|
|
|
|
|
+ New MT global template tag: <$MTSmartyPantsVersion$> |
|
1287
|
|
|
|
|
|
|
Prints the version number of SmartyPants, e.g. "1.2". |
|
1288
|
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
|
|
1290
|
|
|
|
|
|
|
1.2.1: Mon Mar 10, 2003 |
|
1291
|
|
|
|
|
|
|
|
|
1292
|
|
|
|
|
|
|
+ New "stupefy mode" for smarty_pants attribute. If you set |
|
1293
|
|
|
|
|
|
|
|
|
1294
|
|
|
|
|
|
|
smarty_pants="-1" |
|
1295
|
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
SmartyPants will perform reverse transformations, turning HTML |
|
1297
|
|
|
|
|
|
|
entities into plain ASCII equivalents. E.g. "“" is turned |
|
1298
|
|
|
|
|
|
|
into a simple double-quote ("), "—" is turned into two |
|
1299
|
|
|
|
|
|
|
dashes, etc. This is useful if you are using SmartyPants from Brad |
|
1300
|
|
|
|
|
|
|
Choate's MT-Textile text filter, but wish to suppress smart |
|
1301
|
|
|
|
|
|
|
punctuation in specific MT templates, such as RSS feeds. Text |
|
1302
|
|
|
|
|
|
|
filters do their work before templates are processed; but you can |
|
1303
|
|
|
|
|
|
|
use smarty_pants="-1" to reverse the transformations in specific |
|
1304
|
|
|
|
|
|
|
templates. |
|
1305
|
|
|
|
|
|
|
|
|
1306
|
|
|
|
|
|
|
+ Replaced the POSIX-style regex character class [:punct:] with an |
|
1307
|
|
|
|
|
|
|
ugly hard-coded normal character class of all punctuation; POSIX |
|
1308
|
|
|
|
|
|
|
classes require Perl 5.6 or later, but SmartyPants still supports |
|
1309
|
|
|
|
|
|
|
back to 5.005. |
|
1310
|
|
|
|
|
|
|
|
|
1311
|
|
|
|
|
|
|
+ Several small changes to allow SmartyPants to work when Blosxom |
|
1312
|
|
|
|
|
|
|
is running in static mode. |
|
1313
|
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
|
|
1315
|
|
|
|
|
|
|
1.2.2: Thu Mar 13, 2003 |
|
1316
|
|
|
|
|
|
|
|
|
1317
|
|
|
|
|
|
|
+ 1.2.1 contained a boneheaded addition which prevented SmartyPants |
|
1318
|
|
|
|
|
|
|
from compiling under Perl 5.005. This has been remedied, and is |
|
1319
|
|
|
|
|
|
|
the only change from 1.2.1. |
|
1320
|
|
|
|
|
|
|
|
|
1321
|
|
|
|
|
|
|
|
|
1322
|
|
|
|
|
|
|
1.3: Tue 13 May 2003 |
|
1323
|
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
+ Plugged the biggest hole in SmartyPants's smart quotes algorithm. |
|
1325
|
|
|
|
|
|
|
Previous versions were hopelessly confused by single-character |
|
1326
|
|
|
|
|
|
|
quote tokens, such as: |
|
1327
|
|
|
|
|
|
|
|
|
1328
|
|
|
|
|
|
|
<p>"<i>Tricky!</i>"</p> |
|
1329
|
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
The problem was that the EducateQuotes() function works on each |
|
1331
|
|
|
|
|
|
|
token separately, with no means of getting surrounding context |
|
1332
|
|
|
|
|
|
|
from the previous or next tokens. The solution is to curl these |
|
1333
|
|
|
|
|
|
|
single-character quote tokens as a special case, *before* calling |
|
1334
|
|
|
|
|
|
|
EducateQuotes(). |
|
1335
|
|
|
|
|
|
|
|
|
1336
|
|
|
|
|
|
|
+ New single-quotes backtick mode for smarty_pants attribute. |
|
1337
|
|
|
|
|
|
|
The only way to turn it on is to include "B" in the configuration |
|
1338
|
|
|
|
|
|
|
string, e.g. to translate backtick quotes, dashes, and ellipses: |
|
1339
|
|
|
|
|
|
|
|
|
1340
|
|
|
|
|
|
|
smarty_pants="Bde" |
|
1341
|
|
|
|
|
|
|
|
|
1342
|
|
|
|
|
|
|
+ Fixed a bug where an opening quote would get curled the wrong way |
|
1343
|
|
|
|
|
|
|
if the quote started with three dots, e.g.: |
|
1344
|
|
|
|
|
|
|
|
|
1345
|
|
|
|
|
|
|
<p>"...meanwhile"</p> |
|
1346
|
|
|
|
|
|
|
|
|
1347
|
|
|
|
|
|
|
+ Fixed a bug where opening quotes would get curled the wrong way |
|
1348
|
|
|
|
|
|
|
if there were double sets of quotes within each other, e.g.: |
|
1349
|
|
|
|
|
|
|
|
|
1350
|
|
|
|
|
|
|
<p>"'Some' people."</p> |
|
1351
|
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
+ Due to popular demand, four consecutive dots (....) will now be |
|
1353
|
|
|
|
|
|
|
turned into an ellipsis followed by a period. Previous versions |
|
1354
|
|
|
|
|
|
|
would turn this into a period followed by an ellipsis. If you |
|
1355
|
|
|
|
|
|
|
really want a period-then-ellipsis sequence, escape the first |
|
1356
|
|
|
|
|
|
|
period with a backslash: \.... |
|
1357
|
|
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
+ Removed "&" from our home-grown punctuation class, since it |
|
1359
|
|
|
|
|
|
|
denotes an entity, not a literal ampersand punctuation |
|
1360
|
|
|
|
|
|
|
character. This fixes a bug where SmartyPants would mis-curl |
|
1361
|
|
|
|
|
|
|
the opening quote in something like this: |
|
1362
|
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
"…whatever" |
|
1364
|
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
+ SmartyPants has always had a special case where it looks for |
|
1366
|
|
|
|
|
|
|
"'s" in situations like this: |
|
1367
|
|
|
|
|
|
|
|
|
1368
|
|
|
|
|
|
|
<i>Custer</i>'s Last Stand |
|
1369
|
|
|
|
|
|
|
|
|
1370
|
|
|
|
|
|
|
This special case is now case-insensitive. |
|
1371
|
|
|
|
|
|
|
|
|
1372
|
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
=head1 Author |
|
1374
|
|
|
|
|
|
|
|
|
1375
|
|
|
|
|
|
|
John Gruber |
|
1376
|
|
|
|
|
|
|
http://daringfireball.net |
|
1377
|
|
|
|
|
|
|
|
|
1378
|
|
|
|
|
|
|
|
|
1379
|
|
|
|
|
|
|
=head1 Additional Credits |
|
1380
|
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
Portions of this plug-in are based on Brad Choate's nifty MTRegex plug-in. |
|
1382
|
|
|
|
|
|
|
Brad Choate also contributed a few bits of source code to this plug-in. |
|
1383
|
|
|
|
|
|
|
Brad Choate is a fine hacker indeed. (http://bradchoate.com/) |
|
1384
|
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
Jeremy Hedley (http://antipixel.com/) and Charles Wiltgen |
|
1386
|
|
|
|
|
|
|
(http://playbacktime.com/) deserve mention for exemplary beta testing. |
|
1387
|
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
Rael Dornfest (http://raelity.org/) ported SmartyPants to Blosxom. |
|
1389
|
|
|
|
|
|
|
|
|
1390
|
|
|
|
|
|
|
|
|
1391
|
|
|
|
|
|
|
=head1 Copyright and License |
|
1392
|
|
|
|
|
|
|
|
|
1393
|
|
|
|
|
|
|
Copyright (c) 2003 John Gruber |
|
1394
|
|
|
|
|
|
|
(http://daringfireball.net/) |
|
1395
|
|
|
|
|
|
|
All rights reserved. |
|
1396
|
|
|
|
|
|
|
|
|
1397
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without |
|
1398
|
|
|
|
|
|
|
modification, are permitted provided that the following conditions are met: |
|
1399
|
|
|
|
|
|
|
|
|
1400
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright |
|
1401
|
|
|
|
|
|
|
notice, this list of conditions and the following disclaimer. |
|
1402
|
|
|
|
|
|
|
|
|
1403
|
|
|
|
|
|
|
* Redistributions in binary form must reproduce the above copyright |
|
1404
|
|
|
|
|
|
|
notice, this list of conditions and the following disclaimer in the |
|
1405
|
|
|
|
|
|
|
documentation and/or other materials provided with the distribution. |
|
1406
|
|
|
|
|
|
|
|
|
1407
|
|
|
|
|
|
|
* Neither the name "SmartyPants" nor the names of its contributors may |
|
1408
|
|
|
|
|
|
|
be used to endorse or promote products derived from this software |
|
1409
|
|
|
|
|
|
|
without specific prior written permission. |
|
1410
|
|
|
|
|
|
|
|
|
1411
|
|
|
|
|
|
|
This software is provided by the copyright holders and contributors "as is" |
|
1412
|
|
|
|
|
|
|
and any express or implied warranties, including, but not limited to, the |
|
1413
|
|
|
|
|
|
|
implied warranties of merchantability and fitness for a particular purpose |
|
1414
|
|
|
|
|
|
|
are disclaimed. In no event shall the copyright owner or contributors be |
|
1415
|
|
|
|
|
|
|
liable for any direct, indirect, incidental, special, exemplary, or |
|
1416
|
|
|
|
|
|
|
consequential damages (including, but not limited to, procurement of |
|
1417
|
|
|
|
|
|
|
substitute goods or services; loss of use, data, or profits; or business |
|
1418
|
|
|
|
|
|
|
interruption) however caused and on any theory of liability, whether in |
|
1419
|
|
|
|
|
|
|
contract, strict liability, or tort (including negligence or otherwise) |
|
1420
|
|
|
|
|
|
|
arising in any way out of the use of this software, even if advised of the |
|
1421
|
|
|
|
|
|
|
possibility of such damage. |
|
1422
|
|
|
|
|
|
|
|
|
1423
|
|
|
|
|
|
|
=cut |