// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package goldmark import ( "strings" "testing" "github.com/spf13/cast" "github.com/gohugoio/hugo/markup/goldmark/goldmark_config" "github.com/gohugoio/hugo/markup/highlight" "github.com/gohugoio/hugo/markup/markup_config" "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/markup/converter" qt "github.com/frankban/quicktest" ) func convert(c *qt.C, mconf markup_config.Config, content string) converter.Result { p, err := Provider.New( converter.ProviderConfig{ MarkupConfig: mconf, Logger: loggers.NewErrorLogger(), }, ) c.Assert(err, qt.IsNil) conv, err := p.New(converter.DocumentContext{DocumentID: "thedoc"}) c.Assert(err, qt.IsNil) b, err := conv.Convert(converter.RenderContext{RenderTOC: true, Src: []byte(content)}) c.Assert(err, qt.IsNil) return b } func TestConvert(t *testing.T) { c := qt.New(t) // Smoke test of the default configuration. content := ` ## Links https://github.com/gohugoio/hugo/issues/6528 [Live Demo here!](https://docuapi.netlify.com/) [I'm an inline-style link with title](https://www.google.com "Google's Homepage") ## Code Fences §§§bash LINE1 §§§ ## Code Fences No Lexer §§§moo LINE1 §§§ ## Custom ID {#custom} ## Auto ID * Autolink: https://gohugo.io/ * Strikethrough:~~Hi~~ Hello, world! ## Table | foo | bar | | --- | --- | | baz | bim | ## Task Lists (default on) - [x] Finish my changes[^1] - [ ] Push my commits to GitHub - [ ] Open a pull request ## Smartypants (default on) * Straight double "quotes" and single 'quotes' into “curly” quote HTML entities * Dashes (“--” and “---”) into en- and em-dash entities * Three consecutive dots (“...”) into an ellipsis entity * Apostrophes are also converted: "That was back in the '90s, that's a long time ago" ## Footnotes That's some text with a footnote.[^1] ## Definition Lists date : the datetime assigned to this page. description : the description for the content. ## 神真美好 ## 神真美好 ## 神真美好 [^1]: And that's the footnote. ` // Code fences content = strings.Replace(content, "§§§", "```", -1) mconf := markup_config.Default mconf.Highlight.NoClasses = false mconf.Goldmark.Renderer.Unsafe = true b := convert(c, mconf, content) got := string(b.Bytes()) // Links // c.Assert(got, qt.Contains, `Live Demo here!`) // Header IDs c.Assert(got, qt.Contains, `

Custom ID

`, qt.Commentf(got)) c.Assert(got, qt.Contains, `

Auto ID

`, qt.Commentf(got)) c.Assert(got, qt.Contains, `

神真美好

`, qt.Commentf(got)) c.Assert(got, qt.Contains, `

神真美好

`, qt.Commentf(got)) c.Assert(got, qt.Contains, `

神真美好

`, qt.Commentf(got)) // Code fences c.Assert(got, qt.Contains, "
LINE1\n
") c.Assert(got, qt.Contains, "Code Fences No Lexer\n
LINE1\n
") // Extensions c.Assert(got, qt.Contains, `Autolink: https://gohugo.io/`) c.Assert(got, qt.Contains, `Strikethrough:Hi Hello, world`) c.Assert(got, qt.Contains, `foo`) c.Assert(got, qt.Contains, `
  • Push my commits to GitHub
  • `) c.Assert(got, qt.Contains, `Straight double “quotes” and single ‘quotes’`) c.Assert(got, qt.Contains, `Dashes (“–” and “—”) `) c.Assert(got, qt.Contains, `Three consecutive dots (“…”)`) c.Assert(got, qt.Contains, `“That was back in the ’90s, that’s a long time ago”`) c.Assert(got, qt.Contains, `footnote.1`) c.Assert(got, qt.Contains, `
    `) c.Assert(got, qt.Contains, `
    date
    `) toc, ok := b.(converter.TableOfContentsProvider) c.Assert(ok, qt.Equals, true) tocHTML := toc.TableOfContents().ToHTML(1, 2, false) c.Assert(tocHTML, qt.Contains, "TableOfContents") } func TestConvertAutoIDAsciiOnly(t *testing.T) { c := qt.New(t) content := ` ## God is Good: 神真美好 ` mconf := markup_config.Default mconf.Goldmark.Parser.AutoHeadingIDType = goldmark_config.AutoHeadingIDTypeGitHubAscii b := convert(c, mconf, content) got := string(b.Bytes()) c.Assert(got, qt.Contains, "

    ") } func TestConvertAutoIDBlackfriday(t *testing.T) { c := qt.New(t) content := ` ## Let's try this, shall we? ` mconf := markup_config.Default mconf.Goldmark.Parser.AutoHeadingIDType = goldmark_config.AutoHeadingIDTypeBlackfriday b := convert(c, mconf, content) got := string(b.Bytes()) c.Assert(got, qt.Contains, "

    ") } func TestConvertAttributes(t *testing.T) { c := qt.New(t) withBlockAttributes := func(conf *markup_config.Config) { conf.Goldmark.Parser.Attribute.Block = true conf.Goldmark.Parser.Attribute.Title = false } withTitleAndBlockAttributes := func(conf *markup_config.Config) { conf.Goldmark.Parser.Attribute.Block = true conf.Goldmark.Parser.Attribute.Title = true } for _, test := range []struct { name string withConfig func(conf *markup_config.Config) input string expect interface{} }{ { "Title", nil, "## heading {#id .className attrName=attrValue class=\"class1 class2\"}", "

    heading

    \n", }, { "Blockquote", withBlockAttributes, "> foo\n> bar\n{#id .className attrName=attrValue class=\"class1 class2\"}\n", "

    foo\nbar

    \n
    \n", }, { "Paragraph", withBlockAttributes, "\nHi there.\n{.myclass }", "

    Hi there.

    \n", }, { "Ordered list", withBlockAttributes, "\n1. First\n2. Second\n{.myclass }", "
      \n
    1. First
    2. \n
    3. Second
    4. \n
    \n", }, { "Unordered list", withBlockAttributes, "\n* First\n* Second\n{.myclass }", "\n", }, { "Unordered list, indented", withBlockAttributes, `* Fruit * Apple * Orange * Banana {.fruits} * Dairy * Milk * Cheese {.dairies} {.list}`, []string{"