猿问

使用 JavaScript 将纯文本列表转换为 HTML 列表

我经常收到 PDF 格式的文本列表,这些文本列表是分层的(通常是三层深)。我想将它们放入 HTML 列表中,以便它们可以使用 CSS 进行样式设置并变得更美观。由于数据量大,我正在尝试使用 JavaScript 自动化该过程。


示例源数据:

・First Level 1 list item

– First Level 2 list item, which is a subset of the first Level 1 list item.

– Second Level 2 list item, which is a subset of the first Level 1 list item.

♦ First Level 3 list item, which is a subset of the second Level 2 list item.

・Second Level 1 list item.

示例目标:

<ul>

    <li>First Level 1 list item</li>

        <ul>

            <li>First Level 2 list item, which is a subset of the first Level 1 list item.</li>

            <li>Second Level 2 list item, which is a subset of the first Level 1 list item.

                <ul>

                    <li>First Level 3 list item, which is a subset of the second Level 2 list item.</li>

                </ul>

            </li>

        </ul>

    <li>Second Level 1 list item.</li>

</ul>

目前进展:

我已经确定我可以将 1 级列表项与此正则表达式匹配: /^・.+$/gm


并将 2 级列表项与此正则表达式匹配: /^\–.+$/gm


和 3 级: /^♦.+$/gm


或者简单地通过组合这些来一次界定所有列表级别:string.match(/(^・.+$)|(^\–.+$)|(^♦.+$)/gm);


现在知道如何匹配不同类型的项目,我正试图弄清楚如何对它们进行排序。从概念上讲,如果我将它们全部放在一个数组中(让我们在下一个示例中使用简单的颜色编码),那么应该可以创建一个函数来识别模式并在正确的层次结构中创建一个多维数组,然后创建另一个函数在适当的位置输出用 HTML 标记填充的内容。


基于类型将一维数组转换为多维数组的可视化:

假设在上面的简化示例中,我们只有一个对应于颜色的三个字母的字符串 - r、g、b。


所以这可能看起来像: rrgbrgbrgbbrggbr


我一直在试验并试图将这种结构放入多维数组中。


我相信需要低于 3 级的一维来保存实际的文本字符串。并且需要高于 1 级的一个维度来包含每个完整列表。所以像这样的结构:


list

[

    level1

    [

        level2

        [

            level3

            [   

                string

                ["list item text"]

            ]

        ]

    ]

]

在这里,我在弄清楚如何对所有这些进行排序时遇到了一些麻烦。任何帮助表示赞赏。


茅侃侃
浏览 396回答 1
1回答

白猪掌柜的

不需要正则表达式。var log = console.log;var data = `・First Level 1 list item– First Level 2 list item, which is a subset of the first Level 1 list item.– Second Level 2 list item, which is a subset of the first Level 1 list item.♦ First Level 3 list item, which is a subset of the second Level 2 list item.・Second Level 1 list item.`;//split text to array of string. One item per linedata = data.split("\n");var firstChar,prevFirstChar = "";//our output structvar struct = [];var cursor = struct;//we need only one token for return to first levelvar lvl1Key = "・";var prevnode = {};data.forEach(line=>{&nbsp; &nbsp; //get token&nbsp; &nbsp; firstChar = line.charAt(0);&nbsp; &nbsp; let node = {&nbsp; &nbsp; &nbsp; &nbsp; str : line.slice(1),&nbsp; &nbsp; &nbsp; &nbsp; child : []&nbsp; &nbsp; };&nbsp; &nbsp; if (firstChar == lvl1Key) {&nbsp; &nbsp; &nbsp; //return to root&nbsp; &nbsp; &nbsp; cursor = struct;&nbsp; &nbsp; } else if (firstChar != prevFirstChar) {&nbsp; &nbsp; &nbsp; //move up if token change and it is not root token&nbsp; &nbsp; &nbsp; cursor = prevnode.child;&nbsp; &nbsp; }&nbsp; &nbsp; cursor.push(node);&nbsp; &nbsp; prevnode = node;&nbsp; &nbsp; prevFirstChar = firstChar;});log(struct);//Ok, we get struct, convert this to html//offset for formatingconst offsetSize = 2;//recursive function node - array of { str : "string", childs : [nodes]}var toHtml = function(node, offset = "") {&nbsp; &nbsp; var ret = offset + "<ul>\n";&nbsp; &nbsp; offset += " ".repeat(offsetSize);&nbsp; &nbsp; node.forEach(rec=>{&nbsp; &nbsp; &nbsp; &nbsp; ret += offset + "<li>" + rec.str + "</li>\n";&nbsp; &nbsp; &nbsp; &nbsp; //if array not empty add html for childs&nbsp; &nbsp; &nbsp; &nbsp; if (rec.child.length) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret += toHtml(rec.child, offset + " ".repeat(offsetSize));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; });&nbsp; &nbsp; offset = offset.slice(offsetSize);&nbsp; &nbsp; ret += offset + "</ul>\n";&nbsp; &nbsp; return ret;}log(toHtml(struct));
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答