diff --git a/pkg/renderer/context.go b/pkg/renderer/context.go
index 376cb7db..e44001f7 100644
--- a/pkg/renderer/context.go
+++ b/pkg/renderer/context.go
@@ -15,7 +15,7 @@ type Context struct {
Attributes types.Attributes
ElementReferences types.ElementReferences
HasHeader bool
- SectionNumbering SectionNumbers
+ SectionNumbering types.SectionNumbers
}
// NewContext returns a new rendering context for the given document.
diff --git a/pkg/renderer/section_numbering.go b/pkg/renderer/section_numbering.go
deleted file mode 100644
index d6f59275..00000000
--- a/pkg/renderer/section_numbering.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package renderer
-
-import (
- "strconv"
-
- "github.com/bytesparadise/libasciidoc/pkg/types"
-)
-
-// SectionNumbers a registry of section numbers
-
-type SectionNumbers map[string]string // assigned number by section id
-
-// NewSectionNumbers initializes the registry with the content of the given doc
-// (ie, it traverses the doc to look for sections, and assigns them numbers, incrementally)
-func NewSectionNumbers(doc *types.Document) (SectionNumbers, error) {
- // traverse doc and its sections and assign numbers to the latters
- return traverseElements(doc.Elements, "")
-}
-
-func traverseElements(elements []interface{}, prefix string) (map[string]string, error) {
- result := map[string]string{}
- counter := 0
- for _, e := range elements {
- if s, ok := e.(*types.Section); ok {
- id, err := s.GetID()
- if err != nil {
- return nil, err
- }
- counter++
- n := prefix + strconv.Itoa(counter)
- result[id] = n
- numbers, err := traverseElements(s.Elements, n+".")
- if err != nil {
- return nil, err
- }
- for id, n := range numbers {
- result[id] = n
- }
- }
- }
- return result, nil
-}
diff --git a/pkg/renderer/section_numbering_test.go b/pkg/renderer/section_numbering_test.go
deleted file mode 100644
index 5a2ab28d..00000000
--- a/pkg/renderer/section_numbering_test.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package renderer_test
-
-import (
- "github.com/bytesparadise/libasciidoc/pkg/renderer"
- "github.com/bytesparadise/libasciidoc/pkg/types"
-
- . "github.com/onsi/ginkgo/v2"
- . "github.com/onsi/gomega"
-)
-
-var _ = Describe("section numbering", func() {
-
- It("should number sections", func() {
- // given
- doc := &types.Document{
- Elements: []interface{}{
- &types.Section{
- Attributes: types.Attributes{
- types.AttrID: "_section_1",
- },
- Elements: []interface{}{
- &types.Section{
- Attributes: types.Attributes{
- types.AttrID: "_section_1a",
- },
- Elements: []interface{}{},
- },
- &types.Section{
- Attributes: types.Attributes{
- types.AttrID: "_section_1b",
- },
- Elements: []interface{}{},
- },
- },
- },
- },
- }
- // when
- n, err := renderer.NewSectionNumbers(doc)
-
- // then
- Expect(err).NotTo(HaveOccurred())
- Expect(n["_section_1"]).To(Equal("1"))
- Expect(n["_section_1a"]).To(Equal("1.1"))
- Expect(n["_section_1b"]).To(Equal("1.2"))
- })
-})
diff --git a/pkg/renderer/sgml/elements.go b/pkg/renderer/sgml/elements.go
index 5892fd9c..a4600d97 100644
--- a/pkg/renderer/sgml/elements.go
+++ b/pkg/renderer/sgml/elements.go
@@ -7,7 +7,6 @@ import (
"github.com/bytesparadise/libasciidoc/pkg/types"
"github.com/pkg/errors"
- log "github.com/sirupsen/logrus"
)
func (r *sgmlRenderer) renderElements(ctx *renderer.Context, elements []interface{}) (string, error) {
@@ -119,7 +118,7 @@ func (r *sgmlRenderer) renderElement(ctx *renderer.Context, element interface{})
}
func (r *sgmlRenderer) renderPlainText(ctx *renderer.Context, element interface{}) (string, error) {
- log.Debugf("rendering plain string for element of type %T", element)
+ // log.Debugf("rendering plain string for element of type %T", element)
switch e := element.(type) {
case []interface{}:
return r.renderInlineElements(ctx, e, withRenderer(r.renderPlainText))
diff --git a/pkg/renderer/sgml/html5/section_test.go b/pkg/renderer/sgml/html5/section_test.go
index 1e4436b4..af0af1f2 100644
--- a/pkg/renderer/sgml/html5/section_test.go
+++ b/pkg/renderer/sgml/html5/section_test.go
@@ -153,7 +153,7 @@ var _ = Describe("sections", func() {
Expect(RenderHTML(source)).To(MatchHTML(expected))
})
- It("with numbering", func() {
+ It("with numbering always enabled", func() {
source := `= A title
:sectnums:
@@ -198,6 +198,64 @@ var _ = Describe("sections", func() {
+`
+ Expect(RenderHTML(source)).To(MatchHTML(expected))
+ })
+
+ It("with numbering disabled and enabled again", func() {
+ source := `= A title
+:sectnums!:
+
+== Disclaimer
+
+:sectnums:
+
+== Section A
+
+=== Section A.a
+
+=== Section A.b
+
+==== Section that shall not be in ToC
+
+== Section B
+
+=== Section B.a
+
+== Section C`
+
+ expected := `
+
+
1. Section A
+
+
+
1.1. Section A.a
+
+
+
1.2. Section A.b
+
+
1.2.1. Section that shall not be in ToC
+
+
+
+
+
+
`
Expect(RenderHTML(source)).To(MatchHTML(expected))
})
diff --git a/pkg/renderer/sgml/inline_elements.go b/pkg/renderer/sgml/inline_elements.go
index cacc4a9c..e16d9390 100644
--- a/pkg/renderer/sgml/inline_elements.go
+++ b/pkg/renderer/sgml/inline_elements.go
@@ -5,7 +5,6 @@ import (
"github.com/bytesparadise/libasciidoc/pkg/renderer"
"github.com/bytesparadise/libasciidoc/pkg/types"
- log "github.com/sirupsen/logrus"
)
func (r *sgmlRenderer) renderInlineElements(ctx *renderer.Context, elements []interface{}, options ...lineRendererOption) (string, error) {
@@ -32,9 +31,9 @@ func (r *sgmlRenderer) renderInlineElements(ctx *renderer.Context, elements []in
buf.WriteString(renderedElement)
}
}
- if log.IsLevelEnabled(log.DebugLevel) {
- log.Debugf("rendered inline elements: '%s'", buf.String())
- }
+ // if log.IsLevelEnabled(log.DebugLevel) {
+ // log.Debugf("rendered inline elements: '%s'", buf.String())
+ // }
return buf.String(), nil
}
diff --git a/pkg/renderer/sgml/renderer.go b/pkg/renderer/sgml/renderer.go
index d7366ded..6a40cdd3 100644
--- a/pkg/renderer/sgml/renderer.go
+++ b/pkg/renderer/sgml/renderer.go
@@ -172,13 +172,8 @@ func (r *sgmlRenderer) Render(ctx *renderer.Context, doc *types.Document, output
}
}
}
- if ctx.Attributes.Has(types.AttrSectionNumbering) || ctx.Attributes.Has(types.AttrNumbered) {
- var err error
- if ctx.SectionNumbering, err = renderer.NewSectionNumbers(doc); err != nil {
- return metadata, errors.Wrapf(err, "unable to render full document")
- }
- } else {
- log.Debug("section numbering is not enabled")
+ if ctx.SectionNumbering, err = doc.SectionNumbers(); err != nil {
+ return metadata, errors.Wrapf(err, "unable to render full document")
}
// needs to be set before rendering the content elements
diff --git a/pkg/types/section_numbering_test.go b/pkg/types/section_numbering_test.go
new file mode 100644
index 00000000..a913aca7
--- /dev/null
+++ b/pkg/types/section_numbering_test.go
@@ -0,0 +1,207 @@
+package types_test
+
+import (
+ "github.com/bytesparadise/libasciidoc/pkg/types"
+
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("section numbering", func() {
+
+ It("should always number sections - explicitly in document header", func() {
+ // given
+ doc := &types.Document{
+ Elements: []interface{}{
+ &types.DocumentHeader{
+ Elements: []interface{}{
+ &types.AttributeDeclaration{
+ Name: types.AttrSectionNumbering,
+ },
+ },
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1",
+ },
+ Elements: []interface{}{
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1a",
+ },
+ Elements: []interface{}{},
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1b",
+ },
+ Elements: []interface{}{},
+ },
+ },
+ },
+ },
+ }
+ // when
+ n, err := doc.SectionNumbers()
+
+ // then
+ Expect(err).NotTo(HaveOccurred())
+ Expect(n["_section_1"]).To(Equal("1"))
+ Expect(n["_section_1a"]).To(Equal("1.1"))
+ Expect(n["_section_1b"]).To(Equal("1.2"))
+ })
+
+ It("should always number sections - explicitly in document body", func() {
+ // given
+ doc := &types.Document{
+ Elements: []interface{}{
+ &types.AttributeDeclaration{
+ Name: types.AttrSectionNumbering,
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1",
+ },
+ Elements: []interface{}{
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1a",
+ },
+ Elements: []interface{}{},
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1b",
+ },
+ Elements: []interface{}{},
+ },
+ },
+ },
+ },
+ }
+ // when
+ n, err := doc.SectionNumbers()
+
+ // then
+ Expect(err).NotTo(HaveOccurred())
+ Expect(n["_section_1"]).To(Equal("1"))
+ Expect(n["_section_1a"]).To(Equal("1.1"))
+ Expect(n["_section_1b"]).To(Equal("1.2"))
+ })
+
+ It("should never number sections - explicitly", func() {
+ // given
+ doc := &types.Document{
+ Elements: []interface{}{
+ &types.AttributeReset{
+ Name: types.AttrSectionNumbering,
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1",
+ },
+ Elements: []interface{}{
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1a",
+ },
+ Elements: []interface{}{},
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1b",
+ },
+ Elements: []interface{}{},
+ },
+ },
+ },
+ },
+ }
+ // when
+ n, err := doc.SectionNumbers()
+
+ // then
+ Expect(err).NotTo(HaveOccurred())
+ Expect(n).To(BeEmpty())
+ })
+
+ It("should never number sections - by default", func() {
+ // given
+ doc := &types.Document{
+ Elements: []interface{}{
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1",
+ },
+ Elements: []interface{}{
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1a",
+ },
+ Elements: []interface{}{},
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1b",
+ },
+ Elements: []interface{}{},
+ },
+ },
+ },
+ },
+ }
+ // when
+ n, err := doc.SectionNumbers()
+
+ // then
+ Expect(err).NotTo(HaveOccurred())
+ Expect(n).To(BeEmpty())
+ })
+
+ It("should number sections when enabled - case 1", func() {
+ // given
+ doc := &types.Document{
+ Elements: []interface{}{
+ &types.AttributeReset{
+ Name: types.AttrSectionNumbering,
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_disclaimer",
+ },
+ },
+ &types.AttributeDeclaration{
+ Name: types.AttrSectionNumbering,
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1",
+ },
+ Elements: []interface{}{
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1a",
+ },
+ Elements: []interface{}{},
+ },
+ &types.Section{
+ Attributes: types.Attributes{
+ types.AttrID: "_section_1b",
+ },
+ Elements: []interface{}{},
+ },
+ },
+ },
+ },
+ }
+ // when
+ n, err := doc.SectionNumbers()
+
+ // then
+ Expect(err).NotTo(HaveOccurred())
+ Expect(n["_disclaimer"]).To(BeEmpty())
+ Expect(n["_section_1"]).To(Equal("1"))
+ Expect(n["_section_1a"]).To(Equal("1.1"))
+ Expect(n["_section_1b"]).To(Equal("1.2"))
+ })
+})
diff --git a/pkg/types/types.go b/pkg/types/types.go
index c4f06c85..4913191a 100644
--- a/pkg/types/types.go
+++ b/pkg/types/types.go
@@ -141,6 +141,58 @@ func (d *Document) AddElement(element interface{}) error {
return nil
}
+type SectionNumbers map[string]string // assigned number by section id
+
+func (d *Document) SectionNumbers() (SectionNumbers, error) {
+ enabled := false
+ if h := d.Header(); h != nil {
+ // lookup the `sectnums` or `numbered` attribute in the header
+ var err error
+ if _, enabled, err = traverseElements(h.Elements, false, ""); err != nil {
+ return nil, err
+ }
+ }
+ numbers, _, err := traverseElements(d.Elements, enabled, "") // disabled by default
+ return numbers, err
+}
+
+func traverseElements(elements []interface{}, enabled bool, prefix string) (map[string]string, bool, error) {
+ result := map[string]string{}
+ counter := 0
+ for _, e := range elements {
+ switch e := e.(type) {
+ case *AttributeDeclaration:
+ if e.Name == AttrSectionNumbering || e.Name == AttrNumbered {
+ enabled = true
+ }
+ case *AttributeReset:
+ if e.Name == AttrSectionNumbering || e.Name == AttrNumbered {
+ enabled = false
+ }
+ case *Section:
+ var n string
+ if enabled {
+ id, err := e.GetID()
+ if err != nil {
+ return nil, false, err
+ }
+ counter++
+ n = prefix + strconv.Itoa(counter)
+ result[id] = n
+ }
+ numbers, en, err := traverseElements(e.Elements, enabled, n+".")
+ if err != nil {
+ return nil, false, err
+ }
+ enabled = en
+ for id, n := range numbers {
+ result[id] = n
+ }
+ }
+ }
+ return result, enabled, nil
+}
+
// ------------------------------------------
// Document Metadata
// ------------------------------------------