首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PageDown通过ScriptEngine错误地解析Markdown

PageDown通过ScriptEngine错误地解析Markdown
EN

Stack Overflow用户
提问于 2015-09-09 13:04:48
回答 1查看 181关注 0票数 5

我试图在客户端使用PageDown作为编辑器,并在服务器端将其解析为HTML。

它似乎在客户端运行良好,但在服务器端,滴答号只是“编码”后面的字符,而不是它包装的单词。所以如果我这么做

test `test` test

我期望这一点,而这正是我在客户端得到的结果:

test <code>test</code> test

但在服务器端,我最终得到的结果是:

test <code>t</code>est<code> </code>test

我创建了一个名为pageDown.js的文件,它简单地将Markdown.Converter.jsMarkdown.Sanitizer.js组合成一个文件,并添加了以下函数:

代码语言:javascript
复制
function getSanitizedHtml(pagedown){
    var converter =  new Markdown.getSanitizingConverter();
    return converter.makeHtml(pagedown);
}

在客户端,我可以这样使用这个文件:

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
<script src="pageDown.js"></script>
<script>
function convert(){

    var html = getSanitizedHtml("test `test` test");

    console.log(html);

    document.getElementById("content").innerHTML = html;
}

</script>
</head>

<body onload="convert()">
<p id="content"></p>
</body>
</html>

正确显示:<p>test <code>test</code> test</p>

在(Java)服务器端,我通过Java的ScriptEngineManagerInvocable使用相同的文件

代码语言:javascript
复制
import java.io.InputStreamReader;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class PageDownTest{

    public static void main(String... args){

        try{
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName("JavaScript");
            engine.eval(new InputStreamReader(PageDownTest.class.getResourceAsStream("pageDown.js")));
            Invocable inv = (Invocable) engine;
            String s = String.valueOf(inv.invokeFunction("getSanitizedHtml", "test `test` test"));
            System.out.println(s);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}

该程序打印出以下内容:<p>test <code>t</code>est<code></code>test</p>

我发现其他标记也存在类似的问题:test **test** test只是忽略了**部分。但是,##test正确地返回为<h2>test</h2>

如果我直接通过JavaScript访问,这一切都很好,但是当我通过Java时就不行了。这里发生了什么事?我应该以不同的方式处理服务器上的Markdown吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-12 17:12:34

我设法将问题简化为以下代码:

代码语言:javascript
复制
function getSanitizedHtml(text)
{
    return text.replace(/(a)(?!b)\1/gm, 'c');
}

在浏览器中调用为

代码语言:javascript
复制
getSanitizedHtml('aa');

它返回:

代码语言:javascript
复制
c

当从纳什霍恩引擎调用时

代码语言:javascript
复制
String s = String.valueOf(inv.invokeFunction("getSanitizedHtml", "aa"));

它返回:

代码语言:javascript
复制
cc

在我看来,这类似于反向引用\1,它应该指向(a),而不是指向(?!b),其捕获的内容为零长度,因此匹配任何内容。

Java中的等效代码:

代码语言:javascript
复制
System.out.println(("aa").replaceAll("(a)(?!b)\\1", "c"));

返回正确的结果:

代码语言:javascript
复制
c

结论

我很确定这是纳什霍恩引擎里的窃听器。

我提交了一个错误报告,如果它公开的话,我会在这里张贴它的ID。

至于您的问题,我认为您唯一的选择是切换到不同的JavaScript环境,至少是暂时的。

最小的、可运行的示例

浏览器中的JS:

代码语言:javascript
复制
function x(s){return s.replace(/(a)(?!b)\1/gm, 'c');}
document.write(x('aa'));

纳什霍恩引擎的JS:

[ 艾德龙 ]

纯Java:

[ 艾德龙 ]

可能修复

如前所述,您的唯一选择(此时)是切换到另一个JavaScript环境。

其中有很多可用的,维基百科也有比较页。对于这个例子,我选择了io.js (我相信您将设法自己安装它)。

如果要使用pageDown.js文件,首先需要注释掉exports检查并使用普通的旧变量,如下所示:

代码语言:javascript
复制
/*if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (e.g. Node.js) module
    Markdown = exports;
else*/
    Markdown = {};

代码语言:javascript
复制
/*if (typeof exports === "object" && typeof require === "function") { // we're in a CommonJS (e.g. Node.js) module
    output = exports;
    Converter = require("./Markdown.Converter").Converter;
} else {*/
    output = Markdown;
    Converter = output.Converter;
//}

(请注意,我还将output = window.Markdown;更改为output = Markdown; --您一定也这样做了(否则纳什霍恩会给您一个错误),但只是忘了在您的问题中提到这一点。

或者,您当然可以使用导出系统和单独的文件,但是我没有这方面的经验,所以我会这样做。

现在,io.js接受stdin中的JavaScript代码,您可以通过process.stdout.write()写入stdout,因此我们可以执行以下操作(在命令行上):

代码语言:javascript
复制
{ cat pageDown.js; echo 'process.stdout.write(getSanitizedHtml("test `test` test"));'; } | iojs;

我们会得到以下信息:

代码语言:javascript
复制
<p>test <code>test</code> test</p>

如果您需要使用Java来完成这个任务,您可以这样做:

代码语言:javascript
复制
import java.io.*;

class Test
{
    public static void main(String[] args) throws Exception
    {
        Process p = Runtime.getRuntime().exec("/path/to/iojs");
        OutputStream stdin = p.getOutputStream();
        InputStream stdout = p.getInputStream();
        File file = new File("/path/to/pageDown.js");
        byte[] b = new byte[(int)file.length()];
        FileInputStream in = new FileInputStream(file);
        for(int read = 0; read < b.length; read += in.read(b, read, b.length - read)); // <-- note the semicolon
        stdin.write(b);
        stdin.write("process.stdout.write(getSanitizedHtml('test `test` test'));".getBytes());
        stdin.close(); // <-- important to close
        p.waitFor();
        b = new byte[stdout.available()];
        stdout.read(b);
        System.out.println(new String(b));
    }
}

注意在for之后直接使用分号(所以它每次只执行read += in.read(b, read, b.length - read),其他什么都不做),还请注意,虽然在流上调用.close()通常是可选的,因为当对象超出作用域时将自动执行,所以必须在这里调用stdin.close(),否则iojs将继续等待输入,p.waitFor()将永远不会返回。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32480370

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档