Feature: Pagina notize dinamica e renderizzazione del markdown

This commit is contained in:
2021-12-23 02:19:35 +01:00
parent 54f5d798e8
commit e727b2f71f
10 changed files with 373 additions and 93 deletions
+3
View File
@@ -5,4 +5,7 @@ go 1.13
require (
github.com/go-chi/chi/v5 v5.0.7
github.com/joho/godotenv v1.4.0
github.com/litao91/goldmark-mathjax v0.0.0-20210217064022-a43cf739a50f
github.com/yuin/goldmark v1.4.4
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
+17
View File
@@ -1,4 +1,21 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/litao91/goldmark-mathjax v0.0.0-20210217064022-a43cf739a50f h1:plCPYXRXDCO57qjqegCzaVf1t6aSbgCMD+zfz18POfs=
github.com/litao91/goldmark-mathjax v0.0.0-20210217064022-a43cf739a50f/go.mod h1:leg+HM7jUS84JYuY120zmU68R6+UeU6uZ/KAW7cViKE=
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.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.4 h1:zNWRjYUW32G9KirMXYHQHVNFkXvMI7LpgNW2AgYAoIs=
github.com/yuin/goldmark v1.4.4/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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=
+28 -1
View File
@@ -1,6 +1,7 @@
package main
import (
"html/template"
"log"
"net/http"
@@ -25,6 +26,8 @@ func main() {
// Templates & Renderer
renderer := NewTemplateRenderer("base.html")
articleRegistry := NewArticleRegistry()
articleRegistry.LoadAll()
// Routes
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
@@ -52,11 +55,35 @@ func main() {
})
r.Get("/news", func(w http.ResponseWriter, r *http.Request) {
err := renderer.Render(w, "news.html", util.H{})
articles, err := articleRegistry.LoadAll()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := renderer.Render(w, "news.html", util.H{
"Articles": articles,
}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
r.Get("/news/{article}", func(w http.ResponseWriter, r *http.Request) {
article := chi.URLParam(r, "article")
htmlSource, err := articleRegistry.Render(article)
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),
}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
r.Get("/login", func(w http.ResponseWriter, r *http.Request) {
+161
View File
@@ -0,0 +1,161 @@
package main
import (
"bytes"
"os"
"path"
"sort"
"strings"
"time"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer/html"
mathjax "github.com/litao91/goldmark-mathjax"
"gopkg.in/yaml.v3"
)
var md goldmark.Markdown
func init() {
md = goldmark.New(
goldmark.WithExtensions(
extension.GFM,
extension.Typographer,
// Questo pacchetto ha un nome stupido perché in realtà si occupa solo del parsing lato server del Markdown mentre lato client usiamo KaTeX.
mathjax.NewMathJax(),
),
goldmark.WithParserOptions(
parser.WithAutoHeadingID(),
),
goldmark.WithRendererOptions(
html.WithHardWraps(),
html.WithXHTML(),
),
)
}
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"`
}
type Article struct {
Id string
Title string
Description string
Tags []string
PublishDate time.Time
Important bool
SourceMarkdown string
OutputHTML string
}
type ArticleRegistry struct {
Articles map[string]*Article
}
func removeBlanks(v []string) []string {
r := []string{}
for _, s := range v {
if len(strings.TrimSpace(s)) > 0 {
r = append(r, s)
}
}
return r
}
func (ar *ArticleRegistry) LoadArticle(name string) (*Article, error) {
fileBytes, err := os.ReadFile(path.Join("./news/", name+".md"))
if err != nil {
return nil, err
}
source := string(fileBytes)
// TODO: Ehm bugia esiste "https://github.com/yuin/goldmark-meta" però boh per ora funge tutto
parts := removeBlanks(strings.Split(source, "---"))
frontMatterSource := parts[0]
markdownSource := strings.Join(parts[1:], "---")
var frontMatter ArticleFrontMatter
if err := yaml.Unmarshal([]byte(frontMatterSource), &frontMatter); err != nil {
return nil, err
}
publishDate, err := time.Parse("2006/01/02 15:04", frontMatter.PublishDate)
if err != nil {
return nil, err
}
var buf bytes.Buffer
if err := md.Convert([]byte(markdownSource), &buf); err != nil {
return nil, err
}
article := &Article{
Id: name,
Title: frontMatter.Title,
Description: frontMatter.Description,
Tags: frontMatter.Tags,
PublishDate: publishDate,
Important: frontMatter.Important,
SourceMarkdown: markdownSource,
OutputHTML: buf.String(),
}
ar.Articles[name] = article
return article, nil
}
func (ar *ArticleRegistry) LoadAll() ([]*Article, error) {
entries, err := os.ReadDir("./news")
if err != nil {
return nil, err
}
articles := []*Article{}
for _, entry := range entries {
if !entry.IsDir() {
name := strings.TrimRight(entry.Name(), ".md")
article, err := ar.LoadArticle(name)
if err != nil {
return nil, err
}
articles = append(articles, article)
}
}
sort.Slice(articles, func(i, j int) bool {
return articles[i].PublishDate.After(articles[j].PublishDate)
})
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
}
return article.OutputHTML, nil
}
+43
View File
@@ -0,0 +1,43 @@
---
important: yes
title: "Notiza 1"
tags: [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
#### Heading 4
Lorem ipsum dolor, sit amet consectetur "adipisicing" elit. Repudiandae -- optio ad, consequatur **distinctio possimus** laudantium molestias similique placeat, dolore omnis et aperiam rem delectus tempora $1 + 1$ ea, cupiditate explicabo vel! Porro?
$$
\int_0^1 x^2 \mathrm d x
$$
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae optio ad, consequatur distinctio possimus _laudantium molestias similique placeat_, dolore omnis et aperiam rem [delectus tempora ea,](#) cupiditate explicabo vel! Porro?
![testing](https://picsum.photos/200/300)
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae optio ad, consequatur distinctio possimus laudantium molestias similique placeat, dolore omnis et aperiam rem delectus tempora ea, cupiditate explicabo vel! Porro?
- Item 1
- Item 2
- Item 3
- Item 4
- Item 5
- Item 5
- Item 5
- foo
- bar
```Makefile
foo
foo
```
+38
View File
@@ -0,0 +1,38 @@
---
title: "Notiza 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
#### Heading 4
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae optio ad, consequatur **distinctio possimus** laudantium molestias similique placeat, dolore omnis et aperiam rem delectus tempora ea, cupiditate explicabo vel! Porro?
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae optio ad, consequatur distinctio possimus _laudantium molestias similique placeat_, dolore omnis et aperiam rem [delectus tempora ea,](#) cupiditate explicabo vel! Porro?
![testing](https://picsum.photos/200/300)
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae optio ad, consequatur distinctio possimus laudantium molestias similique placeat, dolore omnis et aperiam rem delectus tempora ea, cupiditate explicabo vel! Porro?
- Item 1
- Item 2
- Item 3
- Item 4
- Item 5
- Item 5
- Item 5
- foo
- bar
```Makefile
foo
foo
```
+38
View File
@@ -0,0 +1,38 @@
---
title: "Notiza 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
#### Heading 4
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae optio ad, consequatur **distinctio possimus** laudantium molestias similique placeat, dolore omnis et aperiam rem delectus tempora ea, cupiditate explicabo vel! Porro?
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae optio ad, consequatur distinctio possimus _laudantium molestias similique placeat_, dolore omnis et aperiam rem [delectus tempora ea,](#) cupiditate explicabo vel! Porro?
![testing](https://picsum.photos/200/300)
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae optio ad, consequatur distinctio possimus laudantium molestias similique placeat, dolore omnis et aperiam rem delectus tempora ea, cupiditate explicabo vel! Porro?
- Item 1
- Item 2
- Item 3
- Item 4
- Item 5
- Item 5
- Item 5
- foo
- bar
```Makefile
foo
foo
```
+18 -1
View File
@@ -340,7 +340,24 @@ h1, h2, h3, h4 {
font-weight: var(--font-weight-light);
}
p {
h1 {
font-size: 2rem;
}
h2 {
font-size: 1.5rem;
}
h3 {
font-size: 1.35rem;
}
h4 {
font-size: 1.2rem;
font-weight: var(--font-weight-bold);
}
p, ul, ol, li {
margin: 0.5rem 0;
width: 70ch;
max-width: 100%;
+9
View File
@@ -0,0 +1,9 @@
{{template "base" .}}
{{define "title"}}PHC • phc.dm.xxxxx.xx{{end}}
{{define "body"}}
<section>
{{ .ContentHTML }}
</section>
{{end}}
+18 -91
View File
@@ -4,41 +4,21 @@
{{define "body"}}
<section>
<h2>
<i class="far fa-newspaper"></i>
Notizie Importanti
</h2>
<h2>Notizie Importanti</h2>
<div class="card-list">
{{ range .Articles }}
{{ if .Important }}
<div class="card">
<div class="title">
<a href="/news/notizia-super-wow-1">
News 1
<a href="/news/{{ .Id }}">
{{ .Title }}
</a>
</div>
<div class="date">
yyyy-mm-dd
</div>
<div class="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...
</div>
</div>
<div class="card">
<div class="title">
<a href="/news/notizia-super-wow-2">
News 2
</a>
</div>
<div class="date">
yyyy-mm-dd
</div>
<div class="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...
</div>
<div class="date">{{ .PublishDate.Format "2006/01/02" }}</div>
<div class="description">{{ .Description }}</div>
</div>
{{ end }}
{{ end }}
</div>
</section>
@@ -48,72 +28,19 @@
Archivio notizie
</h2>
<div class="card-list">
{{ range .Articles }}
{{ if not .Important }}
<div class="card">
<div class="title">
<a href="/news/notizia-antica-1">Notizia Antica 1</a>
</div>
<div class="date">yyyy-mm-dd</div>
<div class="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...
</div>
</div>
<div class="card">
<div class="title">
<a href="/news/notizia-antica-2">Notizia Antica 2</a>
</div>
<div class="date">yyyy-mm-dd</div>
<div class="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...
</div>
</div>
<div class="card">
<div class="title">
<a href="/news/notizia-antica-3">Notizia Antica 3</a>
</div>
<div class="date">yyyy-mm-dd</div>
<div class="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...
</div>
</div>
<div class="card">
<div class="title">
<a href="/news/notizia-antica-4">Notizia Antica 4</a>
</div>
<div class="date">yyyy-mm-dd</div>
<div class="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...
</div>
</div>
<div class="card">
<div class="title">
<a href="/news/notizia-antica-5">Notizia Antica 5</a>
</div>
<div class="date">yyyy-mm-dd</div>
<div class="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...
</div>
</div>
<div class="card">
<div class="title">
<a href="/news/notizia-antica-6">Notizia Antica 6</a>
</div>
<div class="date">yyyy-mm-dd</div>
<div class="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...
<a href="/news/{{ .Id }}">
{{ .Title }}
</a>
</div>
<div class="date">{{ .PublishDate.Format "2006/01/02" }}</div>
<div class="description">{{ .Description }}</div>
</div>
{{ end }}
{{ end }}
</div>
</section>
{{end}}