<commit_before>package template

import (
	"bytes"
	"errors"
	"fmt"
	"html/template"
	"reflect"
	"strings"

	"honnef.co/go/js/dom"
)

var (
	// ErrTemplateNotFound will be returned if requested template could not be found.
	ErrTemplateNotFound = errors.New("Template not found")
)

type (
	// Collection is a colletion of templates.
	Collection struct {
		template *template.Template
	}
)

// NewCollection will instantiate a new collection of templates. It will read
// templates from script tags with the type templateType.
func NewCollection(templateType string) *Collection {
	root := template.New("root")

	c := &Collection{
		template: root,
	}

	doc := dom.GetWindow().Document()
	scripts := doc.GetElementsByTagName("script")
	for _, element := range scripts {
		typ := element.GetAttribute("type")

		if typ == templateType {
			name := element.Attributes()["name"]
			payload := element.InnerHTML()
			payload = strings.TrimSpace(payload)
			t := root.New(name)
			_, err := t.Parse(payload)

			if err != nil {
				fmt.Printf("%s\n", err.Error())
			}
		}
	}

	return c
}

// RenderString will render a template to a string.
func (c *Collection) RenderString(templateID string, data interface{}) (string, error) {
	t := c.template.Lookup(templateID)
	if t == nil {
		return "", fmt.Errorf("Template '%s' not found", templateID)
	}

	var buf bytes.Buffer
	err := t.Execute(&buf, data)

	return buf.String(), err
}

// formToMap will collect all input values and return a map.
func formToMap(form dom.Element) map[string]string {
	values := make(map[string]string)

	inputs := form.GetElementsByTagName("input")
	for _, element := range inputs {
		// Type assertion should be safe here - but we check anyway.
		input, ok := element.(*dom.HTMLInputElement)
		if !ok {
			// This should never happen, since we're querying for "input".
			continue
		}

		if input.Name != "" {
			values[input.Name] = input.Value
		}
	}

	return values
}

// RenderElement will render a template to a dom.Element.
func (c *Collection) RenderElement(target dom.Element, templateID string, data interface{}) error {
	str, err := c.RenderString(templateID, data)
	if err != nil {
		return err
	}

	target.SetInnerHTML(str)

	immutable := reflect.ValueOf(data)

	// Find all buttons and attach methods
	buttons := target.GetElementsByTagName("button")
	for _, element := range buttons {
		// This should be safe
		button := element.(*dom.HTMLButtonElement)
		name := button.GetAttribute("name")

		// Find a method matching the buttons name
		val := immutable.MethodByName(name)
		if val.IsValid() {
			// If we have a valid match, attach the method to the button
			button.AddEventListener("click", true, func(event dom.Event) {
				// Get a value from the button to use as argument
				value := event.Target().GetAttribute("value")

				go val.Call([]reflect.Value{reflect.ValueOf(value)})
			})
		} else {
			return fmt.Errorf("No method for button %s", name)
		}
	}

	// Find all forms
	forms := target.GetElementsByTagName("form")
	for _, form := range forms {
		// Find all input elements
		inputs := form.GetElementsByTagName("input")
		for _, input := range inputs {
			// Get name attribute
			typ := input.GetAttribute("type")
			name := input.GetAttribute("name")

			switch typ {
			case "email":
				fallthrough
			case "password":
				fallthrough
			case "url":
				fallthrough
			case "text":
				// text type should be pre-filled from data
				val := immutable.Elem().FieldByName(name)
				if val.IsValid() {<commit_msg>Client: Added number type to template renderer.<commit_after>package template

import (
	"bytes"
	"errors"
	"fmt"
	"html/template"
	"reflect"
	"strings"

	"honnef.co/go/js/dom"
)

var (
	// ErrTemplateNotFound will be returned if requested template could not be found.
	ErrTemplateNotFound = errors.New("Template not found")
)

type (
	// Collection is a colletion of templates.
	Collection struct {
		template *template.Template
	}
)

// NewCollection will instantiate a new collection of templates. It will read
// templates from script tags with the type templateType.
func NewCollection(templateType string) *Collection {
	root := template.New("root")

	c := &Collection{
		template: root,
	}

	doc := dom.GetWindow().Document()
	scripts := doc.GetElementsByTagName("script")
	for _, element := range scripts {
		typ := element.GetAttribute("type")

		if typ == templateType {
			name := element.Attributes()["name"]
			payload := element.InnerHTML()
			payload = strings.TrimSpace(payload)
			t := root.New(name)
			_, err := t.Parse(payload)

			if err != nil {
				fmt.Printf("%s\n", err.Error())
			}
		}
	}

	return c
}

// RenderString will render a template to a string.
func (c *Collection) RenderString(templateID string, data interface{}) (string, error) {
	t := c.template.Lookup(templateID)
	if t == nil {
		return "", fmt.Errorf("Template '%s' not found", templateID)
	}

	var buf bytes.Buffer
	err := t.Execute(&buf, data)

	return buf.String(), err
}

// formToMap will collect all input values and return a map.
func formToMap(form dom.Element) map[string]string {
	values := make(map[string]string)

	inputs := form.GetElementsByTagName("input")
	for _, element := range inputs {
		// Type assertion should be safe here - but we check anyway.
		input, ok := element.(*dom.HTMLInputElement)
		if !ok {
			// This should never happen, since we're querying for "input".
			continue
		}

		if input.Name != "" {
			values[input.Name] = input.Value
		}
	}

	return values
}

// RenderElement will render a template to a dom.Element.
func (c *Collection) RenderElement(target dom.Element, templateID string, data interface{}) error {
	str, err := c.RenderString(templateID, data)
	if err != nil {
		return err
	}

	target.SetInnerHTML(str)

	immutable := reflect.ValueOf(data)

	// Find all buttons and attach methods
	buttons := target.GetElementsByTagName("button")
	for _, element := range buttons {
		// This should be safe
		button := element.(*dom.HTMLButtonElement)
		name := button.GetAttribute("name")

		// Find a method matching the buttons name
		val := immutable.MethodByName(name)
		if val.IsValid() {
			// If we have a valid match, attach the method to the button
			button.AddEventListener("click", true, func(event dom.Event) {
				// Get a value from the button to use as argument
				value := event.Target().GetAttribute("value")

				go val.Call([]reflect.Value{reflect.ValueOf(value)})
			})
		} else {
			return fmt.Errorf("No method for button %s", name)
		}
	}

	// Find all forms
	forms := target.GetElementsByTagName("form")
	for _, form := range forms {
		// Find all input elements
		inputs := form.GetElementsByTagName("input")
		for _, input := range inputs {
			// Get name attribute
			typ := input.GetAttribute("type")
			name := input.GetAttribute("name")

			switch typ {
			case "number":
				// number can be treated like string-types for this case.
				fallthrough
			case "email":
				fallthrough
			case "password":
				fallthrough
			case "url":
				fallthrough
			case "text":
				// text type should be pre-filled from data
				val := immutable.Elem().FieldByName(name)
				if val.IsValid() {
{'fraction_non_alphanumeric': 0.12646402677077523, 'fraction_numerical': 0.0, 'mean_word_length': 3.539873417721519, 'pattern_counts': {'":': 9, '<': 3, '<?xml version=': 0, '>': 3, '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': '4918519', 'n_tokens_mistral': 2413, 'n_tokens_neox': 2175, 'n_words': 688}