diff --git a/go.mod b/go.mod index a6077fd95..1a9c5c1d0 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/stateful/runme go 1.21 +// replace github.com/yuin/goldmark => ../../pastuxso/goldmark + require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 diff --git a/internal/document/editor/cell.go b/internal/document/editor/cell.go index 56e4b7e43..68044f97e 100644 --- a/internal/document/editor/cell.go +++ b/internal/document/editor/cell.go @@ -2,6 +2,7 @@ package editor import ( "bytes" + "fmt" "io" "strconv" "strings" @@ -144,6 +145,11 @@ func toCellsRec( case *document.MarkdownBlock: value := block.Value() + astNode := block.Unwrap() + + metadata := &map[string]string{} + + DumpToMap(astNode, source, astNode.Kind().String(), 0, metadata) isListItem := node.Item() != nil && node.Item().Unwrap().Kind() == ast.KindListItem if childIdx == 0 && isListItem { @@ -168,8 +174,9 @@ func toCellsRec( } *cells = append(*cells, &Cell{ - Kind: MarkupKind, - Value: fmtValue(value), + Kind: MarkupKind, + Value: fmtValue(value), + Metadata: *metadata, }) } } @@ -292,3 +299,76 @@ func trimRightNewLine(s []byte) []byte { s = bytes.TrimRight(s, "\r\n") return bytes.TrimRight(s, "\n") } + +func DumpToMap(node ast.Node, source []byte, root string, level int, metadata *map[string]string) { + rootKey := "runme.dev/" + + if level > 0 { + rootKey = fmt.Sprintf("%s%s/", rootKey, root) + } + + (*metadata)[rootKey+"Kind"] = node.Kind().String() + + if node.Type() == ast.TypeBlock { + buf := []string{} + + for i := 0; i < node.Lines().Len(); i++ { + line := node.Lines().At(i) + buf = append(buf, string(line.Value(source))) + } + + (*metadata)[rootKey+"RawText"] = strings.Join(buf, "") + (*metadata)[rootKey+"HasBlankPreviousLines"] = strconv.FormatBool(node.HasBlankPreviousLines()) + } + + for name, value := range DumpAttributes(node, source) { + (*metadata)[rootKey+name] = value + } + + for c := node.FirstChild(); c != nil; c = c.NextSibling() { + DumpToMap(c, source, root, level+1, metadata) + } +} + +func DumpAttributes(node ast.Node, source []byte) map[string]string { + attributes := map[string]string{} + + switch node.Kind() { + case ast.KindHeading: + heading := node.(*ast.Heading) + attributes["Level"] = fmt.Sprintf("%d", heading.Level) + + case ast.KindText: + text := node.(*ast.Text) + + buf := []string{} + if text.SoftLineBreak() { + buf = append(buf, "SoftLineBreak") + } + if text.HardLineBreak() { + buf = append(buf, "HardLineBreak") + } + if text.IsRaw() { + buf = append(buf, "Raw") + } + + // if text.IsCode() { + // buf = append(buf, "Code") + // } + + fs := strings.Join(buf, ", ") + if len(fs) != 0 { + fs = "(" + fs + ")" + } + + attributes[fmt.Sprintf("Text%s", fs)] = strings.TrimRight(string(text.Text(source)), "\n") + + case ast.KindLink: + link := node.(*ast.Link) + attributes["HasLink"] = "true" + attributes["Destination"] = string(link.Destination) + attributes["Title"] = string(link.Title) + } + + return attributes +}