diff --git a/gemini.go b/gemini.go index 8cbd6df..858f91a 100644 --- a/gemini.go +++ b/gemini.go @@ -20,8 +20,9 @@ import ( "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/hyphae" - "github.com/bouncepaw/mycorrhiza/markup" "github.com/bouncepaw/mycorrhiza/util" + + "github.com/bouncepaw/mycomarkup/legacy" ) func geminiHomeHypha(w *gemini.ResponseWriter, rq *gemini.Request) { diff --git a/go.mod b/go.mod index 1fde72b..de01040 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.14 require ( git.sr.ht/~adnano/go-gemini v0.1.13 github.com/adrg/xdg v0.2.2 - github.com/bouncepaw/mycomarkup v0.0.0-20210511092446-956f169b1499 + github.com/bouncepaw/mycomarkup v0.0.0-20210512131946-becfae76473f github.com/go-ini/ini v1.62.0 github.com/gorilla/feeds v1.1.1 github.com/kr/pretty v0.2.1 // indirect diff --git a/go.sum b/go.sum index 785a95f..a6fcdf1 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/bouncepaw/mycomarkup v0.0.0-20210502065108-4ddae294864d h1:H20wX93QMe github.com/bouncepaw/mycomarkup v0.0.0-20210502065108-4ddae294864d/go.mod h1:fx0FBKaCaV1fofgCQOu2lNIVB/5EoDg/83i8BgBdgpc= github.com/bouncepaw/mycomarkup v0.0.0-20210511092446-956f169b1499 h1:RLKVj992QuayqjpIJ7M2csRjfhAnu9EO2r1Bm4D/WlU= github.com/bouncepaw/mycomarkup v0.0.0-20210511092446-956f169b1499/go.mod h1:fx0FBKaCaV1fofgCQOu2lNIVB/5EoDg/83i8BgBdgpc= +github.com/bouncepaw/mycomarkup v0.0.0-20210512131946-becfae76473f h1:PgXG/AqO96jahMGQA81CWclIg90gsGt5kK4o7y0eZy8= +github.com/bouncepaw/mycomarkup v0.0.0-20210512131946-becfae76473f/go.mod h1:4Fz80hsrXi3lRVZuVfIk5+2xocp50CFAbJfGeJWb5aM= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-ini/ini v1.62.0 h1:7VJT/ZXjzqSrvtraFp4ONq80hTcRQth1c9ZnQ3uNQvU= @@ -62,6 +64,7 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/markup/hr.go b/markup/hr.go deleted file mode 100644 index 278138a..0000000 --- a/markup/hr.go +++ /dev/null @@ -1,34 +0,0 @@ -package markup - -import ( - "unicode" -) - -// MatchesHorizontalLine checks if the string can be interpreted as suitable for rendering as
).
-func MatchesHorizontalLine(line string) bool {
- counter := 0
-
- // Check initially that the symbol is "-". If it is not a "-", it is most likely a space or another character.
- // With unicode.IsLetter() we can separate spaces and characters.
- for _, ch := range line {
- if ch == '-' {
- counter++
- continue
- }
- // If we bump into any other character (letter) in the line, it is immediately an incorrect horizontal line.
- // There is no point in counting further, we end the loop.
- if unicode.IsLetter(ch) {
- counter = 0
- break
- }
- }
-
- if counter >= 4 {
- return true
- }
-
- return false
-}
diff --git a/markup/img.go b/markup/img.go
deleted file mode 100644
index 5c4b51b..0000000
--- a/markup/img.go
+++ /dev/null
@@ -1,203 +0,0 @@
-package markup
-
-import (
- "fmt"
- "regexp"
- "strings"
-
- "github.com/bouncepaw/mycomarkup/links"
-)
-
-var imgRe = regexp.MustCompile(`^img\s+{`)
-
-func MatchesImg(line string) bool {
- return imgRe.MatchString(line)
-}
-
-type imgState int
-
-const (
- inRoot imgState = iota
- inName
- inDimensionsW
- inDimensionsH
- inDescription
-)
-
-type Img struct {
- entries []imgEntry
- currEntry imgEntry
- hyphaName string
- state imgState
-}
-
-func (img *Img) pushEntry() {
- if strings.TrimSpace(img.currEntry.path.String()) != "" {
- img.currEntry.srclink = links.From(img.currEntry.path.String(), "", img.hyphaName)
- // img.currEntry.srclink.DoubtExistence()
- img.entries = append(img.entries, img.currEntry)
- img.currEntry = imgEntry{}
- img.currEntry.path.Reset()
- }
-}
-
-func (img *Img) Process(line string) (shouldGoBackToNormal bool) {
- stateToProcessor := map[imgState]func(rune) bool{
- inRoot: img.processInRoot,
- inName: img.processInName,
- inDimensionsW: img.processInDimensionsW,
- inDimensionsH: img.processInDimensionsH,
- inDescription: img.processInDescription,
- }
- for _, r := range line {
- if shouldReturnTrue := stateToProcessor[img.state](r); shouldReturnTrue {
- return true
- }
- }
- return false
-}
-
-func (img *Img) processInDescription(r rune) (shouldReturnTrue bool) {
- switch r {
- case '}':
- img.state = inName
- default:
- img.currEntry.desc.WriteRune(r)
- }
- return false
-}
-
-func (img *Img) processInRoot(r rune) (shouldReturnTrue bool) {
- switch r {
- case '}':
- img.pushEntry()
- return true
- case '\n', '\r':
- img.pushEntry()
- case ' ', '\t':
- default:
- img.state = inName
- img.currEntry = imgEntry{}
- img.currEntry.path.Reset()
- img.currEntry.path.WriteRune(r)
- }
- return false
-}
-
-func (img *Img) processInName(r rune) (shouldReturnTrue bool) {
- switch r {
- case '}':
- img.pushEntry()
- return true
- case '|':
- img.state = inDimensionsW
- case '{':
- img.state = inDescription
- case '\n', '\r':
- img.pushEntry()
- img.state = inRoot
- default:
- img.currEntry.path.WriteRune(r)
- }
- return false
-}
-
-func (img *Img) processInDimensionsW(r rune) (shouldReturnTrue bool) {
- switch r {
- case '}':
- img.pushEntry()
- return true
- case '*':
- img.state = inDimensionsH
- case ' ', '\t', '\n':
- case '{':
- img.state = inDescription
- default:
- img.currEntry.sizeW.WriteRune(r)
- }
- return false
-}
-
-func (img *Img) processInDimensionsH(r rune) (shouldGoBackToNormal bool) {
- switch r {
- case '}':
- img.pushEntry()
- return true
- case ' ', '\t', '\n':
- case '{':
- img.state = inDescription
- default:
- img.currEntry.sizeH.WriteRune(r)
- }
- return false
-}
-
-func ImgFromFirstLine(line, hyphaName string) (img *Img, shouldGoBackToNormal bool) {
- img = &Img{
- hyphaName: hyphaName,
- entries: make([]imgEntry, 0),
- }
- line = line[strings.IndexRune(line, '{')+1:]
- return img, img.Process(line)
-}
-
-func (img *Img) pagePathFor(path string) string {
- path = strings.TrimSpace(path)
- if strings.IndexRune(path, ':') != -1 || strings.IndexRune(path, '/') == 0 {
- return path
- } else {
- return "/page/" + xclCanonicalName(img.hyphaName, path)
- }
-}
-
-func parseDimensions(dimensions string) (sizeW, sizeH string) {
- xIndex := strings.IndexRune(dimensions, '*')
- if xIndex == -1 { // If no x in dimensions
- sizeW = strings.TrimSpace(dimensions)
- } else {
- sizeW = strings.TrimSpace(dimensions[:xIndex])
- sizeH = strings.TrimSpace(strings.TrimPrefix(dimensions, dimensions[:xIndex+1]))
- }
- return
-}
-
-func (img *Img) markExistenceOfSrcLinks() {
- HyphaIterate(func(hn string) {
- for _, entry := range img.entries {
- if hn == entry.srclink.Address() {
- entry.srclink.DestinationUnknown = false
- }
- }
- })
-}
-
-func (img *Img) ToHtml() (html string) {
- img.markExistenceOfSrcLinks()
- isOneImageOnly := len(img.entries) == 1 && img.entries[0].desc.Len() == 0
- if isOneImageOnly {
- html += ` %s `)
-
-func extractLinks(html string, ch chan string) {
- if results := reLinks.FindAllStringSubmatch(html, -1); results != nil {
- for _, result := range results {
- // result[0] is always present at this point and is not needed, because it is the whole matched substring (which we don't need)
- ch <- result[1]
- }
- }
-}
-
-func extractImageLinks(img Img, ch chan string) {
- for _, entry := range img.entries {
- if entry.srclink.OfKind(links.LinkLocalHypha) {
- ch <- entry.srclink.Address()
- }
- }
-}
diff --git a/markup/paragraph.go b/markup/paragraph.go
deleted file mode 100644
index a576fee..0000000
--- a/markup/paragraph.go
+++ /dev/null
@@ -1,185 +0,0 @@
-package markup
-
-import (
- "bytes"
- "fmt"
- "html"
- "strings"
- "unicode"
-)
-
-type spanTokenType int
-
-const (
- spanTextNode = iota
- spanItalic
- spanBold
- spanMono
- spanSuper
- spanSub
- spanMark
- spanStrike
- spanLink
-)
-
-func tagFromState(stt spanTokenType, tagState map[spanTokenType]bool, tagName, originalForm string) string {
- if tagState[spanMono] && (stt != spanMono) {
- return originalForm
- }
- if tagState[stt] {
- tagState[stt] = false
- return fmt.Sprintf("%s>", tagName)
- } else {
- tagState[stt] = true
- return fmt.Sprintf("<%s>", tagName)
- }
-}
-
-func getLinkNode(input *bytes.Buffer, hyphaName string, isBracketedLink bool) string {
- if isBracketedLink {
- input.Next(2) // drop those [[
- }
- var (
- escaping = false
- addrBuf = bytes.Buffer{}
- displayBuf = bytes.Buffer{}
- currBuf = &addrBuf
- )
- for input.Len() != 0 {
- b, _ := input.ReadByte()
- if escaping {
- currBuf.WriteByte(b)
- escaping = false
- } else if isBracketedLink && b == '|' && currBuf == &addrBuf {
- currBuf = &displayBuf
- } else if isBracketedLink && b == ']' && bytes.HasPrefix(input.Bytes(), []byte{']'}) {
- input.Next(1)
- break
- } else if !isBracketedLink && (unicode.IsSpace(rune(b)) || strings.ContainsRune("<>{}|\\^[]`,()", rune(b))) {
- input.UnreadByte()
- break
- } else {
- currBuf.WriteByte(b)
- }
- }
- href, text, class := LinkParts(addrBuf.String(), displayBuf.String(), hyphaName)
- return fmt.Sprintf(`%s`, href, class, html.EscapeString(text))
-}
-
-// getTextNode splits the `input` into two parts `textNode` and `rest` by the first encountered rune that resembles a span tag. If there is none, `textNode = input`, `rest = ""`. It handles escaping with backslash.
-func getTextNode(input *bytes.Buffer) string {
- var (
- textNodeBuffer = bytes.Buffer{}
- escaping = false
- startsWith = func(t string) bool {
- return bytes.HasPrefix(input.Bytes(), []byte(t))
- }
- couldBeLinkStart = func() bool {
- return startsWith("https://") || startsWith("http://") || startsWith("gemini://") || startsWith("gopher://") || startsWith("ftp://")
- }
- )
- // Always read the first byte in advance to avoid endless loops that kill computers (sad experience)
- if input.Len() != 0 {
- b, _ := input.ReadByte()
- textNodeBuffer.WriteByte(b)
- }
- for input.Len() != 0 {
- // Assume no error is possible because we check for length
- b, _ := input.ReadByte()
- if escaping {
- textNodeBuffer.WriteByte(b)
- escaping = false
- } else if b == '\\' {
- escaping = true
- } else if strings.IndexByte("/*`^,![~", b) >= 0 {
- input.UnreadByte()
- break
- } else if couldBeLinkStart() {
- textNodeBuffer.WriteByte(b)
- break
- } else {
- textNodeBuffer.WriteByte(b)
- }
- }
- return textNodeBuffer.String()
-}
-
-func ParagraphToHtml(hyphaName, input string) string {
- var (
- p = bytes.NewBufferString(input)
- ret strings.Builder
- // true = tag is opened, false = tag is not opened
- tagState = map[spanTokenType]bool{
- spanItalic: false,
- spanBold: false,
- spanMono: false,
- spanSuper: false,
- spanSub: false,
- spanMark: false,
- spanLink: false,
- }
- startsWith = func(t string) bool {
- return bytes.HasPrefix(p.Bytes(), []byte(t))
- }
- noTagsActive = func() bool {
- return !(tagState[spanItalic] || tagState[spanBold] || tagState[spanMono] || tagState[spanSuper] || tagState[spanSub] || tagState[spanMark] || tagState[spanLink])
- }
- )
-
- for p.Len() != 0 {
- switch {
- case startsWith("//"):
- ret.WriteString(tagFromState(spanItalic, tagState, "em", "//"))
- p.Next(2)
- case startsWith("**"):
- ret.WriteString(tagFromState(spanBold, tagState, "strong", "**"))
- p.Next(2)
- case startsWith("`"):
- ret.WriteString(tagFromState(spanMono, tagState, "code", "`"))
- p.Next(1)
- case startsWith("^"):
- ret.WriteString(tagFromState(spanSuper, tagState, "sup", "^"))
- p.Next(1)
- case startsWith(",,"):
- ret.WriteString(tagFromState(spanSub, tagState, "sub", ",,"))
- p.Next(2)
- case startsWith("!!"):
- ret.WriteString(tagFromState(spanMark, tagState, "mark", "!!"))
- p.Next(2)
- case startsWith("~~"):
- ret.WriteString(tagFromState(spanMark, tagState, "s", "~~"))
- p.Next(2)
- case startsWith("[["):
- ret.WriteString(getLinkNode(p, hyphaName, true))
- case (startsWith("https://") || startsWith("http://") || startsWith("gemini://") || startsWith("gopher://") || startsWith("ftp://")) && noTagsActive():
- ret.WriteString(getLinkNode(p, hyphaName, false))
- default:
- ret.WriteString(html.EscapeString(getTextNode(p)))
- }
- }
-
- for stt, open := range tagState {
- if open {
- switch stt {
- case spanItalic:
- ret.WriteString(tagFromState(spanItalic, tagState, "em", "//"))
- case spanBold:
- ret.WriteString(tagFromState(spanBold, tagState, "strong", "**"))
- case spanMono:
- ret.WriteString(tagFromState(spanMono, tagState, "code", "`"))
- case spanSuper:
- ret.WriteString(tagFromState(spanSuper, tagState, "sup", "^"))
- case spanSub:
- ret.WriteString(tagFromState(spanSub, tagState, "sub", ",,"))
- case spanMark:
- ret.WriteString(tagFromState(spanMark, tagState, "mark", "!!"))
- case spanStrike:
- ret.WriteString(tagFromState(spanMark, tagState, "s", "~~"))
- case spanLink:
- ret.WriteString(tagFromState(spanLink, tagState, "a", "[["))
- }
- }
- }
-
- return ret.String()
-}
diff --git a/markup/parser.go b/markup/parser.go
deleted file mode 100644
index db715f1..0000000
--- a/markup/parser.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package markup
-
-const maxRecursionLevel = 3
-
-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, recursionLevel)
- case Img:
- html += v.ToHtml()
- case Table:
- html += v.asHtml()
- case *List:
- html += v.RenderAsHtml()
- case string:
- html += v
- default:
- html += "Unknown element."
- }
- }
- }
- return html
-}
diff --git a/markup/table.go b/markup/table.go
deleted file mode 100644
index b1ddbff..0000000
--- a/markup/table.go
+++ /dev/null
@@ -1,230 +0,0 @@
-package markup
-
-import (
- "fmt"
- "regexp"
- "strings"
- "unicode"
-)
-
-var tableRe = regexp.MustCompile(`^table\s+{`)
-
-func MatchesTable(line string) bool {
- return tableRe.MatchString(line)
-}
-
-func TableFromFirstLine(line, hyphaName string) *Table {
- return &Table{
- hyphaName: hyphaName,
- caption: line[strings.IndexRune(line, '{')+1:],
- rows: make([]*tableRow, 0),
- }
-}
-
-func (t *Table) Process(line string) (shouldGoBackToNormal bool) {
- if strings.TrimSpace(line) == "}" && !t.inMultiline {
- return true
- }
- if !t.inMultiline {
- t.pushRow()
- }
- var (
- inLink bool
- skipNext bool
- escaping bool
- lookingForNonSpace = !t.inMultiline
- countingColspan bool
- )
- for i, r := range line {
- switch {
- case skipNext:
- skipNext = false
- continue
-
- case lookingForNonSpace && unicode.IsSpace(r):
- case lookingForNonSpace && (r == '!' || r == '|'):
- t.currCellMarker = r
- t.currColspan = 1
- lookingForNonSpace = false
- countingColspan = true
- case lookingForNonSpace:
- t.currCellMarker = '^' // ^ represents implicit |, not part of syntax
- t.currColspan = 1
- lookingForNonSpace = false
- t.currCellBuilder.WriteRune(r)
-
- case escaping:
- t.currCellBuilder.WriteRune(r)
- case inLink && r == ']' && len(line)-1 > i && line[i+1] == ']':
- t.currCellBuilder.WriteString("]]")
- inLink = false
- skipNext = true
- case inLink:
- t.currCellBuilder.WriteRune(r)
-
- case t.inMultiline && r == '}':
- t.inMultiline = false
- case t.inMultiline && i == len(line)-1:
- t.currCellBuilder.WriteRune('\n')
- case t.inMultiline:
- t.currCellBuilder.WriteRune(r)
-
- // Not in multiline:
- case (r == '|' || r == '!') && !countingColspan:
- t.pushCell()
- t.currCellMarker = r
- t.currColspan = 1
- countingColspan = true
- case r == t.currCellMarker && (r == '|' || r == '!') && countingColspan:
- t.currColspan++
- case r == '{':
- t.inMultiline = true
- countingColspan = false
- case r == '[' && len(line)-1 > i && line[i+1] == '[':
- t.currCellBuilder.WriteString("[[")
- inLink = true
- skipNext = true
- case i == len(line)-1:
- t.pushCell()
- default:
- t.currCellBuilder.WriteRune(r)
- countingColspan = false
- }
- }
- return false
-}
-
-type Table struct {
- // data
- hyphaName string
- caption string
- rows []*tableRow
- // state
- inMultiline bool
- // tmp
- currCellMarker rune
- currColspan uint
- currCellBuilder strings.Builder
-}
-
-func (t *Table) pushRow() {
- t.rows = append(t.rows, &tableRow{
- cells: make([]*tableCell, 0),
- })
-}
-
-func (t *Table) pushCell() {
- tc := &tableCell{
- content: t.currCellBuilder.String(),
- colspan: t.currColspan,
- }
- switch t.currCellMarker {
- case '|', '^':
- tc.kind = tableCellDatum
- case '!':
- tc.kind = tableCellHeader
- }
- // We expect the table to have at least one row ready, so no nil-checking
- tr := t.rows[len(t.rows)-1]
- tr.cells = append(tr.cells, tc)
- t.currCellBuilder = strings.Builder{}
-}
-
-func (t *Table) asHtml() (html string) {
- if t.caption != "" {
- html += fmt.Sprintf(" Hypha %s does not exist
`
- }
- html += ParagraphToHtml(hyphaName, line)
- }
- }
- return `
")))
- state.buf = ""
- }
- }
-
- // Process empty lines depending on the current state
- if "" == strings.TrimSpace(line) {
- switch state.where {
- case "pre":
- state.buf += "\n"
- case "launchpad":
- state.where = ""
- addLine(state.buf + "")
- case "p":
- addParagraphIfNeeded()
- }
- return
- }
-
- startsWith := func(token string) bool {
- return strings.HasPrefix(line, token)
- }
- addHeading := func(i int) {
- id := util.LettersNumbersOnly(line[i+1:])
- addLine(fmt.Sprintf(`", state.id, strings.TrimPrefix(line, "```"))
- default:
- state.where = ""
- addLine(state.buf + "")
- goto normalState
- }
- return
-
-normalState:
- state.id++
- switch {
-
- case startsWith("```"):
- addParagraphIfNeeded()
- state.where = "pre"
- state.buf = fmt.Sprintf("
", state.id, strings.TrimPrefix(line, "```"))
-
- case startsWith("###### "):
- addParagraphIfNeeded()
- addHeading(6)
- case startsWith("##### "):
- addParagraphIfNeeded()
- addHeading(5)
- case startsWith("#### "):
- addParagraphIfNeeded()
- addHeading(4)
- case startsWith("### "):
- addParagraphIfNeeded()
- addHeading(3)
- case startsWith("## "):
- addParagraphIfNeeded()
- addHeading(2)
- case startsWith("# "):
- addParagraphIfNeeded()
- addHeading(1)
-
- case startsWith(">"):
- addParagraphIfNeeded()
- addLine(
- fmt.Sprintf(
- "
%s
",
- state.id,
- ParagraphToHtml(state.name, remover(">")(line)),
- ),
- )
- case startsWith("=>"):
- addParagraphIfNeeded()
- state.where = "launchpad"
- state.buf = fmt.Sprintf("\n", state.id)
- goto launchpadState
-
- case startsWith("<="):
- addParagraphIfNeeded()
- addLine(parseTransclusion(line, state.name))
- case MatchesHorizontalLine(line):
- addParagraphIfNeeded()
- *ast = append(*ast, Line{id: -1, contents: "
")
- }
- }
-
- if len(item.content) > 0 {
- b.WriteString("")
- }
-}
-
-// A structure representing ordered and unordered lists in the AST.
-type List struct {
- curr *listItem
- hyphaName string
- ordered bool
- finalized bool
-}
-
-func NewList(line, hyphaName string) (*List, bool) {
- list := &List{
- hyphaName: hyphaName,
- curr: newListItem(nil),
- }
- return list, list.Parse(line)
-}
-
-func (list *List) pushItem() {
- item := newListItem(list.curr)
- list.curr.children = append(list.curr.children, item)
- list.curr = item
-}
-
-func (list *List) popItem() {
- if list.curr == nil {
- return
- }
- list.curr = list.curr.parent
-}
-
-func (list *List) balance(level int) {
- for level > list.curr.depth {
- list.pushItem()
- }
-
- for level < list.curr.depth {
- list.popItem()
- }
-}
-
-func (list *List) Parse(line string) (done bool) {
- level, offset, ordered, err := parseListItem(line)
- if err != nil {
- list.Finalize()
- return true
- }
-
- // update ordered flag if the current node is the root one
- // (i.e. no parsing has been done yet)
- if list.curr.parent == nil {
- list.ordered = ordered
- }
-
- // if list type has suddenly changed (ill-formatted list), quit
- if ordered != list.ordered {
- list.Finalize()
- return true
- }
-
- list.balance(level)
-
- // if the current node already has content, create a new one
- // to prevent overwriting existing content (effectively creating
- // a new sibling node)
- if len(list.curr.content) > 0 {
- list.popItem()
- list.pushItem()
- }
-
- list.curr.content = line[offset:]
-
- return false
-}
-
-func (list *List) Finalize() {
- if !list.finalized {
- // close all opened nodes, effectively going up to the root node
- list.balance(0)
- list.finalized = true
- }
-}
-
-func (list *List) RenderAsHtml() (html string) {
- // for a good measure
- list.Finalize()
-
- b := &strings.Builder{}
-
- // fire up recursive render process
- list.curr.renderAsHtmlTo(b, list.hyphaName, list.ordered)
-
- return b.String()
-}
diff --git a/markup/mycomarkup.go b/markup/mycomarkup.go
deleted file mode 100644
index f8c4946..0000000
--- a/markup/mycomarkup.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// This is not done yet
-package markup
-
-import (
- "fmt"
- "regexp"
- "strings"
-
- "github.com/bouncepaw/mycorrhiza/cfg"
-
- "github.com/bouncepaw/mycomarkup/links"
-)
-
-// A Mycomarkup-formatted document
-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 {
- 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 {
- md.html = Parse(md.Lex(0).ast, 0, 0, 0)
- return md.html
-}
-
-// AsGemtext returns a gemtext representation of the document. Currently really limited, just returns source text
-func (md *MycoDoc) AsGemtext() string {
- return md.contents
-}
-
-// 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 {
- md.ogFillVars()
- return strings.Join([]string{
- ogTag("title", md.hyphaName),
- ogTag("type", "article"),
- ogTag("image", md.firstImageURL),
- ogTag("url", cfg.URL+"/hypha/"+md.hyphaName),
- ogTag("determiner", ""),
- ogTag("description", htmlTagRe.ReplaceAllString(md.description, "")),
- }, "\n")
-}
-
-func (md *MycoDoc) ogFillVars() *MycoDoc {
- md.firstImageURL = cfg.URL + "/favicon.ico"
- foundDesc := false
- foundImg := false
- for _, line := range md.ast {
- switch v := line.contents.(type) {
- case string:
- if !foundDesc {
- md.description = v
- foundDesc = true
- }
- case Img:
- if !foundImg && len(v.entries) > 0 {
- md.firstImageURL = v.entries[0].srclink.ImgSrc()
- if !v.entries[0].srclink.OfKind(links.LinkExternal) {
- md.firstImageURL = cfg.URL + md.firstImageURL
- }
- foundImg = true
- }
- }
- }
- return md
-}
-
-func ogTag(property, content string) string {
- return fmt.Sprintf(``, property, content)
-}
diff --git a/markup/outlink.go b/markup/outlink.go
deleted file mode 100644
index aef4847..0000000
--- a/markup/outlink.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package markup
-
-import (
- "regexp"
- "strings"
-
- "github.com/bouncepaw/mycomarkup/links"
-)
-
-// OutLinks returns a channel of names of hyphae this mycodocument links.
-// Links include:
-// * Regular links
-// * Rocketlinks
-// * Transclusion
-// * Image galleries
-// Not needed anymore, I guess.
-func (md *MycoDoc) OutLinks() chan string {
- ch := make(chan string)
- if !md.parsedAlready {
- md.Lex(0)
- }
- go func() {
- for _, line := range md.ast {
- switch v := line.contents.(type) {
- case string:
- if strings.HasPrefix(v, "
"})
- case MatchesList(line):
- addParagraphIfNeeded()
- list, _ := NewList(line, state.name)
- state.where = "list"
- state.list = list
- addLine(state.list)
- case MatchesImg(line):
- addParagraphIfNeeded()
- img, shouldGoBackToNormal := ImgFromFirstLine(line, state.name)
- if shouldGoBackToNormal {
- addLine(*img)
- } else {
- state.where = "img"
- state.img = img
- }
- case MatchesTable(line):
- addParagraphIfNeeded()
- state.where = "table"
- state.table = TableFromFirstLine(line, state.name)
-
- case state.where == "p":
- state.buf += "\n" + line
- default:
- state.where = "p"
- state.buf = line
- }
-}
diff --git a/markup/link.go b/markup/link.go
deleted file mode 100644
index be8a148..0000000
--- a/markup/link.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package markup
-
-import (
- "strings"
-
- "github.com/bouncepaw/mycomarkup/links"
-)
-
-// LinkParts determines what href, text and class should resulting have based on mycomarkup's addr, display and hypha name.
-//
-// => addr display
-// [[addr|display]]
-// TODO: deprecate
-func LinkParts(addr, display, hyphaName string) (href, text, class string) {
- l := links.From(addr, display, hyphaName)
- if l.OfKind(links.LinkLocalHypha) && !HyphaExists(l.Address()) {
- l.DestinationUnknown = true
- }
- return l.Href(), l.Display(), l.Classes()
-}
-
-// Parse markup line starting with "=>" according to wikilink rules.
-// See http://localhost:1737/page/wikilink
-func Rocketlink(src, hyphaName string) (href, text, class string) {
- src = strings.TrimSpace(src[2:]) // Drop =>
- if src == "" {
- return
- }
- // Href is text after => till first whitespace
- addr := strings.Fields(src)[0]
- display := strings.TrimPrefix(src, addr)
- return LinkParts(addr, display, hyphaName)
-}
diff --git a/markup/list.go b/markup/list.go
deleted file mode 100644
index 81b1d1c..0000000
--- a/markup/list.go
+++ /dev/null
@@ -1,171 +0,0 @@
-package markup
-
-import (
- "errors"
- "strings"
-)
-
-func parseListItem(line string) (level int, offset int, ordered bool, err error) {
- for line[level] == '*' {
- level++
- }
-
- if line[level] == '.' {
- ordered = true
- offset = level + 2
- } else {
- ordered = false
- offset = level + 1
- }
-
- if line[offset-1] != ' ' || len(line) < offset+2 || level < 1 || level > 6 {
- err = errors.New("ill-formatted list item")
- }
- return
-}
-
-func MatchesList(line string) bool {
- level, _, _, err := parseListItem(line)
- return err == nil && level == 1
-}
-
-type listItem struct {
- content string
- parent *listItem
- children []*listItem
- depth int
-}
-
-func newListItem(parent *listItem) *listItem {
- depth := 0
- if parent != nil {
- depth = parent.depth + 1
- }
- return &listItem{
- parent: parent,
- children: make([]*listItem, 0),
- depth: depth,
- }
-}
-
-func (item *listItem) renderAsHtmlTo(b *strings.Builder, hyphaName string, ordered bool) {
- if len(item.content) > 0 {
- b.WriteString("")
- } else {
- b.WriteString("
")
- } else {
- b.WriteString("")
- }
-
- for _, child := range item.children {
- child.renderAsHtmlTo(b, hyphaName, ordered)
- }
-
- if ordered {
- b.WriteString("
%s
`, html)
-}
-
-type tableRow struct {
- cells []*tableCell
-}
-
-func (tr *tableRow) asHtml(hyphaName string) (html string) {
- for _, tc := range tr.cells {
- html += tc.asHtml(hyphaName)
- }
- return fmt.Sprintf("%s \n", html)
-}
-
-// Most likely, rows with more than two header cells are theads. I allow one extra datum cell for tables like this:
-// | ! a ! b
-// ! c | d | e
-// ! f | g | h
-func (tr *tableRow) looksLikeThead() bool {
- var (
- headerAmount = 0
- datumAmount = 0
- )
- for _, tc := range tr.cells {
- switch tc.kind {
- case tableCellHeader:
- headerAmount++
- case tableCellDatum:
- datumAmount++
- }
- }
- return headerAmount >= 2 && datumAmount <= 1
-}
-
-type tableCell struct {
- kind tableCellKind
- colspan uint
- content string
-}
-
-func (tc *tableCell) asHtml(hyphaName string) string {
- return fmt.Sprintf(
- "<%[1]s %[2]s>%[3]s%[1]s>\n",
- tc.kind.tagName(),
- tc.colspanAttribute(),
- tc.contentAsHtml(hyphaName),
- )
-}
-
-func (tc *tableCell) colspanAttribute() string {
- if tc.colspan <= 1 {
- return ""
- }
- return fmt.Sprintf(`colspan="%d"`, tc.colspan)
-}
-
-func (tc *tableCell) contentAsHtml(hyphaName string) (html string) {
- for _, line := range strings.Split(tc.content, "\n") {
- if line = strings.TrimSpace(line); line != "" {
- if html != "" {
- html += `
`
- }
- html += ParagraphToHtml(hyphaName, line)
- }
- }
- return html
-}
-
-type tableCellKind int
-
-const (
- tableCellUnknown tableCellKind = iota
- tableCellHeader
- tableCellDatum
-)
-
-func (tck tableCellKind) tagName() string {
- switch tck {
- case tableCellHeader:
- return "th"
- case tableCellDatum:
- return "td"
- default:
- return "p"
- }
-}
diff --git a/markup/testdata/test.myco b/markup/testdata/test.myco
deleted file mode 100644
index fd5880f..0000000
--- a/markup/testdata/test.myco
+++ /dev/null
@@ -1,38 +0,0 @@
-# 1
-## 2
-### 3
-> quote
-
-* li 1
-* li 2
-text
-more text
-=> Pear some link
-
-* li\n"+
-```alt text goes here
-=> preformatted text
-where markup is not lexed
-```it ends here"
-=>linking
-
-text
-```
-()
-/\
-```
-<= Apple : 1..3
-
-img {
-hypha1
-hypha2|
-hypha3| 60
-hypha4| { line1
-line2
-} this is ignored
-
-hypha5| {
-state of minnesota
-}
-}
-
diff --git a/markup/utils.go b/markup/utils.go
deleted file mode 100644
index 9cc89b7..0000000
--- a/markup/utils.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package markup
-
-import (
- "strings"
-)
-
-// Function that returns a function that can strip `prefix` and trim whitespace when called.
-func remover(prefix string) func(string) string {
- return func(l string) string {
- return strings.TrimSpace(strings.TrimPrefix(l, prefix))
- }
-}
diff --git a/markup/xclusion.go b/markup/xclusion.go
deleted file mode 100644
index c20dc96..0000000
--- a/markup/xclusion.go
+++ /dev/null
@@ -1,108 +0,0 @@
-package markup
-
-import (
- "fmt"
- "github.com/bouncepaw/mycorrhiza/util"
- "path"
- "strconv"
- "strings"
-)
-
-const xclError = -9
-
-// Transclusion is used by markup parser to remember what hyphae shall be transcluded.
-type Transclusion struct {
- name string
- from int // inclusive
- to int // inclusive
-}
-
-// Transclude transcludes `xcl` and returns html representation.
-func Transclude(xcl Transclusion, recursionLevel int) (html string) {
- recursionLevel++
- tmptOk := `