Add support for using the filename as the page title

This commit is contained in:
Dennis Verheijden 2025-08-29 14:37:59 +02:00 committed by Manuel Rüger
parent ae5347053a
commit 0f13d249f5
5 changed files with 38 additions and 18 deletions

View File

@ -811,6 +811,7 @@ GLOBAL OPTIONS:
--strip-linebreaks, -L remove linebreaks inside of tags, to accommodate non-standard Confluence behavior (default: false) [$MARK_STRIP_LINEBREAKS] --strip-linebreaks, -L remove linebreaks inside of tags, to accommodate non-standard Confluence behavior (default: false) [$MARK_STRIP_LINEBREAKS]
--title-from-h1 extract page title from a leading H1 heading. If no H1 heading on a page exists, then title must be set in the page metadata. (default: false) [$MARK_TITLE_FROM_H1] --title-from-h1 extract page title from a leading H1 heading. If no H1 heading on a page exists, then title must be set in the page metadata. (default: false) [$MARK_TITLE_FROM_H1]
--title-append-generated-hash appends a short hash generated from the path of the page (space, parents, and title) to the title (default: false) [$MARK_TITLE_APPEND_GENERATED_HASH] --title-append-generated-hash appends a short hash generated from the path of the page (space, parents, and title) to the title (default: false) [$MARK_TITLE_APPEND_GENERATED_HASH]
--title-from-filename use the filename (without extension) as the Confluence page title if no explicit 'Title' header or H1 heading is found. (default: false) [$MARK_TITLE_FROM_FILENAME]
--minor-edit don't send notifications while updating Confluence page. (default: false) [$MARK_MINOR_EDIT] --minor-edit don't send notifications while updating Confluence page. (default: false) [$MARK_MINOR_EDIT]
--version-message string add a message to the page version, to explain the edit (default: "") [$MARK_VERSION_MESSAGE] --version-message string add a message to the page version, to explain the edit (default: "") [$MARK_VERSION_MESSAGE]
--color string display logs in color. Possible values: auto, never. (default: "auto") [$MARK_COLOR] --color string display logs in color. Possible values: auto, never. (default: "auto") [$MARK_COLOR]

View File

@ -5,6 +5,7 @@ import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"fmt" "fmt"
"path/filepath"
"regexp" "regexp"
"strings" "strings"
@ -48,7 +49,7 @@ var (
reHeaderPatternMacro = regexp.MustCompile(`<!-- Macro: .*`) reHeaderPatternMacro = regexp.MustCompile(`<!-- Macro: .*`)
) )
func ExtractMeta(data []byte, spaceFromCli string, titleFromH1 bool, parents []string, titleAppendGeneratedHash bool) (*Meta, []byte, error) { func ExtractMeta(data []byte, spaceFromCli string, titleFromH1 bool, titleFromFilename bool, filename string, parents []string, titleAppendGeneratedHash bool) (*Meta, []byte, error) {
var ( var (
meta *Meta meta *Meta
offset int offset int
@ -141,7 +142,7 @@ func ExtractMeta(data []byte, spaceFromCli string, titleFromH1 bool, parents []s
} }
} }
if titleFromH1 || spaceFromCli != "" { if titleFromH1 || spaceFromCli != "" || titleFromFilename {
if meta == nil { if meta == nil {
meta = &Meta{} meta = &Meta{}
} }
@ -157,6 +158,10 @@ func ExtractMeta(data []byte, spaceFromCli string, titleFromH1 bool, parents []s
if titleFromH1 && meta.Title == "" { if titleFromH1 && meta.Title == "" {
meta.Title = ExtractDocumentLeadingH1(data) meta.Title = ExtractDocumentLeadingH1(data)
} }
if titleFromFilename && meta.Title == "" && filename != "" {
base := filepath.Base(filename)
meta.Title = strings.TrimSuffix(base, filepath.Ext(base))
}
if spaceFromCli != "" && meta.Space == "" { if spaceFromCli != "" && meta.Space == "" {
meta.Space = spaceFromCli meta.Space = spaceFromCli
} }

View File

@ -33,6 +33,7 @@ func ResolveRelativeLinks(
base string, base string,
spaceFromCli string, spaceFromCli string,
titleFromH1 bool, titleFromH1 bool,
titleFromFilename bool,
parents []string, parents []string,
titleAppendGeneratedHash bool, titleAppendGeneratedHash bool,
) ([]LinkSubstitution, error) { ) ([]LinkSubstitution, error) {
@ -47,7 +48,7 @@ func ResolveRelativeLinks(
match.filename, match.filename,
match.hash, match.hash,
) )
resolved, err := resolveLink(api, base, match, spaceFromCli, titleFromH1, parents, titleAppendGeneratedHash) resolved, err := resolveLink(api, base, match, spaceFromCli, titleFromH1, titleFromFilename, parents, titleAppendGeneratedHash)
if err != nil { if err != nil {
return nil, karma.Format(err, "resolve link: %q", match.full) return nil, karma.Format(err, "resolve link: %q", match.full)
} }
@ -71,6 +72,7 @@ func resolveLink(
link markdownLink, link markdownLink,
spaceFromCli string, spaceFromCli string,
titleFromH1 bool, titleFromH1 bool,
titleFromFilename bool,
parents []string, parents []string,
titleAppendGeneratedHash bool, titleAppendGeneratedHash bool,
) (string, error) { ) (string, error) {
@ -107,7 +109,7 @@ func resolveLink(
// This helps to determine if found link points to file that's // This helps to determine if found link points to file that's
// not markdown or have mark required metadata // not markdown or have mark required metadata
linkMeta, _, err := metadata.ExtractMeta(linkContents, spaceFromCli, titleFromH1, parents, titleAppendGeneratedHash) linkMeta, _, err := metadata.ExtractMeta(linkContents, spaceFromCli, titleFromH1, titleFromFilename, filepath, parents, titleAppendGeneratedHash)
if err != nil { if err != nil {
log.Errorf( log.Errorf(
err, err,

View File

@ -116,7 +116,7 @@ func processFile(
parents := strings.Split(cmd.String("parents"), cmd.String("parents-delimiter")) parents := strings.Split(cmd.String("parents"), cmd.String("parents-delimiter"))
meta, markdown, err := metadata.ExtractMeta(markdown, cmd.String("space"), cmd.Bool("title-from-h1"), parents, cmd.Bool("title-append-generated-hash")) meta, markdown, err := metadata.ExtractMeta(markdown, cmd.String("space"), cmd.Bool("title-from-h1"), cmd.Bool("title-from-filename"), file, parents, cmd.Bool("title-append-generated-hash"))
if err != nil { if err != nil {
fatalErrorHandler.Handle(err, "unable to extract metadata from file %q", file) fatalErrorHandler.Handle(err, "unable to extract metadata from file %q", file)
return nil return nil
@ -132,7 +132,10 @@ func processFile(
} }
if pageID == "" && meta == nil { if pageID == "" && meta == nil {
fatalErrorHandler.Handle(nil, "specified file doesn't contain metadata and URL is not specified via command line or doesn't contain pageId GET-parameter") fatalErrorHandler.Handle(
nil,
"specified file doesn't contain metadata and URL is not specified via command line or doesn't contain pageId GET-parameter",
)
return nil return nil
} }
@ -143,7 +146,10 @@ func processFile(
} }
if meta.Title == "" { if meta.Title == "" {
fatalErrorHandler.Handle(nil, "page title is not set ('Title' header is not set and '--title-from-h1' option and 'h1-title' config is not set or there is no H1 in the file)") fatalErrorHandler.Handle(
nil,
"page title is not set: use the 'Title' header, or the --title-from-h1 / --title-from-filename flags",
)
return nil return nil
} }
} }
@ -196,7 +202,7 @@ func processFile(
} }
} }
links, err := page.ResolveRelativeLinks(api, meta, markdown, filepath.Dir(file), cmd.String("space"), cmd.Bool("title-from-h1"), parents, cmd.Bool("title-append-generated-hash")) links, err := page.ResolveRelativeLinks(api, meta, markdown, filepath.Dir(file), cmd.String("space"), cmd.Bool("title-from-h1"), cmd.Bool("title-from-filename"), parents, cmd.Bool("title-append-generated-hash"))
if err != nil { if err != nil {
fatalErrorHandler.Handle(err, "unable to resolve relative links") fatalErrorHandler.Handle(err, "unable to resolve relative links")
return nil return nil

View File

@ -61,6 +61,12 @@ var Flags = []cli.Flag{
Usage: "extract page title from a leading H1 heading. If no H1 heading on a page exists, then title must be set in the page metadata.", Usage: "extract page title from a leading H1 heading. If no H1 heading on a page exists, then title must be set in the page metadata.",
Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_TITLE_FROM_H1"), altsrctoml.TOML("title-from-h1", altsrc.NewStringPtrSourcer(&filename))), Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_TITLE_FROM_H1"), altsrctoml.TOML("title-from-h1", altsrc.NewStringPtrSourcer(&filename))),
}, },
&cli.BoolFlag{
Name: "title-from-filename",
Value: false,
Usage: "use the filename (without extension) as the Confluence page title if no explicit 'Title' header or H1 heading is found.",
Sources: cli.NewValueSourceChain(cli.EnvVar("MARK_TITLE_FROM_FILENAME"), altsrctoml.TOML("title-from-filename", altsrc.NewStringPtrSourcer(&filename))),
},
&cli.BoolFlag{ &cli.BoolFlag{
Name: "title-append-generated-hash", Name: "title-append-generated-hash",
Value: false, Value: false,