goldmark-mmd

A different way of handling Markdown Metadata
git clone git://src.gearsix.net/goldmark-mmd
Log | Files | Refs | Atom | README | LICENSE

commit c86faa6ef073de09500c1c60d09abdb314fcf1f1
parent 6c98a7ff95e170f6af128781fdd61f6e1dfddb0c
Author: gearsix <gearsix@tuta.io>
Date:   Fri, 17 Feb 2023 16:09:28 +0000

meta_test.go: started makes changes to reflect meta.go refactors

Note that tests are not passing yet.

**added:**

- `metadata` type for `map[string]interface{}`
- `validSource`, a *map[string]string* containing equivalent source with
  differing metadata syntax for each metadata format.
- `invalidSource`, a *map[string]string* containing equivalent source
  with differing & invalid metadat syntax for each metadata format.
- `testMetaFormats`, a list of all keys in `validSource` and
  `invalidSource` (one for each accepted format).

**removed:**

- All tests to do with metdata table rendering, since it's being
  removed.

**refactored:**

- `TestMeta` tests against  `validSource`
- `TestMetaError` tests against each `invalidSource`
- Minor changes to code layout

Diffstat:
Mmeta.go | 13+++++++------
Mmeta_test.go | 289+++++++++++++++++++++++--------------------------------------------------------
2 files changed, 92 insertions(+), 210 deletions(-)

diff --git a/meta.go b/meta.go @@ -17,8 +17,10 @@ import ( "gopkg.in/yaml.v2" ) +type metadata map[string]interface{} + type data struct { - Map map[string]interface{} + Map metadata Items yaml.MapSlice Error error Node gast.Node @@ -32,7 +34,7 @@ type Option interface { } // Get returns a metadata. -func Get(pc parser.Context) map[string]interface{} { +func Get(pc parser.Context) metadata { v := pc.Get(contextKey) if v == nil { return nil @@ -43,7 +45,7 @@ func Get(pc parser.Context) map[string]interface{} { // TryGet tries to get a metadata. // If there are parsing errors, then nil and error are returned -func TryGet(pc parser.Context) (map[string]interface{}, error) { +func TryGet(pc parser.Context) (metadata, error) { dtmp := pc.Get(contextKey) if dtmp == nil { return nil, nil @@ -95,7 +97,7 @@ func isOpen(line []byte) bool { func isClose(line []byte, signal byte) bool { line = util.TrimRightSpace(util.TrimLeftSpace(line)) for i := 0; i < len(line); i++ { - if len(line[:i]) > len(closeToken)+1 && line[i] == signal { + if len(line[i:]) >= len(closeToken)+1 && line[i] == signal { i++ if string(line[i:i+len(closeToken)]) == closeToken { return true @@ -134,7 +136,6 @@ func (b *metaParser) Continue(node gast.Node, reader text.Reader, pc parser.Cont return parser.Continue | parser.NoChildren } -// TODO: bookmark func (b *metaParser) Close(node gast.Node, reader text.Reader, pc parser.Context) { lines := node.Lines() var buf bytes.Buffer @@ -144,7 +145,7 @@ func (b *metaParser) Close(node gast.Node, reader text.Reader, pc parser.Context } d := &data{} d.Node = node - meta := map[string]interface{}{} + meta := metadata{} if err := yaml.Unmarshal(buf.Bytes(), &meta); err != nil { d.Error = err } else { diff --git a/meta_test.go b/meta_test.go @@ -5,244 +5,125 @@ import ( "testing" "github.com/yuin/goldmark" - "github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/parser" - "github.com/yuin/goldmark/renderer" - "github.com/yuin/goldmark/text" - "github.com/yuin/goldmark/util" ) -func TestMeta(t *testing.T) { - markdown := goldmark.New( - goldmark.WithExtensions( - Meta, - ), - ) - source := `--- -Title: goldmark-meta +var testMetaFormats = []string{"yaml", "json", "toml"} +var validSource = map[string]string{ + "yaml": `<!--: +Title: mmd Summary: Add YAML metadata to the document Tags: - - markdown - - goldmark ---- - -# Hello goldmark-meta -` - - var buf bytes.Buffer - context := parser.NewContext() - if err := markdown.Convert([]byte(source), &buf, parser.WithContext(context)); err != nil { - panic(err) - } - metaData := Get(context) - title := metaData["Title"] - s, ok := title.(string) - if !ok { - t.Error("Title not found in meta data or is not a string") - } - if s != "goldmark-meta" { - t.Errorf("Title must be %s, but got %v", "goldmark-meta", s) - } - if buf.String() != "<h1>Hello goldmark-meta</h1>\n" { - t.Errorf("should render '<h1>Hello goldmark-meta</h1>', but '%s'", buf.String()) - } - tags, ok := metaData["Tags"].([]interface{}) - if !ok { - t.Error("Tags not found in meta data or is not a slice") - } - if len(tags) != 2 { - t.Error("Tags must be a slice that has 2 elements") - } - if tags[0] != "markdown" { - t.Errorf("Tag#1 must be 'markdown', but got %s", tags[0]) - } - if tags[1] != "goldmark" { - t.Errorf("Tag#2 must be 'goldmark', but got %s", tags[1]) - } +- markdown +- goldmark +:--> + +This is markdown with YAML metadata +`, + "json": `<!--{ "Title": "mmd", "Summary": "Add JSON metadata to the document", "Tags": [ "markdown", "goldmark" ] }-->`, + "toml": `<!--# Title = "mmd" + Summary = "Add TOML metadata to the document + Tags = [ "markdown", "goldmark" ] #-->`, } - -func TestMetaTable(t *testing.T) { - markdown := goldmark.New( - goldmark.WithExtensions( - New(WithTable()), - ), - goldmark.WithRendererOptions( - renderer.WithNodeRenderers( - util.Prioritized(extension.NewTableHTMLRenderer(), 500), - ), - ), - ) - source := `--- -Title: goldmark-meta +var invalidSource = map[string]string{ + "yaml": `<!--: +Title: mmd Summary: Add YAML metadata to the document Tags: - - markdown - - goldmark ---- - -# Hello goldmark-meta -` - - var buf bytes.Buffer - if err := markdown.Convert([]byte(source), &buf); err != nil { - panic(err) - } - if buf.String() != `<table> -<thead> -<tr> -<th>Title</th> -<th>Summary</th> -<th>Tags</th> -</tr> -</thead> -<tbody> -<tr> -<td>goldmark-meta</td> -<td>Add YAML metadata to the document</td> -<td>[markdown goldmark]</td> -</tr> -</tbody> -</table> -<h1>Hello goldmark-meta</h1> -` { - t.Error("invalid table output") - } +- : { +} + - markdown + - goldmark +:--> + +This is markdown with YAML metadata +`, + "json": `<!--{ "Title:" "mmd", "Summary": "Add JSON metadata to the document", "Tags": [ "markdown", "goldmark" ] }-->`, + "toml": `<!--# Title = "mmd" + Summary = "Add TOML metadata to the document + Tags == [ markdown", "goldmark ] #-->`, } -func TestMetaError(t *testing.T) { +func TestMeta(t *testing.T) { markdown := goldmark.New( goldmark.WithExtensions( - New(WithTable()), + Meta, ), ) - source := `--- -Title: goldmark-meta -Summary: Add YAML metadata to the document -Tags: - - : { - } - - markdown - - goldmark ---- - -# Hello goldmark-meta -` var buf bytes.Buffer context := parser.NewContext() - if err := markdown.Convert([]byte(source), &buf, parser.WithContext(context)); err != nil { - panic(err) - } - if buf.String() != `Title: goldmark-meta -Summary: Add YAML metadata to the document -Tags: - - : { - } - - markdown - - goldmark -<!-- yaml: line 3: did not find expected key --> -<h1>Hello goldmark-meta</h1> -` { - t.Error("invalid error output") - } - v, err := TryGet(context) - if err == nil { - t.Error("error should not be nil") - } - if v != nil { - t.Error("data should be nil when there are errors") + for _, format := range testMetaFormats { + if err := markdown.Convert([]byte(validSource[format]), &buf, parser.WithContext(context)); err != nil { + t.Fatal(err) + } + + metaData := Get(context) + + title := metaData["Title"] + if s, ok := title.(string); !ok { + t.Errorf("%s: Title not found in meta data or is not a string", format) + } else if s != "goldmark-meta" { + t.Errorf("%s: Title must be %s, but got %v", "goldmark-meta", format, s) + } + + if buf.String() != "<p>Hello goldmark-meta</p>\n" { + t.Errorf("%s: should render '<p>Hello goldmark-meta</p>', but '%s'", format, buf.String()) + } + + if tags, ok := metaData["Tags"].([]interface{}); !ok { + t.Errorf("%s: Tags not found in meta data or is not a slice", format) + } else if len(tags) != 2 { + t.Errorf("%s: Tags must be a slice that has 2 elements", format) + } else if tags[0] != "markdown" { + t.Errorf("%s: Tag#1 must be 'markdown', but got %s", format, tags[0]) + } else if tags[1] != "goldmark" { + t.Errorf("%s: Tag#2 must be 'goldmark', but got %s", format, tags[1]) + } } } -func TestMetaTableWithBlankline(t *testing.T) { +func TestMetaError(t *testing.T) { markdown := goldmark.New( goldmark.WithExtensions( - New(WithTable()), - ), - goldmark.WithRendererOptions( - renderer.WithNodeRenderers( - util.Prioritized(extension.NewTableHTMLRenderer(), 500), - ), + New(), ), ) - source := `--- -Title: goldmark-meta -Summary: Add YAML metadata to the document - -# comments -Tags: - - markdown - - goldmark ---- - -# Hello goldmark-meta -` var buf bytes.Buffer - if err := markdown.Convert([]byte(source), &buf); err != nil { - panic(err) + context := parser.NewContext() + + if err := markdown.Convert([]byte(invalidSource["json"]), &buf, parser.WithContext(context)); err != nil { + t.Fatal(err) } - if buf.String() != `<table> -<thead> -<tr> -<th>Title</th> -<th>Summary</th> -<th>Tags</th> -</tr> -</thead> -<tbody> -<tr> -<td>goldmark-meta</td> -<td>Add YAML metadata to the document</td> -<td>[markdown goldmark]</td> -</tr> -</tbody> -</table> -<h1>Hello goldmark-meta</h1> + if buf.String() != `<!-- json: line 1: TODO --> +<p>This is a markdown with JSON metadata</p> ` { - t.Error("invalid table output") + t.Error("json: invalid error output") } -} -func TestMetaStoreInDocument(t *testing.T) { - markdown := goldmark.New( - goldmark.WithExtensions( - New( - WithStoresInDocument(), - ), - ), - ) - source := `--- -Title: goldmark-meta -Summary: Add YAML metadata to the document -Tags: - - markdown - - goldmark ---- -` - - document := markdown.Parser().Parse(text.NewReader([]byte(source))) - metaData := document.OwnerDocument().Meta() - title := metaData["Title"] - s, ok := title.(string) - if !ok { - t.Error("Title not found in meta data or is not a string") - } - if s != "goldmark-meta" { - t.Errorf("Title must be %s, but got %v", "goldmark-meta", s) + if err := markdown.Convert([]byte(invalidSource["yaml"]), &buf, parser.WithContext(context)); err != nil { + t.Fatal(err) } - tags, ok := metaData["Tags"].([]interface{}) - if !ok { - t.Error("Tags not found in meta data or is not a slice") + if buf.String() != `<!-- yaml: line 3: did not find expected key --> +<p>This is markdown with YAML metadata</p> +` { + t.Error("yaml: invalid error output") } - if len(tags) != 2 { - t.Error("Tags must be a slice that has 2 elements") + + if err := markdown.Convert([]byte(invalidSource["toml"]), &buf, parser.WithContext(context)); err != nil { + t.Fatal(err) } - if tags[0] != "markdown" { - t.Errorf("Tag#1 must be 'markdown', but got %s", tags[0]) + if buf.String() != `<!-- toml: line 3: did not find expected key --> +<p>This is markdown with TOML metadata</p> +` { + t.Error("toml: invalid error output") } - if tags[1] != "goldmark" { - t.Errorf("Tag#2 must be 'goldmark', but got %s", tags[1]) + + if v, err := TryGet(context); err == nil { + t.Error("error should not be nil") + } else if v != nil { + t.Error("data should be nil when there are errors") } }