mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
wip
This commit is contained in:
parent
52b364ec52
commit
66ab916c6b
@ -12,7 +12,6 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"golang.org/x/net/html/charset"
|
"golang.org/x/net/html/charset"
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type xmlDecoder struct {
|
type xmlDecoder struct {
|
||||||
@ -36,8 +35,8 @@ func (dec *xmlDecoder) Init(reader io.Reader) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*yaml.Node, error) {
|
func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*CandidateNode, error) {
|
||||||
yamlNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
yamlNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
|
||||||
for _, child := range nodes {
|
for _, child := range nodes {
|
||||||
yamlChild, err := dec.convertToYamlNode(child)
|
yamlChild, err := dec.convertToYamlNode(child)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -64,9 +63,9 @@ func (dec *xmlDecoder) processComment(c string) string {
|
|||||||
return replacement
|
return replacement
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
|
func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
|
||||||
log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
|
log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
|
||||||
yamlNode := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
|
yamlNode := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
|
||||||
|
|
||||||
if len(n.Data) > 0 {
|
if len(n.Data) > 0 {
|
||||||
log.Debugf("creating content node for map: %v", dec.prefs.ContentName)
|
log.Debugf("creating content node for map: %v", dec.prefs.ContentName)
|
||||||
@ -82,7 +81,7 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
|
|||||||
label := keyValuePair.K
|
label := keyValuePair.K
|
||||||
children := keyValuePair.V
|
children := keyValuePair.V
|
||||||
labelNode := createScalarNode(label, label)
|
labelNode := createScalarNode(label, label)
|
||||||
var valueNode *yaml.Node
|
var valueNode *CandidateNode
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
@ -126,26 +125,26 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
|
|||||||
return yamlNode, nil
|
return yamlNode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *xmlDecoder) createValueNodeFromData(values []string) *yaml.Node {
|
func (dec *xmlDecoder) createValueNodeFromData(values []string) *CandidateNode {
|
||||||
switch len(values) {
|
switch len(values) {
|
||||||
case 0:
|
case 0:
|
||||||
return createScalarNode(nil, "")
|
return createScalarNode(nil, "")
|
||||||
case 1:
|
case 1:
|
||||||
return createScalarNode(values[0], values[0])
|
return createScalarNode(values[0], values[0])
|
||||||
default:
|
default:
|
||||||
content := make([]*yaml.Node, 0)
|
content := make([]*CandidateNode, 0)
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
content = append(content, createScalarNode(value, value))
|
content = append(content, createScalarNode(value, value))
|
||||||
}
|
}
|
||||||
return &yaml.Node{
|
return &CandidateNode{
|
||||||
Kind: yaml.SequenceNode,
|
Kind: SequenceNode,
|
||||||
Tag: "!!seq",
|
Tag: "!!seq",
|
||||||
Content: content,
|
Content: content,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*yaml.Node, error) {
|
func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*CandidateNode, error) {
|
||||||
if len(n.Children) > 0 {
|
if len(n.Children) > 0 {
|
||||||
return dec.createMap(n)
|
return dec.createMap(n)
|
||||||
}
|
}
|
||||||
@ -190,10 +189,8 @@ func (dec *xmlDecoder) Decode() (*CandidateNode, error) {
|
|||||||
dec.finished = true
|
dec.finished = true
|
||||||
|
|
||||||
return &CandidateNode{
|
return &CandidateNode{
|
||||||
Node: &yaml.Node{
|
Kind: DocumentNode,
|
||||||
Kind: yaml.DocumentNode,
|
Content: []*CandidateNode{firstNode},
|
||||||
Content: []*yaml.Node{firstNode},
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,20 +2,18 @@ package yqlib
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Encoder interface {
|
type Encoder interface {
|
||||||
Encode(writer io.Writer, node *yaml.Node) error
|
Encode(writer io.Writer, node *CandidateNode) error
|
||||||
PrintDocumentSeparator(writer io.Writer) error
|
PrintDocumentSeparator(writer io.Writer) error
|
||||||
PrintLeadingContent(writer io.Writer, content string) error
|
PrintLeadingContent(writer io.Writer, content string) error
|
||||||
CanHandleAliases() bool
|
CanHandleAliases() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapKeysToStrings(node *yaml.Node) {
|
func mapKeysToStrings(node *CandidateNode) {
|
||||||
|
|
||||||
if node.Kind == yaml.MappingNode {
|
if node.Kind == MappingNode {
|
||||||
for index, child := range node.Content {
|
for index, child := range node.Content {
|
||||||
if index%2 == 0 { // its a map key
|
if index%2 == 0 { // its a map key
|
||||||
child.Tag = "!!str"
|
child.Tag = "!!str"
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type base64Encoder struct {
|
type base64Encoder struct {
|
||||||
@ -28,9 +26,9 @@ func (e *base64Encoder) PrintLeadingContent(writer io.Writer, content string) er
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *base64Encoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
|
func (e *base64Encoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
|
||||||
node := unwrapDoc(originalNode)
|
node := originalNode.unwrapDocument()
|
||||||
if guessTagFromCustomType(node) != "!!str" {
|
if node.guessTagFromCustomType() != "!!str" {
|
||||||
return fmt.Errorf("cannot encode %v as base64, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
return fmt.Errorf("cannot encode %v as base64, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
||||||
}
|
}
|
||||||
_, err := writer.Write([]byte(e.encoding.EncodeToString([]byte(originalNode.Value))))
|
_, err := writer.Write([]byte(e.encoding.EncodeToString([]byte(originalNode.Value))))
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type csvEncoder struct {
|
type csvEncoder struct {
|
||||||
@ -89,7 +87,7 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*CandidateNo
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, child := range content {
|
for i, child := range content {
|
||||||
if child.Kind != yaml.MappingNode {
|
if child.Kind != MappingNode {
|
||||||
return fmt.Errorf("csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[%v] is a %v", i, child.Tag)
|
return fmt.Errorf("csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[%v] is a %v", i, child.Tag)
|
||||||
}
|
}
|
||||||
row := e.createChildRow(child, headers)
|
row := e.createChildRow(child, headers)
|
||||||
@ -103,7 +101,7 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*CandidateNo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *csvEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
|
func (e *csvEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
|
||||||
if originalNode.Kind == yaml.ScalarNode {
|
if originalNode.Kind == ScalarNode {
|
||||||
return writeString(writer, originalNode.Value+"\n")
|
return writeString(writer, originalNode.Value+"\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,17 +109,17 @@ func (e *csvEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error
|
|||||||
csvWriter.Comma = e.separator
|
csvWriter.Comma = e.separator
|
||||||
|
|
||||||
// node must be a sequence
|
// node must be a sequence
|
||||||
node := unwrapDoc(originalNode)
|
node := originalNode.unwrapDocument()
|
||||||
if node.Kind != yaml.SequenceNode {
|
if node.Kind != SequenceNode {
|
||||||
return fmt.Errorf("csv encoding only works for arrays, got: %v", node.Tag)
|
return fmt.Errorf("csv encoding only works for arrays, got: %v", node.Tag)
|
||||||
} else if len(node.Content) == 0 {
|
} else if len(node.Content) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if node.Content[0].Kind == yaml.ScalarNode {
|
if node.Content[0].Kind == ScalarNode {
|
||||||
return e.encodeRow(csvWriter, node.Content)
|
return e.encodeRow(csvWriter, node.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.Content[0].Kind == yaml.MappingNode {
|
if node.Content[0].Kind == MappingNode {
|
||||||
return e.encodeObjects(csvWriter, node.Content)
|
return e.encodeObjects(csvWriter, node.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type jsonEncoder struct {
|
type jsonEncoder struct {
|
||||||
@ -38,9 +37,9 @@ func (je *jsonEncoder) PrintLeadingContent(writer io.Writer, content string) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (je *jsonEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
func (je *jsonEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||||
|
|
||||||
if node.Kind == yaml.ScalarNode && je.UnwrapScalar {
|
if node.Kind == ScalarNode && je.UnwrapScalar {
|
||||||
return writeString(writer, node.Value+"\n")
|
return writeString(writer, node.Value+"\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +57,7 @@ func (je *jsonEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
|||||||
// firstly, convert all map keys to strings
|
// firstly, convert all map keys to strings
|
||||||
mapKeysToStrings(node)
|
mapKeysToStrings(node)
|
||||||
errorDecoding := node.Decode(&dataBucket)
|
errorDecoding := node.Decode(&dataBucket)
|
||||||
|
|
||||||
if errorDecoding != nil {
|
if errorDecoding != nil {
|
||||||
return errorDecoding
|
return errorDecoding
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/magiconair/properties"
|
"github.com/magiconair/properties"
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type propertiesEncoder struct {
|
type propertiesEncoder struct {
|
||||||
@ -62,9 +61,9 @@ func (pe *propertiesEncoder) PrintLeadingContent(writer io.Writer, content strin
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe *propertiesEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
func (pe *propertiesEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||||
|
|
||||||
if node.Kind == yaml.ScalarNode {
|
if node.Kind == ScalarNode {
|
||||||
return writeString(writer, node.Value+"\n")
|
return writeString(writer, node.Value+"\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +78,7 @@ func (pe *propertiesEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node, path string, keyNode *yaml.Node) error {
|
func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *CandidateNode, path string, keyNode *CandidateNode) error {
|
||||||
|
|
||||||
comments := ""
|
comments := ""
|
||||||
if keyNode != nil {
|
if keyNode != nil {
|
||||||
@ -91,7 +90,7 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node,
|
|||||||
p.SetComments(path, strings.Split(commentsWithSpaces, "\n"))
|
p.SetComments(path, strings.Split(commentsWithSpaces, "\n"))
|
||||||
|
|
||||||
switch node.Kind {
|
switch node.Kind {
|
||||||
case yaml.ScalarNode:
|
case ScalarNode:
|
||||||
var nodeValue string
|
var nodeValue string
|
||||||
if pe.unwrapScalar || !strings.Contains(node.Value, " ") {
|
if pe.unwrapScalar || !strings.Contains(node.Value, " ") {
|
||||||
nodeValue = node.Value
|
nodeValue = node.Value
|
||||||
@ -100,13 +99,13 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node,
|
|||||||
}
|
}
|
||||||
_, _, err := p.Set(path, nodeValue)
|
_, _, err := p.Set(path, nodeValue)
|
||||||
return err
|
return err
|
||||||
case yaml.DocumentNode:
|
case DocumentNode:
|
||||||
return pe.doEncode(p, node.Content[0], path, node)
|
return pe.doEncode(p, node.Content[0], path, node)
|
||||||
case yaml.SequenceNode:
|
case SequenceNode:
|
||||||
return pe.encodeArray(p, node.Content, path)
|
return pe.encodeArray(p, node.Content, path)
|
||||||
case yaml.MappingNode:
|
case MappingNode:
|
||||||
return pe.encodeMap(p, node.Content, path)
|
return pe.encodeMap(p, node.Content, path)
|
||||||
case yaml.AliasNode:
|
case AliasNode:
|
||||||
return pe.doEncode(p, node.Alias, path, nil)
|
return pe.doEncode(p, node.Alias, path, nil)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported node %v", node.Tag)
|
return fmt.Errorf("Unsupported node %v", node.Tag)
|
||||||
@ -120,7 +119,7 @@ func (pe *propertiesEncoder) appendPath(path string, key interface{}) string {
|
|||||||
return fmt.Sprintf("%v.%v", path, key)
|
return fmt.Sprintf("%v.%v", path, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*yaml.Node, path string) error {
|
func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*CandidateNode, path string) error {
|
||||||
for index, child := range kids {
|
for index, child := range kids {
|
||||||
err := pe.doEncode(p, child, pe.appendPath(path, index), nil)
|
err := pe.doEncode(p, child, pe.appendPath(path, index), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -130,7 +129,7 @@ func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*yaml.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*yaml.Node, path string) error {
|
func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*CandidateNode, path string) error {
|
||||||
for index := 0; index < len(kids); index = index + 2 {
|
for index := 0; index < len(kids); index = index + 2 {
|
||||||
key := kids[index]
|
key := kids[index]
|
||||||
value := kids[index+1]
|
value := kids[index+1]
|
||||||
|
@ -5,8 +5,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var unsafeChars = regexp.MustCompile(`[^\w@%+=:,./-]`)
|
var unsafeChars = regexp.MustCompile(`[^\w@%+=:,./-]`)
|
||||||
@ -31,9 +29,9 @@ func (e *shEncoder) PrintLeadingContent(writer io.Writer, content string) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *shEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
|
func (e *shEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
|
||||||
node := unwrapDoc(originalNode)
|
node := originalNode.unwrapDocument()
|
||||||
if guessTagFromCustomType(node) != "!!str" {
|
if node.guessTagFromCustomType() != "!!str" {
|
||||||
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,6 @@ package yqlib
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type tomlEncoder struct {
|
type tomlEncoder struct {
|
||||||
@ -14,8 +12,8 @@ func NewTomlEncoder() Encoder {
|
|||||||
return &tomlEncoder{}
|
return &tomlEncoder{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (te *tomlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
func (te *tomlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||||
if node.Kind == yaml.ScalarNode {
|
if node.Kind == ScalarNode {
|
||||||
return writeString(writer, node.Value+"\n")
|
return writeString(writer, node.Value+"\n")
|
||||||
}
|
}
|
||||||
return fmt.Errorf("only scalars (e.g. strings, numbers, booleans) are supported for TOML output at the moment. Please use yaml output format (-oy) until the encoder has been fully implemented")
|
return fmt.Errorf("only scalars (e.g. strings, numbers, booleans) are supported for TOML output at the moment. Please use yaml output format (-oy) until the encoder has been fully implemented")
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type uriEncoder struct {
|
type uriEncoder struct {
|
||||||
@ -27,9 +25,9 @@ func (e *uriEncoder) PrintLeadingContent(writer io.Writer, content string) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *uriEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
|
func (e *uriEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
|
||||||
node := unwrapDoc(originalNode)
|
node := originalNode.unwrapDocument()
|
||||||
if guessTagFromCustomType(node) != "!!str" {
|
if node.guessTagFromCustomType() != "!!str" {
|
||||||
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
||||||
}
|
}
|
||||||
_, err := writer.Write([]byte(url.QueryEscape(originalNode.Value)))
|
_, err := writer.Write([]byte(url.QueryEscape(originalNode.Value)))
|
||||||
|
@ -8,8 +8,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type xmlEncoder struct {
|
type xmlEncoder struct {
|
||||||
@ -41,14 +39,14 @@ func (e *xmlEncoder) PrintLeadingContent(writer io.Writer, content string) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
func (e *xmlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||||
encoder := xml.NewEncoder(writer)
|
encoder := xml.NewEncoder(writer)
|
||||||
// hack so we can manually add newlines to procInst and directives
|
// hack so we can manually add newlines to procInst and directives
|
||||||
e.writer = writer
|
e.writer = writer
|
||||||
encoder.Indent("", e.indentString)
|
encoder.Indent("", e.indentString)
|
||||||
var newLine xml.CharData = []byte("\n")
|
var newLine xml.CharData = []byte("\n")
|
||||||
|
|
||||||
mapNode := unwrapDoc(node)
|
mapNode := node.unwrapDocument()
|
||||||
if mapNode.Tag == "!!map" {
|
if mapNode.Tag == "!!map" {
|
||||||
// make sure <?xml .. ?> processing instructions are encoded first
|
// make sure <?xml .. ?> processing instructions are encoded first
|
||||||
for i := 0; i < len(mapNode.Content); i += 2 {
|
for i := 0; i < len(mapNode.Content); i += 2 {
|
||||||
@ -82,18 +80,18 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch node.Kind {
|
switch node.Kind {
|
||||||
case yaml.MappingNode:
|
case MappingNode:
|
||||||
err := e.encodeTopLevelMap(encoder, node)
|
err := e.encodeTopLevelMap(encoder, node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case yaml.DocumentNode:
|
case DocumentNode:
|
||||||
err := e.encodeComment(encoder, headAndLineComment(node))
|
err := e.encodeComment(encoder, headAndLineComment(node))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
unwrappedNode := unwrapDoc(node)
|
unwrappedNode := node.unwrapDocument()
|
||||||
if unwrappedNode.Kind != yaml.MappingNode {
|
if unwrappedNode.Kind != MappingNode {
|
||||||
return fmt.Errorf("cannot encode %v to XML - only maps can be encoded", unwrappedNode.Tag)
|
return fmt.Errorf("cannot encode %v to XML - only maps can be encoded", unwrappedNode.Tag)
|
||||||
}
|
}
|
||||||
err = e.encodeTopLevelMap(encoder, unwrappedNode)
|
err = e.encodeTopLevelMap(encoder, unwrappedNode)
|
||||||
@ -104,7 +102,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case yaml.ScalarNode:
|
case ScalarNode:
|
||||||
var charData xml.CharData = []byte(node.Value)
|
var charData xml.CharData = []byte(node.Value)
|
||||||
err := encoder.EncodeToken(charData)
|
err := encoder.EncodeToken(charData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -119,7 +117,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) error {
|
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *CandidateNode) error {
|
||||||
err := e.encodeComment(encoder, headAndLineComment(node))
|
err := e.encodeComment(encoder, headAndLineComment(node))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -178,7 +176,7 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) er
|
|||||||
return e.encodeComment(encoder, footComment(node))
|
return e.encodeComment(encoder, footComment(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
|
func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
||||||
err := encoder.EncodeToken(start)
|
err := encoder.EncodeToken(start)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -186,7 +184,7 @@ func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yaml.Node, start xm
|
|||||||
return e.encodeComment(encoder, headComment(node))
|
return e.encodeComment(encoder, headComment(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
|
func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
||||||
err := encoder.EncodeToken(start.End())
|
err := encoder.EncodeToken(start.End())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -194,13 +192,13 @@ func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yaml.Node, start xml.
|
|||||||
return e.encodeComment(encoder, footComment(node))
|
return e.encodeComment(encoder, footComment(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
|
func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
||||||
switch node.Kind {
|
switch node.Kind {
|
||||||
case yaml.MappingNode:
|
case MappingNode:
|
||||||
return e.encodeMap(encoder, node, start)
|
return e.encodeMap(encoder, node, start)
|
||||||
case yaml.SequenceNode:
|
case SequenceNode:
|
||||||
return e.encodeArray(encoder, node, start)
|
return e.encodeArray(encoder, node, start)
|
||||||
case yaml.ScalarNode:
|
case ScalarNode:
|
||||||
err := e.encodeStart(encoder, node, start)
|
err := e.encodeStart(encoder, node, start)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -258,7 +256,7 @@ func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
|
func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
||||||
|
|
||||||
if err := e.encodeComment(encoder, headAndLineComment(node)); err != nil {
|
if err := e.encodeComment(encoder, headAndLineComment(node)); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -280,7 +278,7 @@ func (e *xmlEncoder) isAttribute(name string) bool {
|
|||||||
!strings.HasPrefix(name, e.prefs.ProcInstPrefix)
|
!strings.HasPrefix(name, e.prefs.ProcInstPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
|
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
||||||
log.Debug("its a map")
|
log.Debug("its a map")
|
||||||
|
|
||||||
//first find all the attributes and put them on the start token
|
//first find all the attributes and put them on the start token
|
||||||
@ -289,7 +287,7 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.
|
|||||||
value := node.Content[i+1]
|
value := node.Content[i+1]
|
||||||
|
|
||||||
if e.isAttribute(key.Value) {
|
if e.isAttribute(key.Value) {
|
||||||
if value.Kind == yaml.ScalarNode {
|
if value.Kind == ScalarNode {
|
||||||
attributeName := strings.Replace(key.Value, e.prefs.AttributePrefix, "", 1)
|
attributeName := strings.Replace(key.Value, e.prefs.AttributePrefix, "", 1)
|
||||||
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: attributeName}, Value: value.Value})
|
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: attributeName}, Value: value.Value})
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,9 +73,9 @@ func (ye *yamlEncoder) PrintLeadingContent(writer io.Writer, content string) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ye *yamlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
|
func (ye *yamlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||||
|
|
||||||
if node.Kind == yaml.ScalarNode && ye.prefs.UnwrapScalar {
|
if node.Kind == ScalarNode && ye.prefs.UnwrapScalar {
|
||||||
return writeString(writer, node.Value+"\n")
|
return writeString(writer, node.Value+"\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ type Operation struct {
|
|||||||
UpdateAssign bool // used for assign ops, when true it means we evaluate the rhs given the lhs
|
UpdateAssign bool // used for assign ops, when true it means we evaluate the rhs given the lhs
|
||||||
}
|
}
|
||||||
|
|
||||||
func recurseNodeArrayEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
|
func recurseNodeArrayEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
|
||||||
if len(lhs.Content) != len(rhs.Content) {
|
if len(lhs.Content) != len(rhs.Content) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -283,17 +283,17 @@ func parseSnippet(value string) (*CandidateNode, error) {
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func recursiveNodeEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
|
func recursiveNodeEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
|
||||||
if lhs.Kind != rhs.Kind {
|
if lhs.Kind != rhs.Kind {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if lhs.Kind == yaml.ScalarNode {
|
if lhs.Kind == ScalarNode {
|
||||||
//process custom tags of scalar nodes.
|
//process custom tags of scalar nodes.
|
||||||
//dont worry about matching tags of maps or arrays.
|
//dont worry about matching tags of maps or arrays.
|
||||||
|
|
||||||
lhsTag := guessTagFromCustomType(lhs)
|
lhsTag := lhs.guessTagFromCustomType()
|
||||||
rhsTag := guessTagFromCustomType(rhs)
|
rhsTag := rhs.guessTagFromCustomType()
|
||||||
|
|
||||||
if lhsTag != rhsTag {
|
if lhsTag != rhsTag {
|
||||||
return false
|
return false
|
||||||
@ -303,11 +303,11 @@ func recursiveNodeEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
|
|||||||
if lhs.Tag == "!!null" {
|
if lhs.Tag == "!!null" {
|
||||||
return true
|
return true
|
||||||
|
|
||||||
} else if lhs.Kind == yaml.ScalarNode {
|
} else if lhs.Kind == ScalarNode {
|
||||||
return lhs.Value == rhs.Value
|
return lhs.Value == rhs.Value
|
||||||
} else if lhs.Kind == yaml.SequenceNode {
|
} else if lhs.Kind == SequenceNode {
|
||||||
return recurseNodeArrayEqual(lhs, rhs)
|
return recurseNodeArrayEqual(lhs, rhs)
|
||||||
} else if lhs.Kind == yaml.MappingNode {
|
} else if lhs.Kind == MappingNode {
|
||||||
return recurseNodeObjectEqual(lhs, rhs)
|
return recurseNodeObjectEqual(lhs, rhs)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -382,19 +382,19 @@ func parseInt(numberString string) (int, error) {
|
|||||||
return int(parsed), err
|
return int(parsed), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func headAndLineComment(node *yaml.Node) string {
|
func headAndLineComment(node *CandidateNode) string {
|
||||||
return headComment(node) + lineComment(node)
|
return headComment(node) + lineComment(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
func headComment(node *yaml.Node) string {
|
func headComment(node *CandidateNode) string {
|
||||||
return strings.Replace(node.HeadComment, "#", "", 1)
|
return strings.Replace(node.HeadComment, "#", "", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func lineComment(node *yaml.Node) string {
|
func lineComment(node *CandidateNode) string {
|
||||||
return strings.Replace(node.LineComment, "#", "", 1)
|
return strings.Replace(node.LineComment, "#", "", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func footComment(node *yaml.Node) string {
|
func footComment(node *CandidateNode) string {
|
||||||
return strings.Replace(node.FootComment, "#", "", 1)
|
return strings.Replace(node.FootComment, "#", "", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,8 +115,9 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
|
|||||||
comment = startCommentCharaterRegExp.ReplaceAllString(comment, "")
|
comment = startCommentCharaterRegExp.ReplaceAllString(comment, "")
|
||||||
comment = subsequentCommentCharaterRegExp.ReplaceAllString(comment, "\n")
|
comment = subsequentCommentCharaterRegExp.ReplaceAllString(comment, "\n")
|
||||||
|
|
||||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: comment, Tag: "!!str"}
|
result := candidate.CreateReplacement()
|
||||||
result := candidate.CreateReplacement(node)
|
result.Kind = ScalarNode
|
||||||
|
result.Tag = "!!str"
|
||||||
result.LeadingContent = "" // don't include the leading yaml content when retrieving a comment
|
result.LeadingContent = "" // don't include the leading yaml content when retrieving a comment
|
||||||
results.PushBack(result)
|
results.PushBack(result)
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,6 @@ package yqlib
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type compareTypePref struct {
|
type compareTypePref struct {
|
||||||
@ -32,27 +30,27 @@ func compare(prefs compareTypePref) func(d *dataTreeNavigator, context Context,
|
|||||||
return createBooleanCandidate(lhs, false), nil
|
return createBooleanCandidate(lhs, false), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs.Node = unwrapDoc(lhs.Node)
|
lhsU := lhs.unwrapDocument()
|
||||||
rhs.Node = unwrapDoc(rhs.Node)
|
rhsU := rhs.unwrapDocument()
|
||||||
|
|
||||||
switch lhs.Node.Kind {
|
switch lhsU.Kind {
|
||||||
case yaml.MappingNode:
|
case MappingNode:
|
||||||
return nil, fmt.Errorf("maps not yet supported for comparison")
|
return nil, fmt.Errorf("maps not yet supported for comparison")
|
||||||
case yaml.SequenceNode:
|
case SequenceNode:
|
||||||
return nil, fmt.Errorf("arrays not yet supported for comparison")
|
return nil, fmt.Errorf("arrays not yet supported for comparison")
|
||||||
default:
|
default:
|
||||||
if rhs.Node.Kind != yaml.ScalarNode {
|
if rhsU.Kind != ScalarNode {
|
||||||
return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhs.Node.Tag)
|
return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhsU.Tag, rhs.Path, lhsU.Tag)
|
||||||
}
|
}
|
||||||
target := lhs.CreateReplacement(&yaml.Node{})
|
target := lhs.CreateReplacement()
|
||||||
boolV, err := compareScalars(context, prefs, lhs.Node, rhs.Node)
|
boolV, err := compareScalars(context, prefs, lhsU, rhsU)
|
||||||
|
|
||||||
return createBooleanCandidate(target, boolV), err
|
return createBooleanCandidate(target, boolV), err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareDateTime(layout string, prefs compareTypePref, lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
|
func compareDateTime(layout string, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
|
||||||
lhsTime, err := parseDateTime(layout, lhs.Value)
|
lhsTime, err := parseDateTime(layout, lhs.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -73,9 +71,9 @@ func compareDateTime(layout string, prefs compareTypePref, lhs *yaml.Node, rhs *
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareScalars(context Context, prefs compareTypePref, lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
|
func compareScalars(context Context, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
|
||||||
lhsTag := guessTagFromCustomType(lhs)
|
lhsTag := lhs.guessTagFromCustomType()
|
||||||
rhsTag := guessTagFromCustomType(rhs)
|
rhsTag := rhs.guessTagFromCustomType()
|
||||||
|
|
||||||
isDateTime := lhs.Tag == "!!timestamp"
|
isDateTime := lhs.Tag == "!!timestamp"
|
||||||
// if the lhs is a string, it might be a timestamp in a custom format.
|
// if the lhs is a string, it might be a timestamp in a custom format.
|
||||||
|
Loading…
Reference in New Issue
Block a user