github.com/google/yamlfmt@v0.12.2-0.20240514121411-7f77800e2681/formatters/basic/formatter.go (about)

     1  // Copyright 2022 Google LLC
     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  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package basic
    16  
    17  import (
    18  	"bytes"
    19  	"errors"
    20  	"io"
    21  
    22  	"github.com/braydonk/yaml"
    23  	"github.com/google/yamlfmt"
    24  	"github.com/mitchellh/mapstructure"
    25  )
    26  
    27  const BasicFormatterType string = "basic"
    28  
    29  type BasicFormatter struct {
    30  	Config       *Config
    31  	Features     yamlfmt.FeatureList
    32  	YAMLFeatures YAMLFeatureList
    33  }
    34  
    35  // yamlfmt.Formatter interface
    36  
    37  func (f *BasicFormatter) Type() string {
    38  	return BasicFormatterType
    39  }
    40  
    41  func (f *BasicFormatter) Format(input []byte) ([]byte, error) {
    42  	// Run all features with BeforeActions
    43  	yamlContent, err := f.Features.ApplyFeatures(input, yamlfmt.FeatureApplyBefore)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	// Format the yaml content
    49  	reader := bytes.NewReader(yamlContent)
    50  	decoder := f.getNewDecoder(reader)
    51  	documents := []yaml.Node{}
    52  	for {
    53  		var docNode yaml.Node
    54  		err := decoder.Decode(&docNode)
    55  		if err != nil {
    56  			if errors.Is(err, io.EOF) {
    57  				break
    58  			}
    59  			return nil, err
    60  		}
    61  		documents = append(documents, docNode)
    62  	}
    63  
    64  	// Run all YAML features.
    65  	for _, d := range documents {
    66  		if err := f.YAMLFeatures.ApplyFeatures(d); err != nil {
    67  			return nil, err
    68  		}
    69  	}
    70  
    71  	var b bytes.Buffer
    72  	e := f.getNewEncoder(&b)
    73  	for _, doc := range documents {
    74  		err := e.Encode(&doc)
    75  		if err != nil {
    76  			return nil, err
    77  		}
    78  	}
    79  
    80  	// Run all features with AfterActions
    81  	resultYaml, err := f.Features.ApplyFeatures(b.Bytes(), yamlfmt.FeatureApplyAfter)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	return resultYaml, nil
    87  }
    88  
    89  func (f *BasicFormatter) getNewDecoder(reader io.Reader) *yaml.Decoder {
    90  	d := yaml.NewDecoder(reader)
    91  	if f.Config.ScanFoldedAsLiteral {
    92  		d.SetScanBlockScalarAsLiteral(true)
    93  	}
    94  	return d
    95  }
    96  
    97  func (f *BasicFormatter) getNewEncoder(buf *bytes.Buffer) *yaml.Encoder {
    98  	e := yaml.NewEncoder(buf)
    99  	e.SetIndent(f.Config.Indent)
   100  
   101  	if f.Config.LineLength > 0 {
   102  		e.SetWidth(f.Config.LineLength)
   103  	}
   104  
   105  	if f.Config.LineEnding == yamlfmt.LineBreakStyleCRLF {
   106  		e.SetLineBreakStyle(yaml.LineBreakStyleCRLF)
   107  	}
   108  
   109  	e.SetExplicitDocumentStart(f.Config.IncludeDocumentStart)
   110  	e.SetAssumeBlockAsLiteral(f.Config.ScanFoldedAsLiteral)
   111  	e.SetIndentlessBlockSequence(f.Config.IndentlessArrays)
   112  	e.SetDropMergeTag(f.Config.DropMergeTag)
   113  	e.SetPadLineComments(f.Config.PadLineComments)
   114  
   115  	return e
   116  }
   117  
   118  func (f *BasicFormatter) ConfigMap() (map[string]any, error) {
   119  	configMap := map[string]any{}
   120  	err := mapstructure.Decode(f.Config, &configMap)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	configMap["type"] = BasicFormatterType
   125  	return configMap, err
   126  }