diff --git a/activityStreams.go b/activityStreams.go index ce22105..e84a0e3 100644 --- a/activityStreams.go +++ b/activityStreams.go @@ -113,7 +113,7 @@ func (a *goBlog) toASNote(p *post) *asNote { as.Type = "Note" } // Content - as.Content = string(a.absolutePostHTML(p)) + as.Content = string(a.postHtml(p, true)) // Attachments if images := p.Parameters[a.cfg.Micropub.PhotoParam]; len(images) > 0 { for _, image := range images { diff --git a/check.go b/check.go index 8a41248..f0096c4 100644 --- a/check.go +++ b/check.go @@ -127,7 +127,7 @@ func (a *goBlog) checkLinks(w io.Writer, posts ...*post) error { func (a *goBlog) allLinks(posts ...*post) (allLinks []*stringPair, err error) { for _, p := range posts { - links, err := allLinksFromHTMLString(string(a.absolutePostHTML(p)), a.fullPostURL(p)) + links, err := allLinksFromHTMLString(string(a.postHtml(p, true)), a.fullPostURL(p)) if err != nil { return nil, err } diff --git a/feeds.go b/feeds.go index aaf5da8..9087d54 100644 --- a/feeds.go +++ b/feeds.go @@ -17,10 +17,6 @@ const ( rssFeed feedType = "rss" atomFeed feedType = "atom" jsonFeed feedType = "json" - - feedAudioURL = "audio" - feedAudioType = "audiomime" - feedAudioLength = "audiolength" ) func (a *goBlog) generateFeed(blog string, f feedType, w http.ResponseWriter, r *http.Request, posts []*post, title string, description string) { @@ -47,23 +43,14 @@ func (a *goBlog) generateFeed(blog string, f feedType, w http.ResponseWriter, r for _, p := range posts { created, _ := dateparse.ParseLocal(p.Published) updated, _ := dateparse.ParseLocal(p.Updated) - var enc *feeds.Enclosure - if p.firstParameter(feedAudioURL) != "" { - enc = &feeds.Enclosure{ - Url: p.firstParameter(feedAudioURL), - Type: p.firstParameter(feedAudioType), - Length: p.firstParameter(feedAudioLength), - } - } feed.Add(&feeds.Item{ Title: p.Title(), Link: &feeds.Link{Href: a.fullPostURL(p)}, Description: a.postSummary(p), Id: p.Path, - Content: string(a.absolutePostHTML(p)), + Content: string(a.postHtml(p, true)), Created: created, Updated: updated, - Enclosure: enc, }) } var err error diff --git a/original-assets/styles/styles.scss b/original-assets/styles/styles.scss index 05f9029..ca283b3 100644 --- a/original-assets/styles/styles.scss +++ b/original-assets/styles/styles.scss @@ -78,8 +78,8 @@ h1 a, h2 a { text-decoration: none; } -img { - width: 100%; +img, audio { + @extend .fw; } button, input, textarea, select { diff --git a/posts.go b/posts.go index da40ebd..b632af9 100644 --- a/posts.go +++ b/posts.go @@ -4,11 +4,11 @@ import ( "context" "errors" "fmt" - "html/template" "net/http" "reflect" "strconv" "strings" + "sync" "github.com/go-chi/chi/v5" "github.com/microcosm-cc/bluemonday" @@ -29,9 +29,9 @@ type post struct { Status postStatus Priority int // Not persisted - Slug string - rendered template.HTML - absoluteRendered template.HTML + Slug string + renderCache sync.Map + renderMutex sync.Mutex } type postStatus string diff --git a/postsDb.go b/postsDb.go index 1a155a4..f822170 100644 --- a/postsDb.go +++ b/postsDb.go @@ -311,7 +311,7 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg return query, args } -func (d *database) getPostParameters(path string, parameters ...string) (params map[string][]string, err error) { +func (d *database) loadPostParameters(posts []*post, parameters ...string) (err error) { var sqlArgs []interface{} // Parameter filter paramFilter := "" @@ -327,21 +327,44 @@ func (d *database) getPostParameters(path string, parameters ...string) (params } paramFilter += ")" } + // Path filter + pathFilter := "" + if len(posts) > 0 { + pathFilter = " and path in (" + for i, p := range posts { + if i > 0 { + pathFilter += ", " + } + named := fmt.Sprintf("path%v", i) + pathFilter += "@" + named + sqlArgs = append(sqlArgs, sql.Named(named, p.Path)) + } + pathFilter += ")" + } // Query - rows, err := d.query("select parameter, value from post_parameters where path = @path"+paramFilter+" order by id", append(sqlArgs, sql.Named("path", path))...) + rows, err := d.query("select path, parameter, value from post_parameters where 1 = 1"+paramFilter+pathFilter+" order by id", sqlArgs...) if err != nil { - return nil, err + return err } // Result - var name, value string - params = map[string][]string{} + var path, name, value string + params := map[string]map[string][]string{} for rows.Next() { - if err = rows.Scan(&name, &value); err != nil { - return nil, err + if err = rows.Scan(&path, &name, &value); err != nil { + return err } - params[name] = append(params[name], value) + m, ok := params[path] + if !ok { + m = map[string][]string{} + } + m[name] = append(m[name], value) + params[path] = m } - return params, nil + // Add to posts + for _, p := range posts { + p.Parameters = params[p.Path] + } + return nil } func (d *database) getPosts(config *postsRequestConfig) (posts []*post, err error) { @@ -369,13 +392,14 @@ func (d *database) getPosts(config *postsRequestConfig) (posts []*post, err erro Status: postStatus(status), Priority: priority, } - if !config.withoutParameters { - if p.Parameters, err = d.getPostParameters(path, config.withOnlyParameters...); err != nil { - return nil, err - } - } posts = append(posts, p) } + if !config.withoutParameters { + err = d.loadPostParameters(posts, config.withOnlyParameters...) + if err != nil { + return nil, err + } + } return posts, nil } diff --git a/postsFuncs.go b/postsFuncs.go index c8bbeaa..eb7cd8d 100644 --- a/postsFuncs.go +++ b/postsFuncs.go @@ -47,30 +47,40 @@ func firstPostParameter(p *post, parameter string) string { return p.firstParameter(parameter) } -func (a *goBlog) postHtml(p *post) template.HTML { - if p.rendered != "" { - return p.rendered +func (a *goBlog) postHtml(p *post, absolute bool) template.HTML { + p.renderMutex.Lock() + defer p.renderMutex.Unlock() + // Check cache + if r, ok := p.renderCache.Load(absolute); ok && r != nil { + return r.(template.HTML) } - htmlContent, err := a.renderMarkdown(p.Content, false) + // Render markdown + htmlContent, err := a.renderMarkdown(p.Content, absolute) if err != nil { log.Fatal(err) return "" } - p.rendered = template.HTML(htmlContent) - return p.rendered -} - -func (a *goBlog) absolutePostHTML(p *post) template.HTML { - if p.absoluteRendered != "" { - return p.absoluteRendered + htmlContentStr := string(htmlContent) + // Add audio to the top + if audio, ok := p.Parameters["audio"]; ok && len(audio) > 0 { + audios := "" + for _, a := range audio { + audios += fmt.Sprintf(``, a) + } + htmlContentStr = audios + htmlContentStr } - htmlContent, err := a.renderMarkdown(p.Content, true) - if err != nil { - log.Fatal(err) - return "" + // Add links to the bottom + if link, ok := p.Parameters["link"]; ok && len(link) > 0 { + links := "" + for _, l := range link { + links += fmt.Sprintf(`

%s

`, l, l) + } + htmlContentStr += links } - p.absoluteRendered = template.HTML(htmlContent) - return p.absoluteRendered + // Cache + html := template.HTML(htmlContentStr) + p.renderCache.Store(absolute, html) + return html } const summaryDivider = "" @@ -80,7 +90,7 @@ func (a *goBlog) postSummary(p *post) (summary string) { if summary != "" { return } - html := string(a.postHtml(p)) + html := string(a.postHtml(p, false)) if splitted := strings.Split(html, summaryDivider); len(splitted) > 1 { doc, _ := goquery.NewDocumentFromReader(strings.NewReader(splitted[0])) summary = doc.Text() diff --git a/templates/assets/css/styles.css b/templates/assets/css/styles.css index ba6ec9c..636c378 100644 --- a/templates/assets/css/styles.css +++ b/templates/assets/css/styles.css @@ -54,10 +54,6 @@ h1 a, h2 a { text-decoration: none; } -img { - width: 100%; -} - button, .button, input, textarea, select { border: 1px solid #000; border: 1px solid var(--primary, #000); @@ -163,7 +159,7 @@ footer * { display: inline; } -.fw, .fw-form, .fw-form input:not([type]), .fw-form input[type=submit], .fw-form input[type=button], .fw-form input[type=text], .fw-form input[type=email], .fw-form input[type=url], .fw-form input[type=password], .fw-form input[type=file], .fw-form textarea, .fw-form select { +.fw, img, audio, .fw-form, .fw-form input:not([type]), .fw-form input[type=submit], .fw-form input[type=button], .fw-form input[type=text], .fw-form input[type=email], .fw-form input[type=url], .fw-form input[type=password], .fw-form input[type=file], .fw-form textarea, .fw-form select { width: 100%; } diff --git a/templates/post.gohtml b/templates/post.gohtml index 39a3e94..1db927b 100644 --- a/templates/post.gohtml +++ b/templates/post.gohtml @@ -14,13 +14,7 @@ {{ if .Data.Content }} {{ include "oldcontentwarning" . }}
- {{ with p .Data "audio" }} - - {{ end }} - {{ content .Data }} - {{ with p .Data "link" }} -

{{ . }}

- {{ end }} + {{ content .Data false }}
{{ end }} {{ include "posttax" . }} diff --git a/templates/statichome.gohtml b/templates/statichome.gohtml index 36a8b8d..7398509 100644 --- a/templates/statichome.gohtml +++ b/templates/statichome.gohtml @@ -9,7 +9,7 @@ {{ if .Data.Content }}
- {{ content .Data }} + {{ content .Data false }}
{{ end }} diff --git a/webmentionSending.go b/webmentionSending.go index 8a6a35e..d946d80 100644 --- a/webmentionSending.go +++ b/webmentionSending.go @@ -24,7 +24,7 @@ func (a *goBlog) sendWebmentions(p *post) error { return nil } links := []string{} - contentLinks, err := allLinksFromHTML(strings.NewReader(string(a.postHtml(p))), a.fullPostURL(p)) + contentLinks, err := allLinksFromHTML(strings.NewReader(string(a.postHtml(p, false))), a.fullPostURL(p)) if err != nil { return err }