package markup import ( "fmt" "html" "strings" ) // 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) // HyphaIterate is a function that iterates all hypha names existing. var HyphaIterate func(func(string)) // GemLexerState is used by markup parser to remember what is going on. type GemLexerState struct { // Name of hypha being parsed name string where string // "", "list", "pre" // Line id id int buf string // Temporaries img *Img table *Table } type Line struct { id int // interface{} may be bad. TODO: a proper type contents interface{} } func (md *MycoDoc) lex() (ast []Line) { var state = GemLexerState{name: md.hyphaName} 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 lineToAST(line string, state *GemLexerState, ast *[]Line) { addLine := func(text interface{}) { *ast = append(*ast, Line{id: state.id, contents: text}) } addParagraphIfNeeded := func() { if state.where == "p" { state.where = "" addLine(fmt.Sprintf("
%s
", state.id, strings.ReplaceAll(ParagraphToHtml(state.name, state.buf), "\n", "", state.id, strings.TrimPrefix(line, "```"))
default:
state.where = ""
addLine(state.buf + "")
goto normalState
}
return
numberState:
switch {
case startsWith("*. "):
state.buf += fmt.Sprintf("\t%s \n", ParagraphToHtml(state.name, line[3:]))
case startsWith("```"):
state.where = "pre"
addLine(state.buf + "")
state.id++
state.buf = fmt.Sprintf("", state.id, strings.TrimPrefix(line, "```"))
default:
state.where = ""
addLine(state.buf + "")
goto normalState
}
return
launchpadState:
switch {
case startsWith("=>"):
href, text, class, icon := Rocketlink(line, state.name)
state.buf += fmt.Sprintf(` %s%s `, class, href, text, icon)
case startsWith("```"):
state.where = "pre"
addLine(state.buf + "")
state.id++
state.buf = 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()
state.where = "list"
state.buf = fmt.Sprintf("\n", state.id)
goto listState
case startsWith("*. "):
addParagraphIfNeeded()
state.where = "number"
state.buf = fmt.Sprintf("\n", state.id)
goto numberState
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 line == "----":
addParagraphIfNeeded()
*ast = append(*ast, Line{id: -1, contents: "
"})
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
}
}