function markdownElement(start, end) {
    if (end === undefined) {
        end = start;
    }
    
    return function() {
        return {start: start, end: end};
    };
}

function markdownLink(attributes) {
    var href = attributes.href || "";
    return {
        start: "[",
        end: "](" + href + ")",
        anchorPosition: "before"
    };
}

function markdownImage(attributes) {
    var src = attributes.src || "";
    var altText = attributes.alt || "";
    if (src || altText) {
        return {start: "![" + altText + "](" + src + ")"};
    } else {
        return {};
    }
}

function markdownList(attributes, list) {
    return {
        start: list.indent > -1 ? "\n" : "",
        end: list.indent > -1 ? "" : "\n"
    };
}

function markdownListItem(attributes, list) {
    list.count++;
    var start = repeatString("\t", Math.max(list.indent, 0)) +
        (list.type === "ul" ? "-" : list.count + ".") + " ";
        
    return {start: start, end: "\n"};
}

// map HTML tags to Markdown syntax
var htmlmarkdown = {
    // paragraphs elements use three line feeds to close
    // this prevents them being caught by collapsing list elements in `asString`
    // while still allowing them to be collapsed when multiple empty lines are removed
    "p": markdownElement("", "\n\n\n"),
    "br": markdownElement("", "  \n"),
    "ul": markdownList,
    "ol": markdownList,
    "li": markdownListItem,
    "strong": markdownElement("**"),
    "em": markdownElement("*"),
    "a": markdownLink,
    "img": markdownImage,
};

(function() {
    for (var i = 1; i <= 6; i++) {
        htmlmarkdown["h" + i] = markdownElement(repeatString("#", i) + " ", "\n\n\n");
    }
})();

function repeatString(value, count) {
    return new Array(count + 1).join(value);
}

function markdownWriter() {
    var fragments = [];
    var elementStack = [];
    var list = {
        indent: -1,
        type: "ul",
        count: 0
    };
    
    function isList(tagName) {
        return tagName === "ul" || tagName === "ol";
    }

    function open(tagName, attributes) {
        attributes = attributes || {};
        
        var idHasBeenWritten = false;
        
        var createElement = htmlmarkdown[tagName] || function() { return {}; };
        var element = createElement(attributes, list);
        elementStack.push({end: element.end, list: list});
        
        if (element.anchorPosition === "before") {
            writeAnchor(attributes);
            idHasBeenWritten = true;
        }

        fragments.push(element.start || "");

        if (isList(tagName)) {
            list = {
                type: tagName,
                indent: list.indent + 1,
                count: 0
            };
        }
        if (!idHasBeenWritten) {
            writeAnchor(attributes);
        }
    }
    
    function writeAnchor(attributes) {
        if (attributes.id) {
            fragments.push('<a id="' + attributes.id + '"></a>');
        }
    }
    
    function close(tagName) {
        var element = elementStack.pop();
        list = element.list;
        fragments.push(element.end || "");
    }
    
    function selfClosing(tagName, attributes) {
        open(tagName, attributes);
        close(tagName);
    }
    
    function text(value) {
        fragments.push(escapeMarkdown(value));
    }
    
    function append(html) {
        fragments.push(html);
    }
    
    function asString() {
        // massage the output to collapse mulitple empty lines and empty lines between nested lists
        return fragments.join("").replace(/\n{2}(\t*)([2-9]\d*\.|- )/g, "\n$1$2").replace(/\n{3,}/g, "\n\n");
    }

    return {
        asString: asString,
        open: open,
        close: close,
        text: text,
        selfClosing: selfClosing,
        append: append
    };
}

exports.writer = markdownWriter;

function escapeMarkdown(value) {
    return value
        .replace(/\\/g, '\\\\')
        .replace(/([\`\*_\{\}\[\]\(\)\#\+\-\.\!])/g, '\\$1');
}

@@ -669,26 +669,25 @@
 st.indent %3E 
--1
+0
  ? %22%5Cn%22 : %22%22
@@ -715,18 +715,17 @@
 ndent %3E 
--1
+0
  ? %22%22 : 
@@ -2108,32 +2108,262 @@
 %7C%7C %7B%7D;%0A        %0A
+        var parentElementList = list;%0A        %0A        if (isList(tagName)) %7B%0A            list = %7B%0A                type: tagName,%0A                indent: list.indent + 1,%0A                count: 0%0A            %7D;%0A        %7D%0A        %0A
         var idHa
@@ -2384,16 +2384,16 @@
  false;%0A
-
         
@@ -2579,17 +2579,30 @@
 , list: 
-l
+parentElementL
 ist%7D);%0A 
@@ -2741,24 +2741,24 @@
 %0A        %7D%0A%0A
+
         frag
@@ -2793,183 +2793,8 @@
 %22%22);
-%0A%0A        if (isList(tagName)) %7B%0A            list = %7B%0A                type: tagName,%0A                indent: list.indent + 1,%0A                count: 0%0A            %7D;%0A        %7D
 %0A   

Handle list state immediately