From 0d9a677acac9bd7c3c8b460a67897a9b844f4393 Mon Sep 17 00:00:00 2001 From: Dan Konshin Date: Sun, 5 Jul 2020 19:56:03 +0500 Subject: [PATCH 1/2] Gemini parser --- plugin/parser/gemini.go | 70 +++++++++++++++++++++++++++++++++- plugin/parser/toHtml.go | 53 +++++++++++++++++++++++++ wiki/main/testgemini/1.txt | 25 ++++++++++++ wiki/main/testgemini/meta.json | 17 +++++++++ 4 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 plugin/parser/toHtml.go create mode 100644 wiki/main/testgemini/1.txt create mode 100644 wiki/main/testgemini/meta.json diff --git a/plugin/parser/gemini.go b/plugin/parser/gemini.go index 68dbb26..5520109 100644 --- a/plugin/parser/gemini.go +++ b/plugin/parser/gemini.go @@ -1,7 +1,73 @@ package parser -import () +import ( + "bytes" + "strings" + + "github.com/bouncepaw/mycorrhiza/util" +) + +const ( + linkToken = "=>" + headerToken = "#" + quoteToken = ">" + preformattedToken = "```" + listItemToken = "*" +) func GeminiToHtml(gemini []byte) string { - return "" + lines, _ := StringToLines(string(util.NormalizeEOL(gemini))) + var html []string + for _, line := range lines { + html = append(html, geminiLineToHtml(line)) + } + buffer := bytes.Buffer{} + for _, line := range html { + buffer.WriteString(line) + } + return buffer.String() +} + +func geminiLineToHtml(line string) (res string) { + arr := strings.Fields(line) + if len(arr) == 0 { + return lineBreak + } + + content := arr[1:] + token := arr[0] + if string(token[0]) == headerToken { + return makeHeader(makeOutHeader(arr)) + } + + switch token { + case linkToken: + res = makeLink(makeOutLink(content)) + case quoteToken: + res = makeBlockQuote(LinesToString(content, " ")) + case preformattedToken: + res = makePreformatted(LinesToString(content, " ")) + case listItemToken: + res = makeListItem(LinesToString(content, " ")) + default: + res = makeParagraph(line) + } + return res +} + +func makeOutLink(arr []string) (source, content string) { + switch len(arr) { + case 0: + return "", "" + case 1: + return arr[0], arr[0] + default: + return arr[0], LinesToString(arr[1:], " ") + } +} + +func makeOutHeader(arr []string) (level int, content string) { + level = len(arr[0]) + content = LinesToString(arr[1:], " ") + return } diff --git a/plugin/parser/toHtml.go b/plugin/parser/toHtml.go new file mode 100644 index 0000000..f6be2b5 --- /dev/null +++ b/plugin/parser/toHtml.go @@ -0,0 +1,53 @@ +package parser + +import ( + "bufio" + "bytes" + "fmt" + "strings" +) + +const ( + lineBreak = "
" +) + +func makeLink(source, content string) string { + return fmt.Sprintf(`%v`, source, content) +} + +func makeParagraph(content string) string { + return `

` + content + `

` +} + +func makeBlockQuote(content string) string { + return `
` + content + `
` +} + +func makeHeader(level int, content string) string { + return fmt.Sprintf("%v", level, content, level) +} + +func makePreformatted(content string) string { + return "
" + content + "
" +} + +func makeListItem(content string) string { + return "
  • " + content + "
  • " +} + +func StringToLines(s string) (lines []string, err error) { + scanner := bufio.NewScanner(strings.NewReader(s)) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + err = scanner.Err() + return +} + +func LinesToString(lines []string, separator string) string { + buffer := bytes.Buffer{} + for _, line := range lines { + buffer.WriteString(line + separator) + } + return buffer.String() +} diff --git a/wiki/main/testgemini/1.txt b/wiki/main/testgemini/1.txt new file mode 100644 index 0000000..c03e6f3 --- /dev/null +++ b/wiki/main/testgemini/1.txt @@ -0,0 +1,25 @@ +# Gemtext cheatsheet +Here's the basics of how text works in Gemtext: + +Long lines get wrapped by the client to fit the screen +Short lines *don't* get joined together +Write paragraphs as single long lines +Blank lines are rendered verbatim +You get three levels of heading: + +# Heading +## Sub-heading +### Sub-subheading +You get one kind of list and you can't nest them: + +* Mercury +* Gemini +* Apollo +Here's a quote from Maciej CegÅ‚owski: + +> I contend that text-based websites should not exceed in size the major works of Russian literature. +Lines which start with ``` will cause clients to toggle in and out of ordinary rendering mode and preformatted mode. In preformatted mode, Gemtext syntax is ignored so links etc. will not be rendered, and text will appear in a monospace font. +``` =>https://not-a-href.com preformatted + +=> https://proxy.vulpes.one/gemini/gemini.circumlunar.space/docs/cheatsheet.gmi Original cheatsheet +=> https://proxy.vulpes.one/gemini/gemini.circumlunar.space/docs/cheatsheet.gmi diff --git a/wiki/main/testgemini/meta.json b/wiki/main/testgemini/meta.json new file mode 100644 index 0000000..82e4bf3 --- /dev/null +++ b/wiki/main/testgemini/meta.json @@ -0,0 +1,17 @@ +{ + "views": 0, + "deleted": false, + "revisions": { + "1": { + "tags": null, + "name": "Testgemini", + "comment": "Create :Main/Testgemini", + "author": "", + "time": 1593960824, + "text_mime": "text/gemini", + "binary_mime": "", + "text_name": "1.txt", + "binary_name": "" + } + } +} \ No newline at end of file From 0f8f8191853c7480874f74dc62858452c4d5ab25 Mon Sep 17 00:00:00 2001 From: Dan Konshin Date: Tue, 14 Jul 2020 18:46:49 +0500 Subject: [PATCH 2/2] Gemini parser rework --- plugin/parser/gemini.go | 91 +++++++++++++++++++++++++++++++------- plugin/parser/toHtml.go | 53 ---------------------- wiki/main/testgemini/1.txt | 29 +++++++++++- 3 files changed, 103 insertions(+), 70 deletions(-) delete mode 100644 plugin/parser/toHtml.go diff --git a/plugin/parser/gemini.go b/plugin/parser/gemini.go index 5520109..c3b41a9 100644 --- a/plugin/parser/gemini.go +++ b/plugin/parser/gemini.go @@ -1,7 +1,9 @@ package parser import ( + "bufio" "bytes" + "fmt" "strings" "github.com/bouncepaw/mycorrhiza/util" @@ -15,12 +17,17 @@ const ( listItemToken = "*" ) +var preState bool +var listState bool + func GeminiToHtml(gemini []byte) string { lines, _ := StringToLines(string(util.NormalizeEOL(gemini))) var html []string + for _, line := range lines { html = append(html, geminiLineToHtml(line)) } + buffer := bytes.Buffer{} for _, line := range html { buffer.WriteString(line) @@ -30,29 +37,40 @@ func GeminiToHtml(gemini []byte) string { func geminiLineToHtml(line string) (res string) { arr := strings.Fields(line) - if len(arr) == 0 { - return lineBreak - } - - content := arr[1:] - token := arr[0] - if string(token[0]) == headerToken { - return makeHeader(makeOutHeader(arr)) - } + token := checkLineType(arr) switch token { + case headerToken: + level, content := makeOutHeader(arr) + res = fmt.Sprintf("%v", level, content, level) case linkToken: - res = makeLink(makeOutLink(content)) + source, content := makeOutLink(arr[1:]) + res = fmt.Sprintf(`%v`, source, content) case quoteToken: - res = makeBlockQuote(LinesToString(content, " ")) + res = "
    " + LinesToString(arr[1:], " ") + "
    " case preformattedToken: - res = makePreformatted(LinesToString(content, " ")) + preState = true + res = fmt.Sprintf(`
    `, LinesToString(arr[1:], " "))
    +	case "pre/empty":
    +		res = "\n"
    +	case "pre/text":
    +		res = line + "\n"
    +	case "pre/end":
    +		preState = false
    +		res = "
    " + case "list/begin": + res = "" + geminiLineToHtml(line) + case "linebreak": + res = "
    " default: - res = makeParagraph(line) + res = "

    " + line + "

    " } - return res + return } func makeOutLink(arr []string) (source, content string) { @@ -71,3 +89,46 @@ func makeOutHeader(arr []string) (level int, content string) { content = LinesToString(arr[1:], " ") return } + +func checkLineType(arr []string) (res string) { + isEmpty := len(arr) == 0 + if preState { + if isEmpty { + res = "pre/empty" + } else if arr[0] == preformattedToken { + res = "pre/end" + } else { + res = "pre/text" + } + } else if listState { + if arr[0] == listItemToken { + res = listItemToken + } else { + res = "list/end" + } + } else if isEmpty { + res = "linebreak" + } else if arr[0][0] == headerToken[0] { + res = headerToken + } else { + return arr[0] + } + return +} + +func StringToLines(s string) (lines []string, err error) { + scanner := bufio.NewScanner(strings.NewReader(s)) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + err = scanner.Err() + return +} + +func LinesToString(lines []string, separator string) string { + buffer := bytes.Buffer{} + for _, line := range lines { + buffer.WriteString(line + separator) + } + return buffer.String() +} diff --git a/plugin/parser/toHtml.go b/plugin/parser/toHtml.go deleted file mode 100644 index f6be2b5..0000000 --- a/plugin/parser/toHtml.go +++ /dev/null @@ -1,53 +0,0 @@ -package parser - -import ( - "bufio" - "bytes" - "fmt" - "strings" -) - -const ( - lineBreak = "
    " -) - -func makeLink(source, content string) string { - return fmt.Sprintf(`%v`, source, content) -} - -func makeParagraph(content string) string { - return `

    ` + content + `

    ` -} - -func makeBlockQuote(content string) string { - return `
    ` + content + `
    ` -} - -func makeHeader(level int, content string) string { - return fmt.Sprintf("%v", level, content, level) -} - -func makePreformatted(content string) string { - return "
    " + content + "
    " -} - -func makeListItem(content string) string { - return "
  • " + content + "
  • " -} - -func StringToLines(s string) (lines []string, err error) { - scanner := bufio.NewScanner(strings.NewReader(s)) - for scanner.Scan() { - lines = append(lines, scanner.Text()) - } - err = scanner.Err() - return -} - -func LinesToString(lines []string, separator string) string { - buffer := bytes.Buffer{} - for _, line := range lines { - buffer.WriteString(line + separator) - } - return buffer.String() -} diff --git a/wiki/main/testgemini/1.txt b/wiki/main/testgemini/1.txt index c03e6f3..afdf451 100644 --- a/wiki/main/testgemini/1.txt +++ b/wiki/main/testgemini/1.txt @@ -19,7 +19,32 @@ Here's a quote from Maciej CegÅ‚owski: > I contend that text-based websites should not exceed in size the major works of Russian literature. Lines which start with ``` will cause clients to toggle in and out of ordinary rendering mode and preformatted mode. In preformatted mode, Gemtext syntax is ignored so links etc. will not be rendered, and text will appear in a monospace font. -``` =>https://not-a-href.com preformatted - +``` ALT TEXT + . + (' + '| + |' + [::] + [::] _......_ + [::].-' _.-`. + [:.' .-. '-._.-`. + [/ /\ | \ `-.. + / / | `-.' .-. `-. + / `-' ( `. `. + | /\ `-._/ \ + ' .'\ / `. _.-'| + / / / \_.-' _.':;:/ + .' \_/ _.-':;_.-' + / .-. _.-' \;.-' +/ ( \ _..-' | +\ `._/ _..-' .--. | + `-.....-'/ _ _ .' '.| + | |_|_| | | \ (o) + (o) | |_|_| | | | (\'/) + (\'/)/ ''''' | o| \;:; + :; | | | |/) + ;: `-.._ /__..--'\.' ;: + :; `--' :; :; +``` => https://proxy.vulpes.one/gemini/gemini.circumlunar.space/docs/cheatsheet.gmi Original cheatsheet => https://proxy.vulpes.one/gemini/gemini.circumlunar.space/docs/cheatsheet.gmi