--- I have extended the starter layout with advanced topics, especially the sorter, grouper and tagger plugins. Content is updated. Navigation, code styling and text readability are improved.main
@@ -154,7 +154,7 @@ class TaggerPlugin(Plugin): | |||||
if not 'template' in config: | if not 'template' in config: | ||||
raise self.template.exception_class( | raise self.template.exception_class( | ||||
"No Template sepecified in tagger configuration.") | |||||
"No Template specified in tagger configuration.") | |||||
source = content.node_from_relative_path(config.get('source', '')) | source = content.node_from_relative_path(config.get('source', '')) | ||||
target = self.site.config.deploy_root_path.child_folder( | target = self.site.config.deploy_root_path.child_folder( | ||||
config.get('target', 'tags')) | config.get('target', 'tags')) | ||||
@@ -0,0 +1,49 @@ | |||||
--- | |||||
index: 3 | |||||
title_ending: "| Grouping" | |||||
tags: | |||||
- sort | |||||
- group | |||||
learning_order: 2 | |||||
--- | |||||
Grouping | |||||
======== | |||||
Content is very often grouped by theme, size, location or any other | |||||
conceivable measure. Groups can be traversed in a few ways in Hyde, and | |||||
[sorted](sorter.html) at the same time. Here are two common ways: | |||||
Walking all groups and subgroups | |||||
-------------------------------- | |||||
{# Resources are sorted by defining a sorter in the configuration file. #} | |||||
{% for grp, res_walker in site.content.walk_level_groups() %} | |||||
*{{ grp.description }}* | |||||
{% for res in res_walker %} | |||||
* [{{ res.slug|capitalize|replace("-"," ") }}]({{ res.full_url }}) \ | |||||
({{ res.name }}) | |||||
{% endfor %} | |||||
{% endfor %} | |||||
{# The above code layout is not arbitrary. Remember that we're building | |||||
a Markdown page so every space or line ending has a purpose. | |||||
#} | |||||
Listing only the specific (sub)group | |||||
------------------------------------ | |||||
{% for res in site.content.walk_resources_grouped_by_advanced() %} | |||||
* [{{ res.slug|capitalize|replace("-"," ") }}]({{ res.full_url }}) \ | |||||
({{ res.name }}) | |||||
{% endfor %} | |||||
{# You can also call the top level group "level" to get all resources that | |||||
are in the group. Or you can list all resources of the same group in the | |||||
current node with "resource.node.walk_resource_grouped_by_advanced()". | |||||
#} | |||||
{{ macros.render_bottom_article_nav() }} |
@@ -0,0 +1,3 @@ | |||||
extends: base.j2 | |||||
default_block: content | |||||
level: advanced |
@@ -0,0 +1,44 @@ | |||||
--- | |||||
index: 1 | |||||
title_ending: "| Advanced topics" | |||||
tags: | |||||
- sort | |||||
- group | |||||
- tag | |||||
learning_order: 4 | |||||
--- | |||||
More advanced topics | |||||
==================== | |||||
If you have read and understood all basic topics covered in | |||||
{% for res in site.content.walk_resources_grouped_by_basic()|reverse %} | |||||
[{{ res.slug|capitalize|replace("-"," ") }}]({{ res.full_url }}) | |||||
{% endfor %} | |||||
then you are ready for some more advanced features. They are explained in | |||||
the same way as the basic part, building on the knowledge of the previous, | |||||
so it is recommended that you follow them in the listed order. | |||||
{# List all resources from a group, sort them by index and list their tags. #} | |||||
{% for res in resource.node.walk_resources_sorted_by_learning_order() %} | |||||
{{ loop.index }}. \ | |||||
[{{ res.slug|capitalize|replace("-"," ") }}]({{ res.full_url }}) \ | |||||
{% if res.name == "overview.html" %}*(this file)*{% endif %} \ | |||||
{# | |||||
Sometimes you'll have to add HTML tags to a Markdown file for styling | |||||
or adding some special features, and Markdown is OK with that. | |||||
#} | |||||
<span class="tags">tags: | |||||
{% for tag in res.meta.tags %} | |||||
{# | |||||
After wring the tag name, check if that is the last tag in the list. If | |||||
it is, don't append the comma at the end. | |||||
#} | |||||
{{ tag }}{% if tag != res.meta.tags[-1] %},{% endif %} | |||||
{% endfor %} | |||||
</span> | |||||
{% endfor %} | |||||
{{ macros.render_bottom_article_nav() }} |
@@ -0,0 +1,53 @@ | |||||
--- | |||||
index: 2 | |||||
title_ending: "| Sorting" | |||||
tags: | |||||
- sort | |||||
learning_order: 1 | |||||
--- | |||||
Sorting | |||||
======= | |||||
There will come a time when you will need to list and sort resources. Hyde | |||||
allows you to walk the site tree and sort the resources by the predefined | |||||
settings in your configuration file. | |||||
You can list and sort by name all your content files. | |||||
{# With every sorter defined in the configuration file, nodes get a method | |||||
to call. Notice that in the first and last example the method is called | |||||
on the whole content of the site, while the second example shows how to | |||||
invoke it only on one specific node (in this case the current one). | |||||
Also, some new Jinja filters were used to style the output. | |||||
#} | |||||
{% for res in site.content.walk_resources_sorted_by_name() %} | |||||
* [{{ res.slug|capitalize|replace("-"," ") }}]({{ res.full_url }}) \ | |||||
({{ res.name }}) | |||||
{% endfor %} | |||||
Or list only those in the current node (folder). In this case that would be | |||||
all advanced topics. | |||||
{# Have in mind that using the next example in a content page (like here) or | |||||
using it in a layout (Jinja template that is extended or include by | |||||
content pages) will yield very different results. | |||||
In this case it will be called only once, for this resource, and shown | |||||
only on this page. If it was in a layout, it would be called for EVERY | |||||
resource that uses that layout. In that case the context would be | |||||
different, the parent node of the resource could be different and the | |||||
results will probably be different too. | |||||
#} | |||||
{% for res in resource.node.walk_resources_sorted_by_index() %} | |||||
{{ loop.index }}. [{{ res.slug|capitalize }}]({{ res.full_url }}) | |||||
{% endfor %} | |||||
Or sort files by type and then by size. | |||||
{% for res in site.content.walk_resources_sorted_by_file_type() %} | |||||
* [{{ res.source_file.kind|upper }}] {{ res.name }} | |||||
{% endfor %} | |||||
{{ macros.render_bottom_article_nav() }} |
@@ -0,0 +1,51 @@ | |||||
--- | |||||
index: 4 | |||||
title_ending: "| Tagging" | |||||
tags: | |||||
- sort | |||||
- tag | |||||
learning_order: 3 | |||||
--- | |||||
Tagging | |||||
======= | |||||
It seems that human beings want to tag everything. You can do it with | |||||
Hyde also. In this example **tags** are used to represent technologies | |||||
used to build a particular advanced page. So you can see that the | |||||
**sorting** was needed for all advanced topics, but **grouping** was | |||||
used only for overview and grouping pages. | |||||
Listing by tags | |||||
--------------- | |||||
{# You can grab the list of all tags ... #} | |||||
{% for tag, meta in site.tagger.tags %} | |||||
*{{ tag }}* | |||||
{# ... and get all resurces tagged with that node. #} | |||||
{% for res in resource.node.walk_resources_tagged_with(tag) %} | |||||
* [{{ res.slug|capitalize|replace("-"," ") }}]({{ res.full_url }}) \ | |||||
({{ res.name }}) | |||||
{% endfor %} | |||||
{% endfor %} | |||||
{# Another way to walk through resources tagged with a specific tag is | |||||
to use a method that contains that tag's name. | |||||
{% for res in resource.node.walk_resources_tagged_with_sort() %} | |||||
{% endfor %} | |||||
#} | |||||
Tag combination | |||||
--------------- | |||||
You can also search for combination of tags. If you search for a | |||||
resource that has **sort**, **tag** and **group** tags, only an | |||||
{% for res in resource.node.walk_resources_tagged_with('sort+tag+group') -%} | |||||
[{{ res.slug }}]({{ res.full_url }}) | |||||
{%- endfor %} | |||||
will be returned. | |||||
{{ macros.render_bottom_article_nav() }} |
@@ -1,6 +1,6 @@ | |||||
--- | --- | ||||
extends: base.j2 | extends: base.j2 | ||||
title_ending: "| What next" | |||||
title_ending: "| First steps" | |||||
--- | --- | ||||
{# In-file metadata. Supplements data from the site's configuration file | {# In-file metadata. Supplements data from the site's configuration file | ||||
and node (folder) level data in "meta.yaml" files. | and node (folder) level data in "meta.yaml" files. | ||||
@@ -11,8 +11,8 @@ title_ending: "| What next" | |||||
#} | #} | ||||
{% block content %} | {% block content %} | ||||
There and back again | |||||
==================== | |||||
Walk this way if you're a beginner | |||||
================================== | |||||
This template was created to look at its code. So you should spend about | This template was created to look at its code. So you should spend about | ||||
5% of your time looking at the web from the outside and the other 95% | 5% of your time looking at the web from the outside and the other 95% | ||||
@@ -29,24 +29,24 @@ previous one. | |||||
---------------------------------------- | ---------------------------------------- | ||||
The site is made of two folders and a [Hyde configuration][hyde_config] | The site is made of two folders and a [Hyde configuration][hyde_config] | ||||
file. The folders are _content_ and _layout_. | |||||
file. The folders are **content** and **layout**. | |||||
_content_ contains all your page content, blog articles, pictures and | |||||
**content** contains all your page content, blog articles, pictures and | |||||
resources like CSS and JavaScript. Everything that is unique is here. | resources like CSS and JavaScript. Everything that is unique is here. | ||||
_layout_ contains templates and macros. Everything that you'll want to | |||||
**layout** contains templates and macros. Everything that you'll want to | |||||
reuse is here. | reuse is here. | ||||
2. Jinja2 template | 2. Jinja2 template | ||||
------------------ | ------------------ | ||||
_base.j2_ is a very short and simple Jinja2 template. This way you can | |||||
**base.j2** is a very short and simple Jinja2 template. This way you can | |||||
concentrate on some of the basic features. Notice meta and context | concentrate on some of the basic features. Notice meta and context | ||||
variables invocation inside curly braces, dynamic media path generation | variables invocation inside curly braces, dynamic media path generation | ||||
and running all content through the Markdown filter. | and running all content through the Markdown filter. | ||||
_macros.j2_ contains a macro for generating the main menu. | |||||
**macros.j2** contains macros for common and repetitive tasks. | |||||
For more information or to try something new, visit the extensive [Jinja2 | For more information or to try something new, visit the extensive [Jinja2 | ||||
documentation][jinja2_docs]. | documentation][jinja2_docs]. | ||||
@@ -55,19 +55,31 @@ documentation][jinja2_docs]. | |||||
3. Content | 3. Content | ||||
---------- | ---------- | ||||
Look at the three files in this order: _index.html_, _what-next.html_ | |||||
and _about.html_. | |||||
Look at the three files in this order: [index.html](index.html), | |||||
[first-steps.html](first-steps.html) and [about.html](about.html). | |||||
_Index_ extends the base layout in the classic Jinja way and fills the | |||||
content block with some simple Markdown data. | |||||
[Index](index.html) extends the base layout in the classic Jinja way and | |||||
fills the content block with some simple Markdown data. | |||||
_What next_ goes a step furher. It introduces the in-file metadata that | |||||
plugins will use to extend and fill the layout. It also uses some new | |||||
Markdown features. | |||||
[First steps](first-steps.html) goes a step furher. It introduces the | |||||
in-file metadata that plugins will use to extend and fill the layout. It | |||||
also uses some new Markdown features. | |||||
_About_ has a _default_block_ metadata and mixes Markdown content with | |||||
Jinja templates. | |||||
[About](about.html) has a **default_block** metadata and mixes Markdown | |||||
content with Jinja templates. | |||||
[hyde_config]: http://hyde.github.com/config.html "Hyde configuration" | [hyde_config]: http://hyde.github.com/config.html "Hyde configuration" | ||||
[jinja2_docs]: http://jinja.pocoo.org/docs/templates/ "Jinja2 documentation" | [jinja2_docs]: http://jinja.pocoo.org/docs/templates/ "Jinja2 documentation" | ||||
4. Advanced sections | |||||
-------------------- | |||||
While searching and navigating this template you'll find more files and | |||||
sections than mentioned on this page (something like **meta.yaml** | |||||
files, the **content/advanced** folder or other Jinja templates). They | |||||
are files needed for the [advanced topics](advanced/overview.html) so | |||||
just ignore them at the beginning. They will start to make sense while | |||||
you're working through the template or will be explicitly explained when | |||||
the right time comes. | |||||
{% endblock %} | {% endblock %} |
@@ -18,4 +18,6 @@ technologies step by step. Those are: | |||||
* Jinja templates | * Jinja templates | ||||
* Markdown | * Markdown | ||||
* basic metadata and plugins | * basic metadata and plugins | ||||
Are you ready for your [first steps](first-steps.html)? | |||||
{% endblock %} | {% endblock %} |
@@ -4,7 +4,7 @@ | |||||
} | } | ||||
html, body { | html, body { | ||||
color: #fafafa; | |||||
color: #ddd; | |||||
background-color: black; | background-color: black; | ||||
} | } | ||||
@@ -20,6 +20,10 @@ body { | |||||
font-family: Tahoma, sans-serif; | font-family: Tahoma, sans-serif; | ||||
} | } | ||||
strong { | |||||
color: white; | |||||
} | |||||
a { | a { | ||||
color: #f1ee00; | color: #f1ee00; | ||||
} | } | ||||
@@ -28,11 +32,11 @@ a:hover, a:focus { | |||||
text-decoration: none; | text-decoration: none; | ||||
} | } | ||||
p, ul { | |||||
p, ul, ol { | |||||
margin-bottom: 1.6em; | margin-bottom: 1.6em; | ||||
} | } | ||||
ul { | |||||
ul, ol { | |||||
margin-left: 2em; | margin-left: 2em; | ||||
} | } | ||||
@@ -49,6 +53,7 @@ header h1 { | |||||
font-size: 50px; | font-size: 50px; | ||||
font-weight: normal; | font-weight: normal; | ||||
text-shadow: -1px 2px 1px black; | text-shadow: -1px 2px 1px black; | ||||
color: white; | |||||
} | } | ||||
header h1 span { | header h1 span { | ||||
@@ -60,13 +65,14 @@ header h2 { | |||||
font-weight: normal; | font-weight: normal; | ||||
letter-spacing: 11px; | letter-spacing: 11px; | ||||
text-shadow: -1px 2px 1px black; | text-shadow: -1px 2px 1px black; | ||||
color: white; | |||||
} | } | ||||
nav { | nav { | ||||
position: absolute; | position: absolute; | ||||
top: 340px; | top: 340px; | ||||
right: 120px; | right: 120px; | ||||
width: 200px; | |||||
width: 250px; | |||||
text-align: right; | text-align: right; | ||||
font-family: Anton, Tahoma, sans-serif; | font-family: Anton, Tahoma, sans-serif; | ||||
} | } | ||||
@@ -74,7 +80,7 @@ nav { | |||||
nav a, | nav a, | ||||
nav a:visited { | nav a:visited { | ||||
text-decoration: none; | text-decoration: none; | ||||
color: #fafafa; | |||||
color: white; | |||||
text-transform: uppercase; | text-transform: uppercase; | ||||
font-size: 2.8em; | font-size: 2.8em; | ||||
} | } | ||||
@@ -121,6 +127,7 @@ nav, aside { | |||||
font-family: Anton, Tahoma, sans-serif; | font-family: Anton, Tahoma, sans-serif; | ||||
text-transform: uppercase; | text-transform: uppercase; | ||||
margin-bottom: 0.8em; | margin-bottom: 0.8em; | ||||
color: white; | |||||
} | } | ||||
#content h2 { | #content h2 { | ||||
@@ -128,6 +135,8 @@ nav, aside { | |||||
font-size: 1.2em; | font-size: 1.2em; | ||||
font-family: Tahoma, sans-serif; | font-family: Tahoma, sans-serif; | ||||
margin-bottom: 1.33em; | margin-bottom: 1.33em; | ||||
color: white; | |||||
border-bottom: 1px dashed #888; | |||||
} | } | ||||
#content code { | #content code { | ||||
@@ -142,3 +151,19 @@ nav, aside { | |||||
border-bottom: 1px solid #222; | border-bottom: 1px solid #222; | ||||
border-left: 1px solid #111; | border-left: 1px solid #111; | ||||
} | } | ||||
#content .tags { | |||||
font-size: 0.8em; | |||||
color: #888; | |||||
} | |||||
#content .bottom_article_nav { | |||||
border-top: 1px dashed #888; | |||||
overflow: hidden; | |||||
margin-top: 40px; | |||||
padding-top: 10px; | |||||
} | |||||
#content .bottom_article_nav .next { | |||||
float: right; | |||||
} |
@@ -0,0 +1,2 @@ | |||||
level: basic | |||||
@@ -22,8 +22,8 @@ | |||||
way it can be used to generate the list many times, in | way it can be used to generate the list many times, in | ||||
a footer, etc. | a footer, etc. | ||||
#} | #} | ||||
{% from "macros.j2" import render_main_menu with context %} | |||||
{{ render_main_menu() }} | |||||
{% import "macros.j2" as macros with context %} | |||||
{{ macros.render_main_menu() }} | |||||
</nav> | </nav> | ||||
<article id="content"> | <article id="content"> | ||||
{# Main content block. Notice it has to pass through the | {# Main content block. Notice it has to pass through the | ||||
@@ -38,5 +38,15 @@ | |||||
<p>Created by <a href="{{ author.url}}">{{ author.name}}</a> | <p>Created by <a href="{{ author.url}}">{{ author.name}}</a> | ||||
for <a href="{{ project.url }}">{{ project.name }}</a></p> | for <a href="{{ project.url }}">{{ project.name }}</a></p> | ||||
</aside> | </aside> | ||||
{# Some parts of the web are not needed for development and can | |||||
wait for production (ex. analytics). They can be included in | |||||
the final production build. Create a new config file, extend | |||||
the original one and override the "mode" property; then build | |||||
the site with the new "production configuration". | |||||
#} | |||||
{% if site.config.mode == "production" -%} | |||||
{% include "ga.j2" %} | |||||
{%- endif %} | |||||
</body> | </body> | ||||
</html> | </html> |
@@ -0,0 +1,13 @@ | |||||
<script type="text/javascript"> | |||||
var _gaq = _gaq || []; | |||||
_gaq.push(['_setAccount', '{{ site.meta.ga_tracking_code }}']); | |||||
_gaq.push(['_trackPageview']); | |||||
(function() { | |||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | |||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | |||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | |||||
})(); | |||||
</script> |
@@ -1,7 +1,35 @@ | |||||
{% macro render_main_menu() -%} | {% macro render_main_menu() -%} | ||||
{# Set menu item selected if the current resource matches the item in the | |||||
site's config file or set "Advanced topics" selected for any resources | |||||
that have the "advanced" folder as their parent. | |||||
#} | |||||
<ul> | <ul> | ||||
{% for menu_item in menu -%} | {% for menu_item in menu -%} | ||||
<li><a {% if menu_item.url == resource.url %}class="selected"{% endif %} href="{{ menu_item.url }}">{{ menu_item.title }}</a></li> | |||||
<li><a {% if (menu_item.url == resource.full_url) or | |||||
(menu_item.title == "Advanced topics" | |||||
and resource.node.name == "advanced") | |||||
%}class="selected"{% endif %} | |||||
href="{{ menu_item.url }}">{{ menu_item.title }}</a></li> | |||||
{%- endfor %} | {%- endfor %} | ||||
</ul> | </ul> | ||||
{%- endmacro %} | {%- endmacro %} | ||||
{# Advanced topics macro. Renders navigation at the end of the article. #} | |||||
{% macro render_bottom_article_nav() %} | |||||
<div class="bottom_article_nav"> | |||||
{% if resource.next_by_index is not none -%} | |||||
<div class="next"><a href="{{ resource.next_by_index.full_url }}"> | |||||
{{ resource.next_by_index.meta.title_ending|replace("| ", "") }}</a> | |||||
></div> | |||||
{%- endif %} | |||||
{% if resource.prev_by_index is not none -%} | |||||
<div class="prev">< <a href="{{ resource.prev_by_index.full_url }}"> | |||||
{{ resource.prev_by_index.meta.title_ending|replace("| ", "") }}</a> | |||||
</div> | |||||
{%- endif %} | |||||
</div> | |||||
{% endmacro %} |
@@ -1,11 +1,14 @@ | |||||
mode: learning | mode: learning | ||||
media_root: media | media_root: media | ||||
media_url: media # will use relative path, prepend "/" for absolute path | |||||
media_url: /media | |||||
template: hyde.ext.templates.jinja.Jinja2Template | template: hyde.ext.templates.jinja.Jinja2Template | ||||
plugins: | plugins: | ||||
- hyde.ext.plugins.meta.MetaPlugin | - hyde.ext.plugins.meta.MetaPlugin | ||||
- hyde.ext.plugins.auto_extend.AutoExtendPlugin | - hyde.ext.plugins.auto_extend.AutoExtendPlugin | ||||
- hyde.ext.plugins.syntext.SyntextPlugin | |||||
# Plugins needed for the advances section. | |||||
- hyde.ext.plugins.sorter.SorterPlugin | |||||
- hyde.ext.plugins.grouper.GrouperPlugin | |||||
- hyde.ext.plugins.tagger.TaggerPlugin | |||||
context: | context: | ||||
data: | data: | ||||
author: | author: | ||||
@@ -20,8 +23,66 @@ context: | |||||
install: "http://hyde.github.com/install.html" | install: "http://hyde.github.com/install.html" | ||||
menu: | menu: | ||||
- title: Home | - title: Home | ||||
url: index.html | |||||
- title: What next | |||||
url: what-next.html | |||||
url: /index.html | |||||
- title: First steps | |||||
url: /first-steps.html | |||||
- title: Advanced topics | |||||
url: /advanced/overview.html | |||||
- title: About | - title: About | ||||
url: about.html | |||||
url: /about.html | |||||
### Advanced part ### | |||||
# This defines meta data on the whole site. | |||||
meta: | |||||
# 'nodemeta' will tell Hyde what file to look for inside a folder from | |||||
# which to apply meta data to all files (resources) inside it. This is | |||||
# a great way of simply adding or modifying properties of a very large | |||||
# number of files. | |||||
nodemeta: meta.yaml | |||||
ga_tracking_code: XX-XXXXXXXX-X | |||||
sorter: | |||||
name: # the name of the sorter (no pun intended) | |||||
attr: name # by which attributes will resources be sorted | |||||
filters: | |||||
source_file.kind: html | |||||
# You can include only files from a certain folder. | |||||
#resource.node: (name of the folder) | |||||
#reverse: True # if you need the list backwards | |||||
file_type: | |||||
attr: | |||||
- source_file.kind | |||||
- source_file.size | |||||
index: | |||||
attr: meta.index | |||||
filters: | |||||
source_file.kind: html | |||||
learning_order: | |||||
attr: meta.learning_order | |||||
filters: | |||||
source_file.kind: html | |||||
grouper: | |||||
level: | |||||
sorter: name | |||||
description: Difficulty levels | |||||
groups: | |||||
- name: basic | |||||
description: Basic | |||||
- name: advanced | |||||
description: Advanced | |||||
# You can have more than one group section, depending on your needs. | |||||
# For example: "categories", "menu sections", etc. | |||||
#category: | |||||
# description: To which category a blog post belongs to. | |||||
# groups: | |||||
# - name: software | |||||
# description: Software engineering | |||||
# - name: web | |||||
# description: Web technologies | |||||
# - name: seo | |||||
# description: Search Engine Optimization | |||||
tagger: | |||||
sorter: name |