diff --git a/help/en/recent_changes.myco b/help/en/recent_changes.myco
new file mode 100644
index 0000000..95ecad2
--- /dev/null
+++ b/help/en/recent_changes.myco
@@ -0,0 +1,20 @@
+# Recent changes
+**Recent changes** is a special page that lists all latest changes on the wiki. There is a link to it by default in the [[/help/en/top_bar | top bar]]. You can also jump to it quickly by pressing the `g r` hotkey.
+
+Engaged wiki editors usually visit this page quite often.
+
+=> /recent-changes See this wiki's recent changes
+
+By default, it lists 20 recent changes. On the page, you can choose other number: 50 or 100.
+
+The changes are grouped by date.
+
+Each edit has these properties:
+* **UTC time.**
+* **Commit hash.** It functions as edit's id.
+* **Editor,** if any.
+* **Affected hyphae.** Most actions affect one hypha (such as actual editing), but some affect more (recursive editing, for example).
+* **Message.** This message tells you what the edit is about. The message format is quite regular and parseable.
+
+## See also
+=> /help/en/feeds Feeds
\ No newline at end of file
diff --git a/static/default.css b/static/default.css
index 3a36420..3562d96 100644
--- a/static/default.css
+++ b/static/default.css
@@ -761,4 +761,20 @@ kbd {
.top-bar__section_hidden-on-mobile {
display: none;
}
+}
+
+/*
+ * Help badge
+ */
+.help-topic-badge {
+ display: block;
+ float: right;
+ line-height: 2rem;
+ height: 2rem;
+ width: 2rem;
+ text-align: center;
+ color: inherit;
+ text-decoration: none;
+ border: 1px solid #999;
+ border-radius: 1rem;
}
\ No newline at end of file
diff --git a/views/history.qtpl b/views/history.qtpl
index 4864f42..0c26465 100644
--- a/views/history.qtpl
+++ b/views/history.qtpl
@@ -82,6 +82,7 @@ if err != nil {
{% endfor %}
{% endif %}
+ {%s= helpTopicBadgeHTML("en", "recent_changes") %}
diff --git a/views/history.qtpl.go b/views/history.qtpl.go
index 5780fc3..7a29058 100644
--- a/views/history.qtpl.go
+++ b/views/history.qtpl.go
@@ -260,181 +260,186 @@ func StreamRecentChangesHTML(qw422016 *qt422016.Writer, n int) {
//line views/history.qtpl:84
}
//line views/history.qtpl:84
+ qw422016.N().S(`
+ `)
+//line views/history.qtpl:85
+ qw422016.N().S(helpTopicBadgeHTML("en", "recent_changes"))
+//line views/history.qtpl:85
qw422016.N().S(`
`)
-//line views/history.qtpl:88
+//line views/history.qtpl:89
}
-//line views/history.qtpl:88
+//line views/history.qtpl:89
func WriteRecentChangesHTML(qq422016 qtio422016.Writer, n int) {
-//line views/history.qtpl:88
+//line views/history.qtpl:89
qw422016 := qt422016.AcquireWriter(qq422016)
-//line views/history.qtpl:88
+//line views/history.qtpl:89
StreamRecentChangesHTML(qw422016, n)
-//line views/history.qtpl:88
+//line views/history.qtpl:89
qt422016.ReleaseWriter(qw422016)
-//line views/history.qtpl:88
+//line views/history.qtpl:89
}
-//line views/history.qtpl:88
+//line views/history.qtpl:89
func RecentChangesHTML(n int) string {
-//line views/history.qtpl:88
+//line views/history.qtpl:89
qb422016 := qt422016.AcquireByteBuffer()
-//line views/history.qtpl:88
+//line views/history.qtpl:89
WriteRecentChangesHTML(qb422016, n)
-//line views/history.qtpl:88
+//line views/history.qtpl:89
qs422016 := string(qb422016.B)
-//line views/history.qtpl:88
+//line views/history.qtpl:89
qt422016.ReleaseByteBuffer(qb422016)
-//line views/history.qtpl:88
+//line views/history.qtpl:89
return qs422016
-//line views/history.qtpl:88
+//line views/history.qtpl:89
}
-//line views/history.qtpl:90
+//line views/history.qtpl:91
func streamrecentChangesEntry(qw422016 *qt422016.Writer, rev history.Revision) {
-//line views/history.qtpl:90
+//line views/history.qtpl:91
qw422016.N().S(`
`)
-//line views/history.qtpl:105
+//line views/history.qtpl:106
qw422016.N().S(rev.HyphaeLinksHTML())
-//line views/history.qtpl:105
+//line views/history.qtpl:106
qw422016.N().S(`
`)
-//line views/history.qtpl:108
+//line views/history.qtpl:109
qw422016.E().S(rev.Message)
-//line views/history.qtpl:108
+//line views/history.qtpl:109
qw422016.N().S(`
`)
-//line views/history.qtpl:111
+//line views/history.qtpl:112
}
-//line views/history.qtpl:111
+//line views/history.qtpl:112
func writerecentChangesEntry(qq422016 qtio422016.Writer, rev history.Revision) {
-//line views/history.qtpl:111
+//line views/history.qtpl:112
qw422016 := qt422016.AcquireWriter(qq422016)
-//line views/history.qtpl:111
+//line views/history.qtpl:112
streamrecentChangesEntry(qw422016, rev)
-//line views/history.qtpl:111
+//line views/history.qtpl:112
qt422016.ReleaseWriter(qw422016)
-//line views/history.qtpl:111
+//line views/history.qtpl:112
}
-//line views/history.qtpl:111
+//line views/history.qtpl:112
func recentChangesEntry(rev history.Revision) string {
-//line views/history.qtpl:111
+//line views/history.qtpl:112
qb422016 := qt422016.AcquireByteBuffer()
-//line views/history.qtpl:111
+//line views/history.qtpl:112
writerecentChangesEntry(qb422016, rev)
-//line views/history.qtpl:111
+//line views/history.qtpl:112
qs422016 := string(qb422016.B)
-//line views/history.qtpl:111
+//line views/history.qtpl:112
qt422016.ReleaseByteBuffer(qb422016)
-//line views/history.qtpl:111
+//line views/history.qtpl:112
return qs422016
-//line views/history.qtpl:111
+//line views/history.qtpl:112
}
-//line views/history.qtpl:113
+//line views/history.qtpl:114
func StreamHistoryHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName, list string) {
-//line views/history.qtpl:113
+//line views/history.qtpl:114
qw422016.N().S(`
`)
-//line views/history.qtpl:114
+//line views/history.qtpl:115
StreamNavHTML(qw422016, rq, hyphaName, "history")
-//line views/history.qtpl:114
+//line views/history.qtpl:115
qw422016.N().S(`
History of `)
-//line views/history.qtpl:118
+//line views/history.qtpl:119
qw422016.E().S(util.BeautifulName(hyphaName))
-//line views/history.qtpl:118
+//line views/history.qtpl:119
qw422016.N().S(`
`)
-//line views/history.qtpl:119
+//line views/history.qtpl:120
qw422016.N().S(list)
-//line views/history.qtpl:119
+//line views/history.qtpl:120
qw422016.N().S(`
`)
-//line views/history.qtpl:123
+//line views/history.qtpl:124
}
-//line views/history.qtpl:123
+//line views/history.qtpl:124
func WriteHistoryHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName, list string) {
-//line views/history.qtpl:123
+//line views/history.qtpl:124
qw422016 := qt422016.AcquireWriter(qq422016)
-//line views/history.qtpl:123
+//line views/history.qtpl:124
StreamHistoryHTML(qw422016, rq, hyphaName, list)
-//line views/history.qtpl:123
+//line views/history.qtpl:124
qt422016.ReleaseWriter(qw422016)
-//line views/history.qtpl:123
+//line views/history.qtpl:124
}
-//line views/history.qtpl:123
+//line views/history.qtpl:124
func HistoryHTML(rq *http.Request, hyphaName, list string) string {
-//line views/history.qtpl:123
+//line views/history.qtpl:124
qb422016 := qt422016.AcquireByteBuffer()
-//line views/history.qtpl:123
+//line views/history.qtpl:124
WriteHistoryHTML(qb422016, rq, hyphaName, list)
-//line views/history.qtpl:123
+//line views/history.qtpl:124
qs422016 := string(qb422016.B)
-//line views/history.qtpl:123
+//line views/history.qtpl:124
qt422016.ReleaseByteBuffer(qb422016)
-//line views/history.qtpl:123
+//line views/history.qtpl:124
return qs422016
-//line views/history.qtpl:123
+//line views/history.qtpl:124
}
diff --git a/views/stuff.qtpl b/views/stuff.qtpl
index ca99036..2e5d637 100644
--- a/views/stuff.qtpl
+++ b/views/stuff.qtpl
@@ -155,6 +155,11 @@ It outputs a poorly formatted JSON, but it works and is valid.
...
+ Special pages
+
+
Configuration (for administrators)
- Lock
@@ -167,6 +172,10 @@ It outputs a poorly formatted JSON, but it works and is valid.
{% endfunc %}
+{% func helpTopicBadgeHTML(lang, topic string) %}
+?
+{% endfunc %}
+
{% func UserListHTML() %}
diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go
index 4289608..c8969ff 100644
--- a/views/stuff.qtpl.go
+++ b/views/stuff.qtpl.go
@@ -504,6 +504,11 @@ func streamhelpTopicsHTML(qw422016 *qt422016.Writer) {
- ...
+ - Special pages
+
+
- Configuration (for administrators)
- Lock
@@ -515,44 +520,87 @@ func streamhelpTopicsHTML(qw422016 *qt422016.Writer) {
`)
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
}
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
func writehelpTopicsHTML(qq422016 qtio422016.Writer) {
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
qw422016 := qt422016.AcquireWriter(qq422016)
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
streamhelpTopicsHTML(qw422016)
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
qt422016.ReleaseWriter(qw422016)
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
}
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
func helpTopicsHTML() string {
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
qb422016 := qt422016.AcquireByteBuffer()
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
writehelpTopicsHTML(qb422016)
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
qs422016 := string(qb422016.B)
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
qt422016.ReleaseByteBuffer(qb422016)
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
return qs422016
-//line views/stuff.qtpl:168
+//line views/stuff.qtpl:173
}
-//line views/stuff.qtpl:170
+//line views/stuff.qtpl:175
+func streamhelpTopicBadgeHTML(qw422016 *qt422016.Writer, lang, topic string) {
+//line views/stuff.qtpl:175
+ qw422016.N().S(`
+?
+`)
+//line views/stuff.qtpl:177
+}
+
+//line views/stuff.qtpl:177
+func writehelpTopicBadgeHTML(qq422016 qtio422016.Writer, lang, topic string) {
+//line views/stuff.qtpl:177
+ qw422016 := qt422016.AcquireWriter(qq422016)
+//line views/stuff.qtpl:177
+ streamhelpTopicBadgeHTML(qw422016, lang, topic)
+//line views/stuff.qtpl:177
+ qt422016.ReleaseWriter(qw422016)
+//line views/stuff.qtpl:177
+}
+
+//line views/stuff.qtpl:177
+func helpTopicBadgeHTML(lang, topic string) string {
+//line views/stuff.qtpl:177
+ qb422016 := qt422016.AcquireByteBuffer()
+//line views/stuff.qtpl:177
+ writehelpTopicBadgeHTML(qb422016, lang, topic)
+//line views/stuff.qtpl:177
+ qs422016 := string(qb422016.B)
+//line views/stuff.qtpl:177
+ qt422016.ReleaseByteBuffer(qb422016)
+//line views/stuff.qtpl:177
+ return qs422016
+//line views/stuff.qtpl:177
+}
+
+//line views/stuff.qtpl:179
func StreamUserListHTML(qw422016 *qt422016.Writer) {
-//line views/stuff.qtpl:170
+//line views/stuff.qtpl:179
qw422016.N().S(`
List of users
`)
-//line views/stuff.qtpl:175
+//line views/stuff.qtpl:184
var (
admins = make([]string, 0)
moderators = make([]string, 0)
@@ -569,345 +617,345 @@ func StreamUserListHTML(qw422016 *qt422016.Writer) {
}
}
-//line views/stuff.qtpl:190
+//line views/stuff.qtpl:199
qw422016.N().S(`
`)
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
}
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
func WriteUserListHTML(qq422016 qtio422016.Writer) {
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
qw422016 := qt422016.AcquireWriter(qq422016)
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
StreamUserListHTML(qw422016)
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
qt422016.ReleaseWriter(qw422016)
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
}
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
func UserListHTML() string {
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
qb422016 := qt422016.AcquireByteBuffer()
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
WriteUserListHTML(qb422016)
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
qs422016 := string(qb422016.B)
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
qt422016.ReleaseByteBuffer(qb422016)
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
return qs422016
-//line views/stuff.qtpl:211
+//line views/stuff.qtpl:220
}
-//line views/stuff.qtpl:213
+//line views/stuff.qtpl:222
func StreamHyphaListHTML(qw422016 *qt422016.Writer) {
-//line views/stuff.qtpl:213
+//line views/stuff.qtpl:222
qw422016.N().S(`
List of hyphae
This wiki has `)
-//line views/stuff.qtpl:217
+//line views/stuff.qtpl:226
qw422016.N().D(hyphae.Count())
-//line views/stuff.qtpl:217
+//line views/stuff.qtpl:226
qw422016.N().S(` hyphae.
`)
-//line views/stuff.qtpl:219
+//line views/stuff.qtpl:228
for h := range hyphae.YieldExistingHyphae() {
-//line views/stuff.qtpl:219
+//line views/stuff.qtpl:228
qw422016.N().S(`
-
`)
-//line views/stuff.qtpl:221
+//line views/stuff.qtpl:230
qw422016.E().S(util.BeautifulName(h.Name))
-//line views/stuff.qtpl:221
+//line views/stuff.qtpl:230
qw422016.N().S(`
`)
-//line views/stuff.qtpl:222
+//line views/stuff.qtpl:231
if h.BinaryPath != "" {
-//line views/stuff.qtpl:222
+//line views/stuff.qtpl:231
qw422016.N().S(`
`)
-//line views/stuff.qtpl:223
+//line views/stuff.qtpl:232
qw422016.E().S(filepath.Ext(h.BinaryPath)[1:])
-//line views/stuff.qtpl:223
+//line views/stuff.qtpl:232
qw422016.N().S(`
`)
-//line views/stuff.qtpl:224
+//line views/stuff.qtpl:233
}
-//line views/stuff.qtpl:224
+//line views/stuff.qtpl:233
qw422016.N().S(`
`)
-//line views/stuff.qtpl:226
+//line views/stuff.qtpl:235
}
-//line views/stuff.qtpl:226
+//line views/stuff.qtpl:235
qw422016.N().S(`
`)
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
}
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
func WriteHyphaListHTML(qq422016 qtio422016.Writer) {
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
qw422016 := qt422016.AcquireWriter(qq422016)
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
StreamHyphaListHTML(qw422016)
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
qt422016.ReleaseWriter(qw422016)
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
}
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
func HyphaListHTML() string {
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
qb422016 := qt422016.AcquireByteBuffer()
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
WriteHyphaListHTML(qb422016)
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
qs422016 := string(qb422016.B)
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
qt422016.ReleaseByteBuffer(qb422016)
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
return qs422016
-//line views/stuff.qtpl:230
+//line views/stuff.qtpl:239
}
-//line views/stuff.qtpl:232
+//line views/stuff.qtpl:241
func StreamAboutHTML(qw422016 *qt422016.Writer) {
-//line views/stuff.qtpl:232
+//line views/stuff.qtpl:241
qw422016.N().S(`
About `)
-//line views/stuff.qtpl:236
+//line views/stuff.qtpl:245
qw422016.E().S(cfg.WikiName)
-//line views/stuff.qtpl:236
+//line views/stuff.qtpl:245
qw422016.N().S(`
See /list for information about hyphae on this wiki.
`)
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
}
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
func WriteAboutHTML(qq422016 qtio422016.Writer) {
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
qw422016 := qt422016.AcquireWriter(qq422016)
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
StreamAboutHTML(qw422016)
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
qt422016.ReleaseWriter(qw422016)
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
}
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
func AboutHTML() string {
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
qb422016 := qt422016.AcquireByteBuffer()
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
WriteAboutHTML(qb422016)
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
qs422016 := string(qb422016.B)
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
qt422016.ReleaseByteBuffer(qb422016)
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
return qs422016
-//line views/stuff.qtpl:254
+//line views/stuff.qtpl:263
}
-//line views/stuff.qtpl:256
+//line views/stuff.qtpl:265
func StreamCommonScripts(qw422016 *qt422016.Writer) {
-//line views/stuff.qtpl:256
+//line views/stuff.qtpl:265
qw422016.N().S(`
`)
-//line views/stuff.qtpl:257
+//line views/stuff.qtpl:266
for _, scriptPath := range cfg.CommonScripts {
-//line views/stuff.qtpl:257
+//line views/stuff.qtpl:266
qw422016.N().S(`
`)
-//line views/stuff.qtpl:259
+//line views/stuff.qtpl:268
}
-//line views/stuff.qtpl:259
+//line views/stuff.qtpl:268
qw422016.N().S(`
`)
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
}
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
func WriteCommonScripts(qq422016 qtio422016.Writer) {
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
qw422016 := qt422016.AcquireWriter(qq422016)
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
StreamCommonScripts(qw422016)
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
qt422016.ReleaseWriter(qw422016)
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
}
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
func CommonScripts() string {
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
qb422016 := qt422016.AcquireByteBuffer()
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
WriteCommonScripts(qb422016)
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
qs422016 := string(qb422016.B)
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
qt422016.ReleaseByteBuffer(qb422016)
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
return qs422016
-//line views/stuff.qtpl:260
+//line views/stuff.qtpl:269
}