diff --git a/internal/action/edit.go b/internal/action/edit.go index 7e4ce90..d34e7c0 100644 --- a/internal/action/edit.go +++ b/internal/action/edit.go @@ -23,7 +23,7 @@ func View(cfg *config.Config, w http.ResponseWriter, r *http.Request, params *Pa tmpl := util.NewTemplate("view.html") title, _, plain, rendered := format.Apply(cfg, params.DbName, content) - summary := format.Summarize(plain, 144) + summary := format.TrimForSummary(plain, 144) subAction := r.URL.Query().Get("b") diffText := "" diff --git a/internal/format/creole.go b/internal/format/creole.go index a7e4069..8f16ae2 100644 --- a/internal/format/creole.go +++ b/internal/format/creole.go @@ -1,6 +1,6 @@ package format // TODO -func creole(cfg formatConfig, title string, text string) (string, string, string, string) { - return nomark(cfg, title, text) // fallback +func creole(fc formatConfig, title string, text string) (string, string, string, string) { + return nomark(fc, title, text) // fallback } diff --git a/internal/format/format.go b/internal/format/format.go index de2f2db..83c060d 100644 --- a/internal/format/format.go +++ b/internal/format/format.go @@ -6,40 +6,49 @@ import ( "github.com/akikareha/himewiki/internal/config" ) -// Returns title, wiki text, plain text, HTML +// Apply applies wiki formatting on input text +// and returns title, wiki text, plain text, HTML. func Apply(cfg *config.Config, title string, text string) (string, string, string, string) { if len(text) < 1 { - return title, text, text, "" + return title, "", "", "" } head := text[0] - fcfg := toFormatConfig(cfg) + fc := toFormatConfig(cfg) // Detect markup by very first character of input text. // * '=' : Creole // * '#' : Markdown // * Others : Nomark if head == '=' { - return creole(fcfg, title, text) + return creole(fc, title, text) } else if head == '#' { - return markdown(fcfg, title, text) + return markdown(fc, title, text) } else { - return nomark(fcfg, title, text) + return nomark(fc, title, text) } } -func Summarize(s string, n int) string { - if n < 2 { +// TrimForSummary trims text to specified length with ellipsis. +// Spaces are compressed. +func TrimForSummary(text string, length int) string { + if length < 0 { + panic("program error") + } + if length < 1 { + return "" + } + if length < 2 { return "." } - var b strings.Builder - long := false + var buf strings.Builder + overflowed := false space := false i := 0 - for _, r := range s { - if i >= n-2 { - long = true + for _, r := range text { + if i >= length-2 { + overflowed = true break } if r == '\r' || r == '\n' || r == '\t' { @@ -52,13 +61,13 @@ func Summarize(s string, n int) string { } else { space = false } - b.WriteRune(r) + buf.WriteRune(r) i++ } - if long { - return b.String() + ".." + if overflowed { + return buf.String() + ".." } else { - return b.String() + return buf.String() } } diff --git a/internal/format/markdown.go b/internal/format/markdown.go index f558b6a..b84f790 100644 --- a/internal/format/markdown.go +++ b/internal/format/markdown.go @@ -1,6 +1,6 @@ package format // TODO -func markdown(cfg formatConfig, title string, text string) (string, string, string, string) { - return nomark(cfg, title, text) // fallback +func markdown(fc formatConfig, title string, text string) (string, string, string, string) { + return nomark(fc, title, text) // fallback } diff --git a/internal/format/nomark.go b/internal/format/nomark.go index 41fbb17..c487e1f 100644 --- a/internal/format/nomark.go +++ b/internal/format/nomark.go @@ -203,7 +203,7 @@ func ensureBlock(s *state, block blockMode) { openBlock(s, block) } -func math(cfg formatConfig, s *state) bool { +func math(fc formatConfig, s *state) bool { line := s.input[s.index:s.lineEnd] if !strings.HasPrefix(line, "%%") { return false @@ -231,7 +231,7 @@ func math(cfg formatConfig, s *state) bool { return true } -func strong(cfg formatConfig, s *state) bool { +func strong(fc formatConfig, s *state) bool { line := s.input[s.index:s.lineEnd] if !strings.HasPrefix(line, "**") { return false @@ -266,7 +266,7 @@ func strong(cfg formatConfig, s *state) bool { } s.index += 2 - markup(cfg, s) + markup(fc, s) if s.innerDeco == decoStrong { s.html.WriteString("") @@ -287,7 +287,7 @@ func strong(cfg formatConfig, s *state) bool { return true } -func em(cfg formatConfig, s *state) bool { +func em(fc formatConfig, s *state) bool { line := s.input[s.index:s.lineEnd] if !strings.HasPrefix(line, "//") { return false @@ -322,7 +322,7 @@ func em(cfg formatConfig, s *state) bool { } s.index += 2 - markup(cfg, s) + markup(fc, s) if s.innerDeco == decoEm { s.html.WriteString("") @@ -477,7 +477,7 @@ func nonURLIndex(line string) int { return len(line) } -func link(cfg formatConfig, s *state) bool { +func link(fc formatConfig, s *state) bool { line := s.input[s.index:s.lineEnd] if !strings.HasPrefix(line, "https:") { return false @@ -496,7 +496,7 @@ func link(cfg formatConfig, s *state) bool { ext = ext[1:] } extFound := false - for _, extension := range cfg.image.extensions { + for _, extension := range fc.image.extensions { if ext == extension { extFound = true break @@ -504,7 +504,7 @@ func link(cfg formatConfig, s *state) bool { } domainFound := false if extFound { - for _, domain := range cfg.image.domains { + for _, domain := range fc.image.domains { if u.Host == domain { domainFound = true break @@ -616,19 +616,19 @@ func parseHeading(s *state, line string) (int, string, bool) { return level, title, true } -func markup(cfg formatConfig, s *state) { +func markup(fc formatConfig, s *state) { for s.index < s.lineEnd { - if math(cfg, s) { + if math(fc, s) { continue - } else if strong(cfg, s) { + } else if strong(fc, s) { continue - } else if em(cfg, s) { + } else if em(fc, s) { continue } else if camel(s) { continue } else if wikiLink(s) { continue - } else if link(cfg, s) { + } else if link(fc, s) { continue } else if html(s) { continue @@ -640,7 +640,7 @@ func markup(cfg formatConfig, s *state) { } } -func nomarkLine(cfg formatConfig, s *state) { +func nomarkLine(fc formatConfig, s *state) { line := s.input[s.index:s.lineEnd] if s.block == blockCode { @@ -696,6 +696,13 @@ func nomarkLine(cfg formatConfig, s *state) { return } + if line == "" { + ensureBlock(s, blockNone) + s.text.WriteString("\n") + nextLine(s) + return + } + prevBlock := s.block ensureBlock(s, blockParagraph) for s.index < s.lineEnd { @@ -707,7 +714,7 @@ func nomarkLine(cfg formatConfig, s *state) { s.html.WriteString(" ") s.index += 1 } - markup(cfg, s) + markup(fc, s) nextLine(s) if s.index < len(s.input) { @@ -723,7 +730,7 @@ func nomarkLine(cfg formatConfig, s *state) { skipLastBlanks(s) } -func nomark(cfg formatConfig, title string, text string) (string, string, string, string) { +func nomark(fc formatConfig, title string, text string) (string, string, string, string) { s := state{ input: text, index: 0, @@ -768,7 +775,7 @@ func nomark(cfg formatConfig, title string, text string) (string, string, string } else if s.block == blockCode && s.prevLine == "" && line == "}}}" { closeBlock(&s, blockParagraph) ensureBlock(&s, blockParagraph) - nomarkLine(cfg, &s) + nomarkLine(fc, &s) } else if s.block != blockMath && s.block != blockRaw && s.block != blockCode && line == "%%%" { ensureBlock(&s, blockMath) nextLine(&s) @@ -776,8 +783,13 @@ func nomark(cfg formatConfig, title string, text string) (string, string, string closeBlock(&s, blockParagraph) nextLine(&s) } else if level, title, ok := parseHeading(&s, line); ok { - s.text.WriteString("\n" + line + "\n") - s.plain.WriteString("\n" + title + "\n") + s.text.WriteString("\n") + s.text.WriteString(line) + s.text.WriteString("\n") + + s.plain.WriteString("\n") + s.plain.WriteString(title) + s.plain.WriteString("\n") if level == 1 && s.title == "" { s.title = title nextLine(&s) @@ -791,11 +803,21 @@ func nomark(cfg formatConfig, title string, text string) (string, string, string buf.WriteRune('!') } mark := buf.String() - s.html.WriteString("" + "" + mark + " " + titleHTML + " " + mark + "" + "\n") + s.html.WriteString("") + s.html.WriteString(mark) + s.html.WriteString(" ") + s.html.WriteString(titleHTML) + s.html.WriteString(" ") + s.html.WriteString(mark) + s.html.WriteString("\n") nextLine(&s) } } else { - nomarkLine(cfg, &s) + nomarkLine(fc, &s) } } closeBlock(&s, blockNone)