使用数组而非对象时返回 {} 而不是 []

问题描述 投票:0回答:3

我有一个程序,它获取 MD 文件中的每一行,然后将其作为每个

\n
行输出为新的 JSON 位。我遇到的问题是我无法获取正确的 JSON 来返回我的数组。被
marked
解析后正常返回在控制台是这样的:

[["<h1>h1 header from md </h1>"]]

我希望我的返回看起来像这样而不使用对象:

{{"<h1>h1 header from md </h1>"}}

注意我通常会有不止一行MD,所以预期的回报应该是这样的:

{{"<h1>hello</h1>"}, {"<h1>world</h1>"}}

我该如何使用数组而不是对象来解决这个问题?

javascript html json
3个回答
2
投票

这里有一个更好、更通用的方法来处理这个问题。此外,它不会像您的那样删除字符串中间的“#”。这依赖于 ### 标头后面必须跟有空格的事实。

function render(md){
    let code = "";

    let mdLines = md.split('\n');

    for(let i = 0; i < mdLines.length; i++){
        
        if(mdLines[i][0] == "#") {
            // We have a header.  How many are there?
            let s = mdLines[i].indexOf(" ")
            if( mdLines[i].slice(0,s) == '#'.repeat(s) )
                code += "<h"+s+">" + mdLines[i].slice(s+1) + "</h"+s+">";
            else
                code += mdLines[i];
        }
        else
            code += mdLines[i];
    };
    
    return code;
}

let text1 = "## he#llo \n there \n # yooo"
let text2 = "# he#llo \n there \n ## yooo"

console.log(render(text1));
console.log(render(text2));

输出:

timr@Tims-NUC:~/src$ node x.js
<h2>he#llo </h2> there  # yooo
<h1>he#llo </h1> there  ## yooo

timr@Tims-NUC:~/src$

跟进

这显然是您想要测试的内容:

let text1 = "## he#llo\nthere\n# yooo"
let text2 = "# he#llo\nthere\n## yooo"

这是输出:

timr@Tims-NUC:~/src$ node x.js
<h2>he#llo</h2>there<h1>yooo</h1>
<h1>he#llo</h1>there<h2>yooo</h2>
timr@Tims-NUC:~/src$

1
投票

如果你正在写的东西做“同样的事情,每一步只改变一件事”,那就是一个循环,或者如果你预见到一种确实需要

if
语句的情况,那么你通常希望这样解决它们您首先处理“最大的事情”(以确保不会失败)或使用
if-else
语句(也因此不会出现失败)。

您可能会考虑使用 switch,但 switch 语句是编程语言的遗留物,这些语言没有字典/键值对象来执行 O(1) 查找,而 JS、Python 等都这样做。因此,在 JS 中,您几乎总是更好地使用映射对象,并将 case 值作为属性键,将带有开关的 O(n) 代码路径转换为 O(1) 立即查找)

但是,在这种情况下,我们真正做的是简单的文本匹配,因此您可以使用工具集中最好的工具来实现:您可以使用正则表达式轻松获取

#
序列和“剩余文本”,并且然后使用捕获的数据生成替换 HTML :

function markdownToHTML(doc) { return convertMultiLineMD(doc.split(`\n`)).join(`\n`); } function convertMultiLineMD(lines) { // convert tables, lists, etc, while also making sure // to perform inline markup conversion for any content // that doesn't span multiple lines. For the purpose of // this answer, we're going to ignore multi-line entirely: return convertInlineMD(lines); } function convertInlineMD(lines) { return lines.map((line) => { // convert headings line = line.replace( // two capture groups, one for the markup, and one for the heading, // with a third optional group so we don't capture EOL whitespace. /^(#+)\s+(.+?)(\s+)?$/, // and we extract the first group's length immediately (_, { length: h }, text) => `<h${h}>${text}</h${h}>` ); // then wrap bare text in <p>, convert bold, italic, etc. etc. return line; }); } // And a simple test based on what you indicated: const docs = [`## he#llo\nthere\n# yooo `, `# he#llo\nthere\n## yooo`]; docs.forEach((doc, i) => console.log(`[doc ${i + 1}]\n`, markdownToHTML(doc)));

但请注意,即使这仍然是编写转译器的一种简单方法,与基于 markdown 语法(“标记语言规范”语法,即规定哪些令牌可以跟随哪些其他令牌的规则),您可以通过跟踪我们正在处理的令牌类型来运行文档,并在我们传递令牌终止时即时转换。

(事实上,这就是正则表达式的工作原理:它们根据您指定的正则语法模式生成 DFA,然后通过该 DFA 运行输入,从而实现近乎完美的运行时性能)

经过不断的请求,我查看了预期的输出,这可能不是最好/最简洁的代码,但它确实有效,并且相当紧凑


1
投票

function render(md) { let code = ""; //For functions return let mdLines = md.split("\n"); const re = /^\s*([#]{1,6})\s/; for (let line of mdLines) { const hash = line.match(re); if (hash) { const h = hash[1].length; line = `<h${h}>${line.replace(re, "").trim()}</h${h}>`; } code += line; } return code; } let text1 = "## he#llo \n there \n # yooo"; let text2 = "# he#llo \n there \n ## yooo"; console.log(render(text1)); console.log(render(text2));

    
© www.soinside.com 2019 - 2024. All rights reserved.