<commit_before>import { InvalidArgumentError } from '../errors/InvalidArgumentError';
import { NotImplementedError } from '../errors/NotImplementedError';
import mustache from 'mustache';

export class Control {
	constructor(id, template, localCSS) {
		if (typeof id !== 'string' || !isNaN(id)) {
			throw new InvalidArgumentError('Cannot create the control because the id is not a string');
		}
		if (id.length < 1) {
			throw new InvalidArgumentError('Cannot create the control because the id is not a non-empty string');
		}
		if (null === template || undefined === template) {
			throw new InvalidArgumentError('Cannot create the control because the template cannot be null or undefined');
		}
		if (typeof template !== 'string') {
			throw new InvalidArgumentError('Cannot create the control because the template is not a string');
		}

		this.id = id;
		this.template = template;

		if (template && localCSS) {
			// localize the CSS class names in the templates
			for (const oCN in localCSS) {
				const nCN = localCSS[oCN];
				this.template = this.template
					.replace(new RegExp(`class="${oCN}"`, 'gi'), `class="${nCN}"`)
					.replace(new RegExp(`class='${oCN}'`, 'gi'), `class='${nCN}'`);
			}
		}

		this.controls = {};
	}

	addControl(control) {
		if (!(control instanceof Control)) {
			throw new InvalidArgumentError('Cannot add sub-control because it is invalid');
		}
		this.controls[control.id] = control;
	}

	// val: Either controlId or control instance
	removeControl(val) {
		if (val instanceof Control) {
			delete this.controls[val.id];
		} else {
			delete this.controls[val];
		}
	}

	render(data) {
		let content = mustache.render(this.template, data);

		if (this.controls) {
			const controlData = {};
			for (let controlId in this.controls) {
				const control = this.controls[controlId];
				controlData[control.constructor.name] = {};
				controlData[control.constructor.name][control.id] = control.render(data);
			}
			content = mustache.render(content, control);
		}

		return content;
	}

	// This method is invoked so the control can bind events after the DOM has been updated
	// domContainerElement: The DOM container element into which the control was rendered
	onDOMUpdated(domContainerElement) {
		if (this.controls) {
			for (let controlId in this.controls) {
				const control = this.controls[controlId];
				control.onDOMUpdated(this.domContainerElement);
			}
		}
	}
};<commit_msg>Fixed templating mustache.render invocation in Control<commit_after>import { InvalidArgumentError } from '../errors/InvalidArgumentError';
import { NotImplementedError } from '../errors/NotImplementedError';
import mustache from 'mustache';

export class Control {
	constructor(id, template, localCSS) {
		if (typeof id !== 'string' || !isNaN(id)) {
			throw new InvalidArgumentError('Cannot create the control because the id is not a string');
		}
		if (id.length < 1) {
			throw new InvalidArgumentError('Cannot create the control because the id is not a non-empty string');
		}
		if (null === template || undefined === template) {
			throw new InvalidArgumentError('Cannot create the control because the template cannot be null or undefined');
		}
		if (typeof template !== 'string') {
			throw new InvalidArgumentError('Cannot create the control because the template is not a string');
		}

		this.id = id;
		this.template = template;

		if (template && localCSS) {
			// localize the CSS class names in the templates
			for (const oCN in localCSS) {
				const nCN = localCSS[oCN];
				this.template = this.template
					.replace(new RegExp(`class="${oCN}"`, 'gi'), `class="${nCN}"`)
					.replace(new RegExp(`class='${oCN}'`, 'gi'), `class='${nCN}'`);
			}
		}

		this.controls = {};
	}

	addControl(control) {
		if (!(control instanceof Control)) {
			throw new InvalidArgumentError('Cannot add sub-control because it is invalid');
		}
		this.controls[control.id] = control;
	}

	// val: Either controlId or control instance
	removeControl(val) {
		if (val instanceof Control) {
			delete this.controls[val.id];
		} else {
			delete this.controls[val];
		}
	}

	render(data) {
		let content = mustache.render(this.template, data);

		if (this.controls) {
			const controlData = {};
			for (let controlId in this.controls) {
				const control = this.controls[controlId];
				controlData[control.constructor.name] = {};
				controlData[control.constructor.name][control.id] = control.render(data);
			}
			content = mustache.render(content, controlData);
		}

		return content;
	}

	// This method is invoked so the control can bind events after the DOM has been updated
	// domContainerElement: The DOM container element into which the control was rendered
	onDOMUpdated(domContainerElement) {
		if (this.controls) {
			for (let controlId in this.controls) {
				const control = this.controls[controlId];
				control.onDOMUpdated(this.domContainerElement);
			}
		}
	}
};
{'fraction_non_alphanumeric': 0.12533115956796415, 'fraction_numerical': 0.0004075810067250866, 'mean_word_length': 3.922768304914744, 'pattern_counts': {'":': 0, '<': 5, '<?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': '1637859', 'n_tokens_mistral': 1602, 'n_tokens_neox': 1411, 'n_words': 445}