folio 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,129 @@
1
+ <?xml version="1.0"?>
2
+ <log>
3
+ <entry>
4
+ <date>Tue Sep 16 13:18:40 -0400 2008</date>
5
+ <author> trans <transfire@gmail.com></author>
6
+ <revison>77b1389e5bccf8b5052152a8d75cc0c00b1d1b52</revison>
7
+ <type></type>
8
+ <message>added more spec fictures</message>
9
+ </entry>
10
+ <entry>
11
+ <date>Tue Sep 16 13:18:06 -0400 2008</date>
12
+ <author> trans <transfire@gmail.com></author>
13
+ <revison>8a2eb973587d99ef4978191eececf6d0f588b90a</revison>
14
+ <type></type>
15
+ <message>improved error messages</message>
16
+ </entry>
17
+ <entry>
18
+ <date>Tue Sep 16 13:16:36 -0400 2008</date>
19
+ <author> trans <transfire@gmail.com></author>
20
+ <revison>7e0c67bf84574d0343ce78330959f5bf5335247f</revison>
21
+ <type></type>
22
+ <message>added LinkNotFound error</message>
23
+ </entry>
24
+ <entry>
25
+ <date>Tue Sep 16 13:16:03 -0400 2008</date>
26
+ <author> trans <transfire@gmail.com></author>
27
+ <revison>8b72d67261db24f2b40597c34827a35441d76c30</revison>
28
+ <type></type>
29
+ <message>remarked out Folio shortcut #[] method for time being</message>
30
+ </entry>
31
+ <entry>
32
+ <date>Tue Sep 16 11:53:43 -0400 2008</date>
33
+ <author> trans <transfire@gmail.com></author>
34
+ <revison>b1ed5ded2ec3798397461004186bb7b59b9d1ef9</revison>
35
+ <type></type>
36
+ <message>added spec for link.rb</message>
37
+ </entry>
38
+ <entry>
39
+ <date>Tue Sep 16 11:42:22 -0400 2008</date>
40
+ <author> trans <transfire@gmail.com></author>
41
+ <revison>5d2f4d23c060c92d5e7e843079379f43e4d881e0</revison>
42
+ <type></type>
43
+ <message>removed relpath</message>
44
+ </entry>
45
+ <entry>
46
+ <date>Tue Sep 16 11:41:04 -0400 2008</date>
47
+ <author> trans <transfire@gmail.com></author>
48
+ <revison>b9a38c5a8370aa7e4cf57bba80bdafbc39cdb674</revison>
49
+ <type></type>
50
+ <message>renamed spec_prompt.rb to spec_shell.rb</message>
51
+ </entry>
52
+ <entry>
53
+ <date>Tue Sep 16 11:30:40 -0400 2008</date>
54
+ <author> trans <transfire@gmail.com></author>
55
+ <revison>da2eb57bccd4400e0b272836ad9cf23ce23d6b19</revison>
56
+ <type>major</type>
57
+ <message>Renamed Prompt to Shell. </message>
58
+ </entry>
59
+ <entry>
60
+ <date>Thu Sep 11 12:50:59 -0400 2008</date>
61
+ <author> trans <transfire@gmail.com></author>
62
+ <revison>e8dadfff85bbf3dc5cf8cced5be17b0789b04650</revison>
63
+ <type></type>
64
+ <message>moved test directory to spec directory</message>
65
+ </entry>
66
+ <entry>
67
+ <date>Thu Sep 11 12:44:48 -0400 2008</date>
68
+ <author> trans <transfire@gmail.com></author>
69
+ <revison>94d3c4989d012173606ddbc37ddf0a8bc702b661</revison>
70
+ <type></type>
71
+ <message>turned tests into specs</message>
72
+ </entry>
73
+ <entry>
74
+ <date>Thu Sep 11 12:44:07 -0400 2008</date>
75
+ <author> trans <transfire@gmail.com></author>
76
+ <revison>2454fe9d762aee096db7143dacc398582269690e</revison>
77
+ <type></type>
78
+ <message>fixed tests by adding #== to FileObject class</message>
79
+ </entry>
80
+ <entry>
81
+ <date>Wed Sep 10 16:30:28 -0400 2008</date>
82
+ <author> trans <transfire@gmail.com></author>
83
+ <revison>c07c7bd87c0109db8019cac1be89b217855397b5</revison>
84
+ <type></type>
85
+ <message>custom rdoc-template</message>
86
+ </entry>
87
+ <entry>
88
+ <date>Wed Sep 10 15:10:48 -0400 2008</date>
89
+ <author> trans <transfire@gmail.com></author>
90
+ <revison>b4cb8082c81719d5fa0788f0566fe28656f1533d</revison>
91
+ <type></type>
92
+ <message>added TODO and VERSION files</message>
93
+ </entry>
94
+ <entry>
95
+ <date>Wed Sep 10 15:06:56 -0400 2008</date>
96
+ <author> trans <transfire@gmail.com></author>
97
+ <revison>9a926a12a0b061c3ec9bfbd23f5387e65c1e7201</revison>
98
+ <type>major</type>
99
+ <message>Added XDG methods to Prompt class. </message>
100
+ </entry>
101
+ <entry>
102
+ <date>Wed Sep 10 14:16:35 -0400 2008</date>
103
+ <author> trans <transfire@gmail.com></author>
104
+ <revison>474f3f77720a102e47bcd699ae5700b7a40e741b</revison>
105
+ <type></type>
106
+ <message>moved METADATA to meta/</message>
107
+ </entry>
108
+ <entry>
109
+ <date>Sat Sep 06 12:59:40 -0400 2008</date>
110
+ <author> trans <transfire@gmail.com></author>
111
+ <revison>9714d9df4d409a4013acb6530ea3e3ce7b53acb5</revison>
112
+ <type></type>
113
+ <message>added .gitignore file</message>
114
+ </entry>
115
+ <entry>
116
+ <date>Sat Sep 06 12:58:25 -0400 2008</date>
117
+ <author> trans <transfire@gmail.com></author>
118
+ <revison>168a1faaf6148677bfdeec36793d4d141cf2a6d8</revison>
119
+ <type></type>
120
+ <message>reorganized project for reap changes</message>
121
+ </entry>
122
+ <entry>
123
+ <date>Thu Sep 04 17:03:44 -0400 2008</date>
124
+ <author> trans <transfire@gmail.com></author>
125
+ <revison>20c00238d1401c2b4385f0a6109c2c001b922008</revison>
126
+ <type>major</type>
127
+ <message>Started Repository. </message>
128
+ </entry>
129
+ </log>
@@ -0,0 +1,33 @@
1
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
2
+
3
+ <xsl:output cdata-section-elements="script"/>
4
+
5
+ <xsl:template match="/">
6
+ <html>
7
+ <head>
8
+ <title>Changelog</title>
9
+ <link REL='SHORTCUT ICON' HREF="../img/ruby-sm.png" />
10
+ <style>
11
+ td { font-family: sans-serif; padding: 0px 10px; }
12
+ </style>
13
+ </head>
14
+ <body>
15
+ <div class="container">
16
+ <h1>Changelog</h1>
17
+ <table style="width: 100%;">
18
+ <xsl:apply-templates />
19
+ </table>
20
+ </div>
21
+ </body>
22
+ </html>
23
+ </xsl:template>
24
+
25
+ <xsl:template match="entry">
26
+ <tr>
27
+ <td><b><pre><xsl:value-of select="msg"/></pre></b></td>
28
+ <td><xsl:value-of select="author"/></td>
29
+ <td><xsl:value-of select="date"/></td>
30
+ </tr>
31
+ </xsl:template>
32
+
33
+ </xsl:stylesheet>
@@ -0,0 +1,35 @@
1
+ <notes>
2
+ <set label="FIXME">
3
+ <file src="lib/folio/minitar.rb">
4
+ <note line="421" type="FIXME">FIXME: what if an exception is raised in the block?</note>
5
+ <note line="458" type="FIXME">FIXME: what if an exception is raised in the block?</note>
6
+ </file>
7
+ </set>
8
+ <set label="TODO">
9
+ <file src="lib/folio/fileutils.rb">
10
+ <note line="10" type="TODO">TODO: Rename to linkstage or something less likely to name clash?</note>
11
+ <note line="22" type="TODO">TODO: dryrun test here or before folder creation?</note>
12
+ </file>
13
+ <file src="lib/folio/filetest.rb">
14
+ <note line="33" type="TODO">TODO: Make more robust. Probably needs to be fixed for Windows.</note>
15
+ <note line="52" type="TODO">TODO: Make more robust.</note>
16
+ </file>
17
+ <file src="lib/folio/fileobject.rb">
18
+ <note line="204" type="TODO">TODO: I don&apos;t like the name of this.</note>
19
+ </file>
20
+ <file src="lib/folio/document.rb">
21
+ <note line="40" type="TODO">TODO: how to handle unkinking (b/c file no longer exists)</note>
22
+ </file>
23
+ <file src="lib/folio/ziputils.rb">
24
+ <note line="7" type="TODO">TODO: Much of this shells out. It would be best to internalize.</note>
25
+ <note line="29" type="TODO">TODO: support gzip and bzip2 as well.</note>
26
+ <note line="141" type="TODO">TODO: Write unified untar_gzip function.</note>
27
+ </file>
28
+ <file src="lib/folio/shell.rb">
29
+ <note line="66" type="TODO">TODO: Should there be methods like this for each
30
+ type, and raise an error if not the right type?</note>
31
+ <note line="131" type="TODO">TODO: Ultimately merge #glob and #multiglob.</note>
32
+ <note line="196" type="TODO">TODO: Is #out_of_date? this the same as #uptodate?</note>
33
+ </file>
34
+ </set>
35
+ </notes>
@@ -7,5 +7,5 @@ This is the third release since the initial idea.
7
7
  Techincally this is still "alpha" code as it needs
8
8
  many more tests. Nontheless, the library is a rather
9
9
  strightforward wrapper around Ruby internals, so it
10
- already fairly usable.
10
+ is already very usable.
11
11
 
@@ -0,0 +1,552 @@
1
+ <html>
2
+ <head>
3
+ <title>Specifications</title>
4
+
5
+ <style>
6
+ #container{ margin: 0 auto; width: 800px; }
7
+ /* Debug borders */
8
+ p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
9
+ /*
10
+ border: 1px solid red;
11
+ */
12
+ }
13
+ body { font-size: 0.9em; margin: 1em 5% 1em 5%; }
14
+ a { color: blue; text-decoration: underline; }
15
+ a:visited { color: fuchsia; }
16
+ em { font-style: italic; }
17
+ strong { font-weight: bold; }
18
+ tt { color: navy; }
19
+ h1, h2, h3, h4, h5, h6 {
20
+ color: #527bbd;
21
+ font-family: sans-serif;
22
+ margin-top: 1.2em;
23
+ margin-bottom: 0.5em;
24
+ line-height: 1.3;
25
+ }
26
+ h1 { border-bottom: 2px solid silver; }
27
+ h2 { border-bottom: 2px solid silver; padding-top: 0.5em; }
28
+ hr { border: 1px solid silver; }
29
+ p { color: #555;
30
+ text-align: justify;
31
+ margin-top: 0.5em;
32
+ margin-bottom: 0.5em;
33
+ line-height: 1.4em;
34
+ }
35
+ pre { padding: 10; margin: 0; }
36
+
37
+ span#author {
38
+ color: #527bbd;
39
+ font-family: sans-serif;
40
+ font-weight: bold;
41
+ font-size: 1.1em;
42
+ }
43
+ span#email {
44
+ }
45
+ span#revision {
46
+ font-family: sans-serif;
47
+ }
48
+
49
+ div#footer {
50
+ font-family: sans-serif;
51
+ font-size: small;
52
+ border-top: 2px solid silver;
53
+ padding-top: 0.5em;
54
+ margin-top: 4.0em;
55
+ }
56
+
57
+ div#footer-text {
58
+ float: left;
59
+ padding-bottom: 0.5em;
60
+ }
61
+
62
+ div#footer-badges {
63
+ float: right;
64
+ padding-bottom: 0.5em;
65
+ }
66
+
67
+ div.content { /* Block element content. */
68
+ padding: 0;
69
+ }
70
+
71
+ /* Block element titles. */
72
+ h1.title {
73
+ font-family: sans-serif;
74
+ font-weight: bold;
75
+ text-align: left;
76
+ font-size: 3em;
77
+ margin-top: 1.0em;
78
+ margin-bottom: 0.5em;
79
+ }
80
+
81
+ /* Block element titles. */
82
+ div.title, caption.title {
83
+ font-family: sans-serif;
84
+ font-weight: bold;
85
+ text-align: left;
86
+ margin-top: 1.0em;
87
+ margin-bottom: 0.5em;
88
+ }
89
+ div.title + * {
90
+ margin-top: 0;
91
+ }
92
+
93
+ td div.title:first-child {
94
+ margin-top: 0.0em;
95
+ }
96
+ div.content div.title:first-child {
97
+ margin-top: 0.0em;
98
+ }
99
+ div.content + div.title {
100
+ margin-top: 0.0em;
101
+ }
102
+
103
+ div.sidebarblock > div.content {
104
+ background: #ffffee;
105
+ border: 1px solid silver;
106
+ padding: 0.5em;
107
+ }
108
+
109
+ img { border-style: none; }
110
+
111
+ dl { margin-top: 0.8em; margin-bottom: 0.8em; }
112
+ dt { margin-top: 0.5em; margin-bottom: 0; font-style: italic; }
113
+ dd > *:first-child { margin-top: 0; }
114
+ ul, ol { list-style-position: outside; }
115
+
116
+ thead { font-family: sans-serif; font-weight: bold; }
117
+ tfoot { font-weight: bold; }
118
+ </style>
119
+
120
+ <!-- JQuery is needed -->
121
+ <script src="../assets/scripts/jquery.js" type="text/javascript" language="javascript"></script>
122
+
123
+
124
+
125
+ <link href="../assets/styles/spec.css" type="text/css" rel="stylesheet">
126
+ </head>
127
+
128
+ <body>
129
+
130
+ <!-- Side Table of Contents -->
131
+ <div id="sidebar" style="position: fixed; top: 10; right: 10; background: white;">
132
+ <a href="javascript: toc_toggle();">
133
+ <img src="img/icon/book.jpg" height="30px;" style="border: none;" alt="TOC" align="right"/>
134
+ </a>
135
+
136
+ <div id="toc_side" class="toc">
137
+ </div>
138
+ </div>
139
+
140
+ <div id="container">
141
+ <div id="header">
142
+ <img src="img/icon/book.jpg" align="left" style="padding-right: 10px;" alt=""/>
143
+
144
+ <h1 class="title">Specifications</h1>
145
+
146
+ <h1>Table of Contents</h1>
147
+
148
+ <div class="toc">
149
+ </div>
150
+ </div>
151
+
152
+ <div id="content">
153
+ <h1>Document Unit Testing</h1>
154
+ <p>
155
+ Load the Folio library.
156
+ </p>
157
+ <pre>
158
+ require 'folio'
159
+ </pre>
160
+ <p>
161
+ Instantiate document object.
162
+ </p>
163
+ <pre>
164
+ @foo = Folio.file('fixtures/foo.txt')
165
+ </pre>
166
+ <p>
167
+ Confirm it is a a document.
168
+ </p>
169
+ <pre>
170
+ @foo.assert.document?
171
+ </pre>
172
+ <p>
173
+ Confirm it is equal to another document initialized identically.
174
+ </p>
175
+ <pre>
176
+ @foo.assert == Folio.file('fixtures/foo.txt')
177
+ </pre>
178
+ <p>
179
+ Confirm it is equal to the same file initialized from a different working
180
+ directory.
181
+ </p>
182
+ <pre>
183
+ f = nil
184
+ Dir.chdir('fixtures') do
185
+ f = Folio.file('foo.txt')
186
+ end
187
+ @foo.assert == f
188
+ </pre>
189
+ <p>
190
+ Document can be read.
191
+ </p>
192
+ <pre>
193
+ @foo.read.assert == &quot;THIS IS FOO!\n&quot;
194
+ </pre>
195
+ <p>
196
+ The #readlines methods read the document into an array of lines.
197
+ </p>
198
+ <pre>
199
+ @foo.readlines.assert == [&quot;THIS IS FOO!\n&quot;]
200
+ </pre>
201
+ <p>
202
+ We can also open the document for reading using the more traditional open()
203
+ method.
204
+ </p>
205
+ <pre>
206
+ t = nil
207
+ @foo.open('r'){ |f| t = f.read }
208
+ t.assert == &quot;THIS IS FOO!\n&quot;
209
+ </pre>
210
+ <p>
211
+ The #parent method return the Directory object in which the document is
212
+ contained.
213
+ </p>
214
+ <pre>
215
+ @foo.parent.assert == Folio.file('fixtures')
216
+ </pre>
217
+ <p>
218
+ A document can be written to as well using the #write method.
219
+ </p>
220
+ <pre>
221
+ out = Folio.doc('fixtures/out.txt')
222
+ out.write('Hello')
223
+ File.read(out.to_s).assert == 'Hello'
224
+ </pre>
225
+
226
+
227
+
228
+
229
+
230
+ <h1>General Usage of Folio Link Object</h1>
231
+ <p>
232
+ Require the Folio library.
233
+ </p>
234
+ <pre>
235
+ require 'folio'
236
+ </pre>
237
+ <p>
238
+ Instantiate a soft link.
239
+ </p>
240
+ <pre>
241
+ @foo = Folio.file('fixtures/foo_softlink.txt')
242
+ </pre>
243
+ <p>
244
+ It is a link.
245
+ </p>
246
+ <pre>
247
+ @foo.link?.assert == true
248
+ </pre>
249
+ <p>
250
+ It is equal to a link defined identically.
251
+ </p>
252
+ <pre>
253
+ @foo.assert == Folio.file('fixtures/foo_softlink.txt')
254
+ </pre>
255
+ <p>
256
+ The link is not equal to the target document.
257
+ </p>
258
+ <pre>
259
+ @foo.assert! == Folio.file('fixtures/foo.txt')
260
+ </pre>
261
+ <p>
262
+ But it is equal to a same link instantiated from a differnt working
263
+ directory.
264
+ </p>
265
+ <pre>
266
+ f = nil
267
+ Dir.chdir('fixtures') do
268
+ f = Folio.file('foo_softlink.txt')
269
+ end
270
+ @foo.assert == f
271
+ </pre>
272
+ <p>
273
+ Reads the linked document correctly.
274
+ </p>
275
+ <pre>
276
+ @foo.read == &quot;THIS IS FOO!&quot;
277
+ </pre>
278
+ <p>
279
+ Opens the linked document for reading.
280
+ </p>
281
+ <pre>
282
+ t = nil
283
+ @foo.open('r'){ |f| t = f.read }
284
+ t.assert == &quot;THIS IS FOO!\n&quot;
285
+ </pre>
286
+ <p>
287
+ It provides the parent directory object.
288
+ </p>
289
+ <pre>
290
+ @foo.parent.assert == Folio.dir('fixtures')
291
+ </pre>
292
+
293
+
294
+
295
+
296
+ <h1>General Usage of the Folio Shell</h1>
297
+ <p>
298
+ Require the Folio library.
299
+ </p>
300
+ <pre>
301
+ require 'folio'
302
+ </pre>
303
+ <p>
304
+ Open a new Folio::Shell object.
305
+ </p>
306
+ <pre>
307
+ @c = Folio.shell('fixtures')
308
+ </pre>
309
+ <p>
310
+ Method #work returns current working directory.
311
+ </p>
312
+ <pre>
313
+ @c.work.assert == Folio.dir('fixtures')
314
+ </pre>
315
+ <p>
316
+ Method #to_s returns current working dirname.
317
+ </p>
318
+ <pre>
319
+ @c.to_s.assert == File.join(Dir.pwd, 'fixtures')
320
+ </pre>
321
+ <p>
322
+ Method #entries returns a list of names of the current directory content.
323
+ </p>
324
+ <pre>
325
+ @c.entries.sort.assert == ['foo.txt', 'foo_softlink.txt', 'out.txt']
326
+ </pre>
327
+ <p>
328
+ Method #files returns an array of file objects in the current directory.
329
+ </p>
330
+ <pre>
331
+ f = @c.files.to_a
332
+ f.size.assert == 3
333
+ f.assert.include?(Folio.file('fixtures/foo_softlink.txt'))
334
+ f.assert.include?(Folio.file('fixtures/foo.txt'))
335
+ </pre>
336
+
337
+ <h1>Problem Scenerios</h1>
338
+ <h2>Non-existant paths</h2>
339
+ <p>
340
+ If a path does not exist, how do we know if it is intended to be a file, or
341
+ directory, or what?
342
+ </p>
343
+ <pre>
344
+ d1 = dir('home/trans')
345
+ d2 = d1 / 'images'
346
+ </pre>
347
+ <p>
348
+ Optons for resolution include:
349
+ </p>
350
+ <ul>
351
+ <li>Do not support ambiguitous methods.
352
+
353
+ </li>
354
+ <li>Raise an error if non-existant.
355
+
356
+ </li>
357
+ <li>Default to a directory when ambiguious.
358
+
359
+ </li>
360
+ <li>Use a delegator.
361
+
362
+ </li>
363
+ </ul>
364
+ <p>
365
+ The first solution is the most straightforward. The second is reasonably
366
+ viable as well, but at least it provides some understanble use for such
367
+ methods.
368
+ </p>
369
+ <p>
370
+ The return value of the third feels to quirky. And the last is a complex
371
+ solution that effectively only leaves us with some sort of non-disk
372
+ Pathname object; a solution almost a quirky.
373
+ </p>
374
+ <h2>Removal of file-io object</h2>
375
+ <p>
376
+ If we delete a file object, then the object looses it&#8217;s reference.
377
+ This is especially problematic if we do not allow file objects to have
378
+ non-existant paths.
379
+ </p>
380
+ <pre>
381
+ d2 = d1.dir('images')
382
+ d2.rm_r
383
+ </pre>
384
+ <p>
385
+ Options for resolution:
386
+ </p>
387
+ <ul>
388
+ <li>Do not support removal methods.
389
+
390
+ </li>
391
+ <li>Allow non-existant paths.
392
+
393
+ </li>
394
+ <li>Use delegator.
395
+
396
+ </li>
397
+ </ul>
398
+ <p>
399
+ The first solution would mean using a parent directory object to delete
400
+ anything.
401
+ </p>
402
+ <pre>
403
+ f1 = file('/home/trans/.bashrc')
404
+ f1.rm # not allowed
405
+ f1.parent.rm(f1) # instead
406
+ </pre>
407
+ <p>
408
+ I do not like this option becuase it means a directory object would behave
409
+ substantially differnt from other file objects. That might not be so bad is
410
+ Shell and Directory could be one and the same, but methods like #ctime
411
+ would still clash.
412
+ </p>
413
+ <p>
414
+ The second option is the simplist. The file object simply takes on a
415
+ &quot;virtual&quot; state. This could lead to errors being thrown, but it
416
+ is not unacceptable.
417
+ </p>
418
+ <pre>
419
+ f1 = file('/home/trans/.bashrc')
420
+ f1.rm
421
+ f1.ctime # error
422
+ </pre>
423
+ <p>
424
+ The last solution creates an indirection for all file objects. Removing a
425
+ file would redelegate to a virtual pathname object. This is a more
426
+ complicated solution and is really no better than the previous solutution
427
+ &#8212;MethodMissing would be the error. A delegtor solution is a bit more
428
+ interesting when we consider virtual file objects that can mimic a file
429
+ system. However that could be a rather misleading redelgation.
430
+ </p>
431
+ <h2>Looking at the Lager Picture</h2>
432
+ <p>
433
+ Do we really need these objects? Isn&#8217;t the core idea the Folio Shell?
434
+ For the first issue, what is wrong with:
435
+ </p>
436
+ <pre>
437
+ s1 = shell('home/trans')
438
+ s2 = s1 / 'images'
439
+ </pre>
440
+ <p>
441
+ Which would clearly raise an error if it were not existant.
442
+ </p>
443
+ <p>
444
+ As for the second. While it might not be quite as concise, it fits the
445
+ shell prompt pattern:
446
+ </p>
447
+ <pre>
448
+ s1 = shell('/home/trans')
449
+ s1.rm('.bashrc')
450
+ </pre>
451
+ <p>
452
+ Yea, ok. However, while we could pass around shell objects as a form of
453
+ directory object, this would leave us no way to pass file objects.
454
+ </p>
455
+ <h2>Conclusion</h2>
456
+ <p>
457
+ It is fairly clear that the second solution to the second issue is the
458
+ clearest choice. And that Directory and Shell should in fact stay separate
459
+ objects. The &quot;Larger Picture&quot; should be the general pattern for
460
+ theses cases, however this ought not prevent the use of the file objects as
461
+ well.
462
+ </p>
463
+ <p>
464
+ As for the first issue, the first or second options the better choices. I
465
+ will probably raise the error.
466
+ </p>
467
+
468
+
469
+ </div>
470
+ </div>
471
+
472
+ </body>
473
+
474
+ </html>
475
+
476
+ <script src="../assets/scripts/spec.js" type="text/javascript" language="javascript"></script>
477
+
478
+ <script type="text/javascript" language="javascript">
479
+ /*****************************************************************
480
+ * $.toc()
481
+ * by rebecca murphey
482
+ * rmurphey gmail com
483
+ *
484
+ * This function is called on its own and takes as an argument
485
+ * a list of selectors with which it will build a table of
486
+ * contents.
487
+ *
488
+ * The first selector will make up the top level of the TOC;
489
+ * the second selector will make up the second level of the TOC;
490
+ * etc.
491
+ *
492
+ * This function returns a div containing nested unordered lists;
493
+ * each list item is linked to an anchor tag added before the item
494
+ * on the page.
495
+ *
496
+ * usage: $.toc('h1,h2,h3').prependTo('body');
497
+ ************************************************************************/
498
+ (function($) {
499
+ $.toc = function(tocList) {
500
+ $(tocList).addClass('jquery-toc');
501
+ var tocListArray = tocList.split(',');
502
+ $.each(tocListArray, function(i,v) { tocListArray[i] = $.trim(v); });
503
+ var $elements = $('.jquery-toc');
504
+ $('body').append('<div></div>');
505
+ var $toc = $('body div:last');
506
+ var lastLevel = 1;
507
+ $toc.append('<ul class="jquery-toc-1"></ul>');
508
+ $elements.each(function() {
509
+ var $e = $(this);
510
+ var text = $e.text();
511
+ var anchor = text.replace(/ /g,'-');
512
+ $e.before('<a name="' + anchor + '"></a>');
513
+ var level;
514
+ $.each(tocListArray, function(i,v) {
515
+ if (v.match(' ')) {
516
+ var vArray = v.split(' ');
517
+ var e = vArray[vArray.length - 1];
518
+ } else { e = v; }
519
+ if ($e.is(e)) { level = i+1; }
520
+ });
521
+ var className = 'jquery-toc-' + level;
522
+ var li = '<li><a href="#' + anchor + '">' + text + '</a></li>';
523
+ if (level == lastLevel) {
524
+ $('ul.' + className + ':last',$toc).append(li);
525
+ } else if (level > lastLevel) {
526
+ var parentLevel = level - 1;
527
+ var parentClassName = 'jquery-toc-' + parentLevel;
528
+ $('ul.' + parentClassName + ':last',$toc).
529
+ append('<ul class="' + className + '"></ul>');
530
+ $('ul.' + className + ':last',$toc).append(li);
531
+ } else if (level < lastLevel) {
532
+ $('ul.' + className + ':last',$toc).append(li);
533
+ }
534
+ lastLevel = level;
535
+ });
536
+ var $toc_ul = $('ul.jquery-toc-1',$toc);
537
+ $toc.remove();
538
+ return($toc_ul);
539
+ }
540
+ })(jQuery);
541
+ </script>
542
+
543
+ <script>
544
+ function toc_toggle() {
545
+ $('#toc_side').toggle();
546
+ };
547
+
548
+ $.toc('#content h1,h2,h3,h4').appendTo('.toc');
549
+
550
+ toc_toggle();
551
+ </script>
552
+