将文档中的标题列表解析为已排序的树

时间:2017-06-22 20:29:22

标签: javascript jquery dom recursion

我正在尝试解析标题列表(h1h2等),以便在结构良好的javascript变量中获取内容表(有点像树)。

以下是我的文档结构:

<div id="content">
    <h1>The content</h1>blah
    <h2 class="show-in-toc">Test 1</h2>
    <h3 class="show-in-toc">Test 1.1</h3>
    <h3 class="show-in-toc">Test 1.2</h3>
    <h4 class="show-in-toc">Test 1.2.1</h4>
    <h4 class="show-in-toc">Test 1.2.2</h4>
    <h2 class="show-in-toc">Test 2</h2>
    <h3 class="show-in-toc">Test 2.1</h3>
    <h4 class="show-in-toc">Test 2.1.1</h4>
    <h3 class="show-in-toc">Test 2.2</h3>
</div>

这就是我想要的:

[
    {"text": "Test 1","level": 2, "children": [
        {"text": "Test 1.1","level": 3,"children": []},
        {"text": "Test 1.2", "level": 3, "children": [
            {"text": "Test 1.2.1", "level": 4, "children": []},
            {"text": "Test 1.2.2", "level": 4, "children": []}
        ]}
    ]},
    {"text": "Test 2", "level": 2, "children": [
        {"text": "Test 2.1", "level": 3, "children": [
            {"text": "Test 2.1.1", "level": 4, "children": []}
        ]},
        {"text": "Test 2.2", "level": 3, "children": []}
    ]}
]

我猜这个函数应该是递归的,看起来像这样:

headings = $('.show-in-toc:header'); // Maybe .toArray() ?
toc = generateToc(headings, 2); // With 2 being the starting level

我尝试激发算法from this subject,但我没有得到任何结果(他们直接将结果放入dom元素中)。

你有什么建议可以指导我吗?提前谢谢

1 个答案:

答案 0 :(得分:0)

我终于设法做了我想要的算法,感谢那些给我一点提示的评论。在这里the result on a JSFiddle,我会解释它并稍后对其进行评论,即使它很容易理解。

function headerTagToObject(tag, level) {
    tag = $(tag);
    return {
        'title': tag.text(),
        'level': level,
        'children': []
    }
}

function generateToc(level, filter = undefined, initial_parent = undefined, parent = undefined) {
    var result, tags;
    result = [];
    if (parent) {
        tags = $(parent).nextUntil('h' + (level - 1), 'h' + level).filter(filter);
    } else {
        if (initial_parent) {
            tags = $(initial_parent).find('h' + level).filter(filter);
        } else {
            tags = $('h' + level).filter(filter);
        }

    }

    tags.each(function(i, tag) {
        var tagResult;
        tagResult = headerTagToObject(tag, level);
        tagResult['children'] = generateToc(level + 1, filter, initial_parent, tag);
        result.push(tagResult);
    });
    return result;
}

// Usage
result = generateToc(2, '.show-in-toc', '#content');