feat: editor heading levels, outline, link rel, generic-anchor warning and image naming
- the blogeditor and mlblogeditor types serve headingLevels and genericAnchors through RequestOptions, per schema request - J1: H2 to H4 with a pasted or loaded H1 parsed as H2 while the H1 setting is on, H1 to H4 while it is off; H5 and H6 still parse - J2: the outline bar and panel (skipped, empty, link-only, H1 in Source, generic link texts), 300 ms after a change, collapsed, read-only - J3: nofollow/sponsored/ugc checkboxes for absolute http(s) links only, and a non-blocking warning for a generic link text - J4: one form per picked file with the slugged file name, alt required unless decorative (alt=""); Insert uploads the renamed file and the image is inserted on the upload result - assets/dist rebuilt
This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
||||
"git.golem15.com/golem15/summercms/modules/pact"
|
||||
"gocloud.dev/blob"
|
||||
xhtml "golang.org/x/net/html"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// BlogEditorElement is the custom element of the blogeditor and mlblogeditor
|
||||
@@ -88,31 +89,34 @@ var (
|
||||
func BlogEditorTypes(app func() *backpack.App) []pact.FormFieldType {
|
||||
upload := uploadBlogImage(app)
|
||||
decode := decodeBlogHTMLFor(app)
|
||||
options := blogRequestOptions(app)
|
||||
return []pact.FormFieldType{
|
||||
{
|
||||
Name: "blogeditor",
|
||||
Element: BlogEditorElement,
|
||||
Scripts: []string{"assets/dist/blogeditor.js"},
|
||||
Styles: []string{"assets/dist/blogeditor.css"},
|
||||
Options: []string{"uploadFolder"},
|
||||
CheckOptions: checkBlogOptions,
|
||||
Decode: decode,
|
||||
Load: loadBlogHTML,
|
||||
ListValue: blogListValue,
|
||||
Upload: upload,
|
||||
Name: "blogeditor",
|
||||
Element: BlogEditorElement,
|
||||
Scripts: []string{"assets/dist/blogeditor.js"},
|
||||
Styles: []string{"assets/dist/blogeditor.css"},
|
||||
Options: []string{"uploadFolder"},
|
||||
CheckOptions: checkBlogOptions,
|
||||
Decode: decode,
|
||||
Load: loadBlogHTML,
|
||||
ListValue: blogListValue,
|
||||
Upload: upload,
|
||||
RequestOptions: options,
|
||||
},
|
||||
{
|
||||
Name: "mlblogeditor",
|
||||
Element: BlogEditorElement,
|
||||
Translatable: true,
|
||||
Scripts: []string{"assets/dist/blogeditor.js"},
|
||||
Styles: []string{"assets/dist/blogeditor.css"},
|
||||
Options: []string{"htmlColumn", "uploadFolder"},
|
||||
CheckOptions: checkBlogOptions,
|
||||
Decode: decode,
|
||||
Load: loadBlogHTML,
|
||||
ListValue: blogListValue,
|
||||
Upload: upload,
|
||||
Name: "mlblogeditor",
|
||||
Element: BlogEditorElement,
|
||||
Translatable: true,
|
||||
Scripts: []string{"assets/dist/blogeditor.js"},
|
||||
Styles: []string{"assets/dist/blogeditor.css"},
|
||||
Options: []string{"htmlColumn", "uploadFolder"},
|
||||
CheckOptions: checkBlogOptions,
|
||||
Decode: decode,
|
||||
Load: loadBlogHTML,
|
||||
ListValue: blogListValue,
|
||||
Upload: upload,
|
||||
RequestOptions: options,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -194,6 +198,25 @@ func h1ConvertedNotice(record any) string {
|
||||
return EditorH1Converted
|
||||
}
|
||||
|
||||
// blogRequestOptions is the Blog Editor types' RequestOptions (33-01
|
||||
// P33-02, UI-SPEC C28): headingLevels, [2, 3, 4] while the H1 setting is on
|
||||
// and [1, 2, 3, 4] while it is off (J1), and genericAnchors, the settings'
|
||||
// generic link texts (J2, J3). Both are read per schema request, so a
|
||||
// changed setting reaches the next form that opens. db may be nil; the
|
||||
// defaults then apply. fields.yaml options with the same names win.
|
||||
func blogRequestOptions(app func() *backpack.App) func(context.Context, *gorm.DB) (map[string]any, error) {
|
||||
return func(ctx context.Context, db *gorm.DB) (map[string]any, error) {
|
||||
levels := []int{2, 3, 4}
|
||||
if !EffectiveH1ToH2(ctx, db, appConfig(app)) {
|
||||
levels = []int{1, 2, 3, 4}
|
||||
}
|
||||
return map[string]any{
|
||||
"headingLevels": levels,
|
||||
"genericAnchors": GenericAnchors(ctx, db),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// appConfig is the config of the application app answers, nil when there
|
||||
// is none.
|
||||
func appConfig(app func() *backpack.App) *compass.Config {
|
||||
|
||||
Reference in New Issue
Block a user