ref: fd33e5d20245add7eef49ef15beea0de925304f9
parent: 112c3c5c04c2a7c9bc5d66cdd343ff71805b396e
author: Austin Ziegler <[email protected]>
date: Mon Nov 24 22:07:18 EST 2014
Documentation for `ref` and `relref`. - Rejigged the weight of the extras/ content for the new crossreferences page. - Used the new {{</*…*/>}} format for documenting highlighting and to prevent a warning about the missing `fig` shortcode.
--- a/docs/content/extras/builders.md
+++ b/docs/content/extras/builders.md
@@ -7,7 +7,7 @@
next: /extras/comments
prev: /extras/aliases
title: Hugo Builders
-weight: 12
+weight: 20
---
Hugo provides the functionality to quickly get a site, theme or page
--- a/docs/content/extras/comments.md
+++ b/docs/content/extras/comments.md
@@ -4,10 +4,10 @@
menu:
main:
parent: extras
-next: /extras/livereload
+next: /extras/crossreferences
prev: /extras/builders
title: Comments in Hugo
-weight: 14
+weight: 30
---
As Hugo is a static site generator, the content produced is static and
--- /dev/null
+++ b/docs/content/extras/crossreferences.md
@@ -1,0 +1,150 @@
+---
+date: 2014-11-25
+menu:
+ main:
+ parent: extras
+next: /extras/livereload
+prev: /extras/comments
+title: Cross-References
+weight: 40
+---
+
+Hugo makes it easy to link documents together with the `ref` and `relref` shortcodes. These shortcodes are also used to safely provide links to headings inside of your content, whether across documents or within a document. The only difference between `ref` and `relref` is whether the resulting URL is absolute (`http://1.com/about/`) or relative (`/about/`).
+
+## Using `ref` and `relref`
+
+ {{</* ref "document" */>}}
+ {{</* ref "#anchor" */>}}
+ {{</* ref "document#anchor" */>}}
+ {{</* relref "document" */>}}
+ {{</* relref "#anchor" */>}}
+ {{</* relref "document#anchor" */>}}
+
+The single parameter to `ref` is a string with a content _document name_ (`about.md`), an in-document _anchor_ (`#who`), or both (`about.md#who`).
+
+### Document Names
+
+The _document name_ is the name of a document including the format extension; this may be just the filename, or the relative path from the `content/` directory. With a document `content/blog/post.md`, either format will produce the same result.
+
+ {{</* relref "blog/post.md" */>}} ⇒ `/blog/post/`
+ {{</* relref "post.md" */>}} ⇒ `/blog/post/`
+
+If you have multiple sections with the same filename, you should only use the relative path format, because the behaviour is _undefined_. So, if I also have a document `link/post.md`, the output of `ref` is unknown for `post.md`.
+
+ {{</* relref "blog/post.md" */>}} ⇒ `/blog/post/`
+ {{</* relref "post.md" */>}} ⇒ `/blog/post/` (maybe)
+ {{</* relref "post.md" */>}} ⇒ `/link/post/` (maybe)
+ {{</* relref "link/post.md" */>}} ⇒ `/link/post/`
+
+A relative document name must *not* begin with a slash (`/`).
+
+ {{</* relref "/blog/post.md" */>}} ⇒ `""`
+
+### Anchors
+
+When an _anchor_ is provided by itself, the current page’s unique identifier will be appended; when an _anchor_ is provided with a document name, the found page's unique identifier will be appended.
+
+ {{</* relref "#who" */>}} ⇒ `#who:9decaf7`
+ {{</* relref "blog/post.md#who" */>}} ⇒ `/blog/post/#who:badcafe`
+
+More information about document unique identifiers and headings can be found [below]({{< ref "#hugo-heading-anchors" >}}).
+
+### Examples
+
+* `{{</* ref "blog/post.md" */>}}` ⇒ `http://1.com/blog/post/`
+* `{{</* ref "post.md#tldr" */>}}` ⇒ `http://1.com/blog/post/#tldr:caffebad`
+* `{{</* relref "post.md" */>}}` ⇒ `/blog/post/`
+* `{{</* relref "blog/post.md#tldr" */>}}` ⇒ `/blog/post/#tldr:caffebad`
+* `{{</* ref "#tldr" */>}}` ⇒ `#tldr:badcaffe`
+* `{{</* relref "#tldr" */>}}` ⇒ `#tldr:badcaffe`
+
+## Hugo Heading Anchors
+
+When using Markdown document types, Hugo generates heading anchors automatically. The generated anchor for this section is `hugo-heading-anchors`. Because the heading anchors are generated automatically, Hugo takes some effort to ensure that heading anchors are unique both inside a document and across the entire site.
+
+Ensuring heading uniqueness across the site is accomplished with a unique identifier for each document based on its path. Unless a document is renamed or moved between sections *in the filesystem*, the unique identifier for the document will not change: `blog/post.md` will always have a unique identifier of `81df004c333b392d34a49fd3a91ba720`.
+
+`ref` and `relref` were added so you can make these reference links without having to know the document’s unique identifier. (The links in document tables of contents are automatically up-to-date with this value.)
+
+ {{</* relref "extras/crossreferences.md#hugo-heading-anchors" */>}}
+ /extras/crossreferences/#hugo-heading-anchors:77cd9ea530577debf4ce0f28c8dca242
+
+> What follows is a deeper discussion of *why* and *how* Hugo generates heading anchors. It is not necessary to know this to use `ref` and `relref`, but it may be useful in understanding how some anchors may not match your expectations.
+
+### How to Generate a Heading Anchor
+
+Convert the text of the heading to lowercase.
+
+ Hugo: A Fast & Modern Static Web Engine
+ hugo: a fast & modern static web engine
+
+Replace anything that isn't an ASCII letter (`a-z`) or number (`0-9`) with a dash (`-`).
+
+ hugo: a fast & modern static web engine
+ hugo--a-fast---modern-static-web-engine
+
+Get rid of extra dashes.
+
+ hugo--a-fast---modern-static-web-engine
+ hugo-a-fast-modern-static-web-engine
+
+You have just converting the text of a heading to a suitable anchor. If your document has unique heading text, all of the anchors will be unique, too.
+
+#### Specifying Heading Anchors
+
+You can also tell Hugo to use a particular heading anchor.
+
+ # Hugo: A Fast & Modern Static Web Engine {#hugo-main}
+
+Hugo will use `hugo-main` as the heading anchor.
+
+### What About Duplicate Heading Anchors?
+
+The technique outlined above works well enough, but some documents have headings with identical text, like the [shortcodes](/extras/shortcodes/) page—there are three headings with the text "Example". You can specify heading anchors manually:
+
+ ### Example {#example-1}
+ ### Example {#example-2}
+ ### Example {#example-3}
+
+It’s easy to forget to do that all the time, and Hugo is smart enough to do it for you. It just adds `-x` to the end of each heading it has already seen.
+
+* `### Example` ⇒ `example`
+* `### Example` ⇒ `example-1`
+* `### Example` ⇒ `example-2`
+
+Sometimes it's a little harder, but Hugo can recover from those, too, by adding more suffixes:
+
+* `# Heading` ⇒ `heading`
+* `# Heading 1` ⇒ `heading-1`
+* `# Heading` ⇒ `heading-1-1`
+* `# Heading` ⇒ `heading-1-2`
+* `# Heading 1` ⇒ `heading-2`
+
+This can even affect specified heading anchors that come after a generated heading anchor.
+
+* `# My Heading` ⇒ `my-heading`
+* `# My Heading {#my-heading}` ⇒ `my-heading-1`
+
+> This particular collision and override is unfortunate, but unavoidable because Hugo processes each heading for collision detection as it sees it during conversion.
+
+This technique works well for documents rendered on individual pages, like blog posts. What about on Hugo list pages?
+
+### Unique Heading Anchors in Lists
+
+Hugo converts each document from Markdown independently. it doesn’t know that `blog/post.md` has an "Example" heading that will collide with the "Example" heading in `blog/post2.md`. Even if it did know this, the addition of `blog/post3.md` should not cause the anchors for the headings in the other blog posts to change.
+
+Enter the document’s unique identifier. To prevent this sort of collision on
+list pages, Hugo always appends the document's to a generated heading anchor.
+So, the "Example" heading in `blog/post.md` actually turns into
+`#example:81df004…`, and the "Example" heading in `blog/post2.md` actually
+turns into `#example:8cf1599…`. All you have to know is the heading anchor that
+was generated, not the document identifier; `ref` and `relref` take care of the
+rest for you.
+
+ <a href='{{</* relref "blog/post.md#example" */>}}'>Post Example</a>
+ <a href='/blog/post.md#81df004…'>Post Example</a>
+
+ [Post Two Example]({{</* relref "blog/post2.md#example" */>}})
+ <a href='/blog/post2.md#8cf1599…'>Post Two Example</a>
+
+Now you know.
--- a/docs/content/extras/highlighting.md
+++ b/docs/content/extras/highlighting.md
@@ -8,7 +8,7 @@
next: /extras/toc
prev: /extras/shortcodes
title: Syntax Highlighting
-weight: 50
+weight: 90
---
Hugo provides the ability for you to highlight source code in two different
@@ -43,20 +43,20 @@
closing shortcode.
### Example
-The example has an extra space between the “`{{`” and “`%`” characters to prevent rendering here. Since this example is a code block, we use GitHub flavored Markdown's code fences, ```, to delimit the code. If you are using standard Markdown, instead of the code fence delimiters, each line must be preceeded by 4 spaces to identify each line as a line of code. Not doing either will result in the text being rendered as HTML. This will prevent Pygments highlighting from working.
+Since this example is a code block, we use Github flavored Markdown's code fences, ```, to delimit the code. If you are using standard Markdown, instead of the code fence delimiters, each line must be preceeded by 4 spaces to identify each line as a line of code. Not doing either will result in the text being rendered as HTML. This will prevent Pygment highlighting from working.
- ```
- {{ % highlight html %}}
- <section id="main">
- <div>
- <h1 id="title">{{ .Title }}</h1>
- {{ range .Data.Pages }}
- {{ .Render "summary"}}
- {{ end }}
- </div>
- </section>
- {{ % /highlight %}}
- ```
+```
+{{%/* highlight html */%}}
+<section id="main">
+ <div>
+ <h1 id="title">{{ .Title }}</h1>
+ {{ range .Data.Pages }}
+ {{ .Render "summary"}}
+ {{ end }}
+ </div>
+</section>
+{{%/* /highlight */%}}
+```
### Example Output
--- a/docs/content/extras/livereload.md
+++ b/docs/content/extras/livereload.md
@@ -4,9 +4,9 @@
main:
parent: extras
next: /extras/menus
-prev: /extras/comments
+prev: /extras/crossreferences
title: Live Reload
-weight: 15
+weight: 50
---
Hugo may not be the first static site generator to utilize live reload
--- a/docs/content/extras/menus.md
+++ b/docs/content/extras/menus.md
@@ -6,7 +6,7 @@
next: /extras/permalinks
prev: /extras/livereload
title: Menus
-weight: 20
+weight: 60
---
Hugo has a simple yet powerful menu system that permits content to be
binary files a/docs/content/extras/permalinks.md b/docs/content/extras/permalinks.md differ
--- a/docs/content/extras/shortcodes.md
+++ b/docs/content/extras/shortcodes.md
@@ -8,7 +8,7 @@
next: /extras/highlighting
prev: /extras/permalinks
title: Shortcodes
-weight: 40
+weight: 80
---
Hugo uses Markdown for its simple content format. However, there’s a lot
@@ -128,6 +128,33 @@
<h4>Steve Francia</h4>
</figcaption>
</figure>
+
+### ref, relref
+
+These shortcodes will look up the pages by their relative path (e.g.,
+`blog/post.md`) or their logical name (`post.md`) and return the permalink
+(`ref`) or relative permalink (`relref`) for the found page.
+
+`ref` and `relref` also make it possible to make fragmentary links that work
+for the header links generated by Hugo.
+
+Read more on [cross-references]({{% ref "extras/crossreferences.md" %}}).
+
+#### Usage
+
+`ref` and `relref` take exactly one required parameter of _reference_.
+
+#### Example
+
+ [Neat]({{</* ref "blog/neat.md" */>}})
+ [Who]({{</* relref "about.md#who" */>}})
+
+#### Example Output
+
+Assuming that standard Hugo pretty URLs are turned on.
+
+ <a href="/blog/neat">Neat</a>
+ <a href="/about/#who:c28654c202e73453784cfd2c5ab356c0">Who</a>
## Creating your own shortcodes
--- a/docs/content/extras/toc.md
+++ b/docs/content/extras/toc.md
@@ -6,7 +6,7 @@
next: /extras/urls
prev: /extras/highlighting
title: Table of Contents
-weight: 60
+weight: 100
---
Hugo will automatically parse the Markdown for your content and create
--- a/docs/content/extras/urls.md
+++ b/docs/content/extras/urls.md
@@ -9,7 +9,7 @@
notoc: true
prev: /extras/toc
title: URLs
-weight: 70
+weight: 110
---
## Pretty URLs
--- a/docs/content/templates/functions.md
+++ b/docs/content/templates/functions.md
@@ -174,4 +174,10 @@
### highlight
Take a string of code and a language, uses Pygments to return the syntax
-highlighted code in HTML. Used in the [highlight shortcode](/extras/highlighting).
+highlighted code in HTML. Used in the [highlight
+shortcode](/extras/highlighting).
+
+### ref, relref
+Looks up a content page by relative path or logical name to return the permalink (`ref`) or relative permalink (`relref`). Requires a Node or Page object (usually satisfied with `.`). Used in the [`ref` and `relref` shortcodes]({{% ref "extras/crossreferences.md" %}}).
+
+e.g. {{ ref . "about.md" }}
--- a/docs/content/templates/variables.md
+++ b/docs/content/templates/variables.md
@@ -29,16 +29,16 @@
**.Keywords** The meta keywords for this content.<br>
**.Date** The date the content is associated with.<br>
**.PublishDate** The date the content is published on.<br>
-**.Type** The content [type](/content/types/) (e.g. post)<br>
-**.Section** The [section](/content/sections/) this content belongs to<br>
+**.Type** The content [type](/content/types/) (e.g. post).<br>
+**.Section** The [section](/content/sections/) this content belongs to.<br>
**.Permalink** The Permanent link for this page.<br>
**.RelPermalink** The Relative permanent link for this page.<br>
-**.LinkTitle** Access when creating links to this content. Will use linktitle if set in front-matter, else title<br>
-**.Taxonomies** These will use the field name of the plural form of the index (see tags and categories above)<br>
-**.RSSLink** Link to the indexes' rss link <br>
-**.TableOfContents** The rendered table of contents for this content<br>
-**.Prev** Pointer to the previous content (based on pub date)<br>
-**.Next** Pointer to the following content (based on pub date)<br>
+**.LinkTitle** Access when creating links to this content. Will use linktitle if set in front-matter, else title.<br>
+**.Taxonomies** These will use the field name of the plural form of the index (see tags and categories above).<br>
+**.RSSLink** Link to the indexes' rss link.<br>
+**.TableOfContents** The rendered table of contents for this content.<br>
+**.Prev** Pointer to the previous content (based on pub date).<br>
+**.Next** Pointer to the following content (based on pub date).<br>
**.FuzzyWordCount** The approximate number of words in the content.<br>
**.WordCount** The number of words in the content.<br>
**.ReadingTime** The estimated time it takes to read the content in minutes.<br>
@@ -45,7 +45,7 @@
**.Weight** Assigned weight (in the front matter) to this content, used in sorting.<br>
**.IsNode** Always false for pages.<br>
**.IsPage** Always true for page.<br>
-**.Site** See site variables below<br>
+**.Site** See site variables below.<br>
## Page Params
@@ -65,6 +65,8 @@
**.Date** The date the content is published on.<br>
**.Permalink** The Permanent link for this node<br>
**.Url** The relative url for this node.<br>
+**.Ref(ref)** Returns the permalink for `ref`. See [cross-references]({{% ref "extras/crossreferences.md" %}}). Does not handle in-page fragments correctly.<br>
+**.RelRef(ref)** Returns the relative permalink for `ref`. See [cross-references]({{% ref "extras/crossreferences.md" %}}). Does not handle in-page fragments correctly.<br>
**.RSSLink** Link to the indexes' rss link <br>
**.Data** The data specific to this type of node.<br>
**.IsNode** Always true for nodes.<br>
--- a/docs/content/tutorials/migrate-from-jekyll.md
+++ b/docs/content/tutorials/migrate-from-jekyll.md
@@ -141,7 +141,7 @@
to this (this example uses a slightly extended version named `fig`, different than the built-in `figure`):
- {{</* fig class="full" src="http://farm5.staticflickr.com/4136/4829260124_57712e570a_o_d.jpg" title="One of my favorite touristy-type photos. I secretly waited for the good light while we were having fun and took this. Only regret: a stupid pole in the top-left corner of the frame I had to clumsily get rid of at post-processing." link="http://www.flickr.com/photos/alexnormand/4829260124/in/set-72157624547713078/" */>}}
+ {{%/* fig class="full" src="http://farm5.staticflickr.com/4136/4829260124_57712e570a_o_d.jpg" title="One of my favorite touristy-type photos. I secretly waited for the good light while we were having fun and took this. Only regret: a stupid pole in the top-left corner of the frame I had to clumsily get rid of at post-processing." link="http://www.flickr.com/photos/alexnormand/4829260124/in/set-72157624547713078/" */%}}
As a bonus, the shortcode named parameters are, arguably, more readable.