@@ -18,23 +18,45 @@ import (
1818)
1919
2020type BuildOptions struct {
21- Indent int
22- Tabs bool
23- Header bool
24- ExternalBuilds []Builder // handle specific directives
21+ Indent int
22+ Tabs bool
23+ Header bool
24+ Builders []RegisterBuilder // handle specific directives
25+ extBuilders map [string ]Builder
26+ }
27+
28+ // RegisterBuilder is an option that can be used to add a builder to build NGINX configuration for custom directives.
29+ type RegisterBuilder interface {
30+ applyBuildOptions (options * BuildOptions )
31+ }
32+
33+ type registerBuilder struct {
34+ b Builder
35+ directives []string
36+ }
37+
38+ func (rb registerBuilder ) applyBuildOptions (o * BuildOptions ) {
39+ if o .extBuilders == nil {
40+ o .extBuilders = make (map [string ]Builder )
41+ }
42+
43+ for _ , s := range rb .directives {
44+ o .extBuilders [s ] = rb .b
45+ }
46+ }
47+
48+ // BuildWithBuilder registers a builder to build the NGINX configuration for the given directives.
49+ func BuildWithBuilder (b Builder , directives ... string ) RegisterBuilder {
50+ return registerBuilder {b : b , directives : directives }
2551}
2652
2753// Builder is the interface implemented by types that can render a Directive
2854// as it appears in NGINX configuration files.
2955//
30- // RegisterBuilder returns the names of the directives for which the builder can
31- // build NGINX configuration.
32- //
3356// Build writes the strings that represent the Directive and it's Block to the
3457// io.StringWriter returning any error encountered that caused the write to stop
3558// early. Build must not modify the Directive.
3659type Builder interface {
37- RegisterBuilder () []string
3860 Build (stmt * Directive ) string
3961}
4062
@@ -63,6 +85,10 @@ func BuildFiles(payload Payload, dir string, options *BuildOptions) error {
6385 dir = cwd
6486 }
6587
88+ for _ , o := range options .Builders {
89+ o .applyBuildOptions (options )
90+ }
91+
6692 for _ , config := range payload .Config {
6793 path := config .File
6894 if ! filepath .IsAbs (path ) {
@@ -111,6 +137,12 @@ func Build(w io.Writer, config Config, options *BuildOptions) error {
111137 }
112138 }
113139
140+ if options .extBuilders == nil { // might be set if using BuildFiles
141+ for _ , o := range options .Builders {
142+ o .applyBuildOptions (options )
143+ }
144+ }
145+
114146 body := strings.Builder {}
115147 buildBlock (& body , nil , config .Parsed , 0 , 0 , options )
116148
@@ -123,7 +155,7 @@ func Build(w io.Writer, config Config, options *BuildOptions) error {
123155 return err
124156}
125157
126- //nolint:funlen, gocognit
158+ //nolint:gocognit
127159func buildBlock (sb io.StringWriter , parent * Directive , block Directives , depth int , lastLine int , options * BuildOptions ) {
128160 for i , stmt := range block {
129161 // if the this statement is a comment on the same line as the preview, do not emit EOL for this stmt
@@ -147,18 +179,10 @@ func buildBlock(sb io.StringWriter, parent *Directive, block Directives, depth i
147179 directive := Enquote (stmt .Directive )
148180 _ , _ = sb .WriteString (directive )
149181
150- if options .ExternalBuilds != nil {
151- extDirectivesMap := make (map [string ]Builder )
152- for _ , ext := range options .ExternalBuilds {
153- directives := ext .RegisterBuilder ()
154- for _ , d := range directives {
155- extDirectivesMap [d ] = ext
156- }
157-
158- if ext , ok := extDirectivesMap [directive ]; ok {
159- _ , _ = sb .WriteString (" " ) // space between directives and arguments
160- _ , _ = sb .WriteString (ext .Build (stmt ))
161- }
182+ if options .extBuilders != nil {
183+ if ext , ok := options .extBuilders [directive ]; ok {
184+ _ , _ = sb .WriteString (" " ) // space between directives and arguments
185+ _ , _ = sb .WriteString (ext .Build (stmt ))
162186 }
163187 } else {
164188 // special handling for if statements
0 commit comments