escape 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Readme +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 | 
            +
             |