Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fdb854e6c7 | |||
| f934c2917f | |||
| 1bfefdccb3 | |||
| 9ca58bc16c | |||
| 122acf6999 | |||
| f627946c0d | |||
| 5b42685956 | |||
| 90fedf86d9 | |||
| a9a6b51a3f | |||
| 9687f90cf5 | |||
| 5cc93387e7 | |||
| fc57e4d8f3 | |||
| 2bc26c5966 | |||
| f5767db840 | |||
| edf88d1f31 | |||
| 262c3ba903 | |||
| a260d102ee | |||
| 179617d058 | |||
| 5347efb51a | |||
| e3cee5b94c | |||
| e4cf02cde7 | |||
| 06e5b4ddf9 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,3 +8,6 @@ cmd/yatwiki-server/yatwiki-server
|
|||||||
# Development db files
|
# Development db files
|
||||||
cmd/yatwiki-server/*.db
|
cmd/yatwiki-server/*.db
|
||||||
cmd/yatwiki-server/config.json
|
cmd/yatwiki-server/config.json
|
||||||
|
|
||||||
|
# Vendor
|
||||||
|
vendor/
|
||||||
|
|||||||
14
DB.go
14
DB.go
@@ -3,6 +3,7 @@ package yatwiki
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
@@ -91,7 +92,7 @@ func (this *WikiDB) GetRevision(revId int) (*Article, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *WikiDB) GetLatestVersion(title string) (*Article, error) {
|
func (this *WikiDB) GetLatestVersion(title string) (*Article, error) {
|
||||||
row := this.db.QueryRow(`SELECT articles.* FROM articles WHERE article = (SELECT id FROM titles WHERE title = ?) ORDER BY modified DESC LIMIT 1`, title)
|
row := this.db.QueryRow(`SELECT articles.* FROM articles WHERE article = (SELECT id FROM titles WHERE title = ?) ORDER BY modified DESC LIMIT 1`, this.normaliseTitle(title))
|
||||||
return this.parseArticle(row)
|
return this.parseArticle(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +104,10 @@ func (aae ArticleAlteredError) Error() string {
|
|||||||
return fmt.Sprintf("Warning: Your changes were not based on the most recent version of the page (r%d ≠ r%d). No changes were saved.", aae.got, aae.expected)
|
return fmt.Sprintf("Warning: Your changes were not based on the most recent version of the page (r%d ≠ r%d). No changes were saved.", aae.got, aae.expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *WikiDB) normaliseTitle(title string) string {
|
||||||
|
return strings.ToLower(strings.Trim(title, " \r\n\t"))
|
||||||
|
}
|
||||||
|
|
||||||
func (this *WikiDB) SaveArticle(title, author, body string, expectBaseRev int64) error {
|
func (this *WikiDB) SaveArticle(title, author, body string, expectBaseRev int64) error {
|
||||||
isNewArticle := false
|
isNewArticle := false
|
||||||
a, err := this.GetLatestVersion(title)
|
a, err := this.GetLatestVersion(title)
|
||||||
@@ -125,7 +130,7 @@ func (this *WikiDB) SaveArticle(title, author, body string, expectBaseRev int64)
|
|||||||
|
|
||||||
var titleId int64
|
var titleId int64
|
||||||
if isNewArticle {
|
if isNewArticle {
|
||||||
titleInsert, err := this.db.Exec(`INSERT INTO titles (title) VALUES (?)`, title)
|
titleInsert, err := this.db.Exec(`INSERT INTO titles (title) VALUES (?)`, this.normaliseTitle(title))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -147,7 +152,10 @@ func (this *WikiDB) SaveArticle(title, author, body string, expectBaseRev int64)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *WikiDB) GetRevisionHistory(title string) ([]Article, error) {
|
func (this *WikiDB) GetRevisionHistory(title string) ([]Article, error) {
|
||||||
rows, err := this.db.Query(`SELECT articles.id, articles.modified, articles.author FROM articles WHERE article = (SELECT id FROM titles WHERE title = ?) ORDER BY modified DESC`, title)
|
rows, err := this.db.Query(
|
||||||
|
`SELECT articles.id, articles.modified, articles.author FROM articles WHERE article = (SELECT id FROM titles WHERE title = ?) ORDER BY modified DESC`,
|
||||||
|
this.normaliseTitle(title),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
21
Gopkg.lock
generated
Normal file
21
Gopkg.lock
generated
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||||
|
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/mattn/go-sqlite3"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "5160b48509cf5c877bc22c11c373f8c7738cdb38"
|
||||||
|
version = "v1.3.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/net"
|
||||||
|
packages = ["context"]
|
||||||
|
revision = "c73622c77280266305273cb545f54516ced95b93"
|
||||||
|
|
||||||
|
[solve-meta]
|
||||||
|
analyzer-name = "dep"
|
||||||
|
analyzer-version = 1
|
||||||
|
inputs-digest = "a1f2d643f8c1770c92ee1759184a0c7004af5672869db579328d05bb7cfd6bef"
|
||||||
|
solver-name = "gps-cdcl"
|
||||||
|
solver-version = 1
|
||||||
26
Gopkg.toml
Normal file
26
Gopkg.toml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
# Gopkg.toml example
|
||||||
|
#
|
||||||
|
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||||
|
# for detailed Gopkg.toml documentation.
|
||||||
|
#
|
||||||
|
# required = ["github.com/user/thing/cmd/thing"]
|
||||||
|
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project"
|
||||||
|
# version = "1.0.0"
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project2"
|
||||||
|
# branch = "dev"
|
||||||
|
# source = "github.com/myfork/project2"
|
||||||
|
#
|
||||||
|
# [[override]]
|
||||||
|
# name = "github.com/x/y"
|
||||||
|
# version = "2.4.0"
|
||||||
|
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/mattn/go-sqlite3"
|
||||||
|
version = "1.3.0"
|
||||||
21
Makefile
21
Makefile
@@ -2,20 +2,24 @@
|
|||||||
# Makefile for YATWiki3
|
# Makefile for YATWiki3
|
||||||
#
|
#
|
||||||
|
|
||||||
VERSION:=3.0.1
|
VERSION:=3.1.3
|
||||||
|
|
||||||
SOURCES:=Makefile \
|
SOURCES:=Makefile \
|
||||||
static \
|
static \
|
||||||
cmd $(wildcard cmd/yatwiki-server/*.go) \
|
cmd $(wildcard cmd/yatwiki-server/*.go) \
|
||||||
|
Gopkg.lock Gopkg.toml \
|
||||||
$(wildcard *.go)
|
$(wildcard *.go)
|
||||||
|
|
||||||
GOFLAGS := -ldflags='-s -w' -gcflags='-trimpath=$(GOPATH)' -asmflags='-trimpath=$(GOPATH)'
|
GOFLAGS:=-a \
|
||||||
|
-ldflags "-s -w -X code.ivysaur.me/yatwiki.SERVER_HEADER=YATWiki/$(VERSION)" \
|
||||||
|
-gcflags '-trimpath=$(GOPATH)' \
|
||||||
|
-asmflags '-trimpath=$(GOPATH)'
|
||||||
|
|
||||||
#
|
#
|
||||||
# Phony targets
|
# Phony targets
|
||||||
#
|
#
|
||||||
|
|
||||||
.PHONY: all dist clean
|
.PHONY: all dist clean deps
|
||||||
|
|
||||||
all: build/linux64/yatwiki-server build/win32/yatwiki-server.exe
|
all: build/linux64/yatwiki-server build/win32/yatwiki-server.exe
|
||||||
|
|
||||||
@@ -25,9 +29,14 @@ dist: \
|
|||||||
_dist/yatwiki-$(VERSION)-src.zip
|
_dist/yatwiki-$(VERSION)-src.zip
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
if [ -f ./staticResources.go ] ; then rm ./staticResources.go ; fi
|
rm -f ./staticResources.go
|
||||||
if [ -d ./build ] ; then rm -r ./build ; fi
|
rm -fr ./build
|
||||||
if [ -f ./yatwiki ] ; then rm ./yatwiki ; fi
|
rm -f ./yatwiki
|
||||||
|
|
||||||
|
deps:
|
||||||
|
go get -u github.com/jteeuwen/go-bindata/...
|
||||||
|
go get -u github.com/golang/dep/cmd/dep
|
||||||
|
dep ensure
|
||||||
|
|
||||||
#
|
#
|
||||||
# Generated files
|
# Generated files
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type ServerOptions struct {
|
|||||||
ExternalBaseURL string
|
ExternalBaseURL string
|
||||||
DeclareRSSLanguage string
|
DeclareRSSLanguage string
|
||||||
DeclareRSSEmail string
|
DeclareRSSEmail string
|
||||||
|
ContentedServer string
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultOptions() *ServerOptions {
|
func DefaultOptions() *ServerOptions {
|
||||||
@@ -41,5 +42,6 @@ func DefaultOptions() *ServerOptions {
|
|||||||
ExternalBaseURL: "http://127.0.0.1/",
|
ExternalBaseURL: "http://127.0.0.1/",
|
||||||
DeclareRSSLanguage: "en-GB",
|
DeclareRSSLanguage: "en-GB",
|
||||||
DeclareRSSEmail: `nobody@example.com`,
|
DeclareRSSEmail: `nobody@example.com`,
|
||||||
|
ContentedServer: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var SERVER_HEADER string = "YATWiki/0.0.0-devel"
|
||||||
|
|
||||||
type WikiServer struct {
|
type WikiServer struct {
|
||||||
db *WikiDB
|
db *WikiDB
|
||||||
opts *ServerOptions
|
opts *ServerOptions
|
||||||
@@ -79,7 +81,7 @@ func (this *WikiServer) Close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Server", "YATWiki3")
|
w.Header().Set("Server", SERVER_HEADER)
|
||||||
|
|
||||||
if len(this.bans) > 0 {
|
if len(this.bans) > 0 {
|
||||||
remoteIP := RemoteAddrToIPAddress(r.RemoteAddr)
|
remoteIP := RemoteAddrToIPAddress(r.RemoteAddr)
|
||||||
@@ -110,9 +112,13 @@ func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write(content)
|
w.Write(content)
|
||||||
return
|
return
|
||||||
|
|
||||||
} else if remainingPath == "favicon.ico" && len(this.opts.FaviconFilePath) > 0 {
|
} else if remainingPath == "favicon.ico" {
|
||||||
|
if len(this.opts.FaviconFilePath) > 0 {
|
||||||
w.Header().Set("Content-Type", "image/x-icon")
|
w.Header().Set("Content-Type", "image/x-icon")
|
||||||
http.ServeFile(w, r, this.opts.FaviconFilePath)
|
http.ServeFile(w, r, this.opts.FaviconFilePath)
|
||||||
|
} else {
|
||||||
|
http.Error(w, "Not found", 404)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
} else if remainingPath == "download-database" {
|
} else if remainingPath == "download-database" {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
A semi-anonymous wiki for use in trusted environments.
|
A semi-anonymous wiki for use in trusted environments.
|
||||||
|
|
||||||
As of the 20150901 release, a desktop version is available for Windows (based on PHPDesktop).
|
For the 20150901 release, a desktop version is available for Windows (based on PHPDesktop).
|
||||||
|
|
||||||
As of the 3.0 release, YATWiki is now a standalone server instead of a PHP script.
|
As of the 3.0 release, YATWiki is now a standalone server instead of a PHP script.
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ As of the 3.0 release, YATWiki is now a standalone server instead of a PHP scrip
|
|||||||
- IP-based ban system
|
- IP-based ban system
|
||||||
- Article index, random article, download database backup
|
- Article index, random article, download database backup
|
||||||
- Source code highlighting (thanks [url=https://github.com/isagalaev/highlight.js]highlight.js[/url])
|
- Source code highlighting (thanks [url=https://github.com/isagalaev/highlight.js]highlight.js[/url])
|
||||||
|
- Optional integration with `contented` for file/image uploads
|
||||||
|
|
||||||
Written in Golang, PHP
|
Written in Golang, PHP
|
||||||
|
|
||||||
@@ -35,6 +36,24 @@ This package can be installed via go get: `go get code.ivysaur.me/yatwiki`
|
|||||||
|
|
||||||
=CHANGELOG=
|
=CHANGELOG=
|
||||||
|
|
||||||
|
2017-10-29 3.1.3
|
||||||
|
- Fix one more case of article title normalisation
|
||||||
|
|
||||||
|
2017-10-29 3.1.2
|
||||||
|
- Lock dependency versions
|
||||||
|
- Enhancement: Advertise build number in Server headers
|
||||||
|
- Fix a regression in 3.x series with not normalising article titles
|
||||||
|
- Fix server response if favicon is not configured
|
||||||
|
|
||||||
|
2017-10-15 3.1.1
|
||||||
|
- Update `contented` integration (requires `contented` >= 1.1.0)
|
||||||
|
|
||||||
|
2017-10-08 3.1.0
|
||||||
|
- Feature: Support content upload to a `contented` server
|
||||||
|
|
||||||
|
2017-08-11 3.0.2
|
||||||
|
- Fix an issue with XSS prevention for web browsers other than Chrome
|
||||||
|
|
||||||
2017-08-11 3.0.1
|
2017-08-11 3.0.1
|
||||||
- Feature: New `TrustXForwardedFor` config option for usage behind reverse proxies
|
- Feature: New `TrustXForwardedFor` config option for usage behind reverse proxies
|
||||||
- Fix an issue with article titles containing `+`
|
- Fix an issue with article titles containing `+`
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.ivysaur.me/yatwiki3/diff"
|
"code.ivysaur.me/yatwiki/diff"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDiff(t *testing.T) {
|
func TestDiff(t *testing.T) {
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ type pageTemplateOptions struct {
|
|||||||
LoadCodeResources bool
|
LoadCodeResources bool
|
||||||
DefaultPage string
|
DefaultPage string
|
||||||
AllowDownload bool
|
AllowDownload bool
|
||||||
SessionMessage template.HTML
|
SessionMessage string
|
||||||
|
PageNotExistsError bool
|
||||||
|
PageNotExistsTarget string
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultPageTemplateOptions(opts *ServerOptions) *pageTemplateOptions {
|
func DefaultPageTemplateOptions(opts *ServerOptions) *pageTemplateOptions {
|
||||||
@@ -105,6 +107,12 @@ function els(e,s){ // no js exec in innerHTML
|
|||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
{{if .PageNotExistsError}}
|
||||||
|
<div class="info">
|
||||||
|
No such article exists.
|
||||||
|
<a href="{{.BaseURL}}modify/{{.PageNotExistsTarget | pathcomponent}}">Click here</a> to create it.
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
{{if len .SessionMessage}}
|
{{if len .SessionMessage}}
|
||||||
<div class="info">{{.SessionMessage}}</div>
|
<div class="info">{{.SessionMessage}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
25
rErrors.go
25
rErrors.go
@@ -8,12 +8,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (this *WikiServer) noSuchArticleError(title string) template.HTML {
|
func (this *WikiServer) serveErrorMessage(w http.ResponseWriter, err error) {
|
||||||
return template.HTML(`No such article exists. <a href="` + this.opts.ExpectBaseURL + `modify/` + template.HTMLEscapeString(url.PathEscape(title)) + `">Click here</a> to create it.`)
|
this.serveErrorText(w, err.Error())
|
||||||
}
|
|
||||||
|
|
||||||
func (this *WikiServer) serveErrorMessage(w http.ResponseWriter, message error) {
|
|
||||||
this.serveErrorHTMLMessage(w, template.HTML(template.HTMLEscapeString(message.Error())))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *WikiServer) serveInternalError(w http.ResponseWriter, r *http.Request, e error) {
|
func (this *WikiServer) serveInternalError(w http.ResponseWriter, r *http.Request, e error) {
|
||||||
@@ -21,8 +17,12 @@ func (this *WikiServer) serveInternalError(w http.ResponseWriter, r *http.Reques
|
|||||||
http.Error(w, "An internal error occurred. Please ask an administrator to check the log file.", 500)
|
http.Error(w, "An internal error occurred. Please ask an administrator to check the log file.", 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *WikiServer) serveErrorHTMLMessage(w http.ResponseWriter, msg template.HTML) {
|
func (this *WikiServer) serveErrorText(w http.ResponseWriter, msg string) {
|
||||||
this.serveRedirect(w, this.opts.ExpectBaseURL+"view/"+url.PathEscape(this.opts.DefaultPage)+"?error="+url.QueryEscape(string(msg)))
|
this.serveRedirect(w, this.opts.ExpectBaseURL+"view/"+url.PathEscape(this.opts.DefaultPage)+"?error="+url.QueryEscape(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *WikiServer) serveNoSuchArticle(w http.ResponseWriter, lookingFor string) {
|
||||||
|
this.serveRedirect(w, this.opts.ExpectBaseURL+"view/"+url.PathEscape(this.opts.DefaultPage)+"?notfound="+url.QueryEscape(lookingFor))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *WikiServer) serveRedirect(w http.ResponseWriter, location string) {
|
func (this *WikiServer) serveRedirect(w http.ResponseWriter, location string) {
|
||||||
@@ -32,7 +32,14 @@ func (this *WikiServer) serveRedirect(w http.ResponseWriter, location string) {
|
|||||||
|
|
||||||
func (this *WikiServer) servePageResponse(w http.ResponseWriter, r *http.Request, pto *pageTemplateOptions) {
|
func (this *WikiServer) servePageResponse(w http.ResponseWriter, r *http.Request, pto *pageTemplateOptions) {
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
pto.SessionMessage = template.HTML(r.URL.Query().Get("error")) // FIXME reflected XSS (although Chrome automatically blocks it..)
|
|
||||||
|
if noSuchArticleTarget, ok := r.URL.Query()["notfound"]; ok {
|
||||||
|
pto.PageNotExistsError = true
|
||||||
|
pto.PageNotExistsTarget = noSuchArticleTarget[0]
|
||||||
|
|
||||||
|
} else {
|
||||||
|
pto.SessionMessage = r.URL.Query().Get("error")
|
||||||
|
}
|
||||||
|
|
||||||
err := this.pageTmp.Execute(w, pto)
|
err := this.pageTmp.Execute(w, pto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func (this *WikiServer) routeHistory(w http.ResponseWriter, r *http.Request, art
|
|||||||
revs, err := this.db.GetRevisionHistory(articleTitle)
|
revs, err := this.db.GetRevisionHistory(articleTitle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle))
|
this.serveNoSuchArticle(w, articleTitle)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ func (this *WikiServer) routeHistory(w http.ResponseWriter, r *http.Request, art
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(revs) == 0 {
|
if len(revs) == 0 {
|
||||||
this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle))
|
this.serveNoSuchArticle(w, articleTitle)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
rModify.go
18
rModify.go
@@ -49,6 +49,24 @@ func (this *WikiServer) routeModify(w http.ResponseWriter, r *http.Request, arti
|
|||||||
</label>
|
</label>
|
||||||
<input type="submit" value="Save »">
|
<input type="submit" value="Save »">
|
||||||
| <a href="` + template.HTMLEscapeString(this.opts.ExpectBaseURL+`formatting`) + `" target="_blank">formatting help</a>
|
| <a href="` + template.HTMLEscapeString(this.opts.ExpectBaseURL+`formatting`) + `" target="_blank">formatting help</a>
|
||||||
|
`
|
||||||
|
if len(this.opts.ContentedServer) > 0 {
|
||||||
|
content += `
|
||||||
|
<script type="text/javascript" src="` + this.opts.ContentedServer + `sdk.js"></script>
|
||||||
|
| <a href="javascript:;" id="open-contented-uploader">upload...</a>
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.getElementById("open-contented-uploader").addEventListener("click", function() {
|
||||||
|
contented.init("#contentctr", function(items) {
|
||||||
|
for (var i = 0; i < items.length; ++i) {
|
||||||
|
$("#contentctr textarea").append(" " + contented.getPreviewURL(items[i]) + " ");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
content += `
|
||||||
</div>
|
</div>
|
||||||
<div id="contentctr"><textarea name="content">` + template.HTMLEscapeString(existingBody) + `</textarea></div>
|
<div id="contentctr"><textarea name="content">` + template.HTMLEscapeString(existingBody) + `</textarea></div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
2
rView.go
2
rView.go
@@ -19,7 +19,7 @@ func (this *WikiServer) routeView(w http.ResponseWriter, r *http.Request, articl
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle))
|
this.serveNoSuchArticle(w, articleTitle)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.serveErrorMessage(w, err)
|
this.serveErrorMessage(w, err)
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user