| 1 | #!/usr/bin/python |
|---|
| 2 | """Source code file to www.enricomoretti.it |
|---|
| 3 | |
|---|
| 4 | Generates a tree of HTML files and their navigation using Django's |
|---|
| 5 | templating system and Jason Orendorff path.py""" |
|---|
| 6 | |
|---|
| 7 | import os |
|---|
| 8 | import sys |
|---|
| 9 | from path import path |
|---|
| 10 | from django.conf import settings |
|---|
| 11 | # set up boilerplate Django settings |
|---|
| 12 | settings.configure( |
|---|
| 13 | DEBUG=True, TEMPLATE_DEBUG=True, TEMPLATE_DIRS=('templates',)) |
|---|
| 14 | from django.template import Context |
|---|
| 15 | from django.template.loader import get_template |
|---|
| 16 | |
|---|
| 17 | __author__ = "Antonio Cavedoni <antonio@cavedoni.org>" |
|---|
| 18 | __svnid__ = "$Id$" |
|---|
| 19 | |
|---|
| 20 | IGNORED_DIRS = ( |
|---|
| 21 | '_private', '_vti_log', '2006', 'about', 'aspnet_client', |
|---|
| 22 | 'bin', 'cgi-bin', 'images', 'mdb-database', 'styles', |
|---|
| 23 | 'templates' |
|---|
| 24 | ) |
|---|
| 25 | IGNORED_FILES = ( |
|---|
| 26 | '.DS_Store', '.htaccess', '_vti_inf.html' |
|---|
| 27 | ) |
|---|
| 28 | |
|---|
| 29 | def render_to_file(context, template, filename): |
|---|
| 30 | """Render context to filename with template""" |
|---|
| 31 | t = get_template(template) |
|---|
| 32 | f = open(filename, 'w') |
|---|
| 33 | f.write(t.render(context)) |
|---|
| 34 | f.close() |
|---|
| 35 | |
|---|
| 36 | def deslugify(name): |
|---|
| 37 | """Transform a directory name into a (somewhat) human-readable title""" |
|---|
| 38 | bits = name.split('-') |
|---|
| 39 | bits[0] = bits[0].capitalize() |
|---|
| 40 | return " ".join(bits) |
|---|
| 41 | |
|---|
| 42 | def get_absolute_path(name): |
|---|
| 43 | """Given a relative directory path, make it absolute""" |
|---|
| 44 | return name.replace('./', '/') |
|---|
| 45 | |
|---|
| 46 | def has_contents(directory): |
|---|
| 47 | """Check whether a folder has files (.jpg or .mov) or subdirectories""" |
|---|
| 48 | return directory.files("*.jpg") or directory.files("*.mov") \ |
|---|
| 49 | or directory.dirs() |
|---|
| 50 | |
|---|
| 51 | def htmlize(directory): |
|---|
| 52 | """Return a link to a directory, if it has contents""" |
|---|
| 53 | absolute_dir = get_absolute_path(directory) |
|---|
| 54 | if has_contents(directory): |
|---|
| 55 | return '<a href="%s/">%s</a><br>\n' % \ |
|---|
| 56 | (absolute_dir, deslugify(directory.name)) |
|---|
| 57 | else: |
|---|
| 58 | return "%s<br>\n" % deslugify(directory.name) |
|---|
| 59 | |
|---|
| 60 | def generate_menu(startpath, endpath=None): |
|---|
| 61 | """Generate an HTML menu for a directory. If the parameter `endpath` |
|---|
| 62 | is set, generate a tree from startpath to endpath""" |
|---|
| 63 | |
|---|
| 64 | # @@ I should probably just get rid of path.py |
|---|
| 65 | _path = path(startpath) |
|---|
| 66 | |
|---|
| 67 | # default value of endpath is startpath |
|---|
| 68 | if not endpath: |
|---|
| 69 | endpath = startpath |
|---|
| 70 | |
|---|
| 71 | output = [] |
|---|
| 72 | |
|---|
| 73 | for directory in _path.walkdirs(): |
|---|
| 74 | # filter out unwanted dirs |
|---|
| 75 | if directory.namebase in IGNORED_DIRS: continue |
|---|
| 76 | |
|---|
| 77 | # gather nesting information on the directories |
|---|
| 78 | end_levels = len(endpath.split('/')) |
|---|
| 79 | dir_levels = len(directory.split('/')) |
|---|
| 80 | level_diff = end_levels - dir_levels |
|---|
| 81 | |
|---|
| 82 | # always print top-level directories |
|---|
| 83 | if directory.parent == startpath: |
|---|
| 84 | output.append(htmlize(directory)) |
|---|
| 85 | # all the directories that are not in the root |
|---|
| 86 | elif dir_levels > 2: |
|---|
| 87 | if directory.parent in endpath and level_diff >= -1: |
|---|
| 88 | output.append(" " * (dir_levels - 2)) |
|---|
| 89 | output.append(htmlize(directory)) |
|---|
| 90 | |
|---|
| 91 | return " ".join(output) |
|---|
| 92 | |
|---|
| 93 | def generate_sections(startpath): |
|---|
| 94 | """Generate index pages and single files for a photo/movie gallery""" |
|---|
| 95 | |
|---|
| 96 | _path = path(startpath) |
|---|
| 97 | dirs = [x for x in _path.walkdirs() if x.name not in IGNORED_DIRS] |
|---|
| 98 | |
|---|
| 99 | def generate_files(_files, ext): |
|---|
| 100 | for i in range(len(_files)): |
|---|
| 101 | try: |
|---|
| 102 | next_link = _files[i+1].replace(ext, '.html') |
|---|
| 103 | except IndexError: |
|---|
| 104 | next_link = None |
|---|
| 105 | try: |
|---|
| 106 | prev_link = _files[i-1].replace(ext, '.html') |
|---|
| 107 | except IndexError: |
|---|
| 108 | prev_link = None |
|---|
| 109 | absolute_dir = get_absolute_path(directory) |
|---|
| 110 | c['next_link'] = "%s/%s" % \ |
|---|
| 111 | (absolute_dir, next_link) |
|---|
| 112 | c['prev_link'] = "%s/%s" % \ |
|---|
| 113 | (absolute_dir, prev_link) |
|---|
| 114 | c['src'] = "%s/%s" % \ |
|---|
| 115 | (absolute_dir, _files[i]) |
|---|
| 116 | |
|---|
| 117 | outfile = "%s/%s" % \ |
|---|
| 118 | (directory, _files[i].replace(ext, '.html')) |
|---|
| 119 | |
|---|
| 120 | if i == 0: |
|---|
| 121 | del c['prev_link'] |
|---|
| 122 | outfile = "%s/%s" % (directory, 'index.html') |
|---|
| 123 | elif i == 1: |
|---|
| 124 | c['prev_link'] = "./" |
|---|
| 125 | elif i == (len(_files) - 1): |
|---|
| 126 | del c['next_link'] |
|---|
| 127 | |
|---|
| 128 | if ext == '.jpg': |
|---|
| 129 | render_to_file(c, 'picture.tmpl', outfile) |
|---|
| 130 | elif ext == '.mov': |
|---|
| 131 | render_to_file(c, 'quicktime.tmpl', outfile) |
|---|
| 132 | |
|---|
| 133 | for directory in dirs: |
|---|
| 134 | c = Context({'sections': generate_menu(startpath, directory)}) |
|---|
| 135 | render_to_file(c, 'picture.tmpl', |
|---|
| 136 | "%s/%s" % (directory, 'index.html')) |
|---|
| 137 | jpgs = [x.name for x in directory.files("*.jpg")] |
|---|
| 138 | movs = [x.name for x in directory.files("*.mov")] |
|---|
| 139 | generate_files(jpgs, ".jpg") |
|---|
| 140 | generate_files(movs, ".mov") |
|---|
| 141 | |
|---|
| 142 | if __name__ == "__main__": |
|---|
| 143 | startpath = path('.') |
|---|
| 144 | c = Context({'sections': generate_menu(startpath)}) |
|---|
| 145 | render_to_file(c, 'base.tmpl', "./index.html") |
|---|
| 146 | render_to_file(c, 'about.tmpl', "./about/index.html") |
|---|
| 147 | generate_sections(startpath) |
|---|