Skip to content

Commit d4d8ec7

Browse files
committed
yep
1 parent 35dc8d7 commit d4d8ec7

File tree

123 files changed

+5573
-53
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+5573
-53
lines changed

cmd.go

+10
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,18 @@ type Cmd struct {
2424
res *CmdResult
2525
}
2626

27+
func (c *Cmd) MD() string {
28+
if c == nil {
29+
return ""
30+
}
31+
32+
return c.Children().MD()
33+
}
34+
2735
// Result returns the result of executing the command.
2836
func (c *Cmd) Result() *CmdResult {
37+
c.RLock()
38+
defer c.RUnlock()
2939
return c.res
3040
}
3141

cmd/hype/cli/cli.go

+4
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import (
77
"os"
88
"time"
99

10+
"github.com/gopherguides/hype"
1011
"github.com/markbates/cleo"
1112
"github.com/markbates/plugins"
1213
"github.com/markbates/plugins/plugcmd"
1314
)
1415

1516
type App struct {
1617
cleo.Cmd
18+
19+
Parser *hype.Parser
1720
}
1821

1922
func (cmd *App) Main(ctx context.Context, pwd string, args []string) error {
@@ -93,6 +96,7 @@ func New(root string) *App {
9396
Name: "preview",
9497
Aliases: []string{"p"},
9598
},
99+
Parser: app.Parser,
96100
},
97101
// &Latex{
98102
// Cmd: cleo.Cmd{

cmd_result.go

+13-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ type CmdResult struct {
2222
*clam.Result
2323
}
2424

25+
func (c *CmdResult) MD() string {
26+
if c == nil {
27+
return ""
28+
}
29+
30+
return c.Children().MD()
31+
}
32+
2533
func NewCmdResult(p *Parser, c *Cmd, res *clam.Result) (*CmdResult, error) {
2634
if res == nil {
2735
return nil, c.WrapErr(ErrIsNil("result"))
@@ -36,7 +44,7 @@ func NewCmdResult(p *Parser, c *Cmd, res *clam.Result) (*CmdResult, error) {
3644

3745
ats := c.Attrs()
3846

39-
lang := "text"
47+
lang := "shell"
4048
lang = Language(ats, lang)
4149

4250
var lines []string
@@ -66,7 +74,10 @@ func NewCmdResult(p *Parser, c *Cmd, res *clam.Result) (*CmdResult, error) {
6674
}
6775

6876
pre := NewEl(atomx.Pre, cmd)
69-
cel := NewEl(atomx.Code, pre)
77+
cel := &FencedCode{
78+
Element: NewEl(atomx.Code, pre),
79+
}
80+
7081
if err := cel.Set("language", lang); err != nil {
7182
return nil, err
7283
}

cmd_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func Test_Cmd_Execute(t *testing.T) {
6767
act := c.String()
6868
act = strings.TrimSpace(act)
6969

70-
exp := `<cmd exec="echo hello" hide-cmd=""><pre><code class="language-text" language="text">hello</code></pre></cmd>`
70+
exp := `<cmd exec="echo hello" hide-cmd=""><pre><code class="language-shell" language="shell">hello</code></pre></cmd>`
7171

7272
// fmt.Println(act)
7373
r.Equal(exp, act)

document.go

+21
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"io/fs"
7+
"strings"
78
"sync"
89

910
"golang.org/x/sync/errgroup"
@@ -155,3 +156,23 @@ func (docs Documents) Execute(ctx context.Context) error {
155156

156157
return wg.Wait()
157158
}
159+
160+
func (doc *Document) MD() string {
161+
if doc == nil {
162+
return ""
163+
}
164+
165+
pages, err := doc.Pages()
166+
167+
if err != nil {
168+
return ""
169+
}
170+
171+
bodies := make([]string, 0, len(pages))
172+
173+
for _, page := range pages {
174+
bodies = append(bodies, page.MD())
175+
}
176+
177+
return strings.Join(bodies, "\n---\n")
178+
}

document_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package hype
22

33
import (
44
"context"
5+
"io/fs"
6+
"strings"
57
"testing"
68
"testing/fstest"
79
"time"
@@ -87,3 +89,33 @@ func Test_Document_Execute(t *testing.T) {
8789
r.Equal(exp, act)
8890

8991
}
92+
93+
func Test_Document_MD(t *testing.T) {
94+
t.Skip("TODO: fix this test")
95+
t.Parallel()
96+
r := require.New(t)
97+
98+
root := "testdata/doc/to_md"
99+
100+
p := testParser(t, root)
101+
102+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
103+
defer cancel()
104+
105+
doc, err := p.ParseExecuteFile(ctx, "module.md")
106+
r.NoError(err)
107+
108+
s := doc.MD()
109+
act := string(s)
110+
act = strings.TrimSpace(act)
111+
112+
// fmt.Println(act)
113+
114+
b, err := fs.ReadFile(p.FS, "module.gold")
115+
r.NoError(err)
116+
117+
exp := string(b)
118+
exp = strings.TrimSpace(exp)
119+
120+
r.Equal(exp, act)
121+
}

element.go

+32
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99
"sync"
1010

11+
"github.com/gopherguides/hype/atomx"
1112
"golang.org/x/net/html"
1213
"golang.org/x/net/html/atom"
1314
)
@@ -210,3 +211,34 @@ func (el *Element) Set(k string, v string) error {
210211

211212
return nil
212213
}
214+
215+
func (el *Element) MD() string {
216+
if el == nil {
217+
return ""
218+
}
219+
220+
switch el.Atom() {
221+
case atomx.Strong, atomx.B:
222+
return fmt.Sprintf("**%s**", el.Children().MD())
223+
case atomx.Em, atomx.I:
224+
return fmt.Sprintf("_%s_", el.Children().MD())
225+
case atomx.Pre:
226+
return el.Children().MD()
227+
case atomx.Hr:
228+
return "\n\n---\n\n"
229+
case atomx.Blockquote:
230+
b := el.Children().MD()
231+
b = strings.TrimSpace(b)
232+
// panic(b)
233+
return fmt.Sprintf("> %s", b)
234+
default:
235+
fmt.Printf("TODO: Element.MD(): %q\n", el.Atom())
236+
}
237+
238+
bb := &bytes.Buffer{}
239+
bb.WriteString(el.StartTag())
240+
bb.WriteString(el.Children().MD())
241+
bb.WriteString(el.EndTag())
242+
243+
return bb.String()
244+
}

empty.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package hype
22

3-
import "strings"
3+
import (
4+
"strings"
5+
)
46

57
type EmptyableNode interface {
68
IsEmptyNode() bool

empty_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@ import (
99

1010
func Test_IsEmptyNode(t *testing.T) {
1111
t.Parallel()
12+
// r := require.New(t)
13+
14+
// p := testParser(t, "testdata")
15+
16+
// const frag = `<table>
17+
// <thead>
18+
// <tr>
19+
// <th></th>
20+
// <th></th>
21+
// </tr>
22+
// </thead>`
23+
24+
// table, err := p.ParseFragment(strings.NewReader(frag))
25+
// r.NoError(err)
1226

1327
fullP := NewEl(atomx.P, nil)
1428
fullP.Nodes = append(fullP.Nodes, Text("Hello World"))
@@ -25,6 +39,7 @@ func Test_IsEmptyNode(t *testing.T) {
2539
{name: "empty text", node: Text(""), exp: true},
2640
{name: "empty paragraph", node: emptyP, exp: true},
2741
{name: "full paragraph", node: fullP, exp: false},
42+
// {name: "empty table", node: table, exp: true},
2843
}
2944

3045
for _, tc := range tcs {

fenced_code.go

+25
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package hype
22

3+
import (
4+
"bytes"
5+
"fmt"
6+
"html"
7+
)
8+
39
type FencedCode struct {
410
*Element
511
}
@@ -24,6 +30,25 @@ func (code *FencedCode) String() string {
2430
return code.StartTag() + code.Children().String() + code.EndTag()
2531
}
2632

33+
func (code *FencedCode) MD() string {
34+
if code == nil {
35+
return ""
36+
}
37+
38+
bb := &bytes.Buffer{}
39+
40+
fmt.Fprintf(bb, "```%s\n", code.Lang())
41+
42+
body := code.Children().MD()
43+
body = html.UnescapeString(body)
44+
45+
fmt.Fprintln(bb, body)
46+
47+
fmt.Fprint(bb, "```")
48+
49+
return bb.String()
50+
}
51+
2752
func (code *FencedCode) Lang() string {
2853
lang := "plain"
2954
if code == nil {

figcaption.go

+15
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
11
package hype
22

3+
import "strings"
4+
35
type Figcaption struct {
46
*Element
57
}
68

9+
func (fc *Figcaption) MD() string {
10+
if fc == nil {
11+
return ""
12+
}
13+
14+
bb := &strings.Builder{}
15+
bb.WriteString(fc.StartTag())
16+
bb.WriteString(fc.Nodes.MD())
17+
bb.WriteString(fc.EndTag())
18+
19+
return bb.String()
20+
}
21+
722
func NewFigcaption(el *Element) (*Figcaption, error) {
823
if el == nil {
924
return nil, el.WrapErr(ErrIsNil("element"))

figure.go

+14-23
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,20 @@ type Figure struct {
1717
style string
1818
}
1919

20+
func (f *Figure) MD() string {
21+
if f == nil {
22+
return ""
23+
}
24+
25+
bb := &strings.Builder{}
26+
bb.WriteString(f.StartTag())
27+
fmt.Fprintln(bb)
28+
bb.WriteString(f.Nodes.MD())
29+
bb.WriteString(f.EndTag())
30+
31+
return bb.String()
32+
}
33+
2034
// Type returns type of the figure.
2135
// ex: "figure", "table", "listing", ...
2236
func (f *Figure) Type() string {
@@ -83,29 +97,6 @@ func NewFigure(p *Parser, el *Element) (*Figure, error) {
8397
return nil, f.WrapErr(err)
8498
}
8599

86-
// p2.NodeParsers[atomx.P] = func(p *Parser, el *Element) (Nodes, error) {
87-
// nodes, err := NewParagraphNodes(p, el)
88-
// if err != nil {
89-
// return nil, err
90-
// }
91-
92-
// if len(nodes) == 0 {
93-
// fmt.Println("no p nodes")
94-
// return nil, nil
95-
// }
96-
97-
// x := nodes.String()
98-
// x = strings.TrimSpace(x)
99-
// if len(x) == 0 {
100-
// fmt.Println("no p nodes")
101-
// return nil, nil
102-
// }
103-
104-
// fmt.Printf("TODO >> figure.go:93 nodes.String() %[1]T %+[1]v\n", nodes.String())
105-
106-
// return nodes, nil
107-
// }
108-
109100
nodes, err := p2.ParseFragment(strings.NewReader(body))
110101
if err != nil {
111102
if !errors.Is(err, ErrNilFigure) {

finders.go

+27
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,30 @@ func ByAtom[T ~string](nodes Nodes, want ...T) []AtomableNode {
5151
}
5252
return res
5353
}
54+
55+
func FirstByType[T Node](nodes Nodes) (T, bool) {
56+
res := ByType[T](nodes)
57+
if len(res) == 0 {
58+
return *new(T), false
59+
}
60+
61+
return res[0], true
62+
}
63+
64+
func FirstByAttrs(nodes Nodes, query map[string]string) (AttrNode, bool) {
65+
res := ByAttrs(nodes, query)
66+
if len(res) == 0 {
67+
return nil, false
68+
}
69+
70+
return res[0], true
71+
}
72+
73+
func FirstByAtom[T ~string](nodes Nodes, want ...T) (AtomableNode, bool) {
74+
res := ByAtom(nodes, want...)
75+
if len(res) == 0 {
76+
return nil, false
77+
}
78+
79+
return res[0], true
80+
}

0 commit comments

Comments
 (0)