Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package fx for openSUSE:Factory checked in 
at 2026-10-26 10:00:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/fx (Old)
 and      /work/SRC/openSUSE:Factory/.fx.new.2252680 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "fx"

Mon Oct 26 10:00:14 2026 rev:12 rq:1392376 version:40.0.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/fx/fx.changes    2026-10-06 19:18:08.029825512 
+0200
+++ /work/SRC/openSUSE:Factory/.fx.new.2252680/fx.changes       2026-10-26 
10:01:02.848342985 +0100
@@ -1,0 +2,7 @@
+Sun Oct 25 08:36:49 UTC 2026 - Martin Hauke <[email protected]>
+
+- Update to version 40.0.1
+  * Fixed rendering of Unicode characters in go-to-symbol matches
+    (#440).
+
+-------------------------------------------------------------------

Old:
----
  fx-40.0.0.tar.gz

New:
----
  fx-40.0.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ fx.spec ++++++
--- /var/tmp/diff_new_pack.rD4NSx/_old  2026-10-26 10:01:04.028392494 +0100
+++ /var/tmp/diff_new_pack.rD4NSx/_new  2026-10-26 10:01:04.030392578 +0100
@@ -18,7 +18,7 @@
 
 
 Name:           fx
-Version:        40.0.0
+Version:        40.0.1
 Release:        0
 Summary:        Terminal JSON viewer
 License:        MIT

++++++ fx-40.0.0.tar.gz -> fx-40.0.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/.github/workflows/docker.yml 
new/fx-40.0.1/.github/workflows/docker.yml
--- old/fx-40.0.0/.github/workflows/docker.yml  2026-10-05 17:50:42.000000000 
+0200
+++ new/fx-40.0.1/.github/workflows/docker.yml  2026-10-22 15:49:22.000000000 
+0200
@@ -7,19 +7,19 @@
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
-        uses: actions/checkout@v4
+        uses: actions/checkout@v7
 
       - name: Login to Docker Hub
-        uses: docker/login-action@v3
+        uses: docker/login-action@v4
         with:
           username: antonmedv
           password: ${{ secrets.DOCKERHUB_TOKEN }}
 
       - name: Set up Docker Buildx
-        uses: docker/setup-buildx-action@v3
+        uses: docker/setup-buildx-action@v4
 
       - name: Build and push
-        uses: docker/build-push-action@v5
+        uses: docker/build-push-action@v7
         with:
           context: .
           file: ./Dockerfile
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/.github/workflows/snap.yml 
new/fx-40.0.1/.github/workflows/snap.yml
--- old/fx-40.0.0/.github/workflows/snap.yml    2026-10-05 17:50:42.000000000 
+0200
+++ new/fx-40.0.1/.github/workflows/snap.yml    2026-10-22 15:49:22.000000000 
+0200
@@ -6,7 +6,7 @@
   snap:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v7
         with:
           ref: master
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/.github/workflows/test.yml 
new/fx-40.0.1/.github/workflows/test.yml
--- old/fx-40.0.0/.github/workflows/test.yml    2026-10-05 17:50:42.000000000 
+0200
+++ new/fx-40.0.1/.github/workflows/test.yml    2026-10-22 15:49:22.000000000 
+0200
@@ -10,26 +10,26 @@
   go:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
-      - uses: actions/setup-go@v3
+      - uses: actions/checkout@v7
+      - uses: actions/setup-go@v7
         with:
-          go-version: 1.21
+          go-version-file: go.mod
       - name: Test
         run: go test ./...
 
   go-arm:
     runs-on: ubuntu-24.04-arm
     steps:
-      - uses: actions/checkout@v3
-      - uses: actions/setup-go@v3
+      - uses: actions/checkout@v7
+      - uses: actions/setup-go@v7
         with:
-          go-version: 1.21
+          go-version-file: go.mod
       - name: Test on ARM
         run: go test ./...
 
   node:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v7
       - name: Test NPM version
         run: cd npm && node test.js
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/go.mod new/fx-40.0.1/go.mod
--- old/fx-40.0.0/go.mod        2026-10-05 17:50:42.000000000 +0200
+++ new/fx-40.0.1/go.mod        2026-10-22 15:49:22.000000000 +0200
@@ -20,7 +20,7 @@
        github.com/pelletier/go-toml/v2 v2.4.3
        github.com/rivo/uniseg v0.4.7
        github.com/stretchr/testify v1.12.1
-       golang.org/x/net v0.52.0
+       golang.org/x/net v0.55.0
        golang.org/x/text v0.42.0
 )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/go.sum new/fx-40.0.1/go.sum
--- old/fx-40.0.0/go.sum        2026-10-05 17:50:42.000000000 +0200
+++ new/fx-40.0.1/go.sum        2026-10-22 15:49:22.000000000 +0200
@@ -64,8 +64,8 @@
 github.com/xo/terminfo v1.2.0/go.mod 
h1:lGzkSo8Fe7IRh/w+Gqz7n5mDog4FVXCj3gy/DYTBqio=
 go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
 go.yaml.in/yaml/v3 v3.0.5/go.mod 
h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
-golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
-golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
+golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
+golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
 golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk=
 golang.org/x/sync v0.23.0/go.mod 
h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
 golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/goto_symbol_test.go 
new/fx-40.0.1/goto_symbol_test.go
--- old/fx-40.0.0/goto_symbol_test.go   1970-01-01 01:00:00.000000000 +0100
+++ new/fx-40.0.1/goto_symbol_test.go   2026-10-22 15:49:22.000000000 +0200
@@ -0,0 +1,58 @@
+package main
+
+import (
+       "strings"
+       "testing"
+       "unicode/utf8"
+
+       "github.com/charmbracelet/x/ansi"
+       "github.com/mattn/go-runewidth"
+       "github.com/stretchr/testify/require"
+
+       "github.com/antonmedv/fx/internal/fuzzy"
+       "github.com/antonmedv/fx/internal/theme"
+)
+
+func TestGotoSymbolUnicodeRendering(t *testing.T) {
+       saved := theme.CurrentTheme
+       t.Cleanup(func() { theme.CurrentTheme = saved })
+       theme.CurrentTheme.StatusBar = func(s string) string { return s }
+       theme.CurrentTheme.Search = func(s string) string { return "\x1b[31m" + 
s + "\x1b[0m" }
+
+       for _, tc := range []struct {
+               text, pattern string
+       }{
+               {"name", "m"},
+               {"名前", "前"},
+               {"éclair", "c"},
+               {"🍎apple", "a"},
+       } {
+               t.Run(tc.text, func(t *testing.T) {
+                       m := newQueryModel(t, `{"name": 1}`)
+                       m.gotoSymbolInput = newInput()
+                       m.gotoSymbolInput.Focus()
+                       m.fuzzyMatch = fuzzy.Find([]rune(tc.pattern), 
[]string{tc.text})
+                       require.NotNil(t, m.fuzzyMatch)
+
+                       lines := strings.Split(view(m), "\n")
+                       status := lines[len(lines)-2]
+                       require.True(t, utf8.ValidString(status))
+                       require.Equal(t, tc.text, 
strings.TrimRight(ansi.Strip(status), " "))
+                       require.Contains(t, status, 
"\x1b[31m"+tc.pattern+"\x1b[0m")
+                       require.Equal(t, m.termWidth, 
runewidth.StringWidth(ansi.Strip(status)))
+               })
+       }
+}
+
+func TestGotoSymbolUnicodeKey(t *testing.T) {
+       m := newQueryModel(t, `{"名前": 1}`)
+       m.gotoSymbolInput = newInput()
+       pressKey(m, press("@"))
+       typeKeys(m, "前")
+       require.NotNil(t, m.fuzzyMatch)
+
+       lines := strings.Split(view(m), "\n")
+       status := ansi.Strip(lines[len(lines)-2])
+       require.Contains(t, status, "名前")
+       require.Equal(t, m.termWidth, runewidth.StringWidth(status))
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/npm/package.json 
new/fx-40.0.1/npm/package.json
--- old/fx-40.0.0/npm/package.json      2026-10-05 17:50:42.000000000 +0200
+++ new/fx-40.0.1/npm/package.json      2026-10-22 15:49:22.000000000 +0200
@@ -1,6 +1,6 @@
 {
   "name": "fx",
-  "version": "40.0.0",
+  "version": "40.0.1",
   "bin": {
     "fx": "index.js"
   },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/snap/snapcraft.yaml 
new/fx-40.0.1/snap/snapcraft.yaml
--- old/fx-40.0.0/snap/snapcraft.yaml   2026-10-05 17:50:42.000000000 +0200
+++ new/fx-40.0.1/snap/snapcraft.yaml   2026-10-22 15:49:22.000000000 +0200
@@ -18,7 +18,7 @@
 
   Other install methods (Homebrew, GitHub release binaries, go install) have
   no such restriction: https://fx.wtf/install
-version: 40.0.0
+version: 40.0.1
 base: core24
 grade: stable
 confinement: strict
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/version.go new/fx-40.0.1/version.go
--- old/fx-40.0.0/version.go    2026-10-05 17:50:42.000000000 +0200
+++ new/fx-40.0.1/version.go    2026-10-22 15:49:22.000000000 +0200
@@ -1,3 +1,3 @@
 package main
 
-const version = "40.0.0"
+const version = "40.0.1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fx-40.0.0/view.go new/fx-40.0.1/view.go
--- old/fx-40.0.0/view.go       2026-10-05 17:50:42.000000000 +0200
+++ new/fx-40.0.1/view.go       2026-10-22 15:49:22.000000000 +0200
@@ -7,6 +7,7 @@
        "strings"
 
        tea "charm.land/bubbletea/v2"
+       "github.com/mattn/go-runewidth"
 
        "github.com/antonmedv/fx/internal/ident"
        . "github.com/antonmedv/fx/internal/jsonx"
@@ -163,14 +164,14 @@
        if m.gotoSymbolInput.Focused() && m.fuzzyMatch != nil {
                var matchedStr []byte
                str := m.fuzzyMatch.Str
-               for i := 0; i < len(str); i++ {
+               for i, char := range []rune(str) {
                        if utils.Contains(i, m.fuzzyMatch.Pos) {
-                               matchedStr = append(matchedStr, 
theme.CurrentTheme.Search(string(str[i]))...)
+                               matchedStr = append(matchedStr, 
theme.CurrentTheme.Search(string(char))...)
                        } else {
-                               matchedStr = append(matchedStr, 
theme.CurrentTheme.StatusBar(string(str[i]))...)
+                               matchedStr = append(matchedStr, 
theme.CurrentTheme.StatusBar(string(char))...)
                        }
                }
-               repeatCount := m.termWidth - len(str)
+               repeatCount := m.termWidth - runewidth.StringWidth(str)
                if repeatCount > 0 {
                        matchedStr = append(matchedStr, 
theme.CurrentTheme.StatusBar(strings.Repeat(" ", repeatCount))...)
                }

++++++ vendor.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/golang.org/x/net/html/parse.go 
new/vendor/golang.org/x/net/html/parse.go
--- old/vendor/golang.org/x/net/html/parse.go   2026-10-05 17:50:42.000000000 
+0200
+++ new/vendor/golang.org/x/net/html/parse.go   2026-10-22 15:49:22.000000000 
+0200
@@ -5,9 +5,11 @@
 package html
 
 import (
+       "cmp"
        "errors"
        "fmt"
        "io"
+       "slices"
        "strings"
 
        a "golang.org/x/net/html/atom"
@@ -328,6 +330,14 @@
        })
 }
 
+func attrCompare(a, b Attribute) int {
+       return cmp.Or(
+               cmp.Compare(a.Namespace, b.Namespace),
+               cmp.Compare(a.Key, b.Key),
+               cmp.Compare(a.Val, b.Val),
+       )
+}
+
 // addElement adds a child element based on the current token.
 func (p *parser) addElement() {
        p.addChild(&Node{
@@ -343,6 +353,10 @@
        tagAtom, attr := p.tok.DataAtom, p.tok.Attr
        p.addElement()
 
+       // In order to optimize the search, we need the attributes to be 
sorted, so we
+       // can just use slices.Equal.
+       slices.SortFunc(attr, attrCompare)
+
        // Implement the Noah's Ark clause, but with three per family instead 
of two.
        identicalElements := 0
 findIdenticalElements:
@@ -360,19 +374,7 @@
                if n.DataAtom != tagAtom {
                        continue
                }
-               if len(n.Attr) != len(attr) {
-                       continue
-               }
-       compareAttributes:
-               for _, t0 := range n.Attr {
-                       for _, t1 := range attr {
-                               if t0.Key == t1.Key && t0.Namespace == 
t1.Namespace && t0.Val == t1.Val {
-                                       // Found a match for this attribute, 
continue with the next attribute.
-                                       continue compareAttributes
-                               }
-                       }
-                       // If we get here, there is no attribute that matches a.
-                       // Therefore the element is not identical to the new 
one.
+               if !slices.Equal(n.Attr, attr) {
                        continue findIdenticalElements
                }
 
@@ -382,7 +384,11 @@
                }
        }
 
-       p.afe = append(p.afe, p.top())
+       // Sort the attributes to optimize future identical-element searches.
+       top := p.top()
+       slices.SortFunc(top.Attr, attrCompare)
+
+       p.afe = append(p.afe, top)
 }
 
 // Section 12.2.4.3.
@@ -1372,8 +1378,6 @@
 }
 
 // inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
-// "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in 
foreign content
-// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
 func (p *parser) inBodyEndTagOther(tagAtom a.Atom, tagName string) {
        for i := len(p.oe) - 1; i >= 0; i-- {
                // Two element nodes have the same tag if they have the same 
Data (a
@@ -1383,7 +1387,7 @@
                // Uncommon (custom) tags get a zero DataAtom.
                //
                // The if condition here is equivalent to (p.oe[i].Data == 
tagName).
-               if (p.oe[i].DataAtom == tagAtom) &&
+               if p.oe[i].Namespace == "" && (p.oe[i].DataAtom == tagAtom) &&
                        ((tagAtom != 0) || (p.oe[i].Data == tagName)) {
                        p.oe = p.oe[:i]
                        break
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/golang.org/x/net/html/render.go 
new/vendor/golang.org/x/net/html/render.go
--- old/vendor/golang.org/x/net/html/render.go  2026-10-05 17:50:42.000000000 
+0200
+++ new/vendor/golang.org/x/net/html/render.go  2026-10-22 15:49:22.000000000 
+0200
@@ -113,14 +113,14 @@
                                if _, err := w.WriteString(" PUBLIC "); err != 
nil {
                                        return err
                                }
-                               if err := writeQuoted(w, p); err != nil {
+                               if err := writeDoctypeQuoted(w, p); err != nil {
                                        return err
                                }
                                if s != "" {
                                        if err := w.WriteByte(' '); err != nil {
                                                return err
                                        }
-                                       if err := writeQuoted(w, s); err != nil 
{
+                                       if err := writeDoctypeQuoted(w, s); err 
!= nil {
                                                return err
                                        }
                                }
@@ -128,7 +128,7 @@
                                if _, err := w.WriteString(" SYSTEM "); err != 
nil {
                                        return err
                                }
-                               if err := writeQuoted(w, s); err != nil {
+                               if err := writeDoctypeQuoted(w, s); err != nil {
                                        return err
                                }
                        }
@@ -243,27 +243,50 @@
        if n.Namespace != "" {
                return false
        }
+
        switch n.Data {
        case "iframe", "noembed", "noframes", "noscript", "plaintext", 
"script", "style", "xmp":
+               // We need to check if n is a node that was fostered from a 
HTML namespace
+               // into a non-HTML namespace (in which case, different rules 
apply to it).
+               // We do this by walking up the tree until we find a node with 
a non-empty
+               // namespace. If we find such a node, we also have to check if 
it's
+               // an HTML integration point. If it isn't, then the node we're 
currently
+               // looking at is foster-parented and we should return false.
+               for p := n.Parent; p != nil; p = p.Parent {
+                       if p.Namespace != "" {
+                               if !htmlIntegrationPoint(p) {
+                                       return false
+                               }
+                               break
+                       }
+               }
+
                return true
        default:
                return false
        }
 }
 
-// writeQuoted writes s to w surrounded by quotes. Normally it will use double
+// writeDoctypeQuoted writes s to w surrounded by quotes. Normally it will use 
double
 // quotes, but if s contains a double quote, it will use single quotes.
+// If s contains any '>' characters, they are replaced with &gt; in order
+// to prevent triggering an abrupt-doctype-system-identifier parse error.
 // It is used for writing the identifiers in a doctype declaration.
 // In valid HTML, they can't contain both types of quotes.
-func writeQuoted(w writer, s string) error {
+func writeDoctypeQuoted(w writer, s string) error {
        var q byte = '"'
        if strings.Contains(s, `"`) {
+               // parseDoctype will never produce a Node with both quote 
types, but a user
+               // can construct their own Node that violates this assumption.
+               if strings.Contains(s, `'`) {
+                       return errors.New("doctype contains both quote types, 
cannot be safely rendered")
+               }
                q = '\''
        }
        if err := w.WriteByte(q); err != nil {
                return err
        }
-       if _, err := w.WriteString(s); err != nil {
+       if _, err := w.WriteString(strings.ReplaceAll(s, ">", "&gt;")); err != 
nil {
                return err
        }
        if err := w.WriteByte(q); err != nil {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/golang.org/x/net/html/token.go 
new/vendor/golang.org/x/net/html/token.go
--- old/vendor/golang.org/x/net/html/token.go   2026-10-05 17:50:42.000000000 
+0200
+++ new/vendor/golang.org/x/net/html/token.go   2026-10-22 15:49:22.000000000 
+0200
@@ -156,6 +156,7 @@
        // incremented on each call to TagAttr.
        pendingAttr   [2]span
        attr          [][2]span
+       attrNames     map[string]bool
        nAttrReturned int
        // rawTag is the "script" in "</script>" that closes the next token. If
        // non-empty, the subsequent call to Next will return a raw or RCDATA 
text
@@ -867,6 +868,7 @@
 func (z *Tokenizer) readTag(saveAttr bool) {
        z.attr = z.attr[:0]
        z.nAttrReturned = 0
+       clear(z.attrNames)
        // Read the tag name and attribute key/value pairs.
        z.readTagName()
        if z.skipWhiteSpace(); z.err != nil {
@@ -880,9 +882,11 @@
                z.raw.end--
                z.readTagAttrKey()
                z.readTagAttrVal()
-               // Save pendingAttr if saveAttr and that attribute has a 
non-empty key.
-               if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end {
+               // Save pendingAttr if saveAttr and that attribute has a 
non-empty key, and the key hasn't been seen before.
+               key := 
strings.ToLower(string(z.buf[z.pendingAttr[0].start:z.pendingAttr[0].end]))
+               if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end 
&& !z.attrNames[key] {
                        z.attr = append(z.attr, z.pendingAttr)
+                       z.attrNames[key] = true
                }
                if z.skipWhiteSpace(); z.err != nil {
                        break
@@ -1273,8 +1277,9 @@
 // The input is assumed to be UTF-8 encoded.
 func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer {
        z := &Tokenizer{
-               r:   r,
-               buf: make([]byte, 0, 4096),
+               r:         r,
+               buf:       make([]byte, 0, 4096),
+               attrNames: make(map[string]bool),
        }
        if contextTag != "" {
                switch s := strings.ToLower(contextTag); s {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt
--- old/vendor/modules.txt      2026-10-05 17:50:42.000000000 +0200
+++ new/vendor/modules.txt      2026-10-22 15:49:22.000000000 +0200
@@ -128,7 +128,7 @@
 # go.yaml.in/yaml/v3 v3.0.5
 ## explicit; go 1.16
 go.yaml.in/yaml/v3
-# golang.org/x/net v0.52.0
+# golang.org/x/net v0.55.0
 ## explicit; go 1.25.0
 golang.org/x/net/html
 golang.org/x/net/html/atom

Reply via email to