diff --git a/account.go b/account.go index 72d12ee..6ab73bd 100644 --- a/account.go +++ b/account.go @@ -1021,9 +1021,10 @@ func viewStats(app *App, u *User, w http.ResponseWriter, r *http.Request) error if c.OwnerID != u.ID { return ErrCollectionNotFound } + c.hostName = app.cfg.App.Host } - topPosts, err := app.db.GetTopPosts(u, alias) + topPosts, err := app.db.GetTopPosts(u, alias, c.hostName) if err != nil { log.Error("Unable to get top posts: %v", err) return err diff --git a/app.go b/app.go index 40eb858..4c4aeb9 100644 --- a/app.go +++ b/app.go @@ -30,7 +30,7 @@ import ( "github.com/gorilla/schema" "github.com/gorilla/sessions" "github.com/manifoldco/promptui" - stripmd "github.com/writeas/go-strip-markdown" + stripmd "github.com/writeas/go-strip-markdown/v2" "github.com/writeas/impart" "github.com/writeas/web-core/auth" "github.com/writeas/web-core/converter" @@ -56,7 +56,7 @@ var ( debugging bool // Software version can be set from git env using -ldflags - softwareVer = "0.13.0" + softwareVer = "0.13.1" // DEPRECATED VARS isSingleUser bool @@ -797,7 +797,7 @@ func connectToDatabase(app *App) { os.Exit(1) } db, err = sql.Open("sqlite3_with_regex", app.cfg.Database.FileName+"?parseTime=true&cached=shared") - db.SetMaxOpenConns(1) + db.SetMaxOpenConns(2) } else { log.Error("Invalid database type '%s'. Only 'mysql' and 'sqlite3' are supported right now.", app.cfg.Database.Type) os.Exit(1) diff --git a/collections.go b/collections.go index f79cc2d..beadf19 100644 --- a/collections.go +++ b/collections.go @@ -242,6 +242,8 @@ func (c *Collection) DisplayCanonicalURL() string { return d + p } +// RedirectingCanonicalURL returns the fully-qualified canonical URL for the Collection, with a trailing slash. The +// hostName field needs to be populated for this to work correctly. func (c *Collection) RedirectingCanonicalURL(isRedir bool) string { if c.hostName == "" { // If this is true, the human programmers screwed up. So ask for a bug report and fail, fail, fail diff --git a/database.go b/database.go index fefc3c1..f474ae9 100644 --- a/database.go +++ b/database.go @@ -76,7 +76,7 @@ type writestore interface { GetMeStats(u *User) userMeStats GetTotalCollections() (int64, error) GetTotalPosts() (int64, error) - GetTopPosts(u *User, alias string) (*[]PublicPost, error) + GetTopPosts(u *User, alias string, hostName string) (*[]PublicPost, error) GetAnonymousPosts(u *User, page int) (*[]PublicPost, error) GetUserPosts(u *User) (*[]PublicPost, error) @@ -1767,7 +1767,7 @@ func (db *datastore) GetTotalPosts() (postCount int64, err error) { return } -func (db *datastore) GetTopPosts(u *User, alias string) (*[]PublicPost, error) { +func (db *datastore) GetTopPosts(u *User, alias string, hostName string) (*[]PublicPost, error) { params := []interface{}{u.ID} where := "" if alias != "" { @@ -1802,6 +1802,7 @@ func (db *datastore) GetTopPosts(u *User, alias string) (*[]PublicPost, error) { c.Title = title.String c.Description = description.String c.Views = views.Int64 + c.hostName = hostName pubPost.Collection = &CollectionObj{Collection: c} } diff --git a/feed.go b/feed.go index 32c6591..d85baf8 100644 --- a/feed.go +++ b/feed.go @@ -17,7 +17,7 @@ import ( . "github.com/gorilla/feeds" "github.com/gorilla/mux" - stripmd "github.com/writeas/go-strip-markdown" + stripmd "github.com/writeas/go-strip-markdown/v2" "github.com/writeas/web-core/log" ) diff --git a/go.mod b/go.mod index 8344d4c..cb8bd79 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/urfave/cli/v2 v2.3.0 github.com/writeas/activity v0.1.2 github.com/writeas/activityserve v0.0.0-20200409150223-d7ab3eaa4481 - github.com/writeas/go-strip-markdown v2.0.1+incompatible + github.com/writeas/go-strip-markdown/v2 v2.1.1 github.com/writeas/go-webfinger v1.1.0 github.com/writeas/httpsig v1.0.0 github.com/writeas/impart v1.1.1 diff --git a/go.sum b/go.sum index 354a1dd..5f2eb13 100644 --- a/go.sum +++ b/go.sum @@ -127,8 +127,8 @@ github.com/writeas/activity v0.1.2 h1:Y12B5lIrabfqKE7e7HFCWiXrlfXljr9tlkFm2mp7Dg github.com/writeas/activity v0.1.2/go.mod h1:mYYgiewmEM+8tlifirK/vl6tmB2EbjYaxwb+ndUw5T0= github.com/writeas/activityserve v0.0.0-20200409150223-d7ab3eaa4481 h1:BiSivIxLQFcKoUorpNN3rNwwFG5bITPnqUSyIccfdh0= github.com/writeas/activityserve v0.0.0-20200409150223-d7ab3eaa4481/go.mod h1:4akDJSl+sSp+QhrQKMqzAqdV1gJ1pPx6XPI77zgMM8o= -github.com/writeas/go-strip-markdown v2.0.1+incompatible h1:IIqxTM5Jr7RzhigcL6FkrCNfXkvbR+Nbu1ls48pXYcw= -github.com/writeas/go-strip-markdown v2.0.1+incompatible/go.mod h1:Rsyu10ZhbEK9pXdk8V6MVnZmTzRG0alMNLMwa0J01fE= +github.com/writeas/go-strip-markdown/v2 v2.1.1 h1:hAxUM21Uhznf/FnbVGiJciqzska6iLei22Ijc3q2e28= +github.com/writeas/go-strip-markdown/v2 v2.1.1/go.mod h1:UvvgPJgn1vvN8nWuE5e7v/+qmDu3BSVnKAB6Gl7hFzA= github.com/writeas/go-webfinger v1.1.0 h1:MzNyt0ry/GMsRmJGftn2o9mPwqK1Q5MLdh4VuJCfb1Q= github.com/writeas/go-webfinger v1.1.0/go.mod h1:w2VxyRO/J5vfNjJHYVubsjUGHd3RLDoVciz0DE3ApOc= github.com/writeas/go-writeas v1.1.0 h1:WHGm6wriBkxYAOGbvriXH8DlMUGOi6jhSZLUZKQ+4mQ= diff --git a/oauth_generic.go b/oauth_generic.go index ba8b97e..ccf6a0f 100644 --- a/oauth_generic.go +++ b/oauth_generic.go @@ -1,8 +1,20 @@ +/* + * Copyright © 2020-2021 A Bunch Tell LLC and respective authors. + * + * This file is part of WriteFreely. + * + * WriteFreely is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, included + * in the LICENSE file in this source code package. + */ + package writefreely import ( "context" "errors" + "fmt" + "github.com/writeas/web-core/log" "net/http" "net/url" "strings" @@ -118,6 +130,10 @@ func (c genericOauthClient) inspectOauthAccessToken(ctx context.Context, accessT // map each relevant field in inspectResponse to the mapped field from the config var inspectResponse InspectResponse inspectResponse.UserID, _ = genericInterface[c.MapUserID].(string) + if inspectResponse.UserID == "" { + log.Error("[CONFIGURATION ERROR] Generic OAuth provider returned empty UserID value (`%s`).\n Do you need to configure a different `map_user_id` value for this provider?", c.MapUserID) + return nil, fmt.Errorf("no UserID (`%s`) value returned", c.MapUserID) + } inspectResponse.Username, _ = genericInterface[c.MapUsername].(string) inspectResponse.DisplayName, _ = genericInterface[c.MapDisplayName].(string) inspectResponse.Email, _ = genericInterface[c.MapEmail].(string) diff --git a/postrender.go b/postrender.go index 8e71109..13bf02e 100644 --- a/postrender.go +++ b/postrender.go @@ -11,6 +11,7 @@ package writefreely import ( + "bytes" "encoding/json" "fmt" "html" @@ -23,7 +24,7 @@ import ( "unicode/utf8" "github.com/microcosm-cc/bluemonday" - stripmd "github.com/writeas/go-strip-markdown" + stripmd "github.com/writeas/go-strip-markdown/v2" "github.com/writeas/impart" blackfriday "github.com/writeas/saturday" "github.com/writeas/web-core/log" @@ -181,6 +182,10 @@ func applyMarkdownSpecial(data []byte, skipNoFollow bool, baseURL string, cfg *c } func applyBasicMarkdown(data []byte) string { + if len(bytes.TrimSpace(data)) == 0 { + return "" + } + mdExtensions := 0 | blackfriday.EXTENSION_STRIKETHROUGH | blackfriday.EXTENSION_SPACE_HEADERS | @@ -191,7 +196,12 @@ func applyBasicMarkdown(data []byte) string { blackfriday.HTML_SMARTYPANTS_DASHES // Generate Markdown - md := blackfriday.Markdown([]byte(data), blackfriday.HtmlRenderer(htmlFlags, "", ""), mdExtensions) + // This passes the supplied title into blackfriday.Markdown() as an H1 header, so we only render HTML that + // belongs in an H1. + md := blackfriday.Markdown(append([]byte("# "), data...), blackfriday.HtmlRenderer(htmlFlags, "", ""), mdExtensions) + // Remove H1 markup + md = bytes.TrimSpace(md) // blackfriday.Markdown adds a newline at the end of the

+ md = md[len("

") : len(md)-len("

")] // Strip out bad HTML policy := bluemonday.UGCPolicy() policy.AllowAttrs("class", "id").Globally() diff --git a/postrender_test.go b/postrender_test.go new file mode 100644 index 0000000..531c0f1 --- /dev/null +++ b/postrender_test.go @@ -0,0 +1,43 @@ +/* + * Copyright © 2021 A Bunch Tell LLC. + * + * This file is part of WriteFreely. + * + * WriteFreely is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, included + * in the LICENSE file in this source code package. + */ + +package writefreely + +import "testing" + +func TestApplyBasicMarkdown(t *testing.T) { + tests := []struct { + name string + in string + result string + }{ + {"empty", "", ""}, + {"empty spaces", " ", ""}, + {"empty tabs", "\t", ""}, + {"empty newline", "\n", ""}, + {"nums", "123", "123"}, + {"dot", ".", "."}, + {"dash", "-", "-"}, + {"plain", "Hello, World!", "Hello, World!"}, + {"multibyte", "こんにちは", `こんにちは`}, + {"bold", "**안녕하세요**", `안녕하세요`}, + {"link", "[WriteFreely](https://writefreely.org)", `WriteFreely`}, + {"date", "12. April", `12. April`}, + {"table", "| Hi | There |", `| Hi | There |`}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + res := applyBasicMarkdown([]byte(test.in)) + if res != test.result { + t.Errorf("%s: wanted %s, got %s", test.name, test.result, res) + } + }) + } +} diff --git a/posts.go b/posts.go index 4d8d019..dd824a9 100644 --- a/posts.go +++ b/posts.go @@ -26,7 +26,7 @@ import ( "github.com/guregu/null/zero" "github.com/kylemcc/twitter-text-go/extract" "github.com/microcosm-cc/bluemonday" - stripmd "github.com/writeas/go-strip-markdown" + stripmd "github.com/writeas/go-strip-markdown/v2" "github.com/writeas/impart" "github.com/writeas/monday" "github.com/writeas/slug" @@ -234,7 +234,7 @@ func (p Post) Summary() string { } p.Content = stripHTMLWithoutEscaping(p.Content) // and Markdown - p.Content = stripmd.Strip(p.Content) + p.Content = stripmd.StripOptions(p.Content, stripmd.Options{SkipImages: true}) title := p.Title.String var desc string @@ -1461,7 +1461,7 @@ func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error if slug == "feed" { // User tried to access blog feed without a trailing slash, and // there's no post with a slug "feed" - return impart.HTTPError{http.StatusFound, c.CanonicalURL() + "/feed/"} + return impart.HTTPError{http.StatusFound, c.CanonicalURL() + "feed/"} } po := &Post{ diff --git a/prose/prose.js b/prose/prose.js index 3096c9e..ae8b3ce 100644 --- a/prose/prose.js +++ b/prose/prose.js @@ -40,13 +40,7 @@ class ProseMirrorView { $title.value = title; } - const doc = writeFreelyMarkdownParser.parse( - // Replace all "solo" \n's with \\\n for correct markdown parsing - // Can't use lookahead or lookbehind because it's not supported on Safari - content.replace(/([^]{0,1})(\n)([^]{0,1})/g, (match, p1, p2, p3) => { - return p1 !== "\n" && p3 !== "\n" ? p1 + "\\\n" + p3 : match; - }) - ); + const doc = writeFreelyMarkdownParser.parse(content) this.view = new EditorView(target, { state: EditorState.create({ diff --git a/read.go b/read.go index 35a671f..f2706a9 100644 --- a/read.go +++ b/read.go @@ -21,7 +21,7 @@ import ( . "github.com/gorilla/feeds" "github.com/gorilla/mux" - stripmd "github.com/writeas/go-strip-markdown" + stripmd "github.com/writeas/go-strip-markdown/v2" "github.com/writeas/impart" "github.com/writeas/web-core/log" "github.com/writeas/web-core/memo"