将缩进文本转换为HTML列表的jQuery脚本出错

时间:2013-12-17 01:28:52

标签: javascript jquery html html-lists

我目前正在使用以下脚本将缩进的纯文本转换为HTML列表代码:

jQuery(function($) {
var indentedToHtmlList = function indentedToHtmlList (text, indentChar, folderChar, listType, showIcons) {
  indentChar = indentChar || '\t';
  folderChar = folderChar || ':';
  listType = listType || 'ul';
  showIcons = !!showIcons;

  var lastDepth,
      lines = text.split(/\r?\n/),
      output = '<' + listType + '>\n',
      depthCounter = new RegExp('^(' + indentChar + '*)(.*)');

  for (var i = 0; i < lines.length; i++) {
    var splitted = lines[i].match(depthCounter),
        indentStr = splitted[1],
        fileName = splitted[2],
        currentDepth = (indentStr === undefined) ? 0 : (indentStr.length / indentChar.length),
        isFolder = (fileName.charAt(fileName.length - 1) === folderChar);

    if (isFolder) {
      fileName = fileName.substring(0, fileName.length -1);
    }

    if (lastDepth === currentDepth) {
      output += '</li>\n';
    } else if (lastDepth > currentDepth) {
      while (lastDepth > currentDepth) {
        output += '</li>\n</' + listType + '>\n</li>\n';
        lastDepth--;
      }
    } else if (lastDepth < currentDepth) {
      output += '\n<' + listType + '>\n';
    }

    output += '<li>';
    if (showIcons) {
      output += '<span class=" glyphicon glyphicon-' +
      (isFolder ? 'folder-open' : 'file') +
      '"></span> ';
    }
    output += fileName;

    lastDepth = currentDepth;
  }

  while (lastDepth >= 0) {
    output += '\n</li>\n</' + listType + '>';
    lastDepth--;
  }

  return output;
};

runConvert = function() {
  var originalText = $('#textarea-plain-text').val(),
      listType = $('#list-type').val(),
      showIcons = !!$('#glyph-selector-box').prop('checked'),
      result = indentedToHtmlList(originalText, '\t', ':', listType, showIcons);
  $('#textarea-converted-text').val(result);
  return $('#div-converted-text').html(result);
};

bind = function() {
  return $('#list-conversion-button').click(runConvert);
};

$(bind);
});

脚本输出正确显示的代码,这是花费一段时间注意语法关闭的部分原因。这是一个示例文本,转换后的版本(即脚本的结果),以及转换后的文本的标记版本,显示错误的位置:

  1. Indented plain text sample
  2. Script output
  3. List of errors(由BBEdit检测到)。
  4. Marked up output(已添加错误评论和更正)。
  5. 据我所知,脚本似乎正在插入无关的</li>标记,并在层次结构中的嵌套列表上放置关闭</ul>标记。编辑第一个while循环似乎是</li>问题的解决方案,但是我和另一个开发人员无法弄清楚逻辑在</ul>上出错的地方。< / p>

    这是一个当前已实现脚本的页面(因此您可以生成自己的示例而无需创建页面):Convert Indented/Nested Plain Text to an HTML List

1 个答案:

答案 0 :(得分:1)

这段代码正在构建一个线性字符串,这非常令人困惑且容易出错。没有提到对代码缺乏评论。通过利用jQuery,您可以将元素创建为对象,然后对其进行操作,甚至无需担心标记。我还没有测试下面的代码,它更像是我刚才所说的一个例子:

function indentedToHtmlList (text, indentChar, folderChar, listType, showIcons) {
    indentChar = indentChar || '\t';
    folderChar = folderChar || ':';
    listType = listType || 'ul';
    showIcons = !!showIcons;

    var lines = text.split(/\r?\n/),
        currentLevel = 1,
        rootLevel,
        currentList = rootLevel = $('<' + listType + '/>'),
        previousItem,
        previousLists = [rootLevel];

    for(var i = 0; i < lines.length; i++){

        //split line into array
        var line = lines[i].split(indentChar);

        //handle levels
        if(line.length > currentLevel){
            //add current list to history and create new list
            previousLists.push(currentList);
            currentList = $('<' + listType + '/>');
            previousItem.append(currentList);
            currentLevel++;
        } else if(line.length < currentLevel){
            //get last list from history, until matches current level
            while(line.length < currentLevel){
                currentList = previousLists.pop();
                currentLevel--;
            }
        }

        //create current item
        var itemText = line[line.length - 1];
        var item = $('<li/>').text(itemText);

        //check if is folder
        var isFolder = itemText.charAt(itemText.length - 1) === folderChar;

        //handle icon
        if (showIcons) {
            item.prepend($('<span/>').addClass('glyphicon glyphicon-' + isFolder ? 'folder-open' : 'file'));
        }

        // add item to list
        console.log(currentList);
        currentList.append(item);

        previousItem = item;
    }

    return rootLevel.html();

}

有时只是更快地重写坏代码,而不是找到需要更改的单个字符。在你的情况下,我肯定会改写它......