Skip to content

Commit

Permalink
feat(parser): support file inclusion with absolute level offset (#438)
Browse files Browse the repository at this point in the history
support absolute level offset, converting the absolute offset
into a relative offset based on the actual offset that resulted
on the first section of the file to include, so the same offset
can be applied to all other sections of the same doc, and its
own inclusions, if applicable.

Also, fixed a bug in section arrangement during document processing
(in the parsing phase)

Fixes #314

Signed-off-by: Xavier Coulon <[email protected]>
  • Loading branch information
xcoulon authored Nov 11, 2019
1 parent 2bb6f9d commit 4db334f
Show file tree
Hide file tree
Showing 13 changed files with 981 additions and 31 deletions.
10 changes: 9 additions & 1 deletion pkg/parser/document_preprocessing.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,15 @@ func parseElements(filename string, elements []interface{}, attrs types.Document
})
case types.Section:
for _, offset := range levelOffsets {
offset(&e)
oldLevel := e.Level
offset.apply(&e)
// replace the absolute when the first section is processed with a relative offset
// which is based on the actual level offset that resulted in the application of the absolute offset
if offset.absolute {
levelOffsets = []levelOffset{
relativeOffset(e.Level - oldLevel),
}
}
}
result = append(result, e)
default:
Expand Down
21 changes: 14 additions & 7 deletions pkg/parser/document_processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ func rearrangeSections(blocks []interface{}) (types.Document, error) {
}
// also collect footnotes
if e, ok := element.(types.FootnotesContainer); ok {
log.Debugf("collecting footnotes on element of type %T", element)
// log.Debugf("collecting footnotes on element of type %T", element)
f, fr, err := e.Footnotes()
if err != nil {
return types.Document{}, errors.Wrap(err, "unable to collect footnotes in document")
Expand All @@ -364,6 +364,11 @@ func rearrangeSections(blocks []interface{}) (types.Document, error) {
}
}
// process the remaining sections
if log.IsLevelEnabled(log.DebugLevel) {
log.Debugf("processing the remaining sections...")
spew.Dump(sections)
}

sections = pruneSections(sections, 1)
if len(sections) > 0 {
tle = append(tle, sections[0])
Expand Down Expand Up @@ -398,18 +403,20 @@ func referenceSection(e types.Section, elementRefs types.ElementReferences) {
}

func pruneSections(sections []types.Section, level int) []types.Section {
if level > 0 && level < len(sections) {
log.Debugf("pruning the section path from %d to %d level(s) deep", len(sections), level)
if len(sections) > 0 && level > 0 { // && level < len(sections) {
log.Debugf("pruning the section path with %d level(s) of deep", len(sections))
// add the last list(s) as children of their parent, in reverse order,
// because we copy the value, not the pointers
for i := len(sections) - 1; i > level-1; i-- {
cut := len(sections)
for i := len(sections) - 1; i > 0 && sections[i].Level >= level; i-- {
parentSection := &(sections[i-1])
log.Debugf("appending section at level %d (%v) to the last element of the parent section (%v)", i, sections[i].Title, parentSection.Title)
log.Debugf("appending section at depth %d (%v) to the last element of the parent section (%v)", i, sections[i].Title, parentSection.Title)
(*parentSection).AddElement(sections[i])
cut = i
}
// also, prune the pointers to the remaining sublists
sections := sections[0:level]
log.Debugf("sections list is has now %d level(s) of depth", len(sections))
sections := sections[0:cut]
log.Debugf("sections list has now %d top-level elements", len(sections))
return sections
}
return sections
Expand Down
37 changes: 30 additions & 7 deletions pkg/parser/file_inclusion.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,31 @@ func init() {
}

// levelOffset a func that applies a given offset to the sections of a child document to include in a parent doc (the caller)
type levelOffset func(*types.Section)
type levelOffset struct {
absolute bool
value int
apply func(*types.Section)
}

func relativeOffset(offset int) levelOffset {
return func(s *types.Section) {
s.Level += offset
return levelOffset{
absolute: false,
value: offset,
apply: func(s *types.Section) {
log.Debugf("applying relative offset: %d + %d on %+v", s.Level, offset, s.Title)
s.Level += offset
},
}
}

func absoluteOffset(offset int) levelOffset {
return levelOffset{
absolute: true,
value: offset,
apply: func(s *types.Section) {
log.Debugf("applying absolute offset: %d -> %d on %+v", s.Level, offset, s.Title)
s.Level = offset
},
}
}

Expand Down Expand Up @@ -68,14 +88,17 @@ func parseFileToInclude(filename string, incl types.FileInclusion, attrs types.D
return msg, errors.Wrap(err, "unable to read file to include")
}
// parse the content, and returns the corresponding elements
levelOffset := incl.Attributes.GetAsString(types.AttrLevelOffset)
if levelOffset != "" {
offset, err := strconv.Atoi(levelOffset)
l := incl.Attributes.GetAsString(types.AttrLevelOffset)
if l != "" {
offset, err := strconv.Atoi(l)
if err != nil {
return types.DraftDocument{}, errors.Wrap(err, "unable to read file to include")
}
if strings.HasPrefix(levelOffset, "+") || strings.HasPrefix(levelOffset, "-") {
if strings.HasPrefix(l, "+") || strings.HasPrefix(l, "-") {
levelOffsets = append(levelOffsets, relativeOffset(offset))
} else {
levelOffsets = []levelOffset{absoluteOffset(offset)}

}
}
// use a simpler/different grammar for non-asciidoc files.
Expand Down
Loading

0 comments on commit 4db334f

Please sign in to comment.