Theme support
This commit is contained in:
parent
9fa9fb6117
commit
7cbc2e31bf
@ -2,6 +2,9 @@ xmlns = 'http://planet.intertwingly.net/'
|
||||
|
||||
logger = None
|
||||
|
||||
import config
|
||||
config.__init__()
|
||||
|
||||
def getLogger(level):
|
||||
""" get a logger with the specified log level """
|
||||
global logger
|
||||
|
@ -11,7 +11,7 @@ Usage:
|
||||
config.load('config.ini')
|
||||
|
||||
# administrative / structural information
|
||||
print config.templates()
|
||||
print config.template_files()
|
||||
print config.feeds()
|
||||
|
||||
# planet wide configuration
|
||||
@ -37,6 +37,7 @@ def __init__():
|
||||
"""define the struture of an ini file"""
|
||||
import config
|
||||
|
||||
# underlying implementation
|
||||
def get(section, option, default):
|
||||
if section and parser.has_option(section, option):
|
||||
return parser.get(section, option)
|
||||
@ -49,6 +50,10 @@ def __init__():
|
||||
setattr(config, name, lambda default=default: get(None,name,default))
|
||||
planet_predefined_options.append(name)
|
||||
|
||||
def define_planet_list(name):
|
||||
setattr(config, name, lambda : get(None,name,'').split())
|
||||
planet_predefined_options.append(name)
|
||||
|
||||
def define_tmpl(name, default):
|
||||
setattr(config, name, lambda section, default=default:
|
||||
get(section,name,default))
|
||||
@ -63,25 +68,57 @@ def __init__():
|
||||
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('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_list('template_files')
|
||||
define_planet_list('bill_of_materials')
|
||||
define_planet_list('template_directories')
|
||||
|
||||
# template options
|
||||
define_tmpl_int('days_per_page', 0)
|
||||
define_tmpl_int('items_per_page', 60)
|
||||
define_tmpl('encoding', 'utf-8')
|
||||
|
||||
# prevent re-initialization
|
||||
setattr(config, '__init__', lambda: None)
|
||||
|
||||
def load(file):
|
||||
def load(config_file):
|
||||
""" initialize and load a configuration"""
|
||||
__init__()
|
||||
global parser
|
||||
parser = ConfigParser()
|
||||
parser.read(file)
|
||||
parser.read(config_file)
|
||||
|
||||
def template_files():
|
||||
""" list the templates defined """
|
||||
return parser.get('Planet','template_files').split(' ')
|
||||
if parser.has_option('Planet', 'output_theme'):
|
||||
theme = parser.get('Planet', 'output_theme')
|
||||
for path in ("", os.path.join(sys.path[0],'themes')):
|
||||
theme_dir = os.path.join(path,theme)
|
||||
theme_file = os.path.join(theme_dir,'config.ini')
|
||||
if os.path.exists(theme_file):
|
||||
# initial search list for theme directories
|
||||
dirs = [theme_dir]
|
||||
if parser.has_option('Planet', 'template_directories'):
|
||||
dirs.insert(0,parser.get('Planet', 'template_directories'))
|
||||
|
||||
# read in the theme
|
||||
parser = ConfigParser()
|
||||
parser.read(theme_file)
|
||||
|
||||
# complete search list for theme directories
|
||||
if parser.has_option('Planet', 'template_directories'):
|
||||
dirs += [os.path.join(theme_dir,dir) for dir in
|
||||
parser.get('Planet', 'template_directories').split()]
|
||||
|
||||
# merge configurations, allowing current one to override theme
|
||||
parser.read(config_file)
|
||||
parser.set('Planet', 'template_directories', ' '.join(dirs))
|
||||
break
|
||||
else:
|
||||
import config, planet
|
||||
log = planet.getLogger(config.log_level())
|
||||
log.error('Unable to find theme %s', theme)
|
||||
|
||||
def cache_sources_directory():
|
||||
if parser.has_option('Planet', 'cache_sources_directory'):
|
||||
|
@ -18,7 +18,7 @@ from xml.sax.saxutils import escape
|
||||
from xml.dom import minidom
|
||||
from BeautifulSoup import BeautifulSoup
|
||||
from xml.parsers.expat import ExpatError
|
||||
import planet
|
||||
import planet, config
|
||||
|
||||
illegal_xml_chars = re.compile("[\x01-\x08\x0B\x0C\x0E-\x1F]")
|
||||
|
||||
@ -29,6 +29,7 @@ def createTextElement(parent, name, value):
|
||||
xelement = xdoc.createElement(name)
|
||||
xelement.appendChild(xdoc.createTextNode(value))
|
||||
parent.appendChild(xelement)
|
||||
return xelement
|
||||
|
||||
def invalidate(c):
|
||||
""" replace invalid characters """
|
||||
@ -98,7 +99,9 @@ def date(xentry, name, parsed):
|
||||
""" insert a date-formated element into the entry """
|
||||
if not parsed: return
|
||||
formatted = time.strftime("%Y-%m-%dT%H:%M:%SZ", parsed)
|
||||
createTextElement(xentry, name, formatted)
|
||||
xdate = createTextElement(xentry, name, formatted)
|
||||
formatted = time.strftime(config.date_format(), parsed)
|
||||
xdate.setAttribute('planet:format', formatted)
|
||||
|
||||
def author(xentry, name, detail):
|
||||
""" insert an author-like element into the entry """
|
||||
|
@ -1,8 +1,8 @@
|
||||
""" Splice together a planet from a cache of feed entries """
|
||||
import glob, os
|
||||
import glob, os, time, shutil
|
||||
from xml.dom import minidom
|
||||
import planet, config, feedparser, reconstitute
|
||||
from reconstitute import createTextElement
|
||||
from reconstitute import createTextElement, date
|
||||
from spider import filename
|
||||
|
||||
def splice(configFile):
|
||||
@ -11,6 +11,7 @@ def splice(configFile):
|
||||
config.load(configFile)
|
||||
log = planet.getLogger(config.log_level())
|
||||
|
||||
log.info("Loading cached data")
|
||||
cache = config.cache_directory()
|
||||
dir=[(os.stat(file).st_mtime,file) for file in glob.glob(cache+"/*")
|
||||
if not os.path.isdir(file)]
|
||||
@ -18,17 +19,20 @@ def splice(configFile):
|
||||
dir.reverse()
|
||||
|
||||
items=max([config.items_per_page(templ)
|
||||
for templ in config.template_files()])
|
||||
for templ in config.template_files() or ['Planet']])
|
||||
|
||||
doc = minidom.parseString('<feed xmlns="http://www.w3.org/2005/Atom"/>')
|
||||
feed = doc.documentElement
|
||||
|
||||
# insert Google/LiveJournal's noindex
|
||||
feed.setAttribute('indexing:index','no')
|
||||
feed.setAttribute('xmlns:indexing','urn:atom-extension:indexing')
|
||||
|
||||
# insert feed information
|
||||
createTextElement(feed, 'title', config.name())
|
||||
date(feed, 'updated', time.gmtime())
|
||||
gen = createTextElement(feed, 'generator', config.generator())
|
||||
gen.setAttribute('uri', config.generator_uri())
|
||||
author = doc.createElement('author')
|
||||
createTextElement(author, 'name', config.owner_name())
|
||||
createTextElement(author, 'email', config.owner_email())
|
||||
feed.appendChild(author)
|
||||
|
||||
# insert entry information
|
||||
for mtime,file in dir[:items]:
|
||||
@ -47,3 +51,75 @@ def splice(configFile):
|
||||
feed.appendChild(xdoc.documentElement)
|
||||
|
||||
return doc
|
||||
|
||||
def apply(doc):
|
||||
output_dir = config.output_dir()
|
||||
if not os.path.exists(output_dir): os.makedirs(output_dir)
|
||||
log = planet.getLogger(config.log_level())
|
||||
|
||||
try:
|
||||
# if available, use the python interface to libxslt
|
||||
import libxml2
|
||||
import libxslt
|
||||
dom = libxml2.parseDoc(doc)
|
||||
docfile = None
|
||||
except:
|
||||
# otherwise, use the command line interface
|
||||
dom = None
|
||||
import warnings
|
||||
warnings.simplefilter('ignore', RuntimeWarning)
|
||||
docfile = os.tmpnam()
|
||||
file = open(docfile,'w')
|
||||
file.write(doc)
|
||||
file.close()
|
||||
|
||||
# Go-go-gadget-template
|
||||
for template_file in config.template_files():
|
||||
for template_dir in config.template_directories():
|
||||
template_resolved = os.path.join(template_dir, template_file)
|
||||
if os.path.exists(template_resolved): break
|
||||
else:
|
||||
log.error("Unable to locate template %s", template_file)
|
||||
continue
|
||||
|
||||
base,ext = os.path.splitext(os.path.basename(template_resolved))
|
||||
if ext != '.xslt':
|
||||
log.warning("Skipping template %s", template_resolved)
|
||||
continue
|
||||
|
||||
log.info("Processing template %s", template_resolved)
|
||||
output_file = os.path.join(output_dir, base)
|
||||
if dom:
|
||||
styledoc = libxml2.parseFile(template_resolved)
|
||||
style = libxslt.parseStylesheetDoc(styledoc)
|
||||
result = style.applyStylesheet(dom, None)
|
||||
log.info("Writing %s", output_file)
|
||||
style.saveResultToFilename(output_file, result, 0)
|
||||
style.freeStylesheet()
|
||||
result.freeDoc()
|
||||
else:
|
||||
log.info("Writing %s", output_file)
|
||||
os.system('xsltproc %s %s > %s' %
|
||||
(template_resolved, docfile, output_file))
|
||||
|
||||
if dom: dom.freeDoc()
|
||||
if docfile: os.unlink(docfile)
|
||||
|
||||
# Process bill of materials
|
||||
for copy_file in config.bill_of_materials():
|
||||
dest = os.path.join(output_dir, copy_file)
|
||||
for template_dir in config.template_directories():
|
||||
source = os.path.join(template_dir, copy_file)
|
||||
if os.path.exists(source): break
|
||||
else:
|
||||
log.error('Unable to locate %s', copy_file)
|
||||
continue
|
||||
|
||||
mtime = os.stat(source).st_mtime
|
||||
if not os.path.exists(dest) or os.stat(dest).st_mtime < mtime:
|
||||
dest_dir = os.path.split(dest)[0]
|
||||
if not os.path.exists(dest_dir): os.makedirs(dest_dir)
|
||||
|
||||
log.info("Copying %s to %s", source, dest)
|
||||
shutil.copyfile(source, dest)
|
||||
shutil.copystat(source, dest)
|
||||
|
@ -1,8 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
import glob, trace, unittest
|
||||
import glob, trace, unittest, os, sys
|
||||
|
||||
# start in a consistent, predictable location
|
||||
os.chdir(sys.path[0])
|
||||
|
||||
# find all of the planet test modules
|
||||
modules = map(trace.fullmodname, glob.glob('tests/test_*.py'))
|
||||
modules = map(trace.fullmodname, glob.glob(os.path.join('tests', 'test_*.py')))
|
||||
|
||||
# load all of the tests into a suite
|
||||
suite = unittest.TestLoader().loadTestsFromNames(modules)
|
||||
|
@ -13,10 +13,7 @@ if __name__ == '__main__':
|
||||
# at the moment, we don't have template support, so we cheat and
|
||||
# simply insert a XSLT processing instruction
|
||||
doc = splice.splice(sys.argv[1])
|
||||
pi = doc.createProcessingInstruction(
|
||||
'xml-stylesheet','type="text/xsl" href="planet.xslt"')
|
||||
doc.insertBefore(pi, doc.firstChild)
|
||||
print doc.toxml('utf-8')
|
||||
splice.apply(doc.toxml('utf-8'))
|
||||
else:
|
||||
print "Usage:"
|
||||
print " python %s config.ini" % sys.argv[0]
|
||||
|
42
tests/capture.py
Executable file
42
tests/capture.py
Executable file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
While unit tests are intended to be independently executable, it often
|
||||
is helpful to ensure that some downstream tasks can be run with the
|
||||
exact output produced by upstream tasks.
|
||||
|
||||
This script captures such output. It should be run whenever there is
|
||||
a major change in the contract between stages
|
||||
"""
|
||||
|
||||
import shutil, os, sys
|
||||
|
||||
# move up a directory
|
||||
sys.path.insert(1, os.path.split(sys.path[0])[0])
|
||||
os.chdir(sys.path[1])
|
||||
|
||||
# copy spider output to splice input
|
||||
from planet import spider
|
||||
spider.spiderPlanet('tests/data/spider/config.ini')
|
||||
if os.path.exists('tests/data/splice/cache'):
|
||||
shutil.rmtree('tests/data/splice/cache')
|
||||
shutil.move('tests/work/spider/cache', 'tests/data/splice/cache')
|
||||
|
||||
source=open('tests/data/spider/config.ini')
|
||||
dest1=open('tests/data/splice/config.ini', 'w')
|
||||
dest1.write(source.read().replace('/work/spider/', '/data/splice/'))
|
||||
dest1.close()
|
||||
|
||||
source.seek(0)
|
||||
dest2=open('tests/data/apply/config.ini', 'w')
|
||||
dest2.write(source.read().replace('[Planet]', '''[Planet]
|
||||
output_theme = asf
|
||||
output_dir = tests/work/apply'''))
|
||||
dest2.close()
|
||||
source.close()
|
||||
|
||||
# copy splice output to apply input
|
||||
from planet import splice
|
||||
file=open('tests/data/apply/feed.xml', 'w')
|
||||
file.write(splice.splice('tests/data/splice/config.ini').toxml('utf-8'))
|
||||
file.close()
|
17
tests/data/apply/config.ini
Normal file
17
tests/data/apply/config.ini
Normal file
@ -0,0 +1,17 @@
|
||||
[Planet]
|
||||
output_theme = asf
|
||||
output_dir = tests/work/apply
|
||||
name = test planet
|
||||
cache_directory = tests/work/spider/cache
|
||||
|
||||
[tests/data/spider/testfeed0.atom]
|
||||
name = not found
|
||||
|
||||
[tests/data/spider/testfeed1b.atom]
|
||||
name = one
|
||||
|
||||
[tests/data/spider/testfeed2.atom]
|
||||
name = two
|
||||
|
||||
[tests/data/spider/testfeed3.rss]
|
||||
name = three
|
215
tests/data/apply/feed.xml
Normal file
215
tests/data/apply/feed.xml
Normal file
@ -0,0 +1,215 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/"><title>test planet</title><updated planet:format="August 21, 2006 12:54 PM">2006-08-21T12:54:31Z</updated><generator uri="http://intertwingly.net/code/venus/">Venus</generator><author><name>Anonymous Coward</name></author><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed3/2</id>
|
||||
<link href="http://example.com/2" rel="alternate" type="text/html"/>
|
||||
<title>Venus</title>
|
||||
<summary>the Morning Star</summary>
|
||||
<updated planet:format="August 21, 2006 12:54 PM">2006-08-21T12:54:31Z</updated>
|
||||
<source>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed3.rss" rel="alternate" type="text/html"/>
|
||||
<link href="tests/data/spider/testfeed3.rss" rel="self" type="application/atom+xml"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<planet:name>three</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>http://example.com/4</id>
|
||||
<link href="http://example.com/4" rel="alternate" type="text/html"/>
|
||||
<title>Mars</title>
|
||||
<summary>the Red Planet</summary>
|
||||
<updated planet:format="August 21, 2006 12:54 PM">2006-08-21T12:54:31Z</updated>
|
||||
<source>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed3.rss" rel="alternate" type="text/html"/>
|
||||
<link href="tests/data/spider/testfeed3.rss" rel="self" type="application/atom+xml"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<planet:name>three</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1/2</id>
|
||||
<link href="http://example.com/2" rel="alternate" type="text/html"/>
|
||||
<title>Venus</title>
|
||||
<content>the Jewel of the Sky</content>
|
||||
<updated planet:format="February 02, 2006 12:00 AM">2006-02-02T00:00:00Z</updated>
|
||||
<published planet:format="January 02, 2006 12:00 AM">2006-01-02T00:00:00Z</published>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1</id>
|
||||
<author>
|
||||
<name>Sam Ruby</name>
|
||||
<email>rubys@intertwingly.net</email>
|
||||
<uri>http://www.intertwingly.net/blog/</uri>
|
||||
</author>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed1a.atom" rel="self" type="application/atom+xml"/>
|
||||
<link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>one</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2/4</id>
|
||||
<link href="http://example.com/4" rel="alternate" type="text/html"/>
|
||||
<title>Mars</title>
|
||||
<content>the Red Planet</content>
|
||||
<updated planet:format="January 04, 2006 12:00 AM">2006-01-04T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2</id>
|
||||
<author>
|
||||
<name>Sam Ruby</name>
|
||||
<email>rubys@intertwingly.net</email>
|
||||
<uri>http://www.intertwingly.net/blog/</uri>
|
||||
</author>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed2.atom" rel="self" type="application/atom+xml"/>
|
||||
<link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>two</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1/4</id>
|
||||
<link href="http://example.com/4" rel="alternate" type="text/html"/>
|
||||
<title>Mars</title>
|
||||
<content>the Red Planet</content>
|
||||
<updated planet:format="January 04, 2006 12:00 AM">2006-01-04T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1</id>
|
||||
<author>
|
||||
<name>Sam Ruby</name>
|
||||
<email>rubys@intertwingly.net</email>
|
||||
<uri>http://www.intertwingly.net/blog/</uri>
|
||||
</author>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed1a.atom" rel="self" type="application/atom+xml"/>
|
||||
<link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>one</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2/3</id>
|
||||
<link href="http://example.com/3" rel="alternate" type="text/html"/>
|
||||
<title>Earth</title>
|
||||
<content>the Blue Planet</content>
|
||||
<updated planet:format="January 03, 2006 12:00 AM">2006-01-03T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2</id>
|
||||
<author>
|
||||
<name>Sam Ruby</name>
|
||||
<email>rubys@intertwingly.net</email>
|
||||
<uri>http://www.intertwingly.net/blog/</uri>
|
||||
</author>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed2.atom" rel="self" type="application/atom+xml"/>
|
||||
<link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>two</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1/3</id>
|
||||
<link href="http://example.com/3" rel="alternate" type="text/html"/>
|
||||
<title>Earth</title>
|
||||
<content>the Blue Planet</content>
|
||||
<updated planet:format="January 03, 2006 12:00 AM">2006-01-03T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1</id>
|
||||
<author>
|
||||
<name>Sam Ruby</name>
|
||||
<email>rubys@intertwingly.net</email>
|
||||
<uri>http://www.intertwingly.net/blog/</uri>
|
||||
</author>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed1a.atom" rel="self" type="application/atom+xml"/>
|
||||
<link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>one</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>http://example.com/3</id>
|
||||
<link href="http://example.com/3" rel="alternate" type="text/html"/>
|
||||
<title>Earth</title>
|
||||
<summary>the Blue Planet</summary>
|
||||
<updated planet:format="January 03, 2006 12:00 AM">2006-01-03T00:00:00Z</updated>
|
||||
<source>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed3.rss" rel="alternate" type="text/html"/>
|
||||
<link href="tests/data/spider/testfeed3.rss" rel="self" type="application/atom+xml"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<planet:name>three</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2/2</id>
|
||||
<link href="http://example.com/2" rel="alternate" type="text/html"/>
|
||||
<title>Venus</title>
|
||||
<content>the Morning Star</content>
|
||||
<updated planet:format="January 02, 2006 12:00 AM">2006-01-02T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2</id>
|
||||
<author>
|
||||
<name>Sam Ruby</name>
|
||||
<email>rubys@intertwingly.net</email>
|
||||
<uri>http://www.intertwingly.net/blog/</uri>
|
||||
</author>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed2.atom" rel="self" type="application/atom+xml"/>
|
||||
<link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>two</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed3/1</id>
|
||||
<link href="http://example.com/1" rel="alternate" type="text/html"/>
|
||||
<title>Mercury</title>
|
||||
<summary>Messenger of the Roman Gods</summary>
|
||||
<updated planet:format="January 01, 2006 12:00 AM">2006-01-01T00:00:00Z</updated>
|
||||
<source>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed3.rss" rel="alternate" type="text/html"/>
|
||||
<link href="tests/data/spider/testfeed3.rss" rel="self" type="application/atom+xml"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<planet:name>three</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2/1</id>
|
||||
<link href="http://example.com/1" rel="alternate" type="text/html"/>
|
||||
<title>Mercury</title>
|
||||
<content>Messenger of the Roman Gods</content>
|
||||
<updated planet:format="January 01, 2006 12:00 AM">2006-01-01T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2</id>
|
||||
<author>
|
||||
<name>Sam Ruby</name>
|
||||
<email>rubys@intertwingly.net</email>
|
||||
<uri>http://www.intertwingly.net/blog/</uri>
|
||||
</author>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed2.atom" rel="self" type="application/atom+xml"/>
|
||||
<link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>two</planet:name>
|
||||
</source>
|
||||
</entry><entry xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/">
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1/1</id>
|
||||
<link href="http://example.com/1" rel="alternate" type="text/html"/>
|
||||
<title>Mercury</title>
|
||||
<content>Messenger of the Roman Gods</content>
|
||||
<updated planet:format="January 01, 2006 12:00 AM">2006-01-01T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1</id>
|
||||
<author>
|
||||
<name>Sam Ruby</name>
|
||||
<email>rubys@intertwingly.net</email>
|
||||
<uri>http://www.intertwingly.net/blog/</uri>
|
||||
</author>
|
||||
<link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed1a.atom" rel="self" type="application/atom+xml"/>
|
||||
<link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>one</planet:name>
|
||||
</source>
|
||||
</entry><planet:source xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/"><id>tag:planet.intertwingly.net,2006:testfeed2</id><author><name>Sam Ruby</name><email>rubys@intertwingly.net</email><uri>http://www.intertwingly.net/blog/</uri></author><link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed2.atom" rel="self" type="application/atom+xml"/><link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/><subtitle>It’s just data</subtitle><title>Sam Ruby</title><updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated><planet:name>two</planet:name></planet:source><planet:source xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/"><link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed3.rss" rel="alternate" type="text/html"/><link href="tests/data/spider/testfeed3.rss" rel="self" type="application/atom+xml"/><subtitle>It’s just data</subtitle><title>Sam Ruby</title><planet:name>three</planet:name></planet:source><planet:source xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/"><id>tag:planet.intertwingly.net,2006:testfeed1</id><author><name>Sam Ruby</name><email>rubys@intertwingly.net</email><uri>http://www.intertwingly.net/blog/</uri></author><link href="http://intertwingly.net/code/venus/tests/data/spider/testfeed1a.atom" rel="self" type="application/atom+xml"/><link href="http://www.intertwingly.net/blog/" rel="alternate" type="text/html"/><subtitle>It’s just data</subtitle><title>Sam Ruby</title><updated planet:format="June 17, 2006 12:15 AM">2006-06-17T00:15:18Z</updated><planet:name>one</planet:name></planet:source></feed>
|
14
tests/data/config/themed.ini
Normal file
14
tests/data/config/themed.ini
Normal file
@ -0,0 +1,14 @@
|
||||
[Planet]
|
||||
name = Test Configuration
|
||||
output_theme = asf
|
||||
items_per_page = 50
|
||||
template_directories = /foo /bar
|
||||
|
||||
[index.html.xslt]
|
||||
days_per_page = 7
|
||||
|
||||
[feed1]
|
||||
name = one
|
||||
|
||||
[feed2]
|
||||
name = two
|
@ -1,6 +1,6 @@
|
||||
[Planet]
|
||||
name = test planet
|
||||
cache_directory = tests/work/spider/cache
|
||||
template_files =
|
||||
|
||||
[tests/data/spider/testfeed0.atom]
|
||||
name = not found
|
||||
|
2
tests/data/splice/cache/example.com,3
vendored
2
tests/data/splice/cache/example.com,3
vendored
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/3' type='text/html' rel='alternate'/>
|
||||
<title>Earth</title>
|
||||
<summary>the Blue Planet</summary>
|
||||
<updated>2006-01-03T00:00:00Z</updated>
|
||||
<updated planet:format='January 03, 2006 12:00 AM'>2006-01-03T00:00:00Z</updated>
|
||||
<source>
|
||||
<link href='http://intertwingly.net/code/venus/tests/data/spider/testfeed3.rss' type='text/html' rel='alternate'/>
|
||||
<link href='tests/data/spider/testfeed3.rss' type='application/atom+xml' rel='self'/>
|
||||
|
2
tests/data/splice/cache/example.com,4
vendored
2
tests/data/splice/cache/example.com,4
vendored
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/4' type='text/html' rel='alternate'/>
|
||||
<title>Mars</title>
|
||||
<summary>the Red Planet</summary>
|
||||
<updated>2006-08-18T18:30:50Z</updated>
|
||||
<updated planet:format='August 21, 2006 12:54 PM'>2006-08-21T12:54:31Z</updated>
|
||||
<source>
|
||||
<link href='http://intertwingly.net/code/venus/tests/data/spider/testfeed3.rss' type='text/html' rel='alternate'/>
|
||||
<link href='tests/data/spider/testfeed3.rss' type='application/atom+xml' rel='self'/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/1' type='text/html' rel='alternate'/>
|
||||
<title>Mercury</title>
|
||||
<content>Messenger of the Roman Gods</content>
|
||||
<updated>2006-01-01T00:00:00Z</updated>
|
||||
<updated planet:format='January 01, 2006 12:00 AM'>2006-01-01T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1</id>
|
||||
<author>
|
||||
@ -16,7 +16,7 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>one</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
|
@ -4,8 +4,8 @@
|
||||
<link href='http://example.com/2' type='text/html' rel='alternate'/>
|
||||
<title>Venus</title>
|
||||
<content>the Jewel of the Sky</content>
|
||||
<updated>2006-02-02T00:00:00Z</updated>
|
||||
<published>2006-01-02T00:00:00Z</published>
|
||||
<updated planet:format='February 02, 2006 12:00 AM'>2006-02-02T00:00:00Z</updated>
|
||||
<published planet:format='January 02, 2006 12:00 AM'>2006-01-02T00:00:00Z</published>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1</id>
|
||||
<author>
|
||||
@ -17,7 +17,7 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>one</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/3' type='text/html' rel='alternate'/>
|
||||
<title>Earth</title>
|
||||
<content>the Blue Planet</content>
|
||||
<updated>2006-01-03T00:00:00Z</updated>
|
||||
<updated planet:format='January 03, 2006 12:00 AM'>2006-01-03T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1</id>
|
||||
<author>
|
||||
@ -16,7 +16,7 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>one</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/4' type='text/html' rel='alternate'/>
|
||||
<title>Mars</title>
|
||||
<content>the Red Planet</content>
|
||||
<updated>2006-01-04T00:00:00Z</updated>
|
||||
<updated planet:format='January 04, 2006 12:00 AM'>2006-01-04T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed1</id>
|
||||
<author>
|
||||
@ -16,7 +16,7 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>one</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/1' type='text/html' rel='alternate'/>
|
||||
<title>Mercury</title>
|
||||
<content>Messenger of the Roman Gods</content>
|
||||
<updated>2006-01-01T00:00:00Z</updated>
|
||||
<updated planet:format='January 01, 2006 12:00 AM'>2006-01-01T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2</id>
|
||||
<author>
|
||||
@ -16,7 +16,7 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>two</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/2' type='text/html' rel='alternate'/>
|
||||
<title>Venus</title>
|
||||
<content>the Morning Star</content>
|
||||
<updated>2006-01-02T00:00:00Z</updated>
|
||||
<updated planet:format='January 02, 2006 12:00 AM'>2006-01-02T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2</id>
|
||||
<author>
|
||||
@ -16,7 +16,7 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>two</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/3' type='text/html' rel='alternate'/>
|
||||
<title>Earth</title>
|
||||
<content>the Blue Planet</content>
|
||||
<updated>2006-01-03T00:00:00Z</updated>
|
||||
<updated planet:format='January 03, 2006 12:00 AM'>2006-01-03T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2</id>
|
||||
<author>
|
||||
@ -16,7 +16,7 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>two</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/4' type='text/html' rel='alternate'/>
|
||||
<title>Mars</title>
|
||||
<content>the Red Planet</content>
|
||||
<updated>2006-01-04T00:00:00Z</updated>
|
||||
<updated planet:format='January 04, 2006 12:00 AM'>2006-01-04T00:00:00Z</updated>
|
||||
<source>
|
||||
<id>tag:planet.intertwingly.net,2006:testfeed2</id>
|
||||
<author>
|
||||
@ -16,7 +16,7 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>two</planet:name>
|
||||
</source>
|
||||
</entry>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/1' type='text/html' rel='alternate'/>
|
||||
<title>Mercury</title>
|
||||
<summary>Messenger of the Roman Gods</summary>
|
||||
<updated>2006-01-01T00:00:00Z</updated>
|
||||
<updated planet:format='January 01, 2006 12:00 AM'>2006-01-01T00:00:00Z</updated>
|
||||
<source>
|
||||
<link href='http://intertwingly.net/code/venus/tests/data/spider/testfeed3.rss' type='text/html' rel='alternate'/>
|
||||
<link href='tests/data/spider/testfeed3.rss' type='application/atom+xml' rel='self'/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href='http://example.com/2' type='text/html' rel='alternate'/>
|
||||
<title>Venus</title>
|
||||
<summary>the Morning Star</summary>
|
||||
<updated>2006-08-18T18:30:50Z</updated>
|
||||
<updated planet:format='August 21, 2006 12:54 PM'>2006-08-21T12:54:31Z</updated>
|
||||
<source>
|
||||
<link href='http://intertwingly.net/code/venus/tests/data/spider/testfeed3.rss' type='text/html' rel='alternate'/>
|
||||
<link href='tests/data/spider/testfeed3.rss' type='application/atom+xml' rel='self'/>
|
||||
|
@ -10,6 +10,6 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>one</planet:name>
|
||||
</feed>
|
||||
|
@ -10,6 +10,6 @@
|
||||
<link href='http://www.intertwingly.net/blog/' type='text/html' rel='alternate'/>
|
||||
<subtitle>It’s just data</subtitle>
|
||||
<title>Sam Ruby</title>
|
||||
<updated>2006-06-17T00:15:18Z</updated>
|
||||
<updated planet:format='June 17, 2006 12:15 AM'>2006-06-17T00:15:18Z</updated>
|
||||
<planet:name>two</planet:name>
|
||||
</feed>
|
||||
|
@ -1,7 +1,6 @@
|
||||
[Planet]
|
||||
name = test planet
|
||||
cache_directory = tests/data/splice/cache
|
||||
template_files =
|
||||
|
||||
[tests/data/spider/testfeed0.atom]
|
||||
name = not found
|
||||
|
33
tests/test_apply.py
Normal file
33
tests/test_apply.py
Normal file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import unittest, os, shutil
|
||||
from planet import config, splice
|
||||
|
||||
workdir = 'tests/work/apply'
|
||||
configfile = 'tests/data/apply/config.ini'
|
||||
testfeed = 'tests/data/apply/feed.xml'
|
||||
|
||||
class ApplyTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
try:
|
||||
os.makedirs(workdir)
|
||||
except:
|
||||
self.tearDown()
|
||||
os.makedirs(workdir)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(workdir)
|
||||
os.removedirs(os.path.split(workdir)[0])
|
||||
|
||||
def test_apply(self):
|
||||
testfile = open(testfeed)
|
||||
feeddata = testfile.read()
|
||||
testfile.close()
|
||||
|
||||
config.load(configfile)
|
||||
splice.apply(feeddata)
|
||||
|
||||
for file in ['index.html', 'default.css', 'images/foaf.png']:
|
||||
path = os.path.join(workdir, file)
|
||||
self.assertTrue(os.path.exists(path))
|
||||
self.assertTrue(os.stat(path).st_size > 0)
|
@ -3,8 +3,6 @@
|
||||
import unittest
|
||||
from planet import config
|
||||
|
||||
workdir = 'tests/work/spider/cache'
|
||||
|
||||
class ConfigTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
config.load('tests/data/config/basic.ini')
|
||||
@ -16,7 +14,9 @@ class ConfigTest(unittest.TestCase):
|
||||
config.template_files())
|
||||
|
||||
def test_feeds(self):
|
||||
self.assertEqual(['feed1', 'feed2'], config.feeds())
|
||||
feeds = config.feeds()
|
||||
feeds.sort()
|
||||
self.assertEqual(['feed1', 'feed2'], feeds)
|
||||
|
||||
# planet wide configuration
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import unittest, os, glob, calendar
|
||||
import unittest, os, glob, calendar, shutil
|
||||
from planet.spider import filename, spiderFeed, spiderPlanet
|
||||
from planet import feedparser, config
|
||||
|
||||
@ -17,13 +17,8 @@ class SpiderTest(unittest.TestCase):
|
||||
os.makedirs(workdir)
|
||||
|
||||
def tearDown(self):
|
||||
for file in glob.glob(workdir+"/sources/*"):
|
||||
os.unlink(file)
|
||||
if os.path.exists(workdir+"/sources"):
|
||||
os.rmdir(workdir+"/sources")
|
||||
for file in glob.glob(workdir+"/*"):
|
||||
os.unlink(file)
|
||||
os.removedirs(workdir)
|
||||
shutil.rmtree(workdir)
|
||||
os.removedirs(os.path.split(workdir)[0])
|
||||
|
||||
def test_filename(self):
|
||||
self.assertEqual('./example.com,index.html',
|
||||
|
58
tests/test_themes.py
Normal file
58
tests/test_themes.py
Normal file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import unittest
|
||||
from planet import config
|
||||
from os.path import split
|
||||
|
||||
class ConfigTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
config.load('tests/data/config/themed.ini')
|
||||
|
||||
# template directories
|
||||
|
||||
def test_template_directories(self):
|
||||
self.assertEqual(['foo', 'bar', 'asf', 'common'],
|
||||
[split(dir)[1] for dir in config.template_directories()])
|
||||
|
||||
# administrivia
|
||||
|
||||
def test_template(self):
|
||||
self.assertTrue('index.html.xslt' in config.template_files())
|
||||
|
||||
def test_feeds(self):
|
||||
feeds = config.feeds()
|
||||
feeds.sort()
|
||||
self.assertEqual(['feed1', 'feed2'], feeds)
|
||||
|
||||
# planet wide configuration
|
||||
|
||||
def test_name(self):
|
||||
self.assertEqual('Test Configuration', config.name())
|
||||
|
||||
def test_link(self):
|
||||
self.assertEqual('Unconfigured Planet', config.link())
|
||||
|
||||
# per template configuration
|
||||
|
||||
def test_days_per_page(self):
|
||||
self.assertEqual(7, config.days_per_page('index.html.xslt'))
|
||||
self.assertEqual(0, config.days_per_page('atom.xml.xslt'))
|
||||
|
||||
def test_items_per_page(self):
|
||||
self.assertEqual(50, config.items_per_page('index.html.xslt'))
|
||||
self.assertEqual(50, config.items_per_page('atom.xml.xslt'))
|
||||
|
||||
def test_encoding(self):
|
||||
self.assertEqual('utf-8', config.encoding('index.html.xslt'))
|
||||
self.assertEqual('utf-8', config.encoding('atom.xml.xslt'))
|
||||
|
||||
# dictionaries
|
||||
|
||||
def test_feed_options(self):
|
||||
self.assertEqual('one', config.feed_options('feed1')['name'])
|
||||
self.assertEqual('two', config.feed_options('feed2')['name'])
|
||||
|
||||
def test_template_options(self):
|
||||
option = config.template_options('index.html.xslt')
|
||||
self.assertEqual('7', option['days_per_page'])
|
||||
self.assertEqual('50', option['items_per_page'])
|
19
themes/asf/config.ini
Normal file
19
themes/asf/config.ini
Normal file
@ -0,0 +1,19 @@
|
||||
# This template 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
|
||||
foafroll.xml.xslt
|
||||
index.html.xslt
|
||||
opml.xml.xslt
|
||||
|
||||
template_directories:
|
||||
../common
|
||||
|
||||
bill_of_materials:
|
||||
default.css
|
||||
personalize.js
|
||||
images/feed-icon-10x10.png
|
||||
images/opml.png
|
||||
images/foaf.png
|
429
themes/asf/default.css
Normal file
429
themes/asf/default.css
Normal file
@ -0,0 +1,429 @@
|
||||
/*
|
||||
* Written by Stefano Mazzocchi <stefano at apache dot org>
|
||||
*/
|
||||
|
||||
/* ----------------------------- Global Definitions -------------------- */
|
||||
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
color: #222;
|
||||
background-color: #fff;
|
||||
quotes: "\201C" "\201E" "\2018" "\2019";
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #222;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
a:active {
|
||||
}
|
||||
|
||||
a:focus {
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: x-large;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.25em;
|
||||
padding: 10px;
|
||||
margin: 0px 0px 0px 0px;
|
||||
color: #000;
|
||||
font-weight: normal;
|
||||
background-color: #eee;
|
||||
border-bottom: 2px solid #bbb
|
||||
}
|
||||
|
||||
/* ----------------------------- Sidebar --------------------------- */
|
||||
|
||||
#sidebar {
|
||||
float: right;
|
||||
top: 150px;
|
||||
right: 0px;
|
||||
width: 210px;
|
||||
background-color: white;
|
||||
|
||||
padding: 0px 0px 20px 0px;
|
||||
margin: 0px 0px 20px 20px;
|
||||
border-left: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
#sidebar h2 {
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
font-size: x-small;
|
||||
color: #666;
|
||||
font-weight: normal;
|
||||
padding: 2px 0px 2px 4px;
|
||||
margin: 15px 0px 5px 10px;
|
||||
border-top: 1px solid #ccc;
|
||||
border-left: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
#sidebar p {
|
||||
font-size: x-small;
|
||||
padding-left: 20px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
#sidebar ul {
|
||||
font-family: sans-serif;
|
||||
margin-left: 5px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
#sidebar li {
|
||||
margin-left: 0px;
|
||||
text-indent: -15px;
|
||||
list-style-type: none;
|
||||
font-size: x-small;
|
||||
}
|
||||
|
||||
#sidebar ul li a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#sidebar ul li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#sidebar img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#sidebar dl {
|
||||
font-size: x-small;
|
||||
padding-left: 1.0em;
|
||||
}
|
||||
|
||||
#sidebar dl ul {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
#sidebar dt {
|
||||
margin-top: 1em;
|
||||
font-weight: bold;
|
||||
padding-left: 1.0em;
|
||||
}
|
||||
|
||||
#sidebar dd {
|
||||
margin-left: 2.5em;
|
||||
}
|
||||
|
||||
#sidebar .message {
|
||||
cursor: help;
|
||||
border-bottom: 1px dashed red;
|
||||
}
|
||||
|
||||
#sidebar a.message:hover {
|
||||
cursor: help;
|
||||
background-color: #ffD0D0;
|
||||
border: 1px dashed red !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
/* ----------------------------- Body ---------------------------- */
|
||||
|
||||
#body {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.admin {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#body h2.date {
|
||||
text-transform: none;
|
||||
font-size: medium;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
border-top: 1px solid #ccc;
|
||||
background-color: #eee;
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding: 1px 15px 1px 5px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ----------------------------- News ---------------------------- */
|
||||
|
||||
.news {
|
||||
margin: 30px 10px 30px 10px;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.news > h3 {
|
||||
text-indent: -10px;
|
||||
margin: 12px;
|
||||
padding: 0px;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
.news > h3 > a:first-child {
|
||||
margin-left: 10px
|
||||
}
|
||||
|
||||
.news > h3 > a:first-child:before {
|
||||
content: '⌘';
|
||||
color: #D70;
|
||||
margin-left: -18px;
|
||||
margin-right: 2px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
img.icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-left: -8px;
|
||||
margin-bottom: -2px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.news .content {
|
||||
margin: 5px 5px 5px 15px;
|
||||
padding: 0px 5px 0px 5px;
|
||||
border-left: 1px solid #ccc;
|
||||
line-height: 1.2em;
|
||||
font-size: small;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.news .links {
|
||||
}
|
||||
|
||||
.news .permalink {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* ----------------------------- News Content ---------------------------- */
|
||||
|
||||
.news .content p {
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
.news .content img {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.news .content blockquote {
|
||||
margin: 10px 35px 10px 35px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.news .content pre {
|
||||
font-family: monospace;
|
||||
font-size: medium;
|
||||
font-weight: bold;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
margin: 10px 20px 10px 20px;
|
||||
background-color: #f8f8f8;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.news .content ul, .news .content ol {
|
||||
margin: 5px 35px 5px 35px;
|
||||
padding: 5px;
|
||||
counter-reset: item;
|
||||
}
|
||||
|
||||
.news .content ul > ul, .news .content ul > ol, .news .content ol > ul, .news .content ol > ol {
|
||||
margin: 0px 0px 0px 35px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.news .content li {
|
||||
padding: 1px;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
.news code {
|
||||
font-family: monospace;
|
||||
font-size: medium;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.news .content a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
border-bottom: 1px dotted #777;
|
||||
margin: 0px 2px 0px 2px;
|
||||
padding: 1px 1px 1px 1px;
|
||||
}
|
||||
|
||||
.news .content a:hover {
|
||||
border: 1px dotted #000;
|
||||
background-color: #eee;
|
||||
padding: 1px 2px 1px 2px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.news .content a:active {
|
||||
background-color: #ccc !important;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
padding: 1px 2px 1px 2px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.news .content a:focus {
|
||||
border: 1px solid #fff !important;
|
||||
background-color: #ccc !important;
|
||||
padding: 1px 2px 1px 2px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
/* --------------------------- Accomodations ----------------------- */
|
||||
|
||||
/* boing boing */
|
||||
br {
|
||||
clear: none !important;
|
||||
}
|
||||
|
||||
/* engadget */
|
||||
h6 {
|
||||
clear: left !important;
|
||||
}
|
||||
|
||||
/* cadenhead */
|
||||
p.sourcecode {
|
||||
font-family: monospace;
|
||||
font-size: medium;
|
||||
font-weight: bold;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
margin: 10px 20px 10px 20px;
|
||||
background-color: #f8f8f8;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* cadenhead */
|
||||
span.sourcecode {
|
||||
font-family: monospace;
|
||||
font-size: medium;
|
||||
font-weight: bold;
|
||||
font-size: large;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
/* hsivonen */
|
||||
ul p, ol p {
|
||||
margin-top: 0.3em;
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
|
||||
/* programmableweb */
|
||||
.imgRight {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* gizmodo */
|
||||
img.left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* gizmodo */
|
||||
img.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* gizmodo */
|
||||
img.center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* wikipedia */
|
||||
table {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
/* del.icio.us */
|
||||
.delicious-tags {
|
||||
font-size: x-small;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* musings */
|
||||
img.mathlogo, img.svglogo {
|
||||
float: right;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
math {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
math[display=block] {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.eqno {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* sutor */
|
||||
img.post-img-right {
|
||||
float:right;
|
||||
}
|
||||
|
||||
/* niall */
|
||||
img.floatright {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* jason kolb */
|
||||
.FeaturedPost > li {
|
||||
list-style-type: none;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
/* GigaOM */
|
||||
p img {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* Tantek */
|
||||
ul.tags,ul.tags li,h4.tags {
|
||||
display:inline;
|
||||
font-size: x-small
|
||||
}
|
||||
|
||||
ul.tags a:link, ul.tags a:visited {
|
||||
color:green
|
||||
}
|
||||
|
||||
/* DiveIntoMark */
|
||||
.framed {
|
||||
float: none;
|
||||
}
|
||||
|
||||
/* ----------------------------- Footer ---------------------------- */
|
||||
|
||||
#footer {
|
||||
padding: 0px;
|
||||
margin: 30px 0px 50px 50px;
|
||||
}
|
||||
|
||||
#footer p {
|
||||
padding: 2px 2px 2px 5px;
|
||||
background-color: #ccc;
|
||||
border-top: 1px solid #aaa;
|
||||
border-bottom: 1px solid #aaa;
|
||||
border-left: 1px solid #aaa;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
text-align: left;
|
||||
}
|
153
themes/asf/index.html.xslt
Normal file
153
themes/asf/index.html.xslt
Normal file
@ -0,0 +1,153 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
xmlns:planet="http://planet.intertwingly.net/"
|
||||
xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<xsl:output indent="yes" method="html"/>
|
||||
|
||||
<xsl:template match="atom:feed">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<xsl:text> </xsl:text>
|
||||
<head>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
<title><xsl:value-of select="atom:title"/></title>
|
||||
<meta name="generator" content="{atom:generator}" />
|
||||
<xsl:if test="atom:link[@rel='self']">
|
||||
<link rel="alternate" href="{atom:link[@rel='self']/@uri}"
|
||||
title="{atom:title}" type="{atom:link[@rel='self']/@type}" />
|
||||
</xsl:if>
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<script type="text/javascript" src="personalize.js"></script>
|
||||
</head>
|
||||
|
||||
<xsl:text> </xsl:text>
|
||||
<body>
|
||||
<xsl:text> </xsl:text>
|
||||
<h1><xsl:value-of select="atom:title"/></h1>
|
||||
|
||||
<xsl:text> </xsl:text>
|
||||
<div id="sidebar">
|
||||
|
||||
<xsl:text> </xsl:text>
|
||||
<h2>Subscriptions</h2>
|
||||
<ul>
|
||||
<xsl:for-each select="planet:source">
|
||||
<xsl:sort select="planet:name"/>
|
||||
<xsl:text> </xsl:text>
|
||||
<li>
|
||||
<a href="{atom:link[@rel='self']/@href}" title="subscribe">
|
||||
<img src="images/feed-icon-10x10.png" alt="(feed)"/>
|
||||
</a>
|
||||
<a href="{atom:link[@rel='alternate']/@href}">
|
||||
<xsl:value-of select="planet:name"/>
|
||||
</a>
|
||||
</li>
|
||||
</xsl:for-each>
|
||||
<xsl:text> </xsl:text>
|
||||
</ul>
|
||||
|
||||
<xsl:text> </xsl:text>
|
||||
<h2>Info</h2>
|
||||
|
||||
<dl>
|
||||
<dt>Last updated:</dt>
|
||||
<dd><span class="date" title="GMT"><xsl:value-of select="atom:updated"/></span></dd>
|
||||
<dt>Powered by:</dt>
|
||||
<dd><a href="http://intertwingly.net/code/planet/"><img src="images/planet.png" width="80" height="15" alt="Planet" border="0" /></a></dd>
|
||||
<dt>Export:</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li><a href="opml.xml"><img src="images/opml.png" alt="OPML" /></a></li>
|
||||
<li><a href="foafroll.xml"><img src="images/foaf.png" alt="FOAF" /></a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<xsl:apply-templates select="atom:entry"/>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="atom:entry">
|
||||
<!-- date header -->
|
||||
<xsl:variable name="date" select="substring(atom:updated,1,10)"/>
|
||||
<xsl:if test="not(preceding-sibling::atom:entry
|
||||
[substring(atom:updated,1,10) = $date])">
|
||||
<xsl:text> </xsl:text>
|
||||
<h2 class="date"><xsl:value-of select="$date"/></h2>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:text> </xsl:text>
|
||||
<div class="news">
|
||||
|
||||
<xsl:if test="@xml:lang">
|
||||
<xsl:attribute name="xml:lang" select="{@xml:lang}"/>
|
||||
</xsl:if>
|
||||
|
||||
<!-- entry title -->
|
||||
<xsl:text> </xsl:text>
|
||||
<h3>
|
||||
<xsl:if test="atom:source/atom:icon">
|
||||
<img src="{atom:source/atom:icon}" class="icon"/>
|
||||
</xsl:if>
|
||||
<a href="{atom:source/atom:link['alternate']/@href}" class="icon">
|
||||
<xsl:attribute name="title" select="{atom:source/atom:title}"/>
|
||||
<xsl:value-of select="atom:source/planet:name"/>
|
||||
</a>
|
||||
<xsl:if test="atom:title">
|
||||
<xsl:text>—</xsl:text>
|
||||
<a href="{atom:link[@rel='alternate']/@href}">
|
||||
<xsl:if test="atom:title/@xml:lang != @xml:lang">
|
||||
<xsl:attribute name="xml:lang" select="{atom:title/@xml:lang}"/>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="atom:title"/>
|
||||
</a>
|
||||
</xsl:if>
|
||||
</h3>
|
||||
|
||||
<!-- entry content -->
|
||||
<xsl:text> </xsl:text>
|
||||
<div class="content">
|
||||
<xsl:choose>
|
||||
<xsl:when test="atom:content">
|
||||
<xsl:if test="atom:content/@xml:lang != @xml:lang">
|
||||
<xsl:attribute name="xml:lang" select="{atom:content/@xml:lang}"/>
|
||||
</xsl:if>
|
||||
<xsl:copy-of select="atom:content/*"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:if test="atom:summary/@xml:lang != @xml:lang">
|
||||
<xsl:attribute name="xml:lang" select="{atom:summary/@xml:lang}"/>
|
||||
</xsl:if>
|
||||
<xsl:copy-of select="atom:summary/*"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</div>
|
||||
|
||||
<!-- entry footer -->
|
||||
<xsl:text> </xsl:text>
|
||||
<div class="permalink">
|
||||
<a href="{atom:link[@rel='alternate']/@href}">
|
||||
<xsl:choose>
|
||||
<xsl:when test="atom:author/atom:name">
|
||||
<xsl:text>by </xsl:text>
|
||||
<xsl:value-of select="atom:author/atom:name"/>
|
||||
<xsl:text> at </xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="atom:source/atom:author/atom:name">
|
||||
<xsl:text>by </xsl:text>
|
||||
<xsl:value-of select="atom:source/atom:author/atom:name"/>
|
||||
<xsl:text> at </xsl:text>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<span class="date" title="GMT">
|
||||
<xsl:value-of select="atom:updated"/>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
220
themes/asf/personalize.js
Normal file
220
themes/asf/personalize.js
Normal file
@ -0,0 +1,220 @@
|
||||
var entries = []; // list of news items
|
||||
|
||||
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
|
||||
"Friday", "Saturday"];
|
||||
var months = ["January", "February", "March", "April", "May", "June", "July",
|
||||
"August", "September", "October", "November", "December"];
|
||||
|
||||
// event complete: stop propagation of the event
|
||||
function stopPropagation(event) {
|
||||
if (event.preventDefault) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
} else {
|
||||
event.returnValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
// scroll back to the previous article
|
||||
function prevArticle(event) {
|
||||
for (var i=entries.length; --i>=0;) {
|
||||
if (entries[i].anchor.offsetTop < document.documentElement.scrollTop) {
|
||||
window.location.hash=entries[i].anchor.id;
|
||||
stopPropagation(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// advance to the next article
|
||||
function nextArticle(event) {
|
||||
for (var i=1; i<entries.length; i++) {
|
||||
if (entries[i].anchor.offsetTop-20 > document.documentElement.scrollTop) {
|
||||
window.location.hash=entries[i].anchor.id;
|
||||
stopPropagation(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// process keypresses
|
||||
function navkey(event) {
|
||||
var checkbox = document.getElementById('navkeys');
|
||||
if (!checkbox || !checkbox.checked) return;
|
||||
|
||||
if (!event) event=window.event;
|
||||
key=event.keyCode;
|
||||
|
||||
if (!document.documentElement) return;
|
||||
if (!entries[0].anchor || !entries[0].anchor.offsetTop) return;
|
||||
|
||||
if (key == 'J'.charCodeAt(0)) nextArticle(event);
|
||||
if (key == 'K'.charCodeAt(0)) prevArticle(event);
|
||||
}
|
||||
|
||||
// create (or reset) a cookie
|
||||
function createCookie(name,value,days) {
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime()+(days*24*60*60*1000));
|
||||
var expires = "; expires="+date.toGMTString();
|
||||
}
|
||||
else expires = "";
|
||||
document.cookie = name+"="+value+expires+"; path=/";
|
||||
}
|
||||
|
||||
// read a cookie
|
||||
function readCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0;i < ca.length;i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// each time the value of the option changes, update the cookie
|
||||
function selectOption() {
|
||||
var checkbox = document.getElementById('navkeys');
|
||||
if (!checkbox) return;
|
||||
createCookie("navkeys", checkbox.checked?'true':'false', 365);
|
||||
}
|
||||
|
||||
// add navkeys option to sidebar
|
||||
function addOption(event) {
|
||||
if (entries.length > 1 && entries[entries.length-1].parent.offsetTop > 0) {
|
||||
var sidebar = document.getElementById('sidebar');
|
||||
if (!sidebar) return;
|
||||
|
||||
for (var i=entries.length; --i>=0;) {
|
||||
var a = entries[i].anchor = document.createElement('a');
|
||||
a.id = "news-" + i;
|
||||
entries[i].parent.insertBefore(a, entries[i].parent.firstChild);
|
||||
}
|
||||
|
||||
var h2 = document.createElement('h2');
|
||||
h2.appendChild(document.createTextNode('Options'));
|
||||
sidebar.appendChild(h2);
|
||||
|
||||
var form = document.createElement('form');
|
||||
var p = document.createElement('p');
|
||||
var input = document.createElement('input');
|
||||
input.type = "checkbox";
|
||||
input.id = "navkeys";
|
||||
p.appendChild(input);
|
||||
var a = document.createElement('a');
|
||||
a.title = "Navigate entries";
|
||||
a.appendChild(document.createTextNode('Enable '));
|
||||
var code = document.createElement('code');
|
||||
code.appendChild(document.createTextNode('J'));
|
||||
a.appendChild(code);
|
||||
a.appendChild(document.createTextNode(' and '));
|
||||
code = document.createElement('code');
|
||||
code.appendChild(document.createTextNode('K'));
|
||||
a.appendChild(code);
|
||||
a.appendChild(document.createTextNode(' keys'));
|
||||
p.appendChild(a);
|
||||
form.appendChild(p);
|
||||
sidebar.appendChild(form);
|
||||
|
||||
var cookie = readCookie("navkeys");
|
||||
if (cookie && cookie == 'true') input.checked = true;
|
||||
input.onclick = selectOption;
|
||||
document.onkeydown = navkey;
|
||||
}
|
||||
}
|
||||
|
||||
// convert date to local time
|
||||
var localere = /^(\w+) (\d+) (\w+) \d+ 0?(\d\d?:\d\d):\d\d ([AP]M) (EST|EDT|CST|CDT|MST|MDT|PST|PDT)/;
|
||||
function localizeDate(element) {
|
||||
var date = new Date();
|
||||
date.setTime(Date.parse(element.innerHTML + " GMT"));
|
||||
|
||||
var local = date.toLocaleString();
|
||||
var match = local.match(localere);
|
||||
if (match) {
|
||||
element.innerHTML = match[4] + ' ' + match[5].toLowerCase();
|
||||
element.title = match[6] + " \u2014 " +
|
||||
match[1] + ', ' + match[3] + ' ' + match[2];
|
||||
return days[date.getDay()] + ', ' + months[date.getMonth()] + ' ' +
|
||||
date.getDate() + ', ' + date.getFullYear();
|
||||
} else {
|
||||
element.title = element.innerHTML + ' GMT';
|
||||
element.innerHTML = local;
|
||||
return days[date.getDay()] + ', ' + date.getDate() + ' ' +
|
||||
months[date.getMonth()] + ' ' + date.getFullYear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// find entries (and localizeDates)
|
||||
function findEntries() {
|
||||
|
||||
var span = document.getElementsByTagName('span');
|
||||
|
||||
for (var i=0; i<span.length; i++) {
|
||||
if (span[i].className == "date" && span[i].title == "GMT") {
|
||||
var date = localizeDate(span[i]);
|
||||
|
||||
var parent = span[i];
|
||||
while (parent && parent.className != 'news') {
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
var info = entries[entries.length] = new Object();
|
||||
info.parent = parent;
|
||||
info.date = date;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// insert/remove date headers to indicate change of date in local time zone
|
||||
function moveDateHeaders() {
|
||||
lastdate = ''
|
||||
for (var i=0; i<entries.length; i++) {
|
||||
var parent = entries[i].parent;
|
||||
var date = entries[i].date;
|
||||
|
||||
sibling = parent.previousSibling;
|
||||
while (sibling && sibling.nodeType != 1) {
|
||||
sibling = sibling.previousSibling;
|
||||
}
|
||||
|
||||
if (sibling && sibling.nodeName.toLowerCase() == 'h2') {
|
||||
if (lastdate == date) {
|
||||
sibling.parentNode.removeChild(sibling);
|
||||
} else {
|
||||
sibling.innerHTML = date;
|
||||
lastdate = date;
|
||||
}
|
||||
} else if (lastdate != date) {
|
||||
var h2 = document.createElement('h2');
|
||||
h2.className = 'date'
|
||||
h2.appendChild(document.createTextNode(date));
|
||||
parent.parentNode.insertBefore(h2, parent);
|
||||
lastdate = date;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adjust dates to local time zones, optionally provide navigation keys
|
||||
function personalize() {
|
||||
findEntries();
|
||||
addOption();
|
||||
moveDateHeaders();
|
||||
}
|
||||
|
||||
// hook event
|
||||
window.onload = personalize;
|
||||
if (document.addEventListener) {
|
||||
onDOMLoad = function() {
|
||||
window.onload = undefined;
|
||||
personalize();
|
||||
};
|
||||
document.addEventListener("DOMContentLoaded", onDOMLoad, false);
|
||||
}
|
25
themes/common/atom.xml.xslt
Normal file
25
themes/common/atom.xml.xslt
Normal file
@ -0,0 +1,25 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
xmlns:indexing="urn:atom-extension:indexing"
|
||||
xmlns:planet="http://planet.intertwingly.net/"
|
||||
xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<!-- strip planet elements and attributes -->
|
||||
<xsl:template match="planet:*"/>
|
||||
|
||||
<!-- add Google/LiveJournal-esque noindex directive -->
|
||||
<xsl:template match="atom:feed">
|
||||
<xsl:copy>
|
||||
<xsl:attribute name="indexing:index">no</xsl:attribute>
|
||||
<xsl:apply-templates select="@*|node()"/>
|
||||
</xsl:copy>
|
||||
</xsl:template>
|
||||
|
||||
<!-- pass through everything else -->
|
||||
<xsl:template match="@*|node()">
|
||||
<xsl:copy>
|
||||
<xsl:apply-templates select="@*|node()"/>
|
||||
</xsl:copy>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
39
themes/common/foafroll.xml.xslt
Normal file
39
themes/common/foafroll.xml.xslt
Normal file
@ -0,0 +1,39 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||
xmlns:rss="http://purl.org/rss/1.0/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
xmlns:planet="http://planet.intertwingly.net/"
|
||||
xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<xsl:output indent="yes" method="xml"/>
|
||||
|
||||
<xsl:template match="atom:feed">
|
||||
<rdf:RDF>
|
||||
<foaf:Group>
|
||||
<foaf:name><xsl:value-of select="atom:author/atom:name"/></foaf:name>
|
||||
<foaf:homepage><xsl:value-of select="atom:author/atom:uri"/></foaf:homepage>
|
||||
|
||||
<xsl:apply-templates select="planet:source"/>
|
||||
</foaf:Group>
|
||||
</rdf:RDF>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="planet:source">
|
||||
<foaf:member>
|
||||
<foaf:Agent>
|
||||
<foaf:name><xsl:value-of select="planet:name"/></foaf:name>
|
||||
<foaf:weblog>
|
||||
<foaf:Document rdf:about="{atom:link[@rel='alternate']/@href}">
|
||||
<dc:title><xsl:value-of select="atom:title"/></dc:title>
|
||||
<rdfs:seeAlso>
|
||||
<rss:channel rdf:about="{atom:link[@rel='self']/@href}" />
|
||||
</rdfs:seeAlso>
|
||||
</foaf:Document>
|
||||
</foaf:weblog>
|
||||
</foaf:Agent>
|
||||
</foaf:member>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
BIN
themes/common/images/feed-icon-10x10.png
Normal file
BIN
themes/common/images/feed-icon-10x10.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 469 B |
BIN
themes/common/images/foaf.png
Normal file
BIN
themes/common/images/foaf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
themes/common/images/opml.png
Normal file
BIN
themes/common/images/opml.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 804 B |
BIN
themes/common/images/planet.png
Normal file
BIN
themes/common/images/planet.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 426 B |
25
themes/common/opml.xml.xslt
Normal file
25
themes/common/opml.xml.xslt
Normal file
@ -0,0 +1,25 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
xmlns:planet="http://planet.intertwingly.net/"
|
||||
xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<xsl:output indent="yes" method="xml"/>
|
||||
|
||||
<xsl:template match="atom:feed">
|
||||
<opml version="1.1">
|
||||
<head>
|
||||
<title><xsl:value-of select="atom:title"/></title>
|
||||
<dateModified><xsl:value-of select="atom:updated/@planet:format"/></dateModified>
|
||||
<ownerName><xsl:value-of select="atom:author/atom:name"/></ownerName>
|
||||
<ownerEmail><xsl:value-of select="atom:author/atom:email"/></ownerEmail>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<xsl:for-each select="planet:source">
|
||||
<outline type="rss" text="{planet:name}" title="{atom:title}"
|
||||
xmlUrl="{atom:link[@rel='self']/@href}"/>
|
||||
</xsl:for-each>
|
||||
</body>
|
||||
</opml>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
Loading…
x
Reference in New Issue
Block a user