mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-24 00:33:14 +00:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f0d2ab6493 | ||
|
42ee0372fe | ||
|
9762e09cb3 | ||
|
dd8b7ab27d | ||
|
c348593ef4 | ||
|
a51da7b8ec | ||
|
33503f7896 |
1
.github/workflows/build-docker.yml
vendored
1
.github/workflows/build-docker.yml
vendored
@ -38,3 +38,4 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
@ -90,6 +90,10 @@ func main() {
|
|||||||
log.SetOutput(os.Stdout)
|
log.SetOutput(os.Stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if open && strings.HasPrefix(addr, "unix:") {
|
||||||
|
log.Fatal("Cannot open ", addr, " in browser")
|
||||||
|
}
|
||||||
|
|
||||||
if db == "" {
|
if db == "" {
|
||||||
configPath, err := os.UserConfigDir()
|
configPath, err := os.UserConfigDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
# upcoming
|
# upcoming
|
||||||
|
|
||||||
|
- (new) serve on unix socket (thanks to @rvighne)
|
||||||
|
|
||||||
|
# v2.5 (2025-03-26)
|
||||||
|
|
||||||
- (new) Fever API support (thanks to @icefed)
|
- (new) Fever API support (thanks to @icefed)
|
||||||
- (new) editable feed link (thanks to @adaszko)
|
- (new) editable feed link (thanks to @adaszko)
|
||||||
- (new) switch to feed by clicking the title in the article page (thanks to @tarasglek for suggestion)
|
- (new) switch to feed by clicking the title in the article page (thanks to @tarasglek for suggestion)
|
||||||
- (new) support multiple media links
|
- (new) support multiple media links
|
||||||
|
- (new) next/prev article navigation buttons (thanks to @tillcash)
|
||||||
- (fix) duplicate articles caused by the same feed addition (thanks to @adaszko)
|
- (fix) duplicate articles caused by the same feed addition (thanks to @adaszko)
|
||||||
- (fix) relative article links (thanks to @adazsko for the report)
|
- (fix) relative article links (thanks to @adazsko for the report)
|
||||||
- (fix) atom article links stored in id element (thanks to @adazsko for the report)
|
- (fix) atom article links stored in id element (thanks to @adazsko for the report)
|
||||||
@ -17,6 +22,7 @@
|
|||||||
- (etc) load external images with no-referrer policy (thanks to @tillcash for the report)
|
- (etc) load external images with no-referrer policy (thanks to @tillcash for the report)
|
||||||
- (etc) open external links with no-referrer policy (thanks to @donovanglover)
|
- (etc) open external links with no-referrer policy (thanks to @donovanglover)
|
||||||
- (etc) show article content in the list if title is missing (thanks to @asimpson for suggestion)
|
- (etc) show article content in the list if title is missing (thanks to @asimpson for suggestion)
|
||||||
|
- (etc) accessibility improvements (thanks to @tseykovets)
|
||||||
|
|
||||||
# v2.4 (2023-08-15)
|
# v2.4 (2023-08-15)
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -6,7 +6,7 @@ toolchain go1.23.5
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/mattn/go-sqlite3 v1.14.24
|
github.com/mattn/go-sqlite3 v1.14.24
|
||||||
golang.org/x/net v0.37.0
|
golang.org/x/net v0.38.0
|
||||||
golang.org/x/sys v0.31.0
|
golang.org/x/sys v0.31.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
10
go.sum
10
go.sum
@ -1,14 +1,8 @@
|
|||||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
|
||||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
|
20
readme.md
20
readme.md
@ -9,21 +9,21 @@ The app is a single binary with an embedded database (SQLite).
|
|||||||
|
|
||||||
## usage
|
## usage
|
||||||
|
|
||||||
The latest prebuilt binaries for Linux/MacOS/Windows AMD64 are available
|
The latest prebuilt binaries for Linux/MacOS/Windows are available
|
||||||
[here](https://github.com/nkanaev/yarr/releases/latest). Installation instructions:
|
[here](https://github.com/nkanaev/yarr/releases/latest).
|
||||||
|
The archives follow the naming convention `yarr_{OS}_{ARCH}[_gui].zip`, where:
|
||||||
|
|
||||||
* MacOS
|
* `OS` is the target operating system
|
||||||
|
* `ARCH` is the CPU architecture (`arm64` for AArch64, `amd64` for X86-64)
|
||||||
|
* `-gui` indicates that the binary ships with the GUI (tray icon), and is a command line application if omitted
|
||||||
|
|
||||||
Download `yarr-*-macos64.zip`, unzip it, place `yarr.app` in `/Applications` folder, [open the app][macos-open], click the anchor menu bar icon, select "Open".
|
Usage instructions:
|
||||||
|
|
||||||
* Windows
|
* MacOS: place `yarr.app` in `/Applications` folder, [open the app][macos-open], click the anchor menu bar icon, select "Open".
|
||||||
|
|
||||||
Download `yarr-*-windows64.zip`, unzip it, open `yarr.exe`, click the anchor system tray icon, select "Open".
|
* Windows: open `yarr.exe`, click the anchor system tray icon, select "Open".
|
||||||
|
|
||||||
* Linux
|
* Linux: place `yarr` in `$HOME/.local/bin` and run [the script](etc/install-linux.sh).
|
||||||
|
|
||||||
Download `yarr-*-linux64.zip`, unzip it, place `yarr` in `$HOME/.local/bin`
|
|
||||||
and run [the script](etc/install-linux.sh).
|
|
||||||
|
|
||||||
[macos-open]: https://support.apple.com/en-gb/guide/mac-help/mh40616/mac
|
[macos-open]: https://support.apple.com/en-gb/guide/mac-help/mh40616/mac
|
||||||
|
|
||||||
|
@ -2,7 +2,10 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/nkanaev/yarr/src/storage"
|
"github.com/nkanaev/yarr/src/storage"
|
||||||
@ -53,14 +56,31 @@ func (s *Server) Start() {
|
|||||||
s.worker.RefreshFeeds()
|
s.worker.RefreshFeeds()
|
||||||
}
|
}
|
||||||
|
|
||||||
httpserver := &http.Server{Addr: s.Addr, Handler: s.handler()}
|
var ln net.Listener
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if s.CertFile != "" && s.KeyFile != "" {
|
|
||||||
err = httpserver.ListenAndServeTLS(s.CertFile, s.KeyFile)
|
if path, isUnix := strings.CutPrefix(s.Addr, "unix:"); isUnix {
|
||||||
} else {
|
err = os.Remove(path)
|
||||||
err = httpserver.ListenAndServe()
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
}
|
}
|
||||||
|
ln, err = net.Listen("unix", path)
|
||||||
|
} else {
|
||||||
|
ln, err = net.Listen("tcp", s.Addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
httpserver := &http.Server{Handler: s.handler()}
|
||||||
|
if s.CertFile != "" && s.KeyFile != "" {
|
||||||
|
err = httpserver.ServeTLS(ln, s.CertFile, s.KeyFile)
|
||||||
|
ln.Close()
|
||||||
|
} else {
|
||||||
|
err = httpserver.Serve(ln)
|
||||||
|
}
|
||||||
|
|
||||||
if err != http.ErrServerClosed {
|
if err != http.ErrServerClosed {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
1256
vendor/golang.org/x/net/html/atom/table.go
generated
vendored
1256
vendor/golang.org/x/net/html/atom/table.go
generated
vendored
File diff suppressed because it is too large
Load Diff
4
vendor/golang.org/x/net/html/parse.go
generated
vendored
4
vendor/golang.org/x/net/html/parse.go
generated
vendored
@ -924,7 +924,7 @@ func inBodyIM(p *parser) bool {
|
|||||||
p.addElement()
|
p.addElement()
|
||||||
p.im = inFramesetIM
|
p.im = inFramesetIM
|
||||||
return true
|
return true
|
||||||
case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Main, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
|
case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Main, a.Menu, a.Nav, a.Ol, a.P, a.Search, a.Section, a.Summary, a.Ul:
|
||||||
p.popUntil(buttonScope, a.P)
|
p.popUntil(buttonScope, a.P)
|
||||||
p.addElement()
|
p.addElement()
|
||||||
case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
|
case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
|
||||||
@ -1136,7 +1136,7 @@ func inBodyIM(p *parser) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Main, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
|
case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Main, a.Menu, a.Nav, a.Ol, a.Pre, a.Search, a.Section, a.Summary, a.Ul:
|
||||||
p.popUntil(defaultScope, p.tok.DataAtom)
|
p.popUntil(defaultScope, p.tok.DataAtom)
|
||||||
case a.Form:
|
case a.Form:
|
||||||
if p.oe.contains(a.Template) {
|
if p.oe.contains(a.Template) {
|
||||||
|
18
vendor/golang.org/x/net/html/token.go
generated
vendored
18
vendor/golang.org/x/net/html/token.go
generated
vendored
@ -839,8 +839,22 @@ func (z *Tokenizer) readStartTag() TokenType {
|
|||||||
if raw {
|
if raw {
|
||||||
z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end]))
|
z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end]))
|
||||||
}
|
}
|
||||||
// Look for a self-closing token like "<br/>".
|
// Look for a self-closing token (e.g. <br/>).
|
||||||
if z.err == nil && z.buf[z.raw.end-2] == '/' {
|
//
|
||||||
|
// Originally, we did this by just checking that the last character of the
|
||||||
|
// tag (ignoring the closing bracket) was a solidus (/) character, but this
|
||||||
|
// is not always accurate.
|
||||||
|
//
|
||||||
|
// We need to be careful that we don't misinterpret a non-self-closing tag
|
||||||
|
// as self-closing, as can happen if the tag contains unquoted attribute
|
||||||
|
// values (i.e. <p a=/>).
|
||||||
|
//
|
||||||
|
// To avoid this, we check that the last non-bracket character of the tag
|
||||||
|
// (z.raw.end-2) isn't the same character as the last non-quote character of
|
||||||
|
// the last attribute of the tag (z.pendingAttr[1].end-1), if the tag has
|
||||||
|
// attributes.
|
||||||
|
nAttrs := len(z.attr)
|
||||||
|
if z.err == nil && z.buf[z.raw.end-2] == '/' && (nAttrs == 0 || z.raw.end-2 != z.attr[nAttrs-1][1].end-1) {
|
||||||
return SelfClosingTagToken
|
return SelfClosingTagToken
|
||||||
}
|
}
|
||||||
return StartTagToken
|
return StartTagToken
|
||||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -1,7 +1,7 @@
|
|||||||
# github.com/mattn/go-sqlite3 v1.14.24
|
# github.com/mattn/go-sqlite3 v1.14.24
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
github.com/mattn/go-sqlite3
|
github.com/mattn/go-sqlite3
|
||||||
# golang.org/x/net v0.37.0
|
# golang.org/x/net v0.38.0
|
||||||
## explicit; go 1.23.0
|
## explicit; go 1.23.0
|
||||||
golang.org/x/net/html
|
golang.org/x/net/html
|
||||||
golang.org/x/net/html/atom
|
golang.org/x/net/html/atom
|
||||||
|
Loading…
x
Reference in New Issue
Block a user