From e727b2f71f111771fb94686088542a120ce2b339 Mon Sep 17 00:00:00 2001 From: Antonio De Lucreziis Date: Thu, 23 Dec 2021 02:19:35 +0100 Subject: [PATCH] Feature: Pagina notize dinamica e renderizzazione del markdown --- go.mod | 3 + go.sum | 17 ++++ main.go | 29 ++++++- news.go | 161 +++++++++++++++++++++++++++++++++++ news/2021-12-22-notizia-1.md | 43 ++++++++++ news/2021-12-23-notizia-2.md | 38 +++++++++ news/2021-12-24-notizia-3.md | 38 +++++++++ public/style.css | 19 ++++- views/news-base.html | 9 ++ views/news.html | 109 ++++-------------------- 10 files changed, 373 insertions(+), 93 deletions(-) create mode 100644 news.go create mode 100644 news/2021-12-22-notizia-1.md create mode 100644 news/2021-12-23-notizia-2.md create mode 100644 news/2021-12-24-notizia-3.md create mode 100644 views/news-base.html diff --git a/go.mod b/go.mod index 046a90b..4d6f388 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/go.sum b/go.sum index fa9e443..1a0f312 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/main.go b/main.go index f4c402f..91046ee 100644 --- a/main.go +++ b/main.go @@ -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) { diff --git a/news.go b/news.go new file mode 100644 index 0000000..a764eda --- /dev/null +++ b/news.go @@ -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 +} diff --git a/news/2021-12-22-notizia-1.md b/news/2021-12-22-notizia-1.md new file mode 100644 index 0000000..a629598 --- /dev/null +++ b/news/2021-12-22-notizia-1.md @@ -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 + ``` \ No newline at end of file diff --git a/news/2021-12-23-notizia-2.md b/news/2021-12-23-notizia-2.md new file mode 100644 index 0000000..80250f5 --- /dev/null +++ b/news/2021-12-23-notizia-2.md @@ -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 + ``` \ No newline at end of file diff --git a/news/2021-12-24-notizia-3.md b/news/2021-12-24-notizia-3.md new file mode 100644 index 0000000..495ffd5 --- /dev/null +++ b/news/2021-12-24-notizia-3.md @@ -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 + ``` \ No newline at end of file diff --git a/public/style.css b/public/style.css index efaf5d4..75c7430 100644 --- a/public/style.css +++ b/public/style.css @@ -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%; diff --git a/views/news-base.html b/views/news-base.html new file mode 100644 index 0000000..2e3203e --- /dev/null +++ b/views/news-base.html @@ -0,0 +1,9 @@ +{{template "base" .}} + +{{define "title"}}PHC • phc.dm.xxxxx.xx{{end}} + +{{define "body"}} +
+ {{ .ContentHTML }} +
+{{end}} \ No newline at end of file diff --git a/views/news.html b/views/news.html index d569b84..96d1e33 100644 --- a/views/news.html +++ b/views/news.html @@ -4,41 +4,21 @@ {{define "body"}}
-

- - Notizie Importanti -

+

Notizie Importanti

+ {{ range .Articles }} + {{ if .Important }}
-
- yyyy-mm-dd -
-
- 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... - -
-
-
- -
- yyyy-mm-dd -
-
- 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... - -
+
{{ .PublishDate.Format "2006/01/02" }}
+
{{ .Description }}
+ {{ end }} + {{ end }}
@@ -48,72 +28,19 @@ Archivio notizie
+ {{ range .Articles }} + {{ if not .Important }}
-
yyyy-mm-dd
-
- 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... - -
-
-
- -
yyyy-mm-dd
-
- 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... - -
-
-
- -
yyyy-mm-dd
-
- 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... - -
-
-
- -
yyyy-mm-dd
-
- 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... - -
-
-
- -
yyyy-mm-dd
-
- 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... - -
-
-
- -
yyyy-mm-dd
-
- 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... - + + {{ .Title }} +
+
{{ .PublishDate.Format "2006/01/02" }}
+
{{ .Description }}
+ {{ end }} + {{ end }}
{{end}} \ No newline at end of file