diff options
Diffstat (limited to 'js/lib/blocks.js')
-rw-r--r-- | js/lib/blocks.js | 127 |
1 files changed, 44 insertions, 83 deletions
diff --git a/js/lib/blocks.js b/js/lib/blocks.js index 786c099..cc2263a 100644 --- a/js/lib/blocks.js +++ b/js/lib/blocks.js @@ -1,3 +1,5 @@ +Node = require('./node'); + var C_GREATERTHAN = 62; var C_SPACE = 32; var C_OPEN_BRACKET = 91; @@ -48,19 +50,14 @@ var reHrule = /^(?:(?:\* *){3,}|(?:_ *){3,}|(?:- *){3,}) *$/; // These are methods of a DocParser object, defined below. var makeBlock = function(tag, start_line, start_column) { - return { t: tag, - open: true, - last_line_blank: false, - start_line: start_line, - start_column: start_column, - end_line: start_line, - children: [], - parent: null, - // string_content is formed by concatenating strings, in finalize: - string_content: "", - strings: [], - children: [] - }; + var b = new Node(tag); + b.pos.start = [start_line, start_column]; + b.pos.end = []; // assigned in finalization step + b.open = true; + b.last_line_blank = false; + b.string_content = ""; + b.strings = []; + return b; }; // Returns true if parent block can contain child block. @@ -81,14 +78,17 @@ var acceptsLines = function(block_type) { // Returns true if block ends with a blank line, descending if needed // into lists and sublists. var endsWithBlankLine = function(block) { - if (block.last_line_blank) { + while (block) { + if (block.last_line_blank) { return true; + } + if (block.t === 'List' || block.t === 'ListItem') { + block = block.lastChild; + } else { + break; + } } - if ((block.t === 'List' || block.t === 'ListItem') && block.children.length > 0) { - return endsWithBlankLine(block.children[block.children.length - 1]); - } else { - return false; - } + return false; }; // Break out of all containing lists, resetting the tip of the @@ -135,8 +135,7 @@ var addChild = function(tag, line_number, offset) { var column_number = offset + 1; // offset 0 = column 1 var newBlock = makeBlock(tag, line_number, column_number); - this.tip.children.push(newBlock); - newBlock.parent = this.tip; + this.tip.appendChild(newBlock); this.tip = newBlock; return newBlock; }; @@ -190,7 +189,6 @@ var listsMatch = function(list_data, item_data) { var incorporateLine = function(ln, line_number) { var all_matched = true; - var last_child; var first_nonspace; var offset = 0; var match; @@ -210,12 +208,11 @@ var incorporateLine = function(ln, line_number) { // For each containing block, try to parse the associated line start. // Bail out on failure: container will point to the last matching block. // Set all_matched to false if not all containers match. - while (container.children.length > 0) { - last_child = container.children[container.children.length - 1]; - if (!last_child.open) { + while (container.lastChild) { + if (!container.lastChild.open) { break; } - container = last_child; + container = container.lastChild; match = matchAt(/[^ ]/, ln, offset); if (match === -1) { @@ -472,8 +469,8 @@ var incorporateLine = function(ln, line_number) { container.t === 'Header' || container.t === 'FencedCode' || (container.t === 'ListItem' && - container.children.length === 0 && - container.start_line === line_number)); + !container.firstChild && + container.pos.start[0] === line_number)); var cont = container; while (cont.parent) { @@ -537,10 +534,10 @@ var finalize = function(block, line_number) { return 0; } block.open = false; - if (line_number > block.start_line) { - block.end_line = line_number - 1; + if (line_number > block.pos.start[0]) { + block.pos.end = [line_number - 1]; // TODO end column } else { - block.end_line = line_number; + block.pos.end = [line_number]; } switch (block.t) { @@ -584,30 +581,24 @@ var finalize = function(block, line_number) { case 'List': block.tight = true; // tight by default - var numitems = block.children.length; - var i = 0; - while (i < numitems) { - var item = block.children[i]; + var item = block.firstChild; + while (item) { // check for non-final list item ending with blank line: - var last_item = i === numitems - 1; - if (endsWithBlankLine(item) && !last_item) { + if (endsWithBlankLine(item) && item.next) { block.tight = false; break; } // recurse into children of list item, to see if there are // spaces between any of them: - var numsubitems = item.children.length; - var j = 0; - while (j < numsubitems) { - var subitem = item.children[j]; - var last_subitem = j === numsubitems - 1; - if (endsWithBlankLine(subitem) && !(last_item && last_subitem)) { + var subitem = item.firstChild; + while (subitem) { + if (endsWithBlankLine(subitem) && (item.next || subitem.next)) { block.tight = false; break; } - j++; + subitem = subitem.next; } - i++; + item = item.next; } break; @@ -621,45 +612,14 @@ var finalize = function(block, line_number) { // Walk through a block & children recursively, parsing string content // into inline content where appropriate. Returns new object. var processInlines = function(block) { - var newblock = {}; - newblock.t = block.t; - newblock.start_line = block.start_line; - newblock.start_column = block.start_column; - newblock.end_line = block.end_line; - - switch(block.t) { - case 'Paragraph': - newblock.children = - this.inlineParser.parse(block.string_content.trim(), this.refmap); - break; - case 'Header': - newblock.children = - this.inlineParser.parse(block.string_content.trim(), this.refmap); - newblock.level = block.level; - break; - case 'List': - newblock.list_data = block.list_data; - newblock.tight = block.tight; - break; - case 'CodeBlock': - newblock.string_content = block.string_content; - newblock.info = block.info; - break; - case 'HtmlBlock': - newblock.string_content = block.string_content; - break; - default: - break; - } - - if (block.children && !newblock.children) { - var newchildren = []; - for (var i = 0; i < block.children.length; i++) { - newchildren.push(this.processInlines(block.children[i])); + var node, event; + var walker = block.walker(); + while (event = walker.next()) { + node = event.node; + if (!event.entering && (node.t == 'Paragraph' || node.t == 'Header')) { + this.inlineParser.parse(node, this.refmap); } - newblock.children = newchildren; } - return newblock; }; // The main parsing function. Returns a parsed document AST. @@ -675,7 +635,8 @@ var parse = function(input) { while (this.tip) { this.finalize(this.tip, len - 1); } - return this.processInlines(this.doc); + this.processInlines(this.doc); + return this.doc; }; |