// Copyright 2024 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package relnote import ( "fmt" "strings" md "rsc.io/markdown" ) // DumpMarkdown writes the internal structure of a markdown // document to standard output. // It is intended for debugging. func DumpMarkdown(d *md.Document) { dumpBlocks(d.Blocks, 0) } func dumpBlocks(bs []md.Block, depth int) { for _, b := range bs { dumpBlock(b, depth) } } func dumpBlock(b md.Block, depth int) { typeName := strings.TrimPrefix(fmt.Sprintf("%T", b), "*markdown.") dprintf(depth, "%s\n", typeName) switch b := b.(type) { case *md.Paragraph: dumpInlines(b.Text.Inline, depth+1) case *md.Heading: dumpInlines(b.Text.Inline, depth+1) case *md.List: dumpBlocks(b.Items, depth+1) case *md.Item: dumpBlocks(b.Blocks, depth+1) default: // TODO(jba): additional cases as needed. } } func dumpInlines(ins []md.Inline, depth int) { for _, in := range ins { switch in := in.(type) { case *md.Plain: dprintf(depth, "Plain(%q)\n", in.Text) case *md.Code: dprintf(depth, "Code(%q)\n", in.Text) case *md.Link: dprintf(depth, "Link:\n") dumpInlines(in.Inner, depth+1) dprintf(depth+1, "URL: %q\n", in.URL) case *md.Strong: dprintf(depth, "Strong(%q):\n", in.Marker) dumpInlines(in.Inner, depth+1) case *md.Emph: dprintf(depth, "Emph(%q):\n", in.Marker) dumpInlines(in.Inner, depth+1) case *md.Del: dprintf(depth, "Del(%q):\n", in.Marker) dumpInlines(in.Inner, depth+1) default: fmt.Printf("%*s%#v\n", depth*4, "", in) } } } func dprintf(depth int, format string, args ...any) { fmt.Printf("%*s%s", depth*4, "", fmt.Sprintf(format, args...)) }