Browse Source

feat(layout,install): add automatic syntax highlighting

uses fetch-inject to async load syntax with fallback for noscript
Josh Habdas 10 months ago
parent
commit
3eed5ddd7d
Signed by: Josh Habdas <jhabdas@protonmail.com> GPG Key ID: B148B31154C75A74
5 changed files with 114 additions and 91 deletions
  1. 96
    89
      README.md
  2. 5
    1
      bin/install
  3. 7
    0
      layouts/_default/baseof.html
  4. 5
    1
      layouts/partials/async-scripts.html
  5. 1
    0
      static/css/syntax.css

+ 96
- 89
README.md View File

@@ -20,20 +20,20 @@ The following table outlines key features which differentiate After Dark for oth
20 20
 
21 21
 Feature | Summary
22 22
 --------|--------
23
-[Quick Installer](#getting-started) | After Dark provides a cross-platform quick installer. One command is all you need to start creating a website anywhere you can access a terminal.
24
-[Module System](#module-system) | Add additional functionality to your site using [Hugo Theme Components](https://gohugo.io/themes/theme-components/). After Dark includes a module system and a number of custom-built modules specifically designed to enhance your site.
23
+[Quick Installer](#getting-started) | After Dark provides a cross-platform quick installer. One command is all you need to start creating a website.
24
+[Module System](#module-system) | Add more functionality to your site. After Dark includes a module system and a number of custom-built modules designed to compliment the theme.
25 25
 [Theme Variants](#theme-variants) | Choose from one of three dark color pallets and two different display modes. Toggle between them anytime directly from your site configuration.
26
-[Lazy Loading](#lazy-loading) | Decrease page load time and improve user experience on slower connections. After Dark includes [lazysizes](https://github.com/aFarkas/lazysizes), a zero-configuration JavaScript library, for low-friction lazy-loading of images, scripts, iFrames and more.
26
+[Fuzzy Search](#fuzzy-search) | Find crawlable content anywhere on your site. After Dark includes a custom search app built with [Vue](https://vuejs.org/), [Fuse](http://fusejs.io/) and [Mark](https://markjs.io). No registration necessary.
27
+[Syntax Highlighting](#syntax-highlighting) | Share code with style. After Dark automatically highlights code written more than 160 languages and doesn't require any JavaScript to do it.
28
+[Post Images](#post-images) | Easily add performance-optimized, responsive post images without fiddling around with an image editor or touching a single line of code.
29
+[Lazy Loading](#lazy-loading) | Decrease page load time and improve user experience on slower connections. After Dark includes [lazysizes](https://github.com/aFarkas/lazysizes) for dead simple lazy-loading of images, scripts, iFrames and more.
27 30
 [Social Engagement](#social-engagement) | After Dark provides automatic and configurable [Open Graph](http://ogp.me/) support, Twitter Cards and Telegram Instant View template to make social shares pop like 37 pieces of flair.
28 31
 [Search Optimization](#search-optimization) | Using [Schema Structured Data](https://moz.com/learn/seo/schema-structured-data) and meta tags, After Dark gives crawlers rich data about the site structure and content. No configuration required.
29
-[Post Images](#post-images) | Increase visual appeal of posts. After Dark enables configuration-driven post images which are lazy-loaded, responsive and automatically cropped for a consistent look-and-feel across your site.
30
-[Fuzzy Search](#fuzzy-search) | After Dark ships with an in-browser search app built with [Vue](https://vuejs.org/), [Fuse](http://fusejs.io/) and [Mark](https://markjs.io). Use it to quickly find crawlable content anywhere your site.
31 32
 [Personalization](#personalization) | Tweak CSS using the purpose-built [customization file](#custom-styles). Swap in [your own favicon](#favicon). Leverage [block templates](https://gohugo.io/templates/blocks) to quickly extend new custom layouts. And use [hack.css](https://hackcss.egoist.moe/dark.html) flexbox grids and CSS components to add style your site.
32
-[Snippets](#snippets) | After Dark provides a number of reusable code snippets for adding things like tweets, [coubs](https://coub.com), blockquotes, figures, [hackcss components](https://hackcss.egoist.moe/) and more. Use them to create completely custom layouts or simply spice up an existing document.
33
+[Code Snippets](#code-snippets) | After Dark provides a number of reusable code snippets for adding things like tweets, [coubs](https://coub.com), blockquotes, figures, [hackcss components](https://hackcss.egoist.moe/) and more. Use them to create completely custom layouts or simply spice up an existing document.
33 34
 [Related Content](#related-content) | Promote more of your content to your site visitors. By offering your readers more content that's relevant to them you can increase your site's page views, the time spent on your site and reader loyalty.
34 35
 [Table of Contents](#table-of-contents) | Help users locate and share information in long posts. By providing a Table of Contents, users will spend less time scrolling to locate information in larger documents and are more likely to deep link to specific information on a page.
35 36
 [Modification Dating](#modification-dating) | Surface recently updated content to users and crawlers, allowing them to understand when a post or page was was last modified. Recently updated posts will be flagged as modified and visually lifted upwards in chronological listings.
36
-[Syntax Highlighting](#syntax-highlighting) | Share code snippets with style. After Dark provides Atom One [Light](https://atom.io/themes/one-light-syntax) and [Dark](https://atom.io/themes/one-dark-syntax) syntax highlighting for 1337 code sharing.
37 37
 [Taxonomy Pages](https://gohugo.io/content-management/taxonomies) | Help users discover taxonomic content. After Dark automatically generates taxonomy and taxonomy terms pages and links to them in post bylines.
38 38
 [Error Page](https://hackcabin.com/post/after-dark-error-page-redesign/) | Decrease bounce rate when URL errors occur. After Dark provides an engaging 404 page with animated background.
39 39
 Post Bylines | Rich post bylines include optional author name, word count, links to taxonomy pages and metadata for search engines.
@@ -109,6 +109,90 @@ Finally, the menu can be disabled from site config anytime:
109 109
 
110 110
 See Hugo's [Menu docs](https://gohugo.io/content-management/menus/) for more information.
111 111
 
112
+### Syntax Highlighting
113
+
114
+After Dark automatically highlights code written in more than 160 languages using a customized version of [One Dark Syntax](https://atom.io/themes/one-dark-syntax) with full color display support in terminal browsers.
115
+
116
+To activate the syntax highlighter simply use the [`highlight` shortcode](https://gohugo.io/content-management/syntax-highlighting/#highlight-shortcode) or indicate the [highlighting language](https://gohugo.io/content-management/syntax-highlighting/#list-of-chroma-highlighting-languages) with a fenced code block from within your page content, e.g. ```` ```rust ````
117
+
118
+![Syntax Highlighting screenshot](https://git.habd.as/comfusion/after-dark/raw/branch/master/images/docs/feat-syntax-highlighting-fs8.png "Example JavaScript highlighting with line numbers.")
119
+
120
+If you'd prefer a lighter background color create a file called `syntax.css` in your site `static/css` folder and drop in the contents of one of the following:
121
+
122
+- [`dark.css`](https://cdn.jsdelivr.net/npm/atom-one-chroma/dist/dark.css) `#282c34` colored background
123
+- [`light.css`](https://cdn.jsdelivr.net/npm/atom-one-chroma/dist/light.css) `#fafafa` colored background
124
+
125
+Alternatively, roll your own syntax using the [syntax roller](https://git.habd.as/comfusion/atom-one-chroma) purpose-built for use with After Dark.
126
+
127
+Reference the Hugo [Syntax Highlighting](https://gohugo.io/content-management/syntax-highlighting/) docs for additional information.
128
+
129
+### Fuzzy Search
130
+
131
+Find content site-wide in the blink of an eye. JavaScript fuzzy search is at your fingertips. To use it simply create a section called `search` using the After Dark search layout like so:
132
+
133
+```
134
+└── content
135
+    └── search
136
+        └── _index.md
137
+```
138
+
139
+With `_index.md` like:
140
+
141
+```
142
++++
143
+title = "Search"
144
+layout = "search"
145
+noindex = true
146
++++
147
+```
148
+
149
+Then tell Hugo to output an `index.json` file along with your site when building by adding the following to the config:
150
+
151
+```
152
+[outputs]
153
+  home = ["HTML", "RSS", "JSON"]
154
+  section = ["HTML", "RSS", "JSON"]
155
+```
156
+
157
+**Note:** If you don't see `index.json` in your `public` folder after building try running a `hugo --gc` to cajole the generator into creating the JSON file.
158
+
159
+After that navigate to the `/search/` path on your site and let the fun begin.
160
+
161
+**Tip:** Consider enabling the After Dark [section menu](#section-menu) to expose the search section to users.
162
+
163
+While deep link searches are supported, please note Fuzzy Search will only return results for [Regular Pages](https://gohugo.io/variables/site/#site-variables-list) and intentionally omits any page tagged for [index blocking](#index-blocking). In other words it's easy to find stuff. But only if you want it to be found.
164
+
165
+### Post Images
166
+
167
+Bring your words to life with post images. Post images appear above post content and leverage Hugo's inbuilt [Image Processing](https://gohugo.io/content-management/image-processing/) to enable automatic cropping and image positioning.
168
+
169
+Because post images are often one of the first things users see when visiting your site After Dark takes some extra steps to load them in a performant manner. Techniques used to speed up image loading include [Low-Quality Image Placeholders](https://www.afasterweb.com/2016/08/31/low-quality-blur-in/), [Lazy Loading](#lazy-loading) and responsive images using the `srcset` and `sizes` attributes.
170
+
171
+Using post images requires some opinion with regard to the structure of your content. To create a post with a post image you must:
172
+
173
+1. Create a [Page Bundle](https://gohugo.io/content-management/page-bundles/) grouping your desired image together with your post content.
174
+2. Specify the [Resources Metadata](https://gohugo.io/content-management/page-resources/#resources-metadata-toml-example) in the post front matter and set the `name` property to `"header"`.
175
+
176
+An example page bundle might look like:
177
+
178
+```
179
+└── post
180
+    └── secure-your-digital-life
181
+        ├── images
182
+        │   └── florian-klauer-119557-unsplash.jpg
183
+        └── index.md
184
+```
185
+
186
+With the following front matter specified in `index.md`:
187
+
188
+```
189
+[[resources]]
190
+  src = "images/florian-klauer-119557-unsplash.jpg"
191
+  name = "header"
192
+```
193
+
194
+That's it! After Dark does the rest.
195
+
112 196
 ### Lazy Loading
113 197
 
114 198
 Lazy loading prioritizes when and how images and more are downloaded, improving perceived performance and reducing page load times. Lazy loading will start working automatically. No configuration is necessary.
@@ -138,7 +222,7 @@ To activate lazy loading with [lazysizes], add `lazyload` to the `class` attribu
138 222
 </iframe>
139 223
 ```
140 224
 
141
-After Dark includes a _Shortcode_ taking advantage of this feature, enabling you to easily create [lazy-loaded `figure` elements](#snippets) within your markdown content.
225
+After Dark includes a _Shortcode_ taking advantage of this feature, enabling you to easily create [lazy-loaded `figure` elements](#code-snippets) within your markdown content.
142 226
 
143 227
 Additional information and examples, including how to set-up and use LQIP (Low-Quality Image Placeholders), are available on the [lazysizes] repository on GitHub.
144 228
 
@@ -225,13 +309,13 @@ See the Hugo [Internal Templates documentation](https://gohugo.io/templates/inte
225 309
 
226 310
 #### Telegram Instant View
227 311
 
228
-Improve the experience for Telegram users by providing an [Instant View](https://instantview.telegram.org/) (IV). After Dark makes easy.
312
+Improve the experience for Telegram users by providing an [Instant View](https://instantview.telegram.org/). After Dark makes easy.
229 313
 
230 314
 ![Open Graph sharing card screenshot](https://git.habd.as/comfusion/after-dark/raw/branch/master/images/docs/feat-instant-view-fs8.png "Example Telegram Instant View for After Dark")
231 315
 
232
-To create an IV for your site simply [create your own](https://instantview.telegram.org/my/) Instant View template modeling from the example template below.
316
+To create an Instant View for your site simply [create your own](https://instantview.telegram.org/my/) IV template modeling from the example here:
233 317
 
234
-```
318
+```yaml
235 319
 # enable for items in the post section
236 320
 ?path: /post/.+
237 321
 
@@ -405,73 +489,6 @@ keywords = [
405 489
 
406 490
 While not considered relevant to some crawlers, keywords can be a useful way to document target search terms for use in <abbr title="Pay-Per-Click">PPC</abbr> online advertising and provide semantic value to your pages.
407 491
 
408
-### Post Images
409
-
410
-Bring your words to life with post images. Post images appear above post content and leverage Hugo's inbuilt [Image Processing](https://gohugo.io/content-management/image-processing/) to enable automatic cropping and image positioning.
411
-
412
-Because post images are often one of the first things users see when visiting your site After Dark takes some extra steps to load them in a performant manner. Techniques used to speed up image loading include [Low-Quality Image Placeholders](https://www.afasterweb.com/2016/08/31/low-quality-blur-in/), [Lazy Loading](#lazy-loading) and responsive images using the `srcset` and `sizes` attributes.
413
-
414
-Using post images requires some opinion with regard to the structure of your content. To create a post with a post image you must:
415
-
416
-1. Create a [Page Bundle](https://gohugo.io/content-management/page-bundles/) grouping your desired image together with your post content.
417
-2. Specify the [Resources Metadata](https://gohugo.io/content-management/page-resources/#resources-metadata-toml-example) in the post front matter and set the `name` property to `"header"`.
418
-
419
-An example page bundle might look like:
420
-
421
-```
422
-└── post
423
-    └── secure-your-digital-life
424
-        ├── images
425
-        │   └── florian-klauer-119557-unsplash.jpg
426
-        └── index.md
427
-```
428
-
429
-With the following front matter specified in `index.md`:
430
-
431
-```
432
-[[resources]]
433
-  src = "images/florian-klauer-119557-unsplash.jpg"
434
-  name = "header"
435
-```
436
-
437
-That's it! After Dark does the rest.
438
-
439
-### Fuzzy Search
440
-
441
-Find content site-wide in the blink of an eye. JavaScript fuzzy search is at your fingertips. To use it simply create a section called `search` using the After Dark search layout like so:
442
-
443
-```
444
-└── content
445
-    └── search
446
-        └── _index.md
447
-```
448
-
449
-With `_index.md` like:
450
-
451
-```
452
-+++
453
-title = "Search"
454
-layout = "search"
455
-noindex = true
456
-+++
457
-```
458
-
459
-Then tell Hugo to output an `index.json` file along with your site when building by adding the following to the config:
460
-
461
-```
462
-[outputs]
463
-  home = ["HTML", "RSS", "JSON"]
464
-  section = ["HTML", "RSS", "JSON"]
465
-```
466
-
467
-**Note:** If you don't see `index.json` in your `public` folder after building try running a `hugo --gc` to cajole the generator into creating the JSON file.
468
-
469
-After that navigate to the `/search/` path on your site and let the fun begin.
470
-
471
-**Tip:** Consider enabling the After Dark [section menu](#section-menu) to expose the search section to users.
472
-
473
-While deep link searches are supported, please note Fuzzy Search will only return results for [Regular Pages](https://gohugo.io/variables/site/#site-variables-list) and intentionally omits any page tagged for [index blocking](#index-blocking). In other words it's easy to find stuff. But only if you want it to be found.
474
-
475 492
 ### Markdown Output
476 493
 
477 494
 Gain more control over markdown conversion to HTML. By modifying the markdown processor settings you can take advantage of [Blackfriday](https://github.com/russross/blackfriday) features not enabled by default.
@@ -488,7 +505,7 @@ Overrides to theme markdown processing defaults are available from page front ma
488 505
 
489 506
 See the Hugo docs for additional [configuration options](http://gohugo.io/overview/configuration/#configure-blackfriday-rendering).
490 507
 
491
-### Snippets
508
+### Code Snippets
492 509
 
493 510
 Snippets are reusable bits of code you can sprinkle across your site to reduce repetition and improve consistency. After Dark provides a number of snippets in the form of [hackcss components](https://hackcss.egoist.moe/) and [Hugo Shortcodes](https://gohugo.io/extras/shortcodes) to help make your site easier to maintain.
494 511
 
@@ -534,16 +551,6 @@ To create your own custom shortcodes add a `layouts/shortcodes` directory to you
534 551
 
535 552
 Reference the Hugo docs for [shortcode usage instructions](https://gohugo.io/content-management/shortcodes/#using-a-shortcode) and see the inline documentation within each shortcode for example usage instructions.
536 553
 
537
-### Syntax Highlighting
538
-
539
-Provide a richer experience when sharing code snippets on your site. After Dark provides a [hackable code highlighter](https://git.habd.as/comfusion/atom-one-chroma) using the lovely [One Dark](https://atom.io/themes/one-dark-syntax) and [One Light](https://atom.io/themes/one-light-syntax) syntax themes.
540
-
541
-![Syntax Highlighting screenshot](https://git.habd.as/comfusion/after-dark/raw/branch/master/images/docs/feat-syntax-highlighting-fs8.png "Syntax Highlighting with Atom One")
542
-
543
-To set-up syntax highlighting for your After Dark site copy the contents of [`light.css`](https://cdn.jsdelivr.net/npm/atom-one-chroma/dist/light.css) or [`dark.css`](https://cdn.jsdelivr.net/npm/atom-one-chroma/dist/dark.css) into your [Custom Styles](#custom-styles) file and rebuild your site. Once configured, simply use Hugo built-in [`highlight` shortcode](https://gohugo.io/extras/shortcodes#highlight) to highlight your code.
544
-
545
-Reference Hugo's [Syntax Highlighting docs](https://gohugo.io/content-management/syntax-highlighting/) for usage instructions and additional configuration options.
546
-
547 554
 ### Personalization
548 555
 
549 556
 After Dark uses [hack.css](https://hackcss.egoist.moe/dark.html) to automatically style your markup, giving you instant access to flexbox grids, several dark theme variants, and other pre-built components. Use them while creating new [sections](#section-menu) leveraging [block templates](https://gohugo.io/templates/blocks). Additional personalization options listed below.

+ 5
- 1
bin/install View File

@@ -68,7 +68,11 @@ theme = [
68 68
 ]
69 69
 
70 70
 enableRobotsTXT = true # Suggested, enable robots.txt file
71
-disqusShortname = "" # Optional, add Disqus shortname for comments
71
+disqusShortname = "" # Deprecated, add Disqus shortname for comments
72
+
73
+pygmentsCodefences = true # Suggested, highlight fenced code blocks
74
+pygmentsUseClasses = true # Required for custom syntax highlighting
75
+
72 76
 SectionPagesMenu = "main" # Enable menu system for lazy bloggers
73 77
 footnoteReturnLinkContents = "↩" # Provides a nicer footnote return link
74 78
 

+ 7
- 0
layouts/_default/baseof.html View File

@@ -37,6 +37,13 @@
37 37
     {{ partial "head/favicon.html" . }}
38 38
     {{ partial "global-styles.html" . }}
39 39
     {{ partial "async-scripts.html" . }}
40
+    {{ $highlights := findRE "class\\s*?=\\s*?\".*?\\bhighlight\\b.*?\"|class\\s*?=\\s*?highlight\\b" .Content }}
41
+    {{ if ge (len $highlights) 1 }}
42
+      <script>fetchInject([{{ "/css/syntax.css" | relURL }}])</script>
43
+      <noscript>
44
+        <link href={{ "/css/syntax.css" | relURL }} rel="stylesheet">
45
+      </noscript>
46
+    {{ end }}
40 47
   </head>
41 48
   {{ $hackcss_disabled := .Site.Params.hackcss.disabled | default false }}
42 49
   {{ $hackcss_mode := .Site.Params.hackcss.mode | default "hack" }}

+ 5
- 1
layouts/partials/async-scripts.html View File

@@ -1 +1,5 @@
1
-<script async src={{ "/js/lazysizes.min.js" | relURL }}></script>
1
+<script>
2
+/*! Fetch Inject v2.0.2 | Copyright (C) 2017–2018 Josh Habdas <jhabdas@protonmail.com> | @license Zlib */
3
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.fetchInject=t()}(this,function(){"use strict";const e=function(e,t,n,r,o,c,i){c=t.createElement(n),i=t.getElementsByTagName(n)[0],c.appendChild(t.createTextNode(r.text)),c.onload=o(r),i?i.parentNode.insertBefore(c,i):t.head.appendChild(c)};return function(t,n){if(!arguments.length)return Promise.reject(new ReferenceError("Failed to execute 'fetchInject': 1 argument required but only 0 present."));if(arguments[0]&&arguments[0].constructor!==Array)return Promise.reject(new TypeError("Failed to execute 'fetchInject': argument 1 must be of type 'Array'."));if(arguments[1]&&arguments[1].constructor!==Promise)return Promise.reject(new TypeError("Failed to execute 'fetchInject': argument 2 must be of type 'Promise'."));const r=[],o=n?[].concat(n):[],c=[];return t.forEach(e=>o.push(window.fetch(e).then(e=>[e.clone().text(),e.blob()]).then(e=>Promise.all(e).then(e=>{r.push({text:e[0],blob:e[1]})})))),Promise.all(o).then(()=>(r.forEach(t=>{c.push({then:n=>{t.blob.type.includes("text/css")?e(window,document,"style",t,n):e(window,document,"script",t,n)}})}),Promise.all(c)))}});
4
+fetchInject([{{ "/js/lazysizes.min.js" | relURL }}]);
5
+</script>

+ 1
- 0
static/css/syntax.css View File

@@ -0,0 +1 @@
1
+.highlight,pre.highlight{background:#000;color:#abb2bf}.highlight pre{background:#000}.highlight .ge{font-style:italic}.highlight .gs{font-weight:700}.highlight .ow{font-weight:700}.highlight .n,.highlight .nf,.highlight .nn,.highlight .o,.highlight .p{color:#abb2bf}.highlight .c,.highlight .c1,.highlight .cm,.highlight .cp,.highlight .cs{color:#5c6370;font-style:italic}.highlight .sr,.highlight .ss{color:#56b6c2}.highlight .k,.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:#c678dd}.highlight .l,.highlight .ld,.highlight .s,.highlight .s1,.highlight .s2,.highlight .sb,.highlight .sc,.highlight .sd,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx{color:#98c379}.highlight .nt,.highlight .nx,.highlight .vi{color:#e06c75}.highlight .il,.highlight .m,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo,.highlight .na{color:#d19a66}.highlight .bp,.highlight .nb,.highlight .nc,.highlight .nd,.highlight .ne,.highlight .ni,.highlight .nl,.highlight .no,.highlight .nv,.highlight .py,.highlight .vc,.highlight .vg{color:#e5c07b}.highlight .err{color:#fff;background-color:#e05252}.highlight .gd{color:#e05252}.highlight .gi{color:#43d08a}.highlight .w{color:#f8f8f2}.highlight .cpf{color:navy}.highlight .gu{color:#75715e}.highlight .lineno{color:#636d83;user-select:none}.highlight .ln{color:#636d83;user-select:none}.highlight .ln:after{content:" "}.highlight .hll{color:#abb2bf;background-color:#3a3f4b}.highlight .hl{color:#abb2bf;background-color:#3a3f4b}.highlight .language-json .w+.s2{color:#e06c75}.highlight .language-json .kc{color:#56b6c2}

Loading…
Cancel
Save