diff --git a/news.go b/articles.go similarity index 66% rename from news.go rename to articles.go index 29cb8aa..ad6cace 100644 --- a/news.go +++ b/articles.go @@ -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 } diff --git a/main.go b/main.go index cb3ac22..02ac8d4 100644 --- a/main.go +++ b/main.go @@ -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 diff --git a/news/2021-12-22-notizia-1.md b/news/2021-12-22-notizia-1.md index b0f46b3..a6c63b0 100644 --- a/news/2021-12-22-notizia-1.md +++ b/news/2021-12-22-notizia-1.md @@ -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 } - ``` \ No newline at end of file + ``` + - bar with some `code` + ```go + type Article struct { + Id string + Title string + Description string + Tags []string + PublishDate time.Time + + MarkdownSource string + renderedHTML string + } + ``` + +#### 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$ | + + diff --git a/news/2021-12-23-notizia-2.md b/news/2021-12-23-notizia-2.md index 80250f5..5b970f9 100644 --- a/news/2021-12-23-notizia-2.md +++ b/news/2021-12-23-notizia-2.md @@ -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 diff --git a/news/2021-12-24-notizia-3.md b/news/2021-12-24-notizia-3.md index 495ffd5..ee576fb 100644 --- a/news/2021-12-24-notizia-3.md +++ b/news/2021-12-24-notizia-3.md @@ -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 diff --git a/public/style.css b/public/style.css index 4c6a79d..897a75f 100644 --- a/public/style.css +++ b/public/style.css @@ -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); +} diff --git a/public/theme-dark.css b/public/theme-dark.css index 637a357..65ebd01 100644 --- a/public/theme-dark.css +++ b/public/theme-dark.css @@ -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); } \ No newline at end of file diff --git a/views/news-base.html b/views/news-base.html index d19bdf1..dd7e1e9 100644 --- a/views/news-base.html +++ b/views/news-base.html @@ -4,6 +4,15 @@ {{define "body"}}
+

{{ .Article.Title }}

+
+ {{ .Article.PublishDate.Format "2006/01/02" }} +
+
+ {{ range .Article.Tags }} + {{ . }} + {{ end }} +
{{ .ContentHTML }}
{{end}} \ No newline at end of file diff --git a/views/news.html b/views/news.html index 7ba4333..e3e790c 100644 --- a/views/news.html +++ b/views/news.html @@ -10,7 +10,7 @@
{{ range .Articles }} - {{ if .Important }} + {{ if .HasTag "important" }} {{ end }} {{ end }} @@ -32,7 +37,7 @@