<commit_before>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
Package pango provides a type-safe way to construct pango markup.
Using nested Span and Text nodes, pango formatted output can be easily constructed
with compile-time validation of nesting and automatic escaping.

For example, to construct pango markup for:
 <span color="#ff0000">Red <span weight="bold">Bold Text</span></span>

the go code would be:
 pango.New(
   pango.Text("Red "),
   pango.Text("Bold Text").Bold()).
 Color(colors.Hex("#ff0000"))

or:
 pango.Text("Red ").
   Color(colors.Hex("#ff0000")).
   Append(pango.Text("Bold Text").Bold())
*/
package pango

import (
	"bytes"
	"fmt"
	"html"

	"github.com/soumya92/barista/bar"
)

type nodeType int

const (
	// ntElement is an element node with attributes and/or children.
	ntElement nodeType = iota
	// ntText is a text node with no markup or children.
	ntText
	// ntSizer is a <big> or <small> tag. It has no attributes,
	// and must be the only child of its parent.
	// It exists to support calls like:
	//   Text("x").Size(10.0).Smaller().Smaller().AppendText("y")
	// which would otherwise produce:
	//   <span size="smaller">xy</span>
	// but should actually produce:
	//   <span size="10240"><small><small>xy</small></small></span>
	ntSizer
)

// Node represents a node in a pango "document".
type Node struct {
	nodeType nodeType
	// For element nodes, this holds the tag name ("" = 'markup' node).
	// For text nodes, this holds the text content.
	content    string
	children   []*Node
	attributes map[string]string
}

// Append adds one or more nodes as children of the current node.
// The new nodes will inherit styles by virtue of being descendants,
// to insert them *adjacent* to the current node, use .Parent().Append(...).
func (n *Node) Append(nodes ...*Node) *Node {
	var insertPoint = n
	for len(insertPoint.children) == 1 &&
		insertPoint.children[0].nodeType == ntSizer {
		insertPoint = insertPoint.children[0]
	}
	for _, node := range nodes {
		if node.nodeType == ntElement && node.content == "" {
			// Collapse empty element nodes when appending, to reduce nesting.
			insertPoint.children = append(insertPoint.children, node.children...)
		} else {
			insertPoint.children = append(insertPoint.children, node)
		}
	}
	return n
}
<commit_msg>Update comment to reflect the Parent() -> Concat() change<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
Package pango provides a type-safe way to construct pango markup.
Using nested Span and Text nodes, pango formatted output can be easily constructed
with compile-time validation of nesting and automatic escaping.

For example, to construct pango markup for:
 <span color="#ff0000">Red <span weight="bold">Bold Text</span></span>

the go code would be:
 pango.New(
   pango.Text("Red "),
   pango.Text("Bold Text").Bold()).
 Color(colors.Hex("#ff0000"))

or:
 pango.Text("Red ").
   Color(colors.Hex("#ff0000")).
   Append(pango.Text("Bold Text").Bold())
*/
package pango

import (
	"bytes"
	"fmt"
	"html"

	"github.com/soumya92/barista/bar"
)

type nodeType int

const (
	// ntElement is an element node with attributes and/or children.
	ntElement nodeType = iota
	// ntText is a text node with no markup or children.
	ntText
	// ntSizer is a <big> or <small> tag. It has no attributes,
	// and must be the only child of its parent.
	// It exists to support calls like:
	//   Text("x").Size(10.0).Smaller().Smaller().AppendText("y")
	// which would otherwise produce:
	//   <span size="smaller">xy</span>
	// but should actually produce:
	//   <span size="10240"><small><small>xy</small></small></span>
	ntSizer
)

// Node represents a node in a pango "document".
type Node struct {
	nodeType nodeType
	// For element nodes, this holds the tag name ("" = 'markup' node).
	// For text nodes, this holds the text content.
	content    string
	children   []*Node
	attributes map[string]string
}

// Append adds one or more nodes as children of the current node.
// The new nodes will inherit styles by virtue of being descendants,
// to insert them *adjacent* to the current node, use .Concat(...).
func (n *Node) Append(nodes ...*Node) *Node {
	var insertPoint = n
	for len(insertPoint.children) == 1 &&
		insertPoint.children[0].nodeType == ntSizer {
		insertPoint = insertPoint.children[0]
	}
	for _, node := range nodes {
		if node.nodeType == ntElement && node.content == "" {
			// Collapse empty element nodes when appending, to reduce nesting.
			insertPoint.children = append(insertPoint.children, node.children...)
		} else {
			insertPoint.children = append(insertPoint.children, node)
		}
	}
	return n
}

{'fraction_non_alphanumeric': 0.1226596675415573, 'fraction_numerical': 0.011548556430446194, 'mean_word_length': 3.576461168935148, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '2075966', 'n_tokens_mistral': 1783, 'n_tokens_neox': 1698, 'n_words': 661}