---
Changes since v1:
- "You are creating a new hypha" Russian localization fix
I've explored different ways of refactoring the toolbar button code, but
they all looked far worse than the markup in the first version (weird
template functions and map generators, or a run-time template
generator), so I decided to leave it in. It's not actually solvable
using the text/template syntax, which seems to be by design because
templates should be simple and not contain code.
hypview/hypview.go | 64 +++++-
hypview/mutators.qtpl | 123 -----------
hypview/mutators.qtpl.go | 452 ---------------------------------------
hypview/view_edit.html | 104 +++++++++
static/default.css | 2 +-
viewutil/viewutil.go | 7 +-
web/mutators.go | 86 ++++----
7 files changed, 209 insertions(+), 629 deletions(-)
delete mode 100644 hypview/mutators.qtpl
delete mode 100644 hypview/mutators.qtpl.go
create mode 100644 hypview/view_edit.html
diff --git a/hypview/hypview.go b/hypview/hypview.go
index 216aebc..d284c37 100644
--- a/hypview/hypview.go
+++ b/hypview/hypview.go
@@ -2,16 +2,51 @@ package hypview
import (
"embed"
- "github.com/bouncepaw/mycorrhiza/cfg"
- "github.com/bouncepaw/mycorrhiza/viewutil"
+ "html/template"
"log"
"strings"
+
+ "github.com/bouncepaw/mycorrhiza/cfg"
+ "github.com/bouncepaw/mycorrhiza/viewutil"
)
var (
//go:embed *.html
fs embed.FS
ruTranslation = `
+{{define "editing hypha"}}Редактирование {{beautifulName .}}{{end}}
+{{define "editing [[hypha]]"}}Редактирование <a href="/hypha/{{.}}">{{beautifulName .}}</a>{{end}}
+{{define "you're creating a new hypha"}}Вы создаёте новую гифу.{{end}}
+{{define "describe your changes"}}Опишите ваши правки{{end}}
+{{define "save"}}Сохранить{{end}}
+{{define "preview"}}Предпросмотр{{end}}
+{{define "previewing hypha"}}Предпросмотр «{{beautifulName .}}»{{end}}
+{{define "preview tip"}}Заметьте, эта гифа ещё не сохранена. Вот её предпросмотр:{{end}}
+
+{{define "markup"}}Разметка{{end}}
+{{define "link"}}Ссылка{{end}}
+{{define "link title"}}Текст{{end}}
+{{define "heading"}}Заголовок{{end}}
+{{define "bold"}}Жирный{{end}}
+{{define "italic"}}Курсив{{end}}
+{{define "highlight"}}Выделение{{end}}
+{{define "underline"}}Подчеркивание{{end}}
+{{define "mono"}}Моноширинный{{end}}
+{{define "super"}}Надстрочный{{end}}
+{{define "sub"}}Подстрочный{{end}}
+{{define "strike"}}Зачёркнутый{{end}}
+{{define "rocket"}}Ссылка-ракета{{end}}
+{{define "transclude"}}Трансклюзия{{end}}
+{{define "hr"}}Гориз. черта{{end}}
+{{define "code"}}Код-блок{{end}}
+{{define "bullets"}}Маркир. список{{end}}
+{{define "numbers"}}Нумер. список{{end}}
+{{define "mycomarkup help"}}<a href="/help/en/mycomarkup" class="shy-link">Подробнее</a> о микоразметке{{end}}
+{{define "actions"}}Действия{{end}}
+{{define "current date"}}Текущая дата{{end}}
+{{define "current time"}}Текущее время{{end}}
+{{define "selflink"}}Ссылка на вас{{end}}
+
{{define "empty heading"}}Эта гифа не существует{{end}}
{{define "empty no rights"}}У вас нет прав для создания новых гиф. Вы можете:{{end}}
{{define "empty log in"}}Войти в свою учётную запись, если она у вас есть{{end}}
@@ -37,6 +72,7 @@ var (
{{define "leave redirections"}}Оставить перенаправления{{end}}
`
chainNaviTitle viewutil.Chain
+ chainEditHypha viewutil.Chain
chainEmptyHypha viewutil.Chain
chainDeleteHypha viewutil.Chain
chainRenameHypha viewutil.Chain
@@ -44,11 +80,35 @@ var (
func Init() {
chainNaviTitle = viewutil.CopyEnRuWith(fs, "view_navititle.html", "")
+ chainEditHypha = viewutil.CopyEnRuWith(fs, "view_edit.html", ruTranslation)
chainEmptyHypha = viewutil.CopyEnRuWith(fs, "view_empty_hypha.html", ruTranslation)
chainDeleteHypha = viewutil.CopyEnRuWith(fs, "view_delete.html", ruTranslation)
chainRenameHypha = viewutil.CopyEnRuWith(fs, "view_rename.html", ruTranslation)
}
+type editData struct {
+ *viewutil.BaseData
+ HyphaName string
+ IsNew bool
+ Content string
+ Message string
+ Preview template.HTML
+}
+
+func EditHypha(meta viewutil.Meta, hyphaName string, isNew bool, content string, message string, preview template.HTML) {
+ viewutil.ExecutePage(meta, chainEditHypha, editData{
+ BaseData: &viewutil.BaseData{
+ Addr: "/edit/" + hyphaName,
+ EditScripts: cfg.EditScripts,
+ },
+ HyphaName: hyphaName,
+ IsNew: isNew,
+ Content: content,
+ Message: message,
+ Preview: preview,
+ })
+}
+
type deleteRenameData struct {
*viewutil.BaseData
HyphaName string
diff --git a/hypview/mutators.qtpl b/hypview/mutators.qtpl
deleted file mode 100644
index bab477d..0000000
--- a/hypview/mutators.qtpl
@@ -1,123 +0,0 @@
-{% import "fmt" %}
-{% import "net/http" %}
-
-{% import "github.com/bouncepaw/mycorrhiza/cfg" %}
-{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
-{% import "github.com/bouncepaw/mycorrhiza/user" %}
-
-{% func Toolbar(u *user.User, lc *l18n.Localizer) %}
-<aside class="edit-toolbar markup-toolbar layout-card">
- <h2 class="edit-toolbar__title layout-card__title">{%s lc.Get("edit.markup")%}</h2>
- <section class="edit-toolbar__buttons">
- {% for _, el := range []struct{
- class string
- display string
- }{
- {"link", fmt.Sprintf("[[%s]]", lc.Get("edit.link"))},
- {"titlelink", fmt.Sprintf("[[%s | %s]]", lc.Get("edit.link"), lc.Get("edit.link_title"))},
- {"heading1", fmt.Sprintf("= %s", lc.Get("edit.heading"))},
- {"heading2", fmt.Sprintf("== %s", lc.Get("edit.heading"))},
- {"bold", fmt.Sprintf("<b>**%s**</b>", lc.Get("edit.bold"))},
- {"italic", fmt.Sprintf("<i>//%s//</i>", lc.Get("edit.italic"))},
- {"highlighted", fmt.Sprintf("<mark>++%s++</mark>", lc.Get("edit.highlight"))},
- {"underline", fmt.Sprintf("<u>__%s__</u>", lc.Get("edit.underline"))},
- {"monospace", fmt.Sprintf("<code>`%s`</code>", lc.Get("edit.mono"))},
- {"lifted", fmt.Sprintf("<sup>^^%s^^</sup>", lc.Get("edit.super"))}, // inconsistent names: lifted, supertext. How cute ❤️
- {"lowered", fmt.Sprintf("<sub>,,%s,,</sub>", lc.Get("edit.sub"))},
- {"strikethrough", fmt.Sprintf("<strike>~~%s~~</strike>", lc.Get("edit.strike"))},
- {"rocket", "=> " + lc.Get("edit.rocket")},
- {"xcl", "<= " + lc.Get("edit.transclude")},
- {"img", "<code>img {}</code>"},
- {"table", "<code>table {}</code>"},
- {"hr", lc.Get("edit.hr")},
- {"codeblock", lc.Get("edit.code")},
- {"bulletedlist", "* " + lc.Get("edit.bullets")},
- {"numberedlist", "*. " + lc.Get("edit.numbers")},
- } %}
- <button class="btn edit-toolbar__btn edit-toolbar__{%s el.class %}">
- {%s= el.display %}
- </button>
- {% endfor %}
- </section>
- <p class="edit-toolbar__ad">{%s= lc.Get("edit.help", &l18n.Replacements{"link": fmt.Sprintf("<a href=\"/help/en/mycomarkup\" target=\"_blank\" class=\"shy-link\">%s</a>", lc.Get("edit.help_link"))}) %}</p>
-</aside>
-<aside class="edit-toolbar action-toolbar layout-card">
- <h2 class="edit-toolbar__title layout-card__title">{%s lc.Get("edit.actions")%}</h2>
- <section class="edit-toolbar__buttons">
- {% for _, el := range []struct{
- class string
- display string
- }{
- {"date", lc.Get("edit.date")},
- {"time", lc.Get("edit.time")},
- } %}
- <button class="btn edit-toolbar__btn edit-toolbar__{%s el.class %}">
- {%s= el.display %}
- </button>
- {% endfor %}
- {% if u.Group != "anon" %}
- <button class="btn edit-toolbar__btn edit-toolbar__user-link">
- {%s lc.Get("edit.selflink") %}
- </button>
- {% endif %}
- </section>
-</aside>
-<script src="/static/toolbar.js"></script>
-{% endfunc %}
-
-{% func Editor(rq *http.Request, hyphaName, textAreaFill, warning string) %}
-{% code
- lc := l18n.FromRequest(rq)
-%}
-<main class="main-width edit edit_no-preview">
- <form method="post" class="edit-form"
- action="/upload-text/{%s hyphaName %}">
- <h1 class="edit__title">{%s= fmt.Sprintf(lc.Get("edit.title"), beautifulLink(hyphaName)) %}</h1>
- {%s= warning %}
- <textarea name="text" class="edit-form__textarea" autofocus>{%s textAreaFill %}</textarea>
- <p class="edit-form__message-zone">
- <input id="text" type="text" name="message" class="edit-form__message" placeholder="{%s lc.Get("edit.tag") %}" aria-label="{%s lc.Get("edit.tag") %}">
- </p>
- <p class="edit-form__buttons">
- <button type="submit" name="action" class="btn btn_accent edit-form__save" value="Save">{%s lc.Get("edit.save") %}</button>
- <button type="submit" name="action" class="btn edit-form__preview" value="Preview">{%s lc.Get("edit.preview") %}</button>
- <a href="/hypha/{%s hyphaName %}" class="btn btn_weak">{%s lc.Get("ui.cancel") %}</a>
- </p>
- </form>
-</main>
-{%s= Toolbar(user.FromRequest(rq), lc) %}
-{%= editScripts() %}
-{% endfunc %}
-
-{% func Preview(rq *http.Request, hyphaName, textAreaFill, message, warning string, renderedPage string) %}
-{% code
- lc := l18n.FromRequest(rq)
-%}
-<main class="main-width edit edit_with-preview">
- <form method="post" class="edit-form"
- action="/upload-text/{%s hyphaName %}">
- <h1 class="edit__title">{%s= fmt.Sprintf(lc.Get("edit.title"), beautifulLink(hyphaName)) %}</h1>
- {%s= warning %}
- <textarea name="text" class="edit-form__textarea" autofocus>{%s textAreaFill %}</textarea>
- <p class="edit-form__message-zone">
- <input id="text" type="text" name="message" class="edit-form__message" placeholder="{%s lc.Get("edit.tag") %}" aria-label="{%s lc.Get("edit.tag") %}">
- </p>
- <p class="edit-form__buttons">
- <button type="submit" name="action" class="btn btn_accent edit-form__save" value="Save">{%s lc.Get("edit.save") %}</button>
- <button type="submit" name="action" class="btn edit-form__preview" value="Preview">{%s lc.Get("edit.preview") %}</button>
- <a href="/hypha/{%s hyphaName %}" class="btn btn_weak">{%s lc.Get("ui.cancel") %}</a>
- </p>
- </form>
- <p class="warning">{%s lc.Get("edit.preview_tip") %}</p>
- <article class="edit__preview">{%s= renderedPage %}</article>
-</main>
-{%s= Toolbar(user.FromRequest(rq), lc) %}
-{%= editScripts() %}
-{% endfunc %}
-
-{% func editScripts() %}
-<script src="/static/editor.js"></script>
-{% for _, scriptPath := range cfg.EditScripts %}
-<script src="{%s scriptPath %}"></script>
-{% endfor %}
-{% endfunc %}
diff --git a/hypview/mutators.qtpl.go b/hypview/mutators.qtpl.go
deleted file mode 100644
index 1200c9c..0000000
--- a/hypview/mutators.qtpl.go
@@ -1,452 +0,0 @@
-// Code generated by qtc from "mutators.qtpl". DO NOT EDIT.
-// See https://github.com/valyala/quicktemplate for details.
-
-//line hypview/mutators.qtpl:1
-package hypview
-
-//line hypview/mutators.qtpl:1
-import "fmt"
-
-//line hypview/mutators.qtpl:2
-import "net/http"
-
-//line hypview/mutators.qtpl:4
-import "github.com/bouncepaw/mycorrhiza/cfg"
-
-//line hypview/mutators.qtpl:5
-import "github.com/bouncepaw/mycorrhiza/l18n"
-
-//line hypview/mutators.qtpl:6
-import "github.com/bouncepaw/mycorrhiza/user"
-
-//line hypview/mutators.qtpl:8
-import (
- qtio422016 "io"
-
- qt422016 "github.com/valyala/quicktemplate"
-)
-
-//line hypview/mutators.qtpl:8
-var (
- _ = qtio422016.Copy
- _ = qt422016.AcquireByteBuffer
-)
-
-//line hypview/mutators.qtpl:8
-func StreamToolbar(qw422016 *qt422016.Writer, u *user.User, lc *l18n.Localizer) {
-//line hypview/mutators.qtpl:8
- qw422016.N().S(`
-<aside class="edit-toolbar markup-toolbar layout-card">
- <h2 class="edit-toolbar__title layout-card__title">`)
-//line hypview/mutators.qtpl:10
- qw422016.E().S(lc.Get("edit.markup"))
-//line hypview/mutators.qtpl:10
- qw422016.N().S(`</h2>
- <section class="edit-toolbar__buttons">
- `)
-//line hypview/mutators.qtpl:12
- for _, el := range []struct {
- class string
- display string
- }{
- {"link", fmt.Sprintf("[[%s]]", lc.Get("edit.link"))},
- {"titlelink", fmt.Sprintf("[[%s | %s]]", lc.Get("edit.link"), lc.Get("edit.link_title"))},
- {"heading1", fmt.Sprintf("= %s", lc.Get("edit.heading"))},
- {"heading2", fmt.Sprintf("== %s", lc.Get("edit.heading"))},
- {"bold", fmt.Sprintf("<b>**%s**</b>", lc.Get("edit.bold"))},
- {"italic", fmt.Sprintf("<i>//%s//</i>", lc.Get("edit.italic"))},
- {"highlighted", fmt.Sprintf("<mark>++%s++</mark>", lc.Get("edit.highlight"))},
- {"underline", fmt.Sprintf("<u>__%s__</u>", lc.Get("edit.underline"))},
- {"monospace", fmt.Sprintf("<code>`%s`</code>", lc.Get("edit.mono"))},
- {"lifted", fmt.Sprintf("<sup>^^%s^^</sup>", lc.Get("edit.super"))}, // inconsistent names: lifted, supertext. How cute ❤️
- {"lowered", fmt.Sprintf("<sub>,,%s,,</sub>", lc.Get("edit.sub"))},
- {"strikethrough", fmt.Sprintf("<strike>~~%s~~</strike>", lc.Get("edit.strike"))},
- {"rocket", "=> " + lc.Get("edit.rocket")},
- {"xcl", "<= " + lc.Get("edit.transclude")},
- {"img", "<code>img {}</code>"},
- {"table", "<code>table {}</code>"},
- {"hr", lc.Get("edit.hr")},
- {"codeblock", lc.Get("edit.code")},
- {"bulletedlist", "* " + lc.Get("edit.bullets")},
- {"numberedlist", "*. " + lc.Get("edit.numbers")},
- } {
-//line hypview/mutators.qtpl:36
- qw422016.N().S(`
- <button class="btn edit-toolbar__btn edit-toolbar__`)
-//line hypview/mutators.qtpl:37
- qw422016.E().S(el.class)
-//line hypview/mutators.qtpl:37
- qw422016.N().S(`">
- `)
-//line hypview/mutators.qtpl:38
- qw422016.N().S(el.display)
-//line hypview/mutators.qtpl:38
- qw422016.N().S(`
- </button>
- `)
-//line hypview/mutators.qtpl:40
- }
-//line hypview/mutators.qtpl:40
- qw422016.N().S(`
- </section>
- <p class="edit-toolbar__ad">`)
-//line hypview/mutators.qtpl:42
- qw422016.N().S(lc.Get("edit.help", &l18n.Replacements{"link": fmt.Sprintf("<a href=\"/help/en/mycomarkup\" target=\"_blank\" class=\"shy-link\">%s</a>", lc.Get("edit.help_link"))}))
-//line hypview/mutators.qtpl:42
- qw422016.N().S(`</p>
-</aside>
-<aside class="edit-toolbar action-toolbar layout-card">
- <h2 class="edit-toolbar__title layout-card__title">`)
-//line hypview/mutators.qtpl:45
- qw422016.E().S(lc.Get("edit.actions"))
-//line hypview/mutators.qtpl:45
- qw422016.N().S(`</h2>
- <section class="edit-toolbar__buttons">
- `)
-//line hypview/mutators.qtpl:47
- for _, el := range []struct {
- class string
- display string
- }{
- {"date", lc.Get("edit.date")},
- {"time", lc.Get("edit.time")},
- } {
-//line hypview/mutators.qtpl:53
- qw422016.N().S(`
- <button class="btn edit-toolbar__btn edit-toolbar__`)
-//line hypview/mutators.qtpl:54
- qw422016.E().S(el.class)
-//line hypview/mutators.qtpl:54
- qw422016.N().S(`">
- `)
-//line hypview/mutators.qtpl:55
- qw422016.N().S(el.display)
-//line hypview/mutators.qtpl:55
- qw422016.N().S(`
- </button>
- `)
-//line hypview/mutators.qtpl:57
- }
-//line hypview/mutators.qtpl:57
- qw422016.N().S(`
- `)
-//line hypview/mutators.qtpl:58
- if u.Group != "anon" {
-//line hypview/mutators.qtpl:58
- qw422016.N().S(`
- <button class="btn edit-toolbar__btn edit-toolbar__user-link">
- `)
-//line hypview/mutators.qtpl:60
- qw422016.E().S(lc.Get("edit.selflink"))
-//line hypview/mutators.qtpl:60
- qw422016.N().S(`
- </button>
- `)
-//line hypview/mutators.qtpl:62
- }
-//line hypview/mutators.qtpl:62
- qw422016.N().S(`
- </section>
-</aside>
-<script src="/static/toolbar.js"></script>
-`)
-//line hypview/mutators.qtpl:66
-}
-
-//line hypview/mutators.qtpl:66
-func WriteToolbar(qq422016 qtio422016.Writer, u *user.User, lc *l18n.Localizer) {
-//line hypview/mutators.qtpl:66
- qw422016 := qt422016.AcquireWriter(qq422016)
-//line hypview/mutators.qtpl:66
- StreamToolbar(qw422016, u, lc)
-//line hypview/mutators.qtpl:66
- qt422016.ReleaseWriter(qw422016)
-//line hypview/mutators.qtpl:66
-}
-
-//line hypview/mutators.qtpl:66
-func Toolbar(u *user.User, lc *l18n.Localizer) string {
-//line hypview/mutators.qtpl:66
- qb422016 := qt422016.AcquireByteBuffer()
-//line hypview/mutators.qtpl:66
- WriteToolbar(qb422016, u, lc)
-//line hypview/mutators.qtpl:66
- qs422016 := string(qb422016.B)
-//line hypview/mutators.qtpl:66
- qt422016.ReleaseByteBuffer(qb422016)
-//line hypview/mutators.qtpl:66
- return qs422016
-//line hypview/mutators.qtpl:66
-}
-
-//line hypview/mutators.qtpl:68
-func StreamEditor(qw422016 *qt422016.Writer, rq *http.Request, hyphaName, textAreaFill, warning string) {
-//line hypview/mutators.qtpl:68
- qw422016.N().S(`
-`)
-//line hypview/mutators.qtpl:70
- lc := l18n.FromRequest(rq)
-
-//line hypview/mutators.qtpl:71
- qw422016.N().S(`
-<main class="main-width edit edit_no-preview">
- <form method="post" class="edit-form"
- action="/upload-text/`)
-//line hypview/mutators.qtpl:74
- qw422016.E().S(hyphaName)
-//line hypview/mutators.qtpl:74
- qw422016.N().S(`">
- <h1 class="edit__title">`)
-//line hypview/mutators.qtpl:75
- qw422016.N().S(fmt.Sprintf(lc.Get("edit.title"), beautifulLink(hyphaName)))
-//line hypview/mutators.qtpl:75
- qw422016.N().S(`</h1>
- `)
-//line hypview/mutators.qtpl:76
- qw422016.N().S(warning)
-//line hypview/mutators.qtpl:76
- qw422016.N().S(`
- <textarea name="text" class="edit-form__textarea" autofocus>`)
-//line hypview/mutators.qtpl:77
- qw422016.E().S(textAreaFill)
-//line hypview/mutators.qtpl:77
- qw422016.N().S(`</textarea>
- <p class="edit-form__message-zone">
- <input id="text" type="text" name="message" class="edit-form__message" placeholder="`)
-//line hypview/mutators.qtpl:79
- qw422016.E().S(lc.Get("edit.tag"))
-//line hypview/mutators.qtpl:79
- qw422016.N().S(`" aria-label="`)
-//line hypview/mutators.qtpl:79
- qw422016.E().S(lc.Get("edit.tag"))
-//line hypview/mutators.qtpl:79
- qw422016.N().S(`">
- </p>
- <p class="edit-form__buttons">
- <button type="submit" name="action" class="btn btn_accent edit-form__save" value="Save">`)
-//line hypview/mutators.qtpl:82
- qw422016.E().S(lc.Get("edit.save"))
-//line hypview/mutators.qtpl:82
- qw422016.N().S(`</button>
- <button type="submit" name="action" class="btn edit-form__preview" value="Preview">`)
-//line hypview/mutators.qtpl:83
- qw422016.E().S(lc.Get("edit.preview"))
-//line hypview/mutators.qtpl:83
- qw422016.N().S(`</button>
- <a href="/hypha/`)
-//line hypview/mutators.qtpl:84
- qw422016.E().S(hyphaName)
-//line hypview/mutators.qtpl:84
- qw422016.N().S(`" class="btn btn_weak">`)
-//line hypview/mutators.qtpl:84
- qw422016.E().S(lc.Get("ui.cancel"))
-//line hypview/mutators.qtpl:84
- qw422016.N().S(`</a>
- </p>
- </form>
-</main>
-`)
-//line hypview/mutators.qtpl:88
- qw422016.N().S(Toolbar(user.FromRequest(rq), lc))
-//line hypview/mutators.qtpl:88
- qw422016.N().S(`
-`)
-//line hypview/mutators.qtpl:89
- streameditScripts(qw422016)
-//line hypview/mutators.qtpl:89
- qw422016.N().S(`
-`)
-//line hypview/mutators.qtpl:90
-}
-
-//line hypview/mutators.qtpl:90
-func WriteEditor(qq422016 qtio422016.Writer, rq *http.Request, hyphaName, textAreaFill, warning string) {
-//line hypview/mutators.qtpl:90
- qw422016 := qt422016.AcquireWriter(qq422016)
-//line hypview/mutators.qtpl:90
- StreamEditor(qw422016, rq, hyphaName, textAreaFill, warning)
-//line hypview/mutators.qtpl:90
- qt422016.ReleaseWriter(qw422016)
-//line hypview/mutators.qtpl:90
-}
-
-//line hypview/mutators.qtpl:90
-func Editor(rq *http.Request, hyphaName, textAreaFill, warning string) string {
-//line hypview/mutators.qtpl:90
- qb422016 := qt422016.AcquireByteBuffer()
-//line hypview/mutators.qtpl:90
- WriteEditor(qb422016, rq, hyphaName, textAreaFill, warning)
-//line hypview/mutators.qtpl:90
- qs422016 := string(qb422016.B)
-//line hypview/mutators.qtpl:90
- qt422016.ReleaseByteBuffer(qb422016)
-//line hypview/mutators.qtpl:90
- return qs422016
-//line hypview/mutators.qtpl:90
-}
-
-//line hypview/mutators.qtpl:92
-func StreamPreview(qw422016 *qt422016.Writer, rq *http.Request, hyphaName, textAreaFill, message, warning string, renderedPage string) {
-//line hypview/mutators.qtpl:92
- qw422016.N().S(`
-`)
-//line hypview/mutators.qtpl:94
- lc := l18n.FromRequest(rq)
-
-//line hypview/mutators.qtpl:95
- qw422016.N().S(`
-<main class="main-width edit edit_with-preview">
- <form method="post" class="edit-form"
- action="/upload-text/`)
-//line hypview/mutators.qtpl:98
- qw422016.E().S(hyphaName)
-//line hypview/mutators.qtpl:98
- qw422016.N().S(`">
- <h1 class="edit__title">`)
-//line hypview/mutators.qtpl:99
- qw422016.N().S(fmt.Sprintf(lc.Get("edit.title"), beautifulLink(hyphaName)))
-//line hypview/mutators.qtpl:99
- qw422016.N().S(`</h1>
- `)
-//line hypview/mutators.qtpl:100
- qw422016.N().S(warning)
-//line hypview/mutators.qtpl:100
- qw422016.N().S(`
- <textarea name="text" class="edit-form__textarea" autofocus>`)
-//line hypview/mutators.qtpl:101
- qw422016.E().S(textAreaFill)
-//line hypview/mutators.qtpl:101
- qw422016.N().S(`</textarea>
- <p class="edit-form__message-zone">
- <input id="text" type="text" name="message" class="edit-form__message" placeholder="`)
-//line hypview/mutators.qtpl:103
- qw422016.E().S(lc.Get("edit.tag"))
-//line hypview/mutators.qtpl:103
- qw422016.N().S(`" aria-label="`)
-//line hypview/mutators.qtpl:103
- qw422016.E().S(lc.Get("edit.tag"))
-//line hypview/mutators.qtpl:103
- qw422016.N().S(`">
- </p>
- <p class="edit-form__buttons">
- <button type="submit" name="action" class="btn btn_accent edit-form__save" value="Save">`)
-//line hypview/mutators.qtpl:106
- qw422016.E().S(lc.Get("edit.save"))
-//line hypview/mutators.qtpl:106
- qw422016.N().S(`</button>
- <button type="submit" name="action" class="btn edit-form__preview" value="Preview">`)
-//line hypview/mutators.qtpl:107
- qw422016.E().S(lc.Get("edit.preview"))
-//line hypview/mutators.qtpl:107
- qw422016.N().S(`</button>
- <a href="/hypha/`)
-//line hypview/mutators.qtpl:108
- qw422016.E().S(hyphaName)
-//line hypview/mutators.qtpl:108
- qw422016.N().S(`" class="btn btn_weak">`)
-//line hypview/mutators.qtpl:108
- qw422016.E().S(lc.Get("ui.cancel"))
-//line hypview/mutators.qtpl:108
- qw422016.N().S(`</a>
- </p>
- </form>
- <p class="warning">`)
-//line hypview/mutators.qtpl:111
- qw422016.E().S(lc.Get("edit.preview_tip"))
-//line hypview/mutators.qtpl:111
- qw422016.N().S(`</p>
- <article class="edit__preview">`)
-//line hypview/mutators.qtpl:112
- qw422016.N().S(renderedPage)
-//line hypview/mutators.qtpl:112
- qw422016.N().S(`</article>
-</main>
-`)
-//line hypview/mutators.qtpl:114
- qw422016.N().S(Toolbar(user.FromRequest(rq), lc))
-//line hypview/mutators.qtpl:114
- qw422016.N().S(`
-`)
-//line hypview/mutators.qtpl:115
- streameditScripts(qw422016)
-//line hypview/mutators.qtpl:115
- qw422016.N().S(`
-`)
-//line hypview/mutators.qtpl:116
-}
-
-//line hypview/mutators.qtpl:116
-func WritePreview(qq422016 qtio422016.Writer, rq *http.Request, hyphaName, textAreaFill, message, warning string, renderedPage string) {
-//line hypview/mutators.qtpl:116
- qw422016 := qt422016.AcquireWriter(qq422016)
-//line hypview/mutators.qtpl:116
- StreamPreview(qw422016, rq, hyphaName, textAreaFill, message, warning, renderedPage)
-//line hypview/mutators.qtpl:116
- qt422016.ReleaseWriter(qw422016)
-//line hypview/mutators.qtpl:116
-}
-
-//line hypview/mutators.qtpl:116
-func Preview(rq *http.Request, hyphaName, textAreaFill, message, warning string, renderedPage string) string {
-//line hypview/mutators.qtpl:116
- qb422016 := qt422016.AcquireByteBuffer()
-//line hypview/mutators.qtpl:116
- WritePreview(qb422016, rq, hyphaName, textAreaFill, message, warning, renderedPage)
-//line hypview/mutators.qtpl:116
- qs422016 := string(qb422016.B)
-//line hypview/mutators.qtpl:116
- qt422016.ReleaseByteBuffer(qb422016)
-//line hypview/mutators.qtpl:116
- return qs422016
-//line hypview/mutators.qtpl:116
-}
-
-//line hypview/mutators.qtpl:118
-func streameditScripts(qw422016 *qt422016.Writer) {
-//line hypview/mutators.qtpl:118
- qw422016.N().S(`
-<script src="/static/editor.js"></script>
-`)
-//line hypview/mutators.qtpl:120
- for _, scriptPath := range cfg.EditScripts {
-//line hypview/mutators.qtpl:120
- qw422016.N().S(`
-<script src="`)
-//line hypview/mutators.qtpl:121
- qw422016.E().S(scriptPath)
-//line hypview/mutators.qtpl:121
- qw422016.N().S(`"></script>
-`)
-//line hypview/mutators.qtpl:122
- }
-//line hypview/mutators.qtpl:122
- qw422016.N().S(`
-`)
-//line hypview/mutators.qtpl:123
-}
-
-//line hypview/mutators.qtpl:123
-func writeeditScripts(qq422016 qtio422016.Writer) {
-//line hypview/mutators.qtpl:123
- qw422016 := qt422016.AcquireWriter(qq422016)
-//line hypview/mutators.qtpl:123
- streameditScripts(qw422016)
-//line hypview/mutators.qtpl:123
- qt422016.ReleaseWriter(qw422016)
-//line hypview/mutators.qtpl:123
-}
-
-//line hypview/mutators.qtpl:123
-func editScripts() string {
-//line hypview/mutators.qtpl:123
- qb422016 := qt422016.AcquireByteBuffer()
-//line hypview/mutators.qtpl:123
- writeeditScripts(qb422016)
-//line hypview/mutators.qtpl:123
- qs422016 := string(qb422016.B)
-//line hypview/mutators.qtpl:123
- qt422016.ReleaseByteBuffer(qb422016)
-//line hypview/mutators.qtpl:123
- return qs422016
-//line hypview/mutators.qtpl:123
-}
diff --git a/hypview/view_edit.html b/hypview/view_edit.html
new file mode 100644
index 0000000..465cdf5
--- /dev/null
+++ b/hypview/view_edit.html
@@ -0,0 +1,104 @@
+{{define "toolbar"}}
+<aside class="edit-toolbar markup-toolbar layout-card">
+ <h2 class="edit-toolbar__title layout-card__title">{{block "markup" .}}Markup{{end}}</h2>
+ <section class="edit-toolbar__buttons">
+ <button class="btn edit-toolbar__btn edit-toolbar__link">[[{{block "link" .}}Link{{end}}]]</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__titlelink">[[{{template "link" .}} | {{block "link title" .}}Title{{end}}]]</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__heading1">= {{block "heading" .}}Heading{{end}}</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__heading2">== {{template "heading" .}}</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__bold"><b>**{{block "bold" .}}Bold{{end}}**</b></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__italic"><i>//{{block "italic" .}}Italic{{end}}//</i></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__highlighted"><mark>++{{block "highlight" .}}Highlight{{end}}++</mark></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__underline"><u>__{{block "underline" .}}Underline{{end}}__</u></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__monospace"><code>`{{block "mono" .}}Monospace{{end}}`</code></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__lifted"><sup>^^{{block "super" .}}Supertext{{end}}^^</sup></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__lowered"><sub>,,{{block "sub" .}}Subtext{{end}},,</sub></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__strikethrough"><s>~~{{block "strike" .}}Strikethrough{{end}}~~</s></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__rocket">=> {{block "rocket" .}}Rocketlink{{end}}</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__xcl"><= {{block "transclude" .}}Transclusion{{end}}</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__img"><code>img {}</code></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__table"><code>table {}</code></button>
+ <button class="btn edit-toolbar__btn edit-toolbar__hr">{{block "hr" .}}Horizontal bar{{end}}</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__codeblock">{{block "code" .}}Code block{{end}}</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__bulletedlist">* {{block "bullets" .}}Bullet list{{end}}</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__numberedlist">*. {{block "numbers" .}}Number list{{end}}</button>
+ </section>
+ <p class="edit-toolbar__help">
+ {{block "mycomarkup help" .}}
+ <a href="/help/en/mycomarkup" target="_blank" class="shy-link">Learn more</a> about mycomarkup
+ {{end}}
+ </p>
+</aside>
+<aside class="edit-toolbar action-toolbar layout-card">
+ <h2 class="edit-toolbar__title layout-card__title">{{block "actions" .}}Actions{{end}}</h2>
+ <section class="edit-toolbar__buttons">
+ <button class="btn edit-toolbar__btn edit-toolbar__date">{{block "current date" .}}Insert current date{{end}}</button>
+ <button class="btn edit-toolbar__btn edit-toolbar__time">{{block "current time" .}}Insert current time{{end}}</button>
+ {{if .Meta.U.Group | ne "anon"}}
+ <button class="btn edit-toolbar__btn edit-toolbar__user-link">{{block "selflink" .}}Link yourself{{end}}</button>
+ {{end}}
+ </section>
+</aside>
+<script src="/static/toolbar.js"></script>
+{{end}}
+
+{{define "editing hypha"}}Edit {{beautifulName .}}{{end}}
+{{define "previewing hypha"}}Preview of {{beautifulName .}}{{end}}
+{{define "title"}}
+{{- if .Preview -}}
+ {{template "previewing hypha" .HyphaName}}
+{{- else -}}
+ {{template "editing hypha" .HyphaName}}
+{{- end -}}
+{{end}}
+{{define "body"}}
+<main class="main-width edit {{if .Preview}}edit_with-preview{{else}}edit_no-preview{{end}}">
+ <form method="post" class="edit-form" action="/upload-text/{{.HyphaName}}">
+ <h1 class="edit__title">
+ {{block "editing [[hypha]]" .HyphaName}}
+ Edit <a href="/hypha/{{.}}">{{beautifulName .}}</a>
+ {{end}}
+ </h1>
+ {{if .IsNew}}
+ <p class="warning warning_new-hypha">
+ {{block "you're creating a new hypha" .}}You are creating a new hypha.{{end}}
+ </p>
+ {{end}}
+ <textarea name="text" class="edit-form__textarea" autofocus>{{.Content}}</textarea>
+ <p class="edit-form__message-zone">
+ <input
+ id="text"
+ type="text"
+ name="message"
+ class="edit-form__message"
+ value="{{.Message}}"
+ placeholder="{{block "describe your changes" .}}Describe your changes{{end}}"
+ aria-label="{{template "describe your changes" .}}">
+ </p>
+ <p class="edit-form__buttons">
+ <button type="submit" name="action" class="btn btn_accent edit-form__save" value="save">
+ {{template "save" .}}
+ </button>
+ <button type="submit" name="action" class="btn edit-form__preview" value="preview">
+ {{block "preview" .}}Preview{{end}}
+ </button>
+ <a href="/hypha/{{.HyphaName}}" class="btn btn_weak">
+ {{template "cancel" .}}
+ </a>
+ </p>
+ </form>
+ {{if .Preview}}
+ <p class="warning">
+ {{block "preview tip" .}}Note that the hypha hasn't been saved yet. Here's the preview:{{end}}
+ </p>
+ <article class="edit__preview">
+ {{.Preview}}
+ </article>
+ {{end}}
+</main>
+{{template "toolbar" .}}
+<script src="/static/editor.js"></script>
+{{range .EditScripts}}
+ <script src="{{.}}"></script>
+{{end}}
+{{end}}
diff --git a/static/default.css b/static/default.css
index 663ca91..548b76f 100644
--- a/static/default.css
+++ b/static/default.css
@@ -99,7 +99,7 @@ textarea {font-size:16px; font-family: inherit; line-height: 150%; }
.edit-form p { margin: .25rem 0; }
.edit-form__message { width: 100%; margin: 0.25em 0; }
.edit-form__save { font-weight: bold; }
-.edit-toolbar__buttons, .edit-toolbar__ad { margin: .5rem; }
+.edit-toolbar__buttons, .edit-toolbar__help { margin: .5rem; }
.edit-form { height: 100%; display: flex; flex-direction: column; }
.icon {margin-right: .25rem; vertical-align: bottom; }
diff --git a/viewutil/viewutil.go b/viewutil/viewutil.go
index 3f61e50..ce29d7c 100644
--- a/viewutil/viewutil.go
+++ b/viewutil/viewutil.go
@@ -4,12 +4,13 @@ package viewutil
import (
"embed"
"fmt"
- "github.com/bouncepaw/mycorrhiza/cfg"
- "github.com/bouncepaw/mycorrhiza/util"
"io/fs"
"log"
"strings"
"text/template" // TODO: save the world
+
+ "github.com/bouncepaw/mycorrhiza/cfg"
+ "github.com/bouncepaw/mycorrhiza/util"
)
var (
@@ -95,6 +96,7 @@ type BaseData struct {
HeadElements []string
HeaderLinks []HeaderLink
CommonScripts []string
+ EditScripts []string
Addr string
Title string // TODO: remove
Body string // TODO: remove
@@ -119,6 +121,7 @@ func Base(meta Meta, title, body string, bodyAttributes map[string]string, headE
HeadElements: headElements,
HeaderLinks: HeaderLinks,
CommonScripts: cfg.CommonScripts,
+ EditScripts: cfg.EditScripts,
Body: body,
BodyAttributes: bodyAttributes,
})
diff --git a/web/mutators.go b/web/mutators.go
index e018891..89dac0c 100644
--- a/web/mutators.go
+++ b/web/mutators.go
@@ -2,12 +2,15 @@ package web
import (
"fmt"
+ "html/template"
+ "log"
+ "net/http"
+
"github.com/bouncepaw/mycomarkup/v5"
+
"github.com/bouncepaw/mycorrhiza/hypview"
"github.com/bouncepaw/mycorrhiza/mycoopts"
"github.com/bouncepaw/mycorrhiza/viewutil"
- "log"
- "net/http"
"github.com/bouncepaw/mycomarkup/v5/mycocontext"
@@ -148,80 +151,65 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) {
func handlerEdit(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
var (
- hyphaName = util.HyphaNameFromRq(rq, "edit")
- h = hyphae.ByName(hyphaName)
- warning string
- textAreaFill string
- err error
- u = user.FromRequest(rq)
- lc = l18n.FromRequest(rq)
- meta = viewutil.MetaFrom(w, rq)
+ u = user.FromRequest(rq)
+ lc = l18n.FromRequest(rq)
+ meta = viewutil.MetaFrom(w, rq)
+
+ hyphaName = util.HyphaNameFromRq(rq, "edit")
+ h = hyphae.ByName(hyphaName)
+
+ isNew bool
+ content string
+ err error
)
+
if err := shroom.CanEdit(u, h, lc); err != nil {
viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error())
return
}
+
switch h.(type) {
case *hyphae.EmptyHypha:
- warning = fmt.Sprintf(`<p class="warning warning_new-hypha">%s</p>`, lc.Get("edit.new_hypha"))
+ isNew = true
default:
- textAreaFill, err = hyphae.FetchMycomarkupFile(h)
+ content, err = hyphae.FetchMycomarkupFile(h)
if err != nil {
log.Println(err)
viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, lc.Get("ui.error_text_fetch"))
return
}
}
- util.HTTP200Page(
- w,
- viewutil.Base(
- meta,
- fmt.Sprintf(lc.Get("edit.title"), util.BeautifulName(hyphaName)),
- hypview.Editor(rq, hyphaName, textAreaFill, warning),
- map[string]string{}))
+ hypview.EditHypha(meta, hyphaName, isNew, content, "", "")
}
// handlerUploadText uploads a new text part for the hypha.
func handlerUploadText(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
var (
+ u = user.FromRequest(rq)
+ meta = viewutil.MetaFrom(w, rq)
+
hyphaName = util.HyphaNameFromRq(rq, "upload-text")
h = hyphae.ByName(hyphaName)
- textData = rq.PostFormValue("text")
- action = rq.PostFormValue("action")
- message = rq.PostFormValue("message")
- u = user.FromRequest(rq)
- lc = l18n.FromRequest(rq)
- meta = viewutil.MetaFrom(w, rq)
- )
+ _, isNew = h.(*hyphae.EmptyHypha)
- if action != "Preview" {
- if err := shroom.UploadText(h, []byte(textData), message, u); err != nil {
- viewutil.HttpErr(meta, http.StatusForbidden, hyphaName, err.Error())
- return
- }
- }
+ textData = rq.PostFormValue("text")
+ action = rq.PostFormValue("action")
+ message = rq.PostFormValue("message")
+ )
- if action == "Preview" {
+ if action == "preview" {
ctx, _ := mycocontext.ContextFromStringInput(textData, mycoopts.MarkupOptions(hyphaName))
+ preview := template.HTML(mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx)))
+ hypview.EditHypha(meta, hyphaName, isNew, textData, message, preview)
+ return
+ }
- util.HTTP200Page(
- w,
- viewutil.Base(
- meta,
- fmt.Sprintf(lc.Get("edit.preview_title"), util.BeautifulName(hyphaName)),
- hypview.Preview(
- rq,
- hyphaName,
- textData,
- message,
- "",
- mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx))),
- map[string]string{},
- ))
- } else {
- http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther)
+ if err := shroom.UploadText(h, []byte(textData), message, u); err != nil {
+ viewutil.HttpErr(meta, http.StatusForbidden, hyphaName, err.Error())
+ return
}
+ http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther)
}
// handlerUploadBinary uploads a new media for the hypha.
--
2.32.1 (Apple Git-133)