#!/Users/amk/source/p/python/python.exe
# Read copy of the pyfaq infogami site (assumed to be in the pyfaq/
# subdirectory) and write out a pyramid-formatting tree to pyramid-faq/
#
# Warning: erases the existing pyramid-faq/ directory on starting!
#
# $Id$
import os, shutil, glob, cgi
import htmlload
ET = htmlload.ET
DESTDIR = 'pyramid-faq'
# Master collection of categories
categories = {}
def yaml_escape (S):
"Escape S as a YAML string"
S = normalize_whitespace(S)
S = S.replace("\\", "\\\\")
S = S.replace('"', '\\"')
S = '"' + S + '"'
return S
def normalize_whitespace (S):
"""Replace all whitespace by single spaces.
>>> normalize_whitespace('a b\tc\nd')
'a b c d'
"""
return ' '.join(S.split())
def get_setting (root, setting_name, default=None):
"""Look for a paragraph containing a setting, like 'CATEGORY: general',
and returns the result of the setting.
"""
setting_start = setting_name.upper() + ':'
for para in root.findall('*/p'):
if para.text is not None and para.text.startswith(setting_start):
value = para.text[len(setting_start):]
value = value.strip()
return value
else:
return default
def write_nav (dir, urls):
f = open(os.path.join(dir, 'nav.yml'), 'w')
f.write("""--- !fragment
# Type of template to use
template: nav.html
# Contents of the template
global:
nav : !sectionnav |
""")
for dirname, title in urls:
title = normalize_whitespace(title)
f.write(' '*6 + title + ' ' + dirname + '\n')
f.close()
def convert_question (filename):
base = os.path.basename(filename).replace('.xml', '')
# root is the 'html' element
root = htmlload.load(filename)
title = root.findtext('head/title')
title = normalize_whitespace(title)
# Find category and name
category = get_setting(root, 'category')
if category is None:
##print 'Filename without category:', filename
return
if category in ('test',):
return
if category not in categories:
categories[category] = None
name = get_setting(root, 'name', base)
qdir = os.path.join(DESTDIR, category, name)
os.makedirs(qdir)
# Write body of question
f = open(os.path.join(qdir, 'question.ht'), 'w')
f.write('Title: Unused title\n')
f.write('\n')
f.write('
%s
\n\n' % cgi.escape(title))
body = root.find('body')
for child in body.getchildren():
s = ET.tostring(child, 'utf-8')
f.write(s)
# Add a link to the wiki page for this question
f.write('''[Edit/comment on this page]
\n''' % base)
f.close()
# Write .yml files
page_title = '%s FAQ: %s' % (category.capitalize(), title)
f = open(os.path.join(qdir, 'index.yml'), 'w')
f.write("""--- !fragment
template: index.html
# The data to pass to the template
global:
metadata: {}
local:
title: %s
content: !fragment content.yml
""" % yaml_escape(page_title))
f.close()
f = open(os.path.join(qdir, 'content.yml'), 'w')
f.write("""--- !fragment
# Type of template to use
template: content.html
# The data to pass to the template
local:
content:
breadcrumb: !breadcrumb nav.yml nav
text: !htfile question.ht\n""")
f.close()
def convert_index (filename):
root = htmlload.load(filename)
title = root.findtext('*/title')
title = normalize_whitespace(title)
i = title.find(':')
category = title[i+1:].strip()
idir = os.path.join(DESTDIR, category)
# XXX can there be subsections within a category?
entries = list(root.findall('*/p/a'))
# Write body of question
f = open(os.path.join(idir, 'listing.ht'), 'w')
f.write('\n')
urllist = []
for a in entries:
href = a.get("href")
href = href.lstrip('/')
a.set("href", href)
f.write('- %s
\n' % ET.tostring(a, 'utf-8'))
urllist.append((href, a.text))
f.write('
\n')
f.close()
write_nav(idir, urllist)
# Write .yml files
f = open(os.path.join(idir, 'index.yml'), 'w')
f.write("""--- !fragment
template: index.html
# The data to pass to the template
local:
title: %s
content: !fragment content.yml
""" % yaml_escape(title))
f.close()
f = open(os.path.join(idir, 'content.yml'), 'w')
f.write("""--- !fragment
# Type of template to use
template: content.html
# The data to pass to the template
local:
content:
breadcrumb: !breadcrumb nav.yml nav
text: !htfile listing.ht""")
f.close()
def write_master_index (index_files):
f = open(os.path.join(DESTDIR, 'index.yml'), 'w')
f.write("""--- !fragment
template: index.html
# The data to pass to the template
local:
title: FAQs
content: !fragment content.yml
""")
f.close()
f = open(os.path.join(DESTDIR, 'content.yml'), 'w')
f.write("""--- !fragment
# Type of template to use
template: content.html
# The data to pass to the template
local:
content:
text: !htfile listing.ht
breadcrumb: !breadcrumb nav.yml nav
""")
f.close()
f = open(os.path.join(DESTDIR, 'listing.ht'), 'w')
f.write('Title: Unused title\n')
f.write('\n')
f.write('\n')
for cat in sorted(categories.keys()):
f.write(' - %s' % (cat, cat.capitalize()))
f.write('
\n')
f.close()
# Write navigation info
urllist = []
for cat in sorted(categories.keys()):
urllist.append((cat, cat.capitalize()))
write_nav(DESTDIR, urllist)
f = open(os.path.join(DESTDIR, 'content.html'), 'w')
f.write("""
""")
f.close()
if os.path.exists(DESTDIR):
shutil.rmtree(DESTDIR)
os.mkdir(DESTDIR)
# List the files to be converted
files = set(glob.glob('pyfaq/*.xml'))
for fn in list(files):
if fn.startswith('pyfaq/_'):
files.discard(fn)
index_files = [fn for fn in files if fn.endswith('-index.xml')]
for fn in index_files:
files.discard(fn)
# Convert questions
for fn in list(files):
convert_question(fn)
# Convert indexes
for fn in index_files:
convert_index(fn)
write_master_index(index_files)