Add and enforce golangci-lint (#16)
This commit is contained in:
@@ -4,6 +4,7 @@ go:
|
|||||||
- "1.14"
|
- "1.14"
|
||||||
before_script:
|
before_script:
|
||||||
- make build
|
- make build
|
||||||
|
- make lint
|
||||||
- make test
|
- make test
|
||||||
deploy:
|
deploy:
|
||||||
- provider: script
|
- provider: script
|
||||||
|
4
Makefile
4
Makefile
@@ -8,3 +8,7 @@ build: ## Builds the binary
|
|||||||
test: ## Run unit tests
|
test: ## Run unit tests
|
||||||
go test -v ./...
|
go test -v ./...
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
|
||||||
|
lint: ## Run lint
|
||||||
|
go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.27.0
|
||||||
|
golangci-lint run
|
||||||
|
12
README.md
12
README.md
@@ -27,7 +27,7 @@ go get github.com/davegallant/srv
|
|||||||
|
|
||||||
## configure
|
## configure
|
||||||
|
|
||||||
srv reads configuration from `~/.config/srv/config.yaml`
|
srv reads configuration from `~/.config/srv/config.yml`
|
||||||
|
|
||||||
If a configuration is not provided, a default configuration is generated.
|
If a configuration is not provided, a default configuration is generated.
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ If a configuration is not provided, a default configuration is generated.
|
|||||||
An example config can be copied:
|
An example config can be copied:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cp ./config-example.yaml ~/.config/srv/config.yaml
|
cp ./config-example.yml ~/.config/srv/config.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
## navigate
|
## navigate
|
||||||
@@ -48,6 +48,8 @@ Key mappings are statically defined for the time being.
|
|||||||
- `UP/DOWN` navigates feeds and items`
|
- `UP/DOWN` navigates feeds and items`
|
||||||
- `ENTER` either selects a feed or opens a feed item in an external application.
|
- `ENTER` either selects a feed or opens a feed item in an external application.
|
||||||
- `F5` refresh list of feeds
|
- `F5` refresh list of feeds
|
||||||
|
- `CTRL+C` quit
|
||||||
|
|
||||||
|
|
||||||
## build
|
## build
|
||||||
|
|
||||||
@@ -60,3 +62,9 @@ make build
|
|||||||
```shell
|
```shell
|
||||||
make test
|
make test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## lint
|
||||||
|
|
||||||
|
```shell
|
||||||
|
make lint
|
||||||
|
```
|
||||||
|
@@ -1,12 +1,5 @@
|
|||||||
---
|
|
||||||
feeds:
|
feeds:
|
||||||
- https://news.ycombinator.com/rss
|
- https://aws.amazon.com/blogs/security/feed/
|
||||||
- https://www.reddit.com/r/golang/.rss
|
- https://www.phoronix.com/rss.php
|
||||||
- https://www.reddit.com/r/linux/.rss
|
|
||||||
- https://www.zdnet.com/topic/security/rss.xml
|
- https://www.zdnet.com/topic/security/rss.xml
|
||||||
|
path: .config/srv/config.yml
|
||||||
# Optionally define an application to view the feeds
|
|
||||||
#externalViewer: firefox
|
|
||||||
# Optionally define args for the external viewer
|
|
||||||
#externalViewerArgs:
|
|
||||||
#- --new-window
|
|
||||||
|
12
config-example.yml
Normal file
12
config-example.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
feeds:
|
||||||
|
- https://news.ycombinator.com/rss
|
||||||
|
- https://www.reddit.com/r/linux/.rss
|
||||||
|
- https://www.zdnet.com/topic/security/rss.xml
|
||||||
|
- https://www.phoronix.com/rss.php
|
||||||
|
|
||||||
|
# Optionally define an application to view the feeds
|
||||||
|
#externalViewer: firefox
|
||||||
|
# Optionally define args for the external viewer
|
||||||
|
#externalViewerArgs:
|
||||||
|
#- --new-window
|
@@ -1,31 +1,53 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"github.com/juju/errors"
|
||||||
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/davegallant/srv/file"
|
"github.com/davegallant/srv/file"
|
||||||
|
"github.com/spf13/afero"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ConfigPath defines where the configuration is stored
|
||||||
|
const ConfigPath = ".config/srv/config.yml"
|
||||||
|
|
||||||
// Configuration stores the global config
|
// Configuration stores the global config
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
Feeds []string `yaml:"feeds"`
|
Feeds []string `yaml:"feeds"`
|
||||||
ExternalViewer string `yaml:"externalViewer,omitempty"`
|
ExternalViewer string `yaml:"externalViewer,omitempty"`
|
||||||
ExternalViewerArgs []string `yaml:"externalViewerArgs,omitempty"`
|
ExternalViewerArgs []string `yaml:"externalViewerArgs,omitempty"`
|
||||||
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultConfiguration can be used if a config is missing
|
// DefaultConfiguration can be used if a config is missing
|
||||||
var DefaultConfiguration = Configuration{
|
var DefaultConfiguration = Configuration{
|
||||||
Feeds: []string{
|
Feeds: []string{
|
||||||
"https://news.ycombinator.com/rss",
|
"https://aws.amazon.com/blogs/security/feed/",
|
||||||
"https://www.reddit.com/r/golang/.rss",
|
"https://www.phoronix.com/rss.php",
|
||||||
"https://www.reddit.com/r/linux/.rss",
|
|
||||||
"https://www.zdnet.com/topic/security/rss.xml",
|
"https://www.zdnet.com/topic/security/rss.xml",
|
||||||
},
|
},
|
||||||
|
Path: ConfigPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUGetUGetUserConfigPath returns the full configuration path for the current user
|
||||||
|
func GetUserConfigPath() (string, error) {
|
||||||
|
usr, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
createConfigPath := []string{usr.HomeDir}
|
||||||
|
createConfigPath = append(createConfigPath, strings.Split(ConfigPath, "/")...)
|
||||||
|
return path.Join(createConfigPath...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DetermineExternalViewer checks the OS to decide the default viewer
|
// DetermineExternalViewer checks the OS to decide the default viewer
|
||||||
@@ -40,12 +62,19 @@ func DetermineExternalViewer() (string, error) {
|
|||||||
return "", errors.New("Unable to determine a default external viewer")
|
return "", errors.New("Unable to determine a default external viewer")
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfiguration takes a filename (configuration) and loads it.
|
// EnsureConfigDirExists ensures directory exists with correct permissions
|
||||||
func LoadConfiguration(f string) Configuration {
|
func EnsureConfigDirExists(d string) error {
|
||||||
|
var AppFs = afero.NewOsFs()
|
||||||
|
return AppFs.MkdirAll(d, 0700)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadConfiguration loads a configuration from a file
|
||||||
|
func LoadConfiguration(f string) (Configuration, error) {
|
||||||
var config Configuration
|
var config Configuration
|
||||||
|
|
||||||
if !file.Exists(f) {
|
if !file.Exists(f) {
|
||||||
WriteConfig(DefaultConfiguration, f)
|
err := WriteConfig(DefaultConfiguration, f)
|
||||||
|
return DefaultConfiguration, errors.Annotate(err, "failed to load configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(f)
|
data, err := ioutil.ReadFile(f)
|
||||||
@@ -67,19 +96,26 @@ func LoadConfiguration(f string) Configuration {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
return config
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteConfig writes a config to disk
|
// WriteConfig writes a config to disk
|
||||||
func WriteConfig(config Configuration, file string) error {
|
func WriteConfig(config Configuration, f string) error {
|
||||||
c, err := yaml.Marshal(&config)
|
|
||||||
|
d := filepath.Dir(f)
|
||||||
|
err := EnsureConfigDirExists(d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to marshal default config: %v", err)
|
return errors.Annotatef(err, "Unable to to create config directory '%s'", d)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ioutil.WriteFile(file, c, 0600)
|
c, err := yaml.Marshal(&config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to write default config: %v", err)
|
return errors.Annotatef(err, "Unable to marshal config '%s'", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(f, c, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Annotatef(err, "Unable to write default config: '%s'", f)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -8,12 +8,13 @@ import (
|
|||||||
|
|
||||||
// TestLoadConfiguration tests loading the example config
|
// TestLoadConfiguration tests loading the example config
|
||||||
func TestLoadConfiguration(t *testing.T) {
|
func TestLoadConfiguration(t *testing.T) {
|
||||||
exampleConfig := LoadConfiguration("../config-example.yaml")
|
exampleConfig, err := LoadConfiguration("../config-example.yaml")
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
expectedFeeds := []string{
|
expectedFeeds := []string{
|
||||||
"https://news.ycombinator.com/rss",
|
"https://aws.amazon.com/blogs/security/feed/",
|
||||||
"https://www.reddit.com/r/golang/.rss",
|
"https://www.phoronix.com/rss.php",
|
||||||
"https://www.reddit.com/r/linux/.rss",
|
|
||||||
"https://www.zdnet.com/topic/security/rss.xml",
|
"https://www.zdnet.com/topic/security/rss.xml",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
config "github.com/davegallant/srv/config"
|
config "github.com/davegallant/srv/config"
|
||||||
feeds "github.com/davegallant/srv/feeds"
|
feeds "github.com/davegallant/srv/feeds"
|
||||||
)
|
)
|
||||||
@@ -12,9 +14,19 @@ type Controller struct {
|
|||||||
CurrentFeed int
|
CurrentFeed int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initiates the controller with config
|
// Init initiates the controller
|
||||||
func (c *Controller) Init(conf string) {
|
func (c *Controller) Init() {
|
||||||
c.Config = config.LoadConfiguration(conf)
|
|
||||||
|
configPath, err := config.GetUserConfigPath()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Unable to locate user's config path")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Config, err = config.LoadConfiguration(configPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to load configuration: %s", err)
|
||||||
|
}
|
||||||
c.Rss = &feeds.RSS{}
|
c.Rss = &feeds.RSS{}
|
||||||
c.Rss.Update(c.Config.Feeds)
|
c.Rss.Update(c.Config.Feeds)
|
||||||
c.CurrentFeed = 0
|
c.CurrentFeed = 0
|
||||||
|
23
cui/main.go
23
cui/main.go
@@ -4,8 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
|
||||||
"path"
|
|
||||||
|
|
||||||
"github.com/davegallant/srv/controller"
|
"github.com/davegallant/srv/controller"
|
||||||
"github.com/davegallant/srv/utils"
|
"github.com/davegallant/srv/utils"
|
||||||
@@ -37,7 +35,10 @@ func openFeed(g *gocui.Gui, v *gocui.View) error {
|
|||||||
for _, item := range feed.Items {
|
for _, item := range feed.Items {
|
||||||
fmt.Fprintln(ov, "-", item.Title)
|
fmt.Fprintln(ov, "-", item.Title)
|
||||||
}
|
}
|
||||||
nextView(g, ov)
|
err := nextView(g, ov)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to get next view: %s", err)
|
||||||
|
}
|
||||||
displayDescription(g, ov)
|
displayDescription(g, ov)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -48,17 +49,15 @@ func getCurrentFeedItem(v *gocui.View) *gofeed.Item {
|
|||||||
return Controller.Rss.Feeds[Controller.CurrentFeed].Items[oy]
|
return Controller.Rss.Feeds[Controller.CurrentFeed].Items[oy]
|
||||||
}
|
}
|
||||||
|
|
||||||
// displayDescription displays feed descriptin if it exists
|
// displayDescription displays feed description if it exists
|
||||||
func displayDescription(g *gocui.Gui, v *gocui.View) error {
|
func displayDescription(g *gocui.Gui, v *gocui.View) {
|
||||||
|
|
||||||
ov, _ := g.View("Description")
|
ov, _ := g.View("Description")
|
||||||
ov.Clear()
|
ov.Clear()
|
||||||
|
|
||||||
item := getCurrentFeedItem(v)
|
item := getCurrentFeedItem(v)
|
||||||
description := utils.StripHtmlTags(item.Description)
|
description := utils.StripHTMLTags(item.Description)
|
||||||
fmt.Fprintln(ov, description)
|
fmt.Fprintln(ov, description)
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// openItem opens the feed in an external browser
|
// openItem opens the feed in an external browser
|
||||||
@@ -157,14 +156,8 @@ func quit(g *gocui.Gui, v *gocui.View) error {
|
|||||||
|
|
||||||
// Start initializes the application
|
// Start initializes the application
|
||||||
func Start() {
|
func Start() {
|
||||||
usr, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
configPath := path.Join(usr.HomeDir, ".config", "srv", "config.yaml")
|
|
||||||
|
|
||||||
Controller = &controller.Controller{}
|
Controller = &controller.Controller{}
|
||||||
Controller.Init(configPath)
|
Controller.Init()
|
||||||
|
|
||||||
g, err := gocui.NewGui(gocui.Output256)
|
g, err := gocui.NewGui(gocui.Output256)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -9,8 +9,5 @@ import (
|
|||||||
func Exists(filename string) bool {
|
func Exists(filename string) bool {
|
||||||
var AppFs = afero.NewOsFs()
|
var AppFs = afero.NewOsFs()
|
||||||
_, err := AppFs.Stat(filename)
|
_, err := AppFs.Stat(filename)
|
||||||
if err != nil {
|
return err == nil
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
7
go.mod
7
go.mod
@@ -6,14 +6,17 @@ require (
|
|||||||
github.com/EDDYCJY/fake-useragent v0.2.0
|
github.com/EDDYCJY/fake-useragent v0.2.0
|
||||||
github.com/PuerkitoBio/goquery v1.5.1 // indirect
|
github.com/PuerkitoBio/goquery v1.5.1 // indirect
|
||||||
github.com/jroimartin/gocui v0.4.0
|
github.com/jroimartin/gocui v0.4.0
|
||||||
github.com/kr/pretty v0.1.0 // indirect
|
github.com/juju/errors v0.0.0-20200330140219-3fe23663418f
|
||||||
|
github.com/juju/testing v0.0.0-20200608005635-e4eedbc6f7aa // indirect
|
||||||
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.8 // indirect
|
github.com/mattn/go-runewidth v0.0.8 // indirect
|
||||||
github.com/mmcdole/gofeed v1.0.0
|
github.com/mmcdole/gofeed v1.0.0
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be // indirect
|
github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be // indirect
|
||||||
github.com/spf13/afero v1.3.1
|
github.com/spf13/afero v1.3.1
|
||||||
github.com/stretchr/testify v1.6.1
|
github.com/stretchr/testify v1.6.1
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
|
||||||
golang.org/x/text v0.3.2 // indirect
|
golang.org/x/text v0.3.2 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
gopkg.in/yaml.v2 v2.3.0
|
gopkg.in/yaml.v2 v2.3.0
|
||||||
)
|
)
|
||||||
|
30
go.sum
30
go.sum
@@ -7,26 +7,41 @@ github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9Pq
|
|||||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
github.com/codegangsta/cli v1.20.0/go.mod h1:/qJNoX69yVSKu5o4jLyXAENLRyk1uhi7zkbQ3slBdOA=
|
github.com/codegangsta/cli v1.20.0/go.mod h1:/qJNoX69yVSKu5o4jLyXAENLRyk1uhi7zkbQ3slBdOA=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/jroimartin/gocui v0.4.0 h1:52jnalstgmc25FmtGcWqa0tcbMEWS6RpFLsOIO+I+E8=
|
github.com/jroimartin/gocui v0.4.0 h1:52jnalstgmc25FmtGcWqa0tcbMEWS6RpFLsOIO+I+E8=
|
||||||
github.com/jroimartin/gocui v0.4.0/go.mod h1:7i7bbj99OgFHzo7kB2zPb8pXLqMBSQegY7azfqXMkyY=
|
github.com/jroimartin/gocui v0.4.0/go.mod h1:7i7bbj99OgFHzo7kB2zPb8pXLqMBSQegY7azfqXMkyY=
|
||||||
|
github.com/juju/clock v0.0.0-20180524022203-d293bb356ca4/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA=
|
||||||
|
github.com/juju/errors v0.0.0-20150916125642-1b5e39b83d18/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
||||||
|
github.com/juju/errors v0.0.0-20200330140219-3fe23663418f h1:MCOvExGLpaSIzLYB4iQXEHP4jYVU6vmzLNQPdMVrxnM=
|
||||||
|
github.com/juju/errors v0.0.0-20200330140219-3fe23663418f/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
||||||
|
github.com/juju/loggo v0.0.0-20170605014607-8232ab8918d9 h1:Y+lzErDTURqeXqlqYi4YBYbDd7ycU74gW1ADt57/bgY=
|
||||||
|
github.com/juju/loggo v0.0.0-20170605014607-8232ab8918d9/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||||
|
github.com/juju/retry v0.0.0-20160928201858-1998d01ba1c3/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4=
|
||||||
|
github.com/juju/testing v0.0.0-20200608005635-e4eedbc6f7aa h1:v1ZEHRVaUgTIkxzYaT78fJ+3bV3vjxj9jfNJcYzi9pY=
|
||||||
|
github.com/juju/testing v0.0.0-20200608005635-e4eedbc6f7aa/go.mod h1:hpGvhGHPVbNBraRLZEhoQwFLMrjK8PSlO4D3nDjKYXo=
|
||||||
|
github.com/juju/utils v0.0.0-20180808125547-9dfc6dbfb02b/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk=
|
||||||
|
github.com/juju/version v0.0.0-20161031051906-1f41e27e54f2/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0=
|
github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0=
|
||||||
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mmcdole/gofeed v1.0.0 h1:PHqwr8fsEm8xarj9s53XeEAFYhRM3E9Ib7Ie766/LTE=
|
github.com/mmcdole/gofeed v1.0.0 h1:PHqwr8fsEm8xarj9s53XeEAFYhRM3E9Ib7Ie766/LTE=
|
||||||
github.com/mmcdole/gofeed v1.0.0/go.mod h1:tkVcyzS3qVMlQrQxJoEH1hkTiuo9a8emDzkMi7TZBu0=
|
github.com/mmcdole/gofeed v1.0.0/go.mod h1:tkVcyzS3qVMlQrQxJoEH1hkTiuo9a8emDzkMi7TZBu0=
|
||||||
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI=
|
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI=
|
||||||
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf/go.mod h1:pasqhqstspkosTneA62Nc+2p9SOBBYAPbnmRRWPQ0V8=
|
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf/go.mod h1:pasqhqstspkosTneA62Nc+2p9SOBBYAPbnmRRWPQ0V8=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be h1:yzmWtPyxEUIKdZg4RcPq64MfS8NA6A5fNOJgYhpR9EQ=
|
github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be h1:yzmWtPyxEUIKdZg4RcPq64MfS8NA6A5fNOJgYhpR9EQ=
|
||||||
github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
|
github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
|
||||||
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
@@ -39,9 +54,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
golang.org/x/crypto v0.0.0-20180214000028-650f4a345ab4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
@@ -50,6 +67,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7
|
|||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
@@ -57,8 +75,12 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/mgo.v2 v2.0.0-20160818015218-f2b6f6c918c4 h1:hILp2hNrRnYjZpmIbx70psAHbBSEcQ1NIzDcUbJ1b6g=
|
||||||
|
gopkg.in/mgo.v2 v2.0.0-20160818015218-f2b6f6c918c4/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20170712054546-1be3d31502d6/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
|
@@ -6,8 +6,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StripHtmlTags uses regex to strip all html elements
|
// StripHTMLTags uses regex to strip all html elements
|
||||||
func StripHtmlTags(s string) string {
|
func StripHTMLTags(s string) string {
|
||||||
const pattern = `(<\/?[a-zA-A]+?[^>]*\/?>)*`
|
const pattern = `(<\/?[a-zA-A]+?[^>]*\/?>)*`
|
||||||
r := regexp.MustCompile(pattern)
|
r := regexp.MustCompile(pattern)
|
||||||
groups := r.FindAllString(s, -1)
|
groups := r.FindAllString(s, -1)
|
||||||
|
Reference in New Issue
Block a user