<commit_before>package gcss

import (
	"bytes"
	"fmt"
	"io"
	"strings"
)

// selector represents a selector of CSS.
type selector struct {
	elementBase
	name string
	sels []*selector
	decs []*declaration
}

// WriteTo writes the selector to the writer.
func (sel *selector) WriteTo(w io.Writer) (int64, error) {
	bf := new(bytes.Buffer)

	// Write the declarations.
	if len(sel.decs) > 0 {
		names, err := sel.names()

		if err != nil {
			return 0, err
		}

		if _, err := bf.WriteString(names + openBrace); err != nil {
			return 0, err
		}

		for _, dec := range sel.decs {
			if _, err := bf.WriteString(dec.property + colon + dec.value + semicolon); err != nil {
				return 0, err
			}
		}

		if _, err := bf.WriteString(closeBrace); err != nil {
			return 0, err
		}
	}

	// Write the child selectors.
	for _, childSel := range sel.sels {
		if _, err := childSel.WriteTo(bf); err != nil {
			return 0, err
		}
	}

	n, err := w.Write(bf.Bytes())

	return int64(n), err
}

// AppendChild appends a selector or declaration to the selector.
func (sel *selector) AppendChild(child element) error {
	switch child.(type) {
	case *selector:
		sel.sels = append(sel.sels, child.(*selector))
	case *declaration:
		sel.decs = append(sel.decs, child.(*declaration))
	default:
		return fmt.Errorf("invalid child's type [line: %d]", sel.ln.no)
	}

	return nil
}

// names returns the selector names.
func (sel *selector) names() (string, error) {
	if sel.parent == nil {
		names := strings.Split(sel.name, comma)

		for i, name := range names {
			names[i] = strings.TrimSpace(name)
		}

		return strings.Join(names, comma), nil
	}

	bf := new(bytes.Buffer)

	names, err := sel.parent.(*selector).names()

	if err != nil {
		return "", err
	}

	for _, parentS := range strings.Split(names, comma) {
		for _, s := range strings.Split(sel.name, comma) {
			s = strings.TrimSpace(s)

			if strings.HasPrefix(s, ampersand) {
				s = strings.TrimPrefix(s, ampersand)
			} else {
				s = space + s
			}

			if bf.Len() > 0 {
				if _, err := bf.WriteString(comma); err != nil {
					return "", err
				}
			}

			if _, err := bf.WriteString(parentS + s); err != nil {
				return "", err
			}
		}
	}

	return bf.String(), nil
}

// newSelector creates and returns a selector.
func newSelector(ln *line, parent element) *selector {
	return &selector{
		elementBase: newElementBase(ln, parent),<commit_msg>Update selector.go<commit_after>package gcss

import (
	"bytes"
	"fmt"
	"io"
	"strings"
)

// selector represents a selector of CSS.
type selector struct {
	elementBase
	name string
	sels []*selector
	decs []*declaration
}

// WriteTo writes the selector to the writer.
func (sel *selector) WriteTo(w io.Writer) (int64, error) {
	bf := new(bytes.Buffer)

	// Write the declarations.
	if len(sel.decs) > 0 {
		bf.WriteString(sel.names())
		bf.WriteString(openBrace)

		for _, dec := range sel.decs {
			bf.WriteString(dec.property)
			bf.WriteString(colon)
			bf.WriteString(dec.value)
			bf.WriteString(semicolon)
		}

		bf.WriteString(closeBrace)
	}

	// Write the child selectors.
	for _, childSel := range sel.sels {
		if _, err := childSel.WriteTo(bf); err != nil {
			return 0, err
		}
	}

	n, err := w.Write(bf.Bytes())

	return int64(n), err
}

// AppendChild appends a selector or declaration to the selector.
func (sel *selector) AppendChild(child element) error {
	switch child.(type) {
	case *selector:
		sel.sels = append(sel.sels, child.(*selector))
	case *declaration:
		sel.decs = append(sel.decs, child.(*declaration))
	default:
		return fmt.Errorf("invalid child's type [line: %d]", sel.ln.no)
	}

	return nil
}

// names returns the selector names.
func (sel *selector) names() string {
	bf := new(bytes.Buffer)

	switch sel.parent.(type) {
	case nil:
		for _, name := range strings.Split(sel.name, comma) {
			if bf.Len() > 0 {
				bf.WriteString(comma)
			}

			bf.WriteString(strings.TrimSpace(name))
		}
	case *selector:
		for _, parentS := range strings.Split(sel.parent.(*selector).names(), comma) {
			for _, s := range strings.Split(sel.name, comma) {
				if bf.Len() > 0 {
					bf.WriteString(comma)
				}

				bf.WriteString(parentS)

				s = strings.TrimSpace(s)

				if strings.HasPrefix(s, ampersand) {
					bf.WriteString(strings.TrimPrefix(s, ampersand))
				} else {
					bf.WriteString(space)
					bf.WriteString(s)
				}
			}
		}
	}

	return bf.String()
}

// newSelector creates and returns a selector.
func newSelector(ln *line, parent element) *selector {
	return &selector{
		elementBase: newElementBase(ln, parent),
{'fraction_non_alphanumeric': 0.14455445544554454, 'fraction_numerical': 0.004180418041804181, 'mean_word_length': 3.2053654024051803, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7265077', 'n_tokens_mistral': 1817, 'n_tokens_neox': 1603, 'n_words': 430}