diff --git a/assets/assets.qtpl b/assets/assets.qtpl deleted file mode 100644 index 5330a7a..0000000 --- a/assets/assets.qtpl +++ /dev/null @@ -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 %} diff --git a/assets/assets.qtpl.go b/assets/assets.qtpl.go deleted file mode 100644 index 71355e9..0000000 --- a/assets/assets.qtpl.go +++ /dev/null @@ -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(` -`) -//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(` -`) -//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(` -`) -//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(` - - - -`) -//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(` - - RSS feed icon - - - - - - - - - -`) -//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 -} diff --git a/flag.go b/flag.go index 19c69d6..872f44c 100644 --- a/flag.go +++ b/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) } diff --git a/go.mod b/go.mod index e9297ed..109d91a 100644 --- a/go.mod +++ b/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 diff --git a/main.go b/main.go index 33e17f9..5f1cb7e 100644 --- a/main.go +++ b/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() diff --git a/assets/default.css b/static/default.css similarity index 96% rename from assets/default.css rename to static/default.css index 66d41a4..8ab0fed 100644 --- a/assets/default.css +++ b/static/default.css @@ -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; } diff --git a/static/icon/README.md b/static/icon/README.md new file mode 100644 index 0000000..676093a --- /dev/null +++ b/static/icon/README.md @@ -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. diff --git a/assets/icon/feed-icon.svg b/static/icon/feed.svg similarity index 100% rename from assets/icon/feed-icon.svg rename to static/icon/feed.svg diff --git a/assets/icon/gemini-protocol-icon.svg b/static/icon/gemini-proto.svg similarity index 100% rename from assets/icon/gemini-protocol-icon.svg rename to static/icon/gemini-proto.svg diff --git a/assets/icon/gopher-protocol-icon.svg b/static/icon/gopher-proto.svg similarity index 100% rename from assets/icon/gopher-protocol-icon.svg rename to static/icon/gopher-proto.svg diff --git a/assets/icon/http-protocol-icon.svg b/static/icon/http-proto.svg similarity index 100% rename from assets/icon/http-protocol-icon.svg rename to static/icon/http-proto.svg diff --git a/assets/icon/mailto-protocol-icon.svg b/static/icon/mailto-proto.svg similarity index 100% rename from assets/icon/mailto-protocol-icon.svg rename to static/icon/mailto-proto.svg diff --git a/static/static.go b/static/static.go new file mode 100644 index 0000000..f36ee71 --- /dev/null +++ b/static/static.go @@ -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, + }, + } +} diff --git a/assets/toolbar.js b/static/toolbar.js similarity index 100% rename from assets/toolbar.js rename to static/toolbar.js diff --git a/views/history.qtpl b/views/history.qtpl index 7049261..7b3cce4 100644 --- a/views/history.qtpl +++ b/views/history.qtpl @@ -45,7 +45,7 @@ if err != nil { recent changes -

Subscribe via RSS, Atom or JSON feed.

+

Subscribe via RSS, Atom or JSON feed.

{% comment %} Here I am, willing to add some accessibility using ARIA. Turns out, diff --git a/views/history.qtpl.go b/views/history.qtpl.go index 0a0462b..50cbad2 100644 --- a/views/history.qtpl.go +++ b/views/history.qtpl.go @@ -163,7 +163,7 @@ func StreamRecentChangesHTML(qw422016 *qt422016.Writer, n int) { recent changes -

Subscribe via RSS, Atom or JSON feed.

+

Subscribe via RSS, Atom or JSON feed.

`) //line views/history.qtpl:55 diff --git a/views/mutators.qtpl b/views/mutators.qtpl index 5b1c321..1ab396e 100644 --- a/views/mutators.qtpl +++ b/views/mutators.qtpl @@ -65,7 +65,7 @@ {% endif %} - + {% endfunc %} {% func EditHTML(rq *http.Request, hyphaName, textAreaFill, warning string) %} diff --git a/views/mutators.qtpl.go b/views/mutators.qtpl.go index 95ac60c..8c36ceb 100644 --- a/views/mutators.qtpl.go +++ b/views/mutators.qtpl.go @@ -141,7 +141,7 @@ func StreamToolbar(qw422016 *qt422016.Writer, u *user.User) { qw422016.N().S(` - + `) //line views/mutators.qtpl:69 } diff --git a/views/stuff.qtpl b/views/stuff.qtpl index 26117af..b3b359f 100644 --- a/views/stuff.qtpl +++ b/views/stuff.qtpl @@ -8,10 +8,11 @@ - - + {%s title %} + + {% for _, el := range headElements %}{%s= el %}{% endfor %} diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go index 9079a25..63a6cb0 100644 --- a/views/stuff.qtpl.go +++ b/views/stuff.qtpl.go @@ -39,22 +39,23 @@ func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string, u *user.User, - - + `) -//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(` + + `) -//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(` @@ -62,81 +63,81 @@ func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string, u *user.User, `) -//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(` `) -//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(`

List of users

`) -//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(`

Admins

    `) -//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(`
  1. `) -//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(`
  2. `) -//line views/stuff.qtpl:59 +//line views/stuff.qtpl:60 } -//line views/stuff.qtpl:59 +//line views/stuff.qtpl:60 qw422016.N().S(`

Moderators

    `) -//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(`
  1. `) -//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(`
  2. `) -//line views/stuff.qtpl:65 +//line views/stuff.qtpl:66 } -//line views/stuff.qtpl:65 +//line views/stuff.qtpl:66 qw422016.N().S(`

Editors

    `) -//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(`
  1. `) -//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(`
  2. `) -//line views/stuff.qtpl:71 +//line views/stuff.qtpl:72 } -//line views/stuff.qtpl:71 +//line views/stuff.qtpl:72 qw422016.N().S(`
`) -//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(`

List of hyphae

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.

`) -//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(`

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(`

See /list for information about hyphae on this wiki.

`) -//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(`
@@ -486,80 +487,80 @@ func StreamAdminPanelHTML(qw422016 *qt422016.Writer) {
`) -//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(` `) -//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 } diff --git a/web/web.go b/web/web.go index 95b3c44..ed0ca78 100644 --- a/web/web.go +++ b/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