mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-09-10 14:15:42 +00:00
68bb85381c
A batch of correctness fixes from a code review of the help center branch.
Public pages:
- hide the article author in JSON-LD when the theme hides the byline, so
the author name no longer leaks in structured data.
- make agent and AI assistant avatars public on upload (and backfill AI
assistants in the v2.7.0 migration) so author avatars don't 401 for
anonymous visitors.
- return the same 401 for missing and existing private uploads to an
anonymous caller, so /uploads can't be used to probe which private
media exists.
- switch the bare /hc/{slug} home redirect from 301 to 302 since the
default locale is mutable and a permanent redirect gets cached.
- match the request host against the public URL by hostname, ignoring
any port, so robots.txt and sitemaps resolve on custom domains.
- fix the lazy-load regex so an img with data-loading or alt text like
"loading=x" still gets loading="lazy" and decoding="async".
- stop logging searches shorter than the minimum length, which never
actually run, so they don't pollute the no-result insights.
Admin and data integrity:
- take the help center row lock in UpdateArticle, MoveArticle,
CreateCollection and UpdateCollection, and run the collection depth
check inside that transaction, so concurrent edits can't create
duplicate slugs or overshoot the max depth.
- default the collection locale before validating the parent, so
creating a child collection without a locale no longer 400s.
- keep a hand-edited help center slug when the name is edited again.
- render the Snippets page title in plural.
- release the feedback dedup key when the insert fails, so a retry
isn't swallowed as a duplicate.
48 lines
1.3 KiB
Go
48 lines
1.3 KiB
Go
package stringutil
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// imgAttrPrefix skips over complete attributes so the name can't match inside another
|
|
// attribute's name (data-loading) or a quoted value (alt="loading=x").
|
|
const imgAttrPrefix = `(?is)^<img(?:\s+[^\s=>]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'>]*))?)*\s+`
|
|
|
|
var (
|
|
imgTagRe = regexp.MustCompile(`(?is)<img\b(?:"[^"]*"|'[^']*'|[^>"'])*>`)
|
|
|
|
imgLoadingAttrRe = regexp.MustCompile(imgAttrPrefix + `loading\s*=`)
|
|
|
|
imgDecodingAttrRe = regexp.MustCompile(imgAttrPrefix + `decoding\s*=`)
|
|
)
|
|
|
|
// DeferOffscreenImages adds loading="lazy" and decoding="async" to every <img> tag
|
|
// except the first, which is left eager since it is the likely LCP element.
|
|
func DeferOffscreenImages(html string) string {
|
|
n := 0
|
|
return imgTagRe.ReplaceAllStringFunc(html, func(tag string) string {
|
|
n++
|
|
if n == 1 {
|
|
return tag
|
|
}
|
|
var attrs strings.Builder
|
|
if !imgLoadingAttrRe.MatchString(tag) {
|
|
attrs.WriteString(` loading="lazy"`)
|
|
}
|
|
if !imgDecodingAttrRe.MatchString(tag) {
|
|
attrs.WriteString(` decoding="async"`)
|
|
}
|
|
if attrs.Len() == 0 {
|
|
return tag
|
|
}
|
|
closing := ">"
|
|
body := strings.TrimSuffix(tag, ">")
|
|
if trimmed, ok := strings.CutSuffix(body, "/"); ok {
|
|
body = trimmed
|
|
closing = " />"
|
|
}
|
|
return strings.TrimRight(body, " \t\r\n") + attrs.String() + closing
|
|
})
|
|
}
|