<commit_before>(function (root, factory) {
	if(typeof define === "function" && define.amd) {
		define(function(){
			return factory();
		});
	} else if(typeof module === "object" && module.exports) {
		module.exports = factory();
	} else {
		root.EagleCanvas = factory();
	}
}(this, function () {

var p = function(o){ console.log(o) }
// -----------------------
// --- ENUMS, DEFAULTS ---
// -----------------------

EagleCanvas.LayerId = {
	'BOTTOM_COPPER' : 1,
	'BOTTOM_SILKSCREEN' : 2,
	'BOTTOM_DOCUMENTATION' : 3,
	'DIM_BOARD' : 4,
	'TOP_COPPER' : 5,
	'TOP_SILKSCREEN' : 6,
	'TOP_DOCUMENTATION' : 7,
	'VIAS' : 8,
	'OUTLINE' : 9
}

EagleCanvas.LARGE_NUMBER = 99999;

EagleCanvas.prototype.scale = 25;
EagleCanvas.prototype.minScale = 2.5;
EagleCanvas.prototype.maxScale = 250;
EagleCanvas.prototype.minLineWidth = 0.05;
EagleCanvas.prototype.boardFlipped = false;
EagleCanvas.prototype.dimBoardAlpha = 0.7;

// -------------------
// --- CONSTRUCTOR ---
// -------------------

function EagleCanvas(canvasSelector) {
	this.canvasSelector = canvasSelector;

	this.visibleLayers = {};
	this.visibleLayers[EagleCanvas.LayerId.BOTTOM_COPPER]        = true;
	this.visibleLayers[EagleCanvas.LayerId.BOTTOM_SILKSCREEN]    = true;
	this.visibleLayers[EagleCanvas.LayerId.BOTTOM_DOCUMENTATION] = true;
	this.visibleLayers[EagleCanvas.LayerId.DIM_BOARD]            = true;
	this.visibleLayers[EagleCanvas.LayerId.TOP_COPPER]           = true;
	this.visibleLayers[EagleCanvas.LayerId.TOP_SILKSCREEN]       = true;
	this.visibleLayers[EagleCanvas.LayerId.TOP_DOCUMENTATION]    = true;
	this.visibleLayers[EagleCanvas.LayerId.VIAS]                 = true;
	this.visibleLayers[EagleCanvas.LayerId.OUTLINE]              = true;

	this.renderLayerOrder = [];
	this.renderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_DOCUMENTATION);
	this.renderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_SILKSCREEN);
	this.renderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_COPPER);
	this.renderLayerOrder.push(EagleCanvas.LayerId.DIM_BOARD);
	this.renderLayerOrder.push(EagleCanvas.LayerId.OUTLINE);
	this.renderLayerOrder.push(EagleCanvas.LayerId.TOP_COPPER);
	this.renderLayerOrder.push(EagleCanvas.LayerId.VIAS);
	this.renderLayerOrder.push(EagleCanvas.LayerId.TOP_SILKSCREEN);
	this.renderLayerOrder.push(EagleCanvas.LayerId.TOP_DOCUMENTATION);

	this.reverseRenderLayerOrder = [];
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.TOP_DOCUMENTATION);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.TOP_SILKSCREEN);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.TOP_COPPER);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.DIM_BOARD);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.OUTLINE);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_COPPER);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.VIAS);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_SILKSCREEN);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_DOCUMENTATION);

	this.layerRenderFunctions = {};
	
	this.layerRenderFunctions[EagleCanvas.LayerId.BOTTOM_COPPER] = function(that,ctx) {
		that.drawSignalWires(that.eagleLayersByName['Bottom'],ctx);
		that.drawElements(that.eagleLayersByName['Bottom'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['Bottom'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.BOTTOM_SILKSCREEN] = function(that,ctx) {
		that.drawElements(that.eagleLayersByName['bNames'],ctx);
		that.drawElements(that.eagleLayersByName['bValues'],ctx);
		that.drawElements(that.eagleLayersByName['bPlace'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['bNames'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['bValues'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.BOTTOM_DOCUMENTATION] = function(that,ctx) {
		that.drawElements(that.eagleLayersByName['bKeepout'],ctx);
		that.drawElements(that.eagleLayersByName['bDocu'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['bKeepout'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['bDocu'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.TOP_COPPER] = function(that,ctx) {
		that.drawSignalWires(that.eagleLayersByName['Top'],ctx);
		that.drawElements   (that.eagleLayersByName['Top'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['Top'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.TOP_SILKSCREEN] = function(that,ctx) {
		that.drawElements(that.eagleLayersByName['tNames'],ctx);
		that.drawElements(that.eagleLayersByName['tValues'],ctx);
		that.drawElements(that.eagleLayersByName['tPlace'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['tNames'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['tValues'],ctx);

	}

	this.layerRenderFunctions[EagleCanvas.LayerId.TOP_DOCUMENTATION] = function(that,ctx) {
		that.drawElements(that.eagleLayersByName['tKeepout'],ctx);
		that.drawElements(that.eagleLayersByName['tDocu'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['tKeepout'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['tDocu'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.DIM_BOARD] = function(that,ctx) {
		that.dimCanvas(ctx,that.dimBoardAlpha);
	}	

	this.layerRenderFunctions[EagleCanvas.LayerId.VIAS] = function(that,ctx) {
		that.drawSignalVias('1-16',ctx, that.viaPadColor());
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.OUTLINE] = function(that,ctx) {
		that.drawPlainWires(that.eagleLayersByName['Dimension'],ctx);
		that.drawPlainHoles(that.eagleLayersByName['Dimension'],ctx);
	}

	this.hitTestFunctions = {};

	this.hitTestFunctions[EagleCanvas.LayerId.BOTTOM_COPPER] = function(x,y) {
		return this.hitTestElements (this.eagleLayersByName['Bottom'],x,y)
			|| this.hitTestSignals  (this.eagleLayersByName['Bottom'],x,y);
	}.bind (this);

	this.hitTestFunctions[EagleCanvas.LayerId.TOP_COPPER] = function(x,y) {
		return this.hitTestElements (this.eagleLayersByName['Top'],x,y)
			|| this.hitTestSignals  (this.eagleLayersByName['Top'],x,y);
	}.bind (this);


}


// -------------------------
// --- GENERIC ACCESSORS ---
// -------------------------

/** sets an element id to which the drawing should be initially scaled */
EagleCanvas.prototype.setScaleToFit = function(elementSelector) {
	this.scaleToFitSelector = elementSelector;
}

EagleCanvas.prototype.getScale = function(scale) {
	return this.scale;
}

/** sets the scale factor, triggers resizing and redrawing */
EagleCanvas.prototype.setScale = function(scale) {
	this.scale = scale;
	var canvas = document.querySelector (this.canvasSelector);
	var context = canvas.getContext('2d'),
		devicePixelRatio = window.devicePixelRatio || 1,
		backingStoreRatio =
			context.webkitBackingStorePixelRatio ||
			context.mozBackingStorePixelRatio ||
			context.msBackingStorePixelRatio ||
			context.oBackingStorePixelRatio ||
			context.backingStorePixelRatio || 1,
		ratio = devicePixelRatio / backingStoreRatio;

	canvas.width  = scale * this.nativeSize[0] * ratio;
	canvas.height = scale * this.nativeSize[1] * ratio;

	canvas.style.width  = scale * this.nativeSize[0] + "px";
	canvas.style.height = scale * this.nativeSize[1] + "px";

	this.ratio = ratio;

	this.draw();
}


/** Returns whether a given layer is visible or not */
EagleCanvas.prototype.isLayerVisible = function (layerId) {
	return this.visibleLayers[layerId] ? true : false;
}

/** Turns a layer on or off */
EagleCanvas.prototype.setLayerVisible = function (layerId, on) {
	if (this.isLayerVisible(layerId) == on) { return; }
	this.visibleLayers[layerId] = on ? true : false;
	this.draw();
}

/** Returns whether the board is flipped (bottom at fromt) or not */
EagleCanvas.prototype.isBoardFlipped = function () {
	return this.boardFlipped;
}

/** Turns top or bottom to the front */
EagleCanvas.prototype.setBoardFlipped = function (flipped) {
	if (this.boardFlipped == flipped) { return; }
	this.boardFlipped = flipped ? true : false;
	this.draw();
}

EagleCanvas.prototype.setHighlightedItem = function(item) {
	this.highlightedItem = item;
	this.draw();
}

// ---------------
// --- PARSERS ---
// ---------------

EagleCanvas.EagleParser = function (board) {
	// TODO: move all parsing to the new class
	return board;
}

EagleCanvas.parsers = [
	EagleCanvas.EagleParser
];

if ("KicadNewParser" in window) {
	EagleCanvas.parsers.push (window.KicadNewParser);
}

EagleCanvas.EagleParser.supports = function (text) {
	if (text.match (/\<\?xml/) && text.match (/\<eagle/)) return true;
}

EagleCanvas.EagleParser.name = "eagle brd";


EagleCanvas.prototype.loadText = function (text) {
	this.text = text;

	EagleCanvas.parsers.some (function (parser) {
		if (!parser) return;

		if (parser.supports (text)) {
			console.log (parser.name, "can parse this file");
			var parser = new parser (this);
			parser.parse (text);
			return true;
		}
	}, this)

	this.nativeBounds = this.calculateBounds();
	this.nativeSize   = [this.nativeBounds[2]-this.nativeBounds[0],this.nativeBounds[3]-this.nativeBounds[1]];
	this.scaleToFit();
}


// ---------------
// --- LOADING ---
// ---------------

EagleCanvas.prototype.loadURL = function(url, cb) {
	this.url = url;
	var request = new XMLHttpRequest(),
			self = this;
	request.open('GET', this.url, true);
    request.onreadystatechange = function () {
        if (request.readyState == 4) {
        	self.loadText(request.responseText);
					cb(self)
	    }
	};
	request.send(null);
};

// ---------------
// --- PARSING ---
// ---------------

EagleCanvas.prototype.parse = function (text) {
	var parser = new DOMParser ();
	var boardXML = parser.parseFromString (this.text,"text/xml");
	this.parseDOM (boardXML)
}
<commit_msg>fixed issue when callback not defined<commit_after>(function (root, factory) {
	if(typeof define === "function" && define.amd) {
		define(function(){
			return factory();
		});
	} else if(typeof module === "object" && module.exports) {
		module.exports = factory();
	} else {
		root.EagleCanvas = factory();
	}
}(this, function () {

var p = function(o){ console.log(o) }
// -----------------------
// --- ENUMS, DEFAULTS ---
// -----------------------

EagleCanvas.LayerId = {
	'BOTTOM_COPPER' : 1,
	'BOTTOM_SILKSCREEN' : 2,
	'BOTTOM_DOCUMENTATION' : 3,
	'DIM_BOARD' : 4,
	'TOP_COPPER' : 5,
	'TOP_SILKSCREEN' : 6,
	'TOP_DOCUMENTATION' : 7,
	'VIAS' : 8,
	'OUTLINE' : 9
}

EagleCanvas.LARGE_NUMBER = 99999;

EagleCanvas.prototype.scale = 25;
EagleCanvas.prototype.minScale = 2.5;
EagleCanvas.prototype.maxScale = 250;
EagleCanvas.prototype.minLineWidth = 0.05;
EagleCanvas.prototype.boardFlipped = false;
EagleCanvas.prototype.dimBoardAlpha = 0.7;

// -------------------
// --- CONSTRUCTOR ---
// -------------------

function EagleCanvas(canvasSelector) {
	this.canvasSelector = canvasSelector;

	this.visibleLayers = {};
	this.visibleLayers[EagleCanvas.LayerId.BOTTOM_COPPER]        = true;
	this.visibleLayers[EagleCanvas.LayerId.BOTTOM_SILKSCREEN]    = true;
	this.visibleLayers[EagleCanvas.LayerId.BOTTOM_DOCUMENTATION] = true;
	this.visibleLayers[EagleCanvas.LayerId.DIM_BOARD]            = true;
	this.visibleLayers[EagleCanvas.LayerId.TOP_COPPER]           = true;
	this.visibleLayers[EagleCanvas.LayerId.TOP_SILKSCREEN]       = true;
	this.visibleLayers[EagleCanvas.LayerId.TOP_DOCUMENTATION]    = true;
	this.visibleLayers[EagleCanvas.LayerId.VIAS]                 = true;
	this.visibleLayers[EagleCanvas.LayerId.OUTLINE]              = true;

	this.renderLayerOrder = [];
	this.renderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_DOCUMENTATION);
	this.renderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_SILKSCREEN);
	this.renderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_COPPER);
	this.renderLayerOrder.push(EagleCanvas.LayerId.DIM_BOARD);
	this.renderLayerOrder.push(EagleCanvas.LayerId.OUTLINE);
	this.renderLayerOrder.push(EagleCanvas.LayerId.TOP_COPPER);
	this.renderLayerOrder.push(EagleCanvas.LayerId.VIAS);
	this.renderLayerOrder.push(EagleCanvas.LayerId.TOP_SILKSCREEN);
	this.renderLayerOrder.push(EagleCanvas.LayerId.TOP_DOCUMENTATION);

	this.reverseRenderLayerOrder = [];
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.TOP_DOCUMENTATION);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.TOP_SILKSCREEN);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.TOP_COPPER);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.DIM_BOARD);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.OUTLINE);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_COPPER);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.VIAS);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_SILKSCREEN);
	this.reverseRenderLayerOrder.push(EagleCanvas.LayerId.BOTTOM_DOCUMENTATION);

	this.layerRenderFunctions = {};
	
	this.layerRenderFunctions[EagleCanvas.LayerId.BOTTOM_COPPER] = function(that,ctx) {
		that.drawSignalWires(that.eagleLayersByName['Bottom'],ctx);
		that.drawElements(that.eagleLayersByName['Bottom'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['Bottom'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.BOTTOM_SILKSCREEN] = function(that,ctx) {
		that.drawElements(that.eagleLayersByName['bNames'],ctx);
		that.drawElements(that.eagleLayersByName['bValues'],ctx);
		that.drawElements(that.eagleLayersByName['bPlace'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['bNames'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['bValues'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.BOTTOM_DOCUMENTATION] = function(that,ctx) {
		that.drawElements(that.eagleLayersByName['bKeepout'],ctx);
		that.drawElements(that.eagleLayersByName['bDocu'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['bKeepout'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['bDocu'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.TOP_COPPER] = function(that,ctx) {
		that.drawSignalWires(that.eagleLayersByName['Top'],ctx);
		that.drawElements   (that.eagleLayersByName['Top'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['Top'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.TOP_SILKSCREEN] = function(that,ctx) {
		that.drawElements(that.eagleLayersByName['tNames'],ctx);
		that.drawElements(that.eagleLayersByName['tValues'],ctx);
		that.drawElements(that.eagleLayersByName['tPlace'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['tNames'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['tValues'],ctx);

	}

	this.layerRenderFunctions[EagleCanvas.LayerId.TOP_DOCUMENTATION] = function(that,ctx) {
		that.drawElements(that.eagleLayersByName['tKeepout'],ctx);
		that.drawElements(that.eagleLayersByName['tDocu'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['tKeepout'],ctx);
		that.drawPlainTexts(that.eagleLayersByName['tDocu'],ctx);
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.DIM_BOARD] = function(that,ctx) {
		that.dimCanvas(ctx,that.dimBoardAlpha);
	}	

	this.layerRenderFunctions[EagleCanvas.LayerId.VIAS] = function(that,ctx) {
		that.drawSignalVias('1-16',ctx, that.viaPadColor());
	}

	this.layerRenderFunctions[EagleCanvas.LayerId.OUTLINE] = function(that,ctx) {
		that.drawPlainWires(that.eagleLayersByName['Dimension'],ctx);
		that.drawPlainHoles(that.eagleLayersByName['Dimension'],ctx);
	}

	this.hitTestFunctions = {};

	this.hitTestFunctions[EagleCanvas.LayerId.BOTTOM_COPPER] = function(x,y) {
		return this.hitTestElements (this.eagleLayersByName['Bottom'],x,y)
			|| this.hitTestSignals  (this.eagleLayersByName['Bottom'],x,y);
	}.bind (this);

	this.hitTestFunctions[EagleCanvas.LayerId.TOP_COPPER] = function(x,y) {
		return this.hitTestElements (this.eagleLayersByName['Top'],x,y)
			|| this.hitTestSignals  (this.eagleLayersByName['Top'],x,y);
	}.bind (this);


}


// -------------------------
// --- GENERIC ACCESSORS ---
// -------------------------

/** sets an element id to which the drawing should be initially scaled */
EagleCanvas.prototype.setScaleToFit = function(elementSelector) {
	this.scaleToFitSelector = elementSelector;
}

EagleCanvas.prototype.getScale = function(scale) {
	return this.scale;
}

/** sets the scale factor, triggers resizing and redrawing */
EagleCanvas.prototype.setScale = function(scale) {
	this.scale = scale;
	var canvas = document.querySelector (this.canvasSelector);
	var context = canvas.getContext('2d'),
		devicePixelRatio = window.devicePixelRatio || 1,
		backingStoreRatio =
			context.webkitBackingStorePixelRatio ||
			context.mozBackingStorePixelRatio ||
			context.msBackingStorePixelRatio ||
			context.oBackingStorePixelRatio ||
			context.backingStorePixelRatio || 1,
		ratio = devicePixelRatio / backingStoreRatio;

	canvas.width  = scale * this.nativeSize[0] * ratio;
	canvas.height = scale * this.nativeSize[1] * ratio;

	canvas.style.width  = scale * this.nativeSize[0] + "px";
	canvas.style.height = scale * this.nativeSize[1] + "px";

	this.ratio = ratio;

	this.draw();
}


/** Returns whether a given layer is visible or not */
EagleCanvas.prototype.isLayerVisible = function (layerId) {
	return this.visibleLayers[layerId] ? true : false;
}

/** Turns a layer on or off */
EagleCanvas.prototype.setLayerVisible = function (layerId, on) {
	if (this.isLayerVisible(layerId) == on) { return; }
	this.visibleLayers[layerId] = on ? true : false;
	this.draw();
}

/** Returns whether the board is flipped (bottom at fromt) or not */
EagleCanvas.prototype.isBoardFlipped = function () {
	return this.boardFlipped;
}

/** Turns top or bottom to the front */
EagleCanvas.prototype.setBoardFlipped = function (flipped) {
	if (this.boardFlipped == flipped) { return; }
	this.boardFlipped = flipped ? true : false;
	this.draw();
}

EagleCanvas.prototype.setHighlightedItem = function(item) {
	this.highlightedItem = item;
	this.draw();
}

// ---------------
// --- PARSERS ---
// ---------------

EagleCanvas.EagleParser = function (board) {
	// TODO: move all parsing to the new class
	return board;
}

EagleCanvas.parsers = [
	EagleCanvas.EagleParser
];

if ("KicadNewParser" in window) {
	EagleCanvas.parsers.push (window.KicadNewParser);
}

EagleCanvas.EagleParser.supports = function (text) {
	if (text.match (/\<\?xml/) && text.match (/\<eagle/)) return true;
}

EagleCanvas.EagleParser.name = "eagle brd";


EagleCanvas.prototype.loadText = function (text) {
	this.text = text;

	EagleCanvas.parsers.some (function (parser) {
		if (!parser) return;

		if (parser.supports (text)) {
			console.log (parser.name, "can parse this file");
			var parser = new parser (this);
			parser.parse (text);
			return true;
		}
	}, this)

	this.nativeBounds = this.calculateBounds();
	this.nativeSize   = [this.nativeBounds[2]-this.nativeBounds[0],this.nativeBounds[3]-this.nativeBounds[1]];
	this.scaleToFit();
}


// ---------------
// --- LOADING ---
// ---------------

EagleCanvas.prototype.loadURL = function (url, cb) {
	this.url = url;
	var request = new XMLHttpRequest(),
		self = this;
	request.open('GET', this.url, true);
	request.onreadystatechange = function () {
		if (request.readyState == 4) {
			self.loadText(request.responseText);
			cb && cb(self);
		}
	};
	request.send(null);
};

// ---------------
// --- PARSING ---
// ---------------

EagleCanvas.prototype.parse = function (text) {
	var parser = new DOMParser ();
	var boardXML = parser.parseFromString (this.text,"text/xml");
	this.parseDOM (boardXML)
}

{'fraction_non_alphanumeric': 0.1621157746918396, 'fraction_numerical': 0.004264835907837937, 'mean_word_length': 4.612375948628138, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, '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': '1946218', 'n_tokens_mistral': 6997, 'n_tokens_neox': 6656, 'n_words': 861}