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 }