(function() {
	'use strict';

	require('chai').should();

	var fs = require('fs'),
		extension = require('../src/showdown-htmlescape.js'),
		showdown = require('showdown'),
		converter = new showdown.Converter({
			extensions: [extension]
		}),
		cases = fs.readdirSync('test/cases/')
		.filter(filter())
		.map(map('test/cases/')),
		issues = [];
	// issues = fs.readdirSync('test/issues/')
	//   .filter(filter())
	//   .map(map('test/issues/'));

	/////////////////////////////////////////////////////////////////////////////
	// Test cases
	//
	describe('HTML Escape Extension simple testcases', function() {
		for (var i = 0; i < cases.length; ++i) {
			it(cases[i].name, assertion(cases[i]));
		}
	});

	describe('HTML Escape Extension issues testcase', function() {
		for (var i = 0; i < issues.length; ++i) {
			it(issues[i].name, assertion(issues[i]));
		}
	});

	/////////////////////////////////////////////////////////////////////////////
	// Test cases
	//
	function filter() {
		return function(file) {
			var ext = file.slice(-3);
			return (ext === '.md');
		};
	}

	function map(dir) {
		return function(file) {
			var name = file.replace('.md', ''),
				htmlPath = dir + name + '.html',
				html = fs.readFileSync(htmlPath, 'utf8'),
				mdPath = dir + name + '.md',
				md = fs.readFileSync(mdPath, 'utf8');

			return {
				name: name,
				input: md,
				expected: html
			};
		};
	}

	//Normalize input/output
	function normalize(testCase) {

		// Normalize line returns
		testCase.expected = testCase.expected.replace(/\r/g, '');
		testCase.actual = testCase.actual.replace(/\r/g, '');

		// Ignore all leading/trailing whitespace
		testCase.expected = testCase.expected.split('\n').map(function(x) {
			return x.trim();
		}).join('\n');
		testCase.actual = testCase.actual.split('\n').map(function(x) {
			return x.trim();
		}).join('\n');

		// Remove extra lines
		testCase.expected = testCase.expected.trim();

		// Convert whitespace to a visible character so that it shows up on error reports
		testCase.expected = testCase.expected.replace(/ /g, '·');
		testCase.expected = testCase.expected.replace(/\n/g, '•\n');
		testCase.actual = testCase.actual.replace(/ /g, '·');
		testCase.actual = testCase.actual.replace(/\n/g, '•\n');

		return testCase;

	}

	function assertion(testCase) {
		return function() {
			testCase.actual = converter.makeHtml(testCase.input);
			testCase = normalize(testCase);

			// Compare
			testCase.actual.should.equal(testCase.expected);
		};
	}
})();

@@ -170,80 +170,8 @@
 '),%0A
-%09%09converter = new showdown.Converter(%7B%0A%09%09%09extensions: %5Bextension%5D%0A%09%09%7D),%0A
 %09%09ca
@@ -208,16 +208,17 @@
 es/')%0A%09%09
+%09
 .filter(
@@ -227,16 +227,17 @@
 lter())%0A
+%09
 %09%09.map(m
@@ -1247,17 +1247,247 @@
  'utf8')
-;
+,%0A%09%09%09%09optionsPath = dir + name + '.json',%0A%09%09%09%09options = %7B%7D;%0A%0A%09%09%09try %7B%0A%09%09%09%09options = JSON.parse(fs.readFileSync(optionsPath, 'utf8'));%0A%09%09%09%09options.extensions = %5Bextension%5D;%0A%09%09%09%7D catch (e) %7B%0A%09%09%09%09options.extensions = %5Bextension%5D;%0A%09%09%09%7D
 %0A%0A%09%09%09ret
@@ -1541,16 +1541,38 @@
 ed: html
+,%0A%09%09%09%09options: options
 %0A%09%09%09%7D;%0A%09
@@ -2453,17 +2453,16 @@
 stCase;%0A
-%0A
 %09%7D%0A%0A%09fun
@@ -2485,24 +2485,24 @@
 testCase) %7B%0A
-
 %09%09return fun
@@ -2511,16 +2511,77 @@
 ion() %7B%0A
+%09%09%09var converter = new showdown.Converter(testCase.options);%0A
 %09%09%09testC

Test runner can now parse custom options per test case.