mirror of
https://github.com/facundoolano/jorge.git
synced 2024-12-25 21:58:28 +01:00
Syntax highlighting (#15)
* update markdown and org renderers to use chrome highlighting * add example code blocks * fix missing nav in default layout * remove problematic code nowrap * add language to tutorial samples * set theme explicitly * allow setting highlight theme with config * fix config key for hl * try to handle both light dark settings gracefully * fix some problematic css color settings * fix missing raw template * fix weird chroma code height artifacts * improve tabler rendering in mobile * remove redundant default
This commit is contained in:
parent
924e4629b2
commit
e344dcb6ad
17 changed files with 260 additions and 68 deletions
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
layout: base
|
||||
---
|
||||
{% include nav.html %}
|
||||
|
||||
<div class="content layout-{{ page.layout }}" lang="{{ page.lang | default:site.config.lang | default:'en' }}">
|
||||
<header {% if page.cover-img %}class="with-cover"{% endif %}>
|
||||
|
|
|
@ -60,9 +60,14 @@ a:hover {
|
|||
}
|
||||
|
||||
a.title {
|
||||
color: unset!important;
|
||||
color: black;
|
||||
padding-right: .25rem;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
a.title {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.footer, .footer a, .date, .tags, .tags a {
|
||||
color: silver;
|
||||
|
@ -129,7 +134,8 @@ img.cover-img {
|
|||
margin-top: -0.5rem;
|
||||
}
|
||||
|
||||
.src pre {
|
||||
pre {
|
||||
font-size: 1rem;
|
||||
overflow-x: auto;
|
||||
line-height: 1.5;
|
||||
padding: 1rem;
|
||||
|
@ -137,21 +143,52 @@ img.cover-img {
|
|||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
.src pre, code {
|
||||
background: whitesmoke;
|
||||
font-size: 1rem;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
||||
.src pre::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
hack to fix height weirdness in code snippets
|
||||
https://github.com/alecthomas/chroma/issues/617#issuecomment-1063251066
|
||||
*/
|
||||
code > span[style^="display:flex;"] {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
/* There are several code rendering scenarios that need to be handled reasonably:
|
||||
- light vs dark preferred color scheme
|
||||
- pre code blocks vs inline code spans
|
||||
- language set vs no language set
|
||||
- markdown vs org rendering
|
||||
|
||||
Need to decide between:
|
||||
- fixing the color scheme of the page + using one of chroma's themes
|
||||
- supporting both light/dark and disabling syntax highlighting altogether
|
||||
- supporting light/dark, picking a theme and patching it to render decently
|
||||
with both preferences (as done below, assuming chroma's github theme)
|
||||
*/
|
||||
.layout-post :not(pre) > code {
|
||||
padding: .2em .4em;
|
||||
background-color: whitesmoke!important;
|
||||
color: black;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.layout-post :not(pre) > code {
|
||||
background-color: rgba(110, 118, 129, 0.4)!important;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-post pre, .layout-post code {
|
||||
border-radius: 6px;
|
||||
background-color: whitesmoke!important;
|
||||
font-size: 1rem;
|
||||
hyphens: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 2px solid whitesmoke;
|
||||
padding-left: 1rem;
|
||||
|
@ -208,6 +245,10 @@ table tr {
|
|||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
td { display: inline-block }
|
||||
}
|
||||
|
||||
td, th {
|
||||
padding: .5rem;
|
||||
}
|
||||
|
|
|
@ -10,4 +10,16 @@ layout: post
|
|||
For the record, even though it has *org* in the name, jorge can also render markdown,
|
||||
thanks to [goldmark](https://github.com/yuin/goldmark/).
|
||||
|
||||
Let's look at some code:
|
||||
|
||||
``` python
|
||||
import os
|
||||
|
||||
def hello():
|
||||
print("Hello World!")
|
||||
os.exit(0)
|
||||
|
||||
hello()
|
||||
```
|
||||
|
||||
[Next time](./hello-org), I'll talk about org-mode posts.
|
||||
|
|
|
@ -15,6 +15,18 @@ As you can see, /italics/ and *bold* render as expected, and you can even use fo
|
|||
|
||||
All of this is powered by [[https://github.com/niklasfasching/go-org][go-org]], btw[fn:2].
|
||||
|
||||
Let's look at some code:
|
||||
|
||||
#+begin_src python
|
||||
import os
|
||||
|
||||
def hello():
|
||||
print("Hello World!")
|
||||
os.exit(0)
|
||||
|
||||
hello()
|
||||
#+end_src
|
||||
|
||||
** Notes
|
||||
|
||||
[fn:1] See?
|
||||
|
|
|
@ -29,6 +29,7 @@ type Config struct {
|
|||
SiteUrl string
|
||||
PostFormat string
|
||||
Lang string
|
||||
HighlightTheme string
|
||||
|
||||
Minify bool
|
||||
LiveReload bool
|
||||
|
@ -56,6 +57,7 @@ func Load(rootDir string) (*Config, error) {
|
|||
DataDir: filepath.Join(rootDir, "data"),
|
||||
PostFormat: "blog/:title.org",
|
||||
Lang: "en",
|
||||
HighlightTheme: "github",
|
||||
Minify: true,
|
||||
LiveReload: false,
|
||||
LinkStatic: false,
|
||||
|
@ -79,6 +81,7 @@ func Load(rootDir string) (*Config, error) {
|
|||
}
|
||||
|
||||
// set user-provided overrides of declared config keys
|
||||
// TODO less copypasty way of declaring config overrides
|
||||
if url, found := config.overrides["url"]; found {
|
||||
config.SiteUrl = url.(string)
|
||||
}
|
||||
|
@ -88,6 +91,9 @@ func Load(rootDir string) (*Config, error) {
|
|||
if format, found := config.overrides["lang"]; found {
|
||||
config.Lang = format.(string)
|
||||
}
|
||||
if format, found := config.overrides["highlight_theme"]; found {
|
||||
config.HighlightTheme = format.(string)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
|
|
@ -60,9 +60,14 @@ a:hover {
|
|||
}
|
||||
|
||||
a.title {
|
||||
color: unset!important;
|
||||
color: black;
|
||||
padding-right: .25rem;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
a.title {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.footer, .footer a, .date, .tags, .tags a {
|
||||
color: silver;
|
||||
|
@ -129,7 +134,7 @@ img.cover-img {
|
|||
margin-top: -0.5rem;
|
||||
}
|
||||
|
||||
.src pre {
|
||||
pre {
|
||||
font-size: 1rem;
|
||||
overflow-x: auto;
|
||||
line-height: 1.5;
|
||||
|
@ -138,21 +143,52 @@ img.cover-img {
|
|||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
.layout-post .src pre, .layout-post code {
|
||||
background: whitesmoke;
|
||||
font-size: 1rem;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
||||
.src pre::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
hack to fix height weirdness in code snippets
|
||||
https://github.com/alecthomas/chroma/issues/617#issuecomment-1063251066
|
||||
*/
|
||||
code > span[style^="display:flex;"] {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
/* There are several code rendering scenarios that need to be handled reasonably:
|
||||
- light vs dark preferred color scheme
|
||||
- pre code blocks vs inline code spans
|
||||
- language set vs no language set
|
||||
- markdown vs org rendering
|
||||
|
||||
Need to decide between:
|
||||
- fixing the color scheme of the page + using one of chroma's themes
|
||||
- supporting both light/dark and disabling syntax highlighting altogether
|
||||
- supporting light/dark, picking a theme and patching it to render decently
|
||||
with both preferences (as done below, assuming chroma's github theme)
|
||||
*/
|
||||
.layout-post :not(pre) > code {
|
||||
padding: .2em .4em;
|
||||
background-color: whitesmoke!important;
|
||||
color: black
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.layout-post :not(pre) > code {
|
||||
background-color: rgba(110, 118, 129, 0.4)!important;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-post pre, .layout-post code {
|
||||
border-radius: 6px;
|
||||
background-color: whitesmoke!important;
|
||||
font-size: 1rem;
|
||||
hyphens: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 2px solid whitesmoke;
|
||||
padding-left: 1rem;
|
||||
|
@ -209,6 +245,11 @@ table tr {
|
|||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
td { display: inline-block }
|
||||
}
|
||||
|
||||
|
||||
td, th {
|
||||
padding: .5rem;
|
||||
}
|
||||
|
|
|
@ -10,4 +10,16 @@ layout: post
|
|||
For the record, even though it has *org* in the name, jorge can also render markdown,
|
||||
thanks to [goldmark](https://github.com/yuin/goldmark/).
|
||||
|
||||
Let's look at some code:
|
||||
|
||||
``` python
|
||||
import os
|
||||
|
||||
def hello():
|
||||
print("Hello World!")
|
||||
os.exit(0)
|
||||
|
||||
hello()
|
||||
```
|
||||
|
||||
[Next time](./hello-org), I'll talk about org-mode posts.
|
||||
|
|
|
@ -15,6 +15,18 @@ As you can see, /italics/ and *bold* render as expected, and you can even use fo
|
|||
|
||||
All of this is powered by [[https://github.com/niklasfasching/go-org][go-org]], btw[fn:2].
|
||||
|
||||
Let's look at some code:
|
||||
|
||||
#+begin_src python
|
||||
import os
|
||||
|
||||
def hello():
|
||||
print("Hello World!")
|
||||
os.exit(0)
|
||||
|
||||
hello()
|
||||
#+end_src
|
||||
|
||||
** Notes
|
||||
|
||||
[fn:1] See?
|
||||
|
|
|
@ -11,7 +11,7 @@ index: 5
|
|||
|
||||
So far you've seen how to [[file:jorge-init][start a project]], [[file:jorge-serve][serve it locally]] and [[file:jorge-post][add some content]] to it. The last part of job is to prepare your site for the public, and ~jorge build~ will help with that:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src console
|
||||
$ jorge build
|
||||
wrote target/2024-02-23-another-kind-of-post.html
|
||||
wrote target/blog/my-own-blog-post.html
|
||||
|
@ -34,7 +34,7 @@ Once you have your static site rendered, it's just a matter to putting it out in
|
|||
|
||||
But for the sake of completenss, this is how this site is deployed: I have a VPS box running Debian Linux and with the [[https://www.nginx.com/][nginx]] server installed on it. I added this configuration to ~/etc/nginx/sites-enabled/jorge~:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src nginx
|
||||
server {
|
||||
charset utf-8;
|
||||
root /var/www/jorge;
|
||||
|
@ -52,7 +52,7 @@ I instructed my DNS provider to point ~jorge.olano.dev~ to the box and I ran [[h
|
|||
|
||||
I then created the ~/var/www/jorge~ directory in the server, and deployed from my laptop using ~rsync~:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src console
|
||||
$ jorge build
|
||||
$ rsync -vPrz --delete target/ root@olano.dev:/var/www/jorge
|
||||
#+end_src
|
||||
|
|
|
@ -11,12 +11,11 @@ index: 2
|
|||
|
||||
Once jorge is [[file:installation][installed]], you can start a new site with the ~init~ command, specifying a project directory (~myblog~ in the example):
|
||||
|
||||
#+begin_src bash
|
||||
#+begin_src console
|
||||
$ jorge init myblog
|
||||
site name: My Blog
|
||||
site url: https://myblog.example.com
|
||||
author: Jorge Blog
|
||||
|
||||
> site name: My Blog
|
||||
> site url: https://myblog.example.com
|
||||
> author: Jorge Blog
|
||||
added myblog/config.yml
|
||||
added myblog/README.md
|
||||
added myblog/.gitignore
|
||||
|
|
|
@ -30,14 +30,14 @@ Each website has its own layout so it's hard to predict what you may need to do
|
|||
|
||||
From the root directory of your project run ~jorge post "My own blog post"~:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src console
|
||||
$ jorge post "My own blog post"
|
||||
added src/blog/my-own-blog-post.org
|
||||
#+end_src
|
||||
|
||||
If you open the new file with your editor, you should see something like this:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src org
|
||||
---
|
||||
title: My own blog post
|
||||
date: 2024-02-23 11:45:30
|
||||
|
@ -65,18 +65,18 @@ With ~jorge serve~ running, you can start filling in some content on this new po
|
|||
** Customizing the post format
|
||||
As you may have noticed, the ~jorge post~ command makes a lot of assumptions: where to put it, how to name it, and what format to use. You can control some of these decisions by setting the ~post_format~ configuration key. The default is:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src yaml
|
||||
post_format: "blog/:title.org"
|
||||
#+end_src
|
||||
|
||||
Let's say that you want to put posts in the root folder, include the date in them, and use the markdown format by default. Add this key to your ~config.yml~:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src yaml
|
||||
post_format: ":year-:month-:day-:title.md"
|
||||
#+end_src
|
||||
|
||||
The, if you add a new post:
|
||||
#+begin_src
|
||||
#+begin_src console
|
||||
$ jorge post "Another kind of post"
|
||||
added src/2024-02-23-another-kind-of-post.md
|
||||
#+end_src
|
||||
|
|
|
@ -11,7 +11,7 @@ index: 3
|
|||
|
||||
Now that you have some [[file:jorge-init][default files]] in place, let's see how the website looks. Run ~jorge serve~ on the website directory:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src console
|
||||
$ cd myblog
|
||||
$ jorge serve
|
||||
building site
|
||||
|
@ -31,7 +31,7 @@ If you open your browser at http://localhost:4001 you'll see the website we just
|
|||
|
||||
If you open ~src/index.html~ in your editor, you should see something roughly matching what you see on the browser:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src html
|
||||
{% raw %}
|
||||
---
|
||||
layout: default
|
||||
|
@ -50,11 +50,13 @@ This file is a [[https://shopify.github.io/][liquid template]] for an HTML file.
|
|||
2. The rest of the file contents will be rendered according to the liquid template syntax.
|
||||
3. If it's an org-mode or markdown file, its contents will be converted to their corresponding HTML in the target.
|
||||
|
||||
{% raw %}
|
||||
In the example above, the ~layout: default~ instructs jorge to embed the index.html rendered output inside the layout defined at ~layouts/default.html~. And the liquid variables expressed by ~{{ site.config.name }}~ and ~{{ site.config.author }}~ will be replaced by the values found at ~config.yml~.
|
||||
{% endraw %}
|
||||
|
||||
If you change the markup in ~src/index.html~, you should see your browser tab refresh automatically to reflect those changes. Try, for instance, changing the title in the first header:
|
||||
|
||||
#+begin_src
|
||||
#+begin_src html
|
||||
<h2><a href="#home" class="title" id="home">Home sweet home</a></h2>
|
||||
#+end_src
|
||||
|
||||
|
|
3
go.mod
3
go.mod
|
@ -3,6 +3,7 @@ module github.com/facundoolano/jorge
|
|||
go 1.22.0
|
||||
|
||||
require (
|
||||
github.com/alecthomas/chroma/v2 v2.5.0
|
||||
github.com/alecthomas/kong v0.8.1
|
||||
github.com/elliotchance/orderedmap/v2 v2.2.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
|
@ -10,6 +11,7 @@ require (
|
|||
github.com/osteele/liquid v1.3.2
|
||||
github.com/tdewolff/minify/v2 v2.20.16
|
||||
github.com/yuin/goldmark v1.7.0
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
|
||||
golang.org/x/text v0.3.3
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
|
@ -17,6 +19,7 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/dlclark/regexp2 v1.7.0 // indirect
|
||||
github.com/osteele/tuesday v1.0.3 // indirect
|
||||
github.com/tdewolff/parse/v2 v2.7.11 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
|
|
22
go.sum
22
go.sum
|
@ -1,11 +1,19 @@
|
|||
github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0=
|
||||
github.com/alecthomas/assert/v2 v2.1.0/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA=
|
||||
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
|
||||
github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.5.0 h1:CQCdj1BiBV17sD4Bd32b/Bzuiq/EqoNTrnIhyQAZ+Rk=
|
||||
github.com/alecthomas/chroma/v2 v2.5.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw=
|
||||
github.com/alecthomas/kong v0.8.1 h1:acZdn3m4lLRobeh3Zi2S2EpnXTd1mOL6U7xVml+vfkY=
|
||||
github.com/alecthomas/kong v0.8.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
|
||||
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
|
||||
github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
|
||||
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/elliotchance/orderedmap/v2 v2.2.0 h1:7/2iwO98kYT4XkOjA9mBEIwvi4KpGB4cyHeOFOnj4Vk=
|
||||
github.com/elliotchance/orderedmap/v2 v2.2.0/go.mod h1:85lZyVbpGaGvHvnKa7Qhx7zncAdBIBq6u56Hb1PRU5Q=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
|
@ -20,6 +28,8 @@ github.com/osteele/tuesday v1.0.3 h1:SrCmo6sWwSgnvs1bivmXLvD7Ko9+aJvvkmDjB5G4FTU
|
|||
github.com/osteele/tuesday v1.0.3/go.mod h1:pREKpE+L03UFuR+hiznj3q7j3qB1rUZ4XfKejwWFF2M=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tdewolff/minify/v2 v2.20.16 h1:/C8dtRkxLTIyUlKlBz46gDiktCrE8a6+c1gTrnPFz+U=
|
||||
|
@ -29,8 +39,11 @@ github.com/tdewolff/parse/v2 v2.7.11/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W
|
|||
github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
|
||||
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
||||
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA=
|
||||
github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -44,5 +57,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
|
|||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -9,9 +9,15 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/chroma/v2"
|
||||
"github.com/alecthomas/chroma/v2/formatters/html"
|
||||
"github.com/alecthomas/chroma/v2/lexers"
|
||||
"github.com/alecthomas/chroma/v2/styles"
|
||||
|
||||
"github.com/niklasfasching/go-org/org"
|
||||
"github.com/osteele/liquid"
|
||||
"github.com/yuin/goldmark"
|
||||
gm_highlight "github.com/yuin/goldmark-highlighting/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
|
@ -105,7 +111,7 @@ func (templ Template) Ext() string {
|
|||
// Renders the liquid template with the given context as bindings.
|
||||
// If the template source is org or md, convert them to html after the
|
||||
// liquid rendering.
|
||||
func (templ Template) Render(context map[string]interface{}) ([]byte, error) {
|
||||
func (templ Template) Render(context map[string]interface{}, hlTheme string) ([]byte, error) {
|
||||
// liquid rendering
|
||||
content, err := templ.liquidTemplate.Render(context)
|
||||
if err != nil {
|
||||
|
@ -121,6 +127,7 @@ func (templ Template) Render(context map[string]interface{}) ([]byte, error) {
|
|||
|
||||
// make * -> h1, ** -> h2, etc
|
||||
htmlWriter.TopLevelHLevel = 1
|
||||
htmlWriter.HighlightCodeBlock = highlightCodeBlock(hlTheme)
|
||||
|
||||
contentStr, err := doc.Write(htmlWriter)
|
||||
if err != nil {
|
||||
|
@ -130,7 +137,12 @@ func (templ Template) Render(context map[string]interface{}) ([]byte, error) {
|
|||
} else if ext == ".md" {
|
||||
// markdown rendering
|
||||
var buf bytes.Buffer
|
||||
if err := goldmark.Convert(content, &buf); err != nil {
|
||||
md := goldmark.New(goldmark.WithExtensions(
|
||||
gm_highlight.NewHighlighting(
|
||||
gm_highlight.WithStyle(hlTheme),
|
||||
),
|
||||
))
|
||||
if err := md.Convert(content, &buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
content = buf.Bytes()
|
||||
|
@ -138,3 +150,28 @@ func (templ Template) Render(context map[string]interface{}) ([]byte, error) {
|
|||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func highlightCodeBlock(hlTheme string) func(source string, lang string, inline bool, params map[string]string) string {
|
||||
// from https://github.com/niklasfasching/go-org/blob/a32df1461eb34a451b1e0dab71bd9b2558ea5dc4/blorg/util.go#L58
|
||||
return func(source, lang string, inline bool, params map[string]string) string {
|
||||
var w strings.Builder
|
||||
l := lexers.Get(lang)
|
||||
if l == nil {
|
||||
l = lexers.Fallback
|
||||
}
|
||||
l = chroma.Coalesce(l)
|
||||
it, _ := l.Tokenise(nil, source)
|
||||
options := []html.Option{}
|
||||
if params[":hl_lines"] != "" {
|
||||
ranges := org.ParseRanges(params[":hl_lines"])
|
||||
if ranges != nil {
|
||||
options = append(options, html.HighlightLines(ranges))
|
||||
}
|
||||
}
|
||||
_ = html.New(options...).Format(&w, styles.Get(hlTheme), it)
|
||||
if inline {
|
||||
return `<div class="highlight-inline">` + "\n" + w.String() + "\n" + `</div>`
|
||||
}
|
||||
return `<div class="highlight">` + "\n" + w.String() + "\n" + `</div>`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ tags: ["software", "web"]
|
|||
assertEqual(t, templ.Metadata["tags"].([]interface{})[0], "software")
|
||||
assertEqual(t, templ.Metadata["tags"].([]interface{})[1], "web")
|
||||
|
||||
content, err := templ.Render(nil)
|
||||
content, err := templ.Render(nil, "github")
|
||||
assertEqual(t, err, nil)
|
||||
assertEqual(t, string(content), "<p>Hello World!</p>")
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ tags: ["software", "web"]
|
|||
templ, err := Parse(NewEngine("https://olano.dev", "includes"), file.Name())
|
||||
assertEqual(t, err, nil)
|
||||
ctx := map[string]interface{}{"page": templ.Metadata}
|
||||
content, err := templ.Render(ctx)
|
||||
content, err := templ.Render(ctx, "github")
|
||||
assertEqual(t, err, nil)
|
||||
expected := `<h1>my new post</h1>
|
||||
<h2>a blog post</h2>
|
||||
|
@ -133,7 +133,7 @@ tags: ["software", "web"]
|
|||
templ, err := Parse(NewEngine("https://olano.dev", "includes"), file.Name())
|
||||
assertEqual(t, err, nil)
|
||||
|
||||
content, err := templ.Render(nil)
|
||||
content, err := templ.Render(nil, "github")
|
||||
assertEqual(t, err, nil)
|
||||
expected := `<div id="outline-container-headline-1" class="outline-1">
|
||||
<h1 id="headline-1">
|
||||
|
@ -175,7 +175,7 @@ tags: ["software", "web"]
|
|||
templ, err := Parse(NewEngine("https://olano.dev", "includes"), file.Name())
|
||||
assertEqual(t, err, nil)
|
||||
|
||||
content, err := templ.Render(nil)
|
||||
content, err := templ.Render(nil, "github")
|
||||
assertEqual(t, err, nil)
|
||||
expected := `<h1>My title</h1>
|
||||
<h2>my Subtitle</h2>
|
||||
|
|
|
@ -295,7 +295,7 @@ func (site *Site) render(templ *markup.Template) ([]byte, error) {
|
|||
}
|
||||
|
||||
ctx["page"] = templ.Metadata
|
||||
content, err := templ.Render(ctx)
|
||||
content, err := templ.Render(ctx, site.Config.HighlightTheme)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -306,7 +306,7 @@ func (site *Site) render(templ *markup.Template) ([]byte, error) {
|
|||
if layout_templ, ok := site.layouts[layout.(string)]; ok {
|
||||
ctx["layout"] = layout_templ.Metadata
|
||||
ctx["content"] = content
|
||||
content, err = layout_templ.Render(ctx)
|
||||
content, err = layout_templ.Render(ctx, site.Config.HighlightTheme)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ func getExcerpt(templ *markup.Template) string {
|
|||
ctx := map[string]interface{}{
|
||||
"page": templ.Metadata,
|
||||
}
|
||||
content, err := templ.Render(ctx)
|
||||
content, err := templ.Render(ctx, "tango")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue