Get htmltmpl mostly working
This commit is contained in:
parent
d17d509adc
commit
92eab64934
@ -64,17 +64,19 @@ def __init__():
|
||||
|
||||
# planet wide options
|
||||
define_planet('name', "Unconfigured Planet")
|
||||
define_planet('link', "Unconfigured Planet")
|
||||
define_planet('link', '')
|
||||
define_planet('cache_directory', "cache")
|
||||
define_planet('log_level', "WARNING")
|
||||
define_planet('feed_timeout', 20)
|
||||
define_planet('date_format', "%B %d, %Y %I:%M %p")
|
||||
define_planet('new_date_format', "%B %d, %Y")
|
||||
define_planet('generator', 'Venus')
|
||||
define_planet('generator_uri', 'http://intertwingly.net/code/venus/')
|
||||
define_planet('owner_name', 'Anonymous Coward')
|
||||
define_planet('owner_email', '')
|
||||
define_planet('output_theme', '')
|
||||
define_planet('output_dir', 'output')
|
||||
define_planet('feed', None)
|
||||
|
||||
define_planet_list('template_files')
|
||||
define_planet_list('bill_of_materials')
|
||||
@ -160,8 +162,25 @@ def cache_lists_directory():
|
||||
else:
|
||||
return os.path.join(cache_directory(), 'lists')
|
||||
|
||||
def feeds():
|
||||
""" list the feeds defined """
|
||||
def feed():
|
||||
if parser.has_option('Planet', 'feed'):
|
||||
parser.get('Planet', 'feed')
|
||||
elif link():
|
||||
for template_file in template_files:
|
||||
name = os.path.splitext(os.path.basename(template_file))[0]
|
||||
if name.find('atom')>=0 or name.find('rss')>=0:
|
||||
return urlparse.urljoin(link(), name)
|
||||
|
||||
def feedtype():
|
||||
if parser.has_option('Planet', 'feedtype'):
|
||||
parser.get('Planet', 'feedtype')
|
||||
elif feed() and feed().find('atom')>=0:
|
||||
return 'atom'
|
||||
elif feed() and feed().find('rss')>=0:
|
||||
return 'rss'
|
||||
|
||||
def subscriptions():
|
||||
""" list the feed subscriptions """
|
||||
return filter(lambda feed: feed!='Planet' and feed not in template_files(),
|
||||
parser.sections())
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
from xml.sax.saxutils import escape
|
||||
import sgmllib, time, os, sys
|
||||
import sgmllib, time, os, sys, new, urlparse
|
||||
from planet import config, feedparser, htmltmpl
|
||||
|
||||
class stripHtml(sgmllib.SGMLParser):
|
||||
@ -54,6 +54,9 @@ def Plain(value):
|
||||
def PlanetDate(value):
|
||||
return time.strftime(config.date_format(), value)
|
||||
|
||||
def NewDate(value):
|
||||
return time.strftime(config.new_date_format(), value)
|
||||
|
||||
def Rfc822(value):
|
||||
return time.strftime("%a, %d %b %Y %H:%M:%S +0000", value)
|
||||
|
||||
@ -64,7 +67,6 @@ def Rfc3399(value):
|
||||
Base = [
|
||||
['author', String, 'author'],
|
||||
['author_name', String, 'author_detail', 'name'],
|
||||
['feed', String, 'links', {'rel':'self'}, 'href'],
|
||||
['generator', String, 'generator'],
|
||||
['id', String, 'id'],
|
||||
['icon', String, 'icon'],
|
||||
@ -76,9 +78,9 @@ Base = [
|
||||
['subtitle', String, 'subtitle_detail', 'value'],
|
||||
['title', String, 'title_detail', 'value'],
|
||||
['title_plain', Plain, 'title_detail', 'value'],
|
||||
['url', String, 'links', {'rel':'self'}, 'href'],
|
||||
]
|
||||
|
||||
# ? new_date, new_channel
|
||||
Items = [
|
||||
['author', String, 'author'],
|
||||
['author_email', String, 'author_detail', 'email'],
|
||||
@ -95,6 +97,9 @@ Items = [
|
||||
['date_iso', Rfc3399, 'updated_parsed'],
|
||||
['id', String, 'id'],
|
||||
['link', String, 'links', {'rel': 'alternate'}, 'href'],
|
||||
['new_channel', String, 'id'],
|
||||
['new_date', NewDate, 'published_parsed'],
|
||||
['new_date', NewDate, 'updated_parsed'],
|
||||
['rights', String, 'rights_detail', 'value'],
|
||||
['title_language', String, 'title_detail', 'language'],
|
||||
['title_plain', Plain, 'title_detail', 'value'],
|
||||
@ -108,14 +113,6 @@ Items = [
|
||||
['published_iso', Rfc3399, 'published_parsed'],
|
||||
]
|
||||
|
||||
Channels = [
|
||||
['url', None],
|
||||
['link', None],
|
||||
['message', None],
|
||||
['title_plain', None],
|
||||
['name', None],
|
||||
]
|
||||
|
||||
# Add additional rules for source information
|
||||
for rule in Base:
|
||||
Items.append(['channel_'+rule[0], rule[1], 'source'] + rule[2:])
|
||||
@ -161,13 +158,67 @@ def tmpl_mapper(source, rules):
|
||||
|
||||
return output
|
||||
|
||||
def _end_planet_source(self):
|
||||
self._end_source()
|
||||
context = self._getContext()
|
||||
if not context.has_key('sources'): context['sources'] = []
|
||||
context.sources.append(context.source)
|
||||
del context['source']
|
||||
|
||||
def template_info(source):
|
||||
""" get template information from a feedparser output """
|
||||
|
||||
# wire in support for planet:source, call feedparser, unplug planet:source
|
||||
mixin=feedparser._FeedParserMixin
|
||||
mixin._start_planet_source = mixin._start_source
|
||||
mixin._end_planet_source = \
|
||||
new.instancemethod(_end_planet_source, None, mixin)
|
||||
data=feedparser.parse(source)
|
||||
del mixin._start_planet_source
|
||||
del mixin._end_planet_source
|
||||
|
||||
# apply rules to convert feed parser output to htmltmpl input
|
||||
output = {'Channels': [], 'Items': []}
|
||||
output['Channels'].append(tmpl_mapper(data.feed, Base))
|
||||
output.update(tmpl_mapper(data.feed, Base))
|
||||
sources = [(source.get('planet_name',None),source)
|
||||
for source in data.feed.get('sources',[])]
|
||||
sources.sort()
|
||||
for name, feed in sources:
|
||||
output['Channels'].append(tmpl_mapper(feed, Base))
|
||||
for entry in data.entries:
|
||||
output['Items'].append(tmpl_mapper(entry, Items))
|
||||
|
||||
# feed level information
|
||||
output['generator'] = config.generator_uri()
|
||||
output['name'] = config.name()
|
||||
output['link'] = config.link()
|
||||
output['owner_name'] = config.owner_name()
|
||||
output['owner_email'] = config.owner_email()
|
||||
if config.feed():
|
||||
output['feed'] = config.feed()
|
||||
output['feedtype'] = config.feed().find('rss')>=0 and 'rss' or 'atom'
|
||||
|
||||
# date/time information
|
||||
date = time.gmtime()
|
||||
output['date'] = PlanetDate(date)
|
||||
output['date_iso'] = Rfc3399(date)
|
||||
output['date_822'] = Rfc822(date)
|
||||
|
||||
# remove new_dates and new_channels that aren't "new"
|
||||
date = channel = None
|
||||
for item in output['Items']:
|
||||
if item.has_key('new_date'):
|
||||
if item['new_date'] == date:
|
||||
del item['new_date']
|
||||
else:
|
||||
date = item['new_date']
|
||||
|
||||
if item.has_key('new_channel'):
|
||||
if item['new_channel'] == channel:
|
||||
del item['new_channel']
|
||||
else:
|
||||
channel = item['new_channel']
|
||||
|
||||
return output
|
||||
|
||||
def run(script, doc, output_file=None):
|
||||
@ -177,6 +228,10 @@ def run(script, doc, output_file=None):
|
||||
tp = htmltmpl.TemplateProcessor(html_escape=0)
|
||||
for key,value in template_info(doc).items():
|
||||
tp.set(key, value)
|
||||
|
||||
reluri = os.path.splitext(os.path.basename(output_file))[0]
|
||||
tp.set('url', urlparse.urljoin(config.link(),reluri))
|
||||
|
||||
output = open(output_file, "w")
|
||||
output.write(tp.process(template))
|
||||
output.close()
|
||||
|
@ -147,5 +147,5 @@ def spiderPlanet(configFile):
|
||||
log = planet.getLogger(config.log_level())
|
||||
planet.setTimeout(config.feed_timeout())
|
||||
|
||||
for feed in config.feeds():
|
||||
for feed in config.subscriptions():
|
||||
spiderFeed(feed)
|
||||
|
@ -42,7 +42,7 @@ def splice(configFile):
|
||||
# insert subscription information
|
||||
feed.setAttribute('xmlns:planet',planet.xmlns)
|
||||
sources = config.cache_sources_directory()
|
||||
for sub in config.feeds():
|
||||
for sub in config.subscriptions():
|
||||
data=feedparser.parse(filename(sources,sub))
|
||||
if not data.feed: continue
|
||||
xdoc=minidom.parseString('''<planet:source xmlns:planet="%s"
|
||||
|
7
tests/data/filter/tmpl/feed_feed.ini
Normal file
7
tests/data/filter/tmpl/feed_feed.ini
Normal file
@ -0,0 +1,7 @@
|
||||
;
|
||||
; Description: id
|
||||
; Expect: feed == 'http://example.com/atom.xml' and feedtype == 'atom'
|
||||
;
|
||||
|
||||
[Planet]
|
||||
feed: http://example.com/atom.xml
|
7
tests/data/filter/tmpl/feed_generator.ini
Normal file
7
tests/data/filter/tmpl/feed_generator.ini
Normal file
@ -0,0 +1,7 @@
|
||||
;
|
||||
; Description: id
|
||||
; Expect: generator == 'http://example.com/planet'
|
||||
;
|
||||
|
||||
[Planet]
|
||||
generator_uri: http://example.com/planet
|
7
tests/data/filter/tmpl/feed_link.ini
Normal file
7
tests/data/filter/tmpl/feed_link.ini
Normal file
@ -0,0 +1,7 @@
|
||||
;
|
||||
; Description: id
|
||||
; Expect: link == 'http://example.com/planet'
|
||||
;
|
||||
|
||||
[Planet]
|
||||
link: http://example.com/planet
|
7
tests/data/filter/tmpl/feed_name.ini
Normal file
7
tests/data/filter/tmpl/feed_name.ini
Normal file
@ -0,0 +1,7 @@
|
||||
;
|
||||
; Description: id
|
||||
; Expect: name == 'My Planet'
|
||||
;
|
||||
|
||||
[Planet]
|
||||
name: My Planet
|
7
tests/data/filter/tmpl/feed_owner_email.ini
Normal file
7
tests/data/filter/tmpl/feed_owner_email.ini
Normal file
@ -0,0 +1,7 @@
|
||||
;
|
||||
; Description: id
|
||||
; Expect: owner_email == 'me@example.com'
|
||||
;
|
||||
|
||||
[Planet]
|
||||
owner_email: me@example.com
|
7
tests/data/filter/tmpl/feed_owner_name.ini
Normal file
7
tests/data/filter/tmpl/feed_owner_name.ini
Normal file
@ -0,0 +1,7 @@
|
||||
;
|
||||
; Description: id
|
||||
; Expect: owner_name == 'me'
|
||||
;
|
||||
|
||||
[Planet]
|
||||
owner_name: me
|
@ -1,14 +1,16 @@
|
||||
<!--
|
||||
Description: id
|
||||
Expect: Channels[0]['name'] == 'foo'
|
||||
Expect: Channels[0]['name'] == 'foo' and Items[0]['channel_name'] == 'foo'
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<planet:name>foo</planet:name>
|
||||
<entry>
|
||||
<source>
|
||||
<planet:name>foo</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<planet:name>foo</planet:name>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -4,9 +4,6 @@ Expect: Channels[0]['author'] == 'John Doe' and Channels[0]['author_name']
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<author>
|
||||
<name>John Doe</name>
|
||||
</author>
|
||||
<entry>
|
||||
<source>
|
||||
<author>
|
||||
@ -14,5 +11,10 @@ Expect: Channels[0]['author'] == 'John Doe' and Channels[0]['author_name']
|
||||
</author>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<author>
|
||||
<name>John Doe</name>
|
||||
</author>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['icon'] == 'http://www.example.com/favicon.ico' and It
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<icon>http://www.example.com/favicon.ico</icon>
|
||||
<entry>
|
||||
<source>
|
||||
<icon>http://www.example.com/favicon.ico</icon>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<icon>http://www.example.com/favicon.ico</icon>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['id'] == 'http://example.com/' and Items[0]['channel_i
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<id>http://example.com/</id>
|
||||
<entry>
|
||||
<source>
|
||||
<id>http://example.com/</id>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<id>http://example.com/</id>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['logo'] == 'http://www.example.com/logo.jpg' and Items
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<logo>http://www.example.com/logo.jpg</logo>
|
||||
<entry>
|
||||
<source>
|
||||
<logo>http://www.example.com/logo.jpg</logo>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<logo>http://www.example.com/logo.jpg</logo>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['name'] == 'foo' and Items[0]['channel_name'] == 'foo'
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<planet:name>foo</planet:name>
|
||||
<entry>
|
||||
<source>
|
||||
<planet:name>foo</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<planet:name>foo</planet:name>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['rights'] == '© 2006' and Items[0]['channel_right
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<rights type="html">&copy; 2006</rights>
|
||||
<entry>
|
||||
<source>
|
||||
<rights type="html">&copy; 2006</rights>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<rights type="html">&copy; 2006</rights>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['subtitle'] == 'snarky phrase' and Items[0]['channel_s
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<subtitle>snarky phrase</subtitle>
|
||||
<entry>
|
||||
<source>
|
||||
<subtitle>snarky phrase</subtitle>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<subtitle>snarky phrase</subtitle>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['title'] == 'visible name' and Channels[0]['title_plai
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>visible name</title>
|
||||
<entry>
|
||||
<source>
|
||||
<title>visible name</title>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<title>visible name</title>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['last_updated_iso'] == '2004-02-29T02:14:55+00:00' and
|
||||
-->
|
||||
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<updated>2004-02-28T18:14:55-08:00</updated>
|
||||
<entry>
|
||||
<source>
|
||||
<updated>2004-02-28T18:14:55-08:00</updated>
|
||||
</source>
|
||||
</entry>
|
||||
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||
<updated>2004-02-28T18:14:55-08:00</updated>
|
||||
</planet:source>
|
||||
</feed>
|
||||
|
||||
|
@ -14,7 +14,7 @@ class ConfigTest(unittest.TestCase):
|
||||
config.template_files())
|
||||
|
||||
def test_feeds(self):
|
||||
feeds = config.feeds()
|
||||
feeds = config.subscriptions()
|
||||
feeds.sort()
|
||||
self.assertEqual(['feed1', 'feed2'], feeds)
|
||||
|
||||
@ -24,7 +24,7 @@ class ConfigTest(unittest.TestCase):
|
||||
self.assertEqual('Test Configuration', config.name())
|
||||
|
||||
def test_link(self):
|
||||
self.assertEqual('Unconfigured Planet', config.link())
|
||||
self.assertEqual('', config.link())
|
||||
|
||||
# per template configuration
|
||||
|
||||
|
@ -1,20 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import unittest, os, sys, glob, new, re, StringIO, time
|
||||
from planet import config
|
||||
from planet.shell import tmpl
|
||||
|
||||
testfiles = 'tests/data/filter/tmpl/%s.xml'
|
||||
testfiles = 'tests/data/filter/tmpl/%s.%s'
|
||||
|
||||
class FilterTmplTest(unittest.TestCase):
|
||||
desc_re = re.compile("Description:\s*(.*?)\s*Expect:\s*(.*)\s*-->")
|
||||
desc_feed_re = re.compile("Description:\s*(.*?)\s*Expect:\s*(.*)\s*-->")
|
||||
desc_config_re = re.compile(";\s*Description:\s*(.*?)\s*;\s*Expect:\s*(.*)")
|
||||
simple_re = re.compile("^(\S+) == (u?'[^']*'|\([0-9, ]+\))$")
|
||||
|
||||
def eval(self, name):
|
||||
def eval_feed(self, name):
|
||||
# read the test case
|
||||
try:
|
||||
testcase = open(testfiles % name)
|
||||
testcase = open(testfiles % (name,'xml'))
|
||||
data = testcase.read()
|
||||
description, expect = self.desc_re.search(data).groups()
|
||||
description, expect = self.desc_feed_re.search(data).groups()
|
||||
testcase.close()
|
||||
except:
|
||||
raise RuntimeError, "can't parse %s" % name
|
||||
@ -29,9 +31,37 @@ class FilterTmplTest(unittest.TestCase):
|
||||
lhs, rhs = self.simple_re.match(expect).groups()
|
||||
self.assertEqual(eval(rhs), eval(lhs, results))
|
||||
|
||||
# build a test method for each test file
|
||||
for testcase in glob.glob(testfiles % '*'):
|
||||
def eval_config(self, name):
|
||||
# read the test case
|
||||
try:
|
||||
testcase = open(testfiles % (name,'ini'))
|
||||
data = testcase.read()
|
||||
description, expect = self.desc_config_re.search(data).groups()
|
||||
testcase.close()
|
||||
except:
|
||||
raise RuntimeError, "can't parse %s" % name
|
||||
|
||||
# map to template info
|
||||
config.load(testfiles % (name,'ini'))
|
||||
results = tmpl.template_info("<feed/>")
|
||||
|
||||
# verify the results
|
||||
if not self.simple_re.match(expect):
|
||||
self.assertTrue(eval(expect, results), expect)
|
||||
else:
|
||||
lhs, rhs = self.simple_re.match(expect).groups()
|
||||
self.assertEqual(eval(rhs), eval(lhs, results))
|
||||
|
||||
# build a test method for each xml test file
|
||||
for testcase in glob.glob(testfiles % ('*','xml')):
|
||||
root = os.path.splitext(os.path.basename(testcase))[0]
|
||||
func = lambda self, name=root: self.eval(name)
|
||||
func = lambda self, name=root: self.eval_feed(name)
|
||||
method = new.instancemethod(func, None, FilterTmplTest)
|
||||
setattr(FilterTmplTest, "test_" + root, method)
|
||||
|
||||
# build a test method for each ini test file
|
||||
for testcase in glob.glob(testfiles % ('*','ini')):
|
||||
root = os.path.splitext(os.path.basename(testcase))[0]
|
||||
func = lambda self, name=root: self.eval_config(name)
|
||||
method = new.instancemethod(func, None, FilterTmplTest)
|
||||
setattr(FilterTmplTest, "test_" + root, method)
|
||||
|
@ -19,7 +19,7 @@ class ReadingListTest(unittest.TestCase):
|
||||
# administrivia
|
||||
|
||||
def test_feeds(self):
|
||||
feeds = [split(feed)[1] for feed in config.feeds()]
|
||||
feeds = [split(feed)[1] for feed in config.subscriptions()]
|
||||
feeds.sort()
|
||||
self.assertEqual(['testfeed0.atom', 'testfeed1a.atom',
|
||||
'testfeed2.atom', 'testfeed3.rss'], feeds)
|
||||
@ -27,7 +27,7 @@ class ReadingListTest(unittest.TestCase):
|
||||
# dictionaries
|
||||
|
||||
def test_feed_options(self):
|
||||
feeds = dict([(split(feed)[1],feed) for feed in config.feeds()])
|
||||
feeds = dict([(split(feed)[1],feed) for feed in config.subscriptions()])
|
||||
feed1 = feeds['testfeed1a.atom']
|
||||
self.assertEqual('one', config.feed_options(feed1)['name'])
|
||||
|
||||
|
@ -20,7 +20,7 @@ class ConfigTest(unittest.TestCase):
|
||||
self.assertTrue('index.html.xslt' in config.template_files())
|
||||
|
||||
def test_feeds(self):
|
||||
feeds = config.feeds()
|
||||
feeds = config.subscriptions()
|
||||
feeds.sort()
|
||||
self.assertEqual(['feed1', 'feed2'], feeds)
|
||||
|
||||
@ -30,7 +30,7 @@ class ConfigTest(unittest.TestCase):
|
||||
self.assertEqual('Test Configuration', config.name())
|
||||
|
||||
def test_link(self):
|
||||
self.assertEqual('Unconfigured Planet', config.link())
|
||||
self.assertEqual('', config.link())
|
||||
|
||||
# per template configuration
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
# This template is based on the one originally developed by Stefano Mazzocci
|
||||
# This theme is based on the one originally developed by Stefano Mazzocci
|
||||
# for planetapache.org, and modified by Sam Ruby for planet.intertwingly.net
|
||||
|
||||
[Planet]
|
||||
template_files:
|
||||
atom.xml.xslt
|
||||
rss20.xml.tmpl
|
||||
foafroll.xml.xslt
|
||||
index.html.xslt
|
||||
opml.xml.xslt
|
||||
|
20
themes/classic_fancy/config.ini
Normal file
20
themes/classic_fancy/config.ini
Normal file
@ -0,0 +1,20 @@
|
||||
# This theme is based on the one contained in Planet V2.0. It demonstrates
|
||||
# that one can mix the use of htmltmpl and xslt templates.
|
||||
|
||||
[Planet]
|
||||
template_files:
|
||||
atom.xml.xslt
|
||||
foafroll.xml.xslt
|
||||
index.html.tmpl
|
||||
opml.xml.xslt
|
||||
rss10.xml.tmpl
|
||||
rss20.xml.tmpl
|
||||
|
||||
template_directories:
|
||||
../common
|
||||
|
||||
bill_of_materials:
|
||||
planet.css
|
||||
images/feed-icon-10x10.png
|
||||
images/logo.png
|
||||
images/planet.png
|
126
themes/classic_fancy/index.html.tmpl
Normal file
126
themes/classic_fancy/index.html.tmpl
Normal file
@ -0,0 +1,126 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
|
||||
### Fancy Planet HTML template.
|
||||
###
|
||||
### When combined with the stylesheet and images in the output/ directory
|
||||
### of the Planet source, this gives you a much prettier result than the
|
||||
### default examples template and demonstrates how to use the config file
|
||||
### to support things like faces
|
||||
###
|
||||
### For documentation on the more boring template elements, see
|
||||
### examples/config.ini and examples/index.html.tmpl in the Planet source.
|
||||
|
||||
<head>
|
||||
<title><TMPL_VAR name></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="generator" content="<TMPL_VAR generator ESCAPE="HTML">">
|
||||
<link rel="stylesheet" href="planet.css" type="text/css">
|
||||
<TMPL_IF feedtype>
|
||||
<link rel="alternate" href="<TMPL_VAR feed ESCAPE="HTML">" title="<TMPL_VAR channel_title_plain ESCAPE="HTML">" type="application/<TMPL_VAR feedtype>+xml">
|
||||
</TMPL_IF>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><TMPL_VAR name></h1>
|
||||
<TMPL_VAR admin>
|
||||
|
||||
<TMPL_LOOP Items>
|
||||
<TMPL_IF new_date>
|
||||
<TMPL_UNLESS __FIRST__>
|
||||
### End <div class="channelgroup">
|
||||
</div>
|
||||
### End <div class="daygroup">
|
||||
</div>
|
||||
</TMPL_UNLESS>
|
||||
<div class="daygroup">
|
||||
<h2><TMPL_VAR new_date></h2>
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF new_channel>
|
||||
<TMPL_UNLESS new_date>
|
||||
### End <div class="channelgroup">
|
||||
</div>
|
||||
</TMPL_UNLESS>
|
||||
<div class="channelgroup">
|
||||
|
||||
### Planet provides template variables for *all* configuration options for
|
||||
### the channel (and defaults), even if it doesn't know about them. We
|
||||
### exploit this here to add hackergotchi faces to our channels. Planet
|
||||
### doesn't know about the "face", "facewidth" and "faceheight" configuration
|
||||
### variables, but makes them available to us anyway.
|
||||
|
||||
<h3><a href="<TMPL_VAR channel_link ESCAPE="HTML">" title="<TMPL_VAR channel_title_plain ESCAPE="HTML">"><TMPL_VAR channel_name></a></h3>
|
||||
<TMPL_IF channel_face>
|
||||
<img class="face" src="images/<TMPL_VAR channel_face ESCAPE="HTML">" width="<TMPL_VAR channel_facewidth ESCAPE="HTML">" height="<TMPL_VAR channel_faceheight ESCAPE="HTML">" alt="">
|
||||
</TMPL_IF>
|
||||
</TMPL_IF>
|
||||
|
||||
|
||||
<div class="entrygroup" id="<TMPL_VAR id>"<TMPL_IF channel_language> lang="<TMPL_VAR channel_language>"</TMPL_IF>>
|
||||
<TMPL_IF title>
|
||||
<h4<TMPL_IF title_language> lang="<TMPL_VAR title_language>"</TMPL_IF>><a href="<TMPL_VAR link ESCAPE="HTML">"><TMPL_VAR title></a></h4>
|
||||
</TMPL_IF>
|
||||
<div class="entry">
|
||||
<div class="content"<TMPL_IF content_language> lang="<TMPL_VAR content_language>"</TMPL_IF>>
|
||||
<TMPL_VAR content>
|
||||
</div>
|
||||
|
||||
### Planet also makes available all of the information from the feed
|
||||
### that it can. Use the 'planet-cache' tool on the cache file for
|
||||
### a particular feed to find out what additional keys it supports.
|
||||
### Comment extra fields are 'author' and 'category' which we
|
||||
### demonstrate below.
|
||||
|
||||
<p class="date">
|
||||
<a href="<TMPL_VAR link ESCAPE="HTML">"><TMPL_IF author>by <TMPL_VAR author ESCAPE="HTML"> at </TMPL_IF><TMPL_VAR date><TMPL_IF category> under <TMPL_VAR category></TMPL_IF></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TMPL_IF __LAST__>
|
||||
### End <div class="channelgroup">
|
||||
</div>
|
||||
### End <div class="daygroup">
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
</TMPL_LOOP>
|
||||
|
||||
|
||||
<div class="sidebar">
|
||||
<img src="images/logo.png" width="136" height="136" alt="">
|
||||
|
||||
<h2>Subscriptions</h2>
|
||||
<ul>
|
||||
<TMPL_LOOP Channels>
|
||||
<li>
|
||||
<a href="<TMPL_VAR url ESCAPE="HTML">" title="subscribe"><img src="images/feed-icon-10x10.png" alt="(feed)"></a> <a <TMPL_IF link>href="<TMPL_VAR link ESCAPE="HTML">" </TMPL_IF><TMPL_IF message>class="message" title="<TMPL_VAR message ESCAPE="HTML">"</TMPL_IF><TMPL_UNLESS message>title="<TMPL_VAR title_plain ESCAPE="HTML">"</TMPL_UNLESS>><TMPL_VAR name></a>
|
||||
</li>
|
||||
</TMPL_LOOP>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<strong>Last updated:</strong><br>
|
||||
<TMPL_VAR date><br>
|
||||
<em>All times are UTC.</em><br>
|
||||
<br>
|
||||
Powered by:<br>
|
||||
<a href="http://www.planetplanet.org/"><img src="images/planet.png" width="80" height="15" alt="Planet" border="0"></a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<h2>Planetarium:</h2>
|
||||
<ul>
|
||||
<li><a href="http://www.planetapache.org/">Planet Apache</a></li>
|
||||
<li><a href="http://planet.debian.net/">Planet Debian</a></li>
|
||||
<li><a href="http://planet.freedesktop.org/">Planet freedesktop.org</a></li>
|
||||
<li><a href="http://planet.gnome.org/">Planet GNOME</a></li>
|
||||
<li><a href="http://planetsun.org/">Planet Sun</a></li>
|
||||
<li><a href="http://fedora.linux.duke.edu/fedorapeople/">Fedora People</a></li>
|
||||
<li><a href="http://www.planetplanet.org/">more...</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
150
themes/classic_fancy/planet.css
Normal file
150
themes/classic_fancy/planet.css
Normal file
@ -0,0 +1,150 @@
|
||||
body {
|
||||
border-right: 1px solid black;
|
||||
margin-right: 200px;
|
||||
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0px;
|
||||
padding-top: 20px;
|
||||
|
||||
font-family: "Bitstream Vera Sans", sans-serif;
|
||||
font-weight: normal;
|
||||
letter-spacing: -2px;
|
||||
text-transform: lowercase;
|
||||
text-align: right;
|
||||
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.admin {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-family: "Bitstream Vera Sans", sans-serif;
|
||||
font-weight: normal;
|
||||
color: #200080;
|
||||
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-family: "Bitstream Vera Sans", sans-serif;
|
||||
font-weight: normal;
|
||||
|
||||
background-color: #a0c0ff;
|
||||
border: 1px solid #5080b0;
|
||||
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
h3 a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-family: "Bitstream Vera Sans", sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h4 a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
img.face {
|
||||
float: right;
|
||||
margin-top: -3em;
|
||||
}
|
||||
|
||||
.entry {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.entry .date {
|
||||
font-family: "Bitstream Vera Sans", sans-serif;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.entry .date a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
width: 200px;
|
||||
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
padding-right: 0px;
|
||||
|
||||
padding-top: 20px;
|
||||
padding-left: 0px;
|
||||
|
||||
font-family: "Bitstream Vera Sans", sans-serif;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
|
||||
padding-left: 5px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.sidebar ul {
|
||||
padding-left: 1em;
|
||||
margin-left: 0px;
|
||||
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.sidebar ul li:hover {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.sidebar ul li a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sidebar ul li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.sidebar ul li a img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.sidebar p {
|
||||
border-top: 1px solid grey;
|
||||
margin-top: 30px;
|
||||
padding-top: 10px;
|
||||
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.sidebar .message {
|
||||
cursor: help;
|
||||
border-bottom: 1px dashed red;
|
||||
}
|
||||
|
||||
.sidebar a.message:hover {
|
||||
cursor: help;
|
||||
background-color: #ff0000;
|
||||
color: #ffffff !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline !important;
|
||||
color: blue !important;
|
||||
}
|
BIN
themes/common/images/logo.png
Normal file
BIN
themes/common/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
37
themes/common/rss10.xml.tmpl
Normal file
37
themes/common/rss10.xml.tmpl
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0"?>
|
||||
<rdf:RDF
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||
xmlns:content="http://purl.org/rss/1.0/modules/content/"
|
||||
xmlns="http://purl.org/rss/1.0/"
|
||||
>
|
||||
<channel rdf:about="<TMPL_VAR link ESCAPE="HTML">">
|
||||
<title><TMPL_VAR name ESCAPE="HTML"></title>
|
||||
<link><TMPL_VAR link ESCAPE="HTML"></link>
|
||||
<description><TMPL_VAR name ESCAPE="HTML"> - <TMPL_VAR link ESCAPE="HTML"></description>
|
||||
|
||||
<items>
|
||||
<rdf:Seq>
|
||||
<TMPL_LOOP Items>
|
||||
<rdf:li rdf:resource="<TMPL_VAR id ESCAPE="HTML">" />
|
||||
</TMPL_LOOP>
|
||||
</rdf:Seq>
|
||||
</items>
|
||||
</channel>
|
||||
|
||||
<TMPL_LOOP Items>
|
||||
<item rdf:about="<TMPL_VAR id ESCAPE="HTML">">
|
||||
<title><TMPL_VAR channel_name ESCAPE="HTML"><TMPL_IF title>: <TMPL_VAR title_plain ESCAPE="HTML"></TMPL_IF></title>
|
||||
<link><TMPL_VAR link ESCAPE="HTML"></link>
|
||||
<TMPL_IF content>
|
||||
<content:encoded><TMPL_VAR content ESCAPE="HTML"></content:encoded>
|
||||
</TMPL_IF>
|
||||
<dc:date><TMPL_VAR date_iso></dc:date>
|
||||
<TMPL_IF author_name>
|
||||
<dc:creator><TMPL_VAR author_name></dc:creator>
|
||||
</TMPL_IF>
|
||||
</item>
|
||||
</TMPL_LOOP>
|
||||
|
||||
</rdf:RDF>
|
Loading…
x
Reference in New Issue
Block a user