@@ -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 | |||
@@ -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) | |||
@@ -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 | |||
@@ -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} | |||
} | |||
@@ -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" | |||
) | |||
@@ -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 | |||
@@ -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= | |||
@@ -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) | |||
@@ -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 <h1> | |||
md = md[len("<h1>") : len(md)-len("</h1>")] | |||
// Strip out bad HTML | |||
policy := bluemonday.UGCPolicy() | |||
policy.AllowAttrs("class", "id").Globally() | |||
@@ -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", "**안녕하세요**", `<strong>안녕하세요</strong>`}, | |||
{"link", "[WriteFreely](https://writefreely.org)", `<a href="https://writefreely.org" rel="nofollow">WriteFreely</a>`}, | |||
{"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) | |||
} | |||
}) | |||
} | |||
} |
@@ -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{ | |||
@@ -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({ | |||
@@ -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" | |||