jonathansudhakar1 opened a new pull request, #40948:
URL: https://github.com/apache/beam/pull/40948

   Fixes #20809.
   
   Blog post headers put a space before each comma in the author list. For 
example, https://beam.apache.org/blog/kafka-to-pubsub-example/ currently 
renders:
   
   > Artur Khanin , Ilya Kozyrev & Alex Kosolapov
   
   In `website/www/site/layouts/blog/single.html` the comma separator is 
emitted at the start of the next loop iteration, on its own template line, and 
the newline left over after the previous author's name renders as a space. This 
PR adds `{{-` trim markers before the separator and on the closing actions 
after each name, so the comma follows the name directly:
   
   > Artur Khanin, Ilya Kozyrev & Alex Kosolapov
   
   The separator logic itself is unchanged. The blog index 
(`layouts/blog/list.html`) and the home page (`layouts/index.html`) already put 
the comma right after the name, so only the post header needed fixing.
   
   ### Testing
   
   I don't have Hugo installed locally, so I tested the template logic 
directly. A small Go program extracts the author-list block from `single.html`, 
renders it with `html/template` (the engine Hugo templates use, with the same 
`{{-` whitespace trimming), strips tags and collapses whitespace the way a 
browser displays it, and compares the result with the expected text. It covers 
1 to 4 authors, an author with a Twitter handle (which adds a link after the 
name), and an author id missing from `authors.yml`.
   
   - Before this change: 4 of 7 cases fail, for example `got "Bob B , Carol C & 
Dave D"`, matching the live site.
   - After this change: all 7 cases pass, for example `"Bob B, Carol C & Dave 
D"`, `"Alice A [@alice], Bob B & Carol C"`, `"Bob B & Carol C"` and `"Bob B"`.
   
   The website precommit build on this PR is the end-to-end check with Hugo 
itself.
   
   <details>
   <summary>Harness used (run with <code>go run main.go 
website/www/site/layouts/blog/single.html</code>)</summary>
   
   ```go
   // Renders the blog post author list from 
website/www/site/layouts/blog/single.html
   // with Go's html/template (the engine Hugo's templates are built on) and 
checks the
   // text a browser would display (tags stripped, whitespace collapsed).
   //
   // Usage: go run main.go <path/to/single.html>
   package main
   
   import (
        "fmt"
        "html"
        "html/template"
        "os"
        "regexp"
        "strings"
   )
   
   func main() {
        src, err := os.ReadFile(os.Args[1])
        if err != nil {
                panic(err)
        }
        // The author list lives in the <span> inside the header's post-info 
div.
        re := regexp.MustCompile(`(?s)<header 
class="post-header">.*?<span>(.*?)</span>`)
        m := re.FindSubmatch(src)
        if m == nil {
                panic("author span not found")
        }
        body := "{{ $authors := .Params.authors }}" + string(m[1])
        tmpl := template.Must(template.New("authors").Funcs(template.FuncMap{
                "sub": func(a, b int) int { return a - b },
        }).Parse(body))
   
        authors := map[string]any{
                "alice": map[string]any{"name": "Alice A", "twitter": "alice"},
                "bob":   map[string]any{"name": "Bob B"},
                "carol": map[string]any{"name": "Carol C"},
                "dave":  map[string]any{"name": "Dave D"},
        }
        cases := []struct {
                ids  []string
                want string
        }{
                {[]string{"bob"}, "Bob B"},
                {[]string{"bob", "carol"}, "Bob B & Carol C"},
                {[]string{"bob", "carol", "dave"}, "Bob B, Carol C & Dave D"},
                {[]string{"bob", "carol", "dave", "alice"}, "Bob B, Carol C, 
Dave D & Alice A [@alice]"},
                {[]string{"alice", "bob", "carol"}, "Alice A [@alice], Bob B & 
Carol C"},
                {[]string{"alice", "bob"}, "Alice A [@alice] & Bob B"},
                {[]string{"unknown", "bob", "carol"}, "unknown, Bob B & Carol 
C"},
        }
        tags := regexp.MustCompile(`<[^>]*>`)
        failed := 0
        for _, c := range cases {
                var sb strings.Builder
                data := map[string]any{
                        "Params": map[string]any{"authors": c.ids},
                        "Site":   map[string]any{"Data": 
map[string]any{"authors": authors}},
                }
                if err := tmpl.Execute(&sb, data); err != nil {
                        panic(err)
                }
                got := 
strings.Join(strings.Fields(html.UnescapeString(tags.ReplaceAllString(sb.String(),
 ""))), " ")
                status := "PASS"
                if got != c.want {
                        status = "FAIL"
                        failed++
                }
                fmt.Printf("%s %v\n     got:  %q\n     want: %q\n", status, 
c.ids, got, c.want)
        }
        if failed > 0 {
                fmt.Printf("%d of %d cases failed\n", failed, len(cases))
                os.Exit(1)
        }
        fmt.Printf("all %d cases passed\n", len(cases))
   }
   ```
   
   </details>
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to