1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-01-06 10:00:26 +00:00

Implement OpenGraph meta tags

This commit is contained in:
bouncepaw 2020-12-17 17:59:59 +05:00
parent df26dfe511
commit 7b9375da39
10 changed files with 183 additions and 102 deletions

View File

@ -10,7 +10,7 @@ import (
)
func init() {
flag.StringVar(&util.URL, "url", "http://0.0.0.0:$port", "URL at which your wiki can be found. Used to generate feeds")
flag.StringVar(&util.URL, "url", "http://0.0.0.0:$port", "URL at which your wiki can be found. Used to generate feeds and social media previews")
flag.StringVar(&util.ServerPort, "port", "1737", "Port to serve the wiki at using HTTP")
flag.StringVar(&util.HomePage, "home", "home", "The home page name")
flag.StringVar(&util.SiteTitle, "title", "🍄", "How to call your wiki in the navititle")

View File

@ -36,7 +36,7 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
textContents, err = history.FileAtRevision(textPath, revHash)
)
if err == nil {
contents = markup.ToHtml(hyphaName, textContents)
contents = markup.Doc(hyphaName, textContents).AsHTML()
}
treeHTML, _, _ := tree.Tree(hyphaName, IterateHyphaNamesWith)
page := templates.RevisionHTML(
@ -81,20 +81,27 @@ func handlerPage(w http.ResponseWriter, rq *http.Request) {
hyphaName = HyphaNameFromRq(rq, "page")
data, hyphaExists = HyphaStorage[hyphaName]
contents string
openGraph string
)
if hyphaExists {
fileContentsT, errT := ioutil.ReadFile(data.textPath)
_, errB := os.Stat(data.binaryPath)
if errT == nil {
contents = markup.ToHtml(hyphaName, string(fileContentsT))
md := markup.Doc(hyphaName, string(fileContentsT))
contents = md.AsHTML()
openGraph = md.OpenGraphHTML()
}
if !os.IsNotExist(errB) {
contents = binaryHtmlBlock(hyphaName, data) + contents
}
}
treeHTML, prevHypha, nextHypha := tree.Tree(hyphaName, IterateHyphaNamesWith)
util.HTTP200Page(w, base(hyphaName, templates.PageHTML(rq, hyphaName,
naviTitle(hyphaName),
contents,
treeHTML, prevHypha, nextHypha)))
util.HTTP200Page(w,
templates.BaseHTML(
hyphaName,
templates.PageHTML(rq, hyphaName,
naviTitle(hyphaName),
contents,
treeHTML, prevHypha, nextHypha),
openGraph))
}

View File

@ -33,6 +33,12 @@ func init() {
return
}
markup.HyphaIterate = IterateHyphaNamesWith
markup.HyphaImageForOG = func(hyphaName string) string {
if hd, isOld := GetHyphaData(hyphaName); isOld && hd.binaryPath != "" {
return util.URL + "/binary/" + hyphaName
}
return util.URL + "/favicon.ico"
}
}
// GetHyphaData finds a hypha addressed by `hyphaName` and returns its `hyphaData`. `hyphaData` is set to a zero value if this hypha does not exist. `isOld` is false if this hypha does not exist.

View File

@ -4,6 +4,8 @@ import (
"fmt"
"regexp"
"strings"
"github.com/bouncepaw/mycorrhiza/util"
)
var imgRe = regexp.MustCompile(`^img\s+{`)
@ -184,6 +186,14 @@ func (img *Img) binaryPathFor(path string) string {
}
}
func (img *Img) ogBinaryPathFor(path string) string {
path = img.binaryPathFor(path)
if strings.HasPrefix(path, "/binary/") {
return util.URL + path
}
return path
}
func (img *Img) pagePathFor(path string) string {
path = strings.TrimSpace(path)
if strings.IndexRune(path, ':') != -1 || strings.IndexRune(path, '/') == 0 {

View File

@ -9,6 +9,9 @@ import (
// HyphaExists holds function that checks that a hypha is present.
var HyphaExists func(string) bool
//
var HyphaImageForOG func(string) string
// HyphaAccess holds function that accesses a hypha by its name.
var HyphaAccess func(string) (rawText, binaryHtml string, err error)
@ -29,21 +32,21 @@ type GemLexerState struct {
type Line struct {
id int
// interface{} may be bad. What I need is a sum of string and Transclusion
// interface{} may be bad. TODO: a proper type
contents interface{}
}
func lex(name, content string) (ast []Line) {
var state = GemLexerState{name: name}
func (md *MycoDoc) lex() (ast []Line) {
var state = GemLexerState{name: md.hyphaName}
for _, line := range append(strings.Split(content, "\n"), "") {
geminiLineToAST(line, &state, &ast)
for _, line := range append(strings.Split(md.contents, "\n"), "") {
lineToAST(line, &state, &ast)
}
return ast
}
// Lex `line` in markup and save it to `ast` using `state`.
func geminiLineToAST(line string, state *GemLexerState, ast *[]Line) {
func lineToAST(line string, state *GemLexerState, ast *[]Line) {
addLine := func(text interface{}) {
*ast = append(*ast, Line{id: state.id, contents: text})
}

View File

@ -2,8 +2,12 @@
package markup
import (
"fmt"
"html"
"regexp"
"strings"
"github.com/bouncepaw/mycorrhiza/util"
)
// A Mycomarkup-formatted document
@ -11,24 +15,75 @@ type MycoDoc struct {
// data
hyphaName string
contents string
// indicators
parsedAlready bool
// results
ast []Line
html string
firstImageURL string
description string
}
// Constructor
func Doc(hyphaName, contents string) *MycoDoc {
return &MycoDoc{
md := &MycoDoc{
hyphaName: hyphaName,
contents: contents,
}
return md
}
func (md *MycoDoc) Lex(recursionLevel int) *MycoDoc {
if !md.parsedAlready {
md.ast = md.lex()
}
md.parsedAlready = true
return md
}
// AsHtml returns an html representation of the document
func (md *MycoDoc) AsHTML() string {
return ""
md.html = Parse(md.Lex(0).ast, 0, 0, 0)
return md.html
}
// Used to clear opengraph description from html tags. This method is usually bad because of dangers of malformed HTML, but I'm going to use it only for Mycorrhiza-generated HTML, so it's okay. The question mark is required; without it the whole string is eaten away.
var htmlTagRe = regexp.MustCompile(`<.*?>`)
// OpenGraphHTML returns an html representation of og: meta tags.
func (md *MycoDoc) OpenGraphHTML() string {
return ""
md.ogFillVars()
return strings.Join([]string{
ogTag("title", md.hyphaName),
ogTag("type", "article"),
ogTag("image", md.firstImageURL),
ogTag("url", util.URL+"/page/"+md.hyphaName),
ogTag("determiner", ""),
ogTag("description", htmlTagRe.ReplaceAllString(md.description, "")),
}, "\n")
}
func (md *MycoDoc) ogFillVars() *MycoDoc {
foundDesc := false
md.firstImageURL = HyphaImageForOG(md.hyphaName)
for _, line := range md.ast {
switch v := line.contents.(type) {
case string:
if !foundDesc {
md.description = v
foundDesc = true
}
case Img:
if len(v.entries) > 0 {
md.firstImageURL = v.entries[0].path.String()
}
}
}
return md
}
func ogTag(property, content string) string {
return fmt.Sprintf(`<meta property="og:%s" content="%s"/>`, property, content)
}
/* The rest of this file is currently unused. TODO: use it I guess */

View File

@ -1,35 +1,24 @@
package markup
import ()
const maxRecursionLevel = 3
type GemParserState struct {
recursionLevel int
}
func Parse(ast []Line, from, to int, state GemParserState) (html string) {
if state.recursionLevel > maxRecursionLevel {
func Parse(ast []Line, from, to int, recursionLevel int) (html string) {
if recursionLevel > maxRecursionLevel {
return "Transclusion depth limit"
}
for _, line := range ast {
if line.id >= from && (line.id <= to || to == 0) || line.id == -1 {
switch v := line.contents.(type) {
case Transclusion:
html += Transclude(v, state)
html += Transclude(v, recursionLevel)
case Img:
html += v.ToHtml()
case string:
html += v
default:
html += "Unknown"
html += "<b class='error'>Unknown element.</b>"
}
}
}
return html
}
func ToHtml(name, text string) string {
state := GemParserState{}
return Parse(lex(name, text), 0, 0, state)
}

View File

@ -17,14 +17,14 @@ type Transclusion struct {
}
// Transclude transcludes `xcl` and returns html representation.
func Transclude(xcl Transclusion, state GemParserState) (html string) {
state.recursionLevel++
func Transclude(xcl Transclusion, recursionLevel int) (html string) {
recursionLevel++
tmptOk := `<section class="transclusion transclusion_ok">
<a class="transclusion__link" href="/page/%s">%s</a>
<div class="transclusion__content">%s</div>
</section>`
tmptFailed := `<section class="transclusion transclusion_failed">
<p>Failed to transclude <a href="/page/%s">%s</a></p>
<p class="error">Hypha <a class="wikilink_new" href="/page/%s">%s</a> does not exist</p>
</section>`
if xcl.from == xclError || xcl.to == xclError || xcl.from > xcl.to {
return fmt.Sprintf(tmptFailed, xcl.name, xcl.name)
@ -34,7 +34,8 @@ func Transclude(xcl Transclusion, state GemParserState) (html string) {
if err != nil {
return fmt.Sprintf(tmptFailed, xcl.name, xcl.name)
}
xclText := Parse(lex(xcl.name, rawText), xcl.from, xcl.to, state)
md := Doc(xcl.name, rawText)
xclText := Parse(md.lex(), xcl.from, xcl.to, recursionLevel)
return fmt.Sprintf(tmptOk, xcl.name, xcl.name, binaryHtml+xclText)
}

View File

@ -1,10 +1,11 @@
{% func BaseHTML(title, body string) %}
{% func BaseHTML(title, body string, headElements ...string) %}
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/static/common.css">
<title>{%s title %}</title>
{% for _, el := range headElements %}{%s= el %}{% endfor %}
</head>
<body>
{%s= body %}

View File

@ -18,7 +18,7 @@ var (
)
//line templates/http_stuff.qtpl:1
func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string) {
func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string, headElements ...string) {
//line templates/http_stuff.qtpl:1
qw422016.N().S(`
<!doctype html>
@ -31,55 +31,64 @@ func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string) {
qw422016.E().S(title)
//line templates/http_stuff.qtpl:7
qw422016.N().S(`</title>
`)
//line templates/http_stuff.qtpl:8
for _, el := range headElements {
//line templates/http_stuff.qtpl:8
qw422016.N().S(el)
//line templates/http_stuff.qtpl:8
}
//line templates/http_stuff.qtpl:8
qw422016.N().S(`
</head>
<body>
`)
//line templates/http_stuff.qtpl:10
//line templates/http_stuff.qtpl:11
qw422016.N().S(body)
//line templates/http_stuff.qtpl:10
//line templates/http_stuff.qtpl:11
qw422016.N().S(`
</body>
</html>
`)
//line templates/http_stuff.qtpl:13
//line templates/http_stuff.qtpl:14
}
//line templates/http_stuff.qtpl:13
func WriteBaseHTML(qq422016 qtio422016.Writer, title, body string) {
//line templates/http_stuff.qtpl:13
//line templates/http_stuff.qtpl:14
func WriteBaseHTML(qq422016 qtio422016.Writer, title, body string, headElements ...string) {
//line templates/http_stuff.qtpl:14
qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/http_stuff.qtpl:13
StreamBaseHTML(qw422016, title, body)
//line templates/http_stuff.qtpl:13
//line templates/http_stuff.qtpl:14
StreamBaseHTML(qw422016, title, body, headElements...)
//line templates/http_stuff.qtpl:14
qt422016.ReleaseWriter(qw422016)
//line templates/http_stuff.qtpl:13
//line templates/http_stuff.qtpl:14
}
//line templates/http_stuff.qtpl:13
func BaseHTML(title, body string) string {
//line templates/http_stuff.qtpl:13
//line templates/http_stuff.qtpl:14
func BaseHTML(title, body string, headElements ...string) string {
//line templates/http_stuff.qtpl:14
qb422016 := qt422016.AcquireByteBuffer()
//line templates/http_stuff.qtpl:13
WriteBaseHTML(qb422016, title, body)
//line templates/http_stuff.qtpl:13
//line templates/http_stuff.qtpl:14
WriteBaseHTML(qb422016, title, body, headElements...)
//line templates/http_stuff.qtpl:14
qs422016 := string(qb422016.B)
//line templates/http_stuff.qtpl:13
//line templates/http_stuff.qtpl:14
qt422016.ReleaseByteBuffer(qb422016)
//line templates/http_stuff.qtpl:13
//line templates/http_stuff.qtpl:14
return qs422016
//line templates/http_stuff.qtpl:13
//line templates/http_stuff.qtpl:14
}
//line templates/http_stuff.qtpl:15
//line templates/http_stuff.qtpl:16
func StreamHyphaListHTML(qw422016 *qt422016.Writer, tbody string, pageCount int) {
//line templates/http_stuff.qtpl:15
//line templates/http_stuff.qtpl:16
qw422016.N().S(`
<main>
<h1>List of hyphae</h1>
<p>This wiki has `)
//line templates/http_stuff.qtpl:18
//line templates/http_stuff.qtpl:19
qw422016.N().D(pageCount)
//line templates/http_stuff.qtpl:18
//line templates/http_stuff.qtpl:19
qw422016.N().S(` hyphae.</p>
<table>
<thead>
@ -90,105 +99,105 @@ func StreamHyphaListHTML(qw422016 *qt422016.Writer, tbody string, pageCount int)
</thead>
<tbody>
`)
//line templates/http_stuff.qtpl:27
//line templates/http_stuff.qtpl:28
qw422016.N().S(tbody)
//line templates/http_stuff.qtpl:27
//line templates/http_stuff.qtpl:28
qw422016.N().S(`
</tbody>
</table>
</main>
`)
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
}
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
func WriteHyphaListHTML(qq422016 qtio422016.Writer, tbody string, pageCount int) {
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
StreamHyphaListHTML(qw422016, tbody, pageCount)
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
qt422016.ReleaseWriter(qw422016)
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
}
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
func HyphaListHTML(tbody string, pageCount int) string {
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
qb422016 := qt422016.AcquireByteBuffer()
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
WriteHyphaListHTML(qb422016, tbody, pageCount)
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
qs422016 := string(qb422016.B)
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
qt422016.ReleaseByteBuffer(qb422016)
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
return qs422016
//line templates/http_stuff.qtpl:31
//line templates/http_stuff.qtpl:32
}
//line templates/http_stuff.qtpl:33
//line templates/http_stuff.qtpl:34
func StreamHyphaListRowHTML(qw422016 *qt422016.Writer, hyphaName, binaryMime string, binaryPresent bool) {
//line templates/http_stuff.qtpl:33
//line templates/http_stuff.qtpl:34
qw422016.N().S(`
<tr>
<td><a href="/page/`)
//line templates/http_stuff.qtpl:35
//line templates/http_stuff.qtpl:36
qw422016.E().S(hyphaName)
//line templates/http_stuff.qtpl:35
//line templates/http_stuff.qtpl:36
qw422016.N().S(`">`)
//line templates/http_stuff.qtpl:35
//line templates/http_stuff.qtpl:36
qw422016.E().S(hyphaName)
//line templates/http_stuff.qtpl:35
//line templates/http_stuff.qtpl:36
qw422016.N().S(`</a></td>
`)
//line templates/http_stuff.qtpl:36
//line templates/http_stuff.qtpl:37
if binaryPresent {
//line templates/http_stuff.qtpl:36
//line templates/http_stuff.qtpl:37
qw422016.N().S(`
<td>`)
//line templates/http_stuff.qtpl:37
//line templates/http_stuff.qtpl:38
qw422016.E().S(binaryMime)
//line templates/http_stuff.qtpl:37
//line templates/http_stuff.qtpl:38
qw422016.N().S(`</td>
`)
//line templates/http_stuff.qtpl:38
//line templates/http_stuff.qtpl:39
} else {
//line templates/http_stuff.qtpl:38
//line templates/http_stuff.qtpl:39
qw422016.N().S(`
<td></td>
`)
//line templates/http_stuff.qtpl:40
//line templates/http_stuff.qtpl:41
}
//line templates/http_stuff.qtpl:40
//line templates/http_stuff.qtpl:41
qw422016.N().S(`
</tr>
`)
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
}
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
func WriteHyphaListRowHTML(qq422016 qtio422016.Writer, hyphaName, binaryMime string, binaryPresent bool) {
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
StreamHyphaListRowHTML(qw422016, hyphaName, binaryMime, binaryPresent)
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
qt422016.ReleaseWriter(qw422016)
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
}
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
func HyphaListRowHTML(hyphaName, binaryMime string, binaryPresent bool) string {
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
qb422016 := qt422016.AcquireByteBuffer()
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
WriteHyphaListRowHTML(qb422016, hyphaName, binaryMime, binaryPresent)
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
qs422016 := string(qb422016.B)
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
qt422016.ReleaseByteBuffer(qb422016)
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
return qs422016
//line templates/http_stuff.qtpl:42
//line templates/http_stuff.qtpl:43
}