5 files changed, 8 insertions(+), 553 deletions(-)
M README.md
R docs/macros.md =>
R docs/recipes.md =>
R docs/sites.md =>
R docs/themes.md =>
M README.md +8 -4
@@ 15,7 15,7 @@ done fast and easy -- if you know Python
Check the list of [sites built with Poole][examples] (and feel free to add
yours).
-[examples]: ./docs/sites.md
+[examples]: https://man.sr.ht/~obensonne/poole/sites.md
[markdown]: http://daringfireball.net/projects/markdown/
[pymd]: https://pypi.python.org/pypi/Markdown
@@ 49,7 49,7 @@ Next to the *minimal* theme, there are s
Run `poole --build` whenever you've made some changes in the *input* folder.
[tgz]: https://hg.sr.ht/~obensonne/poole/archive/tip.tar.gz
-[themes]: ./docs/themes.md
+[themes]: https://hg.sr.ht/~obensonne/poole/browse/default/themes
## How It Works
@@ 116,7 116,7 @@ property `tempalte` in the front matter
In that case the given file is used as the page template instead of the default
`page.html` file.
-[pimp]: http://obensonne.bitbucket.org/blog/20091122-using-a-free-css-templates-in-poole.html
+[pimp]: http://obensonne.com/blog/20091122-using-a-free-css-templates-in-poole.html
## Content Generation
@@ 187,6 187,10 @@ Currently, there is only one builtin mac
> However, since escaping it does not hurt within normal HTML, it is
> just escaped unconditionally.
+The [wiki goes a bit more into detail on macros][macros].
+
+[macros]: https://man.sr.ht/~obensonne/poole/macros.md
+
### Working with pages
Next to stuff defined in `macros.py` the objects `page` and `pages` are
@@ 349,7 353,7 @@ You can do some pretty fancy and useful
the macros module, for instance generate a list of blog posts or create an RSS
file. Check out the [example recipes][recipes].
-[recipes]: ./docs/recipes.md
+[recipes]: https://man.sr.ht/~obensonne/poole/recipes.md
## Feedback
R docs/macros.md => +0 -152
@@ 1,152 0,0 @@
-Macros
-------
-
-Though poole is made for simple websites you can add a thin layer of
-smartness to a site using macros.
-
-**Note:** If you end up using macros a lot and everywhere, you should
-have a look at more powerful site generator\'s like Jekyll or Hyde which
-realize the idea of processing logic much better and with a more clear
-distinction between logic, content and layout.
-
-### Macros as variables
-
-You can use macros to avoid writing some repetitive content again and
-again. Consider the following as the content of a page, let\'s say
-*some-page.md*, in your project\'s *input* folder:
-
-**some-page.md**:
-
- #!text
- # book_title: Fool
- # book_author: Moore
-
- Books
- -----
-
- My current favorite book is {{ book_title }} by {{ book_author }}.
- ...
- That is why I love *{{book_title}}*.
-
-At the beginning it defines 2 macros which are used later using *{{
-macro-name }}*. Macros defined within a page are only valid in the scope
-of that page. If you want to reference your currently favored book on
-other pages, you should define it as a *global* macro.
-
-To define global macros, create a file *macros.py* in the same folder
-where *page.html* is located and set your macros there:
-
-**macros.py**:
-
- #!python
- book_title = Fool
- book_author = Moore
-
-Now you can reference these macro in every page.
-
-What about a *today* macro, specifying the site build day:
-
-**macros.py:**
-
- #!python
- import datetime
- today = datetime.datetime.now().strftime("%Y-%m-%d")
-
-### Overriding global macros in pages
-
-A good use case for a global macro defined in *macors.py* is to set a
-description or some keywords for your site which can then be referenced
-in the *page.html* file, e.g.:
-
-**macros.py:**
-
- #!python
- # ...
- description = "a site about boo"
- keywords = "foo, bar"
- # ...
-
-**page.html:**
-
- #!html
- <!-- ... -->
- <meta name="description" content="{{ description }}">
- <meta name="keywords" content="{{ keywords }}">
- <!-- ... -->
-
-For individual pages you can override these settings, for instance:
-
-**some-page.md:**
-
- #!text
- # keywords: foo, baz
- ...
-
-Page macro definitions override global macro definitions in *macros.py*!
-
-### Dynamically generated content
-
-In *macros.py* you can define functions which then can be referenced as
-macros. Here\'s a simple and useless example:
-
-**macros.py**:
-
- #!python
- def asum(pages, page, a="0", b="1"):
- return int(a) + int(b)
-
-**some-page.md:**
-
- #!text
- ...
- The sum of 1 and 5 is {{ asum a=1 b=5 }}.
- ...
-
-This will be replaced by, suprise, *6*.
-
-Macro function in must have at least 2 parameters:
-
-1. *pages*: a list of all pages in the site processed by *poole*
-2. *page*: the current page where this macro is used
-
-Additional parameters must be declared as keword arguments.
-
-The objects in *pages* as well as *page* itself are Page objects which
-have the following public fields:
-
-- *name*: name of the page (either the file name without extension or
- the value of the `name` macro, if defined within the page\'s source
- file
-- *macros*: a dictionary of all macros defined for the page (including
- global macros defined in *macro.py*)
-- *url*: URL to link to that page
-
-Here is a more complex example, the built-in *menu* macro used in the
-default *page.html/ file to display a navigation menu:*
-
- #!python
- def menu(pages, page, tag="span", current="current"):
- """Compile an HTML list of pages to appear as a navigation menu.
-
- Any page which has a macro {{{menu_pos}}} defined is included. Menu
- positions are sorted by the integer values of {{{menu_pos}}} (smallest
- first).
-
- The current page's //tag// element is assigned the CSS class //current//.
-
- """
- menu_pages = [p for p in self.pages if "menu_pos" in p.macros]
- menu_pages.sort(key=lambda p: int(p.macros["menu_pos"]))
-
- html = ''
- for p in menu_pages:
- style = p == self.__page and (' class="%s"' % current) or ''
- html += '<%s%s><a href="%s">%s</a></%s>' % (tag, style, p.url, p.name, tag)
- return html
-
-You can write your own *menu* macro in *macros.py*, if you don\'t like
-the built-in one.
-
-### Limitations
-
-Macros are not nestable.
R docs/recipes.md => +0 -368
@@ 1,368 0,0 @@
-Recipes
-=======
-
-\* Fancy things you can do with Poole. *
-
-[Navigation Menu](Recipes#!navigation-menu) ·
-[Breadcrumb Navigation](Recipes#!breadcrumb-navigation) ·
-[List of Blog Posts](Recipes#!list-of-blog-posts) ·
-[Google Sitemap File](Recipes#!google-sitemap-file) ·
-[RSS Feed for Blog Posts](Recipes#!rss-feed-for-blog-posts) ·
-[Multiple Languages Support](Recipes#!multiple-languages-support) ·
-[Link File Size](Recipes#!link-file-size)
-
-Feel free to add yours!
-
-------------------------------------------------------------------------
-
-Navigation Menu
----------------
-
-Have a look into the `page.html` file in a freshly initialized Poole
-project.
-
-------------------------------------------------------------------------
-
-Breadcrumb Navigation
----------------------
-
-To add breadcrumb navigation, put this into the project\'s `macros.py`
-file:
-
- #!python
- def breadcrumb():
- parents = {p.title: (p.url, p.get('parent')) for p in pages}
- title = page.title
- output = hx(title)
- while parents[title][1] is not None:
- title = parents[title][1]
- url = parents[title][0]
- output = '<a href="%s">%s</a> > %s' % (url, hx(title), output)
- return output
-
-For each page that has a parent, set the page attribute `parent` to the
-`title` of the parent page. The breadcrumb trail can then be included by
-specifying `{{ breadcrumb() }}` in your `page.html` (or elsewhere).
-
-------------------------------------------------------------------------
-
-List of Blog Posts
-------------------
-
-If you want to write some blog posts, you probably would like to have a
-page listing all or the latest blog posts. This is easy if you set
-certain page attributes in every blog post page:
-
-`input/brain-on-mongs.md`:
-
- title: blog
- post: This is your brain on mongs
- date: 2010-03-01
- ---
-
- # {{ page.post }}
-
- Posted on {{ page.date }}
-
- My hero is full of keyboards. Get nonsense at <http://automeme.net/>
-
-`input/blog.md`:
-
- This is my blog.
-
- # My posts
-
- {%
- from datetime import datetime
- posts = [p for p in pages if "post" in p] # get all blog post pages
- posts.sort(key=lambda p: p.get("date"), reverse=True) # sort post pages by date
- for p in posts:
- date = datetime.strptime(p["date"], "%Y-%m-%d").strftime("%B %d, %Y")
- print " * **[%s](%s)** - %s" % (p.post, p.url, date) # markdown list item
- %}
-
-Feel free to adjust this to your needs.
-
-**TIP:** Instead of setting the post title and date as page attributes,
-you can encode them in the page\'s file name using a structure like
-`page-title.YYYY-MM-DD.post-title.md`. For instance for the file name
-`blog.2010-03-01.This_is_your_brain_on_mongs.md` Poole would
-automatically set the page attributes which has been set manually in the
-example above.
-
-To see this example in action, have a look into the example pages in a
-freshly initialized Poole project.
-
-------------------------------------------------------------------------
-
-Google Sitemap File
--------------------
-
-To generate a Google `sitemap.xml` file, put this into the project\'s
-`macros.py` file:
-
- #!python
- from datetime import datetime
- import os.path
-
- _SITEMAP = """<?xml version="1.0" encoding="UTF-8"?>
- <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
- %s
- </urlset>
- """
-
- _SITEMAP_URL = """
- <url>
- <loc>%s/%s</loc>
- <lastmod>%s</lastmod>
- <changefreq>%s</changefreq>
- <priority>%s</priority>
- </url>
- """
-
- def hook_preconvert_sitemap():
- """Generate Google sitemap.xml file."""
- date = datetime.strftime(datetime.now(), "%Y-%m-%d")
- urls = []
- for p in pages:
- urls.append(_SITEMAP_URL % (options.base_url.rstrip('/'), p.url, date,
- p.get("changefreq", "monthly"), p.get("priority", "0.8")))
- fname = os.path.join(options.project, "output", "sitemap.xml")
- fp = open(fname, 'w')
- fp.write(_SITEMAP % "".join(urls))
- fp.close()
-
-You probably want to adjust the default values for *changefreq* and
-*priority*.
-
-**Info:** Every function in `macros.py` whose name starts with
-`hook_preconvert_` or `hook_postconvert_` is executed exactly once per
-project build \-- either before or after converting pages from markdown
-to HTML. In post-convert hooks the HTML content of a page (yet without
-header and footer) can be accessed with `page.html`. This is useful to
-generate full-content RSS feeds.
-
-------------------------------------------------------------------------
-
-RSS Feed for Blog Posts
------------------------
-
-To generate an RSS feed for blog posts put this into the project\'s
-`macros.py` file and adjust for your site:
-
- #!python
- import email.utils
- import os.path
- import time
-
- _RSS = """<?xml version="1.0"?>
- <rss version="2.0">
- <channel>
- <title>%s</title>
- <link>%s</link>
- <description>%s</description>
- <language>en-us</language>
- <pubDate>%s</pubDate>
- <lastBuildDate>%s</lastBuildDate>
- <docs>http://blogs.law.harvard.edu/tech/rss</docs>
- <generator>Poole</generator>
- %s
- </channel>
- </rss>
- """
-
- _RSS_ITEM = """
- <item>
- <title>%s</title>
- <link>%s</link>
- <description>%s</description>
- <pubDate>%s</pubDate>
- <guid>%s</guid>
- </item>
- """
-
- def hook_postconvert_rss():
- items = []
- posts = [p for p in pages if "post" in p] # get all blog post pages
- posts.sort(key=lambda p: p.date, reverse=True)
- for p in posts:
- title = p.post
- link = "%s/%s" % (options.base_url.rstrip("/"), p.url)
- desc = p.get("description", "")
- date = time.mktime(time.strptime("%s 12" % p.date, "%Y-%m-%d %H"))
- date = email.utils.formatdate(date)
- items.append(_RSS_ITEM % (title, link, desc, date, link))
-
- items = "".join(items)
-
- # --- CHANGE THIS --- #
- title = "Maximum volume yields maximum moustaches"
- link = "%s/blog.html" % options.base_url.rstrip("/")
- desc = "My name is dragonforce. You killed my dragons. Prepare to scream."
- date = email.utils.formatdate()
-
- rss = _RSS % (title, link, desc, date, date, items)
-
- fp = open(os.path.join(output, "rss.xml"), 'w')
- fp.write(rss)
- fp.close()
-
-------------------------------------------------------------------------
-
-Multiple languages support
---------------------------
-
-To make your website available in several languages, put this into the
-project\'s `macros.py` file:
-
- #!python
-
- import re
- import itertools
-
-
- def hook_preconvert_multilang():
- MKD_PATT = r'\.(?:md|mkd|mdown|markdown)$'
- _re_lang = re.compile(r'^[\s+]?lang[\s+]?[:=]((?:.|\n )*)', re.MULTILINE)
- vpages = [] # Set of all virtual pages
- for p in pages:
- current_lang = "en" # Default language
- langs = [] # List of languages for the current page
- page_vpages = {} # Set of virtual pages for the current page
- text_lang = re.split(_re_lang, p.source)
- text_grouped = dict(zip([current_lang,] + \
- [lang.strip() for lang in text_lang[1::2]], \
- text_lang[::2]))
-
- for lang, text in text_grouped.iteritems():
- spath = p.fname.split(os.path.sep)
- langs.append(lang)
- filename = re.sub(MKD_PATT, ".%s\g<0>" % lang, p.fname).split(os.path.sep)[-1]
- vp = Page(filename, virtual=text)
- # Copy real page attributes to the virtual page
- for attr in p:
- if not vp.has_key(attr):
- vp[attr] = p[attr]
- # Define a title in the proper language
- vp["title"] = p["title_%s" % lang] \
- if p.has_key("title_%s" % lang) \
- else p["title"]
- # Keep track of the current lang of the virtual page
- vp["lang"] = lang
- # Fix post name if exists
- if vp.has_key("post"):
- vp["post"] = vp["post"][:-len(lang) - 1]
- page_vpages[lang] = vp
-
- # Each virtual page has to know about its sister vpages
- for lang, vpage in page_vpages.iteritems():
- vpage["lang_links"] = dict([(l, v["url"]) for l, v in page_vpages.iteritems()])
- vpage["other_lang"] = langs # set other langs and link
-
- vpages += page_vpages.values()
-
- pages[:] = vpages
-
-Then make the following modifications in `page.html`:
-
- #!python
-
- mpages = [p for p in pages if "menu-position" in p]
-
-becomes
-
- #!python
-
- mpages = [p for p in pages if "menu-position" in p and p.has_key("lang") and p["lang"] == page["lang"]]
-
-Add the language list by adding this code in `page.html`, for example at
-the end of the div menu:
-
- #!html
- <div id="lang">
- <!--%
- print " | ".join(["<span><a href='%s'>%s</a></span>" % \
- (url, lang) for lang, url in page["lang_links"].iteritems()])
- %-->
- </div>
-
-Adjust the `poole.css` file by adding something like:
-
- #!css
- div#lang {
- float:right;
- text-align:right;
- color: white;
- }
-
-Finally, if you want to show blog pages of the current language only,
-replace:
-
- #!python
-
- posts = [p for p in pages if "post" in p] # get all blog post pages
-
-with
-
- #!python
-
- posts = [p for p in pages if "post" in p if p.lang == page.lang] # get all blog post pages
-
-in `blog.md` (or whatever your blog file is).
-
-### Usage
-
-The directive `lang: lang_name` (where `lang_name` can be any language
-code, typically according to
-[ISO 639-1](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes))
-separate different languages of the same page. The attribute
-`title_lang_name` can be used to translate the title page (which may be
-displayed in the menu). Example:
-
-`input/stuff/news.md:`
-
- title: Hot News
- title_fr: Nouvelles
- foobar: King Kong
- ---
- Here are some news about {{ page.foobar }}.
- Did I say {% print(page.foobar) %}?
-
- lang: fr
-
- Voici quelques nouvelles a propos de {{ page.foobar }}.
- Ai-je bien dit {% print(page.foobar) %} ?
-
-The first block will always take the default language (which can be
-changed in the hook above).
-
-------------------------------------------------------------------------
-
-Link File Size
---------------
-
-For people with slow internet access, or simply to inform the visitor
-about the size of a downloadable file on your poole web site, you can
-use the following postconvert hook:
-
- #!python
- def hook_postconvert_size():
- file_ext = '|'.join(['pdf', 'eps', 'ps'])
- def matched_link(matchobj):
- try:
- # We assume a relative link to a document in the output directory of poole.
- size = os.path.getsize(os.path.join("output", matchobj.group(1)))
- return "<a href=\"%s\">%s</a> (%d KiB)" % (matchobj.group(1), \
- matchobj.group(3), \
- size // 1024)
- except:
- print "Unable to estimate file size for %s" % matchobj.group(1)
- return '<a href=\"%s\">%s</a>' % (matchobj.group(1), \
- matchobj.group(3))
-
- _re_url = '<a href=\"(.*?\.(%s))\">(.*?)<\/a>' % file_ext
- for p in pages:
- p.html = re.sub(_re_url, matched_link, p.html)
-
-It will add the file size in KiB, right after the link, for the file
-extensions specified in the second line.
R docs/sites.md => +0 -29
@@ 1,29 0,0 @@
-Websites built with Poole
--------------------------
-
-- [twentyweeks.com](https://twentyweeks.com)
-- [bertjwregeer.com](http://bertjwregeer.com/index.html)
-- [chistoe-nebo.info](http://www.chistoe-nebo.info/)
-- [evanchen.cc](http://web.evanchen.cc/)
-- [hpi.uni-potsdam.de/giese/events/2011/seams2011](http://www.hpi.uni-potsdam.de/giese/events/2011/seams2011/index.html)
-- [i-for-change.co.uk](http://www.i-for-change.co.uk)
-- [jcby.com](http://jcby.com/index.html)
-- [land.umonkey.net](http://land.umonkey.net/)
-- <http://adiultra.github.io/lynx/index.html>
-- [ mechatronics3d.com](http://www.mechatronics3d.com)
-- [monitoring-plugins.org](http://www.monitoring-plugins.org/)
-- [obensonne.bitbucket.org](http://obensonne.bitbucket.org/)
-- [paulbarker.me.uk](http://www.paulbarker.me.uk)
-- [profgra.org/lycee](http://profgra.org/lycee/)
-- [rpedroso.github.com/sharme](http://rpedroso.github.com/sharme)
-- [serge.liyun.free.fr/serge](http://serge.liyun.free.fr/serge/index.html)
-- [taecilla.github.io](http://taecilla.github.io/)
-- [thpani.at](http://thpani.at/)
-- [translation.baham.co](https://translation.baham.co)
-- [ultimatehurl.com](http://ultimatehurl.com/index.html)
-- [ece.mcgill.ca/\~\~tnorth](http://www.ece.mcgill.ca/~tnorth/)
-- [xythobuz.de](http://xythobuz.de)
-
-*This list is in alphabetical order. Feel free to add your site (or
-remove it if the addition by someone else is not your will).*
-
R docs/themes.md => +0 -0