Skip to content

Commit

Permalink
New normalizeAnchors option for disco-balling
Browse files Browse the repository at this point in the history
  • Loading branch information
hasty committed Nov 6, 2024
1 parent b76de4c commit 8ef6d02
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 39 deletions.
2 changes: 2 additions & 0 deletions cmd/disco/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func init() {
Command.Flags().Bool("addSpaceAfterPunctuation", true, "add missing space after punctuation")
Command.Flags().Bool("removeExtraSpaces", true, "remove extraneous spaces")
Command.Flags().Bool("disambiguateConformanceChoice", false, "ensure conformance choices are only used once per document")
Command.Flags().Bool("normalizeAnchors", false, "rewrite anchors and references without labels")
Command.Flags().Int("wrap", 0, "the maximum length of a line")
}

Expand All @@ -72,6 +73,7 @@ func getDiscoOptions(cmd *cobra.Command) []disco.Option {
"removeExtraSpaces": disco.RemoveExtraSpaces,
"normalizeFeatureNames": disco.NormalizeFeatureNames,
"disambiguateConformanceChoice": disco.DisambiguateConformanceChoice,
"normalizeAnchors": disco.NormalizeAnchors,
}
var discoOptions []disco.Option
for name, o := range optionFuncs {
Expand Down
22 changes: 16 additions & 6 deletions disco/anchors.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ type anchorGroup struct {
}

type AnchorNormalizer struct {
discoOptions []Option
options options
}

func newAnchorNormalizer(discoOptions []Option) AnchorNormalizer {
return AnchorNormalizer{discoOptions: discoOptions}
an := AnchorNormalizer{}
for _, o := range discoOptions {
o(&an.options)
}
return an
}

func (r AnchorNormalizer) Name() string {
Expand Down Expand Up @@ -115,7 +119,7 @@ func (p AnchorNormalizer) Process(cxt context.Context, inputs []*pipeline.Data[*
}
for _, input := range inputs {
doc := input.Content
rewriteCrossReferences(doc)
p.rewriteCrossReferences(doc)
delete(extraDocs, doc)
outputs = append(outputs, pipeline.NewData[render.InputDocument](input.Path, input.Content))
}
Expand All @@ -125,7 +129,7 @@ func (p AnchorNormalizer) Process(cxt context.Context, inputs []*pipeline.Data[*
return
}

func (AnchorNormalizer) normalizeAnchors(inputs []*pipeline.Data[*spec.Doc]) (anchorGroups map[*spec.DocGroup]*anchorGroup, err error) {
func (an AnchorNormalizer) normalizeAnchors(inputs []*pipeline.Data[*spec.Doc]) (anchorGroups map[*spec.DocGroup]*anchorGroup, err error) {
anchorGroups = make(map[*spec.DocGroup]*anchorGroup)
unaffiliatedDocs := spec.NewDocGroup("")
for _, input := range inputs {
Expand Down Expand Up @@ -155,7 +159,7 @@ func (AnchorNormalizer) normalizeAnchors(inputs []*pipeline.Data[*spec.Doc]) (an
for _, as := range da {
for _, a := range as {
id := a.ID
newID := normalizeAnchor(a)
newID := an.normalizeAnchor(a)
if id == newID {
ag.updatedAnchors[id] = append(ag.updatedAnchors[id], a)
continue
Expand All @@ -174,7 +178,7 @@ func (AnchorNormalizer) normalizeAnchors(inputs []*pipeline.Data[*spec.Doc]) (an
return
}

func normalizeAnchor(info *spec.Anchor) (id string) {
func (an AnchorNormalizer) normalizeAnchor(info *spec.Anchor) (id string) {
id = info.ID
if skipAnchor(info) {
return
Expand Down Expand Up @@ -204,6 +208,12 @@ func normalizeAnchor(info *spec.Anchor) (id string) {
if labelText(info.LabelElements) == name {
info.LabelElements = nil
}
if an.options.normalizeAnchors {
_, isSection := info.Element.(*asciidoc.Section)
if isSection {
info.LabelElements = nil
}
}
return
}

Expand Down
2 changes: 1 addition & 1 deletion disco/baller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (r Baller) Type() pipeline.ProcessorType {
func (r Baller) Process(cxt context.Context, input *pipeline.Data[*spec.Doc], index int32, total int32) (outputs []*pipeline.Data[*spec.Doc], extras []*pipeline.Data[*spec.Doc], err error) {
b := NewBall(input.Content)
for _, option := range r.discoOptions {
option(b)
option(&b.options)
}
err = b.disco(cxt)
if err != nil {
Expand Down
70 changes: 39 additions & 31 deletions disco/option.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package disco

type Option func(b *Ball)
type Option func(options *options)

type options struct {
linkIndexTables bool
Expand All @@ -18,6 +18,7 @@ type options struct {
removeExtraSpaces bool
normalizeFeatureNames bool
disambiguateConformanceChoice bool
normalizeAnchors bool
}

var defaultOptions = options{
Expand All @@ -36,94 +37,101 @@ var defaultOptions = options{
removeExtraSpaces: true,
normalizeFeatureNames: true,
disambiguateConformanceChoice: false,
normalizeAnchors: false,
}

func LinkIndexTables(link bool) Option {
return func(b *Ball) {
b.options.linkIndexTables = link
return func(options *options) {
options.linkIndexTables = link
}
}

func AddMissingColumns(add bool) Option {
return func(b *Ball) {
b.options.addMissingColumns = add
return func(options *options) {
options.addMissingColumns = add
}
}

func ReorderColumns(reorder bool) Option {
return func(b *Ball) {
b.options.reorderColumns = reorder
return func(options *options) {
options.reorderColumns = reorder
}
}

func RenameTableHeaders(rename bool) Option {
return func(b *Ball) {
b.options.renameTableHeaders = rename
return func(options *options) {
options.renameTableHeaders = rename
}
}

func FormatAccess(format bool) Option {
return func(b *Ball) {
b.options.formatAccess = format
return func(options *options) {
options.formatAccess = format
}
}

func PromoteDataTypes(promote bool) Option {
return func(b *Ball) {
b.options.promoteDataTypes = promote
return func(options *options) {
options.promoteDataTypes = promote
}
}

func ReorderSections(reorder bool) Option {
return func(b *Ball) {
b.options.reorderSections = reorder
return func(options *options) {
options.reorderSections = reorder
}
}

func FixCommandDirection(add bool) Option {
return func(b *Ball) {
b.options.fixCommandDirection = add
return func(options *options) {
options.fixCommandDirection = add
}
}

func AppendSubsectionTypes(add bool) Option {
return func(b *Ball) {
b.options.appendSubsectionTypes = add
return func(options *options) {
options.appendSubsectionTypes = add
}
}

func UppercaseHex(add bool) Option {
return func(b *Ball) {
b.options.uppercaseHex = add
return func(options *options) {
options.uppercaseHex = add
}
}

func AddSpaceAfterPunctuation(add bool) Option {
return func(b *Ball) {
b.options.addSpaceAfterPunctuation = add
return func(options *options) {
options.addSpaceAfterPunctuation = add
}
}

func RemoveExtraSpaces(add bool) Option {
return func(b *Ball) {
b.options.removeExtraSpaces = add
return func(options *options) {
options.removeExtraSpaces = add
}
}

func NormalizeTableOptions(add bool) Option {
return func(b *Ball) {
b.options.normalizeTableOptions = add
return func(options *options) {
options.normalizeTableOptions = add
}
}

func NormalizeFeatureNames(add bool) Option {
return func(b *Ball) {
b.options.normalizeFeatureNames = add
return func(options *options) {
options.normalizeFeatureNames = add
}
}

func DisambiguateConformanceChoice(add bool) Option {
return func(b *Ball) {
b.options.disambiguateConformanceChoice = add
return func(options *options) {
options.disambiguateConformanceChoice = add
}
}

func NormalizeAnchors(add bool) Option {
return func(options *options) {
options.normalizeAnchors = add
}
}
49 changes: 48 additions & 1 deletion disco/references.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package disco

import (
"log/slog"
"strings"

"github.com/project-chip/alchemy/asciidoc"
"github.com/project-chip/alchemy/internal/log"
"github.com/project-chip/alchemy/internal/parse"
"github.com/project-chip/alchemy/internal/text"
"github.com/project-chip/alchemy/matter/spec"
)

func rewriteCrossReferences(doc *spec.Doc) {
func (p AnchorNormalizer) rewriteCrossReferences(doc *spec.Doc) {
for id, xrefs := range doc.CrossReferences() {
anchor := doc.FindAnchor(id)
if anchor == nil {
Expand Down Expand Up @@ -37,6 +41,12 @@ func rewriteCrossReferences(doc *spec.Doc) {
continue
}
anchorLabel := labelText(anchor.LabelElements)
if anchorLabel == "" {
section, isSection := anchor.Element.(*asciidoc.Section)
if isSection {
anchorLabel = section.Name()
}
}
// We're going to be modifying the underlying array, so we need to make a copy of the slice
xrefsToChange := make([]*spec.CrossReference, len(xrefs))
copy(xrefsToChange, xrefs)
Expand All @@ -53,6 +63,43 @@ func rewriteCrossReferences(doc *spec.Doc) {
}
}
}
if p.options.normalizeAnchors {
parse.Traverse(nil, doc.Base.Elements(), func(icr *asciidoc.CrossReference, parent parse.HasElements, index int) parse.SearchShould {
if len(icr.Set) > 0 {
return parse.SearchShouldContinue
}
anchor := doc.FindAnchor(icr.ID)
if anchor == nil {
return parse.SearchShouldContinue
}
section, isSection := anchor.Element.(*asciidoc.Section)
if !isSection {
return parse.SearchShouldContinue
}
sectionName := section.Name()
elements := parent.Elements()
if index >= len(elements)-1 {
return parse.SearchShouldContinue
}
nextElement := elements[index+1]
nextString, ok := nextElement.(*asciidoc.String)
if !ok {
return parse.SearchShouldContinue
}
lastSpaceIndex := strings.LastIndex(sectionName, " ")
if lastSpaceIndex == -1 {
return parse.SearchShouldContinue
}
suffix := sectionName[lastSpaceIndex:]
if !text.HasCaseInsensitivePrefix(nextString.Value, suffix) {
return parse.SearchShouldContinue
}
replacement := text.TrimCaseInsensitivePrefix(nextString.Value, suffix)
nextString.Value = replacement
return parse.SearchShouldContinue
})

}
}

func findRefSection(parent any) *spec.Section {
Expand Down

0 comments on commit 8ef6d02

Please sign in to comment.