diff --git a/source/Ox/js/JavaScript.js b/source/Ox/js/JavaScript.js index d39d2b5a..8eb8d1ea 100644 --- a/source/Ox/js/JavaScript.js +++ b/source/Ox/js/JavaScript.js @@ -195,13 +195,12 @@ Ox.doc = (function() { } }); blocks.forEach(function(block, i) { - var item, lastItem, + var item, lastItem, lastToken, lines = block .replace(re.script, encodeLinebreaks) .replace(re.test, encodeLinebreaks) .split('\n'), - parent, - tree = parseTree(lines); + parent, tree = parseTree(lines); if (re.item.test(tree.line)) { // parse the tree's root node item = parseNode(tree); @@ -211,13 +210,13 @@ Ox.doc = (function() { } if (/^[A-Z]/.test(item.name)) { // main item - // include leading whitespace + // remove leading linebreaks and whitespace item.source = parseTokens(tokens[i]); item.line = item.source[0].line; items.push(item); } else { - // property of a function item - lastItem = items[items.length - 1]; + // property of an item + lastItem = Ox.last(items); parent = lastItem.types[0] == 'function' && lastItem.returns && lastItem.returns[0].types[0] == 'object' @@ -229,8 +228,16 @@ Ox.doc = (function() { ) { parent.order.push('properties'); } - // include leading linebreaks and whitespace + // add a linebreak, and the property's source without + // leading whitespace, to the last item's source + lastToken = Ox.last(lastItem.source); lastItem.source = lastItem.source.concat( + { + column: lastToken.column + lastToken.value.length, + line: lastToken.line, + type: 'linebreak', + value: '\n' + }, parseTokens(tokens[i], true) ); } @@ -248,36 +255,31 @@ Ox.doc = (function() { expected: lines[1].trim() }; } - function parseTokens(tokens, includeLeadingLinebreaks) { - var isLeading = true, - isTrailing = false, - tokens_ = [], + function parseTokens(tokens, includeLeading) { + // removes leading and trailing linebreaks and whitespace + var start = 0, stop = tokens.length, types = ['linebreak', 'whitespace']; - tokens.forEach(function(token) { - if (isLeading && types.indexOf(token.type) > -1) { - if (token.type == 'linebreak') { - if (includeLeadingLinebreaks) { - tokens_.push(token); - } else { - tokens_ = []; - } - } else { - tokens_.push(token); - } - } else { - tokens_.push(token); - isLeading = false; - if (types.indexOf(token.type) == -1) { - isTrailing = true; - } + if (includeLeading) { + // for properties, whose tokens belong to the main item, we only + // remove leading whitespace + while (tokens[start].type == 'whitespace') { + start++; } - }); - if (isTrailing) { - while (types.indexOf(tokens_[tokens_.length - 1].type) > -1) { - tokens_.pop(); + } else { + // remove leading linebreaks and whitespace + while (types.indexOf(tokens[start].type) > -1) { + start++; + } + // but keep leading whitespace in the first significant line + while (start && tokens[start - 1].type == 'whitespace') { + start--; } } - return tokens_; + // remove trailing linebreaks and whitespace + while (stop > start && types.indexOf(tokens[stop - 1].type) > -1) { + stop--; + } + return tokens.slice(start, stop); } function parseTree(lines) { // parses indented lines into a tree structure, like