# HG changeset patch # User Oben Sonne # Date 1573343020 -3600 # Sun Nov 10 00:43:40 2019 +0100 # Node ID 1454e383413744a42b24782dfdf166cf516bc076 # Parent e067410da3c30491fa7ab3f21fdd2278aafb0f5c Use sourcehut wiki for docs beyond README diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ 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 @@ 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 @@ 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 @@ > 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 @@ 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 diff --git a/docs/macros.md b/docs/macros.md deleted file mode 100644 --- a/docs/macros.md +++ /dev/null @@ -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 - - - - - -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>%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. diff --git a/docs/recipes.md b/docs/recipes.md deleted file mode 100644 --- a/docs/recipes.md +++ /dev/null @@ -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 = '%s > %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 - -`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 = """ - - %s - - """ - - _SITEMAP_URL = """ - - %s/%s - %s - %s - %s - - """ - - 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 = """ - - - %s - %s - %s - en-us - %s - %s - http://blogs.law.harvard.edu/tech/rss - Poole - %s - - - """ - - _RSS_ITEM = """ - - %s - %s - %s - %s - %s - - """ - - 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 -
- -
- -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 "%s (%d KiB)" % (matchobj.group(1), \ - matchobj.group(3), \ - size // 1024) - except: - print "Unable to estimate file size for %s" % matchobj.group(1) - return '%s' % (matchobj.group(1), \ - matchobj.group(3)) - - _re_url = '(.*?)<\/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. diff --git a/docs/sites.md b/docs/sites.md deleted file mode 100644 --- a/docs/sites.md +++ /dev/null @@ -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/) -- -- [ 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).* - diff --git a/docs/themes.md b/docs/themes.md deleted file mode 100644