1
2
3
4
5 package relnote
6
7 import (
8 "fmt"
9 "strings"
10
11 md "rsc.io/markdown"
12 )
13
14
15
16
17 func DumpMarkdown(d *md.Document) {
18 dumpBlocks(d.Blocks, 0)
19 }
20
21 func dumpBlocks(bs []md.Block, depth int) {
22 for _, b := range bs {
23 dumpBlock(b, depth)
24 }
25 }
26
27 func dumpBlock(b md.Block, depth int) {
28 typeName := strings.TrimPrefix(fmt.Sprintf("%T", b), "*markdown.")
29 dprintf(depth, "%s\n", typeName)
30 switch b := b.(type) {
31 case *md.Paragraph:
32 dumpInlines(b.Text.Inline, depth+1)
33 case *md.Heading:
34 dumpInlines(b.Text.Inline, depth+1)
35 case *md.List:
36 dumpBlocks(b.Items, depth+1)
37 case *md.Item:
38 dumpBlocks(b.Blocks, depth+1)
39 default:
40
41 }
42 }
43
44 func dumpInlines(ins []md.Inline, depth int) {
45 for _, in := range ins {
46 switch in := in.(type) {
47 case *md.Plain:
48 dprintf(depth, "Plain(%q)\n", in.Text)
49 case *md.Code:
50 dprintf(depth, "Code(%q)\n", in.Text)
51 case *md.Link:
52 dprintf(depth, "Link:\n")
53 dumpInlines(in.Inner, depth+1)
54 dprintf(depth+1, "URL: %q\n", in.URL)
55 case *md.Strong:
56 dprintf(depth, "Strong(%q):\n", in.Marker)
57 dumpInlines(in.Inner, depth+1)
58 case *md.Emph:
59 dprintf(depth, "Emph(%q):\n", in.Marker)
60 dumpInlines(in.Inner, depth+1)
61 case *md.Del:
62 dprintf(depth, "Del(%q):\n", in.Marker)
63 dumpInlines(in.Inner, depth+1)
64 default:
65 fmt.Printf("%*s%#v\n", depth*4, "", in)
66 }
67 }
68 }
69
70 func dprintf(depth int, format string, args ...any) {
71 fmt.Printf("%*s%s", depth*4, "", fmt.Sprintf(format, args...))
72 }
73
View as plain text