Get htmltmpl mostly working
This commit is contained in:
parent
d17d509adc
commit
92eab64934
@ -64,17 +64,19 @@ def __init__():
|
|||||||
|
|
||||||
# planet wide options
|
# planet wide options
|
||||||
define_planet('name', "Unconfigured Planet")
|
define_planet('name', "Unconfigured Planet")
|
||||||
define_planet('link', "Unconfigured Planet")
|
define_planet('link', '')
|
||||||
define_planet('cache_directory', "cache")
|
define_planet('cache_directory', "cache")
|
||||||
define_planet('log_level', "WARNING")
|
define_planet('log_level', "WARNING")
|
||||||
define_planet('feed_timeout', 20)
|
define_planet('feed_timeout', 20)
|
||||||
define_planet('date_format', "%B %d, %Y %I:%M %p")
|
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', 'Venus')
|
||||||
define_planet('generator_uri', 'http://intertwingly.net/code/venus/')
|
define_planet('generator_uri', 'http://intertwingly.net/code/venus/')
|
||||||
define_planet('owner_name', 'Anonymous Coward')
|
define_planet('owner_name', 'Anonymous Coward')
|
||||||
define_planet('owner_email', '')
|
define_planet('owner_email', '')
|
||||||
define_planet('output_theme', '')
|
define_planet('output_theme', '')
|
||||||
define_planet('output_dir', 'output')
|
define_planet('output_dir', 'output')
|
||||||
|
define_planet('feed', None)
|
||||||
|
|
||||||
define_planet_list('template_files')
|
define_planet_list('template_files')
|
||||||
define_planet_list('bill_of_materials')
|
define_planet_list('bill_of_materials')
|
||||||
@ -160,8 +162,25 @@ def cache_lists_directory():
|
|||||||
else:
|
else:
|
||||||
return os.path.join(cache_directory(), 'lists')
|
return os.path.join(cache_directory(), 'lists')
|
||||||
|
|
||||||
def feeds():
|
def feed():
|
||||||
""" list the feeds defined """
|
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(),
|
return filter(lambda feed: feed!='Planet' and feed not in template_files(),
|
||||||
parser.sections())
|
parser.sections())
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from xml.sax.saxutils import escape
|
from xml.sax.saxutils import escape
|
||||||
import sgmllib, time, os, sys
|
import sgmllib, time, os, sys, new, urlparse
|
||||||
from planet import config, feedparser, htmltmpl
|
from planet import config, feedparser, htmltmpl
|
||||||
|
|
||||||
class stripHtml(sgmllib.SGMLParser):
|
class stripHtml(sgmllib.SGMLParser):
|
||||||
@ -54,6 +54,9 @@ def Plain(value):
|
|||||||
def PlanetDate(value):
|
def PlanetDate(value):
|
||||||
return time.strftime(config.date_format(), value)
|
return time.strftime(config.date_format(), value)
|
||||||
|
|
||||||
|
def NewDate(value):
|
||||||
|
return time.strftime(config.new_date_format(), value)
|
||||||
|
|
||||||
def Rfc822(value):
|
def Rfc822(value):
|
||||||
return time.strftime("%a, %d %b %Y %H:%M:%S +0000", value)
|
return time.strftime("%a, %d %b %Y %H:%M:%S +0000", value)
|
||||||
|
|
||||||
@ -64,7 +67,6 @@ def Rfc3399(value):
|
|||||||
Base = [
|
Base = [
|
||||||
['author', String, 'author'],
|
['author', String, 'author'],
|
||||||
['author_name', String, 'author_detail', 'name'],
|
['author_name', String, 'author_detail', 'name'],
|
||||||
['feed', String, 'links', {'rel':'self'}, 'href'],
|
|
||||||
['generator', String, 'generator'],
|
['generator', String, 'generator'],
|
||||||
['id', String, 'id'],
|
['id', String, 'id'],
|
||||||
['icon', String, 'icon'],
|
['icon', String, 'icon'],
|
||||||
@ -76,9 +78,9 @@ Base = [
|
|||||||
['subtitle', String, 'subtitle_detail', 'value'],
|
['subtitle', String, 'subtitle_detail', 'value'],
|
||||||
['title', String, 'title_detail', 'value'],
|
['title', String, 'title_detail', 'value'],
|
||||||
['title_plain', Plain, 'title_detail', 'value'],
|
['title_plain', Plain, 'title_detail', 'value'],
|
||||||
|
['url', String, 'links', {'rel':'self'}, 'href'],
|
||||||
]
|
]
|
||||||
|
|
||||||
# ? new_date, new_channel
|
|
||||||
Items = [
|
Items = [
|
||||||
['author', String, 'author'],
|
['author', String, 'author'],
|
||||||
['author_email', String, 'author_detail', 'email'],
|
['author_email', String, 'author_detail', 'email'],
|
||||||
@ -95,6 +97,9 @@ Items = [
|
|||||||
['date_iso', Rfc3399, 'updated_parsed'],
|
['date_iso', Rfc3399, 'updated_parsed'],
|
||||||
['id', String, 'id'],
|
['id', String, 'id'],
|
||||||
['link', String, 'links', {'rel': 'alternate'}, 'href'],
|
['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'],
|
['rights', String, 'rights_detail', 'value'],
|
||||||
['title_language', String, 'title_detail', 'language'],
|
['title_language', String, 'title_detail', 'language'],
|
||||||
['title_plain', Plain, 'title_detail', 'value'],
|
['title_plain', Plain, 'title_detail', 'value'],
|
||||||
@ -108,14 +113,6 @@ Items = [
|
|||||||
['published_iso', Rfc3399, 'published_parsed'],
|
['published_iso', Rfc3399, 'published_parsed'],
|
||||||
]
|
]
|
||||||
|
|
||||||
Channels = [
|
|
||||||
['url', None],
|
|
||||||
['link', None],
|
|
||||||
['message', None],
|
|
||||||
['title_plain', None],
|
|
||||||
['name', None],
|
|
||||||
]
|
|
||||||
|
|
||||||
# Add additional rules for source information
|
# Add additional rules for source information
|
||||||
for rule in Base:
|
for rule in Base:
|
||||||
Items.append(['channel_'+rule[0], rule[1], 'source'] + rule[2:])
|
Items.append(['channel_'+rule[0], rule[1], 'source'] + rule[2:])
|
||||||
@ -161,13 +158,67 @@ def tmpl_mapper(source, rules):
|
|||||||
|
|
||||||
return output
|
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):
|
def template_info(source):
|
||||||
""" get template information from a feedparser output """
|
""" 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)
|
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': [], '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:
|
for entry in data.entries:
|
||||||
output['Items'].append(tmpl_mapper(entry, Items))
|
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
|
return output
|
||||||
|
|
||||||
def run(script, doc, output_file=None):
|
def run(script, doc, output_file=None):
|
||||||
@ -177,6 +228,10 @@ def run(script, doc, output_file=None):
|
|||||||
tp = htmltmpl.TemplateProcessor(html_escape=0)
|
tp = htmltmpl.TemplateProcessor(html_escape=0)
|
||||||
for key,value in template_info(doc).items():
|
for key,value in template_info(doc).items():
|
||||||
tp.set(key, value)
|
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 = open(output_file, "w")
|
||||||
output.write(tp.process(template))
|
output.write(tp.process(template))
|
||||||
output.close()
|
output.close()
|
||||||
|
@ -147,5 +147,5 @@ def spiderPlanet(configFile):
|
|||||||
log = planet.getLogger(config.log_level())
|
log = planet.getLogger(config.log_level())
|
||||||
planet.setTimeout(config.feed_timeout())
|
planet.setTimeout(config.feed_timeout())
|
||||||
|
|
||||||
for feed in config.feeds():
|
for feed in config.subscriptions():
|
||||||
spiderFeed(feed)
|
spiderFeed(feed)
|
||||||
|
@ -42,7 +42,7 @@ def splice(configFile):
|
|||||||
# insert subscription information
|
# insert subscription information
|
||||||
feed.setAttribute('xmlns:planet',planet.xmlns)
|
feed.setAttribute('xmlns:planet',planet.xmlns)
|
||||||
sources = config.cache_sources_directory()
|
sources = config.cache_sources_directory()
|
||||||
for sub in config.feeds():
|
for sub in config.subscriptions():
|
||||||
data=feedparser.parse(filename(sources,sub))
|
data=feedparser.parse(filename(sources,sub))
|
||||||
if not data.feed: continue
|
if not data.feed: continue
|
||||||
xdoc=minidom.parseString('''<planet:source xmlns:planet="%s"
|
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
|
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">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<planet:name>foo</planet:name>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<planet:name>foo</planet:name>
|
<planet:name>foo</planet:name>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<planet:name>foo</planet:name>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</feed>
|
||||||
|
|
||||||
|
@ -4,9 +4,6 @@ Expect: Channels[0]['author'] == 'John Doe' and Channels[0]['author_name']
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<author>
|
|
||||||
<name>John Doe</name>
|
|
||||||
</author>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<author>
|
<author>
|
||||||
@ -14,5 +11,10 @@ Expect: Channels[0]['author'] == 'John Doe' and Channels[0]['author_name']
|
|||||||
</author>
|
</author>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<author>
|
||||||
|
<name>John Doe</name>
|
||||||
|
</author>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</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">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<icon>http://www.example.com/favicon.ico</icon>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<icon>http://www.example.com/favicon.ico</icon>
|
<icon>http://www.example.com/favicon.ico</icon>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<icon>http://www.example.com/favicon.ico</icon>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</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">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<id>http://example.com/</id>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<id>http://example.com/</id>
|
<id>http://example.com/</id>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<id>http://example.com/</id>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</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">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<logo>http://www.example.com/logo.jpg</logo>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<logo>http://www.example.com/logo.jpg</logo>
|
<logo>http://www.example.com/logo.jpg</logo>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<logo>http://www.example.com/logo.jpg</logo>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</feed>
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['name'] == 'foo' and Items[0]['channel_name'] == 'foo'
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<planet:name>foo</planet:name>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<planet:name>foo</planet:name>
|
<planet:name>foo</planet:name>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<planet:name>foo</planet:name>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</feed>
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['rights'] == '© 2006' and Items[0]['channel_right
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<rights type="html">&copy; 2006</rights>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<rights type="html">&copy; 2006</rights>
|
<rights type="html">&copy; 2006</rights>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<rights type="html">&copy; 2006</rights>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</feed>
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['subtitle'] == 'snarky phrase' and Items[0]['channel_s
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<subtitle>snarky phrase</subtitle>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<subtitle>snarky phrase</subtitle>
|
<subtitle>snarky phrase</subtitle>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<subtitle>snarky phrase</subtitle>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</feed>
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@ Expect: Channels[0]['title'] == 'visible name' and Channels[0]['title_plai
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<title>visible name</title>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<title>visible name</title>
|
<title>visible name</title>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<title>visible name</title>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</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">
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
<updated>2004-02-28T18:14:55-08:00</updated>
|
|
||||||
<entry>
|
<entry>
|
||||||
<source>
|
<source>
|
||||||
<updated>2004-02-28T18:14:55-08:00</updated>
|
<updated>2004-02-28T18:14:55-08:00</updated>
|
||||||
</source>
|
</source>
|
||||||
</entry>
|
</entry>
|
||||||
|
<planet:source xmlns:planet='http://planet.intertwingly.net/'>
|
||||||
|
<updated>2004-02-28T18:14:55-08:00</updated>
|
||||||
|
</planet:source>
|
||||||
</feed>
|
</feed>
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class ConfigTest(unittest.TestCase):
|
|||||||
config.template_files())
|
config.template_files())
|
||||||
|
|
||||||
def test_feeds(self):
|
def test_feeds(self):
|
||||||
feeds = config.feeds()
|
feeds = config.subscriptions()
|
||||||
feeds.sort()
|
feeds.sort()
|
||||||
self.assertEqual(['feed1', 'feed2'], feeds)
|
self.assertEqual(['feed1', 'feed2'], feeds)
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ class ConfigTest(unittest.TestCase):
|
|||||||
self.assertEqual('Test Configuration', config.name())
|
self.assertEqual('Test Configuration', config.name())
|
||||||
|
|
||||||
def test_link(self):
|
def test_link(self):
|
||||||
self.assertEqual('Unconfigured Planet', config.link())
|
self.assertEqual('', config.link())
|
||||||
|
|
||||||
# per template configuration
|
# per template configuration
|
||||||
|
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import unittest, os, sys, glob, new, re, StringIO, time
|
import unittest, os, sys, glob, new, re, StringIO, time
|
||||||
|
from planet import config
|
||||||
from planet.shell import tmpl
|
from planet.shell import tmpl
|
||||||
|
|
||||||
testfiles = 'tests/data/filter/tmpl/%s.xml'
|
testfiles = 'tests/data/filter/tmpl/%s.%s'
|
||||||
|
|
||||||
class FilterTmplTest(unittest.TestCase):
|
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, ]+\))$")
|
simple_re = re.compile("^(\S+) == (u?'[^']*'|\([0-9, ]+\))$")
|
||||||
|
|
||||||
def eval(self, name):
|
def eval_feed(self, name):
|
||||||
# read the test case
|
# read the test case
|
||||||
try:
|
try:
|
||||||
testcase = open(testfiles % name)
|
testcase = open(testfiles % (name,'xml'))
|
||||||
data = testcase.read()
|
data = testcase.read()
|
||||||
description, expect = self.desc_re.search(data).groups()
|
description, expect = self.desc_feed_re.search(data).groups()
|
||||||
testcase.close()
|
testcase.close()
|
||||||
except:
|
except:
|
||||||
raise RuntimeError, "can't parse %s" % name
|
raise RuntimeError, "can't parse %s" % name
|
||||||
@ -29,9 +31,37 @@ class FilterTmplTest(unittest.TestCase):
|
|||||||
lhs, rhs = self.simple_re.match(expect).groups()
|
lhs, rhs = self.simple_re.match(expect).groups()
|
||||||
self.assertEqual(eval(rhs), eval(lhs, results))
|
self.assertEqual(eval(rhs), eval(lhs, results))
|
||||||
|
|
||||||
# build a test method for each test file
|
def eval_config(self, name):
|
||||||
for testcase in glob.glob(testfiles % '*'):
|
# 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]
|
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)
|
method = new.instancemethod(func, None, FilterTmplTest)
|
||||||
setattr(FilterTmplTest, "test_" + root, method)
|
setattr(FilterTmplTest, "test_" + root, method)
|
||||||
|
@ -19,7 +19,7 @@ class ReadingListTest(unittest.TestCase):
|
|||||||
# administrivia
|
# administrivia
|
||||||
|
|
||||||
def test_feeds(self):
|
def test_feeds(self):
|
||||||
feeds = [split(feed)[1] for feed in config.feeds()]
|
feeds = [split(feed)[1] for feed in config.subscriptions()]
|
||||||
feeds.sort()
|
feeds.sort()
|
||||||
self.assertEqual(['testfeed0.atom', 'testfeed1a.atom',
|
self.assertEqual(['testfeed0.atom', 'testfeed1a.atom',
|
||||||
'testfeed2.atom', 'testfeed3.rss'], feeds)
|
'testfeed2.atom', 'testfeed3.rss'], feeds)
|
||||||
@ -27,7 +27,7 @@ class ReadingListTest(unittest.TestCase):
|
|||||||
# dictionaries
|
# dictionaries
|
||||||
|
|
||||||
def test_feed_options(self):
|
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']
|
feed1 = feeds['testfeed1a.atom']
|
||||||
self.assertEqual('one', config.feed_options(feed1)['name'])
|
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())
|
self.assertTrue('index.html.xslt' in config.template_files())
|
||||||
|
|
||||||
def test_feeds(self):
|
def test_feeds(self):
|
||||||
feeds = config.feeds()
|
feeds = config.subscriptions()
|
||||||
feeds.sort()
|
feeds.sort()
|
||||||
self.assertEqual(['feed1', 'feed2'], feeds)
|
self.assertEqual(['feed1', 'feed2'], feeds)
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ class ConfigTest(unittest.TestCase):
|
|||||||
self.assertEqual('Test Configuration', config.name())
|
self.assertEqual('Test Configuration', config.name())
|
||||||
|
|
||||||
def test_link(self):
|
def test_link(self):
|
||||||
self.assertEqual('Unconfigured Planet', config.link())
|
self.assertEqual('', config.link())
|
||||||
|
|
||||||
# per template configuration
|
# 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
|
# for planetapache.org, and modified by Sam Ruby for planet.intertwingly.net
|
||||||
|
|
||||||
[Planet]
|
[Planet]
|
||||||
template_files:
|
template_files:
|
||||||
atom.xml.xslt
|
atom.xml.xslt
|
||||||
rss20.xml.tmpl
|
|
||||||
foafroll.xml.xslt
|
foafroll.xml.xslt
|
||||||
index.html.xslt
|
index.html.xslt
|
||||||
opml.xml.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