New static files system
assets.qtpl is no more! Now you can just add files to static/ folder, make sure the extension is registered in static.go (a shortcoming that'll be addressed in future Go versions), and you're done! It searches the local file system first, then falls back to the files embedded with the binary (in the static/ folder).
@ -1,38 +0,0 @@
|
||||
{%- func HelpMessage() -%}
|
||||
Usage of %s:
|
||||
{%- endfunc -%}
|
||||
|
||||
{%- func ExampleConfig() -%}
|
||||
{% cat "config.ini" %}
|
||||
{%- endfunc -%}
|
||||
|
||||
{% func DefaultCSS() %}
|
||||
{% cat "default.css" %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func ToolbarJS() %}
|
||||
{% cat "toolbar.js" %}
|
||||
{% endfunc %}
|
||||
|
||||
Next three are from https://remixicon.com/
|
||||
{% func IconHTTP() %}
|
||||
{% cat "icon/http-protocol-icon.svg" %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func IconGemini() %}
|
||||
{% cat "icon/gemini-protocol-icon.svg" %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func IconMailto() %}
|
||||
{% cat "icon/mailto-protocol-icon.svg" %}
|
||||
{% endfunc %}
|
||||
|
||||
This is a modified version of https://www.svgrepo.com/svg/232085/rat
|
||||
{% func IconGopher() %}
|
||||
{% cat "icon/gopher-protocol-icon.svg" %}
|
||||
{% endfunc %}
|
||||
|
||||
https://upload.wikimedia.org/wikipedia/commons/4/46/Generic_Feed-icon.svg
|
||||
{% func IconFeed() %}
|
||||
{% cat "icon/feed-icon.svg" %}
|
||||
{% endfunc %}
|
@ -1,828 +0,0 @@
|
||||
// Code generated by qtc from "assets.qtpl". DO NOT EDIT.
|
||||
// See https://github.com/valyala/quicktemplate for details.
|
||||
|
||||
//line assets/assets.qtpl:1
|
||||
package assets
|
||||
|
||||
//line assets/assets.qtpl:1
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line assets/assets.qtpl:1
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line assets/assets.qtpl:1
|
||||
func StreamHelpMessage(qw422016 *qt422016.Writer) {
|
||||
//line assets/assets.qtpl:1
|
||||
qw422016.N().S(`Usage of %s:
|
||||
`)
|
||||
//line assets/assets.qtpl:3
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:3
|
||||
func WriteHelpMessage(qq422016 qtio422016.Writer) {
|
||||
//line assets/assets.qtpl:3
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line assets/assets.qtpl:3
|
||||
StreamHelpMessage(qw422016)
|
||||
//line assets/assets.qtpl:3
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line assets/assets.qtpl:3
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:3
|
||||
func HelpMessage() string {
|
||||
//line assets/assets.qtpl:3
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line assets/assets.qtpl:3
|
||||
WriteHelpMessage(qb422016)
|
||||
//line assets/assets.qtpl:3
|
||||
qs422016 := string(qb422016.B)
|
||||
//line assets/assets.qtpl:3
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line assets/assets.qtpl:3
|
||||
return qs422016
|
||||
//line assets/assets.qtpl:3
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:5
|
||||
func StreamExampleConfig(qw422016 *qt422016.Writer) {
|
||||
//line assets/assets.qtpl:6
|
||||
qw422016.N().S(`WikiName = My wiki
|
||||
NaviTitleIcon = 🐑
|
||||
|
||||
[Hyphae]
|
||||
HomeHypha = home
|
||||
UserHypha = u
|
||||
HeaderLinksHypha = header-links
|
||||
|
||||
[Network]
|
||||
HTTPPort = 8080
|
||||
URL = https://wiki
|
||||
GeminiCertificatePath = /home/wiki/gemcerts
|
||||
|
||||
[Authorization]
|
||||
UseFixedAuth = true
|
||||
FixedAuthCredentialsPath = /home/wiki/mycocredentials.json
|
||||
|
||||
UseRegistration = true
|
||||
RegistrationCredentialsPath = /home/wiki/mycoregistration.json
|
||||
LimitRegistration = 10
|
||||
`)
|
||||
//line assets/assets.qtpl:6
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:7
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:7
|
||||
func WriteExampleConfig(qq422016 qtio422016.Writer) {
|
||||
//line assets/assets.qtpl:7
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line assets/assets.qtpl:7
|
||||
StreamExampleConfig(qw422016)
|
||||
//line assets/assets.qtpl:7
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line assets/assets.qtpl:7
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:7
|
||||
func ExampleConfig() string {
|
||||
//line assets/assets.qtpl:7
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line assets/assets.qtpl:7
|
||||
WriteExampleConfig(qb422016)
|
||||
//line assets/assets.qtpl:7
|
||||
qs422016 := string(qb422016.B)
|
||||
//line assets/assets.qtpl:7
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line assets/assets.qtpl:7
|
||||
return qs422016
|
||||
//line assets/assets.qtpl:7
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:9
|
||||
func StreamDefaultCSS(qw422016 *qt422016.Writer) {
|
||||
//line assets/assets.qtpl:9
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:10
|
||||
qw422016.N().S(`.non-existent-hypha { }
|
||||
.non-existent-hypha__ways { display: flex; flex-direction: column; width: 100%; margin: 0 0 1rem 0;}
|
||||
.non-existent-hypha__way { border: 1px #999 solid; border-radius: .25rem; padding: .25rem; }
|
||||
.non-existent-hypha__title { margin-bottom: 1rem; }
|
||||
.non-existent-hypha__subtitle { margin: 0; }
|
||||
|
||||
.amnt-grid { display: grid; grid-template-columns: 1fr 1fr; }
|
||||
#upload-binary__input { display: block; margin: .25rem 0 .25rem 0; }
|
||||
|
||||
.modal__title { font-size: 2rem; }
|
||||
.modal__title_small { font-size: 1.5rem; }
|
||||
.modal__confirmation-msg { margin: 0 0 .5rem 0; }
|
||||
|
||||
.hypha-list { padding-left: 0; }
|
||||
.hypha-list__entry { list-style-type: none; }
|
||||
.hypha-list__link { text-decoration: none; display: inline-block; padding: .25rem; }
|
||||
.hypha-list__link:hover { text-decoration: underline; }
|
||||
.hypha-list__amnt-type { font-size: smaller; color: #999; }
|
||||
|
||||
/* General element positions, from small to big */
|
||||
/* Phones and whatnot */
|
||||
.layout { display: grid; row-gap: 1rem; }
|
||||
header { width: 100%; margin-bottom: 1rem; }
|
||||
.header-links__list, .hypha-tabs__flex { margin: 0; padding: 0; display: flex; flex-wrap: wrap; }
|
||||
.header-links__entry, .hypha-tabs__tab { list-style-type: none; }
|
||||
|
||||
.header-links__entry { margin-right: .5rem; }
|
||||
.header-links__entry_user, .header-links__entry_register { font-style:italic; }
|
||||
.header-links__link { display: inline-block; padding: .25rem; text-decoration: none; }
|
||||
|
||||
.hypha-tabs { padding: 0; margin: 0; }
|
||||
.hypha-tabs__tab { margin-right: .5rem; padding: 0; }
|
||||
.hypha-tabs__link { display: inline-block; padding: .25rem; text-decoration: none; }
|
||||
.hypha-tabs__selection { display: inline-block; padding: .25rem; font-weight: bold; }
|
||||
|
||||
.layout-card li { list-style-type: none; }
|
||||
.backlinks__list { padding: 0; margin: 0; }
|
||||
.backlinks__link { text-decoration: none; display: block; padding: .25rem; padding-left: 1.25rem; }
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.amnt-grid { grid-template-columns: 1fr; }
|
||||
.layout { grid-template-columns: auto; grid-template-rows: auto auto auto; }
|
||||
.main-width { width: 100%; }
|
||||
main { padding: 1rem; margin: 0; }
|
||||
}
|
||||
|
||||
@media screen and (min-width: 500px) {
|
||||
.non-existent-hypha__way { flex: 1; margin-right: .5rem; }
|
||||
.non-existent-hypha__ways { flex-direction: row; }
|
||||
.non-existent-hypha__way:last-child { margin-right: 0; }
|
||||
}
|
||||
|
||||
/* No longer a phone but still small screen: draw normal tabs, center main */
|
||||
@media screen and (min-width: 801px) {
|
||||
.main-width { padding: 1rem 2rem; width: 800px; margin: 0 auto; }
|
||||
main { border-radius: .25rem; }
|
||||
.layout-card { width: 800px; margin: 0 auto; }
|
||||
|
||||
.header-links { padding: 0; }
|
||||
.header-links__entry { margin-right: 1.5rem; }
|
||||
.header-links__entry_user { margin: 0 2rem 0 auto; }
|
||||
.header-links__entry:nth-of-type(1),
|
||||
|
||||
.hypha-tabs { padding: 0; }
|
||||
.hypha-tabs__tab { border-radius: .25rem .25rem 0 0; margin-right: 0; }
|
||||
.hypha-tabs__selection, .hypha-tabs__link { padding: .25rem .5rem; }
|
||||
|
||||
.header-links__entry:nth-of-type(1), .hypha-tabs__tab:nth-of-type(1) { margin-left: 2rem; }
|
||||
}
|
||||
|
||||
|
||||
/* Wide enough to fit two columns ok */
|
||||
@media screen and (min-width: 1100px) {
|
||||
.layout { display: grid; grid-template-columns: auto 1fr; column-gap: 1rem; margin: 0 1rem; row-gap: 1rem; }
|
||||
.main-width { margin: 0; }
|
||||
main { grid-column: 1 / span 1; grid-row: 1 / span 2; }
|
||||
.relative-hyphae, .edit-toolbar { grid-column: 2 / span 1; grid-row: 1 / span 1; }
|
||||
.layout-card { width: 100%; }
|
||||
.edit-toolbar__buttons {display: grid; }
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1150px) {
|
||||
.edit-toolbar__buttons { grid-template-columns: 1fr 1fr; }
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1250px) {
|
||||
.layout { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
|
||||
.layout-card {max-width: 18rem;}
|
||||
.main-width { margin: 0 auto; }
|
||||
.backlinks { grid-column: 1 / span 1; margin-right: 0; }
|
||||
main { grid-column: 2 / span 1; }
|
||||
.relative-hyphae, .edit-toolbar { grid-column: 3 / span 1; margin-left: 0; }
|
||||
.edit-toolbar__buttons { grid-template-columns: 1fr; }
|
||||
|
||||
.backlinks__title { text-align: right; }
|
||||
.backlinks__link { text-align: right; padding-right: 1.25rem; padding-left: .25rem; }
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1400px) {
|
||||
.edit-toolbar__buttons { grid-template-columns: 1fr 1fr; }
|
||||
}
|
||||
|
||||
*, *::before, *::after {box-sizing: border-box;}
|
||||
html { height:100%; padding:0; }
|
||||
body {height:100%; margin:0; }
|
||||
body, input { font-size:16px; font-family: 'PT Sans', 'Liberation Sans', sans-serif;}
|
||||
main > form {margin-bottom:1rem;}
|
||||
textarea {font-size:16px; font-family: 'PT Sans', 'Liberation Sans', sans-serif;}
|
||||
|
||||
.edit { min-height: 80vh; }
|
||||
.edit__title { margin-top: 0; }
|
||||
.edit__preview { border: 2px dashed #ddd; }
|
||||
.edit-form {height:70vh;}
|
||||
.edit-form textarea {width:100%;height:95%;}
|
||||
.edit-form__save { font-weight: bold; }
|
||||
.edit-toolbar__buttons, .edit-toolbar__ad { margin: .5rem; }
|
||||
|
||||
.icon {margin-right: .25rem; vertical-align: bottom; }
|
||||
|
||||
main h1:not(.navi-title) {font-size:1.7rem;}
|
||||
blockquote { margin: 0; padding-left: .75rem; }
|
||||
.wikilink_external::before { display: inline-block; width: 18px; height: 16px; vertical-align: sub; }
|
||||
/* .wikilink_external { padding-left: 16px; } */
|
||||
.wikilink_gopher::before { content: url("/assets/icon/gopher"); }
|
||||
.wikilink_http::before { content: url("/assets/icon/http"); }
|
||||
.wikilink_https::before { content: url("/assets/icon/http"); }
|
||||
/* .wikilink_https { background: transparent url("/assets/icon/http") center left no-repeat; } */
|
||||
.wikilink_gemini::before { content: url("/assets/icon/gemini"); }
|
||||
.wikilink_mailto::before { content: url("/assets/icon/mailto"); }
|
||||
|
||||
article { overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; line-height: 150%; }
|
||||
main h1, main h2, main h3, main h4, main h5, main h6 { margin: 1.5rem 0 0 0; }
|
||||
.heading__link { text-decoration: none; display: inline-block; }
|
||||
.heading__link::after { width: 1rem; content: "§"; color: transparent; }
|
||||
.heading__link:hover::after, .heading__link:active::after { color: #999; }
|
||||
article p { margin: .5rem 0; }
|
||||
article ul, ol { padding-left: 1.5rem; margin: .5rem 0; }
|
||||
article code { padding: .1rem .3rem; border-radius: .25rem; font-size: 90%; font-family: 'Menlo', 'PT Mono', monospace; }
|
||||
article pre.codeblock { padding:.5rem; white-space: pre-wrap; border-radius: .25rem;}
|
||||
.codeblock code {padding:0; font-size:15px;}
|
||||
.transclusion { border-radius: .25rem; }
|
||||
.transclusion__content > *:not(.binary-container) {margin: 0.5rem; }
|
||||
.transclusion__link {display: block; text-align: right; font-style: italic; margin-top: .5rem; margin-right: .25rem; text-decoration: none;}
|
||||
.transclusion__link::before {content: "⇐ ";}
|
||||
|
||||
/* Derived from https://commons.wikimedia.org/wiki/File:U%2B21D2.svg */
|
||||
.launchpad__entry { list-style-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.0' width='25' height='12'%3E%3Cg transform='scale(0.7,0.8) translate(-613.21429,-421)'%3E%3Cpath fill='%23999' d='M 638.06773,429.49751 L 631.01022,436.87675 L 630.1898,436.02774 L 632.416,433.30375 L 613.46876,433.30375 L 613.46876,431.66382 L 633.82089,431.66382 L 635.57789,429.5261 L 633.79229,427.35979 L 613.46876,427.35979 L 613.46876,425.71985 L 632.416,425.71985 L 630.1898,422.99587 L 631.01022,422.08788 L 638.06773,429.49751 z '/%3E%3C/g%3E%3C/svg%3E"); }
|
||||
|
||||
.binary-container { width: 100%; text-align: center; }
|
||||
.binary-container_with-img img,
|
||||
.binary-container_with-video video,
|
||||
.binary-container_with-audio audio { max-width: 100%; max-height: 30em; width: auto; }
|
||||
|
||||
.subhyphae__title { padding-bottom: .5rem; clear: both; }
|
||||
.navi-title { padding-bottom: .5rem; margin: .25rem 0; }
|
||||
.navi-title a {text-decoration:none; }
|
||||
.navi-title__separator { margin: 0 .25rem; }
|
||||
.navi-title__colon { margin-right: .5rem; }
|
||||
.upload-amnt { clear: both; padding: .5rem; border-radius: .25rem; }
|
||||
.upload-amnt__unattach { display: block; }
|
||||
aside { clear: both; }
|
||||
|
||||
.img-gallery { text-align: center; margin-top: .25rem; margin-bottom: .25rem; }
|
||||
.img-gallery_many-images { border-radius: .25rem; padding: .5rem; }
|
||||
.img-gallery img { max-width: 100%; max-height: 50vh; }
|
||||
figure { margin: 0; }
|
||||
figcaption { padding-bottom: .5rem; }
|
||||
|
||||
#new-name {width:100%;}
|
||||
|
||||
|
||||
.rc-entry { display: grid; list-style-type: none; padding: .25rem; grid-template-columns: 1fr 1fr; border-radius: .25rem; }
|
||||
.rc-entry__time { font-style: italic; }
|
||||
.rc-entry__hash { font-style: italic; text-align: right; }
|
||||
.rc-entry__links, .rc-entry__msg { grid-column: 1 / span 2; }
|
||||
.rc-entry__author { font-style: italic; }
|
||||
|
||||
.prevnext__el { display: inline-block; min-width: 40%; padding: .5rem; margin-bottom: .25rem; text-decoration: none; border-radius: .25rem; max-width: 49%; }
|
||||
.prevnext__prev { float: left; }
|
||||
.prevnext__next { float: right; text-align: right; }
|
||||
|
||||
.page-separator { clear: both; }
|
||||
.history__entries { background-color: #eee; margin: 0; padding: 0; border-radius: .25rem; }
|
||||
.history__month-anchor { text-decoration: none; color: inherit; }
|
||||
.history__entry { list-style-type: none; padding: .25rem; }
|
||||
.history-entry { padding: .25rem; }
|
||||
.history-entry__time { font-weight: bold; }
|
||||
.history-entry__author { font-style: italic; }
|
||||
|
||||
table { border: #ddd 1px solid; border-radius: .25rem; min-width: 4rem; }
|
||||
td { padding: .25rem; }
|
||||
caption { caption-side: top; font-size: small; }
|
||||
|
||||
.subhyphae__list, .subhyphae__list ul { display: flex; padding: 0; margin: 0; flex-wrap: wrap; }
|
||||
.subhyphae__list ul { font-size: 90%; }
|
||||
.subhyphae__entry { list-style-type: none; border: 1px solid #999; padding: 0; margin: .125rem; border-radius: .25rem; }
|
||||
.subhyphae__link { display: block; padding: .25rem; text-decoration: none; }
|
||||
.subhyphae__link:hover { background: #eee; }
|
||||
|
||||
.relative-hyphae__list { padding: 0; margin: 0; }
|
||||
.relative-hyphae__entry { clear: both; }
|
||||
.relative-hyphae__count { display: inline-block; float: right; }
|
||||
.relative-hyphae__entry_this { padding: .25rem .5rem; font-weight: bold; }
|
||||
.relative-hyphae__link { text-decoration: none; display: block; padding: .25rem .5rem; }
|
||||
|
||||
::-webkit-file-upload-button,
|
||||
.btn { line-height: normal; display: inline-block; border: 1px #999 solid; border-radius: .25rem; text-decoration: none; padding: .25rem; font-size: 1rem; margin: 0; }
|
||||
.btn_weak { border: 1px #999 dashed; }
|
||||
|
||||
/* Color stuff */
|
||||
/* Lighter stuff #eee */
|
||||
::-webkit-file-upload-button, .btn { background-color: #eee; color: black; }
|
||||
.btn:visited { color: black; }
|
||||
.btn_weak { background-color: transparent; }
|
||||
|
||||
article code,
|
||||
article .codeblock,
|
||||
.transclusion,
|
||||
.img-gallery_many-images,
|
||||
.rc-entry,
|
||||
.prevnext__el,
|
||||
table { background-color: #eee; }
|
||||
|
||||
.hypha-tabs__tab { background-color: #eee; }
|
||||
.hypha-tabs__tab a { color: black; }
|
||||
.hypha-tabs__tab_active { border-bottom: 2px white solid; background: white; }
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.hypha-tabs,
|
||||
.hypha-tabs__tab { background-color: white; }
|
||||
}
|
||||
|
||||
@media screen and (min-width: 801px) {
|
||||
.hypha-tabs__tab { border: 1px #ddd solid; }
|
||||
.hypha-tabs__tab_active { border-bottom: 1px white solid; }
|
||||
}
|
||||
|
||||
.layout-card { border-radius: .25rem; background-color: white; }
|
||||
.layout-card__title { font-size: 1rem; margin: 0; padding: .25rem .5rem; border-radius: .25rem .25rem 0 0; }
|
||||
.layout-card__title { border-bottom: 1px solid #eee; }
|
||||
|
||||
/* Other stuff */
|
||||
html { background-color: #eee;
|
||||
}
|
||||
header { background-color: #eee; }
|
||||
.header-links__link { color: black; }
|
||||
.header-links__link:hover { background-color: #ddd; }
|
||||
main { background-color: white; }
|
||||
|
||||
blockquote { border-left: 2px #999 solid; }
|
||||
.wikilink_new {color:#a55858;}
|
||||
.transclusion code, .transclusion .codeblock {background-color:#ddd;}
|
||||
.transclusion__link { color: black; }
|
||||
.wikilink_new:visited {color:#a55858;}
|
||||
.navi-title { border-bottom: #eee 1px solid; }
|
||||
.upload-amnt { border: #eee 1px solid; }
|
||||
td { border: #ddd 1px solid; }
|
||||
|
||||
.relative-hyphae__link:hover, .backlinks__link:hover { background-color: #eee; }
|
||||
|
||||
/* Dark theme! */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html { background: #222; color: #ddd; }
|
||||
main, article, .hypha-tabs__tab, header, .layout-card { background-color: #343434; color: #ddd; }
|
||||
|
||||
a, .wikilink_external { color: #f1fa8c; }
|
||||
a:visited, .wikilink_external:visited { color: #ffb86c; }
|
||||
.wikilink_new, .wikilink_new:visited { color: #dd4444; }
|
||||
.subhyphae__link:hover, .relative-hyphae__link:hover, .backlinks__link:hover { background-color: #444; }
|
||||
|
||||
.header-links__link, .header-links__link:visited,
|
||||
.prevnext__el, .prevnext__el:visited { color: #ddd; }
|
||||
.header-links__link:hover { background-color: #444; }
|
||||
|
||||
.hypha-tabs__tab a, .hypha-tabs__tab { color: #ddd; background-color: #232323; border: 0; }
|
||||
.layout-card__title, .hypha-tabs__tab_active { background-color: #343434; }
|
||||
|
||||
|
||||
.transclusion .transclusion__link { color: #ddd; }
|
||||
|
||||
input[type="text"], input[type="password"],
|
||||
::-webkit-file-upload-button,
|
||||
.btn,
|
||||
article code,
|
||||
article .codeblock,
|
||||
.transclusion,
|
||||
.img-gallery_many-images,
|
||||
.rc-entry,
|
||||
.history__entry,
|
||||
.prevnext__el,
|
||||
.upload-amnt,
|
||||
textarea,
|
||||
table { border: 0; background-color: #444444; color: #ddd; }
|
||||
.btn:visited { color: #ddd;}
|
||||
|
||||
.btn { border: #444 solid 1px; border-radius: .25rem; }
|
||||
.btn_weak { background-color: transparent; }
|
||||
|
||||
.transclusion code,
|
||||
.transclusion .codeblock { background-color: #454545; }
|
||||
mark { background: rgba(130, 80, 30, 5); color: inherit; }
|
||||
@media screen and (max-width: 800px) {
|
||||
.hypha-tabs { background-color: #232323; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
`)
|
||||
//line assets/assets.qtpl:10
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:11
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:11
|
||||
func WriteDefaultCSS(qq422016 qtio422016.Writer) {
|
||||
//line assets/assets.qtpl:11
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line assets/assets.qtpl:11
|
||||
StreamDefaultCSS(qw422016)
|
||||
//line assets/assets.qtpl:11
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line assets/assets.qtpl:11
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:11
|
||||
func DefaultCSS() string {
|
||||
//line assets/assets.qtpl:11
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line assets/assets.qtpl:11
|
||||
WriteDefaultCSS(qb422016)
|
||||
//line assets/assets.qtpl:11
|
||||
qs422016 := string(qb422016.B)
|
||||
//line assets/assets.qtpl:11
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line assets/assets.qtpl:11
|
||||
return qs422016
|
||||
//line assets/assets.qtpl:11
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:13
|
||||
func StreamToolbarJS(qw422016 *qt422016.Writer) {
|
||||
//line assets/assets.qtpl:13
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S(`const editTextarea = document.getElementsByClassName('edit-form__textarea')[0]
|
||||
|
||||
function placeCursor(position, el = editTextarea) {
|
||||
el.selectionEnd = position
|
||||
el.selectionStart = el.selectionEnd
|
||||
}
|
||||
|
||||
function getSelectedText(el = editTextarea) {
|
||||
const [start, end] = [el.selectionStart, el.selectionEnd]
|
||||
const text = el.value
|
||||
return text.substring(start, end)
|
||||
}
|
||||
|
||||
function textInserter(text, cursorPosition = null, el = editTextarea) {
|
||||
return function() {
|
||||
const [start, end] = [el.selectionStart, el.selectionEnd]
|
||||
el.setRangeText(text, start, end, 'select')
|
||||
el.focus()
|
||||
if (cursorPosition == null) {
|
||||
placeCursor(end + text.length)
|
||||
} else {
|
||||
placeCursor(end + cursorPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectionWrapper(cursorPosition, prefix, postfix = null, el = editTextarea) {
|
||||
return function() {
|
||||
const [start, end] = [el.selectionStart, el.selectionEnd]
|
||||
if (postfix == null) {
|
||||
postfix = prefix
|
||||
}
|
||||
let text = getSelectedText(el)
|
||||
let result = prefix + text + postfix
|
||||
el.setRangeText(result, start, end, 'select')
|
||||
el.focus()
|
||||
placeCursor(end + cursorPosition)
|
||||
}
|
||||
}
|
||||
|
||||
const wrapBold = selectionWrapper(2, '**'),
|
||||
wrapItalic = selectionWrapper(2, '//'),
|
||||
wrapMonospace = selectionWrapper(1, '`)
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S("`")
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S(`'),
|
||||
wrapHighlighted = selectionWrapper(2, '!!'),
|
||||
wrapLifted = selectionWrapper(2, '^^'),
|
||||
wrapLowered = selectionWrapper(2, ',,'),
|
||||
wrapStrikethrough = selectionWrapper(2, '~~'),
|
||||
wrapLink = selectionWrapper(2, '[[', ']]')
|
||||
|
||||
const insertHorizontalBar = textInserter('\n----\n'),
|
||||
insertImgBlock = textInserter('\nimg {\n \n}\n', 10),
|
||||
insertTableBlock = textInserter('\ntable {\n \n}\n', 12),
|
||||
insertRocket = textInserter('\n=> '),
|
||||
insertXcl = textInserter('\n<= '),
|
||||
insertHeading2 = textInserter('\n## '),
|
||||
insertHeading3 = textInserter('\n### '),
|
||||
insertCodeblock = textInserter('\n`)
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S("`")
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S(``)
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S("`")
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S(``)
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S("`")
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S(`\n\n`)
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S("`")
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S(``)
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S("`")
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S(``)
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S("`")
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S(`\n', 5),
|
||||
insertBulletedList = textInserter('\n* '),
|
||||
insertNumberedList = textInserter('\n*. ')
|
||||
|
||||
function insertDate() {
|
||||
let date = new Date().toISOString().split('T')[0]
|
||||
textInserter(date)()
|
||||
}
|
||||
|
||||
function insertTimeUTC() {
|
||||
let time = new Date().toISOString().substring(11, 19) + " UTC"
|
||||
textInserter(time)()
|
||||
}
|
||||
|
||||
function insertUserlink() {
|
||||
const userlink = document.querySelector('.header-links__entry_user a')
|
||||
const userHypha = userlink.getAttribute('href').substring(7) // no /hypha/
|
||||
textInserter('[[' + userHypha + ']]')()
|
||||
}
|
||||
`)
|
||||
//line assets/assets.qtpl:14
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:15
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:15
|
||||
func WriteToolbarJS(qq422016 qtio422016.Writer) {
|
||||
//line assets/assets.qtpl:15
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line assets/assets.qtpl:15
|
||||
StreamToolbarJS(qw422016)
|
||||
//line assets/assets.qtpl:15
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line assets/assets.qtpl:15
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:15
|
||||
func ToolbarJS() string {
|
||||
//line assets/assets.qtpl:15
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line assets/assets.qtpl:15
|
||||
WriteToolbarJS(qb422016)
|
||||
//line assets/assets.qtpl:15
|
||||
qs422016 := string(qb422016.B)
|
||||
//line assets/assets.qtpl:15
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line assets/assets.qtpl:15
|
||||
return qs422016
|
||||
//line assets/assets.qtpl:15
|
||||
}
|
||||
|
||||
// Next three are from https://remixicon.com/
|
||||
|
||||
//line assets/assets.qtpl:18
|
||||
func StreamIconHTTP(qw422016 *qt422016.Writer) {
|
||||
//line assets/assets.qtpl:18
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:19
|
||||
qw422016.N().S(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="#999" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"/></svg>
|
||||
`)
|
||||
//line assets/assets.qtpl:19
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:20
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:20
|
||||
func WriteIconHTTP(qq422016 qtio422016.Writer) {
|
||||
//line assets/assets.qtpl:20
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line assets/assets.qtpl:20
|
||||
StreamIconHTTP(qw422016)
|
||||
//line assets/assets.qtpl:20
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line assets/assets.qtpl:20
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:20
|
||||
func IconHTTP() string {
|
||||
//line assets/assets.qtpl:20
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line assets/assets.qtpl:20
|
||||
WriteIconHTTP(qb422016)
|
||||
//line assets/assets.qtpl:20
|
||||
qs422016 := string(qb422016.B)
|
||||
//line assets/assets.qtpl:20
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line assets/assets.qtpl:20
|
||||
return qs422016
|
||||
//line assets/assets.qtpl:20
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:22
|
||||
func StreamIconGemini(qw422016 *qt422016.Writer) {
|
||||
//line assets/assets.qtpl:22
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:23
|
||||
qw422016.N().S(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="#999" d="M15.502 20A6.523 6.523 0 0 1 12 23.502 6.523 6.523 0 0 1 8.498 20h2.26c.326.489.747.912 1.242 1.243.495-.33.916-.754 1.243-1.243h2.259zM18 14.805l2 2.268V19H4v-1.927l2-2.268V9c0-3.483 2.504-6.447 6-7.545C15.496 2.553 18 5.517 18 9v5.805zM17.27 17L16 15.56V9c0-2.318-1.57-4.43-4-5.42C9.57 4.57 8 6.681 8 9v6.56L6.73 17h10.54zM12 11a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></svg>
|
||||
`)
|
||||
//line assets/assets.qtpl:23
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:24
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:24
|
||||
func WriteIconGemini(qq422016 qtio422016.Writer) {
|
||||
//line assets/assets.qtpl:24
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line assets/assets.qtpl:24
|
||||
StreamIconGemini(qw422016)
|
||||
//line assets/assets.qtpl:24
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line assets/assets.qtpl:24
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:24
|
||||
func IconGemini() string {
|
||||
//line assets/assets.qtpl:24
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line assets/assets.qtpl:24
|
||||
WriteIconGemini(qb422016)
|
||||
//line assets/assets.qtpl:24
|
||||
qs422016 := string(qb422016.B)
|
||||
//line assets/assets.qtpl:24
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line assets/assets.qtpl:24
|
||||
return qs422016
|
||||
//line assets/assets.qtpl:24
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:26
|
||||
func StreamIconMailto(qw422016 *qt422016.Writer) {
|
||||
//line assets/assets.qtpl:26
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:27
|
||||
qw422016.N().S(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="#999" d="M3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm17 4.238l-7.928 7.1L4 7.216V19h16V7.238zM4.511 5l7.55 6.662L19.502 5H4.511z"/></svg>
|
||||
`)
|
||||
//line assets/assets.qtpl:27
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:28
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:28
|
||||
func WriteIconMailto(qq422016 qtio422016.Writer) {
|
||||
//line assets/assets.qtpl:28
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line assets/assets.qtpl:28
|
||||
StreamIconMailto(qw422016)
|
||||
//line assets/assets.qtpl:28
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line assets/assets.qtpl:28
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:28
|
||||
func IconMailto() string {
|
||||
//line assets/assets.qtpl:28
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line assets/assets.qtpl:28
|
||||
WriteIconMailto(qb422016)
|
||||
//line assets/assets.qtpl:28
|
||||
qs422016 := string(qb422016.B)
|
||||
//line assets/assets.qtpl:28
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line assets/assets.qtpl:28
|
||||
return qs422016
|
||||
//line assets/assets.qtpl:28
|
||||
}
|
||||
|
||||
// This is a modified version of https://www.svgrepo.com/svg/232085/rat
|
||||
|
||||
//line assets/assets.qtpl:31
|
||||
func StreamIconGopher(qw422016 *qt422016.Writer) {
|
||||
//line assets/assets.qtpl:31
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:32
|
||||
qw422016.N().S(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="16" height="16">
|
||||
<path fill="#999" d="M447.238,204.944v-70.459c0-8.836-7.164-16-16-16c-34.051,0-64.414,21.118-75.079,55.286
|
||||
C226.094,41.594,0,133.882,0,319.435c0,0.071,0.01,0.14,0.011,0.21c0.116,44.591,36.423,80.833,81.04,80.833h171.203
|
||||
c8.836,0,16-7.164,16-16c0-8.836-7.164-16-16-16H81.051c-21.441,0-39.7-13.836-46.351-33.044H496c8.836,0,16-7.164,16-16
|
||||
C512,271.82,486.82,228.692,447.238,204.944z M415.238,153.216v37.805c-10.318-2.946-19.556-4.305-29.342-4.937
|
||||
C390.355,168.611,402.006,157.881,415.238,153.216z M295.484,303.435L295.484,303.435c-7.562-41.495-43.948-73.062-87.593-73.062
|
||||
c-8.836,0-16,7.164-16,16c0,8.836,7.164,16,16,16c25.909,0,47.826,17.364,54.76,41.062H32.722
|
||||
c14.415-159.15,218.064-217.856,315.136-90.512c3.545,4.649,9.345,6.995,15.124,6.118
|
||||
c55.425-8.382,107.014,29.269,115.759,84.394H295.484z"/>
|
||||
<circle fill="#999" cx="415.238" cy="260.05" r="21.166"/>
|
||||
</svg>
|
||||
`)
|
||||
//line assets/assets.qtpl:32
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:33
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:33
|
||||
func WriteIconGopher(qq422016 qtio422016.Writer) {
|
||||
//line assets/assets.qtpl:33
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line assets/assets.qtpl:33
|
||||
StreamIconGopher(qw422016)
|
||||
//line assets/assets.qtpl:33
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line assets/assets.qtpl:33
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:33
|
||||
func IconGopher() string {
|
||||
//line assets/assets.qtpl:33
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line assets/assets.qtpl:33
|
||||
WriteIconGopher(qb422016)
|
||||
//line assets/assets.qtpl:33
|
||||
qs422016 := string(qb422016.B)
|
||||
//line assets/assets.qtpl:33
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line assets/assets.qtpl:33
|
||||
return qs422016
|
||||
//line assets/assets.qtpl:33
|
||||
}
|
||||
|
||||
// https://upload.wikimedia.org/wikipedia/commons/4/46/Generic_Feed-icon.svg
|
||||
|
||||
//line assets/assets.qtpl:36
|
||||
func StreamIconFeed(qw422016 *qt422016.Writer) {
|
||||
//line assets/assets.qtpl:36
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:37
|
||||
qw422016.N().S(`<svg xmlns="http://www.w3.org/2000/svg"
|
||||
id="RSSicon"
|
||||
viewBox="0 0 8 8" width="256" height="256">
|
||||
|
||||
<title>RSS feed icon</title>
|
||||
|
||||
<style type="text/css">
|
||||
.button {stroke: none; fill: orange;}
|
||||
.symbol {stroke: none; fill: white;}
|
||||
</style>
|
||||
|
||||
<rect class="button" width="8" height="8" rx="1.5" />
|
||||
<circle class="symbol" cx="2" cy="6" r="1" />
|
||||
<path class="symbol" d="m 1,4 a 3,3 0 0 1 3,3 h 1 a 4,4 0 0 0 -4,-4 z" />
|
||||
<path class="symbol" d="m 1,2 a 5,5 0 0 1 5,5 h 1 a 6,6 0 0 0 -6,-6 z" />
|
||||
|
||||
</svg>
|
||||
`)
|
||||
//line assets/assets.qtpl:37
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line assets/assets.qtpl:38
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:38
|
||||
func WriteIconFeed(qq422016 qtio422016.Writer) {
|
||||
//line assets/assets.qtpl:38
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line assets/assets.qtpl:38
|
||||
StreamIconFeed(qw422016)
|
||||
//line assets/assets.qtpl:38
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line assets/assets.qtpl:38
|
||||
}
|
||||
|
||||
//line assets/assets.qtpl:38
|
||||
func IconFeed() string {
|
||||
//line assets/assets.qtpl:38
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line assets/assets.qtpl:38
|
||||
WriteIconFeed(qb422016)
|
||||
//line assets/assets.qtpl:38
|
||||
qs422016 := string(qb422016.B)
|
||||
//line assets/assets.qtpl:38
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line assets/assets.qtpl:38
|
||||
return qs422016
|
||||
//line assets/assets.qtpl:38
|
||||
}
|
12
flag.go
@ -1,18 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/assets"
|
||||
)
|
||||
|
||||
// CLI options are read and parsed here.
|
||||
|
||||
//go:embed assets/config.ini
|
||||
var defaultConfig []byte
|
||||
|
||||
var printExampleConfig bool
|
||||
|
||||
func init() {
|
||||
@ -21,11 +23,11 @@ func init() {
|
||||
flag.Usage = printHelp
|
||||
}
|
||||
|
||||
// printHelp prints the help message. The help message is stored in assets.
|
||||
// printHelp prints the help message.
|
||||
func printHelp() {
|
||||
_, err := fmt.Fprintf(
|
||||
flag.CommandLine.Output(),
|
||||
assets.HelpMessage(),
|
||||
"Usage of %s:\n",
|
||||
os.Args[0],
|
||||
)
|
||||
if err != nil {
|
||||
@ -40,7 +42,7 @@ func parseCliArgs() {
|
||||
|
||||
args := flag.Args()
|
||||
if printExampleConfig {
|
||||
fmt.Printf(assets.ExampleConfig())
|
||||
os.Stdout.Write(defaultConfig)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
|
2
go.mod
@ -1,6 +1,6 @@
|
||||
module github.com/bouncepaw/mycorrhiza
|
||||
|
||||
go 1.14
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
git.sr.ht/~adnano/go-gemini v0.1.13
|
||||
|
4
main.go
@ -11,6 +11,7 @@ import (
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/shroom"
|
||||
"github.com/bouncepaw/mycorrhiza/static"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/web"
|
||||
"log"
|
||||
@ -40,6 +41,9 @@ func main() {
|
||||
history.Start()
|
||||
shroom.SetHeaderLinks()
|
||||
|
||||
// Static files:
|
||||
static.InitFS(cfg.WikiDir + "/static")
|
||||
|
||||
// Network:
|
||||
go handleGemini()
|
||||
web.Init()
|
||||
|
@ -121,12 +121,11 @@ main h1:not(.navi-title) {font-size:1.7rem;}
|
||||
blockquote { margin: 0; padding-left: .75rem; }
|
||||
.wikilink_external::before { display: inline-block; width: 18px; height: 16px; vertical-align: sub; }
|
||||
/* .wikilink_external { padding-left: 16px; } */
|
||||
.wikilink_gopher::before { content: url("/assets/icon/gopher"); }
|
||||
.wikilink_http::before { content: url("/assets/icon/http"); }
|
||||
.wikilink_https::before { content: url("/assets/icon/http"); }
|
||||
/* .wikilink_https { background: transparent url("/assets/icon/http") center left no-repeat; } */
|
||||
.wikilink_gemini::before { content: url("/assets/icon/gemini"); }
|
||||
.wikilink_mailto::before { content: url("/assets/icon/mailto"); }
|
||||
.wikilink_gopher::before { content: url("/static/icon/gopher-proto.svg"); }
|
||||
.wikilink_http::before, .wikilink_https::before { content: url("/static/icon/http-proto.svg"); }
|
||||
/* .wikilink_https { background: transparent url("/static/icon/http-proto.svg") center left no-repeat; } */
|
||||
.wikilink_gemini::before { content: url("/static/icon/gemini-proto.svg"); }
|
||||
.wikilink_mailto::before { content: url("/static/icon/mailto-proto.svg"); }
|
||||
|
||||
article { overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; line-height: 150%; }
|
||||
main h1, main h2, main h3, main h4, main h5, main h6 { margin: 1.5rem 0 0 0; }
|
10
static/icon/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Icons
|
||||
|
||||
#### `{http,gemini,mailto}-proto`
|
||||
These are from https://remixicon.com/.
|
||||
|
||||
#### `gopher-proto`
|
||||
This is a modified version of https://www.svgrepo.com/svg/232085/rat.
|
||||
|
||||
#### `feed`
|
||||
This one is from https://upload.wikimedia.org/wikipedia/commons/4/46/Generic_Feed-icon.svg.
|
Before Width: | Height: | Size: 531 B After Width: | Height: | Size: 531 B |
Before Width: | Height: | Size: 473 B After Width: | Height: | Size: 473 B |
Before Width: | Height: | Size: 951 B After Width: | Height: | Size: 951 B |
Before Width: | Height: | Size: 627 B After Width: | Height: | Size: 627 B |
Before Width: | Height: | Size: 261 B After Width: | Height: | Size: 261 B |
50
static/static.go
Normal file
@ -0,0 +1,50 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
//go:embed *.css *.js icon
|
||||
var embedFS embed.FS
|
||||
|
||||
// FS serves all static files.
|
||||
var FS HybridFS
|
||||
|
||||
// HybridFS is a filesystem that implements fs.FS. It can serve files
|
||||
// from multiple filesystems, falling back on failures.
|
||||
type HybridFS struct {
|
||||
fs []fs.FS
|
||||
}
|
||||
|
||||
// Open tries to open the requested file using all filesystems provided.
|
||||
// If neither succeeds, it returns the last error.
|
||||
func (f HybridFS) Open(name string) (fs.File, error) {
|
||||
log.Printf("serving static file: %s\n", name)
|
||||
|
||||
var file fs.File
|
||||
var err error
|
||||
|
||||
for _, candidate := range f.fs {
|
||||
file, err = candidate.Open(name)
|
||||
if err == nil {
|
||||
log.Println("succeeded")
|
||||
return file, nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("failed: %v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// InitFS initializes the global HybridFS singleton with the local wiki.
|
||||
func InitFS(localPath string) {
|
||||
FS = HybridFS{
|
||||
fs: []fs.FS{
|
||||
os.DirFS(localPath),
|
||||
embedFS,
|
||||
},
|
||||
}
|
||||
}
|
@ -45,7 +45,7 @@ if err != nil {
|
||||
recent changes
|
||||
</nav>
|
||||
|
||||
<p><img class="icon" width="20" height="20" src="/assets/icon/feed">Subscribe via <a href="/recent-changes-rss">RSS</a>, <a href="/recent-changes-atom">Atom</a> or <a href="/recent-changes-json">JSON feed</a>.</p>
|
||||
<p><img class="icon" width="20" height="20" src="/static/icon/feed.svg">Subscribe via <a href="/recent-changes-rss">RSS</a>, <a href="/recent-changes-atom">Atom</a> or <a href="/recent-changes-json">JSON feed</a>.</p>
|
||||
|
||||
{% comment %}
|
||||
Here I am, willing to add some accessibility using ARIA. Turns out,
|
||||
|
@ -163,7 +163,7 @@ func StreamRecentChangesHTML(qw422016 *qt422016.Writer, n int) {
|
||||
recent changes
|
||||
</nav>
|
||||
|
||||
<p><img class="icon" width="20" height="20" src="/assets/icon/feed">Subscribe via <a href="/recent-changes-rss">RSS</a>, <a href="/recent-changes-atom">Atom</a> or <a href="/recent-changes-json">JSON feed</a>.</p>
|
||||
<p><img class="icon" width="20" height="20" src="/static/icon/feed.svg">Subscribe via <a href="/recent-changes-rss">RSS</a>, <a href="/recent-changes-atom">Atom</a> or <a href="/recent-changes-json">JSON feed</a>.</p>
|
||||
|
||||
`)
|
||||
//line views/history.qtpl:55
|
||||
|
@ -65,7 +65,7 @@
|
||||
{% endif %}
|
||||
</section>
|
||||
</aside>
|
||||
<script src="/assets/toolbar.js"></script>
|
||||
<script src="/static/toolbar.js"></script>
|
||||
{% endfunc %}
|
||||
|
||||
{% func EditHTML(rq *http.Request, hyphaName, textAreaFill, warning string) %}
|
||||
|
@ -141,7 +141,7 @@ func StreamToolbar(qw422016 *qt422016.Writer, u *user.User) {
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</aside>
|
||||
<script src="/assets/toolbar.js"></script>
|
||||
<script src="/static/toolbar.js"></script>
|
||||
`)
|
||||
//line views/mutators.qtpl:69
|
||||
}
|
||||
|
@ -8,10 +8,11 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/common.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{%s title %}</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
||||
{% for _, el := range headElements %}{%s= el %}{% endfor %}
|
||||
</head>
|
||||
<body>
|
||||
|
@ -39,22 +39,23 @@ func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string, u *user.User,
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/common.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>`)
|
||||
//line views/stuff.qtpl:14
|
||||
//line views/stuff.qtpl:13
|
||||
qw422016.E().S(title)
|
||||
//line views/stuff.qtpl:14
|
||||
//line views/stuff.qtpl:13
|
||||
qw422016.N().S(`</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
||||
`)
|
||||
//line views/stuff.qtpl:15
|
||||
//line views/stuff.qtpl:16
|
||||
for _, el := range headElements {
|
||||
//line views/stuff.qtpl:15
|
||||
//line views/stuff.qtpl:16
|
||||
qw422016.N().S(el)
|
||||
//line views/stuff.qtpl:15
|
||||
//line views/stuff.qtpl:16
|
||||
}
|
||||
//line views/stuff.qtpl:15
|
||||
//line views/stuff.qtpl:16
|
||||
qw422016.N().S(`
|
||||
</head>
|
||||
<body>
|
||||
@ -62,81 +63,81 @@ func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string, u *user.User,
|
||||
<nav class="header-links main-width">
|
||||
<ul class="header-links__list">
|
||||
`)
|
||||
//line views/stuff.qtpl:21
|
||||
//line views/stuff.qtpl:22
|
||||
for _, link := range cfg.HeaderLinks {
|
||||
//line views/stuff.qtpl:21
|
||||
//line views/stuff.qtpl:22
|
||||
qw422016.N().S(` <li class="header-links__entry"><a class="header-links__link" href="`)
|
||||
//line views/stuff.qtpl:22
|
||||
//line views/stuff.qtpl:23
|
||||
qw422016.E().S(link.Href)
|
||||
//line views/stuff.qtpl:22
|
||||
//line views/stuff.qtpl:23
|
||||
qw422016.N().S(`">`)
|
||||
//line views/stuff.qtpl:22
|
||||
//line views/stuff.qtpl:23
|
||||
qw422016.E().S(link.Display)
|
||||
//line views/stuff.qtpl:22
|
||||
//line views/stuff.qtpl:23
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/stuff.qtpl:23
|
||||
//line views/stuff.qtpl:24
|
||||
}
|
||||
//line views/stuff.qtpl:23
|
||||
//line views/stuff.qtpl:24
|
||||
qw422016.N().S(` `)
|
||||
//line views/stuff.qtpl:24
|
||||
//line views/stuff.qtpl:25
|
||||
qw422016.N().S(UserMenuHTML(u))
|
||||
//line views/stuff.qtpl:24
|
||||
//line views/stuff.qtpl:25
|
||||
qw422016.N().S(`
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
`)
|
||||
//line views/stuff.qtpl:28
|
||||
//line views/stuff.qtpl:29
|
||||
qw422016.N().S(body)
|
||||
//line views/stuff.qtpl:28
|
||||
//line views/stuff.qtpl:29
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/stuff.qtpl:29
|
||||
//line views/stuff.qtpl:30
|
||||
streamomnipresentScripts(qw422016)
|
||||
//line views/stuff.qtpl:29
|
||||
//line views/stuff.qtpl:30
|
||||
qw422016.N().S(`
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
func WriteBaseHTML(qq422016 qtio422016.Writer, title, body string, u *user.User, headElements ...string) {
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
StreamBaseHTML(qw422016, title, body, u, headElements...)
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
func BaseHTML(title, body string, u *user.User, headElements ...string) string {
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
WriteBaseHTML(qb422016, title, body, u, headElements...)
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:32
|
||||
//line views/stuff.qtpl:33
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:34
|
||||
//line views/stuff.qtpl:35
|
||||
func StreamUserListHTML(qw422016 *qt422016.Writer) {
|
||||
//line views/stuff.qtpl:34
|
||||
//line views/stuff.qtpl:35
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width user-list">
|
||||
<h1>List of users</h1>
|
||||
`)
|
||||
//line views/stuff.qtpl:39
|
||||
//line views/stuff.qtpl:40
|
||||
var (
|
||||
admins = make([]string, 0)
|
||||
moderators = make([]string, 0)
|
||||
@ -153,303 +154,303 @@ func StreamUserListHTML(qw422016 *qt422016.Writer) {
|
||||
}
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:54
|
||||
//line views/stuff.qtpl:55
|
||||
qw422016.N().S(`
|
||||
<section>
|
||||
<h2>Admins</h2>
|
||||
<ol>`)
|
||||
//line views/stuff.qtpl:57
|
||||
//line views/stuff.qtpl:58
|
||||
for _, name := range admins {
|
||||
//line views/stuff.qtpl:57
|
||||
//line views/stuff.qtpl:58
|
||||
qw422016.N().S(`
|
||||
<li><a href="/page/`)
|
||||
//line views/stuff.qtpl:58
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/stuff.qtpl:58
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.N().S(`/`)
|
||||
//line views/stuff.qtpl:58
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.E().S(name)
|
||||
//line views/stuff.qtpl:58
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.N().S(`">`)
|
||||
//line views/stuff.qtpl:58
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.E().S(name)
|
||||
//line views/stuff.qtpl:58
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/stuff.qtpl:59
|
||||
//line views/stuff.qtpl:60
|
||||
}
|
||||
//line views/stuff.qtpl:59
|
||||
//line views/stuff.qtpl:60
|
||||
qw422016.N().S(`</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Moderators</h2>
|
||||
<ol>`)
|
||||
//line views/stuff.qtpl:63
|
||||
//line views/stuff.qtpl:64
|
||||
for _, name := range moderators {
|
||||
//line views/stuff.qtpl:63
|
||||
//line views/stuff.qtpl:64
|
||||
qw422016.N().S(`
|
||||
<li><a href="/page/`)
|
||||
//line views/stuff.qtpl:64
|
||||
//line views/stuff.qtpl:65
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/stuff.qtpl:64
|
||||
//line views/stuff.qtpl:65
|
||||
qw422016.N().S(`/`)
|
||||
//line views/stuff.qtpl:64
|
||||
//line views/stuff.qtpl:65
|
||||
qw422016.E().S(name)
|
||||
//line views/stuff.qtpl:64
|
||||
//line views/stuff.qtpl:65
|
||||
qw422016.N().S(`">`)
|
||||
//line views/stuff.qtpl:64
|
||||
//line views/stuff.qtpl:65
|
||||
qw422016.E().S(name)
|
||||
//line views/stuff.qtpl:64
|
||||
//line views/stuff.qtpl:65
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/stuff.qtpl:65
|
||||
//line views/stuff.qtpl:66
|
||||
}
|
||||
//line views/stuff.qtpl:65
|
||||
//line views/stuff.qtpl:66
|
||||
qw422016.N().S(`</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Editors</h2>
|
||||
<ol>`)
|
||||
//line views/stuff.qtpl:69
|
||||
//line views/stuff.qtpl:70
|
||||
for _, name := range editors {
|
||||
//line views/stuff.qtpl:69
|
||||
//line views/stuff.qtpl:70
|
||||
qw422016.N().S(`
|
||||
<li><a href="/page/`)
|
||||
//line views/stuff.qtpl:70
|
||||
//line views/stuff.qtpl:71
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/stuff.qtpl:70
|
||||
//line views/stuff.qtpl:71
|
||||
qw422016.N().S(`/`)
|
||||
//line views/stuff.qtpl:70
|
||||
//line views/stuff.qtpl:71
|
||||
qw422016.E().S(name)
|
||||
//line views/stuff.qtpl:70
|
||||
//line views/stuff.qtpl:71
|
||||
qw422016.N().S(`">`)
|
||||
//line views/stuff.qtpl:70
|
||||
//line views/stuff.qtpl:71
|
||||
qw422016.E().S(name)
|
||||
//line views/stuff.qtpl:70
|
||||
//line views/stuff.qtpl:71
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/stuff.qtpl:71
|
||||
//line views/stuff.qtpl:72
|
||||
}
|
||||
//line views/stuff.qtpl:71
|
||||
//line views/stuff.qtpl:72
|
||||
qw422016.N().S(`</ol>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
func WriteUserListHTML(qq422016 qtio422016.Writer) {
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
StreamUserListHTML(qw422016)
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
func UserListHTML() string {
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
WriteUserListHTML(qb422016)
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:75
|
||||
//line views/stuff.qtpl:76
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:77
|
||||
//line views/stuff.qtpl:78
|
||||
func StreamHyphaListHTML(qw422016 *qt422016.Writer) {
|
||||
//line views/stuff.qtpl:77
|
||||
//line views/stuff.qtpl:78
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<h1>List of hyphae</h1>
|
||||
<p>This wiki has `)
|
||||
//line views/stuff.qtpl:81
|
||||
//line views/stuff.qtpl:82
|
||||
qw422016.N().D(hyphae.Count())
|
||||
//line views/stuff.qtpl:81
|
||||
//line views/stuff.qtpl:82
|
||||
qw422016.N().S(` hyphae.</p>
|
||||
<ul class="hypha-list">
|
||||
`)
|
||||
//line views/stuff.qtpl:83
|
||||
//line views/stuff.qtpl:84
|
||||
for h := range hyphae.YieldExistingHyphae() {
|
||||
//line views/stuff.qtpl:83
|
||||
//line views/stuff.qtpl:84
|
||||
qw422016.N().S(`
|
||||
<li class="hypha-list__entry">
|
||||
<a class="hypha-list__link" href="/hypha/`)
|
||||
//line views/stuff.qtpl:85
|
||||
//line views/stuff.qtpl:86
|
||||
qw422016.E().S(h.Name)
|
||||
//line views/stuff.qtpl:85
|
||||
//line views/stuff.qtpl:86
|
||||
qw422016.N().S(`">`)
|
||||
//line views/stuff.qtpl:85
|
||||
//line views/stuff.qtpl:86
|
||||
qw422016.E().S(util.BeautifulName(h.Name))
|
||||
//line views/stuff.qtpl:85
|
||||
//line views/stuff.qtpl:86
|
||||
qw422016.N().S(`</a>
|
||||
`)
|
||||
//line views/stuff.qtpl:86
|
||||
//line views/stuff.qtpl:87
|
||||
if h.BinaryPath != "" {
|
||||
//line views/stuff.qtpl:86
|
||||
//line views/stuff.qtpl:87
|
||||
qw422016.N().S(`
|
||||
<span class="hypha-list__amnt-type">`)
|
||||
//line views/stuff.qtpl:87
|
||||
//line views/stuff.qtpl:88
|
||||
qw422016.E().S(filepath.Ext(h.BinaryPath)[1:])
|
||||
//line views/stuff.qtpl:87
|
||||
//line views/stuff.qtpl:88
|
||||
qw422016.N().S(`</span>
|
||||
`)
|
||||
//line views/stuff.qtpl:88
|
||||
//line views/stuff.qtpl:89
|
||||
}
|
||||
//line views/stuff.qtpl:88
|
||||
//line views/stuff.qtpl:89
|
||||
qw422016.N().S(`
|
||||
</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:90
|
||||
//line views/stuff.qtpl:91
|
||||
}
|
||||
//line views/stuff.qtpl:90
|
||||
//line views/stuff.qtpl:91
|
||||
qw422016.N().S(`
|
||||
</ul>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
func WriteHyphaListHTML(qq422016 qtio422016.Writer) {
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
StreamHyphaListHTML(qw422016)
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
func HyphaListHTML() string {
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
WriteHyphaListHTML(qb422016)
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:94
|
||||
//line views/stuff.qtpl:95
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:96
|
||||
//line views/stuff.qtpl:97
|
||||
func StreamAboutHTML(qw422016 *qt422016.Writer) {
|
||||
//line views/stuff.qtpl:96
|
||||
//line views/stuff.qtpl:97
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section>
|
||||
<h1>About `)
|
||||
//line views/stuff.qtpl:100
|
||||
//line views/stuff.qtpl:101
|
||||
qw422016.E().S(cfg.WikiName)
|
||||
//line views/stuff.qtpl:100
|
||||
//line views/stuff.qtpl:101
|
||||
qw422016.N().S(`</h1>
|
||||
<ul>
|
||||
<li><b><a href="https://mycorrhiza.lesarbr.es">MycorrhizaWiki</a> version:</b> 1.2.0 indev</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:103
|
||||
//line views/stuff.qtpl:104
|
||||
if user.AuthUsed {
|
||||
//line views/stuff.qtpl:103
|
||||
//line views/stuff.qtpl:104
|
||||
qw422016.N().S(` <li><b>User count:</b> `)
|
||||
//line views/stuff.qtpl:104
|
||||
//line views/stuff.qtpl:105
|
||||
qw422016.N().D(user.Count())
|
||||
//line views/stuff.qtpl:104
|
||||
//line views/stuff.qtpl:105
|
||||
qw422016.N().S(`</li>
|
||||
<li><b>Home page:</b> <a href="/">`)
|
||||
//line views/stuff.qtpl:105
|
||||
//line views/stuff.qtpl:106
|
||||
qw422016.E().S(cfg.HomeHypha)
|
||||
//line views/stuff.qtpl:105
|
||||
//line views/stuff.qtpl:106
|
||||
qw422016.N().S(`</a></li>
|
||||
<li><b>Administrators:</b>`)
|
||||
//line views/stuff.qtpl:106
|
||||
//line views/stuff.qtpl:107
|
||||
for i, username := range user.ListUsersWithGroup("admin") {
|
||||
//line views/stuff.qtpl:107
|
||||
//line views/stuff.qtpl:108
|
||||
if i > 0 {
|
||||
//line views/stuff.qtpl:107
|
||||
//line views/stuff.qtpl:108
|
||||
qw422016.N().S(`<span aria-hidden="true">, </span>
|
||||
`)
|
||||
//line views/stuff.qtpl:108
|
||||
//line views/stuff.qtpl:109
|
||||
}
|
||||
//line views/stuff.qtpl:108
|
||||
//line views/stuff.qtpl:109
|
||||
qw422016.N().S(` <a href="/page/`)
|
||||
//line views/stuff.qtpl:109
|
||||
//line views/stuff.qtpl:110
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/stuff.qtpl:109
|
||||
//line views/stuff.qtpl:110
|
||||
qw422016.N().S(`/`)
|
||||
//line views/stuff.qtpl:109
|
||||
//line views/stuff.qtpl:110
|
||||
qw422016.E().S(username)
|
||||
//line views/stuff.qtpl:109
|
||||
//line views/stuff.qtpl:110
|
||||
qw422016.N().S(`">`)
|
||||
//line views/stuff.qtpl:109
|
||||
//line views/stuff.qtpl:110
|
||||
qw422016.E().S(username)
|
||||
//line views/stuff.qtpl:109
|
||||
//line views/stuff.qtpl:110
|
||||
qw422016.N().S(`</a>`)
|
||||
//line views/stuff.qtpl:109
|
||||
//line views/stuff.qtpl:110
|
||||
}
|
||||
//line views/stuff.qtpl:109
|
||||
//line views/stuff.qtpl:110
|
||||
qw422016.N().S(`</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:110
|
||||
//line views/stuff.qtpl:111
|
||||
} else {
|
||||
//line views/stuff.qtpl:110
|
||||
//line views/stuff.qtpl:111
|
||||
qw422016.N().S(` <li>This wiki does not use authorization</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:112
|
||||
//line views/stuff.qtpl:113
|
||||
}
|
||||
//line views/stuff.qtpl:112
|
||||
//line views/stuff.qtpl:113
|
||||
qw422016.N().S(` </ul>
|
||||
<p>See <a href="/list">/list</a> for information about hyphae on this wiki.</p>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
func WriteAboutHTML(qq422016 qtio422016.Writer) {
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
StreamAboutHTML(qw422016)
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
func AboutHTML() string {
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
WriteAboutHTML(qb422016)
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:118
|
||||
//line views/stuff.qtpl:119
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:120
|
||||
//line views/stuff.qtpl:121
|
||||
func StreamAdminPanelHTML(qw422016 *qt422016.Writer) {
|
||||
//line views/stuff.qtpl:120
|
||||
//line views/stuff.qtpl:121
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
@ -486,80 +487,80 @@ func StreamAdminPanelHTML(qw422016 *qt422016.Writer) {
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
func WriteAdminPanelHTML(qq422016 qtio422016.Writer) {
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
StreamAdminPanelHTML(qw422016)
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
func AdminPanelHTML() string {
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
WriteAdminPanelHTML(qb422016)
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:155
|
||||
//line views/stuff.qtpl:156
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:157
|
||||
//line views/stuff.qtpl:158
|
||||
func streamomnipresentScripts(qw422016 *qt422016.Writer) {
|
||||
//line views/stuff.qtpl:157
|
||||
//line views/stuff.qtpl:158
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/stuff.qtpl:158
|
||||
//line views/stuff.qtpl:159
|
||||
for _, scriptPath := range cfg.OmnipresentScripts {
|
||||
//line views/stuff.qtpl:158
|
||||
//line views/stuff.qtpl:159
|
||||
qw422016.N().S(`
|
||||
<script src="`)
|
||||
//line views/stuff.qtpl:159
|
||||
//line views/stuff.qtpl:160
|
||||
qw422016.E().S(scriptPath)
|
||||
//line views/stuff.qtpl:159
|
||||
//line views/stuff.qtpl:160
|
||||
qw422016.N().S(`"></script>
|
||||
`)
|
||||
//line views/stuff.qtpl:160
|
||||
//line views/stuff.qtpl:161
|
||||
}
|
||||
//line views/stuff.qtpl:160
|
||||
//line views/stuff.qtpl:161
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
func writeomnipresentScripts(qq422016 qtio422016.Writer) {
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
streamomnipresentScripts(qw422016)
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
func omnipresentScripts() string {
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
writeomnipresentScripts(qb422016)
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:161
|
||||
//line views/stuff.qtpl:162
|
||||
}
|
||||
|
71
web/web.go
@ -6,20 +6,20 @@ package web
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/assets"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/static"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
)
|
||||
|
||||
var stylesheets = []string{"default.css", "custom.css"}
|
||||
|
||||
// httpErr is used by many handlers to signal errors in a compact way.
|
||||
func httpErr(w http.ResponseWriter, status int, name, title, errMsg string) {
|
||||
log.Println(errMsg, "for", name)
|
||||
@ -41,51 +41,16 @@ func httpErr(w http.ResponseWriter, status int, name, title, errMsg string) {
|
||||
|
||||
func handlerStyle(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
if _, err := os.Stat(cfg.WikiDir + "/assets/common.css"); err == nil {
|
||||
http.ServeFile(w, rq, cfg.WikiDir+"/assets/common.css")
|
||||
} else {
|
||||
w.Header().Set("Content-Type", "text/css;charset=utf-8")
|
||||
w.Write([]byte(assets.DefaultCSS()))
|
||||
}
|
||||
if bytes, err := ioutil.ReadFile(cfg.WikiDir + "/assets/custom.css"); err == nil {
|
||||
w.Write(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
func handlerToolbar(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
w.Header().Set("Content-Type", "text/javascript;charset=utf-8")
|
||||
w.Write([]byte(assets.ToolbarJS()))
|
||||
}
|
||||
|
||||
// handlerIcon serves the requested icon. All icons are distributed as part of the Mycorrhiza binary.
|
||||
//
|
||||
// See assets/assets/icon/ for icons themselves, see assets/assets.qtpl for their sources.
|
||||
func handlerIcon(w http.ResponseWriter, rq *http.Request) {
|
||||
iconName := strings.TrimPrefix(rq.URL.Path, "/assets/icon/")
|
||||
if iconName == "https" {
|
||||
iconName = "http"
|
||||
}
|
||||
w.Header().Set("Content-Type", "image/svg+xml")
|
||||
icon := func() string {
|
||||
switch iconName {
|
||||
case "gemini":
|
||||
return assets.IconGemini()
|
||||
case "mailto":
|
||||
return assets.IconMailto()
|
||||
case "gopher":
|
||||
return assets.IconGopher()
|
||||
case "feed":
|
||||
return assets.IconFeed()
|
||||
default:
|
||||
return assets.IconHTTP()
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension("css"))
|
||||
for _, name := range stylesheets {
|
||||
file, err := static.FS.Open(name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}()
|
||||
_, err := io.WriteString(w, icon)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
io.Copy(w, file)
|
||||
file.Close()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func handlerUserList(w http.ResponseWriter, rq *http.Request) {
|
||||
@ -113,15 +78,15 @@ func Init() {
|
||||
initHistory()
|
||||
initStuff()
|
||||
|
||||
// Miscellaneous
|
||||
http.HandleFunc("/user-list/", handlerUserList)
|
||||
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(cfg.WikiDir+"/static"))))
|
||||
http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) {
|
||||
http.ServeFile(w, rq, cfg.WikiDir+"/static/favicon.ico")
|
||||
})
|
||||
http.HandleFunc("/assets/common.css", handlerStyle)
|
||||
http.HandleFunc("/assets/toolbar.js", handlerToolbar)
|
||||
http.HandleFunc("/assets/icon/", handlerIcon)
|
||||
http.HandleFunc("/robots.txt", handlerRobotsTxt)
|
||||
|
||||
// Static assets
|
||||
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(static.FS))))
|
||||
http.HandleFunc("/static/style.css", handlerStyle)
|
||||
|
||||
// Index page
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, rq *http.Request) {
|
||||
addr, _ := url.Parse("/hypha/" + cfg.HomeHypha) // Let's pray it never fails
|
||||
rq.URL = addr
|
||||
|