<commit_before>/**
* Donatello - A pure CSS vector drawing library.
*
* Provided under the MIT license.
* See LICENSE file for full text of the license.
* Copyright 2011 <NAME>.
*/


/**
* Donatello objects are used to represent shapes drawn
* in the scene. The scene consists of a tree of these.
*
* id - id string of an existing DOM element or a reference
* to the DOM element itself.
* x/y, w/h - position and size
*/
function Donatello( id, x, y, w, h ) {
	// TODO fix hacky initialization
	Donatello.setTransform();

	/** 
	* Translation between drawing terminology and CSS property 
	* names.
	*/
	this.attrMap = {
		fill: 'backgroundColor',
		stroke: 'borderColor',
		'stroke-style': 'borderStyle',
		// todo: we ignore stroke width becuase it requires
		// the object to be recalculated
		'stroke-width': null,
		'x': null,
		'y': null,
		'w': null,
		'h': null,
		'r': 'borderRadius',
		'type': null,
		'children': null,
		'transform': Donatello.transform
	}

	if( typeof id == 'string' ) {
		var el = document.getElementById( id );
		Donatello.createElement( x, y, w, h, el );
		this.dom = el;
	}
	else {
		this.dom = id;
	}
}

/*
* Paper is a Donatello object that serves as a container 
* and has no visible attributes. Essentially a factory
* method wrapping Donatello constructor for now.
*  todo; thinking about renaming this to plane 
*/
Donatello.paper = function( id, x, y, z, w, h ) {
	return new Donatello( id, x, y, z, w, h );
}

/** 
* create drawing graph declaratively
* par - parent Donatello object
* a - attribute object 
* Only works for rect at this stage.
*/
Donatello.decl = function( par, a ) {
	var don;
	if( a.type == 'rect' ) {
		don = par.rect( a.x, a.y, a.w, a.h, a );
	}
	for( var i=0; i < a.children.length; i++ ) {
		Donatello.decl( don, a.children[i] );	
	}
}

/**
 * Detect css transform attribute for browser compatibility.
 * Must be called after DOM is loaded since we detect
 * features by looking at DOM properties.
 */
Donatello.setTransform = function() {
	if( Donatello.transform == undefined ) {
		var transform;
		// css spec, no browser supports this yet
		if( typeof document.body.style.transform != 'undefined' ) {
			transform = 'transform';
		} 
		else if( typeof document.body.style.webkitTransform != 'undefined' ) {
			transform = 'webkitTransform';
		} 
		else if( typeof document.body.style.MozTransform != 'undefined' ) {
			transform = 'MozTransform';
		} 
		else if( typeof document.body.style.msTransform != 'undefined' ) {
			transform = 'msTransform';
		} 
		else if( typeof document.body.style.OTransform != 'undefined' ) {
			transform = 'OTransform';
		} 
		// transforms not supported
		else { transform = null }
		console.log( 'css transform: ' + transform );
		Donatello.transform = transform;
	}
	// also return transform - used in attr mapping
	// part of hacky init that should be fixed somehow
	return transform;
}


/**
* Internal function for creating the appropriate 
* linear gradient function
*/
Donatello.createLinearGradient = function( deg, color1, color2 ) {
	// we round angles down to multiples of 45deg
	deg = Math.floor(deg/45);
	// default to centered vertical gradient
	var webkitLine = "center top, center bottom";
	switch( deg ) {
		case 0:
			webkitLine = "left center, right center";
			break;
		case 1:
			webkitLine = "left bottom, right top";
			break;
		case 2:
			webkitLine = "center bottom, center top";
			break;
		case 3:
			webkitLine = "right bottom, left top";
			break;
		case 4:
			webkitLine = "right center, left center";
			break;
		case 5:
			webkitLine = "right top, left bottom";
			break;
		case 6:
			webkitLine = "center top, center bottom";
			break;
		case 7:
			webkitLine = "left top, right bottom";
			break;
		case 8:
			webkitLine = "left center, right center";
			break;
	}
	var retval;
	switch( Donatello.transform ) {
		case 'MozTransform':
			retval = '-moz-linear-gradient(' + 
				deg*45 + 'deg,' + color1 + ', ' + color2 + ')';
			break;
		case 'webkitTransform':
			retval = '-webkit-gradient(linear, ' + webkitLine + 
				', from(' + color1 + '), to(' + color2 + '))'; 
			break;
		case 'msTransform':
			// note that filter: attribute must be set rather than background:
			// in IE gradient type is either 0 (top to bottom) or 1 (left to right)
			var gtype = Math.floor(deg%4/2)
			retval = 'progid:DXImageTransform.Microsoft.gradient(GradientType=' + 
				gtype + ', startColorstr="' + 
				color1 + '", endColorstr="' + color2 + '")'; 
			break;
		case 'OTransform':
			retval = '-o-linear-gradient(' + deg*45 +'deg,' + 
				color1 + ',' + color2 + ')';
			break;
	}
	console.log( 'gradient: ' + retval );
	return retval;
}


/**
* Internal function for creating the appropriate 
* radial gradient function
* TODO: this is incomplete - need to decide on what level of
* support to provide for radial gradients
*/
Donatello.createRadialGradient = function( deg, color1, color2 ) {
	var retval;
	switch( Donatello.transform ) {
		case 'MozTransform':
			retval = '-moz-radial-gradient(' + deg + 'deg,' + 
				color1 + ', ' + color2 + ')';
			break;
		default:
			throw 'Gradients not implemented for ' + Donatello.transform;
	}
	console.log( 'gradient: ' + retval );
	return retval;
}

/**
 * Transformation methods that apply to all shapes
 */

Donatello.prototype.rotate = function( deg ) {
	// note that we add the rotation to the existing transform. 
	// not sure if this will cause problems at any point - we may 
	// need some more sophisticated managment of the list of applied
	// transforms later on down the road.
	this.dom.style[ Donatello.transform ] += 'rotate(' + deg + 'deg)';
}

Donatello.prototype.clear = function() {
	while( this.dom.hasChildNodes() ) {
		this.dom.removeChild( this.dom.lastChild );
	}
}

Donatello.prototype['delete'] = function() {
	this.dom.parentNode.removeChild( this.dom );
}

Donatello.prototype.node = function() {
	return this.dom;
}

/**
* Time given in seconds
* Easing is always in-out
*/
Donatello.prototype.animate = function( time, attrs ) {
	// TODO: only works in firefox right now
	var me = this;
	this.attr( {'MozTransition':'all ' + time + 's ease-in 0s'});
	// in order for the animation to work, we have to set
	// moz-transition first, then later in setTimout set the props
	setTimeout( function() { me.attr( attrs ) }, 0 );
	return this.dom;
}

/*
* Stop the current animation
*/
Donatello.prototype.stop = function( time, attrs ) {
	// TODO: this doesn't work how it should
	this.attr( {'MozTransition':''});
}


/**
* Setting attributes looks for mapped attributes first, then
* passes attribute through as a CSS attribute.
*/
Donatello.prototype.attr = function( obj ) {
	var mapping = this.attrMap;
	for( attr in obj ) {
		if( mapping[attr] != null ){
			if( attr == 'r' ) {
				// special case to add 'px' to radius specification
				// TODO: see about simplifying this stuff
				this.dom.style[mapping[attr]] = obj[attr] + 'px';
			}
			else {
				this.dom.style[mapping[attr]] = obj[attr];
			}
		} 
		else if( 
			// ignore attributes that we ordinarily set using
			// positional arguments.
			attr != 'stroke-width' && 
			attr != 'x' && 
			attr != 'y' && 
			attr != 'w' && 
			attr != 'h' && 
			// children and type are used for declarative instantiation
			attr != 'type' && 
			attr != 'children' 
		) {
			this.dom.style[attr] = obj[attr];
		}
	}
	return this;
}


/**
* Drawing methods
*/

/**
 * Draw a circle
 * center coordinates, radius, attributes 
 */
Donatello.prototype.circle = function( x, y, r, a ) {
	a = Donatello.attrDefaults( a );
	var s = a['stroke-width'];
	var c = a['stroke'];
	var f = a['fill'];
	var style = a['stroke-style'];
	var el = Donatello.createElement( x-r-s, y-r-s, 2*r, 2*r, 'div');
	el.style.borderRadius = r + s + 'px';
	el.style.borderStyle = style;
	el.style.borderColor = c;
	el.style.backgroundColor = f;
	el.style.borderWidth = s  + 'px';

	this.dom.appendChild( el );
	var don = new Donatello( el ); 
	don.attr( a );
	return don;
}

/**
 * Ellipse is similar to circle, should consolidate
 * xy position, xy radius, stroke width
 */
Donatello.prototype.ellipse = function( x, y, rx, ry, a ) {
	a = Donatello.attrDefaults( a );
	var s = a['stroke-width'];
	var c = a['stroke'];
	var f = a['fill'];
	var style = a['stroke-style'];

	var el = Donatello.createElement( x-rx-s, y-ry-s, 2*rx, 2*ry, 'div');
	el.style.borderRadius = ( rx + s ) + 'px / ' + ( ry + s ) + 'px';
	el.style.borderStyle = style;
	el.style.borderColor = c;
	el.style.borderWidth = s + 'px';
	el.style.backgroundColor = f;
	
	this.dom.appendChild( el );
	var don = new Donatello( el ); 
	don.attr( a );
	return don; 
}

/**
*  Draw a rectangular region to the scene.
*/
Donatello.prototype.rect = function( x, y, w, h, a ) {
	return this.pgram( x, y, w, h, null, a );
}

/**
 * generalized parallelogram, used by rect.
 */
Donatello.prototype.pgram = function( x, y, dx, dy, skew, a ) {
	a = Donatello.attrDefaults( a );
	var el = Donatello.createElement( x, y, dx, dy, 'div');

	el.style.borderWidth = a['stroke-width'] + 'px';

	if( skew != null ) {
		el.style[ Donatello.transform ] += 'skew(' + skew + 'deg)';
	}
	this.dom.appendChild( el );
	var don = new Donatello( el );
	don.attr( a );
	return don;
}

/**
* Draw text to the scene using a <div> tag.
*/
Donatello.prototype.text = function( x, y, str, a ) {
	var el = Donatello.createElement( x, y, null, null, 'div');
	el.innerHTML = str;
	this.dom.appendChild( el );
	var don = new Donatello( el );
	don.attr( a );
	return don;
}

/**
* Draw an image to the scene using an <img> tag.
*/
Donatello.prototype.image = function( x, y, w, h, img, a ) {
	var el = Donatello.createElement( x, y, w, h, 'img');
	el.src = img;
	this.dom.appendChild( el );
	var don = new Donatello( el );
	don.attr( a );
	return don;
}

/**
* Draw a straight line.
* dx/dy are offsets from start, w is stroke width
*
* TODO: add end caps - box-radius for rounded,
* borders for diagonal. also maybe linejoin
*/
Donatello.prototype.line = function( x, y, dx, dy, a ) {
	a = Donatello.attrDefaults( a );
	var w = a['stroke-width']; 
	var stroke = w;
	var c = a['stroke'];
	var f = a['fill'];
	var style = a['stroke-style'];

	var len = Math.sqrt(dx*dx + dy*dy );
	var el = document.createElement( 'div' );	
	el.style.position = 'absolute';
	el.style.top = y + 'px';
	el.style.left = x + 'px';

	// width is the line length	
	el.style.width = len + 'px';

	// height is the line width
	el.style.height = '0px';

	// setting both borders makes line too thick
	el.style.borderTopStyle = style;
	el.style.borderTopWidth = stroke + 'px';
	el.style.borderTopColor = c;

	// find the angle
	var rot = Math.asin( Math.abs(dy) / len );
	// convert to degrees
	rot = rot * (180/Math.PI);

	// we handle other orientations by adjusting 
	// rotation according to quadrant 
	if( dx < 0 && dy >= 0 ) {
		rot = 180-rot;
	}
	else if( dx < 0 && dy <  0 ) {
		rot = 180+rot;
	}
	else if( dx >= 0 && dy < 0 ) {
		rot = 360-rot;
	}

	el.style[ Donatello.transform ] = 
		'rotate(' + rot + 'deg) translate(0px, -' + stroke/2 + 'px)';
	// transform origin referenced from border width
	el.style[ Donatello.transform + 'Origin' ] = '0px 0px';
	this.dom.appendChild( el );
	var dom = new Donatello( el );
	dom.attr( a );
	return dom;
}

/**
* Internally used  method for creating
* and initializing DOM elements.<commit_msg>removing application of attrs to lines for now - need to find a way to keep from clobbering initial values.<commit_after>/**
* Donatello - A pure CSS vector drawing library.
*
* Provided under the MIT license.
* See LICENSE file for full text of the license.
* Copyright 2011 <NAME>.
*/


/**
* Donatello objects are used to represent shapes drawn
* in the scene. The scene consists of a tree of these.
*
* id - id string of an existing DOM element or a reference
* to the DOM element itself.
* x/y, w/h - position and size
*/
function Donatello( id, x, y, w, h ) {
	// TODO fix hacky initialization
	Donatello.setTransform();

	/** 
	* Translation between drawing terminology and CSS property 
	* names.
	*/
	this.attrMap = {
		fill: 'backgroundColor',
		stroke: 'borderColor',
		'stroke-style': 'borderStyle',
		// todo: we ignore stroke width becuase it requires
		// the object to be recalculated
		'stroke-width': null,
		'x': null,
		'y': null,
		'w': null,
		'h': null,
		'r': 'borderRadius',
		'type': null,
		'children': null,
		'transform': Donatello.transform
	}

	if( typeof id == 'string' ) {
		var el = document.getElementById( id );
		Donatello.createElement( x, y, w, h, el );
		this.dom = el;
	}
	else {
		this.dom = id;
	}
}

/*
* Paper is a Donatello object that serves as a container 
* and has no visible attributes. Essentially a factory
* method wrapping Donatello constructor for now.
*  todo; thinking about renaming this to plane 
*/
Donatello.paper = function( id, x, y, z, w, h ) {
	return new Donatello( id, x, y, z, w, h );
}

/** 
* create drawing graph declaratively
* par - parent Donatello object
* a - attribute object 
* Only works for rect at this stage.
*/
Donatello.decl = function( par, a ) {
	var don;
	if( a.type == 'rect' ) {
		don = par.rect( a.x, a.y, a.w, a.h, a );
	}
	for( var i=0; i < a.children.length; i++ ) {
		Donatello.decl( don, a.children[i] );	
	}
}

/**
 * Detect css transform attribute for browser compatibility.
 * Must be called after DOM is loaded since we detect
 * features by looking at DOM properties.
 */
Donatello.setTransform = function() {
	if( Donatello.transform == undefined ) {
		var transform;
		// css spec, no browser supports this yet
		if( typeof document.body.style.transform != 'undefined' ) {
			transform = 'transform';
		} 
		else if( typeof document.body.style.webkitTransform != 'undefined' ) {
			transform = 'webkitTransform';
		} 
		else if( typeof document.body.style.MozTransform != 'undefined' ) {
			transform = 'MozTransform';
		} 
		else if( typeof document.body.style.msTransform != 'undefined' ) {
			transform = 'msTransform';
		} 
		else if( typeof document.body.style.OTransform != 'undefined' ) {
			transform = 'OTransform';
		} 
		// transforms not supported
		else { transform = null }
		console.log( 'css transform: ' + transform );
		Donatello.transform = transform;
	}
	// also return transform - used in attr mapping
	// part of hacky init that should be fixed somehow
	return transform;
}


/**
* Internal function for creating the appropriate 
* linear gradient function
*/
Donatello.createLinearGradient = function( deg, color1, color2 ) {
	// we round angles down to multiples of 45deg
	deg = Math.floor(deg/45);
	// default to centered vertical gradient
	var webkitLine = "center top, center bottom";
	switch( deg ) {
		case 0:
			webkitLine = "left center, right center";
			break;
		case 1:
			webkitLine = "left bottom, right top";
			break;
		case 2:
			webkitLine = "center bottom, center top";
			break;
		case 3:
			webkitLine = "right bottom, left top";
			break;
		case 4:
			webkitLine = "right center, left center";
			break;
		case 5:
			webkitLine = "right top, left bottom";
			break;
		case 6:
			webkitLine = "center top, center bottom";
			break;
		case 7:
			webkitLine = "left top, right bottom";
			break;
		case 8:
			webkitLine = "left center, right center";
			break;
	}
	var retval;
	switch( Donatello.transform ) {
		case 'MozTransform':
			retval = '-moz-linear-gradient(' + 
				deg*45 + 'deg,' + color1 + ', ' + color2 + ')';
			break;
		case 'webkitTransform':
			retval = '-webkit-gradient(linear, ' + webkitLine + 
				', from(' + color1 + '), to(' + color2 + '))'; 
			break;
		case 'msTransform':
			// note that filter: attribute must be set rather than background:
			// in IE gradient type is either 0 (top to bottom) or 1 (left to right)
			var gtype = Math.floor(deg%4/2)
			retval = 'progid:DXImageTransform.Microsoft.gradient(GradientType=' + 
				gtype + ', startColorstr="' + 
				color1 + '", endColorstr="' + color2 + '")'; 
			break;
		case 'OTransform':
			retval = '-o-linear-gradient(' + deg*45 +'deg,' + 
				color1 + ',' + color2 + ')';
			break;
	}
	console.log( 'gradient: ' + retval );
	return retval;
}


/**
* Internal function for creating the appropriate 
* radial gradient function
* TODO: this is incomplete - need to decide on what level of
* support to provide for radial gradients
*/
Donatello.createRadialGradient = function( deg, color1, color2 ) {
	var retval;
	switch( Donatello.transform ) {
		case 'MozTransform':
			retval = '-moz-radial-gradient(' + deg + 'deg,' + 
				color1 + ', ' + color2 + ')';
			break;
		default:
			throw 'Gradients not implemented for ' + Donatello.transform;
	}
	console.log( 'gradient: ' + retval );
	return retval;
}

/**
 * Transformation methods that apply to all shapes
 */

Donatello.prototype.rotate = function( deg ) {
	// note that we add the rotation to the existing transform. 
	// not sure if this will cause problems at any point - we may 
	// need some more sophisticated managment of the list of applied
	// transforms later on down the road.
	this.dom.style[ Donatello.transform ] += 'rotate(' + deg + 'deg)';
}

Donatello.prototype.clear = function() {
	while( this.dom.hasChildNodes() ) {
		this.dom.removeChild( this.dom.lastChild );
	}
}

Donatello.prototype['delete'] = function() {
	this.dom.parentNode.removeChild( this.dom );
}

Donatello.prototype.node = function() {
	return this.dom;
}

/**
* Time given in seconds
* Easing is always in-out
*/
Donatello.prototype.animate = function( time, attrs ) {
	// TODO: only works in firefox right now
	var me = this;
	this.attr( {'MozTransition':'all ' + time + 's ease-in 0s'});
	// in order for the animation to work, we have to set
	// moz-transition first, then later in setTimout set the props
	setTimeout( function() { me.attr( attrs ) }, 0 );
	return this.dom;
}

/*
* Stop the current animation
*/
Donatello.prototype.stop = function( time, attrs ) {
	// TODO: this doesn't work how it should
	this.attr( {'MozTransition':''});
}


/**
* Setting attributes looks for mapped attributes first, then
* passes attribute through as a CSS attribute.
*/
Donatello.prototype.attr = function( obj ) {
	var mapping = this.attrMap;
	for( attr in obj ) {
		if( mapping[attr] != null ){
			if( attr == 'r' ) {
				// special case to add 'px' to radius specification
				// TODO: see about simplifying this stuff
				this.dom.style[mapping[attr]] = obj[attr] + 'px';
			}
			else {
				this.dom.style[mapping[attr]] = obj[attr];
			}
		} 
		else if( 
			// ignore attributes that we ordinarily set using
			// positional arguments.
			attr != 'stroke-width' && 
			attr != 'x' && 
			attr != 'y' && 
			attr != 'w' && 
			attr != 'h' && 
			// children and type are used for declarative instantiation
			attr != 'type' && 
			attr != 'children' 
		) {
			this.dom.style[attr] = obj[attr];
		}
	}
	return this;
}


/**
* Drawing methods
*/

/**
 * Draw a circle
 * center coordinates, radius, attributes 
 */
Donatello.prototype.circle = function( x, y, r, a ) {
	a = Donatello.attrDefaults( a );
	var s = a['stroke-width'];
	var c = a['stroke'];
	var f = a['fill'];
	var style = a['stroke-style'];
	var el = Donatello.createElement( x-r-s, y-r-s, 2*r, 2*r, 'div');
	el.style.borderRadius = r + s + 'px';
	el.style.borderStyle = style;
	el.style.borderColor = c;
	el.style.backgroundColor = f;
	el.style.borderWidth = s  + 'px';

	this.dom.appendChild( el );
	var don = new Donatello( el ); 
	don.attr( a );
	return don;
}

/**
 * Ellipse is similar to circle, should consolidate
 * xy position, xy radius, stroke width
 */
Donatello.prototype.ellipse = function( x, y, rx, ry, a ) {
	a = Donatello.attrDefaults( a );
	var s = a['stroke-width'];
	var c = a['stroke'];
	var f = a['fill'];
	var style = a['stroke-style'];

	var el = Donatello.createElement( x-rx-s, y-ry-s, 2*rx, 2*ry, 'div');
	el.style.borderRadius = ( rx + s ) + 'px / ' + ( ry + s ) + 'px';
	el.style.borderStyle = style;
	el.style.borderColor = c;
	el.style.borderWidth = s + 'px';
	el.style.backgroundColor = f;
	
	this.dom.appendChild( el );
	var don = new Donatello( el ); 
	don.attr( a );
	return don; 
}

/**
*  Draw a rectangular region to the scene.
*/
Donatello.prototype.rect = function( x, y, w, h, a ) {
	return this.pgram( x, y, w, h, null, a );
}

/**
 * generalized parallelogram, used by rect.
 */
Donatello.prototype.pgram = function( x, y, dx, dy, skew, a ) {
	a = Donatello.attrDefaults( a );
	var el = Donatello.createElement( x, y, dx, dy, 'div');

	el.style.borderWidth = a['stroke-width'] + 'px';

	if( skew != null ) {
		el.style[ Donatello.transform ] += 'skew(' + skew + 'deg)';
	}
	this.dom.appendChild( el );
	var don = new Donatello( el );
	don.attr( a );
	return don;
}

/**
* Draw text to the scene using a <div> tag.
*/
Donatello.prototype.text = function( x, y, str, a ) {
	var el = Donatello.createElement( x, y, null, null, 'div');
	el.innerHTML = str;
	this.dom.appendChild( el );
	var don = new Donatello( el );
	don.attr( a );
	return don;
}

/**
* Draw an image to the scene using an <img> tag.
*/
Donatello.prototype.image = function( x, y, w, h, img, a ) {
	var el = Donatello.createElement( x, y, w, h, 'img');
	el.src = img;
	this.dom.appendChild( el );
	var don = new Donatello( el );
	don.attr( a );
	return don;
}

/**
* Draw a straight line.
* dx/dy are offsets from start, w is stroke width
*
* TODO: add end caps - box-radius for rounded,
* borders for diagonal. also maybe linejoin
*/
Donatello.prototype.line = function( x, y, dx, dy, a ) {
	a = Donatello.attrDefaults( a );
	var w = a['stroke-width']; 
	var stroke = w;
	var c = a['stroke'];
	var f = a['fill'];
	var style = a['stroke-style'];

	var len = Math.sqrt(dx*dx + dy*dy );
	var el = document.createElement( 'div' );	
	el.style.position = 'absolute';
	el.style.top = y + 'px';
	el.style.left = x + 'px';

	// width is the line length	
	el.style.width = len + 'px';

	// height is the line width
	el.style.height = '0px';

	// setting both borders makes line too thick
	el.style.borderTopStyle = style;
	el.style.borderTopWidth = stroke + 'px';
	el.style.borderTopColor = c;

	// find the angle
	var rot = Math.asin( Math.abs(dy) / len );
	// convert to degrees
	rot = rot * (180/Math.PI);

	// we handle other orientations by adjusting 
	// rotation according to quadrant 
	if( dx < 0 && dy >= 0 ) {
		rot = 180-rot;
	}
	else if( dx < 0 && dy <  0 ) {
		rot = 180+rot;
	}
	else if( dx >= 0 && dy < 0 ) {
		rot = 360-rot;
	}

	el.style[ Donatello.transform ] = 
		'rotate(' + rot + 'deg) translate(0px, -' + stroke/2 + 'px)';
	// transform origin referenced from border width
	el.style[ Donatello.transform + 'Origin' ] = '0px 0px';
	this.dom.appendChild( el );
	var dom = new Donatello( el );

	// applying styles messes up lines, fix this
	// dom.attr( a );

	return dom;
}

/**
* Internally used  method for creating
* and initializing DOM elements.
{'fraction_non_alphanumeric': 0.14694431077474956, 'fraction_numerical': 0.0060370094929786955, 'mean_word_length': 3.150326797385621, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 13, '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': '5722826', 'n_tokens_mistral': 8420, 'n_tokens_neox': 7774, 'n_words': 2540}