mirror of
https://github.com/TECHNOFAB11/docsonnet.git
synced 2025-12-14 23:33:56 +01:00
feat: rewrite render
This commit is contained in:
parent
5fbee517fe
commit
7308eecaf3
10 changed files with 352 additions and 198 deletions
130
pkg/md/md.go
Normal file
130
pkg/md/md.go
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
package md
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Elem interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
type JoinType struct {
|
||||
elems []Elem
|
||||
with string
|
||||
}
|
||||
|
||||
func (p JoinType) String() string {
|
||||
s := ""
|
||||
for _, e := range p.elems {
|
||||
s += p.with + e.String()
|
||||
}
|
||||
return strings.TrimPrefix(s, p.with)
|
||||
}
|
||||
|
||||
func Paragraph(elems ...Elem) JoinType {
|
||||
return JoinType{elems: elems, with: " "}
|
||||
}
|
||||
|
||||
func Doc(elems ...Elem) JoinType {
|
||||
return JoinType{elems: elems, with: "\n\n"}
|
||||
}
|
||||
|
||||
type TextType struct {
|
||||
content string
|
||||
}
|
||||
|
||||
func (t TextType) String() string {
|
||||
return t.content
|
||||
}
|
||||
|
||||
func Text(text string) TextType {
|
||||
return TextType{content: text}
|
||||
}
|
||||
|
||||
type HeadlineType struct {
|
||||
level int
|
||||
content string
|
||||
}
|
||||
|
||||
func (h HeadlineType) String() string {
|
||||
return strings.Repeat("#", h.level) + " " + h.content
|
||||
}
|
||||
|
||||
func Headline(level int, content string) HeadlineType {
|
||||
return HeadlineType{
|
||||
level: level,
|
||||
content: content,
|
||||
}
|
||||
}
|
||||
|
||||
type SurroundType struct {
|
||||
body Elem
|
||||
surround string
|
||||
}
|
||||
|
||||
func (s SurroundType) String() string {
|
||||
return s.surround + s.body.String() + s.surround
|
||||
}
|
||||
|
||||
func Bold(e Elem) SurroundType {
|
||||
return SurroundType{body: e, surround: "**"}
|
||||
}
|
||||
|
||||
func Italic(e Elem) SurroundType {
|
||||
return SurroundType{body: e, surround: "*"}
|
||||
}
|
||||
|
||||
func Code(e Elem) SurroundType {
|
||||
return SurroundType{body: e, surround: "`"}
|
||||
}
|
||||
|
||||
type CodeBlockType struct {
|
||||
lang string
|
||||
snippet string
|
||||
}
|
||||
|
||||
func (c CodeBlockType) String() string {
|
||||
return fmt.Sprintf("```%s\n%s\n```", c.lang, c.snippet)
|
||||
}
|
||||
|
||||
func CodeBlock(lang, snippet string) CodeBlockType {
|
||||
return CodeBlockType{lang: lang, snippet: snippet}
|
||||
}
|
||||
|
||||
type ListType struct {
|
||||
elems []Elem
|
||||
}
|
||||
|
||||
func (l ListType) String() string {
|
||||
s := ""
|
||||
for _, e := range l.elems {
|
||||
switch t := e.(type) {
|
||||
case ListType:
|
||||
s += "\n " + strings.Join(strings.Split(t.String(), "\n"), "\n ")
|
||||
default:
|
||||
s += "\n* " + t.String()
|
||||
}
|
||||
}
|
||||
return strings.TrimPrefix(s, "\n")
|
||||
}
|
||||
|
||||
func List(elems ...Elem) ListType {
|
||||
return ListType{elems: elems}
|
||||
}
|
||||
|
||||
type LinkType struct {
|
||||
desc Elem
|
||||
href string
|
||||
}
|
||||
|
||||
func (l LinkType) String() string {
|
||||
return fmt.Sprintf("[%s](%s)", l.desc.String(), l.href)
|
||||
}
|
||||
|
||||
func Link(desc Elem, href string) LinkType {
|
||||
return LinkType{
|
||||
desc: desc,
|
||||
href: href,
|
||||
}
|
||||
}
|
||||
25
pkg/md/md_test.go
Normal file
25
pkg/md/md_test.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package md
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
l := List(
|
||||
Text("foo"),
|
||||
Text("bar"),
|
||||
List(
|
||||
Text("baz"),
|
||||
Text("bing"),
|
||||
),
|
||||
Text("boing"),
|
||||
).String()
|
||||
|
||||
assert.Equal(t, `* foo
|
||||
* bar
|
||||
* baz
|
||||
* bing
|
||||
* boing`, l)
|
||||
}
|
||||
35
pkg/slug/slug.go
Normal file
35
pkg/slug/slug.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package slug
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Slugger struct {
|
||||
occurences map[string]int
|
||||
}
|
||||
|
||||
var (
|
||||
expWhitespace = regexp.MustCompile(`\s`)
|
||||
expSpecials = regexp.MustCompile("[\u2000-\u206F\u2E00-\u2E7F\\'!\"#$%&()*+,./:;<=>?@[\\]^`{|}~’]")
|
||||
)
|
||||
|
||||
func New() *Slugger {
|
||||
return &Slugger{
|
||||
occurences: make(map[string]int),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Slugger) Slug(str string) string {
|
||||
str = expWhitespace.ReplaceAllString(str, "-")
|
||||
str = expSpecials.ReplaceAllString(str, "")
|
||||
|
||||
old := str
|
||||
if o := s.occurences[str]; o > 0 {
|
||||
str += "-" + strconv.Itoa(o)
|
||||
}
|
||||
s.occurences[old] = s.occurences[old] + 1
|
||||
|
||||
return strings.ToLower(str)
|
||||
}
|
||||
44
pkg/slug/slug_test.go
Normal file
44
pkg/slug/slug_test.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package slug
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSlug(t *testing.T) {
|
||||
|
||||
cases := [][]struct {
|
||||
in, out string
|
||||
}{
|
||||
{
|
||||
{"foo", "foo"},
|
||||
{"foo", "foo-1"},
|
||||
{"foo bar", "foo-bar"},
|
||||
},
|
||||
{
|
||||
{"foo", "foo"},
|
||||
{"fooCamelCase", "foocamelcase"},
|
||||
},
|
||||
{
|
||||
{"foo", "foo"},
|
||||
{"foo", "foo-1"},
|
||||
// {"foo 1", "foo-1-1"}, // these are too rare for Jsonnet
|
||||
// {"foo 1", "foo-1-2"},
|
||||
{"foo", "foo-2"},
|
||||
},
|
||||
{
|
||||
{"heading with a - dash", "heading-with-a---dash"},
|
||||
{"heading with an _ underscore", "heading-with-an-_-underscore"},
|
||||
{"heading with a period.txt", "heading-with-a-periodtxt"},
|
||||
{"exchange.bind_headers(exchange, routing [, bindCallback])", "exchangebind_headersexchange-routing--bindcallback"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, cs := range cases {
|
||||
s := New()
|
||||
for _, c := range cs {
|
||||
assert.Equal(t, c.out, s.Slug(c.in))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue