github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/markup/asciidocext/convert_test.go (about)

     1  // Copyright 2020 The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  // Package asciidocext converts AsciiDoc to HTML using Asciidoctor
    15  // external binary. The `asciidoc` module is reserved for a future golang
    16  // implementation.
    17  
    18  package asciidocext
    19  
    20  import (
    21  	"path/filepath"
    22  	"testing"
    23  
    24  	"github.com/gohugoio/hugo/common/loggers"
    25  	"github.com/gohugoio/hugo/config"
    26  	"github.com/gohugoio/hugo/markup/converter"
    27  	"github.com/gohugoio/hugo/markup/markup_config"
    28  	"github.com/gohugoio/hugo/markup/tableofcontents"
    29  
    30  	qt "github.com/frankban/quicktest"
    31  )
    32  
    33  func TestAsciidoctorDefaultArgs(t *testing.T) {
    34  	c := qt.New(t)
    35  	cfg := config.New()
    36  	mconf := markup_config.Default
    37  
    38  	p, err := Provider.New(
    39  		converter.ProviderConfig{
    40  			Cfg:          cfg,
    41  			MarkupConfig: mconf,
    42  			Logger:       loggers.NewErrorLogger(),
    43  		},
    44  	)
    45  	c.Assert(err, qt.IsNil)
    46  
    47  	conv, err := p.New(converter.DocumentContext{})
    48  	c.Assert(err, qt.IsNil)
    49  
    50  	ac := conv.(*asciidocConverter)
    51  	c.Assert(ac, qt.Not(qt.IsNil))
    52  
    53  	args := ac.parseArgs(converter.DocumentContext{})
    54  	expected := []string{"--no-header-footer"}
    55  	c.Assert(args, qt.DeepEquals, expected)
    56  }
    57  
    58  func TestAsciidoctorNonDefaultArgs(t *testing.T) {
    59  	c := qt.New(t)
    60  	cfg := config.New()
    61  	mconf := markup_config.Default
    62  	mconf.AsciidocExt.Backend = "manpage"
    63  	mconf.AsciidocExt.NoHeaderOrFooter = false
    64  	mconf.AsciidocExt.SafeMode = "safe"
    65  	mconf.AsciidocExt.SectionNumbers = true
    66  	mconf.AsciidocExt.Verbose = true
    67  	mconf.AsciidocExt.Trace = false
    68  	mconf.AsciidocExt.FailureLevel = "warn"
    69  	p, err := Provider.New(
    70  		converter.ProviderConfig{
    71  			Cfg:          cfg,
    72  			MarkupConfig: mconf,
    73  			Logger:       loggers.NewErrorLogger(),
    74  		},
    75  	)
    76  	c.Assert(err, qt.IsNil)
    77  
    78  	conv, err := p.New(converter.DocumentContext{})
    79  	c.Assert(err, qt.IsNil)
    80  
    81  	ac := conv.(*asciidocConverter)
    82  	c.Assert(ac, qt.Not(qt.IsNil))
    83  
    84  	args := ac.parseArgs(converter.DocumentContext{})
    85  	expected := []string{"-b", "manpage", "--section-numbers", "--verbose", "--failure-level", "warn", "--safe-mode", "safe"}
    86  	c.Assert(args, qt.DeepEquals, expected)
    87  }
    88  
    89  func TestAsciidoctorDisallowedArgs(t *testing.T) {
    90  	c := qt.New(t)
    91  	cfg := config.New()
    92  	mconf := markup_config.Default
    93  	mconf.AsciidocExt.Backend = "disallowed-backend"
    94  	mconf.AsciidocExt.Extensions = []string{"./disallowed-extension"}
    95  	mconf.AsciidocExt.Attributes = map[string]string{"outdir": "disallowed-attribute"}
    96  	mconf.AsciidocExt.SafeMode = "disallowed-safemode"
    97  	mconf.AsciidocExt.FailureLevel = "disallowed-failurelevel"
    98  	p, err := Provider.New(
    99  		converter.ProviderConfig{
   100  			Cfg:          cfg,
   101  			MarkupConfig: mconf,
   102  			Logger:       loggers.NewErrorLogger(),
   103  		},
   104  	)
   105  	c.Assert(err, qt.IsNil)
   106  
   107  	conv, err := p.New(converter.DocumentContext{})
   108  	c.Assert(err, qt.IsNil)
   109  
   110  	ac := conv.(*asciidocConverter)
   111  	c.Assert(ac, qt.Not(qt.IsNil))
   112  
   113  	args := ac.parseArgs(converter.DocumentContext{})
   114  	expected := []string{"--no-header-footer"}
   115  	c.Assert(args, qt.DeepEquals, expected)
   116  }
   117  
   118  func TestAsciidoctorArbitraryExtension(t *testing.T) {
   119  	c := qt.New(t)
   120  	cfg := config.New()
   121  	mconf := markup_config.Default
   122  	mconf.AsciidocExt.Extensions = []string{"arbitrary-extension"}
   123  	p, err := Provider.New(
   124  		converter.ProviderConfig{
   125  			Cfg:          cfg,
   126  			MarkupConfig: mconf,
   127  			Logger:       loggers.NewErrorLogger(),
   128  		},
   129  	)
   130  	c.Assert(err, qt.IsNil)
   131  
   132  	conv, err := p.New(converter.DocumentContext{})
   133  	c.Assert(err, qt.IsNil)
   134  
   135  	ac := conv.(*asciidocConverter)
   136  	c.Assert(ac, qt.Not(qt.IsNil))
   137  
   138  	args := ac.parseArgs(converter.DocumentContext{})
   139  	expected := []string{"-r", "arbitrary-extension", "--no-header-footer"}
   140  	c.Assert(args, qt.DeepEquals, expected)
   141  }
   142  
   143  func TestAsciidoctorDisallowedExtension(t *testing.T) {
   144  	c := qt.New(t)
   145  	cfg := config.New()
   146  	for _, disallowedExtension := range []string{
   147  		`foo-bar//`,
   148  		`foo-bar\\ `,
   149  		`../../foo-bar`,
   150  		`/foo-bar`,
   151  		`C:\foo-bar`,
   152  		`foo-bar.rb`,
   153  		`foo.bar`,
   154  	} {
   155  		mconf := markup_config.Default
   156  		mconf.AsciidocExt.Extensions = []string{disallowedExtension}
   157  		p, err := Provider.New(
   158  			converter.ProviderConfig{
   159  				Cfg:          cfg,
   160  				MarkupConfig: mconf,
   161  				Logger:       loggers.NewErrorLogger(),
   162  			},
   163  		)
   164  		c.Assert(err, qt.IsNil)
   165  
   166  		conv, err := p.New(converter.DocumentContext{})
   167  		c.Assert(err, qt.IsNil)
   168  
   169  		ac := conv.(*asciidocConverter)
   170  		c.Assert(ac, qt.Not(qt.IsNil))
   171  
   172  		args := ac.parseArgs(converter.DocumentContext{})
   173  		expected := []string{"--no-header-footer"}
   174  		c.Assert(args, qt.DeepEquals, expected)
   175  	}
   176  }
   177  
   178  func TestAsciidoctorWorkingFolderCurrent(t *testing.T) {
   179  	c := qt.New(t)
   180  	cfg := config.New()
   181  	mconf := markup_config.Default
   182  	mconf.AsciidocExt.WorkingFolderCurrent = true
   183  	mconf.AsciidocExt.Trace = false
   184  	p, err := Provider.New(
   185  		converter.ProviderConfig{
   186  			Cfg:          cfg,
   187  			MarkupConfig: mconf,
   188  			Logger:       loggers.NewErrorLogger(),
   189  		},
   190  	)
   191  	c.Assert(err, qt.IsNil)
   192  
   193  	ctx := converter.DocumentContext{Filename: "/tmp/hugo_asciidoc_ddd/docs/chapter2/index.adoc", DocumentName: "chapter2/index.adoc"}
   194  	conv, err := p.New(ctx)
   195  	c.Assert(err, qt.IsNil)
   196  
   197  	ac := conv.(*asciidocConverter)
   198  	c.Assert(ac, qt.Not(qt.IsNil))
   199  
   200  	args := ac.parseArgs(ctx)
   201  	c.Assert(len(args), qt.Equals, 5)
   202  	c.Assert(args[0], qt.Equals, "--base-dir")
   203  	c.Assert(filepath.ToSlash(args[1]), qt.Matches, "/tmp/hugo_asciidoc_ddd/docs/chapter2")
   204  	c.Assert(args[2], qt.Equals, "-a")
   205  	c.Assert(args[3], qt.Matches, `outdir=.*[/\\]{1,2}asciidocext[/\\]{1,2}chapter2`)
   206  	c.Assert(args[4], qt.Equals, "--no-header-footer")
   207  }
   208  
   209  func TestAsciidoctorWorkingFolderCurrentAndExtensions(t *testing.T) {
   210  	c := qt.New(t)
   211  	cfg := config.New()
   212  	mconf := markup_config.Default
   213  	mconf.AsciidocExt.NoHeaderOrFooter = true
   214  	mconf.AsciidocExt.Extensions = []string{"asciidoctor-html5s", "asciidoctor-diagram"}
   215  	mconf.AsciidocExt.Backend = "html5s"
   216  	mconf.AsciidocExt.WorkingFolderCurrent = true
   217  	mconf.AsciidocExt.Trace = false
   218  	p, err := Provider.New(
   219  		converter.ProviderConfig{
   220  			Cfg:          cfg,
   221  			MarkupConfig: mconf,
   222  			Logger:       loggers.NewErrorLogger(),
   223  		},
   224  	)
   225  	c.Assert(err, qt.IsNil)
   226  
   227  	conv, err := p.New(converter.DocumentContext{})
   228  	c.Assert(err, qt.IsNil)
   229  
   230  	ac := conv.(*asciidocConverter)
   231  	c.Assert(ac, qt.Not(qt.IsNil))
   232  
   233  	args := ac.parseArgs(converter.DocumentContext{})
   234  	c.Assert(len(args), qt.Equals, 11)
   235  	c.Assert(args[0], qt.Equals, "-b")
   236  	c.Assert(args[1], qt.Equals, "html5s")
   237  	c.Assert(args[2], qt.Equals, "-r")
   238  	c.Assert(args[3], qt.Equals, "asciidoctor-html5s")
   239  	c.Assert(args[4], qt.Equals, "-r")
   240  	c.Assert(args[5], qt.Equals, "asciidoctor-diagram")
   241  	c.Assert(args[6], qt.Equals, "--base-dir")
   242  	c.Assert(args[7], qt.Equals, ".")
   243  	c.Assert(args[8], qt.Equals, "-a")
   244  	c.Assert(args[9], qt.Contains, "outdir=")
   245  	c.Assert(args[10], qt.Equals, "--no-header-footer")
   246  }
   247  
   248  func TestAsciidoctorAttributes(t *testing.T) {
   249  	c := qt.New(t)
   250  	cfg := config.New()
   251  	mconf := markup_config.Default
   252  	mconf.AsciidocExt.Attributes = map[string]string{"my-base-url": "https://gohugo.io/", "my-attribute-name": "my value"}
   253  	mconf.AsciidocExt.Trace = false
   254  	p, err := Provider.New(
   255  		converter.ProviderConfig{
   256  			Cfg:          cfg,
   257  			MarkupConfig: mconf,
   258  			Logger:       loggers.NewErrorLogger(),
   259  		},
   260  	)
   261  	c.Assert(err, qt.IsNil)
   262  
   263  	conv, err := p.New(converter.DocumentContext{})
   264  	c.Assert(err, qt.IsNil)
   265  
   266  	ac := conv.(*asciidocConverter)
   267  	c.Assert(ac, qt.Not(qt.IsNil))
   268  
   269  	expectedValues := map[string]bool{
   270  		"my-base-url=https://gohugo.io/": true,
   271  		"my-attribute-name=my value":     true,
   272  	}
   273  
   274  	args := ac.parseArgs(converter.DocumentContext{})
   275  	c.Assert(len(args), qt.Equals, 5)
   276  	c.Assert(args[0], qt.Equals, "-a")
   277  	c.Assert(expectedValues[args[1]], qt.Equals, true)
   278  	c.Assert(args[2], qt.Equals, "-a")
   279  	c.Assert(expectedValues[args[3]], qt.Equals, true)
   280  	c.Assert(args[4], qt.Equals, "--no-header-footer")
   281  }
   282  
   283  func TestConvert(t *testing.T) {
   284  	if !Supports() {
   285  		t.Skip("asciidoctor not installed")
   286  	}
   287  	c := qt.New(t)
   288  
   289  	mconf := markup_config.Default
   290  	p, err := Provider.New(
   291  		converter.ProviderConfig{
   292  			MarkupConfig: mconf,
   293  			Logger:       loggers.NewErrorLogger(),
   294  		},
   295  	)
   296  	c.Assert(err, qt.IsNil)
   297  
   298  	conv, err := p.New(converter.DocumentContext{})
   299  	c.Assert(err, qt.IsNil)
   300  
   301  	b, err := conv.Convert(converter.RenderContext{Src: []byte("testContent")})
   302  	c.Assert(err, qt.IsNil)
   303  	c.Assert(string(b.Bytes()), qt.Equals, "<div class=\"paragraph\">\n<p>testContent</p>\n</div>\n")
   304  }
   305  
   306  func TestTableOfContents(t *testing.T) {
   307  	if !Supports() {
   308  		t.Skip("asciidoctor not installed")
   309  	}
   310  	c := qt.New(t)
   311  	mconf := markup_config.Default
   312  	p, err := Provider.New(
   313  		converter.ProviderConfig{
   314  			MarkupConfig: mconf,
   315  			Logger:       loggers.NewErrorLogger(),
   316  		},
   317  	)
   318  	c.Assert(err, qt.IsNil)
   319  	conv, err := p.New(converter.DocumentContext{})
   320  	c.Assert(err, qt.IsNil)
   321  	r, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: macro
   322  :toclevels: 4
   323  toc::[]
   324  
   325  === Introduction
   326  
   327  == Section 1
   328  
   329  === Section 1.1
   330  
   331  ==== Section 1.1.1
   332  
   333  === Section 1.2
   334  
   335  testContent
   336  
   337  == Section 2
   338  `)})
   339  	c.Assert(err, qt.IsNil)
   340  	toc, ok := r.(converter.TableOfContentsProvider)
   341  	c.Assert(ok, qt.Equals, true)
   342  	expected := tableofcontents.Root{
   343  		Headings: tableofcontents.Headings{
   344  			{
   345  				ID:   "",
   346  				Text: "",
   347  				Headings: tableofcontents.Headings{
   348  					{
   349  						ID:       "_introduction",
   350  						Text:     "Introduction",
   351  						Headings: nil,
   352  					},
   353  					{
   354  						ID:   "_section_1",
   355  						Text: "Section 1",
   356  						Headings: tableofcontents.Headings{
   357  							{
   358  								ID:   "_section_1_1",
   359  								Text: "Section 1.1",
   360  								Headings: tableofcontents.Headings{
   361  									{
   362  										ID:       "_section_1_1_1",
   363  										Text:     "Section 1.1.1",
   364  										Headings: nil,
   365  									},
   366  								},
   367  							},
   368  							{
   369  								ID:       "_section_1_2",
   370  								Text:     "Section 1.2",
   371  								Headings: nil,
   372  							},
   373  						},
   374  					},
   375  					{
   376  						ID:       "_section_2",
   377  						Text:     "Section 2",
   378  						Headings: nil,
   379  					},
   380  				},
   381  			},
   382  		},
   383  	}
   384  	c.Assert(toc.TableOfContents(), qt.DeepEquals, expected)
   385  	c.Assert(string(r.Bytes()), qt.Not(qt.Contains), "<div id=\"toc\" class=\"toc\">")
   386  }
   387  
   388  func TestTableOfContentsWithCode(t *testing.T) {
   389  	if !Supports() {
   390  		t.Skip("asciidoctor not installed")
   391  	}
   392  	c := qt.New(t)
   393  	mconf := markup_config.Default
   394  	p, err := Provider.New(
   395  		converter.ProviderConfig{
   396  			MarkupConfig: mconf,
   397  			Logger:       loggers.NewErrorLogger(),
   398  		},
   399  	)
   400  	c.Assert(err, qt.IsNil)
   401  	conv, err := p.New(converter.DocumentContext{})
   402  	c.Assert(err, qt.IsNil)
   403  	r, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: auto
   404  
   405  == Some ` + "`code`" + ` in the title
   406  `)})
   407  	c.Assert(err, qt.IsNil)
   408  	toc, ok := r.(converter.TableOfContentsProvider)
   409  	c.Assert(ok, qt.Equals, true)
   410  	expected := tableofcontents.Root{
   411  		Headings: tableofcontents.Headings{
   412  			{
   413  				ID:   "",
   414  				Text: "",
   415  				Headings: tableofcontents.Headings{
   416  					{
   417  						ID:       "_some_code_in_the_title",
   418  						Text:     "Some <code>code</code> in the title",
   419  						Headings: nil,
   420  					},
   421  				},
   422  			},
   423  		},
   424  	}
   425  	c.Assert(toc.TableOfContents(), qt.DeepEquals, expected)
   426  	c.Assert(string(r.Bytes()), qt.Not(qt.Contains), "<div id=\"toc\" class=\"toc\">")
   427  }
   428  
   429  func TestTableOfContentsPreserveTOC(t *testing.T) {
   430  	if !Supports() {
   431  		t.Skip("asciidoctor not installed")
   432  	}
   433  	c := qt.New(t)
   434  	mconf := markup_config.Default
   435  	mconf.AsciidocExt.PreserveTOC = true
   436  	p, err := Provider.New(
   437  		converter.ProviderConfig{
   438  			MarkupConfig: mconf,
   439  			Logger:       loggers.NewErrorLogger(),
   440  		},
   441  	)
   442  	c.Assert(err, qt.IsNil)
   443  	conv, err := p.New(converter.DocumentContext{})
   444  	c.Assert(err, qt.IsNil)
   445  	r, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc:
   446  :idprefix:
   447  :idseparator: -
   448  
   449  == Some title
   450  `)})
   451  	c.Assert(err, qt.IsNil)
   452  	toc, ok := r.(converter.TableOfContentsProvider)
   453  	c.Assert(ok, qt.Equals, true)
   454  	expected := tableofcontents.Root{
   455  		Headings: tableofcontents.Headings{
   456  			{
   457  				ID:   "",
   458  				Text: "",
   459  				Headings: tableofcontents.Headings{
   460  					{
   461  						ID:       "some-title",
   462  						Text:     "Some title",
   463  						Headings: nil,
   464  					},
   465  				},
   466  			},
   467  		},
   468  	}
   469  	c.Assert(toc.TableOfContents(), qt.DeepEquals, expected)
   470  	c.Assert(string(r.Bytes()), qt.Contains, "<div id=\"toc\" class=\"toc\">")
   471  }