Graphiclious 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.txt CHANGED
@@ -1,3 +1,12 @@
1
+ Changes in 0.1.4
2
+ - additional search field possible
3
+ - url format changed
4
+ - Bugfix in masking ' for Javascript
5
+ - Commandline option --javascript/-j
6
+ - Support Bundles in Javascript
7
+ - Bugfixes in difference computation
8
+ when switching modes
9
+ - Increase count for recent to 25
1
10
  Changes in 0.1.3
2
11
  - Javascript changes urls
3
12
  Changes in 0.1.2
@@ -23,7 +23,7 @@ table, td {
23
23
  </p>
24
24
  <table cellpadding="2" cellspacing="5">
25
25
  <tr>
26
- <td><img src="04-basic-style-js.jpg" alt="04-basic-style-js.jpg" width="537" height="389"></td>
26
+ <td><img src="04-basic-style-js.jpg" alt="04-basic-style-js.jpg" width="569" height="547"></td>
27
27
  </tr>
28
28
  <tr>
29
29
  <td>04-basic-style-js</td>
@@ -34,4 +34,3 @@ table, td {
34
34
  </table>
35
35
  </body>
36
36
  </html>
37
-
@@ -29,7 +29,7 @@
29
29
  <div>03-sample-graph</div>
30
30
  </td>
31
31
  <td>
32
- <a href="original/04-basic-style-js.html"><img src="thumb/t_04-basic-style-js.jpg" alt="04-basic-style-js.jpg" width="100" height="72"></a>
32
+ <a href="original/04-basic-style-js.html"><img src="thumb/t_04-basic-style-js.jpg" alt="04-basic-style-js.jpg" width="100" height="96"></a>
33
33
  <div>04-basic-style-js</div>
34
34
  </td>
35
35
  </tr>
data/javascript/cloud.js CHANGED
@@ -1,63 +1,74 @@
1
1
  // -*-javascript-*-
2
- // $Id: cloud.js 42 2007-10-08 19:09:22Z wsdng $
2
+ // $Id: cloud.js 57 2008-05-13 18:25:29Z wsdng $
3
3
  //
4
4
 
5
5
  // Cloud constructor computes everything we need
6
- // @param links is an Array with Link objects
7
- function Cloud(links, varname, content_id)
6
+ // @param links
7
+ // is an Array with Link objects
8
+ // @param bundles
9
+ // is an Array where the keys are
10
+ // bundle names and each value is an Arrays of tags
11
+ // @param bundle_names
12
+ // is an Array with all bundle names in the
13
+ // order in which they should appear
14
+ function Cloud(links, bundles, bundle_names, varname, content_id)
8
15
  {
9
- this.links = links;
10
- this.links_for_tag = new Array();
11
- this.num_links_for_tag = new Array();
12
- this.filter = new Array(); // which tags are filtered?
13
- this.num_filtered = 0;
14
- this.max_count = 1;
15
- this.tags = new Array();
16
- this.varname = varname;
17
- this.content_id = content_id;
18
- this.filtered_links = new Array();
19
- this.num_filtered_links = 0;
20
- this.visible_links = new Array();
21
- this.search="";
22
- this.change_url = true;
16
+ this.links = links;
17
+ this.links_for_tag = new Array();
18
+ this.num_links_for_tag = new Array();
19
+ this.filter = new Array(); // which tags are filtered?
20
+ this.regexp = null; // patterns to search for
21
+ this.num_filtered = 0;
22
+ this.max_count = 1;
23
+ this.tags = new Array();
24
+ this.varname = varname;
25
+ this.content_id = content_id;
26
+ this.filtered_links = new Array();
27
+ this.num_filtered_links = 0;
28
+ this.visible_links = new Array();
29
+ this.search="";
30
+ this.change_url = true;
31
+ this.bundles = bundles;
32
+ this.bundle_names = bundle_names;
33
+ this.bundle_name = '';
23
34
 
24
- // init hashes
25
- for(var i in links)
26
- {
27
- var link_tags = links[i].tags;
28
- for(var t in link_tags)
35
+ // init hashes
36
+ for(var i in links)
29
37
  {
30
- var tag = link_tags[t];
31
- this.links_for_tag[tag] = new Array();
32
- this.num_links_for_tag[tag] = 0;
33
- this.filter[tag] = false;
34
- }
35
- }
38
+ var link_tags = links[i].tags;
39
+ for(var t in link_tags)
40
+ {
41
+ var tag = link_tags[t];
42
+ this.links_for_tag[tag] = new Array();
43
+ this.num_links_for_tag[tag] = 0;
44
+ this.filter[tag] = false;
45
+ }
46
+ }
36
47
 
37
- // fill hashes
38
- for(var i in links)
39
- {
40
- var link = links[i];
41
- for(var t in link.tags)
48
+ // fill hashes
49
+ for(var i in links)
42
50
  {
43
- var tag = link.tags[t];
44
- this.links_for_tag[tag].push(link);
45
- this.num_links_for_tag[tag] = this.num_links_for_tag[tag] + 1;
51
+ var link = links[i];
52
+ for(var t in link.tags)
53
+ {
54
+ var tag = link.tags[t];
55
+ this.links_for_tag[tag].push(link);
56
+ this.num_links_for_tag[tag] = this.num_links_for_tag[tag] + 1;
57
+ }
46
58
  }
47
- }
48
59
 
49
- // order tags and compute max_count
50
- for(var tag in this.num_links_for_tag)
51
- {
52
- this.tags.push(tag);
53
- if(this.num_links_for_tag[tag] > this.max_count)
60
+ // order tags and compute max_count
61
+ for(var tag in this.num_links_for_tag)
54
62
  {
55
- this.max_count = this.num_links_for_tag[tag];
63
+ this.tags.push(tag);
64
+ if(this.num_links_for_tag[tag] > this.max_count)
65
+ {
66
+ this.max_count = this.num_links_for_tag[tag];
67
+ }
56
68
  }
57
- }
58
- this.tags.sort();
69
+ this.tags.sort();
59
70
  }
60
- new Cloud(new Array());
71
+ new Cloud(new Array(), new Array());
61
72
 
62
73
  Cloud.prototype.MAX_STYLES = 10;
63
74
 
@@ -114,6 +125,31 @@ function Cloud_count_filtered_links_for_tags()
114
125
  }
115
126
  Cloud.prototype.count_filtered_links_for_tags = Cloud_count_filtered_links_for_tags;
116
127
 
128
+ function Cloud_get_bundles_node()
129
+ {
130
+ var div = document.createElement('div');
131
+ div.className = 'bundles';
132
+ for(var i in bundle_names)
133
+ {
134
+ var bundle_name = bundle_names[i];
135
+ var button = document.createElement('span');
136
+ if(this.bundle_name == bundle_name){
137
+ button.className = 'bundle-selected';
138
+ button.appendChild(document.createTextNode(bundle_name));
139
+ } else {
140
+ button.className = 'bundle';
141
+ var ankor = document.createElement('a');
142
+ ankor.href = "javascript:window.location.search='bundle=" + bundle_name + "'";
143
+ ankor.appendChild(document.createTextNode(bundle_name));
144
+ button.appendChild(ankor);
145
+ }
146
+ div.appendChild(button);
147
+ div.appendChild(document.createTextNode(" \n"));
148
+ }
149
+ return div;
150
+ }
151
+ Cloud.prototype.get_bundles_node = Cloud_get_bundles_node;
152
+
117
153
  function Cloud_get_cloud_node()
118
154
  {
119
155
  var div = document.createElement('div');
@@ -123,10 +159,11 @@ function Cloud_get_cloud_node()
123
159
  header.className = 'header_cloud';
124
160
  div.appendChild(header);
125
161
  div.appendChild(document.createTextNode(" \n"));
126
- for(var i in this.tags)
162
+ var cloud_tags = this.bundle_name.length > 0 ? this.bundles[this.bundle_name] : this.tags;
163
+ for(var i in cloud_tags)
127
164
  {
128
- var tag = this.tags[i];
129
- if(this.filter[tag] == false && this.num_links_for_tag[tag] > 0){
165
+ var tag = cloud_tags[i];
166
+ if((this.regexp != null && tag.search(this.regexp) >= 0) || (this.filter[tag] == false && this.num_links_for_tag[tag] > 0)){
130
167
  var span = document.createElement('span');
131
168
  span.className = this.get_style(this.num_links_for_tag[tag]);
132
169
  var tag_node = document.createTextNode(tag);
@@ -180,59 +217,81 @@ Cloud.prototype.get_filter_node = Cloud_get_filter_node;
180
217
 
181
218
  function Cloud_filter_links()
182
219
  {
183
- this.filtered_links = new Array();
184
- this.num_filtered_links = 0;
185
- this.visible_links = new Array();
186
- for(var l in this.links)
187
- {
188
- var link = links[l];
189
- var matched = 0;
190
- var unmatched = 0;
191
- for(t in link.tags){
192
- if(this.filter[link.tags[t]]){
193
- matched++;
194
- } else {
195
- unmatched++;
196
- }
197
- }
198
- if(matched == this.num_filtered){
199
- this.filtered_links.push(link);
200
- this.num_filtered_links++;
201
- if(matched > unmatched){
202
- this.visible_links.push(link);
220
+ this.filtered_links = new Array();
221
+ this.num_filtered_links = 0;
222
+ this.visible_links = new Array();
223
+ for(var l in this.links)
224
+ {
225
+ var link = links[l];
226
+ if(this.regexp != null){
227
+ if(link.matches(this.regexp)){
228
+ this.filtered_links.push(link);
229
+ this.num_filtered_links++;
230
+ this.visible_links.push(link);
231
+ }
232
+ } else { /* no regexp => filter with taglist */
233
+ var matched = 0;
234
+ var unmatched = 0;
235
+ for(t in link.tags){
236
+ if(this.filter[link.tags[t]]){
237
+ matched++;
238
+ } else {
239
+ unmatched++;
240
+ }
241
+ }
242
+ if(matched == this.num_filtered){
243
+ this.filtered_links.push(link);
244
+ this.num_filtered_links++;
245
+ if(matched > unmatched){
246
+ this.visible_links.push(link);
247
+ }
248
+ }
203
249
  }
204
250
  }
205
- }
206
- this.count_filtered_links_for_tags();
251
+ this.count_filtered_links_for_tags();
207
252
  }
208
253
  Cloud.prototype.filter_links = Cloud_filter_links;
209
254
 
210
255
  function Cloud_subst()
211
256
  {
212
- this.filter_links();
213
- var content = document.getElementById(this.content_id);
214
- var div = document.createElement('div');
215
- if(this.num_filtered > 0){
216
- div.appendChild(this.get_filter_node());
217
- }
218
- var list_to_show = this.visible_links;
219
- if(this.num_filtered_links <= 10){
220
- list_to_show = this.filtered_links;
221
- } else {
222
- div.appendChild(this.get_cloud_node());
223
- }
224
- var ul = document.createElement("ul");
225
- ul.className = 'link_list';
226
- list_to_show = list_to_show.sort(Link_compare_desc)
227
- for(var l in list_to_show)
228
- {
229
- var link = list_to_show[l];
230
- var li = document.createElement("li");
231
- ul.appendChild(li);
232
- link.to_html(li);
233
- }
234
- div.appendChild(ul);
235
- content.replaceChild(div, content.firstChild);
257
+ this.filter_links();
258
+ var content = document.getElementById(this.content_id);
259
+ var div = document.createElement('div');
260
+ if(this.bundle_names.length > 0){
261
+ div.appendChild(this.get_bundles_node());
262
+ }
263
+ if(this.num_filtered > 0){
264
+ div.appendChild(this.get_filter_node());
265
+ }
266
+ var num_visible_links = this.visible_links.length;
267
+ var num_hidden_links = this.num_filtered_links - num_visible_links;
268
+ var list_to_show;
269
+ if(this.regexp == null && (this.num_filtered_links <= 20 || num_visible_links > num_hidden_links)){
270
+ list_to_show = this.filtered_links;
271
+ } else {
272
+ list_to_show = this.visible_links;
273
+ div.appendChild(this.get_cloud_node());
274
+ }
275
+ var ul = document.createElement("ul");
276
+ ul.className = 'link_list';
277
+ list_to_show = list_to_show.sort(Link_compare_desc)
278
+ for(var l in list_to_show)
279
+ {
280
+ var link = list_to_show[l];
281
+ var li = document.createElement("li");
282
+ ul.appendChild(li);
283
+ link.to_html(li);
284
+ }
285
+ div.appendChild(ul);
286
+ var stat = document.createElement('p');
287
+ var statString = list_to_show.length;
288
+ if(this.regexp == null){
289
+ statString = statString + "/" + this.num_filtered_links;
290
+ }
291
+ statString = statString + " Links shown";
292
+ stat.appendChild(document.createTextNode(statString));
293
+ div.appendChild(stat);
294
+ content.replaceChild(div, content.firstChild);
236
295
  }
237
296
  Cloud.prototype.subst = Cloud_subst;
238
297
 
@@ -240,9 +299,9 @@ function Cloud_get_search_with(tag)
240
299
  {
241
300
  var new_search = '';
242
301
  if(this.num_filtered > 0){
243
- new_search = this.search + "+" + tag;
302
+ new_search = this.search + "," + tag;
244
303
  } else {
245
- new_search = tag;
304
+ new_search = 'tags=' + tag;
246
305
  }
247
306
  return new_search;
248
307
  }
@@ -250,7 +309,7 @@ Cloud.prototype.get_search_with = Cloud_get_search_with;
250
309
 
251
310
  function Cloud_set_filtered(tag)
252
311
  {
253
- if(this.filter[tag] == false){
312
+ if(tag != '' && this.filter[tag] == false){
254
313
  this.search = this.get_search_with(tag);
255
314
  this.num_filtered++;
256
315
  this.filter[tag] = true;
@@ -268,15 +327,18 @@ Cloud.prototype.add_filter = Cloud_add_filter;
268
327
  function Cloud_get_search_without(tag)
269
328
  {
270
329
  var new_search = '';
271
- var search_tags = this.search.split("+");
272
- var first = true;
273
- for(var i in search_tags){
274
- if(search_tags[i] != tag){
275
- if(first){
276
- new_search = search_tags[i];
277
- first = false;
278
- } else {
279
- new_search += "+" + search_tags[i];
330
+ var pass1 = this.search.split("=");
331
+ if(pass1.length == 2){
332
+ var search_tags = pass1[1].split(",");
333
+ var first = true;
334
+ for(var i in search_tags){
335
+ if(search_tags[i] != tag){
336
+ if(first){
337
+ new_search = "tags=" + search_tags[i];
338
+ first = false;
339
+ } else {
340
+ new_search += "," + search_tags[i];
341
+ }
280
342
  }
281
343
  }
282
344
  }
@@ -295,18 +357,56 @@ function Cloud_remove_filter(tag)
295
357
  }
296
358
  Cloud.prototype.remove_filter = Cloud_remove_filter;
297
359
 
360
+ /*
361
+ actual:
362
+ http://hinterkattentuffel.de/links.htm?bundle=computer
363
+ http://hinterkattentuffel.de/links.htm?tags=c++,c
364
+ ideas:
365
+ http://hinterkattentuffel.de/links.htm?search=pattern
366
+ http://hinterkattentuffel.de/links.htm?tags=c++,c&tags!=java,ruby
367
+ */
298
368
  function Cloud_jump_to(location)
299
369
  {
370
+ /* precondition: cloud just initialized
371
+ TODO: reset all filters if not */
300
372
  var location_params = location.search;
301
373
  var argstr = location_params.substring(1, location_params.length);
302
- var args = argstr.split('+');
374
+ var args = argstr.split('&');
303
375
  for(var i = 0; i < args.length; i++){
304
- var possible_tag = unescape(args[i])
305
- this.set_filtered(possible_tag);
376
+ var keyAndValue = args[i].split("=");
377
+ if(keyAndValue.length == 2){
378
+ var key = keyAndValue[0];
379
+ var value = keyAndValue[1];
380
+ if(key == 'tags'){
381
+ var tags = value.split(",");
382
+ for(var t = 0; t < tags.length; t++){
383
+ var possible_tag = unescape(tags[t])
384
+ this.set_filtered(possible_tag);
385
+ }
386
+ } else if(key == 'bundle'){
387
+ this.bundle_name = unescape(value);
388
+ } else if(key == 'search'){
389
+ this.regexp = new RegExp(unescape(value), 'i');
390
+ }
391
+ } else if(keyAndValue.length == 1) {
392
+ /* backward compatibility:
393
+ http://hinterkattentuffel.de/links.htm?bundle+computer
394
+ http://hinterkattentuffel.de/links.htm?c+cpp
395
+ */
396
+ var parts = keyAndValue[0].split('+');
397
+ if(parts.length == 2 && parts[0] == 'bundle'){
398
+ this.bundle_name = unescape(parts[1]);
399
+ } else {
400
+ for(var p = 0; p < parts.length; p++){
401
+ var possible_tag = unescape(parts[p])
402
+ this.set_filtered(possible_tag);
403
+ }
404
+ }
405
+ }
406
+ }
407
+ if(this.regexp == null && this.bundle_name == '' && this.num_filtered <= 0){
408
+ this.bundle_name = 'full cloud';
306
409
  }
307
410
  this.subst();
308
411
  }
309
- Cloud.prototype.jump_to = Cloud_jump_to;
310
-
311
-
312
-
412
+ Cloud.prototype.jump_to = Cloud_jump_to;
data/javascript/index.htm CHANGED
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
- <!-- $Id: index.htm 42 2007-10-08 19:09:22Z wsdng $ -->
2
+ <!-- $Id: index.htm 56 2008-05-09 16:26:13Z wsdng $ -->
3
3
  <html>
4
4
  <head>
5
5
  <link rel="stylesheet" type="text/css" href="style.css">
@@ -9,16 +9,21 @@
9
9
  <h1>my bookmarks</h1>
10
10
  <div class="main">
11
11
  <noscript>Sorry, but this page requires javascript!</noscript>
12
- <script src="link.js"></script>
13
- <script src="_all.js"></script>
14
- <script src="cloud.js"></script>
12
+ <script type="text/javascript" src="link.js"></script>
13
+ <script type="text/javascript" src="_all.js"></script>
14
+ <script type="text/javascript" src="_bundles.js"></script>
15
+ <script type="text/javascript" src="cloud.js"></script>
16
+ <form method="get">
17
+ Search: <input name="search" type="text" size="30" maxlength="30">
18
+ </form>
19
+ <br>
15
20
  <div id="content">
16
21
  <div></div>
17
22
  </div>
18
23
  </div>
19
24
  <script>
20
25
  <!--
21
- cloud = new Cloud(links, 'cloud', 'content');
26
+ cloud = new Cloud(links, bundles, bundle_names, 'cloud', 'content');
22
27
  //cloud.dont_change_url();
23
28
  cloud.jump_to(document.location);
24
29
  //-->
data/javascript/link.js CHANGED
@@ -1,36 +1,58 @@
1
1
  // -*-javascript-*-
2
- // $Id: link.js 39 2007-01-27 13:36:53Z wsdng $
2
+ // $Id: link.js 55 2008-05-07 22:10:35Z wsdng $
3
3
 
4
4
  // Representing tagged hyperlink
5
- function Link(href, tags, desc)
5
+ function Link(href, tags, desc, ext)
6
6
  {
7
- this.href = href;
8
- this.tags = tags;
9
- this.desc = desc;
7
+ this.href = href;
8
+ this.tags = tags;
9
+ this.desc = desc;
10
+ this.ext = ext;
10
11
  }
11
- new Link('', new Array(), '');
12
+ new Link('', new Array(), '', '');
12
13
 
13
14
  function Link_to_html(parent)
14
15
  {
15
- var ankor = document.createElement("a");
16
- ankor.className = "extern"
17
- ankor.href = this.href;
18
- ankor.appendChild(document.createTextNode(this.desc));
16
+ var ankor = document.createElement("a");
17
+ ankor.className = "extern"
18
+ ankor.href = this.href;
19
+ ankor.appendChild(document.createTextNode(this.desc));
19
20
 
20
- parent.appendChild(ankor);
21
- parent.appendChild(document.createElement("br"));
22
- parent.appendChild(document.createTextNode('tags: ' + this.tags.join(", ")));
23
- parent.appendChild(document.createElement("br"));
21
+ parent.appendChild(ankor);
22
+ parent.appendChild(document.createElement("br"));
23
+
24
+ if(this.ext.length > 0){
25
+ parent.appendChild(document.createTextNode(this.ext));
26
+ parent.appendChild(document.createElement("br"));
27
+ }
28
+
29
+ // parent.appendChild(document.createTextNode('tags: ' + this.tags.join(", ")));
30
+ // parent.appendChild(document.createElement("br"));
24
31
  }
25
32
  Link.prototype.to_html = Link_to_html;
26
33
 
27
- function Link_compare_desc(x, y)
34
+ function Link_matches(regexp)
28
35
  {
29
- if(x.desc < y.desc){
30
- return -1;
31
- }
32
- if(x.desc > y.desc){
33
- return 1;
34
- }
35
- return 0;
36
+ if(this.desc != null && this.desc.search(regexp) >= 0){
37
+ return true;
38
+ }
39
+ if(this.href != null && this.href.search(regexp) >= 0){
40
+ return true;
41
+ }
42
+ if(this.ext != null && this.ext.search(regexp) >= 0){
43
+ return true;
44
+ }
45
+ return false;
36
46
  }
47
+ Link.prototype.matches = Link_matches;
48
+
49
+ function Link_compare_desc(x, y)
50
+ {
51
+ if(x.desc < y.desc){
52
+ return -1;
53
+ }
54
+ if(x.desc > y.desc){
55
+ return 1;
56
+ }
57
+ return 0;
58
+ }
data/javascript/style.css CHANGED
@@ -1,3 +1,7 @@
1
+ #content{
2
+ border:solid 1px;
3
+ }
4
+
1
5
  .filter{
2
6
  margin-bottom:1em;
3
7
  }
@@ -11,6 +15,20 @@
11
15
  margin-bottom:1em;
12
16
  }
13
17
 
18
+ .bundles{
19
+ font-weight:bold;
20
+ margin-bottom:1em;
21
+ }
22
+
23
+ .bundle-selected{
24
+ color:white;
25
+ background-color:gray;
26
+ }
27
+
28
+ .bundle{
29
+ background-color:gray;
30
+ }
31
+
14
32
  .header_cloud{
15
33
  color:white;
16
34
  background-color:black;
data/lib/graphiclious.rb CHANGED
@@ -6,9 +6,11 @@ require 'getoptlong'
6
6
  getOpt = GetoptLong.new(["--user", "-u", GetoptLong::REQUIRED_ARGUMENT],
7
7
  ["--password", "-p", GetoptLong::REQUIRED_ARGUMENT],
8
8
  ["--gui", "-g", GetoptLong::NO_ARGUMENT],
9
+ ["--all", "-a", GetoptLong::NO_ARGUMENT],
9
10
  ["--nomap", "-m", GetoptLong::NO_ARGUMENT],
10
11
  ["--noupdate", "-l", GetoptLong::NO_ARGUMENT],
11
12
  ["--nohtml", "-o", GetoptLong::NO_ARGUMENT],
13
+ ["--javascript", "-j", GetoptLong::NO_ARGUMENT],
12
14
  ["--bundles", "-b", GetoptLong::NO_ARGUMENT],
13
15
  ["--version", "-v", GetoptLong::NO_ARGUMENT],
14
16
  ["--delicious", "-d", GetoptLong::NO_ARGUMENT],
@@ -50,11 +52,13 @@ if opts["--gui"]
50
52
  application = Fox::FXApp.new("Graphiclious", "Sascha D�rdelmann")
51
53
  window = GraphicliousMainWindow.new(application, user, password)
52
54
  window.setOptionFetch(!opts["--noupdate"])
55
+ window.setOptionAll(opts["--all"])
53
56
  window.setOptionGenerate(!opts["--nohtml"])
54
57
  window.setOptionDelicious(opts["--delicious"])
55
58
  window.setOptionBundles(opts["--bundles"])
56
59
  window.setOptionGraphViews(!opts["--nomap"])
57
60
  window.setOptionGraphThumbs(!opts["--nomap"])
61
+ window.setOptionJavasript(opts["--javascript"])
58
62
  application.addSignal("SIGINT", window.method(:onCmdQuit))
59
63
  application.create
60
64
  application.run
@@ -66,15 +70,24 @@ else
66
70
  unless opts["--noupdate"]
67
71
  require 'graphiclious/delicious2yaml'
68
72
  importer = Delicious2Yaml.new(user, password)
73
+ mode_keys = Delicious2Yaml::MODES.keys.sort {|m1, m2| m1.to_s <=> m2.to_s}
74
+ mode = mode_keys[opts["--all"] ? -1 : 0]
75
+ importer.set_mode(mode)
69
76
  importer.run
70
- importer.fetch_and_store_bundles if opts["--bundles"]
71
77
  end
72
78
  unless opts["--nohtml"]
73
- require 'graphiclious/yaml-links2html'
74
- exporter = YamlLinksToHtml.new
75
- exporter.link_to_delicious_if_possible = opts["--delicious"]
76
- exporter.build_graph_thumbs = !opts["--nomap"]
77
- exporter.include_graph_views = !opts["--nomap"]
79
+ if(opts["--javascript"])
80
+ require 'graphiclious/yaml-links2js'
81
+ exporter = YamlLinksToJavascript.new
82
+ else
83
+ require 'graphiclious/yaml-links2html'
84
+ exporter = YamlLinksToHtml.new
85
+ exporter.link_to_delicious_if_possible = opts["--delicious"]
86
+ exporter.build_graph_thumbs = !opts["--nomap"]
87
+ exporter.include_graph_views = !opts["--nomap"]
88
+ end
89
+ exporter.use_bundles = opts["--bundles"]
90
+ exporter.set_working_dir(user)
78
91
  exporter.run
79
92
  end
80
93
  end
@@ -1,81 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  #$Id: delicious2yaml.rb,v 1.8 2006/03/07 23:39:04 wsdng Exp $
3
3
 
4
- require_gem 'Rubilicious'
5
- require 'net/https'
6
-
7
- if(Rubilicious::VERSION == '0.1.5')
8
- class Rubilicious
9
- def all(tag = nil)
10
- args = [(tag ? "tag=#{tag.uri_escape}" : nil)]
11
- get('posts/all?' << args.compact.join('&amp;'), 'post').map do |e|
12
- e['time'] = Time::from_iso8601(e['time'])
13
- e['tags'] = e['tag'].split(/\s/) # wrong in 1.5
14
- e # missing in 1.5
15
- end
16
- end
17
- end
18
- end
19
-
20
- if(Rubilicious::VERSION == '0.2.0')
21
- # #all() and #recent() shoult return the same format
22
- # therefore I changed 'tag' into 'tags'
23
- class Rubilicious
24
- def all(tag = nil)
25
- args = [(tag ? "tag=#{u(tag)}" : nil)]
26
- get('posts/all?' << args.compact.join('&amp;'), 'post').map do |e|
27
- e.merge({
28
- 'time' => Time.iso8601(e['time']),
29
- 'tags' => e['tag'].split(/\s+/),
30
- })
31
- end
32
- end
33
- end
34
- end
35
-
36
- class Rubilicious
37
- #
38
- # Low-level HTTPS GET.
39
- # SDo used the tip at
40
- # http://ruby.about.com/od/tutorials/ss/delicious_tags_4.htm
41
- # to get Rubilicious code working
42
- def https_get(url)
43
- # get proxy info
44
- proxy_host, proxy_port = find_http_proxy
45
- # $stderr.puts "DEBUG: proxy: host = #{proxy_host}, port = #{proxy_port}"
46
-
47
- # get host, port, and base URI for API queries
48
- uri = URI::parse(@base_uri)
49
- base = uri.request_uri
50
-
51
- # prepend base to url
52
- url = "#{base}/#{url}"
53
-
54
- # connect to delicious
55
- http = Net::HTTP.Proxy(proxy_host, proxy_port).new(uri.host, uri.port)
56
- http.use_ssl = true
57
- http.start
58
-
59
- # get URL, check for error
60
- resp = http.get(url, @headers)
61
- unless resp.code =~ /2\d{2}/
62
- puts base
63
- puts url
64
- raise "HTTP #{resp.code}: #{resp.message}"
65
- end
66
-
67
- # close HTTP connection, return response
68
- http.finish
69
- resp.body
70
- end
71
-
72
- # del.icio.us-API change 08/2006!
73
- def http_get(url)
74
- https_get(url)
75
- end
76
- end
77
-
78
4
  require 'yaml'
5
+ require 'graphiclious/delicious_api'
79
6
  require 'graphiclious/utf8'
80
7
 
81
8
  class Delicious2Yaml
@@ -86,16 +13,10 @@ class Delicious2Yaml
86
13
  @working_dir = Dir.getwd
87
14
  @user = user_string
88
15
  @password = password_string
89
- @interface = create_interface
16
+ @interface = Delicious_Api.new(@user, @password)
90
17
  @mode = :b_all
91
18
  end
92
19
 
93
- def create_interface
94
- @interface = Rubilicious.new(@user, @password)
95
- @interface.base_uri = 'https://api.del.icio.us/v1'
96
- @interface
97
- end
98
-
99
20
  def set_working_dir(new_working_dir)
100
21
  @working_dir = new_working_dir
101
22
  end
@@ -170,7 +91,7 @@ class Delicious2Yaml
170
91
  def update_necessary?
171
92
  writeLineOnProtokoll("Check for updates for #{@user} now.")
172
93
 
173
- @time = @interface.update
94
+ @time = @interface.timestamp
174
95
  if File.exists?("#{file_base}.time")
175
96
  last_time = File.open("#{file_base}.time", 'r') { |io|
176
97
  YAML.load(io)
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env ruby
2
+ #$Id: delicious2yaml.rb,v 1.8 2006/03/07 23:39:04 wsdng Exp $
3
+
4
+ require_gem 'Rubilicious'
5
+ require 'net/https'
6
+
7
+ if(Rubilicious::VERSION == '0.1.5')
8
+ class Rubilicious
9
+ def all(tag = nil)
10
+ args = [(tag ? "tag=#{tag.uri_escape}" : nil)]
11
+ get('posts/all?' << args.compact.join('&amp;'), 'post').map do |e|
12
+ e['time'] = Time::from_iso8601(e['time'])
13
+ e['tags'] = e['tag'].split(/\s/) # wrong in 1.5
14
+ e # missing in 1.5
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ if(Rubilicious::VERSION == '0.2.0')
21
+ # #all() and #recent() shoult return the same format
22
+ # therefore I changed 'tag' into 'tags'
23
+ class Rubilicious
24
+ def all(tag = nil)
25
+ args = [(tag ? "tag=#{u(tag)}" : nil)]
26
+ get('posts/all?' << args.compact.join('&amp;'), 'post').map do |e|
27
+ entry = e.merge({
28
+ 'time' => Time.iso8601(e['time']),
29
+ 'tags' => e['tag'].split(/\s+/),
30
+ })
31
+ entry.delete('tag')
32
+ entry
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ class Rubilicious
39
+ #
40
+ # Low-level HTTPS GET.
41
+ # SDo used the tip at
42
+ # http://ruby.about.com/od/tutorials/ss/delicious_tags_4.htm
43
+ # to get Rubilicious code working
44
+ def https_get(url)
45
+ # get proxy info
46
+ proxy_host, proxy_port = find_http_proxy
47
+ # $stderr.puts "DEBUG: proxy: host = #{proxy_host}, port = #{proxy_port}"
48
+
49
+ # get host, port, and base URI for API queries
50
+ uri = URI::parse(@base_uri)
51
+ base = uri.request_uri
52
+
53
+ # prepend base to url
54
+ url = "#{base}/#{url}"
55
+
56
+ # connect to delicious
57
+ http = Net::HTTP.Proxy(proxy_host, proxy_port).new(uri.host, uri.port)
58
+ http.use_ssl = true
59
+ http.start
60
+
61
+ # get URL, check for error
62
+ resp = http.get(url, @headers)
63
+ unless resp.code =~ /2\d{2}/
64
+ puts base
65
+ puts url
66
+ raise "HTTP #{resp.code}: #{resp.message}"
67
+ end
68
+
69
+ # close HTTP connection, return response
70
+ http.finish
71
+ resp.body
72
+ end
73
+
74
+ # del.icio.us-API change 08/2006!
75
+ def http_get(url)
76
+ https_get(url)
77
+ end
78
+ end
79
+
80
+ # These are the only methods that we actually use within
81
+ # Graphiclious. The current implementation uses
82
+ # Rubilicious to realise them. This might change
83
+ # over time.
84
+ class Delicious_Api
85
+ def initialize(user, password)
86
+ @interface = Rubilicious.new(user, password)
87
+ @interface.base_uri = 'https://api.del.icio.us/v1'
88
+ @interface
89
+ end
90
+
91
+ # This method should be used before calling #all.
92
+ # Store this time locally after each call of #all.
93
+ # Compare the stored time with the time returned
94
+ # by this method to decide if an update is necessary.
95
+ def timestamp
96
+ @interface.update
97
+ end
98
+
99
+ def bundles
100
+ @interface.bundles
101
+ end
102
+
103
+ def recent
104
+ links = @interface.recent(nil, 25)
105
+ return nil unless links
106
+ # make sure that format is equal to format in #all
107
+ links.each { |v|
108
+ v["extended"] = "" unless v["extended"]
109
+ }
110
+ links
111
+ end
112
+
113
+ def all
114
+ @interface.all
115
+ end
116
+ end
@@ -195,6 +195,12 @@ class GraphicliousMainWindow < Fox::FXMainWindow
195
195
 
196
196
  def setOptionJavasript(bool)
197
197
  @checkJs.setCheck(bool ? true : false)
198
+ checkJsChanged
199
+ end
200
+
201
+ def setOptionAll(bool)
202
+ modeKeys = Delicious2Yaml::MODES.keys.sort {|m1, m2| m1.to_s <=> m2.to_s}
203
+ @fetchMode.setText(Delicious2Yaml::MODES[modeKeys[bool ? -1 : 0]])
198
204
  end
199
205
 
200
206
  def create
@@ -266,6 +272,7 @@ class GraphicliousMainWindow < Fox::FXMainWindow
266
272
  jsExporter = YamlLinksToJavascript.new
267
273
  jsExporter.set_protocol_block(outputBlock)
268
274
  jsExporter.set_working_dir(File.join(@workingDir, @user))
275
+ jsExporter.use_bundles = @checkBundles.checked?
269
276
  jsExporter.write_only_diff_tags = @checkDiff.checked?
270
277
  jsExporter.include_private = @checkIncludePrivate.checked? && @checkReallyIncludePrivate.checked?
271
278
  jsExporter.run
@@ -295,12 +302,15 @@ class GraphicliousMainWindow < Fox::FXMainWindow
295
302
  end
296
303
 
297
304
  def onCheckJs(sender, sel, ptr)
305
+ checkJsChanged
306
+ end
307
+
308
+ def checkJsChanged
298
309
  dependent_checks = [
299
- @checkBundles,
300
- @checkDiff,
301
- @checkDelicious,
302
- @checkGraphThumbs,
303
- @checkGraphViews]
310
+ @checkDiff,
311
+ @checkDelicious,
312
+ @checkGraphThumbs,
313
+ @checkGraphViews]
304
314
  if @checkJs.checked?
305
315
  dependent_checks.each{ |c| c.disable }
306
316
  else
@@ -6,10 +6,12 @@ module Graphiclious
6
6
  h = String.new
7
7
  h <<
8
8
  "Commandline options:\n" <<
9
+ "--all/-a fetch all instead of recent" <<
9
10
  "--bundles/-b include bundles\n" <<
10
11
  "--delicious/-d prefer links to del.icio.us\n" <<
11
12
  "--gui/-g will start a graphical user interface\n" <<
12
13
  "--help/-h will display this text\n" <<
14
+ "--javascript/-j allow javascript in output files\n" <<
13
15
  "--nomap/-m do not include image map with graph-view" <<
14
16
  "--noupdate/-l do not connect to del.icio.us\n" <<
15
17
  "--nohtml/-o ommit html generation\n" <<
@@ -3,6 +3,6 @@
3
3
 
4
4
  module Graphiclious
5
5
  def self.version
6
- '0.1.3'
6
+ '0.1.4'
7
7
  end
8
8
  end
@@ -65,6 +65,7 @@ class YamlLinksToHtml
65
65
  @use_bundles = false
66
66
  @include_graph_views = false
67
67
  @build_graph_thumbs = @include_graph_views
68
+ @num_files_written = 0
68
69
  end
69
70
 
70
71
  def copy_style_to_user
@@ -136,6 +137,7 @@ class YamlLinksToHtml
136
137
 
137
138
  def write_html_tail_on(fp)
138
139
  fp.puts '</body></html>'
140
+ @num_files_written = @num_files_written + 1
139
141
  end
140
142
 
141
143
  def menuitem(name, id, url)
@@ -202,7 +204,7 @@ class YamlLinksToHtml
202
204
  def write_link_on(link, fp, skip_tags = [])
203
205
  fp.puts(UrlGraph.ankor(link['href'], link['description']))
204
206
  info = link['extended']
205
- if info
207
+ unless info.nil? || info.empty?
206
208
  fp.puts('<br>')
207
209
  fp.puts("#{info}")
208
210
  end
@@ -420,7 +422,7 @@ class YamlLinksToHtml
420
422
  end
421
423
  end
422
424
  end
423
- write_line_on_protokol "Wrote one html-file for each tag to directory #{@html_output_path}."
425
+ write_line_on_protokol "Wrote one html-file for each tag."
424
426
  end
425
427
 
426
428
  def write_double_tag_files
@@ -457,7 +459,7 @@ class YamlLinksToHtml
457
459
  end
458
460
  end
459
461
  end
460
- write_line_on_protokol "Wrote one html-file for each combination of two tags to directory #{@html_output_path}."
462
+ write_line_on_protokol "Wrote one html-file for each combination of two tags."
461
463
  end
462
464
 
463
465
  # make all run-variables garbage collectable
@@ -466,6 +468,7 @@ class YamlLinksToHtml
466
468
  @links_by_tag = nil
467
469
  @links_by_edge = nil
468
470
  @bundles = nil
471
+ @num_files_written = 0
469
472
  end
470
473
 
471
474
  # run the complete batch
@@ -480,7 +483,8 @@ class YamlLinksToHtml
480
483
  load_links
481
484
  write_all_overviews
482
485
  write_single_tag_files
483
- write_double_tag_files
486
+ write_double_tag_files
487
+ write_line_on_protokol "#{@num_files_written.to_s} Files witten to #{@html_output_path}."
484
488
  reset_build_state
485
489
  write_line_on_protokol "Finished."
486
490
  end
@@ -7,13 +7,14 @@ require 'graphiclious/environment'
7
7
  require 'graphiclious/url_graph'
8
8
 
9
9
  class YamlLinksToJavascript
10
- attr_accessor(:write_only_diff_tags, :include_private)
10
+ attr_accessor(:write_only_diff_tags, :include_private, :use_bundles)
11
11
 
12
12
  # differs from working dir in YamlLinksToHtml
13
13
  # because we do not need to know the user
14
14
  def set_working_dir(new_working_dir)
15
15
  @working_dir = new_working_dir
16
16
  @input_file = File.join(@working_dir, 'delicious.yaml')
17
+ @bundles_file = File.join(@working_dir, 'bundles.yaml')
17
18
  @diff_file = File.join(@working_dir, 'delicious.diff.yaml')
18
19
  @js_output_path = File.join(@working_dir, 'js')
19
20
  end
@@ -21,6 +22,7 @@ class YamlLinksToJavascript
21
22
  def initialize
22
23
  @include_private = false
23
24
  @write_only_diff_tags = true
25
+ @use_bundles = true
24
26
  @diff_tags = Set.new
25
27
  set_working_dir(Dir.getwd)
26
28
  end
@@ -56,16 +58,22 @@ class YamlLinksToJavascript
56
58
  fp.puts 'var links = new Array();'
57
59
  fp.puts
58
60
  end
61
+
62
+ def as_javascript_string(ruby_string)
63
+ ruby_string ? ruby_string.gsub(/'/, "\\\\'").gsub(/\n/, "\\\\n") : ''
64
+ end
59
65
 
60
66
  def write_link_on(link, fp, skip_tags = [])
61
67
  fp.puts "links.push(new Link("
62
68
  fp.puts "\t'#{link['href']}',"
63
69
  other_tags = link['tags'].reject { |t| skip_tags.include?(t) }
64
70
  fp.puts "\tnew Array(" + other_tags.collect{|t| "'#{t}'"}.join(", ") + "),"
65
- desc = link['description'].gsub(/'/, "\\'")
66
- fp.puts "\t'#{desc}'));"
71
+ desc = as_javascript_string(link['description'])
72
+ fp.puts "\t'#{desc}', "
73
+ ext = as_javascript_string(link['extended'])
74
+ fp.puts "\t'#{ext}'));"
67
75
  end
68
-
76
+
69
77
  def load_links
70
78
  if(@write_only_diff_tags)
71
79
  @diff_tags = Set.new
@@ -107,7 +115,17 @@ class YamlLinksToJavascript
107
115
  }
108
116
  links
109
117
  end
110
-
118
+
119
+ # load bundles file
120
+ # compute virtual bundles 'full cloud' and 'unbundled'
121
+ def load_bundles
122
+ return {} unless @use_bundles
123
+ bundles = {}
124
+ bundles = File.open(@bundles_file, 'r') { |io|
125
+ YAML.load(io)
126
+ }
127
+ end
128
+
111
129
  def fatal(msg)
112
130
  write_line_on_protokol(msg)
113
131
  exit(1)
@@ -139,6 +157,46 @@ class YamlLinksToJavascript
139
157
  }
140
158
  end
141
159
  end
160
+
161
+ def with_virtual_bundles bundles
162
+ set_of_bundled_tags = {}
163
+ @links_by_tag.keys.each { |tag|
164
+ set_of_bundled_tags[tag] = tag
165
+ }
166
+ bundles['full cloud'] = set_of_bundled_tags.values.sort
167
+ bundles.keys.each { |bundle|
168
+ bundles[bundle].each { |tag|
169
+ set_of_bundled_tags.delete(tag)
170
+ }
171
+ }
172
+ unless set_of_bundled_tags.empty?
173
+ bundles['unbundled'] = set_of_bundled_tags.values.sort
174
+ end
175
+ bundles
176
+ end
177
+
178
+ def write_all_bundles_file bundles
179
+ unless bundles.empty?
180
+ bundle_names = bundles.keys.sort
181
+ bundle_names.unshift('full cloud');
182
+ bundle_names.push('unbundled') if bundles['unbundled'];
183
+ all_bundles = with_virtual_bundles bundles
184
+ else
185
+ bundle_names = Array.new
186
+ all_bundles = bundles
187
+ end
188
+ File.open(File.join(@js_output_path, "_bundles.js"), 'w') do
189
+ |fp|
190
+ fp.puts '/*---javascript generated by graphiclious/yaml-links2js.rb---*/'
191
+ fp.puts
192
+ fp.puts "var bundle_names = new Array('#{bundle_names.join("','")}');"
193
+ fp.puts 'var bundles = new Array();'
194
+ bundle_names.each { |name|
195
+ tagstring = "\n'#{bundles[name].join("',\n'")}'\n"
196
+ fp.puts "bundles['#{name}'] = new Array(#{tagstring});"
197
+ }
198
+ end
199
+ end
142
200
 
143
201
  # run the complete batch
144
202
  def run
@@ -149,7 +207,12 @@ class YamlLinksToJavascript
149
207
  copy_scripts
150
208
  links = load_links
151
209
  write_all_links_file links
152
- # write_single_tag_files
210
+ if @use_bundles && File.exists?(@bundles_file)
211
+ bundles = load_bundles
212
+ else
213
+ bundles = {}
214
+ end
215
+ write_all_bundles_file bundles
153
216
  write_line_on_protokol "Finished."
154
217
  end
155
218
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
2
+ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: Graphiclious
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.3
7
- date: 2007-10-08 00:00:00 +02:00
6
+ version: 0.1.4
7
+ date: 2008-05-13 00:00:00 +02:00
8
8
  summary: Create an html image map pointing to generated static html pages from your del.icio.us links. Uses Rubilicious and Graphviz. Interface done with FXRuby
9
9
  require_paths:
10
10
  - lib
@@ -32,17 +32,7 @@ files:
32
32
  - gemspec.rb
33
33
  - README.txt
34
34
  - styles
35
- - lib
36
- - doc
37
- - bin
38
- - options.yaml
39
- - wickie
40
- - test
41
- - Rakefile
42
- - javascript
43
- - CHANGES.txt
44
35
  - styles/cornflower
45
- - styles/blue-style-1
46
36
  - styles/cornflower/cornflower.png
47
37
  - styles/cornflower/dot-attributes.yaml
48
38
  - styles/cornflower/extern.gif
@@ -51,35 +41,29 @@ files:
51
41
  - styles/cornflower/menuselected.png
52
42
  - styles/cornflower/style.css
53
43
  - styles/cornflower/tr-edge.png
44
+ - styles/blue-style-1
54
45
  - styles/blue-style-1/dot-attributes.yaml
55
46
  - styles/blue-style-1/extern.gif
56
47
  - styles/blue-style-1/style.css
57
- - lib/graphiclious.rb
48
+ - lib
58
49
  - lib/graphiclious
59
- - lib/graphiclious/delicious2yaml.rb
60
50
  - lib/graphiclious/dot_attributes.rb
61
- - lib/graphiclious/help.rb
62
51
  - lib/graphiclious/require_fox.rb
63
52
  - lib/graphiclious/url_graph.rb
64
53
  - lib/graphiclious/utf8.rb
65
54
  - lib/graphiclious/version.rb
66
- - lib/graphiclious/yaml-links2html.rb
67
- - lib/graphiclious/gui.rb
68
55
  - lib/graphiclious/environment.rb
69
56
  - lib/graphiclious/ftp_browser.rb
57
+ - lib/graphiclious/yaml-links2html.rb
58
+ - lib/graphiclious/delicious2yaml.rb
59
+ - lib/graphiclious/delicious_api.rb
60
+ - lib/graphiclious/gui.rb
61
+ - lib/graphiclious/help.rb
70
62
  - lib/graphiclious/yaml-links2js.rb
63
+ - lib/graphiclious.rb
64
+ - doc
71
65
  - doc/screenshots
72
- - doc/index.html
73
- - doc/style.css
74
- - doc/cloud.jpg
75
- - doc/extern.gif
76
- - doc/help.html
77
- - doc/install.html
78
- - doc/screenshots-preview.jpg
79
66
  - doc/screenshots/original
80
- - doc/screenshots/thumb
81
- - doc/screenshots/thumb.html
82
- - doc/screenshots/default.css
83
67
  - doc/screenshots/original/01-blue-style-1.jpg
84
68
  - doc/screenshots/original/02-cornflower.jpg
85
69
  - doc/screenshots/original/03-sample-graph.jpg
@@ -88,14 +72,15 @@ files:
88
72
  - doc/screenshots/original/06-custom-style-js.jpg
89
73
  - doc/screenshots/original/07-user-interface.jpg
90
74
  - doc/screenshots/original/08-ftp-upload.jpg
91
- - doc/screenshots/original/01-blue-style-1.html
75
+ - doc/screenshots/original/05-custom-style.html
92
76
  - doc/screenshots/original/02-cornflower.html
77
+ - doc/screenshots/original/08-ftp-upload.html
78
+ - doc/screenshots/original/07-user-interface.html
93
79
  - doc/screenshots/original/03-sample-graph.html
94
- - doc/screenshots/original/04-basic-style-js.html
95
- - doc/screenshots/original/05-custom-style.html
80
+ - doc/screenshots/original/01-blue-style-1.html
96
81
  - doc/screenshots/original/06-custom-style-js.html
97
- - doc/screenshots/original/07-user-interface.html
98
- - doc/screenshots/original/08-ftp-upload.html
82
+ - doc/screenshots/original/04-basic-style-js.html
83
+ - doc/screenshots/thumb
99
84
  - doc/screenshots/thumb/t_01-blue-style-1.jpg
100
85
  - doc/screenshots/thumb/t_02-cornflower.jpg
101
86
  - doc/screenshots/thumb/t_03-sample-graph.jpg
@@ -104,12 +89,28 @@ files:
104
89
  - doc/screenshots/thumb/t_06-custom-style-js.jpg
105
90
  - doc/screenshots/thumb/t_07-user-interface.jpg
106
91
  - doc/screenshots/thumb/t_08-ftp-upload.jpg
92
+ - doc/screenshots/default.css
93
+ - doc/screenshots/thumb.html
94
+ - doc/index.html
95
+ - doc/style.css
96
+ - doc/cloud.jpg
97
+ - doc/extern.gif
98
+ - doc/help.html
99
+ - doc/install.html
100
+ - doc/screenshots-preview.jpg
101
+ - bin
107
102
  - bin/graphiclious
103
+ - options.yaml
104
+ - wickie
105
+ - test
108
106
  - test/test_delicious2yaml.rb
107
+ - Rakefile
108
+ - javascript
109
109
  - javascript/style.css
110
110
  - javascript/link.js
111
- - javascript/cloud.js
112
111
  - javascript/index.htm
112
+ - javascript/cloud.js
113
+ - CHANGES.txt
113
114
  test_files: []
114
115
 
115
116
  rdoc_options: []