harvester 0.8.0.pre.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.
Files changed (63) hide show
  1. data/CHANGELOG.rdoc +45 -0
  2. data/README.rdoc +74 -0
  3. data/Rakefile +28 -0
  4. data/bin/harvester +13 -0
  5. data/bin/harvester-chart +5 -0
  6. data/bin/harvester-clock +35 -0
  7. data/bin/harvester-db +15 -0
  8. data/bin/harvester-fetch +5 -0
  9. data/bin/harvester-generate +5 -0
  10. data/bin/harvester-jabber +6 -0
  11. data/bin/harvester-new +25 -0
  12. data/bin/harvester-post +5 -0
  13. data/bin/harvester-run +14 -0
  14. data/collections.yaml +15 -0
  15. data/config.yaml +13 -0
  16. data/data/ent/HTMLlat1.ent +194 -0
  17. data/data/ent/HTMLspecial.ent +77 -0
  18. data/data/ent/HTMLsymbol.ent +241 -0
  19. data/data/sql/dbd-mysql-isotime.diff +11 -0
  20. data/data/sql/harvester-0.6-mysql.diff +59 -0
  21. data/data/sql/harvester-0.7-mysql.diff +39 -0
  22. data/data/sql/mysql/chart.sql +1 -0
  23. data/data/sql/mysql/create.table.enclosures.sql +9 -0
  24. data/data/sql/mysql/create.table.items.sql +8 -0
  25. data/data/sql/mysql/create.table.jabbersettings.sql +5 -0
  26. data/data/sql/mysql/create.table.jabbersubscriptions.sql +5 -0
  27. data/data/sql/mysql/create.table.sources.sql +9 -0
  28. data/data/sql/mysql/create.view.last48hours.sql +1 -0
  29. data/data/sql/postgresql/chart.sql +1 -0
  30. data/data/sql/postgresql/create.table.enclosures.sql +9 -0
  31. data/data/sql/postgresql/create.table.items.sql +8 -0
  32. data/data/sql/postgresql/create.table.jabbersettings.sql +5 -0
  33. data/data/sql/postgresql/create.table.jabbersubscriptions.sql +5 -0
  34. data/data/sql/postgresql/create.table.sources.sql +9 -0
  35. data/data/sql/postgresql/create.view.last48hours.sql +1 -0
  36. data/data/sql/sqlite3/chart.sql +1 -0
  37. data/data/sql/sqlite3/create.table.enclosures.sql +9 -0
  38. data/data/sql/sqlite3/create.table.items.sql +8 -0
  39. data/data/sql/sqlite3/create.table.jabbersettings.sql +5 -0
  40. data/data/sql/sqlite3/create.table.jabbersubscriptions.sql +5 -0
  41. data/data/sql/sqlite3/create.table.sources.sql +9 -0
  42. data/data/sql/sqlite3/create.view.last48hours.sql +1 -0
  43. data/data/templates/atom-all.xml +88 -0
  44. data/data/templates/atom.xml +88 -0
  45. data/data/templates/index.html +412 -0
  46. data/data/templates/rss-all.rdf +86 -0
  47. data/data/templates/rss.rdf +85 -0
  48. data/data/templates/static/harvester.css +365 -0
  49. data/data/templates/static/harvester.gif +0 -0
  50. data/data/templates/static/harvester_ie7.css +15 -0
  51. data/data/templates/static/harvester_lte_ie6.css +27 -0
  52. data/harvester.gemspec +35 -0
  53. data/lib/harvester.rb +132 -0
  54. data/lib/harvester/chart.rb +72 -0
  55. data/lib/harvester/db.rb +123 -0
  56. data/lib/harvester/fetch.rb +96 -0
  57. data/lib/harvester/generate.rb +152 -0
  58. data/lib/harvester/generator/entity_translator.rb +46 -0
  59. data/lib/harvester/generator/link_absolutizer.rb +39 -0
  60. data/lib/harvester/jabber.rb +443 -0
  61. data/lib/harvester/mrss.rb +355 -0
  62. data/lib/harvester/post.rb +19 -0
  63. metadata +237 -0
@@ -0,0 +1,5 @@
1
+ create table jabbersettings (
2
+ jid varchar(255) primary key,
3
+ respect_status boolean,
4
+ message_type varchar(16)
5
+ );
@@ -0,0 +1,5 @@
1
+ create table jabbersubscriptions (
2
+ jid varchar(255) not null,
3
+ collection varchar(255) not null,
4
+ unique (jid(166), collection(166))
5
+ );
@@ -0,0 +1,9 @@
1
+ create table sources (
2
+ collection varchar(255) not null,
3
+ rss varchar(255) not null,
4
+ last varchar(40),
5
+ title varchar(255),
6
+ link varchar(255),
7
+ description text,
8
+ unique (collection(166), rss(166))
9
+ );
@@ -0,0 +1 @@
1
+ create view last48hrs as select items.rss, items.title, items.link, sources.title as blogtitle, sources.collection from items, sources where items.rss = sources.rss and now() - interval '48 hour' < items.date order by date;
@@ -0,0 +1 @@
1
+ select date(items.date) as date,sources.collection from items left join sources on sources.rss=items.rss where date > now() - interval '14 days' and date < now() + interval '1 day' order by date
@@ -0,0 +1,9 @@
1
+ create table enclosures (
2
+ rss varchar(255) not null,
3
+ link varchar(255) not null,
4
+ href varchar(255) not null,
5
+ mime varchar(255),
6
+ title varchar(255),
7
+ length int,
8
+ unique (rss, link, href)
9
+ );
@@ -0,0 +1,8 @@
1
+ create table items (
2
+ rss varchar(255) not null,
3
+ title varchar(255),
4
+ link varchar(255),
5
+ date timestamp,
6
+ description text,
7
+ unique (rss, link)
8
+ );
@@ -0,0 +1,5 @@
1
+ create table jabbersettings (
2
+ jid varchar(255) primary key,
3
+ respect_status boolean,
4
+ message_type varchar(16)
5
+ );
@@ -0,0 +1,5 @@
1
+ create table jabbersubscriptions (
2
+ jid varchar(255) not null,
3
+ collection varchar(255) not null,
4
+ unique (jid, collection)
5
+ );
@@ -0,0 +1,9 @@
1
+ create table sources (
2
+ collection varchar(255) not null,
3
+ rss varchar(255) not null,
4
+ last varchar(40),
5
+ title varchar(255),
6
+ link varchar(255),
7
+ description text,
8
+ unique (collection, rss)
9
+ );
@@ -0,0 +1 @@
1
+ create view last48hrs as select items.rss, items.title, items.link, sources.title as blogtitle, sources.collection from items, sources where items.rss = sources.rss and now() - interval '48 hour' < items.date order by date;
@@ -0,0 +1 @@
1
+ select date(items.date) as date,sources.collection from items left join sources on sources.rss=items.rss where date > time('now', '-14 days') and date < time('now', '+1 day') order by date
@@ -0,0 +1,9 @@
1
+ create table enclosures (
2
+ rss varchar(255) not null,
3
+ link varchar(255) not null,
4
+ href varchar(255) not null,
5
+ mime varchar(255),
6
+ title varchar(255),
7
+ length int,
8
+ unique (rss, link, href)
9
+ );
@@ -0,0 +1,8 @@
1
+ create table items (
2
+ rss varchar(255) not null,
3
+ title varchar(255),
4
+ link varchar(255),
5
+ date timestamp,
6
+ description text,
7
+ unique (rss, link)
8
+ );
@@ -0,0 +1,5 @@
1
+ create table jabbersettings (
2
+ jid varchar(255) primary key,
3
+ respect_status boolean,
4
+ message_type varchar(16)
5
+ );
@@ -0,0 +1,5 @@
1
+ create table jabbersubscriptions (
2
+ jid varchar(255) not null,
3
+ collection varchar(255) not null,
4
+ unique (jid, collection)
5
+ );
@@ -0,0 +1,9 @@
1
+ create table sources (
2
+ collection varchar(255) not null,
3
+ rss varchar(255) not null,
4
+ last varchar(40),
5
+ title varchar(255),
6
+ link varchar(255),
7
+ description text,
8
+ unique (collection, rss)
9
+ );
@@ -0,0 +1 @@
1
+ create view last48hrs as select items.rss, items.title, items.link, sources.title as blogtitle, sources.collection from items, sources where items.rss = sources.rss and time('now', '-48 hour') < items.date order by date;
@@ -0,0 +1,88 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <xsl:stylesheet version="1.0"
3
+ xmlns="http://www.w3.org/2005/Atom"
4
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
5
+ xmlns:crypto="http://exslt.org/crypto"
6
+ xmlns:hv="http://astroblog.spaceboyz.net/harvester/xslt-functions"
7
+ xmlns:date="http://exslt.org/dates-and-times"
8
+ exclude-result-prefixes="xsl hv crypto date">
9
+
10
+ <xsl:output method="xml"
11
+ version="1.0"
12
+ encoding="utf-8"
13
+ media-type="application/atom+xml"
14
+ indent="yes"/>
15
+
16
+ <xsl:template match="/collections">
17
+ <feed>
18
+ <title>Blog Harvester (all)</title>
19
+ <id>http://astroblog.spaceboyz.net/harvester/</id>
20
+ <link href="http://astroblog.spaceboyz.net/harvester/" rel="alternate" type="text/html"/>
21
+ <link href="http://astroblog.spaceboyz.net/harvester/atom-all.xml" rel="self" type="application/atom+xml"/>
22
+ <link href="http://astroblog.spaceboyz.net/harvester/rss-all.rdf" rel="alternate" type="application/rss+xml"/>
23
+
24
+ <subtitle type="xhtml">
25
+ <div xmlns="http://www.w3.org/1999/xhtml">
26
+ <p>
27
+ Blog Harvester sammelt Blogs von Menschen rund um Astro.
28
+ Enthalten sind:
29
+ </p>
30
+ <ul>
31
+ <xsl:for-each select="collection/feed">
32
+ <xsl:sort select="translate(title,
33
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
34
+ 'abcdefghijklmnopqrstuvwxyz')"/>
35
+ <li>
36
+ <a href="{link}"
37
+ title="{description}"><xsl:value-of select="title"/></a>
38
+ </li>
39
+ </xsl:for-each>
40
+ </ul>
41
+ <img src="chart.jpg"/>
42
+ </div>
43
+ </subtitle>
44
+ <updated><xsl:value-of select="date:date-time()"/></updated>
45
+
46
+ <xsl:variable name="collections" select="."/>
47
+ <xsl:for-each select="hv:collection-items('%')/item">
48
+ <xsl:variable name="rss" select="string(rss)"/>
49
+ <xsl:variable name="feed" select="$collections/collection/feed[rss=$rss]"/>
50
+ <entry>
51
+ <title><xsl:value-of select="concat($feed/title,': ',title)"/></title>
52
+ <id><xsl:value-of select="link"/></id>
53
+ <link href="{link}" rel="alternate" type="text/html"/>
54
+ <link href="{$feed/link}" rel="via" type="text/html"/>
55
+ <content type="xhtml">
56
+ <div xmlns="http://www.w3.org/1999/xhtml">
57
+ <xsl:value-of select="hv:item-description($rss, string(link))" disable-output-escaping="yes"/>
58
+ </div>
59
+ </content>
60
+ <updated><xsl:value-of select="date"/></updated>
61
+
62
+ <!-- Enclosures -->
63
+ <xsl:for-each select="hv:item-enclosures($rss, string(link))/enclosure">
64
+ <link rel="enclosure" href="{href}">
65
+ <xsl:if test="mime">
66
+ <xsl:attribute name="type">
67
+ <xsl:value-of select="mime"/>
68
+ </xsl:attribute>
69
+ </xsl:if>
70
+ <xsl:if test="string-length(title) &gt; 0">
71
+ <xsl:attribute name="title">
72
+ <xsl:value-of select="title"/>
73
+ </xsl:attribute>
74
+ </xsl:if>
75
+ <xsl:if test="number(length)">
76
+ <xsl:attribute name="length">
77
+ <xsl:value-of select="number(length)"/>
78
+ </xsl:attribute>
79
+ </xsl:if>
80
+ </link>
81
+ </xsl:for-each>
82
+
83
+ </entry>
84
+ </xsl:for-each>
85
+ </feed>
86
+ </xsl:template>
87
+
88
+ </xsl:stylesheet>
@@ -0,0 +1,88 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <xsl:stylesheet version="1.0"
3
+ xmlns="http://www.w3.org/2005/Atom"
4
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
5
+ xmlns:crypto="http://exslt.org/crypto"
6
+ xmlns:hv="http://astroblog.spaceboyz.net/harvester/xslt-functions"
7
+ xmlns:date="http://exslt.org/dates-and-times"
8
+ exclude-result-prefixes="xsl hv crypto date">
9
+
10
+ <xsl:output method="xml"
11
+ version="1.0"
12
+ encoding="utf-8"
13
+ media-type="application/atom+xml"
14
+ indent="yes"/>
15
+
16
+ <xsl:template match="/collections">
17
+ <feed>
18
+ <title>Blog Harvester</title>
19
+ <id>http://astroblog.spaceboyz.net/harvester/</id>
20
+ <link href="http://astroblog.spaceboyz.net/harvester/" rel="alternate" type="text/html"/>
21
+ <link href="http://astroblog.spaceboyz.net/harvester/atom.xml" rel="self" type="application/atom+xml"/>
22
+ <link href="http://astroblog.spaceboyz.net/harvester/rss.rdf" rel="alternate" type="application/rss+xml"/>
23
+
24
+ <subtitle type="xhtml">
25
+ <div xmlns="http://www.w3.org/1999/xhtml">
26
+ <p>
27
+ Blog Harvester sammelt Blogs von Menschen rund um Astro.
28
+ Enthalten sind:
29
+ </p>
30
+ <ul>
31
+ <xsl:for-each select="collection[@name='blogs']/feed">
32
+ <xsl:sort select="translate(title,
33
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
34
+ 'abcdefghijklmnopqrstuvwxyz')"/>
35
+ <li>
36
+ <a href="{link}"
37
+ title="{description}"><xsl:value-of select="title"/></a>
38
+ </li>
39
+ </xsl:for-each>
40
+ </ul>
41
+ <img src="chart.jpg"/>
42
+ </div>
43
+ </subtitle>
44
+ <updated><xsl:value-of select="date:date-time()"/></updated>
45
+
46
+ <xsl:variable name="blogs" select="collection[@name='blogs']"/>
47
+ <xsl:for-each select="hv:collection-items('blogs')/item">
48
+ <xsl:variable name="rss" select="string(rss)"/>
49
+ <xsl:variable name="feed" select="$blogs/feed[rss=$rss]"/>
50
+ <entry>
51
+ <title><xsl:value-of select="concat($feed/title,': ',title)"/></title>
52
+ <id><xsl:value-of select="link"/></id>
53
+ <link href="{link}" rel="alternate" type="text/html"/>
54
+ <link href="{$feed/link}" rel="via" type="text/html"/>
55
+ <content type="xhtml">
56
+ <div xmlns="http://www.w3.org/1999/xhtml">
57
+ <xsl:value-of select="hv:item-description($rss, string(link))" disable-output-escaping="yes"/>
58
+ </div>
59
+ </content>
60
+ <updated><xsl:value-of select="date"/></updated>
61
+
62
+ <!-- Enclosures -->
63
+ <xsl:for-each select="hv:item-enclosures($rss, string(link))/enclosure">
64
+ <link rel="enclosure" href="{href}">
65
+ <xsl:if test="mime">
66
+ <xsl:attribute name="type">
67
+ <xsl:value-of select="mime"/>
68
+ </xsl:attribute>
69
+ </xsl:if>
70
+ <xsl:if test="string-length(title) &gt; 0">
71
+ <xsl:attribute name="title">
72
+ <xsl:value-of select="title"/>
73
+ </xsl:attribute>
74
+ </xsl:if>
75
+ <xsl:if test="number(length)">
76
+ <xsl:attribute name="length">
77
+ <xsl:value-of select="number(length)"/>
78
+ </xsl:attribute>
79
+ </xsl:if>
80
+ </link>
81
+ </xsl:for-each>
82
+
83
+ </entry>
84
+ </xsl:for-each>
85
+ </feed>
86
+ </xsl:template>
87
+
88
+ </xsl:stylesheet>
@@ -0,0 +1,412 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <xsl:stylesheet version="1.0"
3
+ xmlns="http://www.w3.org/1999/xhtml"
4
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
5
+ xmlns:hv="http://astroblog.spaceboyz.net/harvester/xslt-functions"
6
+ xmlns:date="http://exslt.org/dates-and-times"
7
+ xmlns:str="http://exslt.org/strings"
8
+ exclude-result-prefixes="xsl hv date str">
9
+
10
+ <xsl:output method="xml"
11
+ version="1.0"
12
+ encoding="utf-8"
13
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
14
+ doctype-system="DTD/xhtml1-strict.dtd"
15
+ indent="yes"/>
16
+
17
+
18
+ <xsl:template match="/collections">
19
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="de">
20
+ <head>
21
+ <title>Blog Harvester</title>
22
+ <link rel="alternate" type="application/atom+xml" title="ATOM 1.0" href="atom.xml" />
23
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="rss.rdf" />
24
+ <link rel="alternate" type="application/atom+xml" title="ATOM 1.0 (all)" href="atom-all.xml" />
25
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0 (all)" href="rss-all.rdf" />
26
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
27
+ <link rel="stylesheet" type="text/css" href="harvester.css"/>
28
+ <link rel="shortcut icon" type="image/gif" href="harvester.gif"/>
29
+ <xsl:comment><![CDATA[[if IE 7]>
30
+ <link rel="stylesheet" type="text/css" href="harvester_ie7.css" />
31
+ <![endif]]]></xsl:comment>
32
+ <xsl:comment><![CDATA[[if lte IE 6]>
33
+ <link rel="stylesheet" type="text/css" href="harvester_lte_ie6.css" />
34
+ <![endif]]]></xsl:comment>
35
+ </head>
36
+
37
+ <body>
38
+ <div class="head">
39
+ <h1>Blog Harvester</h1>
40
+ <img src="chart.jpg" class="chart" alt="Harvested items per day"/>
41
+ </div>
42
+
43
+ <div class="tickers1">
44
+ <div class="ticker">
45
+ <h2>Harvesting</h2>
46
+ <ul class="tickerlinks">
47
+ <xsl:for-each select="collection[@name='blogs']/feed">
48
+ <xsl:sort select="translate(title, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
49
+ <li><a href="{link}" title="{description}"><xsl:value-of select="title"/></a></li>
50
+ </xsl:for-each>
51
+ </ul>
52
+ </div>
53
+ <div class="ticker">
54
+ <h2>Apropos</h2>
55
+ <p>
56
+ The Harvester is made of fresh flesh from the blogosphere,
57
+ clean design by Tigion
58
+ and hacked-together Ruby scripts by Astro,
59
+ improved by Neingeist, Josef and J-_-L.
60
+ </p>
61
+ </div>
62
+ <div class="ticker">
63
+ <h2>To be fed</h2>
64
+ <p>
65
+ Just blogs: <a href="atom.xml">ATOM 1.0</a> or <a href="rss.rdf">RSS 2.0</a>,
66
+ </p>
67
+ <p>
68
+ All collections: <a href="atom-all.xml">ATOM 1.0</a> or <a href="rss-all.rdf">RSS 2.0</a>
69
+ </p>
70
+ </div>
71
+ <div class="ticker">
72
+ <h2>Info</h2>
73
+ <p>...</p>
74
+ </div>
75
+ <div class="ticker">
76
+ <h2>Links</h2>
77
+ <ul class="tickerlinks">
78
+ <li><a href="http://ruby-lang.org/">Ruby</a></li>
79
+ </ul>
80
+ </div>
81
+
82
+ <xsl:call-template name="ticker-boxen">
83
+ <xsl:with-param name="collection" select="'ticker'"/>
84
+ </xsl:call-template>
85
+
86
+ <xsl:call-template name="ticker-boxen">
87
+ <xsl:with-param name="collection" select="'projects'"/>
88
+ </xsl:call-template>
89
+ </div>
90
+
91
+ <div class="tickers2">
92
+ <xsl:if test="hv:collection-items('photos')/item">
93
+ <div class="ticker">
94
+ <h2>Photos</h2>
95
+
96
+ <ul class="photos">
97
+ <xsl:for-each select="hv:collection-items('photos')/item">
98
+
99
+ <xsl:variable name="title" select="title"/>
100
+ <xsl:variable name="link" select="link"/>
101
+
102
+ <xsl:for-each select="hv:item-images(string(rss),
103
+ string(link))//img">
104
+ <li>
105
+ <a href="{$link}">
106
+ <img src="{@src}" title="{$title}" alt="{$title}"/>
107
+ </a>
108
+ </li>
109
+ </xsl:for-each>
110
+ </xsl:for-each>
111
+ </ul>
112
+ </div>
113
+ </xsl:if>
114
+
115
+ <xsl:call-template name="ticker-boxen">
116
+ <xsl:with-param name="collection" select="'links'"/>
117
+ </xsl:call-template>
118
+ </div>
119
+
120
+ <div class="tickers3">
121
+ <xsl:variable name="microblogs"
122
+ select="collection[@name='microblogs']"/>
123
+ <xsl:variable name="items"
124
+ select="hv:collection-items('microblogs', 100)"/>
125
+ <xsl:variable name="now"
126
+ select="date:date-time()"/>
127
+
128
+ <div class="ticker">
129
+ <h2>Microblogging — today</h2>
130
+ <ul>
131
+ <xsl:for-each select="$items/item">
132
+ <!--xsl:sort select="date" order="descending"/-->
133
+ <xsl:variable name="diff"
134
+ select="date:difference(date, $now)"/>
135
+ <xsl:if test="$diff = 'P0D' or
136
+ starts-with($diff, 'PT') or
137
+ starts-with($diff, '-P')">
138
+ <xsl:variable name="rss" select="string(rss)"/>
139
+ <xsl:variable name="feed"
140
+ select="$microblogs/feed[rss=$rss]"/>
141
+ <xsl:call-template name="microblog-entry">
142
+ <xsl:with-param name="feed" select="$feed"/>
143
+ <xsl:with-param name="entry" select="."/>
144
+ </xsl:call-template>
145
+ </xsl:if>
146
+ </xsl:for-each>
147
+ </ul>
148
+ </div>
149
+ <div class="ticker">
150
+ <h2>Microblogging — yesterday</h2>
151
+ <ul>
152
+ <xsl:for-each select="$items/item">
153
+ <!--xsl:sort select="date" order="descending"/-->
154
+ <xsl:if test="starts-with(date:difference(date, $now),
155
+ 'P1DT')">
156
+ <xsl:variable name="rss" select="string(rss)"/>
157
+ <xsl:variable name="feed"
158
+ select="$microblogs/feed[rss=$rss]"/>
159
+ <xsl:call-template name="microblog-entry">
160
+ <xsl:with-param name="feed" select="$feed"/>
161
+ <xsl:with-param name="entry" select="."/>
162
+ </xsl:call-template>
163
+ </xsl:if>
164
+ </xsl:for-each>
165
+ </ul>
166
+ </div>
167
+ <div class="ticker">
168
+ <h2>Microblogging — past</h2>
169
+ <ul>
170
+ <xsl:for-each select="hv:collection-items('microblogs')/item">
171
+ <!--xsl:sort select="date" order="descending"/-->
172
+ <xsl:variable name="diff"
173
+ select="date:difference(date, $now)"/>
174
+ <xsl:if test="not($diff = 'P0D') and
175
+ not(starts-with($diff, 'PT')) and
176
+ not(starts-with($diff, 'P1DT')) and
177
+ not(starts-with($diff, '-P'))">
178
+ <xsl:variable name="rss" select="string(rss)"/>
179
+ <xsl:variable name="feed"
180
+ select="$microblogs/feed[rss=$rss]"/>
181
+ <xsl:call-template name="microblog-entry">
182
+ <xsl:with-param name="feed" select="$feed"/>
183
+ <xsl:with-param name="entry" select="."/>
184
+ </xsl:call-template>
185
+ </xsl:if>
186
+ </xsl:for-each>
187
+ </ul>
188
+ </div>
189
+ </div>
190
+
191
+ <div class="hfeed">
192
+ <xsl:variable name="blogs" select="collection[@name='blogs']"/>
193
+
194
+ <xsl:for-each select="hv:collection-items('blogs')/item">
195
+ <xsl:variable name="rss" select="string(rss)"/>
196
+ <xsl:variable name="feed" select="$blogs/feed[rss=$rss]"/>
197
+ <div class="entry hentry">
198
+ <h2 class="blog-title">
199
+ <a href="{$feed/link}"><xsl:value-of select="$feed/title"/></a>
200
+ </h2>
201
+ <div class="entrydate published" title="{date}">
202
+ <xsl:value-of select="concat(date:day-in-month(date),'.',date:month-in-year(date),'. ',format-number(date:hour-in-day(date),'00'),':',format-number(date:minute-in-hour(date),'00'))"/>
203
+ </div>
204
+ <h3 class="entry-title"><a href="{link}" rel="bookmark"><xsl:value-of select="title"/></a></h3>
205
+ <div class="entrydesc entry-content">
206
+ <xsl:value-of select="hv:item-description($rss, string(link))" disable-output-escaping="yes"/>
207
+ </div>
208
+
209
+ <xsl:variable name="enclosures" select="hv:item-enclosures(string($rss), string(link))"/>
210
+ <xsl:if test="count($enclosures/enclosure) &gt; 0">
211
+ <ul>
212
+ <xsl:for-each select="$enclosures/enclosure">
213
+ <xsl:variable name="filename">
214
+ <xsl:call-template name="basename">
215
+ <xsl:with-param name="path" select="href"/>
216
+ </xsl:call-template>
217
+ </xsl:variable>
218
+ <li>
219
+ <xsl:choose>
220
+ <xsl:when test="string-length(string(title)) &gt; 0">
221
+ <xsl:value-of select="title"/>
222
+ (<a href="{href}" rel="enclosure"><xsl:value-of select="$filename"/></a>)
223
+ </xsl:when>
224
+ <xsl:otherwise>
225
+ <a href="{href}" rel="enclosure"><xsl:value-of select="$filename"/></a>
226
+ </xsl:otherwise>
227
+ </xsl:choose>
228
+
229
+ <xsl:text> </xsl:text>
230
+
231
+ <xsl:call-template name="format-enclosure-length">
232
+ <xsl:with-param name="length" select="number(length)"/>
233
+ </xsl:call-template>
234
+ </li>
235
+ </xsl:for-each>
236
+ </ul>
237
+ </xsl:if>
238
+
239
+ <div class="entryfoot"><a href="{link}" title="{link}">mehr&#8230;</a></div>
240
+ </div>
241
+ </xsl:for-each>
242
+ </div>
243
+
244
+ <p style="display:none"><a href="http://cthulhu.c3d2.de/~astro/badpit.html">E-Mail Address Index</a></p>
245
+ </body>
246
+ </html>
247
+ </xsl:template>
248
+
249
+ <xsl:template name="ticker-boxen">
250
+ <xsl:param name="collection"/>
251
+
252
+ <xsl:for-each select="collection[@name=$collection]/feed">
253
+ <xsl:sort select="translate(title, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
254
+ <div class="ticker hfeed">
255
+ <h2><a href="{link}"><xsl:value-of select="title"/></a></h2>
256
+ <ul class="tickerlinks">
257
+ <xsl:for-each select="hv:feed-items(string(rss), 8)/item">
258
+ <li class="hentry">
259
+ <xsl:choose>
260
+ <xsl:when test="string-length(title) &gt; 32">
261
+ <a href="{link}" title="{title}" rel="bookmark" class="entry-title"><xsl:value-of select="substring(title, 1, 30)"/>&#8230;</a>
262
+ </xsl:when>
263
+ <xsl:otherwise>
264
+ <a href="{link}" rel="bookmark" class="entry-title"><xsl:value-of select="title"/></a>
265
+ </xsl:otherwise>
266
+ </xsl:choose>
267
+ </li>
268
+ </xsl:for-each>
269
+ </ul>
270
+ </div>
271
+ </xsl:for-each>
272
+ </xsl:template>
273
+
274
+ <xsl:template name="format-enclosure-length">
275
+ <xsl:param name="length"/>
276
+
277
+ <xsl:if test="$length">
278
+ <xsl:choose>
279
+ <xsl:when test="$length &lt; 1024">
280
+ <xsl:value-of select="$length"/> Bytes
281
+ </xsl:when>
282
+ <xsl:when test="$length &lt; 1048576">
283
+ <xsl:value-of select="format-number($length div 1024, '0.0#')"/> KB
284
+ </xsl:when>
285
+ <xsl:when test="$length &lt; 1073741824">
286
+ <xsl:value-of select="format-number($length div 1048576, '0.0#')"/> MB
287
+ </xsl:when>
288
+ <xsl:otherwise>
289
+ <xsl:value-of select="format-number($length div 1073741824, '0.0#')"/> GB
290
+ </xsl:otherwise>
291
+ </xsl:choose>
292
+ </xsl:if>
293
+ </xsl:template>
294
+
295
+ <xsl:template name="basename">
296
+ <xsl:param name="path"/>
297
+
298
+ <xsl:choose>
299
+ <xsl:when test="contains($path, '/')">
300
+ <xsl:call-template name="basename">
301
+ <xsl:with-param name="path" select="substring-after($path, '/')"/>
302
+ </xsl:call-template>
303
+ </xsl:when>
304
+ <xsl:otherwise>
305
+ <xsl:value-of select="$path"/>
306
+ </xsl:otherwise>
307
+ </xsl:choose>
308
+ </xsl:template>
309
+
310
+ <xsl:template name="microblog-entry">
311
+ <xsl:param name="feed"/>
312
+ <xsl:param name="entry" select="."/>
313
+
314
+ <xsl:variable name="nick">
315
+ <xsl:choose>
316
+ <xsl:when test="contains($feed/title, ' timeline')">
317
+ <xsl:value-of select="substring-before(string($feed/title), ' timeline')"/>
318
+ </xsl:when>
319
+ <xsl:when test="contains($feed/title, 'Twitter / ')">
320
+ <xsl:value-of select="substring-after(string($feed/title), 'Twitter / ')"/>
321
+ </xsl:when>
322
+ <xsl:otherwise>
323
+ <xsl:value-of select="$feed/title"/>
324
+ </xsl:otherwise>
325
+ </xsl:choose>
326
+ </xsl:variable>
327
+ <xsl:variable name="text"
328
+ select="hv:item-description(string($entry/rss), string($entry/link))"/>
329
+ <li>
330
+ <xsl:if test="starts-with($entry/link,
331
+ 'http://identi.ca/notice/')">
332
+ <a href="http://identi.ca/{$nick}">
333
+ <img class="avatar" src="http://identi.ca/index.php?action=avatarbynickname&amp;nickname={$nick}&amp;size=24"
334
+ alt="avatar"/>
335
+ </a>
336
+ </xsl:if>
337
+ <xsl:if test="starts-with($entry/link,
338
+ 'http://twitter.com/')">
339
+ <a href="http://twitter.com/{$nick}">
340
+ <img class="avatar" src="http://spiurl.appspot.com/{$nick}"
341
+ alt="avatar"/>
342
+ </a>
343
+ </xsl:if>
344
+ <a class="nickname"
345
+ href="{$entry/link}"><xsl:value-of select="$nick"/></a>:
346
+ <xsl:choose>
347
+ <xsl:when test="starts-with($entry/link,
348
+ 'http://twitter.com/')">
349
+ <!-- Twitter does plaintext only -->
350
+ <xsl:call-template name="linkify">
351
+ <xsl:with-param name="s" select="substring-after($text, ': ')"/>
352
+ </xsl:call-template>
353
+ </xsl:when>
354
+ <xsl:otherwise>
355
+ <!-- identi.ca can haz linkz -->
356
+ <xsl:value-of select="$text"
357
+ disable-output-escaping="yes"/>
358
+ </xsl:otherwise>
359
+ </xsl:choose>
360
+ </li>
361
+ </xsl:template>
362
+
363
+ <xsl:template name="linkify">
364
+ <xsl:param name="s"/>
365
+
366
+ <xsl:choose>
367
+ <xsl:when test="contains($s, 'http://')">
368
+ <xsl:value-of select="substring-before($s, 'http://')"/>
369
+ <xsl:variable name="s2" select="concat('http://', substring-after($s, 'http://'))"/>
370
+ <xsl:choose>
371
+ <xsl:when test="contains($s2, ' ')">
372
+ <xsl:variable name="url" select="substring-before($s2, ' ')"/>
373
+ <a href="{$url}"><xsl:value-of select="$url"/></a>
374
+ <xsl:text> </xsl:text>
375
+ <xsl:call-template name="linkify">
376
+ <xsl:with-param name="s" select="substring-after($s2, ' ')"/>
377
+ </xsl:call-template>
378
+ </xsl:when>
379
+ <xsl:otherwise>
380
+ <a href="{$s2}"><xsl:value-of select="$s2"/></a>
381
+ </xsl:otherwise>
382
+ </xsl:choose>
383
+ </xsl:when>
384
+ <xsl:when test="contains($s, '#')">
385
+ <xsl:value-of select="substring-before($s, '#')"/>
386
+ <xsl:variable name="s2" select="concat('#', substring-after($s, '#'))"/>
387
+ <xsl:choose>
388
+ <xsl:when test="contains($s2, ' ')">
389
+ <xsl:variable name="hashtag" select="substring-before($s2, ' ')"/>
390
+ <a href="http://search.twitter.com/search?q={str:encode-uri($hashtag,
391
+ true())}">
392
+ <xsl:value-of select="$hashtag"/>
393
+ </a>
394
+ <xsl:text> </xsl:text>
395
+ <xsl:call-template name="linkify">
396
+ <xsl:with-param name="s" select="substring-after($s2, ' ')"/>
397
+ </xsl:call-template>
398
+ </xsl:when>
399
+ <xsl:otherwise>
400
+ <a href="http://search.twitter.com/search?q={str:encode-uri($s2, true())}">
401
+ <xsl:value-of select="$s2"/>
402
+ </a>
403
+ </xsl:otherwise>
404
+ </xsl:choose>
405
+ </xsl:when>
406
+ <xsl:otherwise>
407
+ <xsl:value-of select="$s"/>
408
+ </xsl:otherwise>
409
+ </xsl:choose>
410
+ </xsl:template>
411
+
412
+ </xsl:stylesheet>