Anonymous avatar Anonymous committed 272cf6a

Page tag sorting; --test option; ignoring files/_* ...

- Added --test option (opens the site in the default browser)
- Ignore files/_*
- Separated pages.Archive into Month and Year classes
- Tag sorting functions for content page templates
- Usage info, python version checks + other minor stuff

Comments (0)

Files changed (17)

example-site/deploy/2008/whats-new.html

     <div id="footer">
       
   <p>
+        
+        <a href="/pilcrow/loremipsum.html">Lorem Ipsum</a>
+        <span class="sep">|</span>
         <a href="/pilcrow/python.html">Python</a>
-        <a href="/pilcrow/loremipsum.html">Lorem Ipsum</a>
   <p>
 
     <a href="/pilcrow/2008.html">2008</a>

example-site/deploy/2009/lorem-ipsum.html

     <div id="footer">
       
   <p>
+        
         <a href="/pilcrow/loremipsum.html">Lorem Ipsum</a>
+        <span class="sep">|</span>
         <a href="/pilcrow/typography.html">Typography</a>
   <p>
       <a href="/pilcrow/2009/turritopsis-nutricula.html">&larr; Turritopsis nutricula</a>

example-site/deploy/2009/turritopsis-nutricula.html

     <div id="footer">
       
   <p>
+        
         <a href="/pilcrow/wikipedia.html">Wikipedia</a>
+        <span class="sep">|</span>
         <a href="/pilcrow/wtf.html">WTF</a>
   <p>
 

example-site/deploy/loremipsum.html

     <div id="body">
       
 
+<h1>Lorem Ipsum</h1>
+
   <h2>
     <a href="/pilcrow/2009/lorem-ipsum.html">Lorem ipsum</a>
     (2009-Dec-07)

example-site/deploy/python.html

     <div id="body">
       
 
+<h1>Python</h1>
+
   <h2>
     <a href="/pilcrow/2008/whats-new.html">What's new in Python 2.6</a>
     (2009-Dec-06)

example-site/deploy/style.css

+html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, b, cite, code, del, dfn, em, i, img, ins, kbd, q, samp, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  outline: 0;
+  font-size: 100%;
+  vertical-align: baseline;
+  background: transparent;
+}
+html { font-size: 100.01%; }
+caption, cite, code, dfn, th, var {
+  font-style: normal;
+  font-weight: normal;
+}
+h1, h2, h3, h4, h5, h6 { font-weight: normal; }
+blockquote, q { quotes: none; }
+blockquote:before {
+  content: '';
+  content: none;
+}
+blockquote:after {
+  content: '';
+  content: none;
+}
+q:before {
+  content: '';
+  content: none;
+}
+q:after {
+  content: '';
+  content: none;
+}
+:focus { outline: 0; }
+ins { text-decoration: underline; }
+del { text-decoration: line-through; }
+table {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
 body {
   background: #161616;
   color: #eeeeee;
   max-width: 36em;
   padding: 2em 3em;
 }
-#header h1 { margin-top: 0; }
-#header p { margin-top: 0; }
+#header h1 {
+  font-size: 1.5em;
+  margin-bottom: 1em;
+  text-align: center;
+  text-transform: uppercase;
+}
+#header h1 a { font-weight: normal; }
+#header p {
+  font-size: 1.5em;
+  margin-bottom: 1em;
+  text-align: center;
+  text-transform: uppercase;
+}
+#header p a { font-weight: normal; }
 #footer {
   border-top: 3px solid #3b3b3b;
   margin-top: 3em;
 }
 #footer .sep { color: #777777; }
+h1 { font-size: 1.5em; }
+h2 {
+  font-size: 1.25em;
+  line-height: 1.2;
+  font-weight: bold;
+  margin: 1.8em 0 0.6em;
+}
+p, dl { margin-bottom: 1.5em; }
+ul, ol { margin: 0 0 1.5em 1.5em; }
+blockquote {
+  border-left: 0.25em solid #333333;
+  margin: 0 1.5em 1.5em 0.5em;
+  padding-left: 0.75em;
+}
 p.time {
   color: #777777;
   font-size: 0.9em;

example-site/deploy/typography.html

     <div id="body">
       
 
+<h1>Typography</h1>
+
   <h2>
     <a href="/pilcrow/2009/lorem-ipsum.html">Lorem ipsum</a>
     (2009-Dec-07)

example-site/deploy/wikipedia.html

     <div id="body">
       
 
+<h1>Wikipedia</h1>
+
   <h2>
     <a href="/pilcrow/2009/turritopsis-nutricula.html">Turritopsis nutricula</a>
     (2009-Nov-24)

example-site/deploy/wtf.html

     <div id="body">
       
 
+<h1>WTF</h1>
+
   <h2>
     <a href="/pilcrow/2009/turritopsis-nutricula.html">Turritopsis nutricula</a>
     (2009-Nov-24)

example-site/files/_reset.less

+html, body, div, span, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, b, cite, code,
+del, dfn, em, i, img, ins, kbd, q, samp,
+strike, strong, sub, sup, tt, var,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td
+    {margin:0; padding:0; border:0; outline:0; font-size:100%;
+     vertical-align:baseline; background:transparent;}
+html {font-size:100.01%;}
+caption, cite, code, dfn, th, var {font-style:normal; font-weight:normal;}
+h1, h2, h3, h4, h5, h6 {font-weight:normal;}
+blockquote, q {quotes:none;}
+blockquote:before, blockquote:after, q:before, q:after {content:''; content:none;}
+:focus {outline:0;}
+ins {text-decoration:underline;}
+del {text-decoration:line-through;}
+table {border-collapse:collapse; border-spacing:0;} /* still needs cellspacing="0" */

example-site/files/style.less

+@import "_reset";
+
 @background: #222;
 @text: #eee;
 @link: #eb2;
 }
 
 #header {
-    h1, p { margin-top: 0; }
+    h1, p {
+        font-size: 1.5em;
+        margin-bottom: 1em;
+        text-align: center;
+        text-transform: uppercase;
+        a {
+            font-weight: normal;
+        }
+    }
 }
 
 #footer {
     .sep { color: @text / 2; }
 }
 
+h1 {
+    font-size: 1.5em;
+}
+
+h2 {
+    font-size: 1.25em;  line-height: 1.2;
+    font-weight: bold;
+    margin: 1.8em 0 0.6em;
+}
+
+p, dl {
+    margin-bottom: 1.5em;
+}
+
+ul, ol {
+    margin: 0 0 1.5em 1.5em;
+}
+
+blockquote {
+    border-left: 0.25em solid (@background * 1.5);
+    margin: 0 1.5em 1.5em 0.5em;
+    padding-left: 0.75em;
+}
+
 p.time {
     color: @text / 2;
     font-size: 0.9em;

example-site/templates/entry.html

 <%def name="footer()">
   <p>
     % if tags:
-      % for i, tag in enumerate(tags.values()):
+      % for i, tag in enumerate(tags_by_name()):
+        ${i and '<span class="sep">|</span>' or ''}
         <a href="${tag.url}">${tag.title}</a>
       % endfor
     % endif

example-site/templates/tag.html

 <%inherit file="_base.html"/>
 
+% if title:
+<h1>${title}</h1>
+% endif
+
 % for page in pages(tag=tag):
   <h2>
     <a href="${page.url}">${page.title or 'Untitled'}</a>
 Licensed under the terms of the MIT license.
 
 """
+import warnings
+warnings.simplefilter('ignore', DeprecationWarning)
+
+import sys
+
 import pilcrow
 
+
 if __name__ == '__main__':
-    pilcrow.main()
+    exitstatus = pilcrow.main()
+    sys.exit(exitstatus or 0)

pilcrow/__init__.py

 Licensed under the terms of the MIT license.
 
 """
+import sys
+if sys.version_info < (2, 6) or sys.version_info >= (3, 0):
+    msg = "only Python 2.6 is supported at the moment"
+    raise ImportError(msg)
+
+import locale
+locale.setlocale(locale.LC_ALL, '')
+
+import os
+
 from pilcrow import core, pages, util
 from pilcrow.core import Pilcrow
 
 
+__author__ = 'Liam Cooke'
+__copyright__ = 'Copyright (c) 2009 Liam Cooke'
+__license__ = 'MIT License'
+
+
 def main():
     import optparse
-    parser = optparse.OptionParser()
+    parser = optparse.OptionParser('usage: %prog [options] path_to_site')
+    parser.add_option('-x', '--clean', action='store_true', default=False)
+    parser.add_option('-t', '--test', action='store_true', default=False,
+                      help='open the site in your browser after building')
+    options, args = parser.parse_args()
 
-    parser.add_option('-x', '--clean', action='store_true', default=False)
+    if args:
+        site_path = args.pop(0)
+    else:
+        parser.print_help()
+        return 1
 
-    options, args = parser.parse_args()
-    site_path = args and args[0] or '.'
-    Pilcrow(site_path).build(clean=options.clean)
+    site = Pilcrow(site_path)
+    site.build(clean=options.clean)
+
+    if options.test:
+        import webbrowser
+        url = site.join_url(site.get('test_domain', 'http://localhost/'),
+                            site.get('test_root', site['root']), ext=False)
+        webbrowser.open_new_tab(url)
 
 """
 import codecs
+import locale
 import os
 import re
 import shutil
         'deploy': 'deploy',
     },
     'feed': 'feed.rss',
-    'files_exclude': r'(^\.|~$)',
+    'files_exclude': r'^[\._]|~$',
     'files_include': r'^\.htaccess$',
     'files_rename': {
         '.less': '.css',
         for page in self:
             t = page.template or self._site['default_template']
             template = self.lookup.get_template('%s.html' % t)
-            print '%14s : /%s' % (t, page.id)
+            print('%14s : /%s' % (t, page.id))
 
             vars = dict(self._site, **page)
             if vars['title']:
         '.less': lambda s, d: util.run_or_die('lessc %s %s' % (s, d)),
     }
 
-    def __init__(self, site_path='.', config_file=DEFAULT_CONFIG_FILE):
+    def __init__(self, site_path, config_file=DEFAULT_CONFIG_FILE):
         try: os.chdir(site_path)
         except OSError: util.die('invalid path:', site_path)
         if not path.exists(config_file):
             util.die('%s not found' % config_file)
 
         dict.__init__(self, DEFAULT_CONFIG)
+        self.update(locale.localeconv())
         with open(config_file) as f:
             for k, v in yaml.load(f).items():
                 k = util.norm_key(k)
                 if path.isfile(dest) and path.getmtime(src) <= path.getmtime(dest):
                     continue
                 self.FILES_ACTIONS.get(ext, shutil.copy2)(src, dest)
-                print '%s => %s' % (path.relpath(src, base_path), path.relpath(dest, base_path))
+                print('{0} => {1}'.format(path.relpath(src, base_path), path.relpath(dest, base_path)))
         os.chdir(base_path)
 
         db, years = PageDatabase(self), defaultdict(list)
         for root, _, files in os.walk(self['dirs']['content']):
             exts = ['.%s' % ext for ext in self['content_extensions']]
-            for file in filter(lambda f: path.splitext(f)[1] in exts, files):
+            for file in [f for f in files if path.splitext(f)[1] in exts]:
                 with codecs.open(path.join(root, file), 'r', encoding='utf-8') as fp:
                     page = pages.Content(self, fp)
                     db.add(page)
 
         for year, posts in sorted(years.items()):
             posts = sorted(posts, key=pages.Page.sortkey_origin)
-            db.add(pages.Archive(self, posts, year))
+            db.add(pages.Year(self, posts, year))
             for prevpost, post, nextpost in util.neighbours(posts):
                 post['prevpost'], post['nextpost'] = prevpost, nextpost
 
         'summary': lambda s: ''.join(BeautifulSoup(markdown(s)).findAll(text=True)),
     }
     SUMMARY = re.compile('(<summary>)(.*?)(</summary>)', re.DOTALL)
+
     backposted = lambda self: self.posted and self.posted.date() > self.date.date()
 
     def __init__(self, site, fp):
                 'month_name': self.date.strftime('%B'),
                 'prevpost': None,
                 'nextpost': None,
+                'tags_by_count': lambda: sorted(self.tags.values(), key=Tag.sortkey_count),
+                'tags_by_name': lambda: sorted(self.tags.values(), key=Tag.sortkey_tag),
             })
         if 'tags' in self._site:
             self['tags'] -= set((tag for tag in self.tags if tag not in self._site['tags']))
 
 
 class Archive(Page):
-    def __init__(self, site, entries, year, month=0):
+    def __init__(self, site, id, entries, year, month, attrs={}):
         id = site.join_url(year, month and '%02d' % month, ext=False)
         Page.__init__(self, site, id, {
             'entries': entries,
             'month': month,
             'template': 'archive_%s' % (month and 'month' or 'year'),
             'title': month and datetime(year, month, 1).strftime('%B %Y') or year,
+        }, **attrs)
+
+class Month(Archive):
+    def __init__(self, site, entries, year, month):
+        if not (1 <= month <= 12):
+            raise ValueError, 'month must be in the range 1-12'
+        id = site.join_url(year, '%02d' % month, ext=False)
+        Archive.__init__(self, site, id, entries, year, month, {
+            'title': datetime(year, month, 1).strftime('%B %Y'),
+        })
+
+class Year(Archive):
+    def __init__(self, site, entries, year):
+        Archive.__init__(self, site, year, entries, year, 0, {
+            'title': str(year),
         })
 
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.