feat: H1 to H2 setting with the admin save conversion (tracer)
- content_h1_to_h2 and generic_anchors on the settings row (migration
202610280001), Headings and links tab, config key
golem15.journal.content_h1_to_h2 used when no settings row exists
- classes.ConvertH1 on the x/net/html tokenizer; the Blog Editor types
convert while the setting is on and answer editor.h1_converted
- GET /posts/{slug} reports content_h1_to_h2 (additive key)
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
"git.golem15.com/golem15/summercms/modules/backpack"
|
||||
"git.golem15.com/golem15/summercms/modules/compass"
|
||||
"git.golem15.com/golem15/summercms/modules/pact"
|
||||
"gocloud.dev/blob"
|
||||
xhtml "golang.org/x/net/html"
|
||||
@@ -31,6 +32,9 @@ const (
|
||||
editorRemovedAttributes = "golem15.journal::lang.editor.removed_attributes"
|
||||
editorRemovedComments = "golem15.journal::lang.editor.removed_comments"
|
||||
editorMarkupChanged = "golem15.journal::lang.editor.markup_changed"
|
||||
// EditorH1Converted is the notice of a save that turned H1 headings
|
||||
// into H2 (Count is the number of headings).
|
||||
EditorH1Converted = "golem15.journal::lang.editor.h1_converted"
|
||||
)
|
||||
|
||||
// blogListValueRunes is how many runes of text a list column shows.
|
||||
@@ -79,6 +83,7 @@ var (
|
||||
// when unset).
|
||||
func BlogEditorTypes(app func() *backpack.App) []pact.FormFieldType {
|
||||
upload := uploadBlogImage(app)
|
||||
decode := decodeBlogHTMLFor(app)
|
||||
return []pact.FormFieldType{
|
||||
{
|
||||
Name: "blogeditor",
|
||||
@@ -87,7 +92,7 @@ func BlogEditorTypes(app func() *backpack.App) []pact.FormFieldType {
|
||||
Styles: []string{"assets/dist/blogeditor.css"},
|
||||
Options: []string{"uploadFolder"},
|
||||
CheckOptions: checkBlogOptions,
|
||||
Decode: decodeBlogHTML,
|
||||
Decode: decode,
|
||||
Load: loadBlogHTML,
|
||||
ListValue: blogListValue,
|
||||
Upload: upload,
|
||||
@@ -100,7 +105,7 @@ func BlogEditorTypes(app func() *backpack.App) []pact.FormFieldType {
|
||||
Styles: []string{"assets/dist/blogeditor.css"},
|
||||
Options: []string{"htmlColumn", "uploadFolder"},
|
||||
CheckOptions: checkBlogOptions,
|
||||
Decode: decodeBlogHTML,
|
||||
Decode: decode,
|
||||
Load: loadBlogHTML,
|
||||
ListValue: blogListValue,
|
||||
Upload: upload,
|
||||
@@ -146,6 +151,47 @@ func checkUploadFolder(folder string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// decodeBlogHTMLFor is the Blog Editor types' Decode: decodeBlogHTML, then,
|
||||
// while the H1 setting is on (EffectiveH1ToH2 on the save transaction and
|
||||
// the booted application's config), ConvertH1 on the stored HTML with the
|
||||
// EditorH1Converted notice counting the converted headings. app may be nil
|
||||
// or answer nil; the setting is then read from the database alone.
|
||||
func decodeBlogHTMLFor(app func() *backpack.App) func(context.Context, pact.FormFieldValue) (pact.FormFieldDecoded, error) {
|
||||
return func(ctx context.Context, in pact.FormFieldValue) (pact.FormFieldDecoded, error) {
|
||||
out, err := decodeBlogHTML(ctx, in)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
text, isString := out.Value.(string)
|
||||
if !isString || text == "" {
|
||||
return out, nil
|
||||
}
|
||||
if !EffectiveH1ToH2(ctx, in.DB, appConfig(app)) {
|
||||
return out, nil
|
||||
}
|
||||
converted, n := ConvertH1(text)
|
||||
if n == 0 {
|
||||
return out, nil
|
||||
}
|
||||
out.Value = converted
|
||||
out.Notices = append(out.Notices, pact.FormFieldNotice{Message: EditorH1Converted, Count: n})
|
||||
return out, nil
|
||||
}
|
||||
}
|
||||
|
||||
// appConfig is the config of the application app answers, nil when there
|
||||
// is none.
|
||||
func appConfig(app func() *backpack.App) *compass.Config {
|
||||
if app == nil {
|
||||
return nil
|
||||
}
|
||||
a := app()
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
return a.Config
|
||||
}
|
||||
|
||||
// decodeBlogHTML stores the HTML policy's output for a submitted value: the
|
||||
// exact submitted bytes with no notice when the policy keeps everything,
|
||||
// otherwise the stripped HTML with notices naming what was removed. nil
|
||||
|
||||
Reference in New Issue
Block a user