Megarefactoring of hypha views
This commit is contained in:
parent
68a7573764
commit
ea1ae0d078
@ -2,12 +2,13 @@ package hypview
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"github.com/bouncepaw/mycorrhiza/internal/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/internal/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
"html/template"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/internal/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/internal/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@ -1,50 +0,0 @@
|
||||
{% import "github.com/bouncepaw/mycorrhiza/internal/backlinks" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/internal/cfg" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/internal/hyphae" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/internal/user" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/util" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/web/viewutil" %}
|
||||
|
||||
{% func hyphaInfoEntry(h hyphae.Hypha, u *user.User, action string, hasToExist bool, displayText string) %}
|
||||
{% code flag := true %}
|
||||
{% switch h.(type) %}
|
||||
{% case *hyphae.EmptyHypha %}
|
||||
{% code flag = !hasToExist %}
|
||||
{% endswitch %}
|
||||
{% if u.CanProceed(action) && flag %}
|
||||
<li class="hypha-info__entry hypha-info__entry_{%s action %}">
|
||||
<a class="hypha-info__link" href="/{%s action %}/{%s h.CanonicalName() %}">{%s displayText %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func hyphaInfo(meta viewutil.Meta, h hyphae.Hypha) %}
|
||||
{% code
|
||||
u := meta.U
|
||||
lc := meta.Lc
|
||||
backs := backlinks.BacklinksCount(h.CanonicalName())
|
||||
%}
|
||||
<nav class="hypha-info">
|
||||
<ul class="hypha-info__list">
|
||||
{%= hyphaInfoEntry(h, u, "history", false, lc.Get("ui.history_link")) %}
|
||||
{%= hyphaInfoEntry(h, u, "rename", true, lc.Get("ui.rename_link")) %}
|
||||
{%= hyphaInfoEntry(h, u, "delete", true, lc.Get("ui.delete_link")) %}
|
||||
{%= hyphaInfoEntry(h, u, "text", true, lc.Get("ui.text_link")) %}
|
||||
{% switch h := h.(type) %}
|
||||
{% case *hyphae.TextualHypha %}
|
||||
{%= hyphaInfoEntry(h, u, "media", true, lc.Get("ui.media_link_for_textual")) %}
|
||||
{% default %}
|
||||
{%= hyphaInfoEntry(h, u, "media", true, lc.Get("ui.media_link")) %}
|
||||
{% endswitch %}
|
||||
{%= hyphaInfoEntry(h, u, "backlinks", false, lc.GetPlural("ui.backlinks_link", backs)) %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endfunc %}
|
||||
|
||||
{% func commonScripts() %}
|
||||
{% for _, scriptPath := range cfg.CommonScripts %}
|
||||
<script src="{%s scriptPath %}"></script>
|
||||
{% endfor %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func beautifulLink(hyphaName string) %}<a href="/hypha/{%s= hyphaName %}">{%s util.BeautifulName(hyphaName) %}</a>{% endfunc %}
|
||||
@ -1,311 +0,0 @@
|
||||
// Code generated by qtc from "nav.qtpl". DO NOT EDIT.
|
||||
// See https://github.com/valyala/quicktemplate for details.
|
||||
|
||||
//line hypview/nav.qtpl:1
|
||||
package hypview
|
||||
|
||||
//line hypview/nav.qtpl:1
|
||||
import "github.com/bouncepaw/mycorrhiza/internal/backlinks"
|
||||
|
||||
//line hypview/nav.qtpl:2
|
||||
import "github.com/bouncepaw/mycorrhiza/internal/cfg"
|
||||
|
||||
//line hypview/nav.qtpl:3
|
||||
import "github.com/bouncepaw/mycorrhiza/internal/hyphae"
|
||||
|
||||
//line hypview/nav.qtpl:4
|
||||
import "github.com/bouncepaw/mycorrhiza/internal/user"
|
||||
|
||||
//line hypview/nav.qtpl:5
|
||||
import "github.com/bouncepaw/mycorrhiza/util"
|
||||
|
||||
//line hypview/nav.qtpl:6
|
||||
import "github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
|
||||
//line hypview/nav.qtpl:8
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line hypview/nav.qtpl:8
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line hypview/nav.qtpl:8
|
||||
func streamhyphaInfoEntry(qw422016 *qt422016.Writer, h hyphae.Hypha, u *user.User, action string, hasToExist bool, displayText string) {
|
||||
//line hypview/nav.qtpl:8
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:9
|
||||
flag := true
|
||||
|
||||
//line hypview/nav.qtpl:9
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:10
|
||||
switch h.(type) {
|
||||
//line hypview/nav.qtpl:11
|
||||
case *hyphae.EmptyHypha:
|
||||
//line hypview/nav.qtpl:11
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:12
|
||||
flag = !hasToExist
|
||||
|
||||
//line hypview/nav.qtpl:12
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:13
|
||||
}
|
||||
//line hypview/nav.qtpl:13
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:14
|
||||
if u.CanProceed(action) && flag {
|
||||
//line hypview/nav.qtpl:14
|
||||
qw422016.N().S(`
|
||||
<li class="hypha-info__entry hypha-info__entry_`)
|
||||
//line hypview/nav.qtpl:15
|
||||
qw422016.E().S(action)
|
||||
//line hypview/nav.qtpl:15
|
||||
qw422016.N().S(`">
|
||||
<a class="hypha-info__link" href="/`)
|
||||
//line hypview/nav.qtpl:16
|
||||
qw422016.E().S(action)
|
||||
//line hypview/nav.qtpl:16
|
||||
qw422016.N().S(`/`)
|
||||
//line hypview/nav.qtpl:16
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line hypview/nav.qtpl:16
|
||||
qw422016.N().S(`">`)
|
||||
//line hypview/nav.qtpl:16
|
||||
qw422016.E().S(displayText)
|
||||
//line hypview/nav.qtpl:16
|
||||
qw422016.N().S(`</a>
|
||||
</li>
|
||||
`)
|
||||
//line hypview/nav.qtpl:18
|
||||
}
|
||||
//line hypview/nav.qtpl:18
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:19
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:19
|
||||
func writehyphaInfoEntry(qq422016 qtio422016.Writer, h hyphae.Hypha, u *user.User, action string, hasToExist bool, displayText string) {
|
||||
//line hypview/nav.qtpl:19
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line hypview/nav.qtpl:19
|
||||
streamhyphaInfoEntry(qw422016, h, u, action, hasToExist, displayText)
|
||||
//line hypview/nav.qtpl:19
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line hypview/nav.qtpl:19
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:19
|
||||
func hyphaInfoEntry(h hyphae.Hypha, u *user.User, action string, hasToExist bool, displayText string) string {
|
||||
//line hypview/nav.qtpl:19
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line hypview/nav.qtpl:19
|
||||
writehyphaInfoEntry(qb422016, h, u, action, hasToExist, displayText)
|
||||
//line hypview/nav.qtpl:19
|
||||
qs422016 := string(qb422016.B)
|
||||
//line hypview/nav.qtpl:19
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line hypview/nav.qtpl:19
|
||||
return qs422016
|
||||
//line hypview/nav.qtpl:19
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:21
|
||||
func streamhyphaInfo(qw422016 *qt422016.Writer, meta viewutil.Meta, h hyphae.Hypha) {
|
||||
//line hypview/nav.qtpl:21
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:23
|
||||
u := meta.U
|
||||
lc := meta.Lc
|
||||
backs := backlinks.BacklinksCount(h.CanonicalName())
|
||||
|
||||
//line hypview/nav.qtpl:26
|
||||
qw422016.N().S(`
|
||||
<nav class="hypha-info">
|
||||
<ul class="hypha-info__list">
|
||||
`)
|
||||
//line hypview/nav.qtpl:29
|
||||
streamhyphaInfoEntry(qw422016, h, u, "history", false, lc.Get("ui.history_link"))
|
||||
//line hypview/nav.qtpl:29
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:30
|
||||
streamhyphaInfoEntry(qw422016, h, u, "rename", true, lc.Get("ui.rename_link"))
|
||||
//line hypview/nav.qtpl:30
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:31
|
||||
streamhyphaInfoEntry(qw422016, h, u, "delete", true, lc.Get("ui.delete_link"))
|
||||
//line hypview/nav.qtpl:31
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:32
|
||||
streamhyphaInfoEntry(qw422016, h, u, "text", true, lc.Get("ui.text_link"))
|
||||
//line hypview/nav.qtpl:32
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:33
|
||||
switch h := h.(type) {
|
||||
//line hypview/nav.qtpl:34
|
||||
case *hyphae.TextualHypha:
|
||||
//line hypview/nav.qtpl:34
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:35
|
||||
streamhyphaInfoEntry(qw422016, h, u, "media", true, lc.Get("ui.media_link_for_textual"))
|
||||
//line hypview/nav.qtpl:35
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:36
|
||||
default:
|
||||
//line hypview/nav.qtpl:36
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:37
|
||||
streamhyphaInfoEntry(qw422016, h, u, "media", true, lc.Get("ui.media_link"))
|
||||
//line hypview/nav.qtpl:37
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:38
|
||||
}
|
||||
//line hypview/nav.qtpl:38
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:39
|
||||
streamhyphaInfoEntry(qw422016, h, u, "backlinks", false, lc.GetPlural("ui.backlinks_link", backs))
|
||||
//line hypview/nav.qtpl:39
|
||||
qw422016.N().S(`
|
||||
</ul>
|
||||
</nav>
|
||||
`)
|
||||
//line hypview/nav.qtpl:42
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:42
|
||||
func writehyphaInfo(qq422016 qtio422016.Writer, meta viewutil.Meta, h hyphae.Hypha) {
|
||||
//line hypview/nav.qtpl:42
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line hypview/nav.qtpl:42
|
||||
streamhyphaInfo(qw422016, meta, h)
|
||||
//line hypview/nav.qtpl:42
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line hypview/nav.qtpl:42
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:42
|
||||
func hyphaInfo(meta viewutil.Meta, h hyphae.Hypha) string {
|
||||
//line hypview/nav.qtpl:42
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line hypview/nav.qtpl:42
|
||||
writehyphaInfo(qb422016, meta, h)
|
||||
//line hypview/nav.qtpl:42
|
||||
qs422016 := string(qb422016.B)
|
||||
//line hypview/nav.qtpl:42
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line hypview/nav.qtpl:42
|
||||
return qs422016
|
||||
//line hypview/nav.qtpl:42
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:44
|
||||
func streamcommonScripts(qw422016 *qt422016.Writer) {
|
||||
//line hypview/nav.qtpl:44
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:45
|
||||
for _, scriptPath := range cfg.CommonScripts {
|
||||
//line hypview/nav.qtpl:45
|
||||
qw422016.N().S(`
|
||||
<script src="`)
|
||||
//line hypview/nav.qtpl:46
|
||||
qw422016.E().S(scriptPath)
|
||||
//line hypview/nav.qtpl:46
|
||||
qw422016.N().S(`"></script>
|
||||
`)
|
||||
//line hypview/nav.qtpl:47
|
||||
}
|
||||
//line hypview/nav.qtpl:47
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/nav.qtpl:48
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:48
|
||||
func writecommonScripts(qq422016 qtio422016.Writer) {
|
||||
//line hypview/nav.qtpl:48
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line hypview/nav.qtpl:48
|
||||
streamcommonScripts(qw422016)
|
||||
//line hypview/nav.qtpl:48
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line hypview/nav.qtpl:48
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:48
|
||||
func commonScripts() string {
|
||||
//line hypview/nav.qtpl:48
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line hypview/nav.qtpl:48
|
||||
writecommonScripts(qb422016)
|
||||
//line hypview/nav.qtpl:48
|
||||
qs422016 := string(qb422016.B)
|
||||
//line hypview/nav.qtpl:48
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line hypview/nav.qtpl:48
|
||||
return qs422016
|
||||
//line hypview/nav.qtpl:48
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:50
|
||||
func streambeautifulLink(qw422016 *qt422016.Writer, hyphaName string) {
|
||||
//line hypview/nav.qtpl:50
|
||||
qw422016.N().S(`<a href="/hypha/`)
|
||||
//line hypview/nav.qtpl:50
|
||||
qw422016.N().S(hyphaName)
|
||||
//line hypview/nav.qtpl:50
|
||||
qw422016.N().S(`">`)
|
||||
//line hypview/nav.qtpl:50
|
||||
qw422016.E().S(util.BeautifulName(hyphaName))
|
||||
//line hypview/nav.qtpl:50
|
||||
qw422016.N().S(`</a>`)
|
||||
//line hypview/nav.qtpl:50
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:50
|
||||
func writebeautifulLink(qq422016 qtio422016.Writer, hyphaName string) {
|
||||
//line hypview/nav.qtpl:50
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line hypview/nav.qtpl:50
|
||||
streambeautifulLink(qw422016, hyphaName)
|
||||
//line hypview/nav.qtpl:50
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line hypview/nav.qtpl:50
|
||||
}
|
||||
|
||||
//line hypview/nav.qtpl:50
|
||||
func beautifulLink(hyphaName string) string {
|
||||
//line hypview/nav.qtpl:50
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line hypview/nav.qtpl:50
|
||||
writebeautifulLink(qb422016, hyphaName)
|
||||
//line hypview/nav.qtpl:50
|
||||
qs422016 := string(qb422016.B)
|
||||
//line hypview/nav.qtpl:50
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line hypview/nav.qtpl:50
|
||||
return qs422016
|
||||
//line hypview/nav.qtpl:50
|
||||
}
|
||||
@ -1,94 +0,0 @@
|
||||
{% import "net/http" %}
|
||||
{% import "strings" %}
|
||||
{% import "path" %}
|
||||
{% import "os" %}
|
||||
|
||||
{% import "github.com/bouncepaw/mycorrhiza/internal/cfg" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/internal/hyphae" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/internal/mimetype" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/internal/user" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/web/viewutil" %}
|
||||
|
||||
{% func MediaMenu(rq *http.Request, h hyphae.Hypha, u *user.User) %}
|
||||
{% code
|
||||
lc := l18n.FromRequest(rq)
|
||||
%}
|
||||
<main class="main-width media-tab">
|
||||
<h1>{%s= lc.Get("ui.media_title", &l18n.Replacements{"name": beautifulLink(h.CanonicalName())}) %}</h1>
|
||||
{% switch h.(type) %}
|
||||
{% case *hyphae.MediaHypha %}
|
||||
<p class="explanation">{%s lc.Get("ui.media_tip") %} <a href="/help/en/media" class="shy-link">{%s lc.Get("ui.media_what_is") %}</a></p>
|
||||
{% default %}
|
||||
<p class="explanation">{%s lc.Get("ui.media_empty") %} <a href="/help/en/media" class="shy-link">{%s lc.Get("ui.media_what_is") %}</a></p>
|
||||
{% endswitch %}
|
||||
|
||||
<section class="amnt-grid">
|
||||
{% switch h := h.(type) %}
|
||||
{% case *hyphae.MediaHypha %}
|
||||
{% code
|
||||
mime := mimetype.FromExtension(path.Ext(h.MediaFilePath()))
|
||||
fileinfo, err := os.Stat(h.MediaFilePath()) %}
|
||||
{% if err == nil %}
|
||||
<fieldset class="amnt-menu-block">
|
||||
<legend class="modal__title modal__title_small">{%s lc.Get("ui.media_stat") %}</legend>
|
||||
<p class="modal__confirmation-msg"><b>{%s lc.Get("ui.media_stat_size") %}</b> {%s lc.GetPlural64("ui.media_size_value", fileinfo.Size())%}</p>
|
||||
<p><b>{%s lc.Get("ui.media_stat_mime") %}</b> {%s mime %}</p>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
|
||||
{% if strings.HasPrefix(mime, "image/") %}
|
||||
<fieldset class="amnt-menu-block">
|
||||
<legend class="modal__title modal__title_small">{%s lc.Get("ui.media_include") %}</legend>
|
||||
<p class="modal__confirmation-msg">{%s lc.Get("ui.media_include_tip") %}</p>
|
||||
<pre class="codeblock"><code>img { {%s h.CanonicalName() %} }</code></pre>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% endswitch %}
|
||||
|
||||
{% if u.CanProceed("upload-binary") %}
|
||||
<form action="/upload-binary/{%s h.CanonicalName() %}"
|
||||
method="post" enctype="multipart/form-data"
|
||||
class="upload-binary modal amnt-menu-block">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title modal__title_small">{%s lc.Get("ui.media_new") %}</legend>
|
||||
<p class="modal__confirmation-msg">{%s lc.Get("ui.media_new_tip") %}</p>
|
||||
<label for="upload-binary__input"></label>
|
||||
<input type="file" id="upload-binary__input" name="binary">
|
||||
|
||||
<button type="submit" class="btn stick-to-bottom" value="Upload">{%s lc.Get("ui.media_upload")%}</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% switch h := h.(type) %}
|
||||
{% case *hyphae.MediaHypha %}
|
||||
{% if u.CanProceed("remove-media") %}
|
||||
<form action="/remove-media/{%s h.CanonicalName() %}" method="post" class="modal amnt-menu-block" method="POST">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title modal__title_small">{%s lc.Get("ui.media_remove") %}</legend>
|
||||
<p class="modal__confirmation-msg">{%s lc.Get("ui.media_remove_tip") %}</p>
|
||||
<button type="submit" class="btn" value="Remove media">{%s lc.Get("ui.media_remove_button") %}</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endswitch %}
|
||||
|
||||
</section>
|
||||
</main>
|
||||
{% endfunc %}
|
||||
|
||||
|
||||
{% func Revision(meta viewutil.Meta, h hyphae.Hypha, contents, revHash string) %}
|
||||
<main class="main-width">
|
||||
<section>
|
||||
<p>{%s meta.Lc.Get("ui.revision_warning") %} <a href="/rev-text/{%s revHash %}/{%s h.CanonicalName() %}">{%s meta.Lc.Get("ui.revision_link") %}</a></p>
|
||||
{%s= NaviTitle(meta, h.CanonicalName()) %}
|
||||
{%s= contents %}
|
||||
</section>
|
||||
</main>
|
||||
{% for _, scriptPath := range cfg.ViewScripts %}
|
||||
<script src="{%s scriptPath %}"></script>
|
||||
{% endfor %}
|
||||
{% endfunc %}
|
||||
@ -1,382 +0,0 @@
|
||||
// Code generated by qtc from "readers.qtpl". DO NOT EDIT.
|
||||
// See https://github.com/valyala/quicktemplate for details.
|
||||
|
||||
//line hypview/readers.qtpl:1
|
||||
package hypview
|
||||
|
||||
//line hypview/readers.qtpl:1
|
||||
import "net/http"
|
||||
|
||||
//line hypview/readers.qtpl:2
|
||||
import "strings"
|
||||
|
||||
//line hypview/readers.qtpl:3
|
||||
import "path"
|
||||
|
||||
//line hypview/readers.qtpl:4
|
||||
import "os"
|
||||
|
||||
//line hypview/readers.qtpl:6
|
||||
import "github.com/bouncepaw/mycorrhiza/internal/cfg"
|
||||
|
||||
//line hypview/readers.qtpl:7
|
||||
import "github.com/bouncepaw/mycorrhiza/internal/hyphae"
|
||||
|
||||
//line hypview/readers.qtpl:8
|
||||
import "github.com/bouncepaw/mycorrhiza/l18n"
|
||||
|
||||
//line hypview/readers.qtpl:9
|
||||
import "github.com/bouncepaw/mycorrhiza/internal/mimetype"
|
||||
|
||||
//line hypview/readers.qtpl:10
|
||||
import "github.com/bouncepaw/mycorrhiza/internal/user"
|
||||
|
||||
//line hypview/readers.qtpl:11
|
||||
import "github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
|
||||
//line hypview/readers.qtpl:13
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line hypview/readers.qtpl:13
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line hypview/readers.qtpl:13
|
||||
func StreamMediaMenu(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) {
|
||||
//line hypview/readers.qtpl:13
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/readers.qtpl:15
|
||||
lc := l18n.FromRequest(rq)
|
||||
|
||||
//line hypview/readers.qtpl:16
|
||||
qw422016.N().S(`
|
||||
<main class="main-width media-tab">
|
||||
<h1>`)
|
||||
//line hypview/readers.qtpl:18
|
||||
qw422016.N().S(lc.Get("ui.media_title", &l18n.Replacements{"name": beautifulLink(h.CanonicalName())}))
|
||||
//line hypview/readers.qtpl:18
|
||||
qw422016.N().S(`</h1>
|
||||
`)
|
||||
//line hypview/readers.qtpl:19
|
||||
switch h.(type) {
|
||||
//line hypview/readers.qtpl:20
|
||||
case *hyphae.MediaHypha:
|
||||
//line hypview/readers.qtpl:20
|
||||
qw422016.N().S(`
|
||||
<p class="explanation">`)
|
||||
//line hypview/readers.qtpl:21
|
||||
qw422016.E().S(lc.Get("ui.media_tip"))
|
||||
//line hypview/readers.qtpl:21
|
||||
qw422016.N().S(` <a href="/help/en/media" class="shy-link">`)
|
||||
//line hypview/readers.qtpl:21
|
||||
qw422016.E().S(lc.Get("ui.media_what_is"))
|
||||
//line hypview/readers.qtpl:21
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line hypview/readers.qtpl:22
|
||||
default:
|
||||
//line hypview/readers.qtpl:22
|
||||
qw422016.N().S(`
|
||||
<p class="explanation">`)
|
||||
//line hypview/readers.qtpl:23
|
||||
qw422016.E().S(lc.Get("ui.media_empty"))
|
||||
//line hypview/readers.qtpl:23
|
||||
qw422016.N().S(` <a href="/help/en/media" class="shy-link">`)
|
||||
//line hypview/readers.qtpl:23
|
||||
qw422016.E().S(lc.Get("ui.media_what_is"))
|
||||
//line hypview/readers.qtpl:23
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line hypview/readers.qtpl:24
|
||||
}
|
||||
//line hypview/readers.qtpl:24
|
||||
qw422016.N().S(`
|
||||
|
||||
<section class="amnt-grid">
|
||||
`)
|
||||
//line hypview/readers.qtpl:27
|
||||
switch h := h.(type) {
|
||||
//line hypview/readers.qtpl:28
|
||||
case *hyphae.MediaHypha:
|
||||
//line hypview/readers.qtpl:28
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/readers.qtpl:30
|
||||
mime := mimetype.FromExtension(path.Ext(h.MediaFilePath()))
|
||||
fileinfo, err := os.Stat(h.MediaFilePath())
|
||||
|
||||
//line hypview/readers.qtpl:31
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/readers.qtpl:32
|
||||
if err == nil {
|
||||
//line hypview/readers.qtpl:32
|
||||
qw422016.N().S(`
|
||||
<fieldset class="amnt-menu-block">
|
||||
<legend class="modal__title modal__title_small">`)
|
||||
//line hypview/readers.qtpl:34
|
||||
qw422016.E().S(lc.Get("ui.media_stat"))
|
||||
//line hypview/readers.qtpl:34
|
||||
qw422016.N().S(`</legend>
|
||||
<p class="modal__confirmation-msg"><b>`)
|
||||
//line hypview/readers.qtpl:35
|
||||
qw422016.E().S(lc.Get("ui.media_stat_size"))
|
||||
//line hypview/readers.qtpl:35
|
||||
qw422016.N().S(`</b> `)
|
||||
//line hypview/readers.qtpl:35
|
||||
qw422016.E().S(lc.GetPlural64("ui.media_size_value", fileinfo.Size()))
|
||||
//line hypview/readers.qtpl:35
|
||||
qw422016.N().S(`</p>
|
||||
<p><b>`)
|
||||
//line hypview/readers.qtpl:36
|
||||
qw422016.E().S(lc.Get("ui.media_stat_mime"))
|
||||
//line hypview/readers.qtpl:36
|
||||
qw422016.N().S(`</b> `)
|
||||
//line hypview/readers.qtpl:36
|
||||
qw422016.E().S(mime)
|
||||
//line hypview/readers.qtpl:36
|
||||
qw422016.N().S(`</p>
|
||||
</fieldset>
|
||||
`)
|
||||
//line hypview/readers.qtpl:38
|
||||
}
|
||||
//line hypview/readers.qtpl:38
|
||||
qw422016.N().S(`
|
||||
|
||||
`)
|
||||
//line hypview/readers.qtpl:40
|
||||
if strings.HasPrefix(mime, "image/") {
|
||||
//line hypview/readers.qtpl:40
|
||||
qw422016.N().S(`
|
||||
<fieldset class="amnt-menu-block">
|
||||
<legend class="modal__title modal__title_small">`)
|
||||
//line hypview/readers.qtpl:42
|
||||
qw422016.E().S(lc.Get("ui.media_include"))
|
||||
//line hypview/readers.qtpl:42
|
||||
qw422016.N().S(`</legend>
|
||||
<p class="modal__confirmation-msg">`)
|
||||
//line hypview/readers.qtpl:43
|
||||
qw422016.E().S(lc.Get("ui.media_include_tip"))
|
||||
//line hypview/readers.qtpl:43
|
||||
qw422016.N().S(`</p>
|
||||
<pre class="codeblock"><code>img { `)
|
||||
//line hypview/readers.qtpl:44
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line hypview/readers.qtpl:44
|
||||
qw422016.N().S(` }</code></pre>
|
||||
</fieldset>
|
||||
`)
|
||||
//line hypview/readers.qtpl:46
|
||||
}
|
||||
//line hypview/readers.qtpl:46
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/readers.qtpl:47
|
||||
}
|
||||
//line hypview/readers.qtpl:47
|
||||
qw422016.N().S(`
|
||||
|
||||
`)
|
||||
//line hypview/readers.qtpl:49
|
||||
if u.CanProceed("upload-binary") {
|
||||
//line hypview/readers.qtpl:49
|
||||
qw422016.N().S(`
|
||||
<form action="/upload-binary/`)
|
||||
//line hypview/readers.qtpl:50
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line hypview/readers.qtpl:50
|
||||
qw422016.N().S(`"
|
||||
method="post" enctype="multipart/form-data"
|
||||
class="upload-binary modal amnt-menu-block">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title modal__title_small">`)
|
||||
//line hypview/readers.qtpl:54
|
||||
qw422016.E().S(lc.Get("ui.media_new"))
|
||||
//line hypview/readers.qtpl:54
|
||||
qw422016.N().S(`</legend>
|
||||
<p class="modal__confirmation-msg">`)
|
||||
//line hypview/readers.qtpl:55
|
||||
qw422016.E().S(lc.Get("ui.media_new_tip"))
|
||||
//line hypview/readers.qtpl:55
|
||||
qw422016.N().S(`</p>
|
||||
<label for="upload-binary__input"></label>
|
||||
<input type="file" id="upload-binary__input" name="binary">
|
||||
|
||||
<button type="submit" class="btn stick-to-bottom" value="Upload">`)
|
||||
//line hypview/readers.qtpl:59
|
||||
qw422016.E().S(lc.Get("ui.media_upload"))
|
||||
//line hypview/readers.qtpl:59
|
||||
qw422016.N().S(`</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line hypview/readers.qtpl:62
|
||||
}
|
||||
//line hypview/readers.qtpl:62
|
||||
qw422016.N().S(`
|
||||
|
||||
|
||||
`)
|
||||
//line hypview/readers.qtpl:65
|
||||
switch h := h.(type) {
|
||||
//line hypview/readers.qtpl:66
|
||||
case *hyphae.MediaHypha:
|
||||
//line hypview/readers.qtpl:66
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/readers.qtpl:67
|
||||
if u.CanProceed("remove-media") {
|
||||
//line hypview/readers.qtpl:67
|
||||
qw422016.N().S(`
|
||||
<form action="/remove-media/`)
|
||||
//line hypview/readers.qtpl:68
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line hypview/readers.qtpl:68
|
||||
qw422016.N().S(`" method="post" class="modal amnt-menu-block" method="POST">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title modal__title_small">`)
|
||||
//line hypview/readers.qtpl:70
|
||||
qw422016.E().S(lc.Get("ui.media_remove"))
|
||||
//line hypview/readers.qtpl:70
|
||||
qw422016.N().S(`</legend>
|
||||
<p class="modal__confirmation-msg">`)
|
||||
//line hypview/readers.qtpl:71
|
||||
qw422016.E().S(lc.Get("ui.media_remove_tip"))
|
||||
//line hypview/readers.qtpl:71
|
||||
qw422016.N().S(`</p>
|
||||
<button type="submit" class="btn" value="Remove media">`)
|
||||
//line hypview/readers.qtpl:72
|
||||
qw422016.E().S(lc.Get("ui.media_remove_button"))
|
||||
//line hypview/readers.qtpl:72
|
||||
qw422016.N().S(`</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line hypview/readers.qtpl:75
|
||||
}
|
||||
//line hypview/readers.qtpl:75
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/readers.qtpl:76
|
||||
}
|
||||
//line hypview/readers.qtpl:76
|
||||
qw422016.N().S(`
|
||||
|
||||
</section>
|
||||
</main>
|
||||
`)
|
||||
//line hypview/readers.qtpl:80
|
||||
}
|
||||
|
||||
//line hypview/readers.qtpl:80
|
||||
func WriteMediaMenu(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) {
|
||||
//line hypview/readers.qtpl:80
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line hypview/readers.qtpl:80
|
||||
StreamMediaMenu(qw422016, rq, h, u)
|
||||
//line hypview/readers.qtpl:80
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line hypview/readers.qtpl:80
|
||||
}
|
||||
|
||||
//line hypview/readers.qtpl:80
|
||||
func MediaMenu(rq *http.Request, h hyphae.Hypha, u *user.User) string {
|
||||
//line hypview/readers.qtpl:80
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line hypview/readers.qtpl:80
|
||||
WriteMediaMenu(qb422016, rq, h, u)
|
||||
//line hypview/readers.qtpl:80
|
||||
qs422016 := string(qb422016.B)
|
||||
//line hypview/readers.qtpl:80
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line hypview/readers.qtpl:80
|
||||
return qs422016
|
||||
//line hypview/readers.qtpl:80
|
||||
}
|
||||
|
||||
//line hypview/readers.qtpl:83
|
||||
func StreamRevision(qw422016 *qt422016.Writer, meta viewutil.Meta, h hyphae.Hypha, contents, revHash string) {
|
||||
//line hypview/readers.qtpl:83
|
||||
qw422016.N().S(`
|
||||
<main class="main-width">
|
||||
<section>
|
||||
<p>`)
|
||||
//line hypview/readers.qtpl:86
|
||||
qw422016.E().S(meta.Lc.Get("ui.revision_warning"))
|
||||
//line hypview/readers.qtpl:86
|
||||
qw422016.N().S(` <a href="/rev-text/`)
|
||||
//line hypview/readers.qtpl:86
|
||||
qw422016.E().S(revHash)
|
||||
//line hypview/readers.qtpl:86
|
||||
qw422016.N().S(`/`)
|
||||
//line hypview/readers.qtpl:86
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line hypview/readers.qtpl:86
|
||||
qw422016.N().S(`">`)
|
||||
//line hypview/readers.qtpl:86
|
||||
qw422016.E().S(meta.Lc.Get("ui.revision_link"))
|
||||
//line hypview/readers.qtpl:86
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line hypview/readers.qtpl:87
|
||||
qw422016.N().S(NaviTitle(meta, h.CanonicalName()))
|
||||
//line hypview/readers.qtpl:87
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/readers.qtpl:88
|
||||
qw422016.N().S(contents)
|
||||
//line hypview/readers.qtpl:88
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
`)
|
||||
//line hypview/readers.qtpl:91
|
||||
for _, scriptPath := range cfg.ViewScripts {
|
||||
//line hypview/readers.qtpl:91
|
||||
qw422016.N().S(`
|
||||
<script src="`)
|
||||
//line hypview/readers.qtpl:92
|
||||
qw422016.E().S(scriptPath)
|
||||
//line hypview/readers.qtpl:92
|
||||
qw422016.N().S(`"></script>
|
||||
`)
|
||||
//line hypview/readers.qtpl:93
|
||||
}
|
||||
//line hypview/readers.qtpl:93
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line hypview/readers.qtpl:94
|
||||
}
|
||||
|
||||
//line hypview/readers.qtpl:94
|
||||
func WriteRevision(qq422016 qtio422016.Writer, meta viewutil.Meta, h hyphae.Hypha, contents, revHash string) {
|
||||
//line hypview/readers.qtpl:94
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line hypview/readers.qtpl:94
|
||||
StreamRevision(qw422016, meta, h, contents, revHash)
|
||||
//line hypview/readers.qtpl:94
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line hypview/readers.qtpl:94
|
||||
}
|
||||
|
||||
//line hypview/readers.qtpl:94
|
||||
func Revision(meta viewutil.Meta, h hyphae.Hypha, contents, revHash string) string {
|
||||
//line hypview/readers.qtpl:94
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line hypview/readers.qtpl:94
|
||||
WriteRevision(qb422016, meta, h, contents, revHash)
|
||||
//line hypview/readers.qtpl:94
|
||||
qs422016 := string(qb422016.B)
|
||||
//line hypview/readers.qtpl:94
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line hypview/readers.qtpl:94
|
||||
return qs422016
|
||||
//line hypview/readers.qtpl:94
|
||||
}
|
||||
@ -4,18 +4,6 @@
|
||||
"title_search": "Search by title",
|
||||
"admin_panel": "Admin panel",
|
||||
|
||||
"edit_link": "Edit text",
|
||||
"logout_link": "Log out",
|
||||
"history_link": "View history",
|
||||
"rename_link": "Rename",
|
||||
"delete_link": "Delete",
|
||||
"text_link": "View markup",
|
||||
"media_link": "Manage media",
|
||||
"media_link_for_textual": "Turn to media hypha",
|
||||
"backlinks_link": "{{.n}} backlink%s",
|
||||
"backlinks_link+one": "",
|
||||
"backlinks_link+other": "s",
|
||||
|
||||
"subhyphae": "Subhyphae",
|
||||
|
||||
"random_no_hyphae": "There are no hyphae",
|
||||
@ -57,9 +45,9 @@
|
||||
|
||||
"diff_title": "Diff of {{.name}} at {{.rev}}",
|
||||
|
||||
"revision_title": "{{.name}} at {{.rev}}",
|
||||
"revision_warning": "Please note that viewing media is not supported in history for now.",
|
||||
"revision_link": "Get Mycomarkup source of this revision",
|
||||
"revision_title": "",
|
||||
"revision_warning": "",
|
||||
"revision_link": "",
|
||||
"revision_no_text": "This hypha had no text at this revision.",
|
||||
|
||||
"about_title": "About {{.name}}",
|
||||
@ -76,25 +64,6 @@
|
||||
"media_noaudio": "Your browser does not support audio.",
|
||||
"media_noaudio_link": "Download audio",
|
||||
|
||||
"media_title": "Media of {{.name}}",
|
||||
"media_empty": "This hypha has no media, you can upload it here.",
|
||||
"media_tip": "You can manage the hypha's media on this page.",
|
||||
"media_what_is": "What is media?",
|
||||
"media_upload": "Upload",
|
||||
"media_stat": "Stat",
|
||||
"media_stat_size": "File size:",
|
||||
"media_size_value": "{{.n}} byte%s",
|
||||
"media_size_value+one": "",
|
||||
"media_size_value+other": "s",
|
||||
"media_stat_mime": "MIME type:",
|
||||
"media_include": "Include",
|
||||
"media_include_tip": "This media is an image. To include it in a hypha, use a syntax like this:",
|
||||
"media_new": "media",
|
||||
"media_new_tip": "You can upload a new media. Please do not upload too big pictures unless you need to because may not want to wait for big pictures to load.",
|
||||
"media_remove": "Remove media",
|
||||
"media_remove_tip": "Please note that you don't have to remove media before uploading a new media.",
|
||||
"media_remove_button": "Remove media",
|
||||
|
||||
"confirm": "Confirm",
|
||||
"cancel": "Cancel"
|
||||
}
|
||||
|
||||
@ -8,14 +8,14 @@
|
||||
"backlinks_heading": "Обратные ссылки на {{.hypha_link}}",
|
||||
"backlinks_desc": "Ниже перечислены гифы, на которых есть ссылка на эту гифу, трансклюзия этой гифы или эта гифа вставлена как изображение.",
|
||||
|
||||
"edit_link": "Редактировать",
|
||||
"logout_link": "Выйти",
|
||||
"history_link": "История",
|
||||
"rename_link": "Переименовать",
|
||||
"delete_link": "Удалить",
|
||||
"text_link": "Посмотреть разметку",
|
||||
"media_link": "Медиа",
|
||||
"media_link_for_textual": "Превратить в медиа-гифу",
|
||||
"edit_link": "",
|
||||
"logout_link": "",
|
||||
"history_link": "",
|
||||
"rename_link": "",
|
||||
"delete_link": "",
|
||||
"text_link": "",
|
||||
"media_link": "",
|
||||
"media_link_for_textual": "",
|
||||
"backlinks_link": "{{.n}} %s сюда",
|
||||
"backlinks_link+one": "ссылка",
|
||||
"backlinks_link+few": "ссылки",
|
||||
@ -59,9 +59,9 @@
|
||||
"ask_really": "Вы действительно хотите {{.verb}} гифу «{{.name}}»?",
|
||||
"ask_remove_media_verb": "убрать медиа",
|
||||
|
||||
"revision_title": "{{.name}} из {{.rev}}",
|
||||
"revision_warning": "Обратите внимание, просмотр медиа в истории пока что недоступен.",
|
||||
"revision_link": "Посмотреть Микоразметку для этой ревизии",
|
||||
"revision_title": "",
|
||||
"revision_warning": "",
|
||||
"revision_link": "",
|
||||
"revision_no_text": "В этой ревизии гифы не было текста.",
|
||||
|
||||
"about_title": "О {{.name}}",
|
||||
@ -78,26 +78,6 @@
|
||||
"media_noaudio": "Ваш браузер не поддерживает аудио.",
|
||||
"media_noaudio_link": "Скачать аудио",
|
||||
|
||||
"media_title": "Медиа «{{.name}}»",
|
||||
"media_empty": "Эта гифа не имеет медиа, здесь вы можете его загрузить.",
|
||||
"media_tip": "На этой странице вы можете управлять медиа.",
|
||||
"media_what_is": "Что такое медиа?",
|
||||
"media_upload": "Загрузить",
|
||||
"media_stat": "Свойства",
|
||||
"media_stat_size": "Размер файла:",
|
||||
"media_size_value": "{{.n}} %s",
|
||||
"media_size_value+one": "байт",
|
||||
"media_size_value+few": "байта",
|
||||
"media_size_value+many": "байт",
|
||||
"media_stat_mime": "MIME-тип:",
|
||||
"media_include": "Добавление",
|
||||
"media_include_tip": "Это медиа – изображение. Чтобы добавить его в текст гифы, используйте синтаксис ниже:",
|
||||
"media_new": "Прикрепить",
|
||||
"media_new_tip": "Вы можете загрузить новое медиа. Пожалуйста, не загружайте слишком большие изображения без необходимости, чтобы впоследствии не ждать её долгую загрузку.",
|
||||
"media_remove": "Открепить",
|
||||
"media_remove_tip": "Заметьте, чтобы заменить медиа, вам не нужно его перед этим откреплять.",
|
||||
"media_remove_button": "Открепить",
|
||||
|
||||
"confirm": "Применить",
|
||||
"cancel": "Отмена"
|
||||
}
|
||||
|
||||
1
main.go
1
main.go
@ -3,7 +3,6 @@
|
||||
//go:generate go run github.com/valyala/quicktemplate/qtc -dir=history
|
||||
//go:generate go run github.com/valyala/quicktemplate/qtc -dir=mycoopts
|
||||
//go:generate go run github.com/valyala/quicktemplate/qtc -dir=auth
|
||||
//go:generate go run github.com/valyala/quicktemplate/qtc -dir=hypview
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/internal/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
viewutil2 "github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
"github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
"html/template"
|
||||
"strings"
|
||||
)
|
||||
@ -27,6 +27,15 @@ func NewPage(fs embed.FS, russianTranslation map[string]string, tmpls ...string)
|
||||
Funcs(template.FuncMap{
|
||||
"beautifulName": util.BeautifulName,
|
||||
"inc": func(i int) int { return i + 1 },
|
||||
"base": func(hyphaName string) string {
|
||||
parts := strings.Split(hyphaName, "/")
|
||||
return parts[len(parts)-1]
|
||||
},
|
||||
"beautifulLink": func(hyphaName string) template.HTML {
|
||||
return template.HTML(
|
||||
fmt.Sprintf(
|
||||
`<a href="/hypha/%s">%s</a>`, hyphaName, hyphaName))
|
||||
},
|
||||
}).
|
||||
Parse(fmt.Sprintf(`
|
||||
{{define "wiki name"}}%s{{end}}
|
||||
@ -67,6 +76,13 @@ func NewPage(fs embed.FS, russianTranslation map[string]string, tmpls ...string)
|
||||
}
|
||||
|
||||
russianTranslation["search by title"] = "Поиск по названию"
|
||||
russianTranslation["login"] = "Войти"
|
||||
russianTranslation["register"] = "Регистрация"
|
||||
russianTranslation["cancel"] = "Отмена"
|
||||
russianTranslation["categories"] = "Категории"
|
||||
russianTranslation["remove from category title"] = "Убрать гифу из этой категории"
|
||||
russianTranslation["placeholder"] = "Название категории..."
|
||||
russianTranslation["add to category title"] = "Добавить гифу в эту категорию"
|
||||
|
||||
return &Page{
|
||||
TemplateEnglish: en,
|
||||
@ -84,13 +100,13 @@ func translationsIntoTemplates(m map[string]string) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (p *Page) RenderTo(meta viewutil2.Meta, data map[string]any) error {
|
||||
func (p *Page) RenderTo(meta viewutil.Meta, data map[string]any) error {
|
||||
data["Meta"] = meta
|
||||
data["HeadElements"] = meta.HeadElements
|
||||
data["BodyAttributes"] = meta.BodyAttributes
|
||||
data["CommonScripts"] = cfg.CommonScripts
|
||||
data["EditScripts"] = cfg.EditScripts
|
||||
data["HeaderLinks"] = viewutil2.HeaderLinks
|
||||
data["HeaderLinks"] = viewutil.HeaderLinks
|
||||
|
||||
tmpl := p.TemplateEnglish
|
||||
if meta.LocaleIsRussian() {
|
||||
|
||||
169
web/pages.go
169
web/pages.go
@ -11,6 +11,7 @@ var fs embed.FS
|
||||
|
||||
var pageOrphans, pageBacklinks, pageUserList, pageChangePassword *newtmpl.Page
|
||||
var pageHyphaDelete, pageHyphaEdit, pageHyphaEmpty, pageHypha *newtmpl.Page
|
||||
var pageRevision, pageMedia *newtmpl.Page
|
||||
var panelChain, listChain, newUserChain, editUserChain, deleteUserChain viewutil.Chain
|
||||
|
||||
func initPages() {
|
||||
@ -24,32 +25,19 @@ func initPages() {
|
||||
pageOrphans = newtmpl.NewPage(fs, map[string]string{
|
||||
"orphaned hyphae": "Гифы-сироты",
|
||||
"orphan description": "Ниже перечислены гифы без ссылок на них.",
|
||||
}, "views/orphans.html", map[string]string{
|
||||
"orphaned hyphae": "Гифы-сироты",
|
||||
"orphan description": "Ниже перечислены гифы без ссылок на них.",
|
||||
})
|
||||
}, "views/orphans.html")
|
||||
pageBacklinks = newtmpl.NewPage(fs, map[string]string{
|
||||
"backlinks to text": `Обратные ссылки на {{.}}`,
|
||||
"backlinks to link": `Обратные ссылки на <a href="/hypha/{{.}}">{{beautifulName .}}</a>`,
|
||||
"description": `Ниже перечислены гифы, на которых есть ссылка на эту гифу, трансклюзия этой гифы или эта гифа вставлена как изображение.`,
|
||||
}, "views/backlinks.html", map[string]string{
|
||||
"backlinks to text": `Обратные ссылки на {{.}}`,
|
||||
"backlinks to link": `Обратные ссылки на <a href="/hypha/{{.}}">{{beautifulName .}}</a>`,
|
||||
"description": `Ниже перечислены гифы, на которых есть ссылка на эту гифу, трансклюзия этой гифы или эта гифа вставлена как изображение.`,
|
||||
})
|
||||
}, "views/backlinks.html")
|
||||
pageUserList = newtmpl.NewPage(fs, map[string]string{
|
||||
"title": "Список пользователей",
|
||||
"administrators": "Администраторы",
|
||||
"moderators": "Модераторы",
|
||||
"editors": "Редакторы",
|
||||
"readers": "Читатели",
|
||||
}, "views/user-list.html", map[string]string{
|
||||
"title": "Список пользователей",
|
||||
"administrators": "Администраторы",
|
||||
"moderators": "Модераторы",
|
||||
"editors": "Редакторы",
|
||||
"readers": "Читатели",
|
||||
})
|
||||
}, "views/user-list.html")
|
||||
pageChangePassword = newtmpl.NewPage(fs, map[string]string{
|
||||
"change password": "Сменить пароль",
|
||||
"confirm password": "Повторите пароль",
|
||||
@ -57,25 +45,13 @@ func initPages() {
|
||||
"non local password change": "Пароль можно поменять только местным аккаунтам. Telegram-аккаунтам нельзя.",
|
||||
"password": "Пароль",
|
||||
"submit": "Поменять",
|
||||
}, "views/change-password.html", map[string]string{
|
||||
"change password": "Сменить пароль",
|
||||
"confirm password": "Повторите пароль",
|
||||
"current password": "Текущий пароль",
|
||||
"non local password change": "Пароль можно поменять только местным аккаунтам. Telegram-аккаунтам нельзя.",
|
||||
"password": "Пароль",
|
||||
"submit": "Поменять",
|
||||
})
|
||||
}, "views/change-password.html")
|
||||
pageHyphaDelete = newtmpl.NewPage(fs, map[string]string{
|
||||
"delete hypha?": "Удалить {{beautifulName .}}?",
|
||||
"delete [[hypha]]?": "Удалить <a href=\"/hypha/{{.}}\">{{beautifulName .}}</a>?",
|
||||
"want to delete?": "Вы действительно хотите удалить эту гифу?",
|
||||
"delete tip": "Нельзя отменить удаление гифы, но её история останется доступной.",
|
||||
}, "views/hypha-delete.html", map[string]string{
|
||||
"delete hypha?": "Удалить {{beautifulName .}}?",
|
||||
"delete [[hypha]]?": "Удалить <a href=\"/hypha/{{.}}\">{{beautifulName .}}</a>?",
|
||||
"want to delete?": "Вы действительно хотите удалить эту гифу?",
|
||||
"delete tip": "Нельзя отменить удаление гифы, но её история останется доступной.",
|
||||
})
|
||||
}, "views/hypha-delete.html")
|
||||
pageHyphaEdit = newtmpl.NewPage(fs, map[string]string{
|
||||
"editing hypha": `Редактирование {{beautifulName .}}`,
|
||||
"editing [[hypha]]": `Редактирование <a href="/hypha/{{.}}">{{beautifulName .}}</a>`,
|
||||
@ -87,65 +63,45 @@ func initPages() {
|
||||
"previewing hypha": `Предпросмотр «{{beautifulName .}}»`,
|
||||
"preview tip": `Заметьте, эта гифа ещё не сохранена. Вот её предпросмотр:`,
|
||||
|
||||
"markup": `Разметка`,
|
||||
"link": `Ссылка`,
|
||||
"link title": `Текст`,
|
||||
"heading": `Заголовок`,
|
||||
"bold": `Жирный`,
|
||||
"italic": `Курсив`,
|
||||
"highlight": `Выделение`,
|
||||
"underline": `Подчеркивание`,
|
||||
"mono": `Моноширинный`,
|
||||
"super": `Надстрочный`,
|
||||
"sub": `Подстрочный`,
|
||||
"strike": `Зачёркнутый`,
|
||||
"rocket": `Ссылка-ракета`,
|
||||
"transclude": `Трансклюзия`,
|
||||
"hr": `Гориз. черта`,
|
||||
"code": `Код-блок`,
|
||||
"bullets": `Маркир. список`,
|
||||
"numbers": `Нумер. список`,
|
||||
"mycomarkup help": `<a href="/help/en/mycomarkup" class="shy-link">Подробнее</a> о Микоразметке`,
|
||||
"actions": `Действия`,
|
||||
"current date": `Текущая дата`,
|
||||
"current time": `Текущее время`,
|
||||
"selflink": `Ссылка на вас`,
|
||||
}, "views/hypha-edit.html", map[string]string{
|
||||
"editing hypha": `Редактирование {{beautifulName .}}`,
|
||||
"editing [[hypha]]": `Редактирование <a href="/hypha/{{.}}">{{beautifulName .}}</a>`,
|
||||
"creating [[hypha]]": `Создание <a href="/hypha/{{.}}">{{beautifulName .}}</a>`,
|
||||
"you're creating a new hypha": `Вы создаёте новую гифу.`,
|
||||
"describe your changes": `Опишите ваши правки`,
|
||||
"save": `Сохранить`,
|
||||
"preview": `Предпросмотр`,
|
||||
"previewing hypha": `Предпросмотр «{{beautifulName .}}»`,
|
||||
"preview tip": `Заметьте, эта гифа ещё не сохранена. Вот её предпросмотр:`,
|
||||
"markup": `Разметка`,
|
||||
"link": `Ссылка`,
|
||||
"link title": `Текст`,
|
||||
"heading": `Заголовок`,
|
||||
"bold": `Жирный`,
|
||||
"italic": `Курсив`,
|
||||
"highlight": `Выделение`,
|
||||
"underline": `Подчеркивание`,
|
||||
"mono": `Моноширинный`,
|
||||
"super": `Надстрочный`,
|
||||
"sub": `Подстрочный`,
|
||||
"strike": `Зачёркнутый`,
|
||||
"rocket": `Ссылка-ракета`,
|
||||
"transclude": `Трансклюзия`,
|
||||
"hr": `Гориз. черта`,
|
||||
"code": `Код-блок`,
|
||||
"bullets": `Маркир. список`,
|
||||
"numbers": `Нумер. список`,
|
||||
"mycomarkup help": `<a href="/help/en/mycomarkup" class="shy-link">Подробнее</a> о Микоразметке`,
|
||||
"actions": `Действия`,
|
||||
"current date local": `Местная дата`,
|
||||
"current time local": `Местное время`,
|
||||
"current date utc": "Дата UTC",
|
||||
"current time utc": "Время UTC",
|
||||
"selflink": `Ссылка на вас`,
|
||||
}, "views/hypha-edit.html")
|
||||
pageHypha = newtmpl.NewPage(fs, map[string]string{
|
||||
"edit text": "Редактировать",
|
||||
"log out": "Выйти",
|
||||
"admin panel": "Админка",
|
||||
"subhyphae": "Подгифы",
|
||||
"history": "История",
|
||||
"rename": "Переименовать",
|
||||
"delete": "Удалить",
|
||||
"view markup": "Посмотреть разметку",
|
||||
"manage media": "Медиа",
|
||||
"turn to media": "Превратить в медиа-гифу",
|
||||
"backlinks": "{{.BacklinkCount}} обратн{{if eq .BacklinkCount 1}}ая ссылка{{else if and (le .BacklinkCount 4) (gt .BacklinkCount 1)}}ые ссылки{{else}}ых ссылок{{end}}",
|
||||
|
||||
"markup": `Разметка`,
|
||||
"link": `Ссылка`,
|
||||
"link title": `Текст`,
|
||||
"heading": `Заголовок`,
|
||||
"bold": `Жирный`,
|
||||
"italic": `Курсив`,
|
||||
"highlight": `Выделение`,
|
||||
"underline": `Подчеркивание`,
|
||||
"mono": `Моноширинный`,
|
||||
"super": `Надстрочный`,
|
||||
"sub": `Подстрочный`,
|
||||
"strike": `Зачёркнутый`,
|
||||
"rocket": `Ссылка-ракета`,
|
||||
"transclude": `Трансклюзия`,
|
||||
"hr": `Гориз. черта`,
|
||||
"code": `Код-блок`,
|
||||
"bullets": `Маркир. список`,
|
||||
"numbers": `Нумер. список`,
|
||||
"mycomarkup help": `<a href="/help/en/mycomarkup" class="shy-link">Подробнее</a> о Микоразметке`,
|
||||
"actions": `Действия`,
|
||||
"current date": `Текущая дата`,
|
||||
"current time": `Текущее время`,
|
||||
"selflink": `Ссылка на вас`,
|
||||
})
|
||||
pageHyphaEmpty = newtmpl.NewPage(fs, map[string]string{
|
||||
"empty heading": `Эта гифа не существует`,
|
||||
"empty no rights": `У вас нет прав для создания новых гиф. Вы можете:`,
|
||||
"empty log in": `Войти в свою учётную запись, если она у вас есть`,
|
||||
@ -157,18 +113,27 @@ func initPages() {
|
||||
"upload a media": `Загрузить медиа`,
|
||||
"upload a media tip": `Загрузите изображение, видео или аудио. Распространённые форматы можно просматривать из браузера, остальные можно только скачать и просмотреть локально. Позже вы можете дописать пояснение к этому медиа.`,
|
||||
"upload a media btn": `Загрузить`,
|
||||
}, "views/hypha-empty.html", map[string]string{
|
||||
"empty heading": `Эта гифа не существует`,
|
||||
"empty no rights": `У вас нет прав для создания новых гиф. Вы можете:`,
|
||||
"empty log in": `Войти в свою учётную запись, если она у вас есть`,
|
||||
"empty register": `Создать новую учётную запись`,
|
||||
"write a text": `Написать текст`,
|
||||
"write a text tip": `Напишите заметку, дневник, статью, рассказ или иной текст с помощью <a href="/help/en/mycomarkup" class="shy-link">Микоразметки</a>. Сохраняется полная история правок документа.`,
|
||||
"write a text writing conventions": `Не забывайте следовать правилам оформления этой вики, если они имеются.`,
|
||||
"write a text btn": `Создать`,
|
||||
"upload a media": `Загрузить медиа`,
|
||||
"upload a media tip": `Загрузите изображение, видео или аудио. Распространённые форматы можно просматривать из браузера, остальные можно только скачать и просмотреть локально. Позже вы можете дописать пояснение к этому медиа.`,
|
||||
"upload a media btn": `Загрузить`,
|
||||
})
|
||||
pageHypha = newtmpl.NewPage(fs, map[string]string{}, "views/hypha.html", map[string]string{})
|
||||
}, "views/hypha.html")
|
||||
pageRevision = newtmpl.NewPage(fs, map[string]string{
|
||||
"revision warning": "Обратите внимание, просмотр медиа в истории пока что недоступен.",
|
||||
"revision link": "Посмотреть Микоразметку для этой ревизии",
|
||||
"hypha at rev": "{{.HyphaName}} на {{.RevHash}}",
|
||||
}, "views/hypha-revision.html")
|
||||
pageMedia = newtmpl.NewPage(fs, map[string]string{ // TODO: сделать новый перевод
|
||||
"media title": "Медиа «{{.HyphaName | beautifulLink}}»",
|
||||
"tip": "На этой странице вы можете управлять медиа.",
|
||||
"empty": "Эта гифа не имеет медиа, здесь вы можете его загрузить.",
|
||||
"what is media?": "Что такое медиа?",
|
||||
"stat": "Свойства",
|
||||
"stat size": "Размер файла:",
|
||||
"stat mime": "MIME-тип:",
|
||||
|
||||
"upload title": "Прикрепить",
|
||||
"upload tip": "Вы можете загрузить новое медиа. Пожалуйста, не загружайте слишком большие изображения без необходимости, чтобы впоследствии не ждать её долгую загрузку.",
|
||||
"upload btn": "Загрузить",
|
||||
|
||||
"remove title": "Открепить",
|
||||
"remove tip": "Заметьте, чтобы заменить медиа, вам не нужно его перед этим откреплять.",
|
||||
"remove btn": "Открепить",
|
||||
}, "views/hypha-media.html")
|
||||
}
|
||||
|
||||
146
web/readers.go
146
web/readers.go
@ -17,8 +17,10 @@ import (
|
||||
"html/template"
|
||||
"io"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
@ -64,15 +66,31 @@ func handlerMedia(w http.ResponseWriter, rq *http.Request) {
|
||||
hyphaName = util.HyphaNameFromRq(rq, "media")
|
||||
h = hyphae.ByName(hyphaName)
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
isMedia = false
|
||||
|
||||
mime string
|
||||
fileSize int64
|
||||
)
|
||||
util.HTTP200Page(w,
|
||||
viewutil.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("ui.media_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName)}),
|
||||
hypview.MediaMenu(rq, h, u),
|
||||
map[string]string{},
|
||||
))
|
||||
switch h := h.(type) {
|
||||
case *hyphae.MediaHypha:
|
||||
isMedia = true
|
||||
mime = mimetype.FromExtension(path.Ext(h.MediaFilePath()))
|
||||
|
||||
fileinfo, err := os.Stat(h.MediaFilePath())
|
||||
if err != nil {
|
||||
slog.Error("failed to stat media file", "err", err)
|
||||
// no return
|
||||
}
|
||||
|
||||
fileSize = fileinfo.Size()
|
||||
}
|
||||
_ = pageMedia.RenderTo(viewutil.MetaFrom(w, rq), map[string]any{
|
||||
"HyphaName": h.CanonicalName(),
|
||||
"U": u,
|
||||
"IsMediaHypha": isMedia,
|
||||
"MimeType": mime,
|
||||
"FileSize": fileSize,
|
||||
})
|
||||
}
|
||||
|
||||
// handlerRevisionText sends Mycomarkup text of the hypha at the given revision. See also: handlerRevision, handlerText.
|
||||
@ -137,7 +155,7 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
|
||||
var (
|
||||
hyphaName = util.CanonicalName(slug)
|
||||
h = hyphae.ByName(hyphaName)
|
||||
contents = fmt.Sprintf(`<p>%s</p>`, lc.Get("ui.revision_no_text"))
|
||||
contents = template.HTML(fmt.Sprintf(`<p>%s</p>`, lc.Get("ui.revision_no_text")))
|
||||
textContents string
|
||||
err error
|
||||
mycoFilePath string
|
||||
@ -151,26 +169,17 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
|
||||
textContents, err = history.FileAtRevision(mycoFilePath, revHash)
|
||||
if err == nil {
|
||||
ctx, _ := mycocontext.ContextFromStringInput(textContents, mycoopts.MarkupOptions(hyphaName))
|
||||
contents = mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx))
|
||||
contents = template.HTML(mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx)))
|
||||
}
|
||||
|
||||
page := hypview.Revision(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
h,
|
||||
contents,
|
||||
revHash,
|
||||
)
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = fmt.Fprint(
|
||||
w,
|
||||
viewutil.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("ui.revision_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName), "rev": revHash}),
|
||||
page,
|
||||
map[string]string{},
|
||||
),
|
||||
)
|
||||
meta := viewutil.MetaFrom(w, rq)
|
||||
_ = pageRevision.RenderTo(meta, map[string]any{
|
||||
"ViewScripts": cfg.ViewScripts,
|
||||
"Contents": contents,
|
||||
"RevHash": revHash,
|
||||
"NaviTitle": hypview.NaviTitle(meta, h.CanonicalName()),
|
||||
"HyphaName": h.CanonicalName(),
|
||||
})
|
||||
}
|
||||
|
||||
// handlerText serves raw source text of the hypha.
|
||||
@ -190,8 +199,7 @@ func handlerBinary(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
hyphaName := util.HyphaNameFromRq(rq, "binary")
|
||||
switch h := hyphae.ByName(hyphaName).(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
case *hyphae.TextualHypha:
|
||||
case *hyphae.EmptyHypha, *hyphae.TextualHypha:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
log.Printf("Textual hypha ‘%s’ has no media, cannot serve\n", h.CanonicalName())
|
||||
case *hyphae.MediaHypha:
|
||||
@ -205,59 +213,61 @@ func handlerBinary(w http.ResponseWriter, rq *http.Request) {
|
||||
func handlerHypha(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
var (
|
||||
hyphaName = util.HyphaNameFromRq(rq, "page", "hypha")
|
||||
h = hyphae.ByName(hyphaName)
|
||||
contents string
|
||||
openGraph string
|
||||
lc = l18n.FromRequest(rq)
|
||||
hyphaName = util.HyphaNameFromRq(rq, "page", "hypha")
|
||||
h = hyphae.ByName(hyphaName)
|
||||
contents template.HTML
|
||||
openGraph template.HTML
|
||||
lc = l18n.FromRequest(rq)
|
||||
meta = viewutil.MetaFrom(w, rq)
|
||||
subhyphae, prevHyphaName, nextHyphaName = tree.Tree(h.CanonicalName())
|
||||
cats = categories.CategoriesWithHypha(h.CanonicalName())
|
||||
category_list = ":" + strings.Join(cats, ":") + ":"
|
||||
isMyProfile = cfg.UseAuth && util.IsProfileName(h.CanonicalName()) && meta.U.Name == strings.TrimPrefix(h.CanonicalName(), cfg.UserHypha+"/")
|
||||
|
||||
data = map[string]any{
|
||||
"HyphaName": h.CanonicalName(),
|
||||
"SubhyphaeHTML": subhyphae,
|
||||
"PrevHyphaName": prevHyphaName,
|
||||
"NextHyphaName": nextHyphaName,
|
||||
"IsMyProfile": isMyProfile,
|
||||
"NaviTitle": hypview.NaviTitle(meta, h.CanonicalName()),
|
||||
"BacklinkCount": backlinks.BacklinksCount(h.CanonicalName()),
|
||||
"GivenPermissionToModify": user.CanProceed(rq, "edit"),
|
||||
"Categories": cats,
|
||||
"IsMediaHypha": false,
|
||||
}
|
||||
)
|
||||
slog.Info("reading hypha", "name", h.CanonicalName(), "can edit", data["GivenPermissionToModify"])
|
||||
meta.BodyAttributes = map[string]string{
|
||||
"cats": category_list,
|
||||
}
|
||||
|
||||
switch h := h.(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
// contents = hypview.EmptyHypha()
|
||||
util.HTTP404Page(w,
|
||||
viewutil.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
util.BeautifulName(hyphaName),
|
||||
hypview.Hypha(viewutil.MetaFrom(w, rq), h, ""),
|
||||
map[string]string{},
|
||||
openGraph))
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
data["Contents"] = ""
|
||||
_ = pageHypha.RenderTo(meta, data)
|
||||
case hyphae.ExistingHypha:
|
||||
fileContentsT, errT := os.ReadFile(h.TextFilePath())
|
||||
if errT == nil {
|
||||
fileContentsT, err := os.ReadFile(h.TextFilePath())
|
||||
if err == nil {
|
||||
ctx, _ := mycocontext.ContextFromStringInput(string(fileContentsT), mycoopts.MarkupOptions(hyphaName))
|
||||
getOpenGraph, descVisitor, imgVisitor := tools.OpenGraphVisitors(ctx)
|
||||
openGraph = template.HTML(getOpenGraph())
|
||||
ast := mycomarkup.BlockTree(ctx, descVisitor, imgVisitor)
|
||||
contents = mycomarkup.BlocksToHTML(ctx, ast)
|
||||
openGraph = getOpenGraph()
|
||||
contents = template.HTML(mycomarkup.BlocksToHTML(ctx, ast))
|
||||
}
|
||||
switch h := h.(type) {
|
||||
case *hyphae.MediaHypha:
|
||||
contents = mycoopts.Media(h, lc) + contents
|
||||
contents = template.HTML(mycoopts.Media(h, lc)) + contents
|
||||
data["IsMediaHypha"] = true
|
||||
}
|
||||
|
||||
meta := viewutil.MetaFrom(w, rq)
|
||||
category_list := ":" + strings.Join(categories.CategoriesWithHypha(h.CanonicalName()), ":") + ":"
|
||||
subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName())
|
||||
isMyProfile := cfg.UseAuth && util.IsProfileName(h.CanonicalName()) && meta.U.Name == strings.TrimPrefix(h.CanonicalName(), cfg.UserHypha+"/")
|
||||
data["Contents"] = contents
|
||||
meta.HeadElements = append(meta.HeadElements, openGraph)
|
||||
_ = pageHypha.RenderTo(meta, data)
|
||||
|
||||
_ = pageHypha.RenderTo(
|
||||
meta,
|
||||
map[string]any{
|
||||
"SubhyphaeHTML": subhyphae,
|
||||
"PrevHyphaName": prevHyphaName,
|
||||
"NextHyphaName": nextHyphaName,
|
||||
"IsMyProfile": isMyProfile,
|
||||
"NaviTitle": hypview.NaviTitle(meta, h.CanonicalName()),
|
||||
"Contents": template.HTML(contents),
|
||||
})
|
||||
util.HTTP200Page(w,
|
||||
viewutil.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
util.BeautifulName(hyphaName),
|
||||
hypview.Hypha(viewutil.MetaFrom(w, rq), h, contents),
|
||||
map[string]string{"cats": category_list},
|
||||
openGraph))
|
||||
// TODO: check head cats
|
||||
// TODO: check opengraph
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
{{define "empty hypha card"}}
|
||||
<section class="non-existent-hypha">
|
||||
<h2 class="non-existent-hypha__title">{{block "empty heading" .}}This hypha does not exist{{end}}</h2>
|
||||
{{if and .UseAuth (eq .Meta.U.Group "anon")}}
|
||||
<p>{{block "empty no rights" .}}You are not authorized to create new hyphae. Here is what you can do:{{end}}</p>
|
||||
<ul>
|
||||
<li><a href="/login">{{block "empty log in" .}}Log in to your account, if you have one{{end}}</a></li>
|
||||
{{if .AllowRegistration}}<li><a href="/register">{{block "empty register" .}}Register a new account{{end}}</a></li>{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<div class="non-existent-hypha__ways">
|
||||
<section class="non-existent-hypha__way">
|
||||
<h3 class="non-existent-hypha__subtitle">📝 {{block "write a text" .}}Write a text{{end}}</h3>
|
||||
<p>{{block "write a text tip" .}}Write a note, a diary, an article, a story or anything textual using <a href="/help/en/mycomarkup" class="shy-link">Mycomarkup</a>. Full history of edits to the document will be saved.{{end}}</p>
|
||||
<p>{{block "write a text writing conventions" .}}Make sure to follow this wiki's writing conventions if there are any.{{end}}</p>
|
||||
<a class="btn btn_accent stick-to-bottom" href="/edit/{{.HyphaName}}">{{block "write a text btn" .}}Create{{end}}</a>
|
||||
</section>
|
||||
|
||||
<section class="non-existent-hypha__way">
|
||||
<h3 class="non-existent-hypha__subtitle">🖼 {{block "upload a media" .}}Upload a media{{end}}</h3>
|
||||
<p>{{block "upload a media tip" .}}Upload a picture, a video or an audio. Most common formats can be viewed from the browser, others can only be downloaded and viewed locally. You can write a description for the media later.{{end}}</p>
|
||||
<form action="/upload-binary/{{.HyphaName}}"
|
||||
method="post" enctype="multipart/form-data"
|
||||
class="upload-binary">
|
||||
<input type="file" id="upload-binary__input" name="binary">
|
||||
<button type="submit" class="btn stick-to-bottom" value="Upload">{{block "upload a media btn" .}}Upload{{end}}</button>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
57
web/views/hypha-media.html
Normal file
57
web/views/hypha-media.html
Normal file
@ -0,0 +1,57 @@
|
||||
{{define "title"}}{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width media-tab">
|
||||
<h1>{{block "media title" .}}Media of {{.HyphaName | beautifulLink }}{{end}}</h1>
|
||||
<p class="explanation">
|
||||
{{if .IsMediaHypha}}
|
||||
{{block "tip" .}}You can manage the hypha's media on this page.{{end}}
|
||||
{{else}}
|
||||
{{block "empty" .}}This hypha has no media, you can upload it here.{{end}}
|
||||
{{end}}
|
||||
<a href="/help/en/media" class="shy-link">
|
||||
{{block "what is media?" .}}What is media?{{end}}
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<section class="amnt-grid">
|
||||
{{if .IsMediaHypha}}
|
||||
<fieldset class="amnt-menu-block"> <!-- TODO: refactor with <dl> -->
|
||||
<legend class="modal__title modal__title_small">{{block "stat" .}}Stat{{end}}</legend>
|
||||
<p><b>{{block "stat size" .}}File size:{{end}}</b> {{.FileSize}}</p> <!-- TODO: human readable measure -->
|
||||
<p><b>{{block "stat mime" .}}MIME type:{{end}}</b> {{.MimeType}}</p>
|
||||
</fieldset>
|
||||
{{end}}
|
||||
|
||||
{{if .U.CanProceed "upload-binary" }}
|
||||
<form action="/upload-binary/{{.HyphaName}}"
|
||||
method="post" enctype="multipart/form-data"
|
||||
class="upload-binary modal amnt-menu-block">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title modal__title_small">
|
||||
{{block "upload title" .}}Upload{{end}}</legend>
|
||||
<p class="modal__confirmation-msg">
|
||||
{{block "upload tip" .}}You can upload a new media. Please do not upload too big pictures unless you need to because may not want to wait for big pictures to load.{{end}}</p>
|
||||
<label for="upload-binary__input"></label> <!-- TODO: ? -->
|
||||
<input type="file" id="upload-binary__input" name="binary">
|
||||
|
||||
<button type="submit" class="btn stick-to-bottom" value="Upload">
|
||||
{{block "upload btn" .}}Upload{{end}}</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
{{end}}
|
||||
|
||||
{{if .IsMediaHypha | and (.U.CanProceed "remove-media")}}
|
||||
<form action="/remove-media/{{.HyphaName}}" class="modal amnt-menu-block" method="POST">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title modal__title_small">
|
||||
{{block "remove title" .}}Remove media{{end}}</legend>
|
||||
<p class="modal__confirmation-msg">
|
||||
{{block "remove tip" .}}Please note that you don't have to remove media before uploading a new media.{{end}}</p>
|
||||
<button type="submit" class="btn" value="Remove media">
|
||||
{{block "remove btn" .}}Remove media{{end}}</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
{{end}}
|
||||
</section>
|
||||
</main>
|
||||
{{end}}
|
||||
18
web/views/hypha-revision.html
Normal file
18
web/views/hypha-revision.html
Normal file
@ -0,0 +1,18 @@
|
||||
{{define "hypha at rev"}}{{.HyphaName}} at {{.RevHash}}{{end}}
|
||||
{{define "title"}}{{template "hypha at rev" .}}{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width">
|
||||
<section>
|
||||
<p>
|
||||
{{block "revision warning" .}}Please note that viewing media is not supported in history for now.{{end}}
|
||||
<a href="/rev-text/{{.RevHash}}/{{.HyphaName}}">
|
||||
{{block "revision link" .}}Get Mycomarkup source of this revision{{end}}
|
||||
</a>
|
||||
</p>
|
||||
{{.NaviTitle}}
|
||||
{{.Contents}}
|
||||
</section>
|
||||
</main>
|
||||
{{range .ViewScripts}}<script src="{{.}}"></script>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@ -1,47 +1,44 @@
|
||||
{{define "title"}}{{.HyphaName | beautifulName}}{{end}}
|
||||
|
||||
{{define "body"}}
|
||||
<main class="main-width">
|
||||
<section id="hypha">
|
||||
{{if .Meta.U.CanProceed "edit"}}
|
||||
<div class="btn btn_navititle">
|
||||
<a class="btn__link_navititle" href="/edit/{{.HyphaName}}">
|
||||
{{block "edit" .}}Edit{{end}}
|
||||
</a>
|
||||
</div>
|
||||
{{block "edit text" .}}Edit text{{end}}</a></div>
|
||||
{{end}}
|
||||
|
||||
{{if .IsMyProfile}}
|
||||
<div class="btn btn_navititle">
|
||||
<a class="btn__link_navititle" href="/logout">
|
||||
{{block "logout" .}}Log out{{end}}
|
||||
</a>
|
||||
</div>
|
||||
{{block "log out" .}}Log out{{end}}</a></div>
|
||||
{{if eq .Meta.U.Group "admin"}}
|
||||
<div class="btn btn_navititle">
|
||||
<a class="btn__link_navititle" href="/admin">
|
||||
{{block "admin panel" .}}Admin panel{{end}}
|
||||
</a>
|
||||
</div>
|
||||
{{block "admin panel" .}}Admin panel{{end}}</a></div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{.NaviTitle}}
|
||||
{{.Contents}}
|
||||
|
||||
{{if .Contents}}{{.Contents}}{{else}}{{template "empty hypha card" .}}{{end}}
|
||||
</section>
|
||||
|
||||
<section class="prevnext">
|
||||
{{if .PrevHyphaName}}
|
||||
<a class="prevnext__el prevnext__prev" href="/hypha/{{.PrevHyphaName}}" rel="prev">
|
||||
← {{base .PrevHyphaName | beautifulName}}</a>
|
||||
← {{.PrevHyphaName | base | beautifulName}}</a>
|
||||
{{end}}
|
||||
{{if .NextHyphaName}}
|
||||
<a class="prevnext__el prevnext__next" href="/hypha/{{.NextHyphaName}}" rel="next">
|
||||
{{base .NextHyphaName | beautifulName}} →</a>
|
||||
{{.NextHyphaName | base | beautifulName}} →</a>
|
||||
{{end}}
|
||||
</section>
|
||||
|
||||
{{ if .SubhyphaeHTML }}
|
||||
<section class="subhyphae">
|
||||
<h2 class="subhyphae__title">{%s lc.Get("ui.subhyphae") %}</h2>
|
||||
<h2 class="subhyphae__title">{{block "subhyphae" .}}Subhyphae{{end}}</h2>
|
||||
<nav class="subhyphae__nav">
|
||||
<ul class="subhyphae__list">
|
||||
{{.SubhyphaeHTML}}
|
||||
@ -51,12 +48,42 @@
|
||||
{{end}}
|
||||
|
||||
<section id="hypha-bottom">
|
||||
{{hyphaInfo(meta, h)}}
|
||||
<nav class="hypha-info">
|
||||
<ul class="hypha-info__list">
|
||||
<li class="hypha-info__entry hypha-info__entry_history">
|
||||
<a class="hypha-info__link" href="/history/{{.HyphaName}}">
|
||||
{{block "history" .}}View history{{end}}</a></li>
|
||||
|
||||
<li class="hypha-info__entry hypha-info__entry_rename">
|
||||
<a class="hypha-info__link" href="/rename/{{.HyphaName}}">
|
||||
{{block "rename" .}}Rename{{end}}</a></li>
|
||||
|
||||
<li class="hypha-info__entry hypha-info__entry_delete">
|
||||
<a class="hypha-info__link" href="/delete/{{.HyphaName}}">
|
||||
{{block "delete" .}}Delete{{end}}</a></li>
|
||||
|
||||
<li class="hypha-info__entry hypha-info__entry_text">
|
||||
<a class="hypha-info__link" href="/text/{{.HyphaName}}">
|
||||
{{block "view markup" .}}View markup{{end}}</a></li>
|
||||
|
||||
<li class="hypha-info__entry hypha-info__entry_media">
|
||||
<a class="hypha-info__link" href="/media/{{.HyphaName}}">
|
||||
{{- if .IsMediaHypha -}}
|
||||
{{block "manage media" .}}Manage media{{end}}
|
||||
{{- else -}}
|
||||
{{block "turn to media" .}}Turn to media{{end}}
|
||||
{{- end}}</a></li>
|
||||
|
||||
<li class="hypha-info__entry hypha-info__entry_backlinks">
|
||||
<a class="hypha-info__link" href="/backlinks/{{.HyphaName}}">
|
||||
{{block "backlinks" .}}backlink{{if gt .BacklinkCount 1}}s{{end}}{{end}}</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</section>
|
||||
</main>
|
||||
{{template "category card" .}}
|
||||
{{range .ViewScripts}}<script src="{{.}}"></script>
|
||||
{{end}}
|
||||
{{range .ViewScripts}}<script src="{{.}}">
|
||||
</script>{{end}}
|
||||
{{end}}
|
||||
|
||||
{{define "category card"}}
|
||||
@ -95,4 +122,39 @@
|
||||
{{end}}
|
||||
</ul>
|
||||
</aside>
|
||||
{{end}}{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
|
||||
{{define "empty hypha card"}}
|
||||
<section class="non-existent-hypha">
|
||||
<h2 class="non-existent-hypha__title">{{block "empty heading" .}}This hypha does not exist{{end}}</h2>
|
||||
{{if and .UseAuth (eq .Meta.U.Group "anon")}}
|
||||
<p>{{block "empty no rights" .}}You are not authorized to create new hyphae. Here is what you can do:{{end}}</p>
|
||||
<ul>
|
||||
<li><a href="/login">{{block "empty log in" .}}Log in to your account, if you have one{{end}}</a></li>
|
||||
{{if .AllowRegistration}}<li><a href="/register">{{block "empty register" .}}Register a new account{{end}}</a></li>{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<div class="non-existent-hypha__ways">
|
||||
<section class="non-existent-hypha__way">
|
||||
<h3 class="non-existent-hypha__subtitle">📝 {{block "write a text" .}}Write a text{{end}}</h3>
|
||||
<p>{{block "write a text tip" .}}Write a note, a diary, an article, a story or anything textual using <a href="/help/en/mycomarkup" class="shy-link">Mycomarkup</a>. Full history of edits to the document will be saved.{{end}}</p>
|
||||
<p>{{block "write a text writing conventions" .}}Make sure to follow this wiki's writing conventions if there are any.{{end}}</p>
|
||||
<a class="btn btn_accent stick-to-bottom" href="/edit/{{.HyphaName}}">{{block "write a text btn" .}}Create{{end}}</a>
|
||||
</section>
|
||||
|
||||
<section class="non-existent-hypha__way">
|
||||
<h3 class="non-existent-hypha__subtitle">🖼 {{block "upload a media" .}}Upload a media{{end}}</h3>
|
||||
<p>{{block "upload a media tip" .}}Upload a picture, a video or an audio. Most common formats can be viewed from the browser, others can only be downloaded and viewed locally. You can write a description for the media later.{{end}}</p>
|
||||
<form action="/upload-binary/{{.HyphaName}}"
|
||||
method="post" enctype="multipart/form-data"
|
||||
class="upload-binary">
|
||||
<input type="file" id="upload-binary__input" name="binary">
|
||||
<button type="submit" class="btn stick-to-bottom" value="Upload">{{block "upload a media btn" .}}Upload{{end}}</button>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
@ -1,8 +1,9 @@
|
||||
package viewutil
|
||||
|
||||
import (
|
||||
user2 "github.com/bouncepaw/mycorrhiza/internal/user"
|
||||
"github.com/bouncepaw/mycorrhiza/internal/user"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
@ -10,12 +11,12 @@ import (
|
||||
// Meta is a bundle of common stuffs used by views, templates.
|
||||
type Meta struct {
|
||||
Lc *l18n.Localizer
|
||||
U *user2.User
|
||||
U *user.User
|
||||
W io.Writer
|
||||
Addr string
|
||||
|
||||
// New template additions
|
||||
HeadElements []string
|
||||
HeadElements []template.HTML
|
||||
BodyAttributes map[string]string
|
||||
}
|
||||
|
||||
@ -23,7 +24,7 @@ type Meta struct {
|
||||
func MetaFrom(w http.ResponseWriter, rq *http.Request) Meta {
|
||||
return Meta{
|
||||
Lc: l18n.FromRequest(rq),
|
||||
U: user2.FromRequest(rq),
|
||||
U: user.FromRequest(rq),
|
||||
W: w,
|
||||
Addr: rq.URL.Path,
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user