escape 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme +20 -0
- data/doc_include/template/qualitysmith.rb +631 -0
- data/escape.rb +247 -0
- data/tasks/shared/shared_tasks.rb +213 -0
- metadata +53 -0
data/Readme
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
= __
|
2
|
+
|
3
|
+
[<b>Home page</b>:] http://__.rubyforge.org/
|
4
|
+
[<b>Project site</b>:] http://rubyforge.org/projects/__
|
5
|
+
[<b>Wiki</b>:] http://wiki.qualitysmith.com/__
|
6
|
+
[<b>Author</b>:] Your name
|
7
|
+
[<b>Copyright</b>:] 2007 QualitySmith, Inc.
|
8
|
+
[<b>License</b>:] {GNU General Public License}[http://www.gnu.org/copyleft/gpl.html]
|
9
|
+
|
10
|
+
== Introduction
|
11
|
+
|
12
|
+
...
|
13
|
+
|
14
|
+
== Installation
|
15
|
+
|
16
|
+
...
|
17
|
+
|
18
|
+
== Usage
|
19
|
+
|
20
|
+
...
|
@@ -0,0 +1,631 @@
|
|
1
|
+
module RDoc
|
2
|
+
module Page
|
3
|
+
|
4
|
+
FONTS = "\"Bitstream Vera Sans\", Verdana, Arial, Helvetica, sans-serif"
|
5
|
+
|
6
|
+
STYLE = <<CSS
|
7
|
+
a {
|
8
|
+
color: #00F;
|
9
|
+
text-decoration: none;
|
10
|
+
}
|
11
|
+
|
12
|
+
a:hover {
|
13
|
+
color: #77F;
|
14
|
+
text-decoration: underline;
|
15
|
+
}
|
16
|
+
|
17
|
+
body, td, p {
|
18
|
+
font-family: %fonts%;
|
19
|
+
background: #FFF;
|
20
|
+
color: #000;
|
21
|
+
margin: 0px;
|
22
|
+
font-size: small;
|
23
|
+
}
|
24
|
+
|
25
|
+
#content {
|
26
|
+
margin: 2em;
|
27
|
+
}
|
28
|
+
|
29
|
+
#description p {
|
30
|
+
margin-bottom: 0.5em;
|
31
|
+
}
|
32
|
+
|
33
|
+
.sectiontitle {
|
34
|
+
margin-top: 1em;
|
35
|
+
margin-bottom: 1em;
|
36
|
+
padding: 0.5em;
|
37
|
+
padding-left: 2em;
|
38
|
+
background: #005;
|
39
|
+
color: #FFF;
|
40
|
+
font-weight: bold;
|
41
|
+
border: 1px dotted black;
|
42
|
+
}
|
43
|
+
|
44
|
+
.attr-rw {
|
45
|
+
padding-left: 1em;
|
46
|
+
padding-right: 1em;
|
47
|
+
text-align: center;
|
48
|
+
color: #055;
|
49
|
+
}
|
50
|
+
|
51
|
+
.attr-name {
|
52
|
+
font-weight: bold;
|
53
|
+
}
|
54
|
+
|
55
|
+
.attr-desc {
|
56
|
+
}
|
57
|
+
|
58
|
+
.attr-value {
|
59
|
+
font-family: monospace;
|
60
|
+
}
|
61
|
+
|
62
|
+
.file-title-prefix {
|
63
|
+
font-size: large;
|
64
|
+
}
|
65
|
+
|
66
|
+
.file-title {
|
67
|
+
font-size: large;
|
68
|
+
font-weight: bold;
|
69
|
+
background: #005;
|
70
|
+
color: #FFF;
|
71
|
+
}
|
72
|
+
|
73
|
+
.banner {
|
74
|
+
background: #005;
|
75
|
+
color: #FFF;
|
76
|
+
border: 1px solid black;
|
77
|
+
padding: 1em;
|
78
|
+
}
|
79
|
+
|
80
|
+
.banner td {
|
81
|
+
background: transparent;
|
82
|
+
color: #FFF;
|
83
|
+
}
|
84
|
+
|
85
|
+
h1 a, h2 a, .sectiontitle a, .banner a {
|
86
|
+
color: #FF0;
|
87
|
+
}
|
88
|
+
|
89
|
+
h1 a:hover, h2 a:hover, .sectiontitle a:hover, .banner a:hover {
|
90
|
+
color: #FF7;
|
91
|
+
}
|
92
|
+
|
93
|
+
.dyn-source {
|
94
|
+
display: none;
|
95
|
+
background: #FFE;
|
96
|
+
color: #000;
|
97
|
+
border: 1px dotted black;
|
98
|
+
margin: 0.5em 2em 0.5em 2em;
|
99
|
+
padding: 0.5em;
|
100
|
+
}
|
101
|
+
|
102
|
+
.dyn-source .cmt {
|
103
|
+
color: #00F;
|
104
|
+
font-style: italic;
|
105
|
+
}
|
106
|
+
|
107
|
+
.dyn-source .kw {
|
108
|
+
color: #070;
|
109
|
+
font-weight: bold;
|
110
|
+
}
|
111
|
+
|
112
|
+
.method {
|
113
|
+
margin-left: 1em;
|
114
|
+
margin-right: 1em;
|
115
|
+
margin-bottom: 1em;
|
116
|
+
}
|
117
|
+
|
118
|
+
.description pre {
|
119
|
+
padding: 0.5em;
|
120
|
+
border: 1px dotted black;
|
121
|
+
background: #FFE;
|
122
|
+
}
|
123
|
+
|
124
|
+
.method .title {
|
125
|
+
font-family: monospace;
|
126
|
+
font-size: large;
|
127
|
+
border-bottom: 1px dashed black;
|
128
|
+
margin-bottom: 0.3em;
|
129
|
+
padding-bottom: 0.1em;
|
130
|
+
}
|
131
|
+
|
132
|
+
.method .description, .method .sourcecode {
|
133
|
+
margin-left: 1em;
|
134
|
+
}
|
135
|
+
|
136
|
+
.description p, .sourcecode p {
|
137
|
+
margin-bottom: 0.5em;
|
138
|
+
}
|
139
|
+
|
140
|
+
.method .sourcecode p.source-link {
|
141
|
+
text-indent: 0em;
|
142
|
+
margin-top: 0.5em;
|
143
|
+
}
|
144
|
+
|
145
|
+
.method .aka {
|
146
|
+
margin-top: 0.3em;
|
147
|
+
margin-left: 1em;
|
148
|
+
font-style: italic;
|
149
|
+
text-indent: 2em;
|
150
|
+
}
|
151
|
+
|
152
|
+
h1 {
|
153
|
+
padding: 1em;
|
154
|
+
border: 1px solid black;
|
155
|
+
font-size: x-large;
|
156
|
+
font-weight: bold;
|
157
|
+
color: #FFF;
|
158
|
+
background: #007;
|
159
|
+
}
|
160
|
+
|
161
|
+
h2 {
|
162
|
+
padding: 0.5em 1em 0.5em 1em;
|
163
|
+
border: 1px solid black;
|
164
|
+
font-size: large;
|
165
|
+
font-weight: bold;
|
166
|
+
color: #FFF;
|
167
|
+
background: #009;
|
168
|
+
}
|
169
|
+
|
170
|
+
h3, h4, h5, h6 {
|
171
|
+
padding: 0.2em 1em 0.2em 1em;
|
172
|
+
border: 1px dashed black;
|
173
|
+
color: #000;
|
174
|
+
background: #AAF;
|
175
|
+
}
|
176
|
+
|
177
|
+
.sourcecode > pre {
|
178
|
+
padding: 0.5em;
|
179
|
+
border: 1px dotted black;
|
180
|
+
background: #FFE;
|
181
|
+
}
|
182
|
+
|
183
|
+
CSS
|
184
|
+
|
185
|
+
XHTML_PREAMBLE = %{<?xml version="1.0" encoding="%charset%"?>
|
186
|
+
<!DOCTYPE html
|
187
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
188
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
189
|
+
}
|
190
|
+
|
191
|
+
HEADER = XHTML_PREAMBLE + <<ENDHEADER
|
192
|
+
<html>
|
193
|
+
<head>
|
194
|
+
<title>%title%</title>
|
195
|
+
<meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
|
196
|
+
<link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
|
197
|
+
|
198
|
+
<script language="JavaScript" type="text/javascript">
|
199
|
+
// <![CDATA[
|
200
|
+
|
201
|
+
function toggleSource( id )
|
202
|
+
{
|
203
|
+
var elem
|
204
|
+
var link
|
205
|
+
|
206
|
+
if( document.getElementById )
|
207
|
+
{
|
208
|
+
elem = document.getElementById( id )
|
209
|
+
link = document.getElementById( "l_" + id )
|
210
|
+
}
|
211
|
+
else if ( document.all )
|
212
|
+
{
|
213
|
+
elem = eval( "document.all." + id )
|
214
|
+
link = eval( "document.all.l_" + id )
|
215
|
+
}
|
216
|
+
else
|
217
|
+
return false;
|
218
|
+
|
219
|
+
if( elem.style.display == "block" )
|
220
|
+
{
|
221
|
+
elem.style.display = "none"
|
222
|
+
link.innerHTML = "show source"
|
223
|
+
}
|
224
|
+
else
|
225
|
+
{
|
226
|
+
elem.style.display = "block"
|
227
|
+
link.innerHTML = "hide source"
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
function openCode( url )
|
232
|
+
{
|
233
|
+
window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" )
|
234
|
+
}
|
235
|
+
// ]]>
|
236
|
+
</script>
|
237
|
+
</head>
|
238
|
+
|
239
|
+
<body>
|
240
|
+
ENDHEADER
|
241
|
+
|
242
|
+
FILE_PAGE = <<HTML
|
243
|
+
<table border='0' cellpadding='0' cellspacing='0' width="100%" class='banner'>
|
244
|
+
<tr><td>
|
245
|
+
<table width="100%" border='0' cellpadding='0' cellspacing='0'><tr>
|
246
|
+
<td class="file-title" colspan="2"><span class="file-title-prefix">File</span><br />%short_name%</td>
|
247
|
+
<td align="right">
|
248
|
+
<table border='0' cellspacing="0" cellpadding="2">
|
249
|
+
<tr>
|
250
|
+
<td>Path:</td>
|
251
|
+
<td>%full_path%
|
252
|
+
IF:cvsurl
|
253
|
+
(<a href="%cvsurl%">CVS</a>)
|
254
|
+
ENDIF:cvsurl
|
255
|
+
</td>
|
256
|
+
</tr>
|
257
|
+
<tr>
|
258
|
+
<td>Modified:</td>
|
259
|
+
<td>%dtm_modified%</td>
|
260
|
+
</tr>
|
261
|
+
</table>
|
262
|
+
</td></tr>
|
263
|
+
</table>
|
264
|
+
</td></tr>
|
265
|
+
</table><br>
|
266
|
+
HTML
|
267
|
+
|
268
|
+
###################################################################
|
269
|
+
|
270
|
+
CLASS_PAGE = <<HTML
|
271
|
+
<table width="100%" border='0' cellpadding='0' cellspacing='0' class='banner'><tr>
|
272
|
+
<td class="file-title"><span class="file-title-prefix">%classmod%</span><br />%full_name%</td>
|
273
|
+
<td align="right">
|
274
|
+
<table cellspacing=0 cellpadding=2>
|
275
|
+
<tr valign="top">
|
276
|
+
<td>In:</td>
|
277
|
+
<td>
|
278
|
+
START:infiles
|
279
|
+
HREF:full_path_url:full_path:
|
280
|
+
IF:cvsurl
|
281
|
+
(<a href="%cvsurl%">CVS</a>)
|
282
|
+
ENDIF:cvsurl
|
283
|
+
END:infiles
|
284
|
+
</td>
|
285
|
+
</tr>
|
286
|
+
IF:parent
|
287
|
+
<tr>
|
288
|
+
<td>Parent:</td>
|
289
|
+
<td>
|
290
|
+
IF:par_url
|
291
|
+
<a href="%par_url%">
|
292
|
+
ENDIF:par_url
|
293
|
+
%parent%
|
294
|
+
IF:par_url
|
295
|
+
</a>
|
296
|
+
ENDIF:par_url
|
297
|
+
</td>
|
298
|
+
</tr>
|
299
|
+
ENDIF:parent
|
300
|
+
</table>
|
301
|
+
</td>
|
302
|
+
</tr>
|
303
|
+
</table>
|
304
|
+
HTML
|
305
|
+
|
306
|
+
###################################################################
|
307
|
+
|
308
|
+
METHOD_LIST = <<HTML
|
309
|
+
<div id="content">
|
310
|
+
IF:diagram
|
311
|
+
<table cellpadding='0' cellspacing='0' border='0' width="100%"><tr><td align="center">
|
312
|
+
%diagram%
|
313
|
+
</td></tr></table>
|
314
|
+
ENDIF:diagram
|
315
|
+
|
316
|
+
IF:description
|
317
|
+
<div class="description">%description%</div>
|
318
|
+
ENDIF:description
|
319
|
+
|
320
|
+
IF:requires
|
321
|
+
<div class="sectiontitle">Required Files</div>
|
322
|
+
<ul>
|
323
|
+
START:requires
|
324
|
+
<li>HREF:aref:name:</li>
|
325
|
+
END:requires
|
326
|
+
</ul>
|
327
|
+
ENDIF:requires
|
328
|
+
|
329
|
+
IF:toc
|
330
|
+
<div class="sectiontitle">Contents</div>
|
331
|
+
<ul>
|
332
|
+
START:toc
|
333
|
+
<li><a href="#%href%">%secname%</a></li>
|
334
|
+
END:toc
|
335
|
+
</ul>
|
336
|
+
ENDIF:toc
|
337
|
+
|
338
|
+
IF:methods
|
339
|
+
<div class="sectiontitle">Methods</div>
|
340
|
+
<ul>
|
341
|
+
START:methods
|
342
|
+
<li>HREF:aref:name:</li>
|
343
|
+
END:methods
|
344
|
+
</ul>
|
345
|
+
ENDIF:methods
|
346
|
+
|
347
|
+
IF:includes
|
348
|
+
<div class="sectiontitle">Included Modules</div>
|
349
|
+
<ul>
|
350
|
+
START:includes
|
351
|
+
<li>HREF:aref:name:</li>
|
352
|
+
END:includes
|
353
|
+
</ul>
|
354
|
+
ENDIF:includes
|
355
|
+
|
356
|
+
START:sections
|
357
|
+
IF:sectitle
|
358
|
+
<div class="sectiontitle"><a name="%secsequence%">%sectitle%</a></div>
|
359
|
+
IF:seccomment
|
360
|
+
<div class="description">
|
361
|
+
%seccomment%
|
362
|
+
</div>
|
363
|
+
ENDIF:seccomment
|
364
|
+
ENDIF:sectitle
|
365
|
+
|
366
|
+
IF:classlist
|
367
|
+
<div class="sectiontitle">Classes and Modules</div>
|
368
|
+
%classlist%
|
369
|
+
ENDIF:classlist
|
370
|
+
|
371
|
+
IF:constants
|
372
|
+
<div class="sectiontitle">Constants</div>
|
373
|
+
<table border='0' cellpadding='5'>
|
374
|
+
START:constants
|
375
|
+
<tr valign='top'>
|
376
|
+
<td class="attr-name">%name%</td>
|
377
|
+
<td>=</td>
|
378
|
+
<td class="attr-value">%value%</td>
|
379
|
+
</tr>
|
380
|
+
IF:desc
|
381
|
+
<tr valign='top'>
|
382
|
+
<td> </td>
|
383
|
+
<td colspan="2" class="attr-desc">%desc%</td>
|
384
|
+
</tr>
|
385
|
+
ENDIF:desc
|
386
|
+
END:constants
|
387
|
+
</table>
|
388
|
+
ENDIF:constants
|
389
|
+
|
390
|
+
IF:attributes
|
391
|
+
<div class="sectiontitle">Attributes</div>
|
392
|
+
<table border='0' cellpadding='5'>
|
393
|
+
START:attributes
|
394
|
+
<tr valign='top'>
|
395
|
+
<td class='attr-rw'>
|
396
|
+
IF:rw
|
397
|
+
[%rw%]
|
398
|
+
ENDIF:rw
|
399
|
+
</td>
|
400
|
+
<td class='attr-name'>%name%</td>
|
401
|
+
<td class='attr-desc'>%a_desc%</td>
|
402
|
+
</tr>
|
403
|
+
END:attributes
|
404
|
+
</table>
|
405
|
+
ENDIF:attributes
|
406
|
+
|
407
|
+
IF:method_list
|
408
|
+
START:method_list
|
409
|
+
IF:methods
|
410
|
+
<div class="sectiontitle">%type% %category% methods</div>
|
411
|
+
START:methods
|
412
|
+
<div class="method">
|
413
|
+
<div class="title">
|
414
|
+
IF:callseq
|
415
|
+
<a name="%aref%"></a><b>%callseq%</b>
|
416
|
+
ENDIF:callseq
|
417
|
+
IFNOT:callseq
|
418
|
+
<a name="%aref%"></a><b>%name%</b>%params%
|
419
|
+
ENDIF:callseq
|
420
|
+
IF:codeurl
|
421
|
+
[ <a href="javascript:openCode('%codeurl%')">source</a> ]
|
422
|
+
ENDIF:codeurl
|
423
|
+
</div>
|
424
|
+
IF:m_desc
|
425
|
+
<div class="description">
|
426
|
+
%m_desc%
|
427
|
+
</div>
|
428
|
+
ENDIF:m_desc
|
429
|
+
IF:aka
|
430
|
+
<div class="aka">
|
431
|
+
This method is also aliased as
|
432
|
+
START:aka
|
433
|
+
<a href="%aref%">%name%</a>
|
434
|
+
END:aka
|
435
|
+
</div>
|
436
|
+
ENDIF:aka
|
437
|
+
IF:sourcecode
|
438
|
+
<div class="sourcecode">
|
439
|
+
<p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
|
440
|
+
<div id="%aref%_source" class="dyn-source">
|
441
|
+
<pre>
|
442
|
+
%sourcecode%
|
443
|
+
</pre>
|
444
|
+
</div>
|
445
|
+
</div>
|
446
|
+
ENDIF:sourcecode
|
447
|
+
</div>
|
448
|
+
END:methods
|
449
|
+
ENDIF:methods
|
450
|
+
END:method_list
|
451
|
+
ENDIF:method_list
|
452
|
+
END:sections
|
453
|
+
</div>
|
454
|
+
HTML
|
455
|
+
|
456
|
+
FOOTER = <<ENDFOOTER
|
457
|
+
</body>
|
458
|
+
</html>
|
459
|
+
ENDFOOTER
|
460
|
+
|
461
|
+
BODY = HEADER + <<ENDBODY
|
462
|
+
!INCLUDE! <!-- banner header -->
|
463
|
+
|
464
|
+
<div id="bodyContent">
|
465
|
+
#{METHOD_LIST}
|
466
|
+
</div>
|
467
|
+
|
468
|
+
#{FOOTER}
|
469
|
+
ENDBODY
|
470
|
+
|
471
|
+
########################## Source code ##########################
|
472
|
+
|
473
|
+
SRC_PAGE = XHTML_PREAMBLE + <<HTML
|
474
|
+
<html>
|
475
|
+
<head><title>%title%</title>
|
476
|
+
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
|
477
|
+
<style>
|
478
|
+
.ruby-comment { color: green; font-style: italic }
|
479
|
+
.ruby-constant { color: #4433aa; font-weight: bold; }
|
480
|
+
.ruby-identifier { color: #222222; }
|
481
|
+
.ruby-ivar { color: #2233dd; }
|
482
|
+
.ruby-keyword { color: #3333FF; font-weight: bold }
|
483
|
+
.ruby-node { color: #777777; }
|
484
|
+
.ruby-operator { color: #111111; }
|
485
|
+
.ruby-regexp { color: #662222; }
|
486
|
+
.ruby-value { color: #662222; font-style: italic }
|
487
|
+
.kw { color: #3333FF; font-weight: bold }
|
488
|
+
.cmt { color: green; font-style: italic }
|
489
|
+
.str { color: #662222; font-style: italic }
|
490
|
+
.re { color: #662222; }
|
491
|
+
</style>
|
492
|
+
</head>
|
493
|
+
<body bgcolor="white">
|
494
|
+
<pre>%code%</pre>
|
495
|
+
</body>
|
496
|
+
</html>
|
497
|
+
HTML
|
498
|
+
|
499
|
+
########################## Index ################################
|
500
|
+
|
501
|
+
FR_INDEX_BODY = <<HTML
|
502
|
+
!INCLUDE!
|
503
|
+
HTML
|
504
|
+
|
505
|
+
FILE_INDEX = XHTML_PREAMBLE + <<HTML
|
506
|
+
<html>
|
507
|
+
<head>
|
508
|
+
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
|
509
|
+
<style>
|
510
|
+
<!--
|
511
|
+
body {
|
512
|
+
background-color: #EEE;
|
513
|
+
font-family: #{FONTS};
|
514
|
+
color: #000;
|
515
|
+
margin: 0px;
|
516
|
+
}
|
517
|
+
.banner {
|
518
|
+
background: #005;
|
519
|
+
color: #FFF;
|
520
|
+
padding: 0.2em;
|
521
|
+
font-size: small;
|
522
|
+
font-weight: bold;
|
523
|
+
text-align: center;
|
524
|
+
}
|
525
|
+
.entries {
|
526
|
+
margin: 0.25em 1em 0 1em;
|
527
|
+
font-size: x-small;
|
528
|
+
}
|
529
|
+
a {
|
530
|
+
display: block;
|
531
|
+
color: #00F;
|
532
|
+
text-decoration: none;
|
533
|
+
white-space: nowrap;
|
534
|
+
}
|
535
|
+
a:hover {
|
536
|
+
color: #77F;
|
537
|
+
text-decoration: underline;
|
538
|
+
}
|
539
|
+
input#link_search {
|
540
|
+
color: #a00;
|
541
|
+
}
|
542
|
+
input#link_search.default {
|
543
|
+
color: #888;
|
544
|
+
}
|
545
|
+
-->
|
546
|
+
</style>
|
547
|
+
<script type="text/javascript" language="javascript">
|
548
|
+
function init_frame_select() {
|
549
|
+
var opts = document.getElementById('frame_select').options;
|
550
|
+
for (i = 0; i < opts.length; i++) {
|
551
|
+
opts[i].selected = (location.href.indexOf(opts[i].value) != -1);
|
552
|
+
}
|
553
|
+
}
|
554
|
+
function do_link_search() {
|
555
|
+
var search_box = document.getElementById('link_search');
|
556
|
+
if (search_box.value == search_box.defaultValue) return;
|
557
|
+
var links = document.getElementById('entries').getElementsByTagName('a');
|
558
|
+
search = new RegExp(search_box.value, 'i');
|
559
|
+
for (i = 0; i < links.length; i++) {
|
560
|
+
links[i].style.display = search.exec(links[i].innerHTML) ? 'block' : 'none';
|
561
|
+
}
|
562
|
+
}
|
563
|
+
function clear_link_search() {
|
564
|
+
var search_box = document.getElementById('link_search');
|
565
|
+
if (search_box.value == search_box.defaultValue) search_box.value = '';
|
566
|
+
search_box.className = '';
|
567
|
+
}
|
568
|
+
function reset_link_search() {
|
569
|
+
var search_box = document.getElementById('link_search');
|
570
|
+
if (search_box.value == '') search_box.value = search_box.defaultValue;
|
571
|
+
search_box.className = 'default';
|
572
|
+
}
|
573
|
+
</script>
|
574
|
+
<base target="docwin">
|
575
|
+
</head>
|
576
|
+
<body onload="init_frame_select(); reset_link_search();">
|
577
|
+
<select id="frame_select" onchange="location.href=this.value" style="width: 100%;">
|
578
|
+
<option value="fr_class_index.html">Classes</option>
|
579
|
+
<option value="fr_file_index.html">Files</option>
|
580
|
+
<option value="fr_method_index.html">Methods</option>
|
581
|
+
</select>
|
582
|
+
<input id="link_search" class="default" type="text" onkeyup="do_link_search()" onfocus="clear_link_search()" onblur="reset_link_search()" style="width: 100%;" value="type search here..." />
|
583
|
+
<div class="banner">%list_title%</div>
|
584
|
+
<div class="entries" id="entries">
|
585
|
+
START:entries
|
586
|
+
<a href="%href%">%name%</a>
|
587
|
+
END:entries
|
588
|
+
</div>
|
589
|
+
</body></html>
|
590
|
+
HTML
|
591
|
+
|
592
|
+
CLASS_INDEX = FILE_INDEX
|
593
|
+
METHOD_INDEX = FILE_INDEX
|
594
|
+
|
595
|
+
INDEX = XHTML_PREAMBLE + <<HTML
|
596
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
597
|
+
<head>
|
598
|
+
<title>%title%</title>
|
599
|
+
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
|
600
|
+
</head>
|
601
|
+
|
602
|
+
<frameset cols="200, *">
|
603
|
+
<frame src="fr_class_index.html" name="framewin" />
|
604
|
+
<frame src="%initial_page%" name="docwin" />
|
605
|
+
</frameset>
|
606
|
+
|
607
|
+
<frameset cols="200,*">
|
608
|
+
<frame src="fr_class_index.html" name="framewin" />
|
609
|
+
IF:inline_source
|
610
|
+
<frame src="%initial_page%" name="docwin">
|
611
|
+
ENDIF:inline_source
|
612
|
+
IFNOT:inline_source
|
613
|
+
<frameset rows="80%,20%">
|
614
|
+
<frame src="%initial_page%" name="docwin">
|
615
|
+
<frame src="blank.html" name="source">
|
616
|
+
</frameset>
|
617
|
+
ENDIF:inline_source
|
618
|
+
<noframes>
|
619
|
+
<body bgcolor="white">
|
620
|
+
Click <a href="html/index.html">here</a> for a non-frames
|
621
|
+
version of this page.
|
622
|
+
</body>
|
623
|
+
</noframes>
|
624
|
+
</frameset>
|
625
|
+
|
626
|
+
</html>
|
627
|
+
HTML
|
628
|
+
|
629
|
+
end
|
630
|
+
end
|
631
|
+
|
data/escape.rb
ADDED
@@ -0,0 +1,247 @@
|
|
1
|
+
# escape.rb - escape/unescape library for several formats
|
2
|
+
#
|
3
|
+
# Copyright (C) 2006,2007 Tanaka Akira <akr@fsij.org>
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
# list of conditions and the following disclaimer.
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# 3. The name of the author may not be used to endorse or promote products
|
14
|
+
# derived from this software without specific prior written permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
17
|
+
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
18
|
+
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
19
|
+
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
20
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
21
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
22
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
23
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
24
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
25
|
+
# OF SUCH DAMAGE.
|
26
|
+
|
27
|
+
# Escape module provides several escape functions.
|
28
|
+
# * URI
|
29
|
+
# * HTML
|
30
|
+
# * shell command
|
31
|
+
module Escape
|
32
|
+
module_function
|
33
|
+
|
34
|
+
# Escape.shell_command composes
|
35
|
+
# a sequence of words to
|
36
|
+
# a single shell command line.
|
37
|
+
# All shell meta characters are quoted and
|
38
|
+
# the words are concatenated with interleaving space.
|
39
|
+
#
|
40
|
+
# Escape.shell_command(["ls", "/"]) #=> "ls /"
|
41
|
+
# Escape.shell_command(["echo", "*"]) #=> "echo '*'"
|
42
|
+
#
|
43
|
+
# Note that system(*command) and
|
44
|
+
# system(Escape.shell_command(command)) is roughly same.
|
45
|
+
# There are two exception as follows.
|
46
|
+
# * The first is that the later may invokes /bin/sh.
|
47
|
+
# * The second is an interpretation of an array with only one element:
|
48
|
+
# the element is parsed by the shell with the former but
|
49
|
+
# it is recognized as single word with the later.
|
50
|
+
# For example, system(*["echo foo"]) invokes echo command with an argument "foo".
|
51
|
+
# But system(Escape.shell_command(["echo foo"])) invokes "echo foo" command without arguments (and it probably fails).
|
52
|
+
def shell_command(command)
|
53
|
+
command.map {|word| shell_single_word(word) }.join(' ')
|
54
|
+
end
|
55
|
+
|
56
|
+
# Escape.shell_single_word quotes shell meta characters.
|
57
|
+
#
|
58
|
+
# The result string is always single shell word, even if
|
59
|
+
# the argument is "".
|
60
|
+
# Escape.shell_single_word("") returns "''".
|
61
|
+
#
|
62
|
+
# Escape.shell_single_word("") #=> "''"
|
63
|
+
# Escape.shell_single_word("foo") #=> "foo"
|
64
|
+
# Escape.shell_single_word("*") #=> "'*'"
|
65
|
+
def shell_single_word(str)
|
66
|
+
if str.empty?
|
67
|
+
"''"
|
68
|
+
elsif %r{\A[0-9A-Za-z+,./:=@_-]+\z} =~ str
|
69
|
+
str
|
70
|
+
else
|
71
|
+
result = ''
|
72
|
+
str.scan(/('+)|[^']+/) {
|
73
|
+
if $1
|
74
|
+
result << %q{\'} * $1.length
|
75
|
+
else
|
76
|
+
result << "'#{$&}'"
|
77
|
+
end
|
78
|
+
}
|
79
|
+
result
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Escape.uri_segment escapes URI segment using percent-encoding.
|
84
|
+
#
|
85
|
+
# Escape.uri_segment("a/b") #=> "a%2Fb"
|
86
|
+
#
|
87
|
+
# The segment is "/"-splitted element after authority before query in URI, as follows.
|
88
|
+
#
|
89
|
+
# scheme://authority/segment1/segment2/.../segmentN?query#fragment
|
90
|
+
#
|
91
|
+
# See RFC 3986 for details of URI.
|
92
|
+
def uri_segment(str)
|
93
|
+
# pchar - pct-encoded = unreserved / sub-delims / ":" / "@"
|
94
|
+
# unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
95
|
+
# sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
96
|
+
str.gsub(%r{[^A-Za-z0-9\-._~!$&'()*+,;=:@]}n) {
|
97
|
+
'%' + $&.unpack("H2")[0].upcase
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
# Escape.uri_path escapes URI path using percent-encoding.
|
102
|
+
# The given path should be a sequence of (non-escaped) segments separated by "/".
|
103
|
+
# The segments cannot contains "/".
|
104
|
+
#
|
105
|
+
# Escape.uri_path("a/b/c") #=> "a/b/c"
|
106
|
+
# Escape.uri_path("a?b/c?d/e?f") #=> "a%3Fb/c%3Fd/e%3Ff"
|
107
|
+
#
|
108
|
+
# The path is the part after authority before query in URI, as follows.
|
109
|
+
#
|
110
|
+
# scheme://authority/path#fragment
|
111
|
+
#
|
112
|
+
# See RFC 3986 for details of URI.
|
113
|
+
#
|
114
|
+
# Note that this function is not appropriate to convert OS path to URI.
|
115
|
+
def uri_path(str)
|
116
|
+
str.gsub(%r{[^/]+}n) { uri_segment($&) }
|
117
|
+
end
|
118
|
+
|
119
|
+
# :stopdoc:
|
120
|
+
def html_form_fast(pairs, sep=';')
|
121
|
+
pairs.map {|k, v|
|
122
|
+
# query-chars - pct-encoded - x-www-form-urlencoded-delimiters =
|
123
|
+
# unreserved / "!" / "$" / "'" / "(" / ")" / "*" / "," / ":" / "@" / "/" / "?"
|
124
|
+
# query-char - pct-encoded = unreserved / sub-delims / ":" / "@" / "/" / "?"
|
125
|
+
# query-char = pchar / "/" / "?" = unreserved / pct-encoded / sub-delims / ":" / "@" / "/" / "?"
|
126
|
+
# unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
127
|
+
# sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
128
|
+
# x-www-form-urlencoded-delimiters = "&" / "+" / ";" / "="
|
129
|
+
k = k.gsub(%r{[^0-9A-Za-z\-\._~:/?@!\$'()*,]}n) {
|
130
|
+
'%' + $&.unpack("H2")[0].upcase
|
131
|
+
}
|
132
|
+
v = v.gsub(%r{[^0-9A-Za-z\-\._~:/?@!\$'()*,]}n) {
|
133
|
+
'%' + $&.unpack("H2")[0].upcase
|
134
|
+
}
|
135
|
+
"#{k}=#{v}"
|
136
|
+
}.join(sep)
|
137
|
+
end
|
138
|
+
# :startdoc:
|
139
|
+
|
140
|
+
# Escape.html_form composes HTML form key-value pairs as a x-www-form-urlencoded encoded string.
|
141
|
+
#
|
142
|
+
# Escape.html_form takes an array of pair of strings or
|
143
|
+
# an hash from string to string.
|
144
|
+
#
|
145
|
+
# Escape.html_form([["a","b"], ["c","d"]]) #=> "a=b&c=d"
|
146
|
+
# Escape.html_form({"a"=>"b", "c"=>"d"}) #=> "a=b&c=d"
|
147
|
+
#
|
148
|
+
# In the array form, it is possible to use same key more than once.
|
149
|
+
# (It is required for a HTML form which contains
|
150
|
+
# checkboxes and select element with multiple attribute.)
|
151
|
+
#
|
152
|
+
# Escape.html_form([["k","1"], ["k","2"]]) #=> "k=1&k=2"
|
153
|
+
#
|
154
|
+
# If the strings contains characters which must be escaped in x-www-form-urlencoded,
|
155
|
+
# they are escaped using %-encoding.
|
156
|
+
#
|
157
|
+
# Escape.html_form([["k=","&;="]]) #=> "k%3D=%26%3B%3D"
|
158
|
+
#
|
159
|
+
# The separator can be specified by the optional second argument.
|
160
|
+
#
|
161
|
+
# Escape.html_form([["a","b"], ["c","d"]], ";") #=> "a=b;c=d"
|
162
|
+
#
|
163
|
+
# See HTML 4.01 for details.
|
164
|
+
def html_form(pairs, sep='&')
|
165
|
+
r = ''
|
166
|
+
first = true
|
167
|
+
pairs.each {|k, v|
|
168
|
+
# query-chars - pct-encoded - x-www-form-urlencoded-delimiters =
|
169
|
+
# unreserved / "!" / "$" / "'" / "(" / ")" / "*" / "," / ":" / "@" / "/" / "?"
|
170
|
+
# query-char - pct-encoded = unreserved / sub-delims / ":" / "@" / "/" / "?"
|
171
|
+
# query-char = pchar / "/" / "?" = unreserved / pct-encoded / sub-delims / ":" / "@" / "/" / "?"
|
172
|
+
# unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
173
|
+
# sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
174
|
+
# x-www-form-urlencoded-delimiters = "&" / "+" / ";" / "="
|
175
|
+
r << sep if !first
|
176
|
+
first = false
|
177
|
+
k.each_byte {|byte|
|
178
|
+
ch = byte.chr
|
179
|
+
if %r{[^0-9A-Za-z\-\._~:/?@!\$'()*,]}n =~ ch
|
180
|
+
r << "%" << ch.unpack("H2")[0].upcase
|
181
|
+
else
|
182
|
+
r << ch
|
183
|
+
end
|
184
|
+
}
|
185
|
+
r << '='
|
186
|
+
v.each_byte {|byte|
|
187
|
+
ch = byte.chr
|
188
|
+
if %r{[^0-9A-Za-z\-\._~:/?@!\$'()*,]}n =~ ch
|
189
|
+
r << "%" << ch.unpack("H2")[0].upcase
|
190
|
+
else
|
191
|
+
r << ch
|
192
|
+
end
|
193
|
+
}
|
194
|
+
}
|
195
|
+
r
|
196
|
+
end
|
197
|
+
|
198
|
+
# :stopdoc:
|
199
|
+
HTML_TEXT_ESCAPE_HASH = {
|
200
|
+
'&' => '&',
|
201
|
+
'<' => '<',
|
202
|
+
'>' => '>',
|
203
|
+
}
|
204
|
+
# :startdoc:
|
205
|
+
|
206
|
+
# Escape.html_text escapes a string appropriate for HTML text using character references.
|
207
|
+
#
|
208
|
+
# It escapes 3 characters:
|
209
|
+
# * '&' to '&'
|
210
|
+
# * '<' to '<'
|
211
|
+
# * '>' to '>'
|
212
|
+
#
|
213
|
+
# Escape.html_text("abc") #=> "abc"
|
214
|
+
# Escape.html_text("a & b < c > d") #=> "a & b < c > d"
|
215
|
+
#
|
216
|
+
# This function is not appropriate for escaping HTML element attribute
|
217
|
+
# because quotes are not escaped.
|
218
|
+
def html_text(str)
|
219
|
+
str.gsub(/[&<>]/) {|ch| HTML_TEXT_ESCAPE_HASH[ch] }
|
220
|
+
end
|
221
|
+
|
222
|
+
# :stopdoc:
|
223
|
+
HTML_ATTR_ESCAPE_HASH = {
|
224
|
+
'&' => '&',
|
225
|
+
'<' => '<',
|
226
|
+
'>' => '>',
|
227
|
+
'"' => '"',
|
228
|
+
}
|
229
|
+
# :startdoc:
|
230
|
+
|
231
|
+
# Escape.html_attr encodes a string as a double-quoted HTML attribute using character references.
|
232
|
+
#
|
233
|
+
# Escape.html_attr("abc") #=> "\"abc\""
|
234
|
+
# Escape.html_attr("a&b") #=> "\"a&b\""
|
235
|
+
# Escape.html_attr("ab&<>\"c") #=> "\"ab&<>"c\""
|
236
|
+
# Escape.html_attr("a'c") #=> "\"a'c\""
|
237
|
+
#
|
238
|
+
# It escapes 4 characters:
|
239
|
+
# * '&' to '&'
|
240
|
+
# * '<' to '<'
|
241
|
+
# * '>' to '>'
|
242
|
+
# * '"' to '"'
|
243
|
+
#
|
244
|
+
def html_attr(str)
|
245
|
+
'"' + str.gsub(/[&<>"]/) {|ch| HTML_ATTR_ESCAPE_HASH[ch] } + '"'
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
# *Audience*: World, QualitySmith
|
6
|
+
|
7
|
+
module SharedTasks
|
8
|
+
#---------------------------------------------------------------------------------------------------------------------------------
|
9
|
+
# Tests
|
10
|
+
|
11
|
+
# Lets you very concisely create a test task using some common default options. A block may be provided if you want to set additional options.
|
12
|
+
# *Example*:
|
13
|
+
# SharedTasks.normal_test_task
|
14
|
+
# *Audience*: World
|
15
|
+
def self.normal_test_task()
|
16
|
+
module_eval do
|
17
|
+
desc 'Run tests'
|
18
|
+
Rake::TestTask.new(:test) do |task|
|
19
|
+
task.libs << 'lib'
|
20
|
+
task.pattern = 'test/**/*_test.rb'
|
21
|
+
task.verbose = true
|
22
|
+
# To do: autorequire color library? Could do something like this once we switch to gem dependencies...
|
23
|
+
#task.ruby_opts << "-r /home/tyler/code/gemables/test_extensions/lib/test_helper.rb"
|
24
|
+
yield task if block_given?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
#---------------------------------------------------------------------------------------------------------------------------------
|
29
|
+
# Documentation
|
30
|
+
|
31
|
+
# Generates an RDoc task for you with common options enabled, including a nicer template than the default.
|
32
|
+
# Pass it a block if you need to customize it.
|
33
|
+
# Example:
|
34
|
+
# SharedTasks.rdoc_task do |rdoc|
|
35
|
+
# rdoc.title = Project::PrettyName
|
36
|
+
# end
|
37
|
+
# *Audience*: World
|
38
|
+
def self.rdoc_task(&block)
|
39
|
+
module_eval do
|
40
|
+
#-------------------------------------------------------------------------------------------
|
41
|
+
desc 'Generate RDoc'
|
42
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
43
|
+
rdoc.rdoc_dir = 'doc'
|
44
|
+
rdoc.options <<
|
45
|
+
'--line-numbers' << # Include line numbers in the source code
|
46
|
+
'--inline-source' << # Causes "Show source" link to display source inline rather than as a popup
|
47
|
+
'--all' << # Include private methods
|
48
|
+
'--diagram' << # Include diagrams showing modules and classes.
|
49
|
+
'--accessor' << 'mattr_accessor' << # So that attributes defined with mattr_accessor will be listed
|
50
|
+
'--extension' << 'rake=rb' # Treat .rake files as files that contain Ruby code
|
51
|
+
rdoc.template = './doc_include/template/qualitysmith.rb'
|
52
|
+
rdoc.rdoc_files.include(
|
53
|
+
'Readme',
|
54
|
+
'lib/**/*.rb'
|
55
|
+
)
|
56
|
+
yield rdoc
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Put images and stuff under doc_include and you can refer to them with links such as Screenshot[link:include/screenshot1.png]
|
62
|
+
task :doc_include do
|
63
|
+
mkdir 'doc' rescue nil
|
64
|
+
cp_r 'doc_include', target = 'doc/include'
|
65
|
+
|
66
|
+
# Remove those pesky .svn directories
|
67
|
+
require 'find'
|
68
|
+
require 'fileutils'
|
69
|
+
Find.find(target) do |path|
|
70
|
+
if File.basename(path) == '.svn'
|
71
|
+
FileUtils.remove_dir(path, true)
|
72
|
+
Find.prune
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Well, I'd rather make :doc_includes a "postrequisite" for :rdoc, but unfortunately Rake doesn't seem to provide a way to specify postrequisites.
|
78
|
+
# and :clobber_rdoc (lib/rake/rdoctask.rb) does a rm_r rdoc_dir so anything we do to the directory *before* :rdoc will get wiped out.
|
79
|
+
# So... we are left with making :doc_include a prerequisite for the publishing tasks. Unless you have a better idea??
|
80
|
+
task :publish_rdoc_local => :rerdoc
|
81
|
+
task :publish_rdoc_local => :doc_include
|
82
|
+
|
83
|
+
|
84
|
+
#---------------------------------------------------------------------------------------------------------------------------------
|
85
|
+
# Packaging (creating a new version/release)
|
86
|
+
|
87
|
+
require 'rake/gempackagetask'
|
88
|
+
|
89
|
+
def release_notes; "doc_include/ReleaseNotes-#{Project::Version}"; end
|
90
|
+
|
91
|
+
def self.package_task(specification, &block)
|
92
|
+
module_eval do
|
93
|
+
Rake::GemPackageTask.new(specification) do |package|
|
94
|
+
package.need_zip = true
|
95
|
+
package.need_tar = true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.inc_version(file)
|
101
|
+
module_eval do
|
102
|
+
desc "Increment version number and create release notes"
|
103
|
+
task :inc_version do
|
104
|
+
# This will be easier once we change to a YAML-based ProjectInfo file...
|
105
|
+
require 'facets/core/file/self/open_as_string'
|
106
|
+
new_version = Project::Version
|
107
|
+
File.open_as_string(file) do |contents|
|
108
|
+
contents.gsub!(/(Version *=.*?)(\d+\.\d+\.\d+)(.*)$/) do
|
109
|
+
before, version, after = $1, $2, $3
|
110
|
+
version = version.split('.')
|
111
|
+
new_version = version[0] + '.' + version[1] + '.' + (version[2].to_i+1).to_s
|
112
|
+
new_text = before + new_version + after
|
113
|
+
puts new_text
|
114
|
+
new_text
|
115
|
+
end
|
116
|
+
end
|
117
|
+
Project.const_set(:Version, new_version)
|
118
|
+
|
119
|
+
system(%(vim #{release_notes}))
|
120
|
+
sh %(svn add #{release_notes})
|
121
|
+
puts "When you're ready to commit, you can use this:"
|
122
|
+
puts "svn ci -F #{release_notes}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
desc "Test installing the gem locally"
|
128
|
+
# Use rake clean to force rebuilding of gem. Otherwise it may see that it has already built a gem file with that name and just try to reinstall the one we've already got.
|
129
|
+
task :gem_install => [:clean, :gem] do
|
130
|
+
# :todo:
|
131
|
+
# This should give a loud warning and require confirmation if this version already installed.
|
132
|
+
# Ask if they want to increment the version number instead (default). It doesn't cost anything to just increment the version number,
|
133
|
+
# and it's bad practice to use the same version number for two versions that are actually *different*.
|
134
|
+
# It would be okay to reinstall (--force) the current version if one is just testing something *prior* to official release.
|
135
|
+
# But once a version is released, it should never be changed. So I guess rather than checking if this version is installed locally,
|
136
|
+
# we should check some flag that we keep in ProjectVersion containing the last version number that has been published and refuse to
|
137
|
+
# rebuild a gem version that has already been released...
|
138
|
+
sh %{sudo gem install --force pkg/#{Project::Name}-#{Project::Version}.gem }
|
139
|
+
end
|
140
|
+
|
141
|
+
desc "Remove generated directories."
|
142
|
+
task :clean do
|
143
|
+
sh %(rm -rf doc/ pkg/)
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
#---------------------------------------------------------------------------------------------------------------------------------
|
148
|
+
# Publishing
|
149
|
+
|
150
|
+
require 'rake/contrib/sshpublisher'
|
151
|
+
|
152
|
+
def self.publish_task()
|
153
|
+
module_eval do
|
154
|
+
desc "Upload RDoc to RubyForge"
|
155
|
+
task :publish_rdoc => [:publish_rdoc_local] do
|
156
|
+
Rake::SshDirPublisher.new("#{ENV['RUBYFORGE_USER']}@rubyforge.org", "/var/www/gforge-projects/#{Project::RubyForgeName}", "doc").upload
|
157
|
+
end
|
158
|
+
|
159
|
+
# This can be invoked from the command line:
|
160
|
+
# rake release RUBYFORGE_USER=myuser \
|
161
|
+
# RUBYFORGE_PASSWORD=mypassword
|
162
|
+
task :verify_user do
|
163
|
+
raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
|
164
|
+
end
|
165
|
+
task :verify_password do
|
166
|
+
raise "RUBYFORGE_PASSWORD environment variable not set!" unless ENV['RUBYFORGE_PASSWORD']
|
167
|
+
end
|
168
|
+
|
169
|
+
desc "Publish package files on RubyForge."
|
170
|
+
task :publish_packages => [:verify_user, :verify_password, :package] do
|
171
|
+
require 'meta_project'
|
172
|
+
require 'rake/contrib/xforge'
|
173
|
+
release_files = FileList[
|
174
|
+
"pkg/#{Project::Name}-#{Project::Version}.gem",
|
175
|
+
"pkg/#{Project::Name}-#{Project::Version}.tgz",
|
176
|
+
"pkg/#{Project::Name}-#{Project::Version}.zip"
|
177
|
+
]
|
178
|
+
|
179
|
+
Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new(Project::RubyForgeName)) do |release|
|
180
|
+
release.user_name = ENV['RUBYFORGE_USER']
|
181
|
+
release.password = ENV['RUBYFORGE_PASSWORD']
|
182
|
+
release.files = release_files.to_a
|
183
|
+
release.package_name = "#{Project::Name}"
|
184
|
+
release.release_name = "#{Project::Name} #{Project::Version}"
|
185
|
+
release.release_changes = ''
|
186
|
+
release.release_notes = File.read(release_notes) # Probably want to put them somewhere else, but for now...
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# *Audience*: Qualitysmith
|
193
|
+
desc "Upload RDoc to rdoc.QualitySmith.com"
|
194
|
+
task :publish_rdoc_local do
|
195
|
+
sh %{ssh commodore mkdir -p /var/www/html/rdoc/#{Project::Name} }
|
196
|
+
sh %{ssh commodore sudo chown :users -R /var/www/html/rdoc/#{Project::Name} }
|
197
|
+
sh %{ssh commodore sudo chmod g+w -R /var/www/html/rdoc/#{Project::Name} }
|
198
|
+
Rake::SshDirPublisher.new("#{ENV['USER']}@commodore", "/var/www/html/rdoc/#{Project::Name}", "doc").upload
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
#---------------------------------------------------------------------------------------------------------------------------------
|
203
|
+
# Announcing
|
204
|
+
|
205
|
+
task :commits_since_last_release do
|
206
|
+
# Look at last release number/revision
|
207
|
+
# Display log messages for all revisions since then
|
208
|
+
# Can use it to write the release notes for you
|
209
|
+
end
|
210
|
+
|
211
|
+
end # SharedTasks
|
212
|
+
|
213
|
+
include SharedTasks
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: escape
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2007-04-26 00:00:00 -07:00
|
8
|
+
summary: ...
|
9
|
+
require_paths:
|
10
|
+
- .
|
11
|
+
email:
|
12
|
+
homepage: http://rdoc.qualitysmith.com/escape
|
13
|
+
rubyforge_project: escape
|
14
|
+
description: ...
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- ...
|
31
|
+
files:
|
32
|
+
- escape.rb
|
33
|
+
- tasks/shared/shared_tasks.rb
|
34
|
+
- doc_include/template/qualitysmith.rb
|
35
|
+
- Readme
|
36
|
+
test_files: []
|
37
|
+
|
38
|
+
rdoc_options:
|
39
|
+
- --title
|
40
|
+
- escape
|
41
|
+
- --main
|
42
|
+
- Readme
|
43
|
+
- --line-numbers
|
44
|
+
extra_rdoc_files:
|
45
|
+
- Readme
|
46
|
+
executables: []
|
47
|
+
|
48
|
+
extensions: []
|
49
|
+
|
50
|
+
requirements: []
|
51
|
+
|
52
|
+
dependencies: []
|
53
|
+
|