ArticleRenderer è ora più generico e miglioramenti allo stile del Markdown

main-old
Antonio De Lucreziis 3 years ago
parent 1a27b2d91e
commit 106531603c

@ -25,7 +25,7 @@ import (
var md goldmark.Markdown
// https://github.com/yuin/goldmark-highlighting/blob/9216f9c5aa010c549cc9fc92bb2593ab299f90d4/highlighting_test.go#L27
func customWrapper(w util.BufWriter, c highlighting.CodeBlockContext, entering bool) {
func customCodeBlockWrapper(w util.BufWriter, c highlighting.CodeBlockContext, entering bool) {
lang, ok := c.Language()
if entering {
if ok {
@ -43,7 +43,6 @@ func customWrapper(w util.BufWriter, c highlighting.CodeBlockContext, entering b
}
func init() {
md = goldmark.New(
goldmark.WithExtensions(
extension.GFM,
@ -52,7 +51,7 @@ func init() {
mathjax.NewMathJax(),
highlighting.NewHighlighting(
highlighting.WithStyle("github"),
highlighting.WithWrapperRenderer(customWrapper),
highlighting.WithWrapperRenderer(customCodeBlockWrapper),
highlighting.WithFormatOptions(
chromahtml.PreventSurroundingPre(true),
),
@ -69,11 +68,10 @@ func init() {
}
type ArticleFrontMatter struct {
Title string `yaml:"title"`
Description string `yaml:"description"`
Tags []string `yaml:"tags,flow"`
PublishDate string `yaml:"publish_date"`
Important bool `yaml:"important"`
Title string `yaml:"title"`
Description string `yaml:"description"`
Tags string `yaml:"tags"`
PublishDate string `yaml:"publish_date"`
}
type Article struct {
@ -82,14 +80,44 @@ type Article struct {
Description string
Tags []string
PublishDate time.Time
Important bool
SourceMarkdown string
OutputHTML string
MarkdownSource string
renderedHTML string
}
func (article *Article) HasTag(tag string) bool {
for _, t := range article.Tags {
if t == tag {
return true
}
}
return false
}
func (article *Article) Render() (string, error) {
if article.renderedHTML == "" {
var buf bytes.Buffer
if err := md.Convert([]byte(article.MarkdownSource), &buf); err != nil {
return "", err
}
article.renderedHTML = buf.String()
}
return article.renderedHTML, nil
}
type ArticleRegistry struct {
Articles map[string]*Article
type ArticleRenderer struct {
RootPath string
}
func trimAll(vs []string) []string {
r := []string{}
for _, v := range vs {
r = append(r, strings.TrimSpace(v))
}
return r
}
func removeBlanks(v []string) []string {
@ -104,8 +132,8 @@ func removeBlanks(v []string) []string {
return r
}
func (ar *ArticleRegistry) LoadArticle(name string) (*Article, error) {
fileBytes, err := os.ReadFile(path.Join("./news/", name+".md"))
func (registry *ArticleRenderer) Load(articlePath string) (*Article, error) {
fileBytes, err := os.ReadFile(path.Join(registry.RootPath, articlePath+".md"))
if err != nil {
return nil, err
}
@ -128,28 +156,22 @@ func (ar *ArticleRegistry) LoadArticle(name string) (*Article, error) {
return nil, err
}
var buf bytes.Buffer
if err := md.Convert([]byte(markdownSource), &buf); err != nil {
return nil, err
}
tags := trimAll(strings.Split(frontMatter.Tags, ","))
article := &Article{
Id: name,
Id: articlePath,
Title: frontMatter.Title,
Description: frontMatter.Description,
Tags: frontMatter.Tags,
Tags: tags,
PublishDate: publishDate,
Important: frontMatter.Important,
SourceMarkdown: markdownSource,
OutputHTML: buf.String(),
MarkdownSource: markdownSource,
}
ar.Articles[name] = article
return article, nil
}
func (ar *ArticleRegistry) LoadAll() ([]*Article, error) {
entries, err := os.ReadDir("./news")
func (registry *ArticleRenderer) LoadAll() ([]*Article, error) {
entries, err := os.ReadDir(registry.RootPath)
if err != nil {
return nil, err
}
@ -159,7 +181,7 @@ func (ar *ArticleRegistry) LoadAll() ([]*Article, error) {
for _, entry := range entries {
if !entry.IsDir() {
name := strings.TrimRight(entry.Name(), ".md")
article, err := ar.LoadArticle(name)
article, err := registry.Load(name)
if err != nil {
return nil, err
}
@ -175,17 +197,8 @@ func (ar *ArticleRegistry) LoadAll() ([]*Article, error) {
return articles, nil
}
func NewArticleRegistry() *ArticleRegistry {
return &ArticleRegistry{
map[string]*Article{},
}
}
func (ar *ArticleRegistry) Render(name string) (string, error) {
article, err := ar.LoadArticle(name)
if err != nil {
return "", err
func NewArticleRegistry(rootPath string) *ArticleRenderer {
return &ArticleRenderer{
rootPath,
}
return article.OutputHTML, nil
}

@ -19,6 +19,7 @@ func main() {
// Middleware
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(middleware.RedirectSlashes)
// Static content
r.Handle("/public/*", http.StripPrefix("/public", http.FileServer(http.Dir("./public"))))
@ -26,8 +27,7 @@ func main() {
// Templates & Renderer
renderer := NewTemplateRenderer("base.html")
articleRegistry := NewArticleRegistry()
articleRegistry.LoadAll()
newsArticlesRegistry := NewArticleRegistry("./news")
// Routes
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
@ -55,7 +55,7 @@ func main() {
})
r.Get("/news", func(w http.ResponseWriter, r *http.Request) {
articles, err := articleRegistry.LoadAll()
articles, err := newsArticlesRegistry.LoadAll()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@ -70,16 +70,23 @@ func main() {
})
r.Get("/news/{article}", func(w http.ResponseWriter, r *http.Request) {
article := chi.URLParam(r, "article")
articleName := chi.URLParam(r, "article")
htmlSource, err := articleRegistry.Render(article)
article, err := newsArticlesRegistry.Load(articleName)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
html, err := article.Render()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := renderer.Render(w, "news-base.html", util.H{
"ContentHTML": template.HTML(htmlSource),
"Article": article,
"ContentHTML": template.HTML(html),
}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return

@ -1,14 +1,11 @@
---
important: yes
title: "Notiza 1"
tags: [prova, test, foo, bar]
title: "Notizia 1"
tags: important, prova, test, foo, bar
publish_date: 2021/12/22 22:00
description: |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quis nemo aperiam, voluptas quam alias esse sed natus tempore suscipit fugiat sit delectus exercitationem numquam ipsum assumenda recusandae consequatur...
---
# Notizia 1
## Heading 2
### Heading 3
@ -36,17 +33,58 @@ Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae optio ad,
- Item 5
- foo
- bar with some `code`
```go
```
type Article struct {
Id string
Title string
Description string
Tags []string
PublishDate time.Time
Important bool
SourceMarkdown string
OutputHTML string
MarkdownSource string
renderedHTML string
}
```
```
- bar with some `code`
```go
type Article struct {
Id string
Title string
Description string
Tags []string
PublishDate time.Time
MarkdownSource string
renderedHTML string
}
```
#### Tables
<https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#tables>
Colons can be used to align columns.
| Tables | Are | Cool |
| ------------- |:-------------:| -----:|
| col 3 is | right-aligned | $1600 |
| col 2 is | centered | $12 |
| zebra stripes | are neat | $1 |
There must be at least 3 dashes separating each header cell.
The outer pipes (|) are optional, and you don't need to make the
raw Markdown line up prettily. You can also use inline Markdown.
Markdown | Less | Pretty
--- | --- | ---
*Still* | `renders` | **nicely**
1 | 2 | 3
| Expression | Derivative | Integral |
| :---: | :---: | :---: |
| $x^a$ | $a x^{a-1}$ | $\displaystyle \frac{1}{a+1} x^{a+1} + c$ se $a \neq -1$ |
| $\sin x$ | $\cos x$ | $\displaystyle -\cos x + c$ |
| $e^x$ | $e^x$ | $\displaystyle e^x + c$ |

@ -1,13 +1,11 @@
---
title: "Notiza 2"
tags: [prova, test, foo, bar]
title: "Notizia 2"
tags: prova, test, foo, bar
publish_date: 2021/12/23 22:00
description: |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quis nemo aperiam, voluptas quam alias esse sed natus tempore suscipit fugiat sit delectus exercitationem numquam ipsum assumenda recusandae consequatur...
---
# Notizia 1
## Heading 2
### Heading 3

@ -1,13 +1,11 @@
---
title: "Notiza 3"
tags: [prova, test, foo, bar]
title: "Notizia 3"
tags: prova, test, foo, bar
publish_date: 2021/12/24 18:00
description: |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quis nemo aperiam, voluptas quam alias esse sed natus tempore suscipit fugiat sit delectus exercitationem numquam ipsum assumenda recusandae consequatur...
---
# Notizia 1
## Heading 2
### Heading 3

@ -332,6 +332,29 @@ section {
color: var(--card-content);
}
.tags {
display: flex;
flex-direction: row;
gap: 0 0.5rem;
margin-top: 0.5rem;
}
.tags .tag {
height: 1.5rem;
border-radius: calc(1.5rem / 2);
padding: 0 calc(1.5rem / 2);
background: var(--bg-darker-2);
color: var(--card-date);
font-size: 15px;
display: flex;
align-items: center;
justify-content: center;
}
/* Typography */
h1, h2, h3, h4 {
@ -359,7 +382,7 @@ h4 {
font-weight: var(--font-weight-bold);
}
p, ul, ol, li, pre {
p, ul, ol, li {
margin: 0.5rem 0;
width: 70ch;
max-width: 100%;
@ -370,12 +393,17 @@ ul, ol {
}
pre {
margin: 0.5rem 0;
background: var(--bg-lighter);
border-radius: 2px;
border: 1px solid #cbcbcb;
border-radius: 2px;
box-shadow: 0 2px 4px 0 #00000033;
font-size: 90%;
display: flex;
overflow-x: auto;
}
pre > code {
@ -629,10 +657,6 @@ form .field-set input {
text-align: center;
}
.news-content .math.display {
margin: 1rem 0;
}
.news-content img {
display: block;
margin: 1rem auto;
@ -643,10 +667,47 @@ form .field-set input {
box-shadow: 0 2px 8px 0 #00000033;
}
.news-content .date {
font-size: 15px;
color: var(--card-date);
display: flex;
justify-content: center;
}
.news-content .tags, .news-content .date {
justify-content: center;
}
.news-content table {
margin: 1rem auto;
}
/* Math */
.katex-display {
margin: 0;
margin: 1rem 0;
font-size: 105%;
}
/* Tables */
table {
border-collapse: collapse;
}
table td, table th {
padding: 0.5rem;
}
table td:not(:first-child), table th:not(:first-child) {
border-left: 1px solid var(--bg-darker-3);
}
table td {
border-top: 1px solid var(--bg-darker-3);
}
table tbody tr:hover {
background: var(--bg-darker);
}

@ -70,4 +70,8 @@ body.dark-mode {
/* Trick molto molto malvagio per non dover rendere il colorscheme dei blocchi di codice dinamici rispetto alla dark mode */
.dark-mode pre > code > span {
filter: invert(1);
}
.dark-mode table td, .dark-mode table th {
border-color: var(--fg);
}

@ -4,6 +4,15 @@
{{define "body"}}
<section class="news-content">
<h1>{{ .Article.Title }}</h1>
<div class="date">
{{ .Article.PublishDate.Format "2006/01/02" }}
</div>
<div class="tags">
{{ range .Article.Tags }}
<span class="tag">{{ . }}</span>
{{ end }}
</div>
{{ .ContentHTML }}
</section>
{{end}}

@ -10,7 +10,7 @@
</h2>
<div class="card-list">
{{ range .Articles }}
{{ if .Important }}
{{ if .HasTag "important" }}
<div class="card">
<div class="title">
<a href="/news/{{ .Id }}">
@ -19,6 +19,11 @@
</div>
<div class="date">{{ .PublishDate.Format "2006/01/02" }}</div>
<div class="description">{{ .Description }}</div>
<div class="tags">
{{ range .Tags }}
<span class="tag">{{ . }}</span>
{{ end }}
</div>
</div>
{{ end }}
{{ end }}
@ -32,7 +37,7 @@
</h2>
<div class="card-list">
{{ range .Articles }}
{{ if not .Important }}
{{ if not (.HasTag "important") }}
<div class="card">
<div class="title">
<a href="/news/{{ .Id }}">
@ -41,6 +46,11 @@
</div>
<div class="date">{{ .PublishDate.Format "2006/01/02" }}</div>
<div class="description">{{ .Description }}</div>
<div class="tags">
{{ range .Tags }}
<span class="tag">{{ . }}</span>
{{ end }}
</div>
</div>
{{ end }}
{{ end }}

Loading…
Cancel
Save