--- 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: | |||
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', '')) | |||
target = self.site.config.deploy_root_path.child_folder( | |||
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 | |||
title_ending: "| What next" | |||
title_ending: "| First steps" | |||
--- | |||
{# In-file metadata. Supplements data from the site's configuration file | |||
and node (folder) level data in "meta.yaml" files. | |||
@@ -11,8 +11,8 @@ title_ending: "| What next" | |||
#} | |||
{% 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 | |||
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] | |||
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. | |||
_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. | |||
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 | |||
variables invocation inside curly braces, dynamic media path generation | |||
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 | |||
documentation][jinja2_docs]. | |||
@@ -55,19 +55,31 @@ documentation][jinja2_docs]. | |||
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" | |||
[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 %} |
@@ -18,4 +18,6 @@ technologies step by step. Those are: | |||
* Jinja templates | |||
* Markdown | |||
* basic metadata and plugins | |||
Are you ready for your [first steps](first-steps.html)? | |||
{% endblock %} |
@@ -4,7 +4,7 @@ | |||
} | |||
html, body { | |||
color: #fafafa; | |||
color: #ddd; | |||
background-color: black; | |||
} | |||
@@ -20,6 +20,10 @@ body { | |||
font-family: Tahoma, sans-serif; | |||
} | |||
strong { | |||
color: white; | |||
} | |||
a { | |||
color: #f1ee00; | |||
} | |||
@@ -28,11 +32,11 @@ a:hover, a:focus { | |||
text-decoration: none; | |||
} | |||
p, ul { | |||
p, ul, ol { | |||
margin-bottom: 1.6em; | |||
} | |||
ul { | |||
ul, ol { | |||
margin-left: 2em; | |||
} | |||
@@ -49,6 +53,7 @@ header h1 { | |||
font-size: 50px; | |||
font-weight: normal; | |||
text-shadow: -1px 2px 1px black; | |||
color: white; | |||
} | |||
header h1 span { | |||
@@ -60,13 +65,14 @@ header h2 { | |||
font-weight: normal; | |||
letter-spacing: 11px; | |||
text-shadow: -1px 2px 1px black; | |||
color: white; | |||
} | |||
nav { | |||
position: absolute; | |||
top: 340px; | |||
right: 120px; | |||
width: 200px; | |||
width: 250px; | |||
text-align: right; | |||
font-family: Anton, Tahoma, sans-serif; | |||
} | |||
@@ -74,7 +80,7 @@ nav { | |||
nav a, | |||
nav a:visited { | |||
text-decoration: none; | |||
color: #fafafa; | |||
color: white; | |||
text-transform: uppercase; | |||
font-size: 2.8em; | |||
} | |||
@@ -121,6 +127,7 @@ nav, aside { | |||
font-family: Anton, Tahoma, sans-serif; | |||
text-transform: uppercase; | |||
margin-bottom: 0.8em; | |||
color: white; | |||
} | |||
#content h2 { | |||
@@ -128,6 +135,8 @@ nav, aside { | |||
font-size: 1.2em; | |||
font-family: Tahoma, sans-serif; | |||
margin-bottom: 1.33em; | |||
color: white; | |||
border-bottom: 1px dashed #888; | |||
} | |||
#content code { | |||
@@ -142,3 +151,19 @@ nav, aside { | |||
border-bottom: 1px solid #222; | |||
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 | |||
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> | |||
<article id="content"> | |||
{# Main content block. Notice it has to pass through the | |||
@@ -38,5 +38,15 @@ | |||
<p>Created by <a href="{{ author.url}}">{{ author.name}}</a> | |||
for <a href="{{ project.url }}">{{ project.name }}</a></p> | |||
</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> | |||
</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() -%} | |||
{# 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> | |||
{% 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 %} | |||
</ul> | |||
{%- 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 | |||
media_root: media | |||
media_url: media # will use relative path, prepend "/" for absolute path | |||
media_url: /media | |||
template: hyde.ext.templates.jinja.Jinja2Template | |||
plugins: | |||
- hyde.ext.plugins.meta.MetaPlugin | |||
- 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: | |||
data: | |||
author: | |||
@@ -20,8 +23,66 @@ context: | |||
install: "http://hyde.github.com/install.html" | |||
menu: | |||
- 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 | |||
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 |