commit b6f9e18e61ec464cdaae6c05d7f4915c6b45e456 Author: infidel Date: Mon Nov 14 23:16:26 2022 +0700 Sync diff --git a/.git.swp b/.git.swp new file mode 100644 index 0000000..f980351 Binary files /dev/null and b/.git.swp differ diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c33a9a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +exampleSite/public/ +resources/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ae21e33 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2017 Heydon Pickering +Copyright (c) 2019 Zachary Betz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6c34a0a --- /dev/null +++ b/README.md @@ -0,0 +1,99 @@ +# Infidel Cupper +[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity) + +This is infidel's fork version of hugo [Cupper](https://github.com/zwbetz-gh/cupper-hugo-theme) theme. I use this theme for my own site [nnag.me](https://nnag.me). + +## Added Feature + +### Plausible integration + +#### Shortcode + +```go + {{ if and (.Site.Params.plsDomain) (.Site.Params.plsUrl) }} + + {{ end }} + +``` + +#### Hugo Conf + +```yml + ... + params: + plsDomain : + plsUrl : + ... +``` +### Plausible Bypass Adblock + +Adblocker easyfilter has some filter on “plausible.js” string, especially if its routed towards external source . To bypass this you can setup a proxy rule on nginx to redirect this plausible api into the currently accessed site. + +### nginx conf +```nginx + + server { + ... + location = /js/script.js { + # Change this if you use a different variant of the script + proxy_pass https://plausible.io/js/script.js; + + # Tiny, negligible performance improvement. Very optional. + proxy_buffering on; + + # Cache the script for 6 hours, as long as plausible.io returns a valid response + proxy_cache jscache; + proxy_cache_valid 200 6h; + proxy_cache_use_stale updating error timeout invalid_header http_500; + + # Optional. Adds a header to tell if you got a cache hit or miss + add_header X-Cache $upstream_cache_status; + } + + location = /api/event { + proxy_pass https://plausible.io/api/event; + proxy_buffering on; + proxy_http_version 1.1; + + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + } + } +``` + +### Hugo Conf + +```yml + ... + params: + plsDomain : + plsUrl : /js/script.js + ... +``` + + + + +### PDF.js + +#### shortcode + +- `layout/shortcodes/embed-pdf.html` + +#### scripts + +- `static/js/pdf.js` +- `static/js/pdf.worker.js` + +### Layout & CSS + +#### Homepage `layout/index.html` + +Homepage splited into two main section, Greetings section and Recent Post section. Both of the section is wrapped using `inf-border` class to give them borders. The Greetings section now has subsection of important links which is paritally loaded from custom layout of `icon-links.html`. + +The Recent Posts section is managed by `inf-patterns-list` class, using html table instead of html lists format. + + + + diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..d677d28 --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +tags: [] +--- + diff --git a/assets/css/.template-styles.css.swp b/assets/css/.template-styles.css.swp new file mode 100644 index 0000000..831b3d4 Binary files /dev/null and b/assets/css/.template-styles.css.swp differ diff --git a/assets/css/search.css b/assets/css/search.css new file mode 100644 index 0000000..77a424b --- /dev/null +++ b/assets/css/search.css @@ -0,0 +1,8 @@ +#search { + height: 50px; + width: 100%; + padding: 8px; + border: 2px solid; + line-height: 1.6; + font-size: 1.25rem; +} diff --git a/assets/css/template-styles.css b/assets/css/template-styles.css new file mode 100644 index 0000000..af861e7 --- /dev/null +++ b/assets/css/template-styles.css @@ -0,0 +1,1120 @@ +/* Fonts */ +@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); + +@font-face { + font-family: 'Miriam Libre'; + src: url('{{ "css/fonts/miriamlibre-bold.woff2" | absURL }}') format('woff2'), url('{{ "css/fonts/miriamlibre-bold.woff" | absURL }}') format('woff'); + font-weight: bold; + font-style: normal; +} +*, +*::before, +*::after { + font-family: inherit; + background-color: inherit; + color: inherit; + margin: 0; + padding: 0; + box-sizing: border-box; +} +html { + font-size: calc(1em + 0.25vw); + font-family: Roboto, Arial, Helvetica Neue, sans-serif; + line-height: 1.5; + color: #111; + background-color: #fefefe; +} +template { + display: none !important; +} +* + * { + margin-top: 2.25rem; +} +br, +dt, +dd, +th, +td, +option, +[hidden] + *, +li + li, +body, +.main-and-footer { + margin-top: 0; +} +p + p { + margin-top: 0.75rem; +} +.priority { + margin-top: 0; +} +a { + text-decoration: none; + border-bottom: 1px solid; +} +abbr { + text-decoration: none; + cursor: help; + border-bottom: 1px dashed; +} +img { + max-width: 100%; + max-height: 50vh; +} +.img-link { + border-bottom: none; +} +p img { + margin: 0.75rem 0; +} +figure p img { + margin: 0; +} +:focus:not([tabindex="-1"]), +[data-expands]:focus svg, +.patterns a:focus .text, +[for="themer"] :focus + [aria-hidden] { + outline: 4px solid #999; +} +a { + outline-offset: 2px; +} + +/* Katex math typesetting */ +.katex * { + margin-top: 0; + background-color: transparent; +} + +/* Fix for IE :( */ +[tabindex="-1"]:focus, +div:not([tabindex]):focus { + outline: none; +} +[hidden] { + display: none; +} + +/* Skip link */ +[href="#main"] { + display: block; + width: 100%; + padding: 0.75rem; + color: #fefefe; + background: #000; + position: absolute; + top: -3rem; + text-align: center; + z-index: 1; +} +[href="#main"]:focus { + top: 0; + outline: none; +} + +/* Text styles */ +h1, +h2, +h3, +h4 { + font-family: Miriam Libre, serif; + line-height: 1.125; +} +h1 { + font-size: 2rem; +} +h2 { + font-size: 1.66rem; +} +h3 { + font-size: 1.25rem; +} +h4, +h5 { + font-size: 1rem; + font-family: PT Sans, sans-serif; +} +h5 { + font-size: 0.85rem; + text-transform: uppercase; +} +kbd { + line-height: 1; + font-size: 0.66rem; + padding: 0.1rem 0.33rem; + border-radius: 0.25rem; + border: 2px solid; + box-shadow: 0.125rem 0.125rem 0 #111; + vertical-align: 0.33em; +} +pre, +.file-tree { + overflow-x: auto; + padding: 1.5rem; + border: 1px solid; +} +code { + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 0.85em; +} +.cmd { + padding: 0.75rem; + background: #111; +} +.cmd code { + color: #fefefe; + white-space: pre-wrap; +} +.cmd code::before { + content: '$'; + font-weight: bold; + padding-right: 0.25em; +} +.cmd code::selection{ + background: #fefefe; + color: rgba(0,0,0,.8); +} +/* Lists */ +main ul, +main ol { + margin-left: 2.25rem; +} +main li + li { + margin-top: 0.5rem; +} +main ul ul, main ol ol, main li ul, main li ol { + margin-top: 0.5rem; +} +ol ol { + list-style: lower-latin; +} +ol ol ol { + list-style: lower-roman; +} +main dt { + font-weight: bold; +} +main dd { + padding-left: 2rem; +} +dd ul { + margin-left: 0; +} +dd li + li { + margin: 0; +} + +/* Blockquotes */ +blockquote { + border-left: 0.5rem solid; + padding-left: 0.75rem; +} +blockquote .author { + font-size: 0.85rem; +} + +/* Buttons */ +button { + font-size: 1.25rem; + border-radius: 0.33em; + font-family: inherit; + background: #111; + color: #fefefe; + padding: 0.75rem; + border: 0; +} +[data-launch] { + font-size: 0.66rem !important; + padding: 0.5rem !important; + margin-top: 0 !important; + border-radius: 0 !important; + border-top-left-radius: 0.33rem !important; + box-shadow: none !important; + background: #111 !important; + color: #fefefe !important; + position: absolute !important; + right: 0 !important; + bottom: 0 !important; +} + +/* Forms */ +label { + display: inline-block; + font-weight: bold; +} +[for="themer"] { + background: #111; + border-radius: 0.33em; + color: #fefefe; + padding: 0.25em 0.75em; + margin: 0.5rem; +} +[for="themer"] [aria-hidden]::before { + content: 'off'; +} +[for="themer"] :checked + [aria-hidden]::before { + content: 'on'; +} + +/* Tables */ +table { + text-align: left; + table-layout: fixed; + width: 100%; + border-collapse: collapse; +} +th, +td { + border: 2px solid; + padding: 0.5rem; + line-height: 1.25; + margin: 0; +} +th { + font-weight: bold; +} +th:empty { + border: 0; +} + +/* Tested using... table */ +.tested { + text-align: center; + border: 1px solid #111; +} +.tested tr { + display: flex; + flex-flow: row wrap; +} +.tested td, .tested th { + vertical-align: middle; + overflow: hidden; + flex: 1 0 auto; + border: 1px solid #111; +} +.tested th { + width: 100%; + background-color: #111; + color: #fefefe; + outline-color: #111; +} +.tested img { + max-width: 3rem; +} +.tested span { + display: block; + margin: 0; +} +.tested .additional { + font-size: 0.85rem; +} +caption { + font-size: 1.125rem; + padding-bottom: 0.25rem; + font-style: italic; +} + +/* Page structure */ +.wrapper { + position: relative; + margin-top: 0; + overflow-x: hidden; +} +.intro-and-nav { + font-size: 1rem; + width: 20rem; + height: 100vh; + position: fixed; + top: 0; + left: 0; + border-right: 2px solid; +} +.intro-and-nav > div { + padding: 2.25rem; + display: flex; + flex-direction: column; + height: 100%; +} +.intro { + flex: 0 0 auto; +} +.patterns { + flex: 1 1 auto; +} +.logo { + border: 0; + margin : 2.25rem; +} +.logo img { + width: 100%; + max-width: 12rem; +} +.library-desc { + margin-top: 0.5rem; + margin-left: auto; + margin-right: auto; + max-width: 25rem; +} +.main-and-footer { + margin-left: 20rem; +} +.main-and-footer > div { + max-width: 55rem; + margin: 0 auto; + padding: 3.25rem; +} +[role="contentinfo"] { + font-size: 0.85rem; + margin-top: 4rem; + text-align: center; +} + +/* Patterns navigation */ +.patterns { + overflow: auto; + margin-top: 1.5rem; + min-width: max-content; +} +.patterns * { + margin-top: 0; +} +.patterns h3 { + font-size: 1rem; +} +.patterns h3 + ul { + margin-top: 0.75rem; +} +.patterns li { + line-height: 1.125; + list-style: none; +} +.patterns li + li { +} +.patterns ul ul { + margin-left: 0.75rem; +} +.pattern a { + border: 0; + display: flex; + flex-wrap: nowrap; + align-items: baseline; + font-weight: bold; + padding: 0 1rem; + padding-top: 0.5em; + padding-bottom: 0.5em; +} +.pattern a:focus { + outline: none; +} +.pattern span { + margin-left: 0.125rem; +} + +/* After */ +.pattern [aria-current] { + background-color: #111; + clip-path: polygon(0% 0%, 90% 0%, 100% 50%, 90% 100%, 0% 100%); + color: #fefefe; +} + +/* Menu button */ +#menu-button { + display: none; + width: 100%; + text-align: center; +} +#menu-button:focus { + outline: none; + box-shadow: inset 0 0 0 0.25rem #999; +} + +/* Tables of contents */ +.toc { + font-size: 0.85rem; + border: 1px solid; + padding: 1.5rem; +} +.toc nav { + margin-top: 1rem; +} +.toc ol { + margin-left: 0.75rem; + margin-top: 0.5rem; +} + + +/* Infidel borders */ +.inf-border { + font-size: 1rem; + border: 2px solid; + padding: 1.5rem; + box-shadow: 5px 10px; +} +.inf-border nav { + margin-top: 1rem; +} +.inf-border ol { + margin-left: 0.75rem; + margin-top: 0.5rem; +} + +/* Disqus Comments */ +#disqus-container { + text-align: center; +} +#disqus-button { + width: 100%; + padding: 0.25em 0.75em; +} +#disqus-comments { + display: none; +} + +/* infidel Pattern lists */ +.inf-patterns-list { + list-style: none; + margin-left: 0; +} +.inf-patterns-list h2 { + font-size: 1.0; + line-height: 1.6; +} + +.inf-patterns-list span { + font-size: 0.75; + line-height: 1.6; +} + +.inf-patterns-list li + li { + margin-top: 1rem; + padding-top: 1rem; + border-top: 2px solid; +} +.inf-patterns-list a { + border-bottom: none !important; +} + +.inf-patterns-list table,th,td { + + border: none !important; +} + +.inf-patterns-list table,tr:first-child { + + border: none !important; +} + + +.inf-patterns-list table,tr { + + border-top: 2px solid !important; +} + +.inf-patterns-list th, td:first-child { + margin-top: 1rem; + padding-top: 1rem; + text-align: left; +} + +.inf-patterns-list th, td { + margin-top: 1rem; + padding-top: 1rem; + text-align: right; +} + +.inf-patterns-list td, a { + border-bottom: none !important; +} + +/* Pattern lists */ +.patterns-list { + list-style: none; + margin-left: 0; +} +.patterns-list h2 { + font-size: 1.25rem; + line-height: 1.6; +} +.patterns-list li + li { + margin-top: 1rem; + padding-top: 1rem; + border-top: 2px solid; +} +.patterns-list a { + border: 0; +} + +/* Tags */ +.tags { + margin-top: 0; + font-size: 0.85rem; +} +.tags * { + display: inline; + margin: 0; +} +.tags strong { + margin-right: 0.25rem; +} +.tags li { + white-space: nowrap; + margin: 0 0.25rem 0 0; +} + +/* Date */ +.date { + margin-top: 0; + font-size: 0.85rem; +} + +/* Notes and warnings */ +.note { + border-left: 0.5rem solid; + font-size: 0.85rem; +} +.note .sign { + height: 2.25rem; + width: 2.25rem; +} +.note > div { + margin-left: 0.75rem; +} +.note > div > img:first-child { + height: 1.5rem; +} +.note > div >:first-child + * { + margin-top: 0; +} +.note.warning { + border-left: 0; + background-image: url({{ "css/images/stripe.svg" | absURL }}); + background-size: 0.5rem auto; + background-repeat: repeat-y; +} +.note.warning > div { + margin-left: 1.25rem; +} + +/* Tick lists */ +.ticks li { + list-style: none; + position: relative; +} +.ticks li::before { + content: ''; + display: inline-block; + width: 1rem; + height: 1rem; + margin-right: 0.25rem; + background-image: url({{ "css/images/icon-tick.svg" | absURL }}); + background-size: 100% auto; + position: absolute; + left: -1.25rem; + top: 0.25rem; +} + +/* Figures */ +figure { + text-align: center; +} +figcaption { + font-size: 0.85rem; + font-style: italic; + margin-top: 0.5rem; +} +main { + display: block; + counter-reset: fig; + min-height: 100vh; +} +figcaption::before { + counter-increment: fig; + content: 'Figure ' counter(fig) ':\0020'; + font-weight: bold; +} + +/* Code blocks */ +pre[class*=language-] { + background: none; + margin-top: 2.25rem; + margin-bottom: 0; + overflow-y: hidden; + overflow-x: auto; +} +code[class*="language-"], pre[class*="language-"] { + text-shadow: none; + /* filter: grayscale(100%); */ +} +pre[class*=language-][data-line] { + padding: 1em 0 0 2.25rem; +} +pre[class*=language-] code * { + margin-top: 0 !important; +} +[data-codeblock-shortcode], .code-annotated code { + display: inline-block; + margin-top: -1rem; +} +.code-annotated { + overflow-y: hidden; + overflow-x: auto; + padding: 1.5rem; + border: 1px solid; + white-space: pre; + counter-reset: annotation; +} +.highlight { + background: #ddd; + padding: 0.0625rem 0.33rem; + border-radius: 0.5rem; +} +.numbered .highlight::after, +.code-annotated.numbered + ol li::before { + counter-increment: annotation; + content: counter(annotation); + font-weight: bold; + font-size: 0.5rem; + background: #111; + color: #fefefe; + border-radius: 1rem; + margin-left: 0.25rem; + padding: 0.125em 0.5em; + vertical-align: 0.33em; +} +.code-annotated.numbered + ol { + list-style: none; + counter-reset: annotation; +} +.code-annotated.numbered + ol li::before { + font-size: 0.66em; + margin-right: 0.33em; + vertical-align: 0.25em; +} + +/* File tree lists */ +.file-tree { + overflow-x: auto; +} +.file-tree ul { + font-family: Courier, monospace; + margin: 0; + padding: 0; + padding-left: 3rem; + list-style: none; + line-height: 1.25; + position: relative; +} +.file-tree > ul { + padding-left: 0; + overflow-x: auto; + overflow-y: hidden; +} +.file-tree li { + background: #fefefe; + position: relative; + white-space: nowrap; +} +.file-tree li + li { + margin-top: 0; +} +.file-tree li:not(:last-child) > ul::before { + content: '\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020\2502\0020'; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 1em; + white-space: normal; +} +.file-tree li::before { + content: '\251C\2500\2500\0020'; +} +.file-tree li:last-child::before { + content: '\2514\2500\2500\0020'; +} + +/* Expandable sections */ +.expandable-section { + border-top: 1px solid; + border-bottom: 1px solid; + padding: 0.75rem 0; +} +[id^="js-expandable-"] { + margin: 0; + padding: 1.5rem 0 0.75rem; +} +@media screen { + .expandable-section + .expandable-section { + margin-top: 0; + border-top: 0; + } +} +[data-expands] { + text-align: left; + color: #111; + border: 0; + background: none; + width: 100%; + padding: 0; + margin: 0; + display: flex; + align-items: center; + justify-content: space-between; + cursor: pointer; +} +[data-expands] svg { + margin-top: 0; + width: 1em; + height: 1em; +} +[data-expands][aria-expanded="true"] svg .up-strut { + display: none; +} +[data-expands]:focus { + outline: none; +} +p:empty { + display: none; +} +*:not(p) + p:empty + p { + margin-top: 2.25rem; +} + +/* WCAG and principles */ +.wcag li { + font-size: 0.85em; +} +.principles p { + font-size: 0.85rem; + margin-top: 0.75rem; +} +.principles.with-desc > li + li, +.wcag.with-desc > li + li { + border-top: 1px solid; + margin-top: 0.75rem; + padding-top: 0.75rem; +} + +/* Site errors */ +.site-error { + padding: 1.5rem; + background: #efefef; +} +.site-error strong { + color: #C83737; +} + +/* SVG icons */ +a svg, +button svg, +h1 svg, +th svg, +li > svg { + height: 0.75em; + width: 0.75em; + margin-right: 0.25em; +} +h1 svg { + margin-right: 0; + width: 0.85em; + height: 0.85em; +} +.wcag-icon { + width: 1.25em; +} +.bookmark-icon { + vertical-align: middle; +} +.link-icon { + width: 0.75em; + height: 0.75em; +} +.tags svg, .link-icon { + vertical-align: middle; +} +.balloon-icon { + width: 0.75em; + margin-right: 0; +} +.print { + white-space: nowrap; + font-style: normal; +} + +/* Color palettes */ +.colors { + display: flex; + height: 5rem; + margin: -0.25rem; + list-style: none; + flex-wrap: nowrap; +} +.colors li { + margin: 0.25rem; + flex: 1 0 auto; + position: relative; +} +.colors span { + line-height: 1; + background-color: #111; + color: #fefefe; + font-size: 0.75rem; + padding: 0.25rem; + position: absolute; + bottom: 0.25rem; + right: 0.25rem; +} + +/* Cross references */ +.pattern-link { + font-weight: bold; +} + +/* Inline demos */ +.demo-inner { + border-top: 1px solid; + border-bottom: 1px solid; + padding: 1.5rem 0; + position: relative; +} +[id^="js-demo-"] { + all: initial; + display: block; +} + +/* Section links */ +.h2-container { + position: relative; + font-size: 1.66rem; +} +.h2-container a { + position: absolute; + margin-top: 0; + top: 0; + line-height: 1; + left: -1em; + border: 0; +} + +/* Single page layout */ +.wrapper.print-version .main-and-footer { + margin-left: 0; +} +.wrapper.print-version .intro-and-nav { + position: static; + border: 0; + width: auto; + text-align: center; + display: flex; + align-items: center; + justify-content: center; +} +.wrapper.print-version main { + min-height: 0; +} +.wrapper.print-version .library-desc { + font-size: 1rem; +} +.wrapper.print-version .intro-and-nav > div { + height: auto; +} +.wrapper.print-version #patterns-list { + margin-left: 0; + margin-top: 1.5rem; + display: block; +} +.wrapper.print-version .toc { + font-size: 1rem; +} +.wrapper.print-version .toc h2 { + font-size: 1.66rem; +} +.wrapper.print-version #patterns-list h3 { + font-size: 1.25rem; +} +.wrapper.print-version .patterns { + margin-top: 0; +} +.pattern-section:not(:last-child) { + padding-bottom: 2.25rem; + border-bottom: 2px solid; +} +.pattern-section h1 { + padding: 0 !important; +} + +/* Custom 404 */ +.custom-404 { + text-align: center; +} +.custom-404 * { + margin: 0; +} +.custom-404 svg { + max-width: 100%; +} + +/* Utilities */ +.vh { + clip: rect(1px, 1px, 1px, 1px); + height: 1px; + overflow: hidden; + position: absolute; + white-space: nowrap; + width: 1px; +} +.gallery { + display: flex; + justify-content: center; +} + +/* Media queries */ +@media screen and (max-width: 45em) { + /* Infidel Customs for mobile screen */ + + .inf-td-hide { + display: none; + } + + body a { + hyphens: auto; + } + [role="banner"] { + position: static; + width: auto; + height: auto; + } + .intro { + text-align: center; + } + .intro-and-nav { + border-right: none; + } + .intro-and-nav > div { + padding: 1.5rem; + } + .main-and-footer { + margin: 0; + } + main { + min-height: auto; + } + #patterns-list { + margin-top: 0.5rem; + border: 1px solid; + } + .patterns h3 { + font-size: 1.5rem; + padding: 1.5rem 1rem 0.75rem; + } + .patterns li:not(.pattern) { + margin-top: 0; + } + .patterns ul ul { + margin: 0; + } + .patterns li { + margin-top: 0; + } + .pattern { + font-size: 1rem; + } + .pattern a { + padding: 1rem; + } + .pattern [aria-current] { + clip-path: none; + padding: 1rem; + } + .pattern + .pattern { + border-top: 1px solid; + margin-top: 0; + } + #menu-button { + display: block; + } + #patterns-list { + display: none; + } + .toc-link { + display: none; + } + [aria-expanded="true"] + #patterns-list { + display: block; + } + code { + word-break: break-all; + } +} +@media print { + .wrapper:not(.print-version) .intro-and-nav, + .wrapper:not(.print-version) [role="contentinfo"] { + display: none; + } + .main-and-footer { + margin-left: 0; + } + a { + border: 0; + } + main a::after { + content: " (" attr(href) ")"; + word-break: break-word; + } + main nav a::after { + content: ''; + } + .cmd code { + background: #fefefe; + color: #111; + } + pre code { + white-space: pre-wrap !important; + } + .expandable-section { + border: 0; + padding: 0; + } + .expandable-section + p { + margin-top: 0.75rem; + } + [id^="js-expandable-"] { + display: block; + } + [data-expands] svg { + display: none; + } + main *:not(.with-desc) { + page-break-inside: avoid; + } + .note.warning { + border-left: 0.5rem solid; + background: none; + } +} +@media (-ms-high-contrast: active) { + img[src*=".svg"] { + background: #fefefe; + padding: 0.5rem; + } + .ticks li::before { + content: '✓'; + background: none; + width: auto; + top: 0; + } + .note.warning { + border-left: 0.5rem solid; + background: none; + } +} + +::-moz-selection { /* Code for Firefox */ + background: rgba(0,0,0,.8); + color: #fefefe; +} + +::selection { + background: rgba(0,0,0,.8); + color: #fefefe; +} diff --git a/assets/js/search.js b/assets/js/search.js new file mode 100644 index 0000000..f760b85 --- /dev/null +++ b/assets/js/search.js @@ -0,0 +1,21 @@ +(function () { + function onEvent() { + var filter = search.value.toUpperCase(); + var list = document.getElementById("list"); + var listItems = list.getElementsByTagName("li"); + for (i = 0; i < listItems.length; i++) { + var item = listItems[i]; + var text = item.innerText.toUpperCase(); + if (text.indexOf(filter) > -1) { + item.style.display = ""; + } else { + item.style.display = "none"; + } + } + } + + var search = document.getElementById("search"); + if (search) { + search.addEventListener("keyup", onEvent); + } +})(); diff --git a/assets/js/template-dom-scripts.js b/assets/js/template-dom-scripts.js new file mode 100644 index 0000000..c2f6b65 --- /dev/null +++ b/assets/js/template-dom-scripts.js @@ -0,0 +1,162 @@ +/* Expandable sections */ +(function () { + function toggle (button, target) { + var expanded = button.getAttribute('aria-expanded') === 'true'; + button.setAttribute('aria-expanded', !expanded); + target.hidden = !target.hidden; + } + + var expanders = document.querySelectorAll('[data-expands]'); + + Array.prototype.forEach.call(expanders, function (expander) { + var target = document.getElementById(expander.getAttribute('data-expands')); + + expander.addEventListener('click', function () { + toggle(expander, target); + }) + }) +}()); + +/* Menu button */ +(function () { + var button = document.getElementById('menu-button'); + if (button) { + var menu = document.getElementById('patterns-list'); + button.addEventListener('click', function() { + var expanded = this.getAttribute('aria-expanded') === 'true'; + this.setAttribute('aria-expanded', !expanded); + }) + } +}()); + +/* Persist navigation scroll point */ +(function () { + window.onbeforeunload = function () { + var patternsNav = document.getElementById('patterns-nav'); + if (patternsNav) { + var scrollPoint = patternsNav.scrollTop; + localStorage.setItem('scrollPoint', scrollPoint); + } + } + + window.addEventListener('DOMContentLoaded', function () { + if (document.getElementById('patterns-nav')) { + if (window.location.href.indexOf('patterns/') !== -1) { + document.getElementById('patterns-nav').scrollTop = parseInt(localStorage.getItem('scrollPoint')); + } else { + document.getElementById('patterns-nav').scrollTop = 0; + } + } + }) +}()); + +{{ if not .Site.Params.hideHeaderLinks }} + /* Add "link here" links to

headings */ + (function () { + var headings = document.querySelectorAll('h2, h3, h4, h5, h6'); + + Array.prototype.forEach.call(headings, function (heading) { + var id = heading.getAttribute('id'); + + if (id) { + var newHeading = heading.cloneNode(true); + newHeading.setAttribute('tabindex', '-1'); + + var container = document.createElement('div'); + container.setAttribute('class', 'h2-container'); + container.appendChild(newHeading); + + heading.parentNode.insertBefore(container, heading); + + var link = document.createElement('a'); + link.setAttribute('href', '#' + id); + link.innerHTML = ''; + + container.appendChild(link); + + heading.parentNode.removeChild(heading); + } + }) + }()); +{{ end }} + +/* Enable scrolling by keyboard of code samples */ +(function () { + var codeBlocks = document.querySelectorAll('pre, .code-annotated'); + + Array.prototype.forEach.call(codeBlocks, function (block) { + if (block.querySelector('code')) { + block.setAttribute('role', 'region'); + block.setAttribute('aria-label', 'code sample'); + if (block.scrollWidth > block.clientWidth) { + block.setAttribute('tabindex', '0'); + } + } + }); +}()); + +/* Switch and persist theme */ +(function () { + var checkbox = document.getElementById('themer'); + + function persistTheme(val) { + localStorage.setItem('darkTheme', val); + } + + function applyDarkTheme() { + var darkTheme = document.getElementById('darkTheme'); + darkTheme.disabled = false; + } + + function clearDarkTheme() { + var darkTheme = document.getElementById('darkTheme'); + darkTheme.disabled = true; + } + + function defaultDarkTheme() { +{{- with .Site.Params.defaultDarkTheme }} + if (localStorage.getItem('darkTheme') == null) { + persistTheme('true'); + checkbox.checked = true; + } +{{- else }} + if (localStorage.getItem('darkTheme') == null) { + persistTheme('false'); + checkbox.checked = false; + } +{{ end }} + } + + checkbox.addEventListener('change', function () { + defaultDarkTheme(); + if (this.checked) { + applyDarkTheme(); + persistTheme('true'); + } else { + clearDarkTheme(); + persistTheme('false'); + } + }); + + function showTheme() { + if (localStorage.getItem('darkTheme') === 'true') { + applyDarkTheme(); + checkbox.checked = true; + } else { + clearDarkTheme(); + checkbox.checked = false; + } + } + + function showContent() { + document.body.style.visibility = 'visible'; + document.body.style.opacity = 1; + } + + window.addEventListener('DOMContentLoaded', function () { + defaultDarkTheme(); + showTheme(); + showContent(); + }); + +}()); diff --git a/data/principles.json b/data/principles.json new file mode 100644 index 0000000..9864138 --- /dev/null +++ b/data/principles.json @@ -0,0 +1,149 @@ +{ + "title": "Inclusive Design Principles", + "description": "

These Inclusive Design Principles are about putting people first. It's about designing for the needs of people with permanent, temporary, situational, or changing disabilities — all of us really.

They are intended to give anyone involved in the design and development of websites and applications - designers, user experience professionals, developers, product owners, idea makers, innovators, artists and thinkers - a broad approach to inclusive design.

For more background, read about the Inclusive Design Principles on the TPG blog.

", + "authors": [ + "Léonie Watson", + "Henny Swan", + "Ian Pouncey", + "Heydon Pickering" + ], + "principles": [ + { + "title": "Provide comparable experience", + "strapline": "Ensure your interface provides a comparable experience for all so people can accomplish tasks in a way that suits their needs without undermining the quality of the content.", + "description": "Whether out of circumstance, choice, or context people are diverse. As people use different approaches and tools to read and operate interfaces, what the interface offers each user should be comparable in value, quality, and efficiency.", + "examples": [ + { + "title": "Content for alternatives", + "description": "Having a basic alternative, whether it's alt text, a transcript, audio description, or sign language, makes the content accessible but to be equivalent it needs to capture the essence of the original." + }, + { + "title": "Ergonomic features", + "description": "Providing synchronized closed captions makes your video accessible. But making them customizable, color coded, and repositionable provides a more comparable experience." + }, + { + "title": "Notifications", + "description": "Notifications that appear in an interface are visually obvious but require proactive discovery by screen reader users. A comparable experience for blind users, can be achieved by using a live region. The notification then requires no explicit action on the part of the user." + } + ] + }, + { + "title": "Consider situation", + "strapline": "People use your interface in different situations. Make sure your interface delivers a valuable experience to people regardless of their circumstances.", + "description": "People are first time users, established users, users at work, users at home, users on the move, and users under pressure. All of these situations can have an impact. For those who already find interaction challenging, such as those with disabilities, this impact may make usage particularly difficult.", + "examples": [ + { + "title": "Colour contrast", + "description": "When using an interface outdoors, good contrast lessens the impact of bright sunshine." + }, + { + "title": "Context sensitive help", + "description": "Users may need help when they first encounter a complex form or interaction. This help may become redundant, even distracting, as a user becomes more familiar with the form or interaction. Context sensitive help provides the user with choice as to when they access help and better control over the page." + }, + { + "title": "Captions on the go", + "description": "You're aware that the video content you are providing will be consumed on mobile devices, which may be in public spaces where people might prefer to consume the content without being antisocial. For smaller viewports, sound is switched off and captions activated by default." + } + ] + }, + { + "title": "Be consistent", + "strapline": "Use familiar conventions and apply them consistently.", + "description": "Familiar interfaces borrow from well-established patterns. These should be used consistently within the interface to reinforce their meaning and purpose. This should be applied to functionality, behavior, editorial, and presentation. You should say the same things in the same way and users should be able to do the same things in the same way.", + "examples": [ + { + "title": "Consistent design patterns", + "description": "Use consistent web and platform design patterns to help build familiarity and understanding." + }, + { + "title": "Consistent editorial", + "description": "Use plain language consistently across platforms including editorial that is relied on by screen reader users such as text alternatives, headings, labels for buttons and so on. Keeping editorial style consistent is also important e.g. making sure the top of the article always has a clearly marked summary paragraph, making sure bullets always start with a bolded definition." + }, + { + "title": "Consistent page architecture", + "description": "Use consistent page architecture across templates to help people scan and navigate key content." + } + ] + }, + { + "title": "Give control", + "strapline": "Ensure people are in control. People should be able to access and interact with content in their preferred way.", + "description": "Do not suppress or disable the ability to change standard browser and platform settings such as orientation, font size, zoom, and contrast. In addition, avoid content changes that have not been initiated by the user unless there is a way to control it.", + "examples": [ + { + "title": "Scrolling control", + "description": "'Infinite scrolling' can be problematic, especially for users navigating by keyboard because they can't get past the stream of refreshing content. Give the option to turn off this feature and replace it with a 'load more' button." + }, + { + "title": "Make it stop", + "description": "Some users find that animations or parallax scrolling cause nausea, and others find them plain distracting. Where they play automatically, they should at least be easy to stop, by providing prominent playback controls." + }, + { + "title": "Allow zoom", + "description": "There are many reasons why a user may want to operate the pinch-to-zoom gesture on their touch device. Make sure it is not suppressed, and that the content does not get obscured when it is put to use." + } + ] + }, + { + "title": "Offer choice", + "strapline": "Consider providing different ways for people to complete tasks, especially those that are complex or non standard.", + "description": "There is often more than one way to complete a task. You cannot assume what someone's preferred way might be. By providing alternatives for layout and task completion, you offer people choices that suit them and their circumstances at the time.", + "examples": [ + { + "title" : "Multiple ways to complete an action", + "description": "Where appropriate, provide multiple ways to complete an action. On mobile swipe to delete an item can be supported together with an edit button that allows you to select items then delete. An example of this is in iOS mail." + }, + { + "title": "Layout", + "description": "Where there are long lists of content consider offering a grid or list layout option. This supports people who may want larger images on screen or smaller rows." + }, + { + "title": "Accessible alternatives", + "description": "Alternative ways of presenting data, such as data tables for info graphics, should be available to all users, as an option rather than a hidden link just for screen reader users. Accessible alternatives can benefit not just a specific target group but all users as long as we offer the choice." + } + ] + }, + { + "title": "Prioritise content", + "strapline": "Help users focus on core tasks, features, and information by prioritising them within the content and layout.", + "description": "Interfaces can be difficult to understand when core features are not clearly exposed and prioritised. A site or application may provide lots of information and functionality, but people should be able to focus on one thing at a time. Identify the core purpose of the interface, and then the content and features needed to fulfill that purpose.", + "examples": [ + { + "title": "Keep task focused", + "description": "Progressively reveal features and content when needed, not all in one go." + }, + { + "title": "Prioritising tasks", + "description": "An email application is principally for writing and reading email. The 'compose' button is, therefore, present on all screens, and early in the focus order. The inbox is prioritised over other lists of email, such as 'sent' and 'spam' messages. Less used features such as tagging or organizing email into folders appear later in the focus order, as they will generally only be used when the primary task of reading the email is complete." + }, + { + "title": "Prioritising content", + "description": "The primary content on a news article page is the story, therefore it should come before other content, both visually and in the source order. Related content, such as similar articles, should follow it, and unrelated content after that." + }, + { + "title": "Prioritising editorial", + "description": "Editorial for links, headings and buttons should use plain language and put the primary text first. This applies to both visible and hidden text. This makes the text easy to scan both visually and audibly for screen reader users. Plain language also benefits non native speakers and is easier to translate." + } + ] + }, + { + "title": "Add value", + "strapline": "Consider the value of features and how they improve the experience for different users.", + "description": "Features should add value to the user experience by providing efficient and diverse ways to find and interact with content. Consider device features such as voice, geolocation, camera and vibration API's, and how integration with connected devices or a second screen could provide choice.", + "examples": [ + { + "title": "Integration with connected devices or second screen", + "description": "Using voice interfaces to control multimedia, search for content, output from music or TV adds value for people who struggle to use other interfaces." + }, + { + "title": "Integration with platform APIs", + "description": "Enhance functionality using platform features. The vibration API makes notifications more usable by deaf and hard of hearing people while the geolocation API makes it easier for people with mobility impairments to use location based services." + }, + { + "title": "Make task completion easier", + "description": "Add a 'Show password' button to input fields so users can verify they have correctly inputted text, or add touch identification for password protected areas." + } + ] + } + ] +} diff --git a/data/wcag.json b/data/wcag.json new file mode 100644 index 0000000..8192898 --- /dev/null +++ b/data/wcag.json @@ -0,0 +1,1427 @@ +[ + { + "ref_id": "1.1.1", + "title": "Non-text Content", + "description": "All non-text content that is presented to the user has a text alternative that serves the equivalent purpose, except for the situations listed below. (", + "url": "https://www.w3.org/TR/WCAG20/#text-equiv-all", + "level": "A", + "special_cases": [ + { + "type": "exception", + "title": "Controls, Input", + "description": "If non-text content is a control or accepts user input, then it has a name that describes its purpose. (Refer to Guideline 4.1 for additional requirements for controls and content that accepts user input.)" + }, + { + "type": "exception", + "title": "Time-Based Media", + "description": "If non-text content is time-based media, then text alternatives at least provide descriptive identification of the non-text content. (Refer to Guideline 1.2 for additional requirements for media.)" + }, + { + "type": "exception", + "title": "Test", + "description": "If non-text content is a test or exercise that would be invalid if presented in text, then text alternatives at least provide descriptive identification of the non-text content." + }, + { + "type": "exception", + "title": "Sensory", + "description": "If non-text content is primarily intended to create a specific sensory experience, then text alternatives at least provide descriptive identification of the non-text content." + }, + { + "type": "exception", + "title": "CAPTCHA", + "description": "If the purpose of non-text content is to confirm that content is being accessed by a person rather than a computer, then text alternatives that identify and describe the purpose of the non-text content are provided, and alternative forms of CAPTCHA using output modes for different types of sensory perception are provided to accommodate different disabilities." + }, + { + "type": "exception", + "title": "Decoration, Formatting, Invisible", + "description": "If non-text content is pure decoration, is used only for visual formatting, or is not presented to users, then it is implemented in a way that it can be ignored by assistive technology." + } + ], + "notes": null, + "references": [ + { + "title": "How to Meet 1.1.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-text-equiv-all" + }, + { + "title": "Understanding 1.1.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/text-equiv-all.html" + } + ] + }, + { + "ref_id": "1.2.1", + "title": "Audio-only and Video-only (Prerecorded", + "description": "For prerecorded audio-only and prerecorded video-only media, the following are true, except when the audio or video is a media alternative for text and is clearly labeled as such.", + "url": "https://www.w3.org/TR/WCAG20/", + "level": "A", + "special_cases": [ + { + "type": "all_true", + "title": "Prerecorded Audio-only", + "description": "An alternative for time-based media is provided that presents equivalent information for prerecorded audio-only content." + }, + { + "type": "all_true", + "title": "Prerecorded Video-only", + "description": "Either an alternative for time-based media or an audio track is provided that presents equivalent information for prerecorded video-only content" + } + ], + "notes": null, + "references": [ + { + "title": "How to Meet 1.2.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-media-equiv-av-only-alt" + }, + { + "title": "Understanding 1.2.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-av-only-alt.html" + } + ] + }, + { + "ref_id": "1.2.2", + "title": "Captions (Prerecorded)", + "description": "Captions are provided for all prerecorded audio content in synchronized media, except when the media is a media alternative for text and is clearly labeled as such", + "url": "https://www.w3.org/TR/WCAG20/#media-equiv-captions", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.2.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-media-equiv-captions" + }, + { + "title": "Understanding 1.2.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-captions.html" + } + ] + }, + { + "ref_id": "1.2.3", + "title": "Audio Description or Media Alternative (Prerecorded)", + "description": "An alternative for time-based media or audio description of the prerecorded video content is provided for synchronized media, except when the media is a media alternative for text and is clearly labeled as such", + "url": "https://www.w3.org/TR/WCAG20/#media-equiv-audio-desc", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.2.3", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-media-equiv-audio-desc" + }, + { + "title": "Understanding 1.2.3", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-audio-desc.html" + } + ] + }, + { + "ref_id": "1.2.4", + "title": "Captions (Live)", + "description": "Captions are provided for all live audio content in synchronized media", + "url": "https://www.w3.org/TR/WCAG20/#media-equiv-real-time-captions", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.2.4", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-media-equiv-real-time-captions" + }, + { + "title": "Understanding 1.2.4", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-real-time-captions.html" + } + ] + }, + { + "ref_id": "1.2.5", + "title": "Audio Description (Prerecorded)", + "description": "Audio description is provided for all prerecorded video content in synchronized media", + "url": "https://www.w3.org/TR/WCAG20/#media-equiv-audio-desc-only", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.2.5", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-media-equiv-audio-desc-only" + }, + { + "title": "Understanding 1.2.5", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-audio-desc-only.html" + } + ] + }, + { + "ref_id": "1.2.6", + "title": "Sign Language (Prerecorded)", + "description": "Sign language interpretation is provided for all prerecorded audio content in synchronized media.", + "url": "https://www.w3.org/TR/WCAG20/#media-equiv-sign", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.2.6", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-media-equiv-sign" + }, + { + "title": "Understanding 1.2.6", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-sign.html" + } + ] + }, + { + "ref_id": "1.2.7", + "title": "Extended Audio Description (Prerecorded)", + "description": "Where pauses in foreground audio are insufficient to allow audio descriptions to convey the sense of the video, extended audio description is provided for all prerecorded video content in synchronized media", + "url": "https://www.w3.org/TR/WCAG20/#media-equiv-extended-ad", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.2.7", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-media-equiv-extended-ad" + }, + { + "title": "Understanding 1.2.7", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-extended-ad.html" + } + ] + }, + { + "ref_id": "1.2.8", + "title": "Media Alternative (Prerecorded)", + "description": "An alternative for time-based media is provided for all prerecorded synchronized media and for all prerecorded video-only media", + "url": "https://www.w3.org/TR/WCAG20/#media-equiv-text-doc", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.2.8", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-media-equiv-text-doc" + }, + { + "title": "Understanding 1.2.8", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-text-doc.html" + } + ] + }, + { + "ref_id": "1.2.9", + "title": "Audio-only (Live)", + "description": " An alternative for time-based media that presents equivalent information for live audio-only content is provided.", + "url": "https://www.w3.org/TR/WCAG20/#media-equiv-live-audio-only", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.2.9", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-media-equiv-live-audio-only" + }, + { + "title": "Understanding 1.2.9", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-live-audio-only.html" + } + ] + }, + { + "ref_id": "1.3.1", + "title": "Info and Relationships", + "description": "Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text.", + "url": "https://www.w3.org/TR/WCAG20/#content-structure-separation-programmatic", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.3.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-content-structure-separation-programmatic" + }, + { + "title": "Understanding 1.3.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/content-structure-separation-programmatic.html" + } + ] + }, + { + "ref_id": "1.3.2", + "title": "Meaningful Sequence", + "description": "When the sequence in which content is presented affects its meaning, a correct reading sequence can be programmatically determined.", + "url": "https://www.w3.org/TR/WCAG20/#content-structure-separation-sequence", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.3.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-content-structure-separation-sequence" + }, + { + "title": "Understanding 1.3.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/content-structure-separation-sequence.html" + } + ] + }, + { + "ref_id": "1.3.3", + "title": "Sensory Characteristics", + "description": "Instructions provided for understanding and operating content do not rely solely on sensory characteristics of components such as shape, size, visual location, orientation, or sound", + "url": "https://www.w3.org/TR/WCAG20/#content-structure-separation-understanding", + "level": "A", + "special_cases": null, + "notes": [ + { + "content": "For requirements related to color, refer to Guideline 1.4." + } + ], + "references": [ + { + "title": "How to Meet 1.3.3", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-content-structure-separation-understanding" + }, + { + "title": "Understanding 1.3.3", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/content-structure-separation-understanding.html" + } + ] + }, + { + "ref_id": "1.4.1", + "title": "Use of Color", + "description": "Color is not used as the only visual means of conveying information, indicating an action, prompting a response, or distinguishing a visual element.", + "url": "https://www.w3.org/TR/WCAG20/#visual-audio-contrast-without-color", + "level": "A", + "special_cases": null, + "notes": [ + { + "content": "This success criterion addresses color perception specifically. Other forms of perception are covered in Guideline 1.3 including programmatic access to color and other visual presentation coding." + } + ], + "references": [ + { + "title": "How to Meet 1.4.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast-without-color" + }, + { + "title": "Understanding 1.4.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-without-color.html" + } + ] + }, + { + "ref_id": "1.4.2", + "title": "Audio Control", + "description": "If any audio on a Web page plays automatically for more than 3 seconds, either a mechanism is available to pause or stop the audio, or a mechanism is available to control audio volume independently from the overall system volume level. (Level A)", + "url": "https://www.w3.org/TR/WCAG20/#visual-audio-contrast-dis-audio", + "level": "A", + "special_cases": null, + "notes": [ + { + "content": "Note: Since any content that does not meet this success criterion can interfere with a user's ability to use the whole page, all content on the Web page (whether or not it is used to meet other success criteria) must meet this success criterion. See Conformance Requirement 5: Non-Interference. (https://www.w3.org/TR/WCAG20/#cc5)" + } + ], + "references": [ + { + "title": "How to Meet 1.4.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast-dis-audio" + }, + { + "title": "Understanding 1.4.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-dis-audio.html" + } + ] + }, + { + "ref_id": "1.4.3", + "title": "Contrast (Minimum)", + "description": " The visual presentation of text and images of text has a contrast ratio of at least 4.5:1, except for the following: ", + "url": "https://www.w3.org/TR/WCAG20/#visual-audio-contrast-contrast", + "level": "AA", + "special_cases": [ + { + "type": "exception", + "title": "Large Text", + "description": "Large-scale text and images of large-scale text have a contrast ratio of at least 3:1" + }, + { + "type": "exception", + "title": "Incidental", + "description": "Text or images of text that are part of an inactive user interface component, that are pure decoration, that are not visible to anyone, or that are part of a picture that contains significant other visual content, have no contrast requirement." + }, + { + "type": "exception", + "title": "Logotypes", + "description": "Text that is part of a logo or brand name has no minimum contrast requirement." + } + ], + "notes": null, + "references": [ + { + "title": "How to Meet 1.4.3", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast-contrast" + }, + { + "title": "Understanding 1.4.3", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html" + } + ] + }, + { + "ref_id": "1.4.4", + "title": "Resize text", + "description": "Except for captions and images of text, text can be resized without assistive technology up to 200 percent without loss of content or functionality", + "url": "https://www.w3.org/TR/WCAG20/#visual-audio-contrast-scale", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 1.4.4", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast-scale" + }, + { + "title": "Understanding 1.4.4", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-scale.html" + } + ] + }, + { + "ref_id": "1.4.5", + "title": "Images of Text", + "description": "If the technologies being used can achieve the visual presentation, text is used to convey information rather than images of text except for the following", + "url": "https://www.w3.org/TR/WCAG20/#visual-audio-contrast-text-presentation", + "level": "AA", + "special_cases": [ + { + "type": "exception", + "title": "Customizable", + "description": "The image of text can be visually customized to the user's requirements" + }, + { + "type": "exception", + "title": "Essential", + "description": "A particular presentation of text is essential to the information being conveyed" + } + ], + "notes": [ + { + "content": "Logotypes (text that is part of a logo or brand name) are considered essential" + } + ], + "references": [ + { + "title": "How to Meet 1.4.5", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast-text-presentation" + }, + { + "title": "Understanding 1.4.5", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-text-presentation.html" + } + ] + }, + { + "ref_id": "1.4.6", + "title": "Contrast (Enhanced)", + "description": "The visual presentation of text and images of text has a contrast ratio of at least 7:1, except for the following: ", + "url": "https://www.w3.org/TR/WCAG20/#visual-audio-contrast7", + "level": "AAA", + "special_cases": [ + { + "type": "exception", + "title": "Large Text", + "description": "Large-scale text and images of large-scale text have a contrast ratio of at least 4.5:1" + }, + { + "type": "exception", + "title": "Text or images of text that are part of an inactive user interface component, that are pure decoration, that are not visible to anyone, or that are part of a picture that contains significant other visual content, have no contrast requirement.", + "description": "Incidental" + }, + { + "type": "exception", + "title": "Logotypes", + "description": "Text that is part of a logo or brand name has no minimum contrast requirement." + } + ], + "notes": null, + "references": [ + { + "title": "How to Meet 1.4.6", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast7" + }, + { + "title": "Understanding 1.4.6", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html" + } + ] + }, + { + "ref_id": "1.4.7", + "title": "Low or No Background Audio", + "description": "For prerecorded audio-only content that (1) contains primarily speech in the foreground, (2) is not an audio CAPTCHA or audio logo, and (3) is not vocalization intended to be primarily musical expression such as singing or rapping, at least one of the following is true: (Level AAA)", + "url": "https://www.w3.org/TR/WCAG20/#visual-audio-contrast-noaudio", + "level": "AAA", + "special_cases": [ + { + "type": "at_least_one", + "title": "No Background", + "description": "The audio does not contain background sounds." + }, + { + "type": "at_least_one", + "title": "Turn Off", + "description": "The background sounds can be turned off." + }, + { + "type": "at_least_one", + "title": "20 dB", + "description": "The background sounds are at least 20 decibels lower than the foreground speech content, with the exception of occasional sounds that last for only one or two seconds." + } + ], + "notes": [ + { + "content": "Per the definition of 'decibel,' background sound that meets this requirement will be approximately four times quieter than the foreground speech content." + } + ], + "references": [ + { + "title": "How to Meet 1.4.7", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast-noaudio" + }, + { + "title": "Understanding 1.4.7" + } + ] + }, + { + "ref_id": "1.4.8", + "title": "Visual Presentation", + "description": "For the visual presentation of blocks of text, a mechanism is available to achieve the following:", + "url": "https://www.w3.org/TR/WCAG20/#visual-audio-contrast-visual-presentation", + "level": "AAA", + "special_cases": [ + { + "type": "all_true", + "title": "Foreground and background colors can be selected by the user." + }, + { + "type": "all_true", + "title": "Width is no more than 80 characters or glyphs (40 if CJK)" + }, + { + "type": "all_true", + "title": "Text is not justified (aligned to both the left and the right margins)." + }, + { + "type": "all_true", + "title": "Line spacing (leading) is at least space-and-a-half within paragraphs, and paragraph spacing is at least 1.5 times larger than the line spacing." + }, + { + "type": "all_true", + "title": "Text can be resized without assistive technology up to 200 percent in a way that does not require the user to scroll horizontally to read a line of text on a full-screen window." + } + ], + "notes": null, + "references": [ + { + "title": "How to Meet 1.4.8", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast-visual-presentation" + }, + { + "title": "Understanding 1.4.8", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-visual-presentation.html" + } + ] + }, + { + "ref_id": "1.4.9", + "title": "Images of Text (No Exception)", + "description": "Images of text are only used for pure decoration or where a particular presentation of text is essential to the information being conveyed.", + "url": "https://www.w3.org/TR/WCAG20/", + "level": "AAA", + "special_cases": null, + "notes": [ + { + "content": "Logotypes (text that is part of a logo or brand name) are considered essential." + } + ], + "references": [ + { + "title": "How to Meet 1.4.9", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-visual-audio-contrast-text-images" + }, + { + "title": "Understanding 1.4.9", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-text-images.html" + } + ] + }, + { + "ref_id": "2.1.1", + "title": "Keyboard", + "description": "All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints", + "url": "https://www.w3.org/TR/WCAG20/#keyboard-operation-keyboard-operable", + "level": "A", + "special_cases": null, + "notes": [ + { + "content": "This exception relates to the underlying function, not the input technique. For example, if using handwriting to enter text, the input technique (handwriting) requires path-dependent input but the underlying function (text input) does not." + }, + { + "content": "This does not forbid and should not discourage providing mouse input or other input methods in addition to keyboard operation." + } + ], + "references": [ + { + "title": "How to Meet 2.1.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-keyboard-operation-keyboard-operable" + }, + { + "title": "Understanding 2.1.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/keyboard-operation-keyboard-operable.html" + } + ] + }, + { + "ref_id": "2.1.2", + "title": "No Keyboard Trap", + "description": "If keyboard focus can be moved to a component of the page using a keyboard interface, then focus can be moved away from that component using only a keyboard interface, and, if it requires more than unmodified arrow or tab keys or other standard exit methods, the user is advised of the method for moving focus away.", + "url": "https://www.w3.org/TR/WCAG20/#keyboard-operation-trapping", + "level": "A", + "special_cases": null, + "notes": [ + { + "content": "Since any content that does not meet this success criterion can interfere with a user's ability to use the whole page, all content on the Web page (whether it is used to meet other success criteria or not) must meet this success criterion. See Conformance Requirement 5: Non-Interference. (https://www.w3.org/TR/WCAG20/#cc5)" + } + ], + "references": [ + { + "title": "How to Meet 2.1.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-keyboard-operation-trapping" + }, + { + "title": "Understanding 2.1.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/keyboard-operation-trapping.html" + } + ] + }, + { + "ref_id": "2.1.3", + "title": "Keyboard (No Exception)", + "description": "All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes.", + "url": "https://www.w3.org/TR/WCAG20/#keyboard-operation-all-funcs", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.1.3", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-keyboard-operation-all-funcs" + }, + { + "title": "Understanding 2.1.3", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/keyboard-operation-all-funcs.html" + } + ] + }, + { + "ref_id": "2.2.1", + "title": "Timing Adjustable", + "description": "For each time limit that is set by the content, at least one of the following is true:", + "url": "https://www.w3.org/TR/WCAG20/#time-limits-required-behaviors", + "level": "A", + "special_cases": [ + { + "type": "at_least_one", + "title": "Turn off", + "description": "The user is allowed to turn off the time limit before encountering it; or" + }, + { + "type": "at_least_one", + "title": "Adjust", + "description": "The user is allowed to adjust the time limit before encountering it over a wide range that is at least ten times the length of the default setting; or" + }, + { + "type": "at_least_one", + "title": "Extend", + "description": "The user is warned before time expires and given at least 20 seconds to extend the time limit with a simple action (for example, 'press the space bar'), and the user is allowed to extend the time limit at least ten times; or" + }, + { + "type": "at_least_one", + "title": "Real-time Exception", + "description": "The time limit is a required part of a real-time event (for example, an auction), and no alternative to the time limit is possible; or" + }, + { + "type": "at_least_one", + "title": "Essential Exception", + "description": "The time limit is essential and extending it would invalidate the activity; or" + }, + { + "type": "at_least_one", + "title": "20 Hour Exception", + "description": "The time limit is longer than 20 hours." + } + ], + "notes": [ + { + "content": "This success criterion helps ensure that users can complete tasks without unexpected changes in content or context that are a result of a time limit. This success criterion should be considered in conjunction with Success Criterion 3.2.1 (https://www.w3.org/TR/WCAG20/#consistent-behavior-receive-focus), which puts limits on changes of content or context as a result of user action." + } + ], + "references": [ + { + "title": "How to Meet 2.2.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-time-limits-required-behaviors" + }, + { + "title": "Understanding 2.2.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/time-limits-required-behaviors.html" + } + ] + }, + { + "ref_id": "2.2.2", + "title": "Pause, Stop, Hide", + "description": "For moving, blinking, scrolling, or auto-updating information, all of the following are true:", + "url": "https://www.w3.org/TR/WCAG20/#time-limits-pause", + "level": "A", + "special_cases": [ + { + "type": "all_true", + "title": "Moving, blinking, scrolling", + "description": "For any moving, blinking or scrolling information that (1) starts automatically, (2) lasts more than five seconds, and (3) is presented in parallel with other content, there is a mechanism for the user to pause, stop, or hide it unless the movement, blinking, or scrolling is part of an activity where it is essential; and" + }, + { + "type": "all_true", + "title": "Auto-updating", + "description": "For any auto-updating information that (1) starts automatically and (2) is presented in parallel with other content, there is a mechanism for the user to pause, stop, or hide it or to control the frequency of the update unless the auto-updating is part of an activity where it is essential." + } + ], + "notes": [ + { + "content": "For requirements related to flickering or flashing content, refer to Guideline 2.3. (https://www.w3.org/TR/WCAG20/#seizure)" + }, + { + "content": "Since any content that does not meet this success criterion can interfere with a user's ability to use the whole page, all content on the Web page (whether it is used to meet other success criteria or not) must meet this success criterion. See Conformance Requirement 5: Non-Interference (https://www.w3.org/TR/WCAG20/#cc5)" + }, + { + "content": "Content that is updated periodically by software or that is streamed to the user agent is not required to preserve or present information that is generated or received between the initiation of the pause and resuming presentation, as this may not be technically possible, and in many situations could be misleading to do so." + }, + { + "content": "An animation that occurs as part of a preload phase or similar situation can be considered essential if interaction cannot occur during that phase for all users and if not indicating progress could confuse users or cause them to think that content was frozen or broken." + } + ], + "references": [ + { + "title": "How to Meet 2.2.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-time-limits-pause" + }, + { + "title": "Understanding 2.2.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/time-limits-pause.html" + } + ] + }, + { + "ref_id": "2.2.3", + "title": "No Timing", + "description": "Timing is not an essential part of the event or activity presented by the content, except for non-interactive synchronized media and real-time events", + "url": "https://www.w3.org/TR/WCAG20/#time-limits-no-exceptions", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.2.3", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-time-limits-no-exceptions" + }, + { + "title": "Understanding 2.2.3", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/time-limits-no-exceptions.html" + } + ] + }, + { + "ref_id": "2.2.4", + "title": "Interruptions", + "description": "Interruptions can be postponed or suppressed by the user, except interruptions involving an emergency.", + "url": "https://www.w3.org/TR/WCAG20/#time-limits-postponed", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.2.4", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-time-limits-postponed" + }, + { + "title": "Understanding 2.2.4", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/time-limits-postponed.html" + } + ] + }, + { + "ref_id": "2.2.5", + "title": "Re-authenticating", + "description": "When an authenticated session expires, the user can continue the activity without loss of data after re-authenticating.", + "url": "https://www.w3.org/TR/WCAG20/#time-limits-server-timeout", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.2.5", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-time-limits-server-timeout" + }, + { + "title": "Understanding 2.2.5", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/time-limits-server-timeout.html" + } + ] + }, + { + "ref_id": "2.3.1", + "title": "Three Flashes or Below Threshold", + "description": "Web pages do not contain anything that flashes more than three times in any one second period, or the flash is below the general flash and red flash thresholds", + "url": "https://www.w3.org/TR/WCAG20/#seizure-does-not-violate", + "level": "A", + "special_cases": null, + "notes": [ + { + "content": "Since any content that does not meet this success criterion can interfere with a user's ability to use the whole page, all content on the Web page (whether it is used to meet other success criteria or not) must meet this success criterion. See Conformance Requirement 5: Non-Interference. (https://www.w3.org/TR/WCAG20/#cc5)" + } + ], + "references": [ + { + "title": "How to Meet 2.3.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-seizure-does-not-violate" + }, + { + "title": "Understanding 2.3.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/seizure-does-not-violate.html" + } + ] + }, + { + "ref_id": "2.3.2", + "title": "Three Flashes", + "description": "Web pages do not contain anything that flashes more than three times in any one second period.", + "url": "https://www.w3.org/TR/WCAG20/#seizure-three-times", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.3.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-seizure-three-times" + }, + { + "title": "Understanding 2.3.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/seizure-three-times.html" + } + ] + }, + { + "ref_id": "2.4.1", + "title": "Bypass Blocks", + "description": "A mechanism is available to bypass blocks of content that are repeated on multiple Web pages.", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-skip", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.4.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-skip" + }, + { + "title": "Understanding 2.4.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-skip.html" + } + ] + }, + { + "ref_id": "2.4.2", + "title": "Page Titled", + "description": "Web pages have titles that describe topic or purpose.", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-title", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.4.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-title" + }, + { + "title": "Understanding 2.4.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-title.html" + } + ] + }, + { + "ref_id": "2.4.3", + "title": "Focus Order", + "description": " If a Web page can be navigated sequentially and the navigation sequences affect meaning or operation, focusable components receive focus in an order that preserves meaning and operability", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-focus-order", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.4.3", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-focus-order" + }, + { + "title": "Understanding 2.4.3", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-focus-order.html" + } + ] + }, + { + "ref_id": "2.4.4", + "title": "Link Purpose (In Context)", + "description": "The purpose of each link can be determined from the link text alone or from the link text together with its programmatically determined link context, except where the purpose of the link would be ambiguous to users in general", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-refs", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.4.4", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-refs" + }, + { + "title": "Understanding 2.4.4", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-refs.html" + } + ] + }, + { + "ref_id": "2.4.5", + "title": "Multiple Ways", + "description": "More than one way is available to locate a Web page within a set of Web pages except where the Web Page is the result of, or a step in, a process.", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-mult-loc", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.4.5", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-mult-loc" + }, + { + "title": "Understanding 2.4.5", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-mult-loc.html" + } + ] + }, + { + "ref_id": "2.4.6", + "title": "Headings and Labels", + "description": "Headings and labels describe topic or purpose.", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-descriptive", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.4.6", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-descriptive" + }, + { + "title": "Understanding 2.4.6", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-descriptive.html" + } + ] + }, + { + "ref_id": "2.4.7", + "title": "Focus Visible", + "description": "Any keyboard operable user interface has a mode of operation where the keyboard focus indicator is visible.", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-focus-visible", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.4.7", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-focus-visible" + }, + { + "title": "Understanding 2.4.7", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-focus-visible.html" + } + ] + }, + { + "ref_id": "2.4.8", + "title": "Location", + "description": "Information about the user's location within a set of Web pages is available", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-location", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.4.8", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-location" + }, + { + "title": "Understanding 2.4.8", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-location.html" + } + ] + }, + { + "ref_id": "2.4.9", + "title": "Link Purpose (Link Only)", + "description": "A mechanism is available to allow the purpose of each link to be identified from link text alone, except where the purpose of the link would be ambiguous to users in general.", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-link", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 2.4.9", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-link" + }, + { + "title": "Understanding 2.4.9", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-link.html" + } + ] + }, + { + "ref_id": "2.4.10", + "title": "Section Headings", + "description": "Section headings are used to organize the content", + "url": "https://www.w3.org/TR/WCAG20/#navigation-mechanisms-headings", + "level": "AAA", + "special_cases": null, + "notes": [ + { + "content": "'Heading' is used in its general sense and includes titles and other ways to add a heading to different types of content." + }, + { + "content": "This success criterion covers sections within writing, not user interface components. User Interface components are covered under Success Criterion 4.1.2. (http://www.w3.org/TR/2008/REC-WCAG20-20081211/#ensure-compat-rsv)" + } + ], + "references": [ + { + "title": "How to Meet 2.4.10", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-navigation-mechanisms-headings" + }, + { + "title": "Understanding 2.4.10", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-headings.html" + } + ] + }, + { + "ref_id": "3.1.1", + "title": "Language of Page", + "description": "The default human language of each Web page can be programmatically determined.", + "url": "https://www.w3.org/TR/WCAG20/#meaning-doc-lang-id", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.1.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-meaning-doc-lang-id" + }, + { + "title": "Understanding 3.1.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-doc-lang-id.html" + } + ] + }, + { + "ref_id": "3.1.2", + "title": "Language of Parts", + "description": "The human language of each passage or phrase in the content can be programmatically determined except for proper names, technical terms, words of indeterminate language, and words or phrases that have become part of the vernacular of the immediately surrounding text.", + "url": "https://www.w3.org/TR/WCAG20/#meaning-other-lang-id", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.1.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-meaning-other-lang-id" + }, + { + "title": "Understanding 3.1.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-other-lang-id.html" + } + ] + }, + { + "ref_id": "3.1.3", + "title": "Unusual Words", + "description": "A mechanism is available for identifying specific definitions of words or phrases used in an unusual or restricted way, including idioms and jargon", + "url": "https://www.w3.org/TR/WCAG20/#meaning-idioms", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.1.3", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-meaning-idioms" + }, + { + "title": "Understanding 3.1.3", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-idioms.html" + } + ] + }, + { + "ref_id": "3.1.4", + "title": "Abbreviations", + "description": "A mechanism for identifying the expanded form or meaning of abbreviations is available.", + "url": "https://www.w3.org/TR/WCAG20/#meaning-located", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.1.4", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-meaning-located" + }, + { + "title": "Understanding 3.1.4", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-located.html" + } + ] + }, + { + "ref_id": "3.1.5", + "title": "Reading Level", + "description": "When text requires reading ability more advanced than the lower secondary education level after removal of proper names and titles, supplemental content, or a version that does not require reading ability more advanced than the lower secondary education level, is available.", + "url": "https://www.w3.org/TR/WCAG20/#meaning-supplements", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.1.5", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-meaning-supplements" + }, + { + "title": "Understanding 3.1.5", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-supplements.html" + } + ] + }, + { + "ref_id": "3.1.6", + "title": "Pronunciation", + "description": "A mechanism is available for identifying specific pronunciation of words where meaning of the words, in context, is ambiguous without knowing the pronunciation", + "url": "https://www.w3.org/TR/WCAG20/#meaning-pronunciation", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.1.6", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-meaning-pronunciation" + }, + { + "title": "Understanding 3.1.6", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-pronunciation.html" + } + ] + }, + { + "ref_id": "3.2.1", + "title": "On Focus", + "description": "When any component receives focus, it does not initiate a change of context", + "url": "https://www.w3.org/TR/WCAG20/#consistent-behavior-receive-focus", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.2.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-consistent-behavior-receive-focus" + }, + { + "title": "Understanding 3.2.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/consistent-behavior-receive-focus.html" + } + ] + }, + { + "ref_id": "3.2.2", + "title": "On Input", + "description": "Changing the setting of any user interface component does not automatically cause a change of context unless the user has been advised of the behavior before using the component.", + "url": "https://www.w3.org/TR/WCAG20/#consistent-behavior-unpredictable-change", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.2.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-consistent-behavior-unpredictable-change" + }, + { + "title": "Understanding 3.2.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/consistent-behavior-unpredictable-change.html" + } + ] + }, + { + "ref_id": "3.2.3", + "title": "Consistent Navigation", + "description": "Navigational mechanisms that are repeated on multiple Web pages within a set of Web pages occur in the same relative order each time they are repeated, unless a change is initiated by the user", + "url": "https://www.w3.org/TR/WCAG20/#consistent-behavior-consistent-locations", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.2.3", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-consistent-behavior-consistent-locations" + }, + { + "title": "Understanding 3.2.3", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/consistent-behavior-consistent-locations.html" + } + ] + }, + { + "ref_id": "3.2.4", + "title": "Consistent Identification", + "description": "Components that have the same functionality within a set of Web pages are identified consistently.", + "url": "https://www.w3.org/TR/WCAG20/#consistent-behavior-consistent-functionality", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.2.4", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-consistent-behavior-consistent-functionality" + }, + { + "title": "Understanding 3.2.4", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/consistent-behavior-consistent-functionality.html" + } + ] + }, + { + "ref_id": "3.2.5", + "title": "Change on Request", + "description": "Changes of context are initiated only by user request or a mechanism is available to turn off such changes", + "url": "https://www.w3.org/TR/WCAG20/#consistent-behavior-no-extreme-changes-context", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.2.5", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-consistent-behavior-no-extreme-changes-context" + }, + { + "title": "Understanding 3.2.5", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/consistent-behavior-no-extreme-changes-context.html" + } + ] + }, + { + "ref_id": "3.3.1", + "title": "Error Identification", + "description": "If an input error is automatically detected, the item that is in error is identified and the error is described to the user in text", + "url": "https://www.w3.org/TR/WCAG20/#minimize-error-identified", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.3.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-minimize-error-identified" + }, + { + "title": "Understanding 3.3.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-identified.html" + } + ] + }, + { + "ref_id": "3.3.2", + "title": "Labels or Instructions", + "description": "Labels or instructions are provided when content requires user input.", + "url": "https://www.w3.org/TR/WCAG20/#minimize-error-cues", + "level": "A", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.3.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-minimize-error-cues" + }, + { + "title": "Understanding 3.3.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-cues.html" + } + ] + }, + { + "ref_id": "3.3.3", + "title": "Error Suggestion", + "description": "If an input error is automatically detected and suggestions for correction are known, then the suggestions are provided to the user, unless it would jeopardize the security or purpose of the content", + "url": "https://www.w3.org/TR/WCAG20/#minimize-error-suggestions", + "level": "AA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.3.3", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-minimize-error-suggestions" + }, + { + "title": "Understanding 3.3.3", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-suggestions.html" + } + ] + }, + { + "ref_id": "3.3.4", + "title": "Error Prevention (Legal, Financial, Data", + "description": " For Web pages that cause legal commitments or financial transactions for the user to occur, that modify or delete user-controllable data in data storage systems, or that submit user test responses, at least one of the following is true:", + "url": "https://www.w3.org/TR/WCAG20/#minimize-error-reversible", + "level": "AA", + "special_cases": [ + { + "type": "at_least_one", + "title": "Reversible", + "description": "Submissions are reversible." + }, + { + "type": "at_least_one", + "title": "Checked", + "description": "Data entered by the user is checked for input errors and the user is provided an opportunity to correct them." + }, + { + "type": "at_least_one", + "title": "Confirmed", + "description": "A mechanism is available for reviewing, confirming, and correcting information before finalizing the submission." + } + ], + "notes": null, + "references": [ + { + "title": "How to Meet 3.3.4", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-minimize-error-reversible" + }, + { + "title": "Understanding 3.3.4", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-reversible.html" + } + ] + }, + { + "ref_id": "3.3.5", + "title": "Help", + "description": "Context-sensitive help is available.", + "url": "https://www.w3.org/TR/WCAG20/#minimize-error-context-help", + "level": "AAA", + "special_cases": null, + "notes": null, + "references": [ + { + "title": "How to Meet 3.3.5", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-minimize-error-context-help" + }, + { + "title": "Understanding 3.3.5", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-context-help.html" + } + ] + }, + { + "ref_id": "3.3.6", + "title": "Error Prevention (All)", + "description": "For Web pages that require the user to submit information, at least one of the following is true:", + "url": "https://www.w3.org/TR/WCAG20/#minimize-error-reversible-all", + "level": "AAA", + "special_cases": [ + { + "type": "at_least_one", + "title": "Reversible", + "description": "Submissions are reversible." + }, + { + "type": "at_least_one", + "title": "Checked", + "description": "Data entered by the user is checked for input errors and the user is provided an opportunity to correct them." + }, + { + "type": "at_least_one", + "title": "Confirmed", + "description": "A mechanism is available for reviewing, confirming, and correcting information before finalizing the submission." + } + ], + "notes": null, + "references": [ + { + "title": "How to Meet 3.3.6", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-minimize-error-reversible-all" + }, + { + "title": "Understanding 3.3.6", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-reversible-all.html" + } + ] + }, + { + "ref_id": "4.1.1", + "title": "Parsing", + "description": "In content implemented using markup languages, elements have complete start and end tags, elements are nested according to their specifications, elements do not contain duplicate attributes, and any IDs are unique, except where the specifications allow these features", + "url": "https://www.w3.org/TR/WCAG20/#ensure-compat-parses", + "level": "A", + "special_cases": null, + "notes": [ + { + "content": "Start and end tags that are missing a critical character in their formation, such as a closing angle bracket or a mismatched attribute value quotation mark are not complete." + } + ], + "references": [ + { + "title": "How to Meet 4.1.1", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-ensure-compat-parses" + }, + { + "title": "Understanding 4.1.1", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/ensure-compat-parses.html" + } + ] + }, + { + "ref_id": "4.1.2", + "title": "Name, Role, Value", + "description": "For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies.", + "url": "https://www.w3.org/TR/WCAG20/#ensure-compat-rsv", + "level": "A", + "special_cases": null, + "notes": [ + { + "content": "This success criterion is primarily for Web authors who develop or script their own user interface components. For example, standard HTML controls already meet this success criterion when used according to specification." + } + ], + "references": [ + { + "title": "How to Meet 4.1.2", + "url": "http://www.w3.org/WAI/WCAG20/quickref/#qr-ensure-compat-rsv" + }, + { + "title": "Understanding 4.1.2", + "url": "http://www.w3.org/TR/UNDERSTANDING-WCAG20/ensure-compat-rsv.html" + } + ] + } +] diff --git a/exampleSite/config.yaml b/exampleSite/config.yaml new file mode 100644 index 0000000..aee36bd --- /dev/null +++ b/exampleSite/config.yaml @@ -0,0 +1,88 @@ +baseURL: https://example.com +languageCode: en-us +defaultContentLanguage: en +title: Cupper +theme: cupper-hugo-theme +googleAnalytics: UA-123456789-1 +disqusShortname: yourdiscussshortname +enableGitInfo: true + +taxonomies: + tag: tags + +permalinks: + post: /:filename/ + +imaging: + quality: 99 + +params: + description: An accessibility-friendly Hugo theme, ported from the [original Cupper](https://github.com/ThePacielloGroup/cupper) project. + homeMetaContent: An accessibility-friendly Hugo theme, ported from the original Cupper project. + footer: Made with [Hugo](https://gohugo.io/). Themed by [Cupper](https://github.com/zwbetz-gh/cupper-hugo-theme). Deployed to [Netlify](https://www.netlify.com/). + # For more date formats see https://gohugo.io/functions/format/ + dateFormat: Jan 2, 2006 + codePenUser: someUser + katex: true + hideHeaderLinks: false + search: true + showThemeSwitcher: true + defaultDarkTheme: false + moveFooterToHeader: false + # navTitleText: Cupper Theme + logoAlt: An alternative text description of the logo + customCss: + - css/custom_01.css + - css/custom_02.css + customJs: + - js/custom_01.js + - js/custom_02.js + +menu: + nav: + - name: Home + url: / + weight: 1 + - name: Blog + url: /post/ + weight: 2 + - name: Tags + url: /tags/ + weight: 3 + - name: About + url: /about/ + weight: 4 + - name: RSS + url: /index.xml + weight: 5 + +markup: + defaultMarkdownHandler: goldmark + goldmark: + extensions: + definitionList: true + footnote: true + linkify: true + strikethrough: true + table: true + taskList: true + typographer: true + parser: + attribute: true + autoHeadingID: true + renderer: + hardWraps: false + unsafe: true + xHTML: false + highlight: + codeFences: false + hl_Lines: "" + lineNoStart: 1 + lineNos: false + lineNumbersInTable: true + noClasses: true + style: monokai + tabWidth: 4 + tableOfContents: + endLevel: 6 + startLevel: 2 diff --git a/exampleSite/content/_index.md b/exampleSite/content/_index.md new file mode 100644 index 0000000..1921c2e --- /dev/null +++ b/exampleSite/content/_index.md @@ -0,0 +1,14 @@ +--- +date: "2017-06-26T18:27:58+01:00" +title: "Home" +--- + +Welcome to **Cupper**: An accessibility-friendly Hugo theme, ported from the [original Cupper](https://github.com/ThePacielloGroup/cupper) project. Here are some of its features: + +{{< ticks >}} +* Screen reader and keyboard accessible +* Responsive +* Numerous shortcodes +* Toggleable dark theme +* Toggleable table of contents per blog post +{{< /ticks >}} diff --git a/exampleSite/content/about.md b/exampleSite/content/about.md new file mode 100644 index 0000000..641354f --- /dev/null +++ b/exampleSite/content/about.md @@ -0,0 +1,16 @@ +--- +date: "2014-04-09" +title: "About" +--- + +Hugo is the **world’s fastest framework for building websites**. It is written in Go. + +It makes use of a variety of open source projects including: + +* https://github.com/russross/blackfriday +* https://github.com/alecthomas/chroma +* https://github.com/muesli/smartcrop +* https://github.com/spf13/cobra +* https://github.com/spf13/viper + +Learn more and contribute on [GitHub](https://github.com/gohugoio). diff --git a/exampleSite/content/post/_index.md b/exampleSite/content/post/_index.md new file mode 100644 index 0000000..6f1bd49 --- /dev/null +++ b/exampleSite/content/post/_index.md @@ -0,0 +1,3 @@ +--- +title: Blog +--- \ No newline at end of file diff --git a/exampleSite/content/post/cmd-test.md b/exampleSite/content/post/cmd-test.md new file mode 100644 index 0000000..55c1569 --- /dev/null +++ b/exampleSite/content/post/cmd-test.md @@ -0,0 +1,13 @@ +--- +title: "cmd Test" +date: 2020-08-04T21:05:05-05:00 +tags: [issue] +--- + +Testing out GitHub issue https://github.com/zwbetz-gh/cupper-hugo-theme/issues/42 + +{{< cmd >}} +Line 1 +Line 2 +Line 3 +{{}} diff --git a/exampleSite/content/post/creating-a-new-theme.md b/exampleSite/content/post/creating-a-new-theme.md new file mode 100644 index 0000000..7f32ce4 --- /dev/null +++ b/exampleSite/content/post/creating-a-new-theme.md @@ -0,0 +1,1144 @@ +--- +date: "2014-09-28" +tags: ["hugo", "theme", "command-line"] +title: "Creating a New Theme" +toc: true +--- + + +## Introduction + +This tutorial will show you how to create a simple theme in Hugo. I assume that you are familiar with HTML, the bash command line, and that you are comfortable using Markdown to format content. I'll explain how Hugo uses templates and how you can organize your templates to create a theme. I won't cover using CSS to style your theme. + +We'll start with creating a new site with a very basic template. Then we'll add in a few pages and posts. With small variations on that, you will be able to create many different types of web sites. + +In this tutorial, commands that you enter will start with the "$" prompt. The output will follow. Lines that start with "#" are comments that I've added to explain a point. When I show updates to a file, the ":wq" on the last line means to save the file. + +Here's an example: + +``` +## this is a comment +$ echo this is a command +this is a command + +## edit the file +$ vi foo.md ++++ +date = "2014-09-28" +title = "creating a new theme" ++++ + +bah and humbug +:wq + +## show it +$ cat foo.md ++++ +date = "2014-09-28" +title = "creating a new theme" ++++ + +bah and humbug +$ +``` + + +## Some Definitions + +There are a few concepts that you need to understand before creating a theme. + +### Skins + +Skins are the files responsible for the look and feel of your site. It’s the CSS that controls colors and fonts, it’s the Javascript that determines actions and reactions. It’s also the rules that Hugo uses to transform your content into the HTML that the site will serve to visitors. + +You have two ways to create a skin. The simplest way is to create it in the ```layouts/``` directory. If you do, then you don’t have to worry about configuring Hugo to recognize it. The first place that Hugo will look for rules and files is in the ```layouts/``` directory so it will always find the skin. + +Your second choice is to create it in a sub-directory of the ```themes/``` directory. If you do, then you must always tell Hugo where to search for the skin. It’s extra work, though, so why bother with it? + +The difference between creating a skin in ```layouts/``` and creating it in ```themes/``` is very subtle. A skin in ```layouts/``` can’t be customized without updating the templates and static files that it is built from. A skin created in ```themes/```, on the other hand, can be and that makes it easier for other people to use it. + +The rest of this tutorial will call a skin created in the ```themes/``` directory a theme. + +Note that you can use this tutorial to create a skin in the ```layouts/``` directory if you wish to. The main difference will be that you won’t need to update the site’s configuration file to use a theme. + +### The Home Page + +The home page, or landing page, is the first page that many visitors to a site see. It is the index.html file in the root directory of the web site. Since Hugo writes files to the public/ directory, our home page is public/index.html. + +### Site Configuration File + +When Hugo runs, it looks for a configuration file that contains settings that override default values for the entire site. The file can use TOML, YAML, or JSON. I prefer to use TOML for my configuration files. If you prefer to use JSON or YAML, you’ll need to translate my examples. You’ll also need to change the name of the file since Hugo uses the extension to determine how to process it. + +Hugo translates Markdown files into HTML. By default, Hugo expects to find Markdown files in your ```content/``` directory and template files in your ```themes/``` directory. It will create HTML files in your ```public/``` directory. You can change this by specifying alternate locations in the configuration file. + +### Content + +Content is stored in text files that contain two sections. The first section is the “front matter,” which is the meta-information on the content. The second section contains Markdown that will be converted to HTML. + +#### Front Matter + +The front matter is information about the content. Like the configuration file, it can be written in TOML, YAML, or JSON. Unlike the configuration file, Hugo doesn’t use the file’s extension to know the format. It looks for markers to signal the type. TOML is surrounded by “`+++`”, YAML by “`---`”, and JSON is enclosed in curly braces. I prefer to use TOML, so you’ll need to translate my examples if you prefer YAML or JSON. + +The information in the front matter is passed into the template before the content is rendered into HTML. + +#### Markdown + +Content is written in Markdown which makes it easier to create the content. Hugo runs the content through a Markdown engine to create the HTML which will be written to the output file. + +### Template Files + +Hugo uses template files to render content into HTML. Template files are a bridge between the content and presentation. Rules in the template define what content is published, where it's published to, and how it will rendered to the HTML file. The template guides the presentation by specifying the style to use. + +There are three types of templates: single, list, and partial. Each type takes a bit of content as input and transforms it based on the commands in the template. + +Hugo uses its knowledge of the content to find the template file used to render the content. If it can’t find a template that is an exact match for the content, it will shift up a level and search from there. It will continue to do so until it finds a matching template or runs out of templates to try. If it can’t find a template, it will use the default template for the site. + +Please note that you can use the front matter to influence Hugo’s choice of templates. + +#### Single Template + +A single template is used to render a single piece of content. For example, an article or post would be a single piece of content and use a single template. + +#### List Template + +A list template renders a group of related content. That could be a summary of recent postings or all articles in a category. List templates can contain multiple groups. + +The homepage template is a special type of list template. Hugo assumes that the home page of your site will act as the portal for the rest of the content in the site. + +#### Partial Template + +A partial template is a template that can be included in other templates. Partial templates must be called using the “partial” template command. They are very handy for rolling up common behavior. For example, your site may have a banner that all pages use. Instead of copying the text of the banner into every single and list template, you could create a partial with the banner in it. That way if you decide to change the banner, you only have to change the partial template. + +## Create a New Site + +Let's use Hugo to create a new web site. I'm a Mac user, so I'll create mine in my home directory, in the Sites folder. If you're using Linux, you might have to create the folder first. + +The "new site" command will create a skeleton of a site. It will give you the basic directory structure and a useable configuration file. + +``` +$ hugo new site ~/Sites/zafta +$ cd ~/Sites/zafta +$ ls -l +total 8 +drwxr-xr-x 7 quoha staff 238 Sep 29 16:49 . +drwxr-xr-x 3 quoha staff 102 Sep 29 16:49 .. +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 archetypes +-rw-r--r-- 1 quoha staff 82 Sep 29 16:49 config.toml +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 content +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 layouts +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 static +$ +``` + +Take a look in the content/ directory to confirm that it is empty. + +The other directories (archetypes/, layouts/, and static/) are used when customizing a theme. That's a topic for a different tutorial, so please ignore them for now. + +### Generate the HTML For the New Site + +Running the `hugo` command with no options will read all the available content and generate the HTML files. It will also copy all static files (that's everything that's not content). Since we have an empty site, it won't do much, but it will do it very quickly. + +``` +$ hugo --verbose +INFO: 2014/09/29 Using config file: config.toml +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ +WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] +WARN: 2014/09/29 Unable to locate layout: [404.html] +0 draft content +0 future content +0 pages created +0 tags created +0 categories created +in 2 ms +$ +``` + +The "`--verbose`" flag gives extra information that will be helpful when we build the template. Every line of the output that starts with "INFO:" or "WARN:" is present because we used that flag. The lines that start with "WARN:" are warning messages. We'll go over them later. + +We can verify that the command worked by looking at the directory again. + +``` +$ ls -l +total 8 +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 archetypes +-rw-r--r-- 1 quoha staff 82 Sep 29 16:49 config.toml +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 content +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 layouts +drwxr-xr-x 4 quoha staff 136 Sep 29 17:02 public +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 static +$ +``` + +See that new public/ directory? Hugo placed all generated content there. When you're ready to publish your web site, that's the place to start. For now, though, let's just confirm that we have what we'd expect from a site with no content. + +``` +$ ls -l public +total 16 +-rw-r--r-- 1 quoha staff 416 Sep 29 17:02 index.xml +-rw-r--r-- 1 quoha staff 262 Sep 29 17:02 sitemap.xml +$ +``` + +Hugo created two XML files, which is standard, but there are no HTML files. + + + +### Test the New Site + +Verify that you can run the built-in web server. It will dramatically shorten your development cycle if you do. Start it by running the "server" command. If it is successful, you will see output similar to the following: + +``` +$ hugo server --verbose +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ +WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] +WARN: 2014/09/29 Unable to locate layout: [404.html] +0 draft content +0 future content +0 pages created +0 tags created +0 categories created +in 2 ms +Serving pages from /Users/quoha/Sites/zafta/public +Web Server is available at http://localhost:1313 +Press Ctrl+C to stop +``` + +Connect to the listed URL (it's on the line that starts with "Web Server"). If everything is working correctly, you should get a page that shows the following: + +``` +index.xml +sitemap.xml +``` + +That's a listing of your public/ directory. Hugo didn't create a home page because our site has no content. When there's no index.html file in a directory, the server lists the files in the directory, which is what you should see in your browser. + +Let’s go back and look at those warnings again. + +``` +WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] +WARN: 2014/09/29 Unable to locate layout: [404.html] +``` + +That second warning is easier to explain. We haven’t created a template to be used to generate “page not found errors.” The 404 message is a topic for a separate tutorial. + +Now for the first warning. It is for the home page. You can tell because the first layout that it looked for was “index.html.” That’s only used by the home page. + +I like that the verbose flag causes Hugo to list the files that it's searching for. For the home page, they are index.html, _default/list.html, and _default/single.html. There are some rules that we'll cover later that explain the names and paths. For now, just remember that Hugo couldn't find a template for the home page and it told you so. + +At this point, you've got a working installation and site that we can build upon. All that’s left is to add some content and a theme to display it. + +## Create a New Theme + +Hugo doesn't ship with a default theme. There are a few available (I counted a dozen when I first installed Hugo) and Hugo comes with a command to create new themes. + +We're going to create a new theme called "zafta." Since the goal of this tutorial is to show you how to fill out the files to pull in your content, the theme will not contain any CSS. In other words, ugly but functional. + +All themes have opinions on content and layout. For example, Zafta uses "post" over "blog". Strong opinions make for simpler templates but differing opinions make it tougher to use themes. When you build a theme, consider using the terms that other themes do. + + +### Create a Skeleton + +Use the hugo "new" command to create the skeleton of a theme. This creates the directory structure and places empty files for you to fill out. + +``` +$ hugo new theme zafta + +$ ls -l +total 8 +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 archetypes +-rw-r--r-- 1 quoha staff 82 Sep 29 16:49 config.toml +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 content +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 layouts +drwxr-xr-x 4 quoha staff 136 Sep 29 17:02 public +drwxr-xr-x 2 quoha staff 68 Sep 29 16:49 static +drwxr-xr-x 3 quoha staff 102 Sep 29 17:31 themes + +$ find themes -type f | xargs ls -l +-rw-r--r-- 1 quoha staff 1081 Sep 29 17:31 themes/zafta/LICENSE.md +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/archetypes/default.md +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/list.html +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/single.html +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/footer.html +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/header.html +-rw-r--r-- 1 quoha staff 93 Sep 29 17:31 themes/zafta/theme.toml +$ +``` + +The skeleton includes templates (the files ending in .html), license file, a description of your theme (the theme.toml file), and an empty archetype. + +Please take a minute to fill out the theme.toml and LICENSE.md files. They're optional, but if you're going to be distributing your theme, it tells the world who to praise (or blame). It's also nice to declare the license so that people will know how they can use the theme. + +``` +$ vi themes/zafta/theme.toml +author = "michael d henderson" +description = "a minimal working template" +license = "MIT" +name = "zafta" +source_repo = "" +tags = ["tags", "categories"] +:wq + +## also edit themes/zafta/LICENSE.md and change +## the bit that says "YOUR_NAME_HERE" +``` + +Note that the the skeleton's template files are empty. Don't worry, we'll be changing that shortly. + +``` +$ find themes/zafta -name '*.html' | xargs ls -l +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/list.html +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/single.html +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/footer.html +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/partials/header.html +$ +``` + + + +### Update the Configuration File to Use the Theme + +Now that we've got a theme to work with, it's a good idea to add the theme name to the configuration file. This is optional, because you can always add "-t zafta" on all your commands. I like to put it the configuration file because I like shorter command lines. If you don't put it in the configuration file or specify it on the command line, you won't use the template that you're expecting to. + +Edit the file to add the theme, add a title for the site, and specify that all of our content will use the TOML format. + +``` +$ vi config.toml +theme = "zafta" +baseurl = "" +languageCode = "en-us" +title = "zafta - totally refreshing" +MetaDataFormat = "toml" +:wq + +$ +``` + +### Generate the Site + +Now that we have an empty theme, let's generate the site again. + +``` +$ hugo --verbose +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ +WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] +0 draft content +0 future content +0 pages created +0 tags created +0 categories created +in 2 ms +$ +``` + +Did you notice that the output is different? The warning message for the home page has disappeared and we have an additional information line saying that Hugo is syncing from the theme's directory. + +Let's check the public/ directory to see what Hugo's created. + +``` +$ ls -l public +total 16 +drwxr-xr-x 2 quoha staff 68 Sep 29 17:56 css +-rw-r--r-- 1 quoha staff 0 Sep 29 17:56 index.html +-rw-r--r-- 1 quoha staff 407 Sep 29 17:56 index.xml +drwxr-xr-x 2 quoha staff 68 Sep 29 17:56 js +-rw-r--r-- 1 quoha staff 243 Sep 29 17:56 sitemap.xml +$ +``` + +Notice four things: + +1. Hugo created a home page. This is the file public/index.html. +2. Hugo created a css/ directory. +3. Hugo created a js/ directory. +4. Hugo claimed that it created 0 pages. It created a file and copied over static files, but didn't create any pages. That's because it considers a "page" to be a file created directly from a content file. It doesn't count things like the index.html files that it creates automatically. + +#### The Home Page + +Hugo supports many different types of templates. The home page is special because it gets its own type of template and its own template file. The file, layouts/index.html, is used to generate the HTML for the home page. The Hugo documentation says that this is the only required template, but that depends. Hugo's warning message shows that it looks for three different templates: + +``` +WARN: 2014/09/29 Unable to locate layout: [index.html _default/list.html _default/single.html] +``` + +If it can't find any of these, it completely skips creating the home page. We noticed that when we built the site without having a theme installed. + +When Hugo created our theme, it created an empty home page template. Now, when we build the site, Hugo finds the template and uses it to generate the HTML for the home page. Since the template file is empty, the HTML file is empty, too. If the template had any rules in it, then Hugo would have used them to generate the home page. + +``` +$ find . -name index.html | xargs ls -l +-rw-r--r-- 1 quoha staff 0 Sep 29 20:21 ./public/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 ./themes/zafta/layouts/index.html +$ +``` + +#### The Magic of Static + +Hugo does two things when generating the site. It uses templates to transform content into HTML and it copies static files into the site. Unlike content, static files are not transformed. They are copied exactly as they are. + +Hugo assumes that your site will use both CSS and JavaScript, so it creates directories in your theme to hold them. Remember opinions? Well, Hugo's opinion is that you'll store your CSS in a directory named css/ and your JavaScript in a directory named js/. If you don't like that, you can change the directory names in your theme directory or even delete them completely. Hugo's nice enough to offer its opinion, then behave nicely if you disagree. + +``` +$ find themes/zafta -type d | xargs ls -ld +drwxr-xr-x 7 quoha staff 238 Sep 29 17:38 themes/zafta +drwxr-xr-x 3 quoha staff 102 Sep 29 17:31 themes/zafta/archetypes +drwxr-xr-x 5 quoha staff 170 Sep 29 17:31 themes/zafta/layouts +drwxr-xr-x 4 quoha staff 136 Sep 29 17:31 themes/zafta/layouts/_default +drwxr-xr-x 4 quoha staff 136 Sep 29 17:31 themes/zafta/layouts/partials +drwxr-xr-x 4 quoha staff 136 Sep 29 17:31 themes/zafta/static +drwxr-xr-x 2 quoha staff 68 Sep 29 17:31 themes/zafta/static/css +drwxr-xr-x 2 quoha staff 68 Sep 29 17:31 themes/zafta/static/js +$ +``` + +## The Theme Development Cycle + +When you're working on a theme, you will make changes in the theme's directory, rebuild the site, and check your changes in the browser. Hugo makes this very easy: + +1. Purge the public/ directory. +2. Run the built in web server in watch mode. +3. Open your site in a browser. +4. Update the theme. +5. Glance at your browser window to see changes. +6. Return to step 4. + +I’ll throw in one more opinion: never work on a theme on a live site. Always work on a copy of your site. Make changes to your theme, test them, then copy them up to your site. For added safety, use a tool like Git to keep a revision history of your content and your theme. Believe me when I say that it is too easy to lose both your mind and your changes. + +Check the main Hugo site for information on using Git with Hugo. + +### Purge the public/ Directory + +When generating the site, Hugo will create new files and update existing ones in the ```public/``` directory. It will not delete files that are no longer used. For example, files that were created in the wrong directory or with the wrong title will remain. If you leave them, you might get confused by them later. I recommend cleaning out your site prior to generating it. + +Note: If you're building on an SSD, you should ignore this. Churning on a SSD can be costly. + +### Hugo's Watch Option + +Hugo's "`--watch`" option will monitor the content/ and your theme directories for changes and rebuild the site automatically. + +### Live Reload + +Hugo's built in web server supports live reload. As pages are saved on the server, the browser is told to refresh the page. Usually, this happens faster than you can say, "Wow, that's totally amazing." + +### Development Commands + +Use the following commands as the basis for your workflow. + +``` +## purge old files. hugo will recreate the public directory. +## +$ rm -rf public +## +## run hugo in watch mode +## +$ hugo server --watch --verbose +``` + +Here's sample output showing Hugo detecting a change to the template for the home page. Once generated, the web browser automatically reloaded the page. I've said this before, it's amazing. + + +``` +$ rm -rf public +$ hugo server --watch --verbose +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ +WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] +0 draft content +0 future content +0 pages created +0 tags created +0 categories created +in 2 ms +Watching for changes in /Users/quoha/Sites/zafta/content +Serving pages from /Users/quoha/Sites/zafta/public +Web Server is available at http://localhost:1313 +Press Ctrl+C to stop +INFO: 2014/09/29 File System Event: ["/Users/quoha/Sites/zafta/themes/zafta/layouts/index.html": MODIFY|ATTRIB] +Change detected, rebuilding site + +WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] +0 draft content +0 future content +0 pages created +0 tags created +0 categories created +in 1 ms +``` + +## Update the Home Page Template + +The home page is one of a few special pages that Hugo creates automatically. As mentioned earlier, it looks for one of three files in the theme's layout/ directory: + +1. index.html +2. _default/list.html +3. _default/single.html + +We could update one of the default templates, but a good design decision is to update the most specific template available. That's not a hard and fast rule (in fact, we'll break it a few times in this tutorial), but it is a good generalization. + +### Make a Static Home Page + +Right now, that page is empty because we don't have any content and we don't have any logic in the template. Let's change that by adding some text to the template. + +``` +$ vi themes/zafta/layouts/index.html + + + +

hugo says hello!

+ + +:wq + +$ +``` + +Build the web site and then verify the results. + +``` +$ hugo --verbose +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ +WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] +0 draft content +0 future content +0 pages created +0 tags created +0 categories created +in 2 ms + +$ find public -type f -name '*.html' | xargs ls -l +-rw-r--r-- 1 quoha staff 78 Sep 29 21:26 public/index.html + +$ cat public/index.html + + + +

hugo says hello!

+ +``` + +#### Live Reload + +Note: If you're running the server with the `--watch` option, you'll see different content in the file: + +``` +$ cat public/index.html + + + +

hugo says hello!

+ + +``` + +When you use `--watch`, the Live Reload script is added by Hugo. Look for live reload in the documentation to see what it does and how to disable it. + +### Build a "Dynamic" Home Page + +"Dynamic home page?" Hugo's a static web site generator, so this seems an odd thing to say. I mean let's have the home page automatically reflect the content in the site every time Hugo builds it. We'll use iteration in the template to do that. + +#### Create New Posts + +Now that we have the home page generating static content, let's add some content to the site. We'll display these posts as a list on the home page and on their own page, too. + +Hugo has a command to generate a skeleton post, just like it does for sites and themes. + +``` +$ hugo --verbose new post/first.md +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 attempting to create post/first.md of post +INFO: 2014/09/29 curpath: /Users/quoha/Sites/zafta/themes/zafta/archetypes/default.md +ERROR: 2014/09/29 Unable to Cast to map[string]interface{} + +$ +``` + +That wasn't very nice, was it? + +The "new" command uses an archetype to create the post file. Hugo created an empty default archetype file, but that causes an error when there's a theme. For me, the workaround was to create an archetypes file specifically for the post type. + +``` +$ vi themes/zafta/archetypes/post.md ++++ +Description = "" +Tags = [] +Categories = [] ++++ +:wq + +$ find themes/zafta/archetypes -type f | xargs ls -l +-rw-r--r-- 1 quoha staff 0 Sep 29 21:53 themes/zafta/archetypes/default.md +-rw-r--r-- 1 quoha staff 51 Sep 29 21:54 themes/zafta/archetypes/post.md + +$ hugo --verbose new post/first.md +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 attempting to create post/first.md of post +INFO: 2014/09/29 curpath: /Users/quoha/Sites/zafta/themes/zafta/archetypes/post.md +INFO: 2014/09/29 creating /Users/quoha/Sites/zafta/content/post/first.md +/Users/quoha/Sites/zafta/content/post/first.md created + +$ hugo --verbose new post/second.md +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 attempting to create post/second.md of post +INFO: 2014/09/29 curpath: /Users/quoha/Sites/zafta/themes/zafta/archetypes/post.md +INFO: 2014/09/29 creating /Users/quoha/Sites/zafta/content/post/second.md +/Users/quoha/Sites/zafta/content/post/second.md created + +$ ls -l content/post +total 16 +-rw-r--r-- 1 quoha staff 104 Sep 29 21:54 first.md +-rw-r--r-- 1 quoha staff 105 Sep 29 21:57 second.md + +$ cat content/post/first.md ++++ +Categories = [] +Description = "" +Tags = [] +date = "2014-09-29T21:54:53-05:00" +title = "first" + ++++ +my first post + +$ cat content/post/second.md ++++ +Categories = [] +Description = "" +Tags = [] +date = "2014-09-29T21:57:09-05:00" +title = "second" + ++++ +my second post + +$ +``` + +Build the web site and then verify the results. + +``` +$ rm -rf public +$ hugo --verbose +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 found taxonomies: map[string]string{"category":"categories", "tag":"tags"} +WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] +0 draft content +0 future content +2 pages created +0 tags created +0 categories created +in 4 ms +$ +``` + +The output says that it created 2 pages. Those are our new posts: + +``` +$ find public -type f -name '*.html' | xargs ls -l +-rw-r--r-- 1 quoha staff 78 Sep 29 22:13 public/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 22:13 public/post/first/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 22:13 public/post/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 22:13 public/post/second/index.html +$ +``` + +The new files are empty because because the templates used to generate the content are empty. The homepage doesn't show the new content, either. We have to update the templates to add the posts. + +### List and Single Templates + +In Hugo, we have three major kinds of templates. There's the home page template that we updated previously. It is used only by the home page. We also have "single" templates which are used to generate output for a single content file. We also have "list" templates that are used to group multiple pieces of content before generating output. + +Generally speaking, list templates are named "list.html" and single templates are named "single.html." + +There are three other types of templates: partials, content views, and terms. We will not go into much detail on these. + +### Add Content to the Homepage + +The home page will contain a list of posts. Let's update its template to add the posts that we just created. The logic in the template will run every time we build the site. + +``` +$ vi themes/zafta/layouts/index.html + + + + {{ range first 10 .Data.Pages }} +

{{ .Title }}

+ {{ end }} + + +:wq + +$ +``` + +Hugo uses the Go template engine. That engine scans the template files for commands which are enclosed between "{{" and "}}". In our template, the commands are: + +1. range +2. .Title +3. end + +The "range" command is an iterator. We're going to use it to go through the first ten pages. Every HTML file that Hugo creates is treated as a page, so looping through the list of pages will look at every file that will be created. + +The ".Title" command prints the value of the "title" variable. Hugo pulls it from the front matter in the Markdown file. + +The "end" command signals the end of the range iterator. The engine loops back to the top of the iteration when it finds "end." Everything between the "range" and "end" is evaluated every time the engine goes through the iteration. In this file, that would cause the title from the first ten pages to be output as heading level one. + +It's helpful to remember that some variables, like .Data, are created before any output files. Hugo loads every content file into the variable and then gives the template a chance to process before creating the HTML files. + +Build the web site and then verify the results. + +``` +$ rm -rf public +$ hugo --verbose +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 found taxonomies: map[string]string{"tag":"tags", "category":"categories"} +WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] +0 draft content +0 future content +2 pages created +0 tags created +0 categories created +in 4 ms +$ find public -type f -name '*.html' | xargs ls -l +-rw-r--r-- 1 quoha staff 94 Sep 29 22:23 public/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 22:23 public/post/first/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 22:23 public/post/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 22:23 public/post/second/index.html +$ cat public/index.html + + + + +

second

+ +

first

+ + + +$ +``` + +Congratulations, the home page shows the title of the two posts. The posts themselves are still empty, but let's take a moment to appreciate what we've done. Your template now generates output dynamically. Believe it or not, by inserting the range command inside of those curly braces, you've learned everything you need to know to build a theme. All that's really left is understanding which template will be used to generate each content file and becoming familiar with the commands for the template engine. + +And, if that were entirely true, this tutorial would be much shorter. There are a few things to know that will make creating a new template much easier. Don't worry, though, that's all to come. + +### Add Content to the Posts + +We're working with posts, which are in the content/post/ directory. That means that their section is "post" (and if we don't do something weird, their type is also "post"). + +Hugo uses the section and type to find the template file for every piece of content. Hugo will first look for a template file that matches the section or type name. If it can't find one, then it will look in the _default/ directory. There are some twists that we'll cover when we get to categories and tags, but for now we can assume that Hugo will try post/single.html, then _default/single.html. + +Now that we know the search rule, let's see what we actually have available: + +``` +$ find themes/zafta -name single.html | xargs ls -l +-rw-r--r-- 1 quoha staff 132 Sep 29 17:31 themes/zafta/layouts/_default/single.html +``` + +We could create a new template, post/single.html, or change the default. Since we don't know of any other content types, let's start with updating the default. + +Remember, any content that we haven't created a template for will end up using this template. That can be good or bad. Bad because I know that we're going to be adding different types of content and we're going to end up undoing some of the changes we've made. It's good because we'll be able to see immediate results. It's also good to start here because we can start to build the basic layout for the site. As we add more content types, we'll refactor this file and move logic around. Hugo makes that fairly painless, so we'll accept the cost and proceed. + +Please see the Hugo documentation on template rendering for all the details on determining which template to use. And, as the docs mention, if you're building a single page application (SPA) web site, you can delete all of the other templates and work with just the default single page. That's a refreshing amount of joy right there. + +#### Update the Template File + +``` +$ vi themes/zafta/layouts/_default/single.html + + + + {{ .Title }} + + +

{{ .Title }}

+ {{ .Content }} + + +:wq + +$ +``` + +Build the web site and verify the results. + +``` +$ rm -rf public +$ hugo --verbose +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 found taxonomies: map[string]string{"tag":"tags", "category":"categories"} +WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] +0 draft content +0 future content +2 pages created +0 tags created +0 categories created +in 4 ms + +$ find public -type f -name '*.html' | xargs ls -l +-rw-r--r-- 1 quoha staff 94 Sep 29 22:40 public/index.html +-rw-r--r-- 1 quoha staff 125 Sep 29 22:40 public/post/first/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 22:40 public/post/index.html +-rw-r--r-- 1 quoha staff 128 Sep 29 22:40 public/post/second/index.html + +$ cat public/post/first/index.html + + + + first + + +

first

+

my first post

+ + + + +$ cat public/post/second/index.html + + + + second + + +

second

+

my second post

+ + + +$ +``` + +Notice that the posts now have content. You can go to localhost:1313/post/first to verify. + +### Linking to Content + +The posts are on the home page. Let's add a link from there to the post. Since this is the home page, we'll update its template. + +``` +$ vi themes/zafta/layouts/index.html + + + + {{ range first 10 .Data.Pages }} +

{{ .Title }}

+ {{ end }} + + +``` + +Build the web site and verify the results. + +``` +$ rm -rf public +$ hugo --verbose +INFO: 2014/09/29 Using config file: /Users/quoha/Sites/zafta/config.toml +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/themes/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 syncing from /Users/quoha/Sites/zafta/static/ to /Users/quoha/Sites/zafta/public/ +INFO: 2014/09/29 found taxonomies: map[string]string{"tag":"tags", "category":"categories"} +WARN: 2014/09/29 Unable to locate layout: [404.html theme/404.html] +0 draft content +0 future content +2 pages created +0 tags created +0 categories created +in 4 ms + +$ find public -type f -name '*.html' | xargs ls -l +-rw-r--r-- 1 quoha staff 149 Sep 29 22:44 public/index.html +-rw-r--r-- 1 quoha staff 125 Sep 29 22:44 public/post/first/index.html +-rw-r--r-- 1 quoha staff 0 Sep 29 22:44 public/post/index.html +-rw-r--r-- 1 quoha staff 128 Sep 29 22:44 public/post/second/index.html + +$ cat public/index.html + + + + +

second

+ +

first

+ + + + +$ +``` + +### Create a Post Listing + +We have the posts displaying on the home page and on their own page. We also have a file public/post/index.html that is empty. Let's make it show a list of all posts (not just the first ten). + +We need to decide which template to update. This will be a listing, so it should be a list template. Let's take a quick look and see which list templates are available. + +``` +$ find themes/zafta -name list.html | xargs ls -l +-rw-r--r-- 1 quoha staff 0 Sep 29 17:31 themes/zafta/layouts/_default/list.html +``` + +As with the single post, we have to decide to update _default/list.html or create post/list.html. We still don't have multiple content types, so let's stay consistent and update the default list template. + +## Creating Top Level Pages + +Let's add an "about" page and display it at the top level (as opposed to a sub-level like we did with posts). + +The default in Hugo is to use the directory structure of the content/ directory to guide the location of the generated html in the public/ directory. Let's verify that by creating an "about" page at the top level: + +``` +$ vi content/about.md ++++ +title = "about" +description = "about this site" +date = "2014-09-27" +slug = "about time" ++++ + +## about us + +i'm speechless +:wq +``` + +Generate the web site and verify the results. + +``` +$ find public -name '*.html' | xargs ls -l +-rw-rw-r-- 1 mdhender staff 334 Sep 27 15:08 public/about-time/index.html +-rw-rw-r-- 1 mdhender staff 527 Sep 27 15:08 public/index.html +-rw-rw-r-- 1 mdhender staff 358 Sep 27 15:08 public/post/first-post/index.html +-rw-rw-r-- 1 mdhender staff 0 Sep 27 15:08 public/post/index.html +-rw-rw-r-- 1 mdhender staff 342 Sep 27 15:08 public/post/second-post/index.html +``` + +Notice that the page wasn't created at the top level. It was created in a sub-directory named 'about-time/'. That name came from our slug. Hugo will use the slug to name the generated content. It's a reasonable default, by the way, but we can learn a few things by fighting it for this file. + +One other thing. Take a look at the home page. + +``` +$ cat public/index.html + + + +

creating a new theme

+

about

+

second

+

first

+ + +``` + +Notice that the "about" link is listed with the posts? That's not desirable, so let's change that first. + +``` +$ vi themes/zafta/layouts/index.html + + + +

posts

+ {{ range first 10 .Data.Pages }} + {{ if eq .Type "post"}} +

{{ .Title }}

+ {{ end }} + {{ end }} + +

pages

+ {{ range .Data.Pages }} + {{ if eq .Type "page" }} +

{{ .Title }}

+ {{ end }} + {{ end }} + + +:wq +``` + +Generate the web site and verify the results. The home page has two sections, posts and pages, and each section has the right set of headings and links in it. + +But, that about page still renders to about-time/index.html. + +``` +$ find public -name '*.html' | xargs ls -l +-rw-rw-r-- 1 mdhender staff 334 Sep 27 15:33 public/about-time/index.html +-rw-rw-r-- 1 mdhender staff 645 Sep 27 15:33 public/index.html +-rw-rw-r-- 1 mdhender staff 358 Sep 27 15:33 public/post/first-post/index.html +-rw-rw-r-- 1 mdhender staff 0 Sep 27 15:33 public/post/index.html +-rw-rw-r-- 1 mdhender staff 342 Sep 27 15:33 public/post/second-post/index.html +``` + +Knowing that hugo is using the slug to generate the file name, the simplest solution is to change the slug. Let's do it the hard way and change the permalink in the configuration file. + +``` +$ vi config.toml +[permalinks] + page = "/:title/" + about = "/:filename/" +``` + +Generate the web site and verify that this didn't work. Hugo lets "slug" or "URL" override the permalinks setting in the configuration file. Go ahead and comment out the slug in content/about.md, then generate the web site to get it to be created in the right place. + +## Sharing Templates + +If you've been following along, you probably noticed that posts have titles in the browser and the home page doesn't. That's because we didn't put the title in the home page's template (layouts/index.html). That's an easy thing to do, but let's look at a different option. + +We can put the common bits into a shared template that's stored in the themes/zafta/layouts/partials/ directory. + +### Create the Header and Footer Partials + +In Hugo, a partial is a sugar-coated template. Normally a template reference has a path specified. Partials are different. Hugo searches for them along a TODO defined search path. This makes it easier for end-users to override the theme's presentation. + +``` +$ vi themes/zafta/layouts/partials/header.html + + + + {{ .Title }} + + +:wq + +$ vi themes/zafta/layouts/partials/footer.html + + +:wq +``` + +### Update the Home Page Template to Use the Partials + +The most noticeable difference between a template call and a partials call is the lack of path: + +``` +{{ template "theme/partials/header.html" . }} +``` +versus +``` +{{ partial "header.html" . }} +``` +Both pass in the context. + +Let's change the home page template to use these new partials. + +``` +$ vi themes/zafta/layouts/index.html +{{ partial "header.html" . }} + +

posts

+ {{ range first 10 .Data.Pages }} + {{ if eq .Type "post"}} +

{{ .Title }}

+ {{ end }} + {{ end }} + +

pages

+ {{ range .Data.Pages }} + {{ if or (eq .Type "page") (eq .Type "about") }} +

{{ .Type }} - {{ .Title }} - {{ .RelPermalink }}

+ {{ end }} + {{ end }} + +{{ partial "footer.html" . }} +:wq +``` + +Generate the web site and verify the results. The title on the home page is now "your title here", which comes from the "title" variable in the config.toml file. + +### Update the Default Single Template to Use the Partials + +``` +$ vi themes/zafta/layouts/_default/single.html +{{ partial "header.html" . }} + +

{{ .Title }}

+ {{ .Content }} + +{{ partial "footer.html" . }} +:wq +``` + +Generate the web site and verify the results. The title on the posts and the about page should both reflect the value in the markdown file. + +## Add “Date Published” to Posts + +It's common to have posts display the date that they were written or published, so let's add that. The front matter of our posts has a variable named "date." It's usually the date the content was created, but let's pretend that's the value we want to display. + +### Add “Date Published” to the Template + +We'll start by updating the template used to render the posts. The template code will look like: + +``` +{{ .Date.Format "Mon, Jan 2, 2006" }} +``` + +Posts use the default single template, so we'll change that file. + +``` +$ vi themes/zafta/layouts/_default/single.html +{{ partial "header.html" . }} + +

{{ .Title }}

+

{{ .Date.Format "Mon, Jan 2, 2006" }}

+ {{ .Content }} + +{{ partial "footer.html" . }} +:wq +``` + +Generate the web site and verify the results. The posts now have the date displayed in them. There's a problem, though. The "about" page also has the date displayed. + +As usual, there are a couple of ways to make the date display only on posts. We could do an "if" statement like we did on the home page. Another way would be to create a separate template for posts. + +The "if" solution works for sites that have just a couple of content types. It aligns with the principle of "code for today," too. + +Let's assume, though, that we've made our site so complex that we feel we have to create a new template type. In Hugo-speak, we're going to create a section template. + +Let's restore the default single template before we forget. + +``` +$ mkdir themes/zafta/layouts/post +$ vi themes/zafta/layouts/_default/single.html +{{ partial "header.html" . }} + +

{{ .Title }}

+ {{ .Content }} + +{{ partial "footer.html" . }} +:wq +``` + +Now we'll update the post's version of the single template. If you remember Hugo's rules, the template engine will use this version over the default. + +``` +$ vi themes/zafta/layouts/post/single.html +{{ partial "header.html" . }} + +

{{ .Title }}

+

{{ .Date.Format "Mon, Jan 2, 2006" }}

+ {{ .Content }} + +{{ partial "footer.html" . }} +:wq + +``` + +Note that we removed the date logic from the default template and put it in the post template. Generate the web site and verify the results. Posts have dates and the about page doesn't. + +### Don't Repeat Yourself + +DRY is a good design goal and Hugo does a great job supporting it. Part of the art of a good template is knowing when to add a new template and when to update an existing one. While you're figuring that out, accept that you'll be doing some refactoring. Hugo makes that easy and fast, so it's okay to delay splitting up a template. diff --git a/exampleSite/content/post/cupper-shortcodes/index.md b/exampleSite/content/post/cupper-shortcodes/index.md new file mode 100644 index 0000000..94162e2 --- /dev/null +++ b/exampleSite/content/post/cupper-shortcodes/index.md @@ -0,0 +1,246 @@ +--- +title: "Cupper Shortcodes" +date: 2019-02-12T23:39:06-06:00 +tags: [hugo, shortcodes] +toc: true +--- + +## blockquote + +``` +{{}} +Even a happy life cannot be without a measure of darkness, and the word happy would lose its meaning if it were not balanced by sadness. It is far better to take things as they come along with patience and equanimity. +{{}} +``` + +{{< blockquote author="Carl Jung" >}} +Even a happy life cannot be without a measure of darkness, and the word happy would lose its meaning if it were not balanced by sadness. It is far better to take things as they come along with patience and equanimity. +{{< /blockquote >}} + +## note + +``` +{{}} +This is a note! It's something the reader may like to know about but is supplementary to the main content. Use notes when something may be interesting but not critical. You can also *include* **markdown** stuffs like `code`. +{{}} +``` + +{{< note >}} +This is a note! It's something the reader may like to know about but is supplementary to the main content. Use notes when something may be interesting but not critical. You can also *include* **markdown** stuffs like `code`. +{{< /note >}} + +## warning note + +``` +{{}} +This is a warning! It's about something the reader should be careful to do or to avoid doing. Use warnings when something could go wrong. You can also *include* **markdown** stuffs like `code`. +{{}} +``` + +{{< warning >}} +This is a warning! It's about something the reader should be careful to do or to avoid doing. Use warnings when something could go wrong. You can also *include* **markdown** stuffs like `code`. +{{< /warning >}} + +## cmd + +``` +{{}} +hugo server --gc +{{}} +``` + +{{< cmd >}} +hugo server --gc +{{< /cmd >}} + +## code + +``` +{{}} +
+ +

Confirmation

+

Press Okay to confirm or Cancel

+ + +
+{{}} + +1. The dialog is only announced as a dialog if it takes the `dialog` ARIA role +2. The `aria-labelledby` relationship attribute makes the element carrying the `id` it points to its label +3. The close button uses `aria-label` to provide the text label "close", overriding the text content +4. The heading is used as the dialog's label. The `aria-labelledby` attribute points to its `id` +``` + +{{< code numbered="true" >}} +
+ +

Confirmation

+

Press Okay to confirm or Cancel

+ + +
+{{< /code >}} + +1. The dialog is only announced as a dialog if it takes the `dialog` ARIA role +2. The `aria-labelledby` relationship attribute makes the element carrying the `id` it points to its label +3. The close button uses `aria-label` to provide the text label "close", overriding the text content +4. The heading is used as the dialog's label. The `aria-labelledby` attribute points to its `id` + +## syntax highlighting + +To get syntax highlighting for your code, use markdown code fences, then specify the language: + +```` +```html +
+ +

Confirmation

+

Press Okay to confirm or Cancel

+ + +
+``` +```` + +```html +
+ +

Confirmation

+

Press Okay to confirm or Cancel

+ + +
+``` + +## codePen + +``` +{{}} +``` + +{{< codePen VpVNKW >}} + +## colors + +``` +{{}} +``` + +{{< colors "#111111, #cccccc, #ffffff" >}} + +## expandable + +``` +{{}} +Here is some markdown including [a link](https://twitter.com/heydonworks). Donec erat est, feugiat a est sed, aliquet pharetra ipsum. Vivamus in arcu leo. Praesent feugiat, purus a molestie ultrices, libero massa iaculis ante, sit amet accumsan leo eros vel ligula. +{{}} +``` + +{{< expandable label="A section of dummy text" level="2" >}} +Here is some markdown including [a link](https://twitter.com/heydonworks). Donec erat est, feugiat a est sed, aliquet pharetra ipsum. Vivamus in arcu leo. Praesent feugiat, purus a molestie ultrices, libero massa iaculis ante, sit amet accumsan leo eros vel ligula. +{{< /expandable >}} + +## fileTree + +``` +{{}} +* Level 1 folder + * Level 2 file + * Level 2 folder + * Level 3 file + * Level 3 folder + * Level 4 file + * Level 3 folder + * Level 4 file + * Level 4 file + * Level 3 file + * Level 2 folder + * Level 3 file + * Level 3 file + * Level 3 file + * Level 2 file +* Level 1 file +{{}} +``` + +{{< fileTree >}} +* Level 1 folder + * Level 2 file + * Level 2 folder + * Level 3 file + * Level 3 folder + * Level 4 file + * Level 3 folder + * Level 4 file + * Level 4 file + * Level 3 file + * Level 2 folder + * Level 3 file + * Level 3 file + * Level 3 file + * Level 2 file +* Level 1 file +{{< /fileTree >}} + +## ticks + +``` +{{}} +* Selling point one +* Selling point two +* Selling point three +{{}} +``` + +{{< ticks >}} +* Selling point one +* Selling point two +* Selling point three +{{< /ticks >}} + +## figureCupper + +``` +{{}} +``` + +{{< figureCupper +img="sun.jpg" +caption="The Sun is the star at the center of the Solar System. It is a nearly perfect sphere of hot plasma, with internal convective motion that generates a magnetic field via a dynamo process. It is by far the most important source of energy for life on Earth. [Credits](https://images.nasa.gov/details-GSFC_20171208_Archive_e000393.html)." +command="Resize" +options="700x" >}} + +## principles + +See the [full principles list](https://github.com/zwbetz-gh/cupper-hugo-theme/blob/master/data/principles.json). + +``` +{{}} +``` + +{{< principles include="Add value, Be consistent" descriptions="true" >}} + +## wcag + +See the [full wcag list](https://github.com/zwbetz-gh/cupper-hugo-theme/blob/master/data/wcag.json). + +``` +{{}} +``` + +{{< wcag include="1.2.1, 1.3.1, 4.1.2" >}} + +## tested + +See the [full browser list](https://github.com/zwbetz-gh/cupper-hugo-theme/tree/master/static/images). + +``` +{{}} +``` + +{{< tested using="Firefox + JAWS, Chrome, Safari iOS + Voiceover, Edge" >}} diff --git a/exampleSite/content/post/cupper-shortcodes/sun.jpg b/exampleSite/content/post/cupper-shortcodes/sun.jpg new file mode 100644 index 0000000..0faeb53 Binary files /dev/null and b/exampleSite/content/post/cupper-shortcodes/sun.jpg differ diff --git a/exampleSite/content/post/cupper-typography.md b/exampleSite/content/post/cupper-typography.md new file mode 100644 index 0000000..9ee0deb --- /dev/null +++ b/exampleSite/content/post/cupper-typography.md @@ -0,0 +1,146 @@ +--- +title: "Cupper Typography" +date: 2019-02-14T15:36:09-06:00 +tags: [hugo, markdown] +toc: true +--- + +## Headings + +``` +## Heading 2 +### Heading 3 +#### Heading 4 +##### Heading 5 +###### Heading 6 +``` + +## Heading 2 +### Heading 3 +#### Heading 4 +##### Heading 5 +###### Heading 6 + +## Text + +``` +*This text will be italic* +_This will also be italic_ + +**This text will be bold** +__This will also be bold__ + +_You **can** combine them_ +``` + +*This text will be italic* + +_This will also be italic_ + +**This text will be bold** + +__This will also be bold__ + +_You **can** combine them_ + +## Lists + +### Unordered + +``` +* Item 1 +* Item 2 + * Item 2a + * Item 2b +``` + +* Item 1 +* Item 2 + * Item 2a + * Item 2b + +### Ordered + +``` +1. Item 1 +1. Item 2 +1. Item 3 + 1. Item 3a + 1. Item 3b +``` + +1. Item 1 +1. Item 2 +1. Item 3 + 1. Item 3a + 1. Item 3b + +## Links + +``` +https://cupper-hugo-theme.netlify.com/ + +[Cupper hugo theme](https://cupper-hugo-theme.netlify.com/) +``` + +https://cupper-hugo-theme.netlify.com/ + +[Cupper hugo theme](https://cupper-hugo-theme.netlify.com/) + +## Blockquotes + +``` +As Kanye West said: + +> We're living the future so +> the present is our past. +``` + +As Kanye West said: + +> We're living the future so +> the present is our past. + +## Tables + +``` +| Animal | Sounds | +|---------|--------| +| Cat | Meow | +| Dog | Woof | +| Cricket | Chirp | +``` + +| Animal | Sounds | +|---------|--------| +| Cat | Meow | +| Dog | Woof | +| Cricket | Chirp | + +## Inline code + +``` +This `` tag is inline code. +``` + +This `` tag is inline code. + +## Block code + +```` +This + +``` + +``` + +tag is block code. +```` + +This + +``` + +``` + +tag is block code. \ No newline at end of file diff --git a/exampleSite/content/post/goisforlovers.md b/exampleSite/content/post/goisforlovers.md new file mode 100644 index 0000000..d218999 --- /dev/null +++ b/exampleSite/content/post/goisforlovers.md @@ -0,0 +1,333 @@ +--- +date: "2014-04-02" +tags: ["go", "templates", "hugo"] +title: "(Hu)go Template Primer" +toc: true +--- + +Hugo uses the excellent [Go][] [html/template][gohtmltemplate] library for +its template engine. It is an extremely lightweight engine that provides a very +small amount of logic. In our experience that it is just the right amount of +logic to be able to create a good static website. If you have used other +template systems from different languages or frameworks you will find a lot of +similarities in Go templates. + +This document is a brief primer on using Go templates. The [Go docs][gohtmltemplate] +provide more details. + +## Introduction to Go Templates + +Go templates provide an extremely simple template language. It adheres to the +belief that only the most basic of logic belongs in the template or view layer. +One consequence of this simplicity is that Go templates parse very quickly. + +A unique characteristic of Go templates is they are content aware. Variables and +content will be sanitized depending on the context of where they are used. More +details can be found in the [Go docs][gohtmltemplate]. + +## Basic Syntax + +Golang templates are HTML files with the addition of variables and +functions. + +**Go variables and functions are accessible within {{ }}** + +Accessing a predefined variable "foo": + + {{ foo }} + +**Parameters are separated using spaces** + +Calling the add function with input of 1, 2: + + {{ add 1 2 }} + +**Methods and fields are accessed via dot notation** + +Accessing the Page Parameter "bar" + + {{ .Params.bar }} + +**Parentheses can be used to group items together** + + {{ if or (isset .Params "alt") (isset .Params "caption") }} Caption {{ end }} + + +## Variables + +Each Go template has a struct (object) made available to it. In hugo each +template is passed either a page or a node struct depending on which type of +page you are rendering. More details are available on the +[variables](/layout/variables) page. + +A variable is accessed by referencing the variable name. + + {{ .Title }} + +Variables can also be defined and referenced. + + {{ $address := "123 Main St."}} + {{ $address }} + + +## Functions + +Go template ship with a few functions which provide basic functionality. The Go +template system also provides a mechanism for applications to extend the +available functions with their own. [Hugo template +functions](/layout/functions) provide some additional functionality we believe +are useful for building websites. Functions are called by using their name +followed by the required parameters separated by spaces. Template +functions cannot be added without recompiling hugo. + +**Example:** + + {{ add 1 2 }} + +## Includes + +When including another template you will pass to it the data it will be +able to access. To pass along the current context please remember to +include a trailing dot. The templates location will always be starting at +the /layout/ directory within Hugo. + +**Example:** + + {{ template "chrome/header.html" . }} + + +## Logic + +Go templates provide the most basic iteration and conditional logic. + +### Iteration + +Just like in Go, the Go templates make heavy use of range to iterate over +a map, array or slice. The following are different examples of how to use +range. + +**Example 1: Using Context** + + {{ range array }} + {{ . }} + {{ end }} + +**Example 2: Declaring value variable name** + + {{range $element := array}} + {{ $element }} + {{ end }} + +**Example 2: Declaring key and value variable name** + + {{range $index, $element := array}} + {{ $index }} + {{ $element }} + {{ end }} + +### Conditionals + +If, else, with, or, & and provide the framework for handling conditional +logic in Go Templates. Like range, each statement is closed with `end`. + + +Go Templates treat the following values as false: + +* false +* 0 +* any array, slice, map, or string of length zero + +**Example 1: If** + + {{ if isset .Params "title" }}

{{ index .Params "title" }}

{{ end }} + +**Example 2: If -> Else** + + {{ if isset .Params "alt" }} + {{ index .Params "alt" }} + {{else}} + {{ index .Params "caption" }} + {{ end }} + +**Example 3: And & Or** + + {{ if and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}} + +**Example 4: With** + +An alternative way of writing "if" and then referencing the same value +is to use "with" instead. With rebinds the context `.` within its scope, +and skips the block if the variable is absent. + +The first example above could be simplified as: + + {{ with .Params.title }}

{{ . }}

{{ end }} + +**Example 5: If -> Else If** + + {{ if isset .Params "alt" }} + {{ index .Params "alt" }} + {{ else if isset .Params "caption" }} + {{ index .Params "caption" }} + {{ end }} + +## Pipes + +One of the most powerful components of Go templates is the ability to +stack actions one after another. This is done by using pipes. Borrowed +from unix pipes, the concept is simple, each pipeline's output becomes the +input of the following pipe. + +Because of the very simple syntax of Go templates, the pipe is essential +to being able to chain together function calls. One limitation of the +pipes is that they only can work with a single value and that value +becomes the last parameter of the next pipeline. + +A few simple examples should help convey how to use the pipe. + +**Example 1 :** + + {{ if eq 1 1 }} Same {{ end }} + +is the same as + + {{ eq 1 1 | if }} Same {{ end }} + +It does look odd to place the if at the end, but it does provide a good +illustration of how to use the pipes. + +**Example 2 :** + + {{ index .Params "disqus_url" | html }} + +Access the page parameter called "disqus_url" and escape the HTML. + +**Example 3 :** + + {{ if or (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}} + Stuff Here + {{ end }} + +Could be rewritten as + + {{ isset .Params "caption" | or isset .Params "title" | or isset .Params "attr" | if }} + Stuff Here + {{ end }} + + +## Context (aka. the dot) + +The most easily overlooked concept to understand about Go templates is that {{ . }} +always refers to the current context. In the top level of your template this +will be the data set made available to it. Inside of a iteration it will have +the value of the current item. When inside of a loop the context has changed. . +will no longer refer to the data available to the entire page. If you need to +access this from within the loop you will likely want to set it to a variable +instead of depending on the context. + +**Example:** + + {{ $title := .Site.Title }} + {{ range .Params.tags }} +
  • {{ . }} - {{ $title }}
  • + {{ end }} + +Notice how once we have entered the loop the value of {{ . }} has changed. We +have defined a variable outside of the loop so we have access to it from within +the loop. + +## Hugo Parameters + +Hugo provides the option of passing values to the template language +through the site configuration (for sitewide values), or through the meta +data of each specific piece of content. You can define any values of any +type (supported by your front matter/config format) and use them however +you want to inside of your templates. + + +## Using Content (page) Parameters + +In each piece of content you can provide variables to be used by the +templates. This happens in the [front matter](/content/front-matter). + +An example of this is used in this documentation site. Most of the pages +benefit from having the table of contents provided. Sometimes the TOC just +doesn't make a lot of sense. We've defined a variable in our front matter +of some pages to turn off the TOC from being displayed. + +Here is the example front matter: + +``` +--- +title: "Permalinks" +date: "2013-11-18" +aliases: + - "/doc/permalinks/" +groups: ["extras"] +groups_weight: 30 +notoc: true +--- +``` + +Here is the corresponding code inside of the template: + + {{ if not .Params.notoc }} +
    + {{ .TableOfContents }} +
    + {{ end }} + + + +## Using Site (config) Parameters +In your top-level configuration file (eg, `config.yaml`) you can define site +parameters, which are values which will be available to you in chrome. + +For instance, you might declare: + +```yaml +params: + CopyrightHTML: "Copyright © 2013 John Doe. All Rights Reserved." + TwitterUser: "spf13" + SidebarRecentLimit: 5 +``` + +Within a footer layout, you might then declare a `