PageDown 通过 ScriptEngine 错误解析 Markdown
PageDown through ScriptEngine incorrectly parsing Markdown
我正在尝试在客户端使用 PageDown 作为编辑器,然后在服务器端将 Markdown 解析为 HTML。
它在客户端似乎工作正常,但在服务器端,刻度线只是 "codifying" 后面的字符,而不是它包裹的单词。所以如果我这样做:
test `test` test
我期待这一点,这确实是我在客户端得到的:
test <code>test</code> test
但在服务器端,我最终得到的是:
test <code>t</code>est<code> </code>test
我创建了一个名为 pageDown.js
的文件,它只是 Markdown.Converter.js
and Markdown.Sanitizer.js
组合成一个文件,并添加了此功能:
function getSanitizedHtml(pagedown){
var converter = new Markdown.getSanitizingConverter();
return converter.makeHtml(pagedown);
}
在客户端,我可以像这样使用这个文件:
<!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 的 ScriptEngineManager
和 Invocable
:
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>
我看到其他 markdown 有类似的问题:test **test** test
只是忽略了 **
部分。但是,##test
正确地 returns 为 <h2>test</h2>
。
如果我直接通过 HTML 转到 Java 脚本,这一切都很好,但当我通过 Java 时就不行了。这里发生了什么?我应该以不同方式处理服务器上的 Markdown 吗?
我设法将问题简化为以下代码:
function getSanitizedHtml(text)
{
return text.replace(/(a)(?!b)/gm, 'c');
}
在浏览器中调用时为
getSanitizedHtml('aa');
它returns:
c
从 Nashorn 引擎调用时
String s = String.valueOf(inv.invokeFunction("getSanitizedHtml", "aa"));
它returns:
cc
对我来说,这看起来像反向引用 </code>,它应该指向 <code>(a)
,而不是指向 (?!b)
,其捕获的内容是零长度的,因此可以匹配任何内容。
Java中的等效代码:
System.out.println(("aa").replaceAll("(a)(?!b)\1", "c"));
return 正确的结果是:
c
结论
我很确定这是 Nashorn 引擎中的错误。
我提交了一份错误报告,如果它 public.
会在此处 post 它的 ID
至于你的问题,我认为你唯一的选择是切换到不同的Java脚本环境,至少是暂时的。
最小的可运行示例
浏览器中的JS:
function x(s){return s.replace(/(a)(?!b)/gm, 'c');}
document.write(x('aa'));
Nashorn 引擎中的 JS:
[Ideone]
纯Java:
[Ideone]
可能的修复
如前所述,您唯一的选择(此时)是切换到另一个 Java脚本环境。
有很多可用的,维基百科有 a comparison page. For this example, I've chosen io.js(我相信你会设法自己安装它)。
如果您想使用 pageDown.js 文件,您首先需要注释掉 exports
检查并使用普通的旧变量,如下所示:
/*if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (e.g. Node.js) module
Markdown = exports;
else*/
Markdown = {};
和
/*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;
- 你一定也做了同样的事情(否则 Nashorn 会给你一个错误),但只是忘了在你的问题中提到这一点。 )
或者,您当然可以使用导出系统和单独的文件,但我没有这方面的经验,所以我会这样做。
现在,io.js 接受来自标准输入的 Java 脚本代码,您可以通过 process.stdout.write()
写入标准输出,因此我们可以执行以下操作(在命令行上):
{ cat pageDown.js; echo 'process.stdout.write(getSanitizedHtml("test `test` test"));'; } | iojs;
我们得到以下结果:
<p>test <code>test</code> test</p>
如果您需要从 Java 执行此操作,您可以这样做:
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()
永远不会 return.
我正在尝试在客户端使用 PageDown 作为编辑器,然后在服务器端将 Markdown 解析为 HTML。
它在客户端似乎工作正常,但在服务器端,刻度线只是 "codifying" 后面的字符,而不是它包裹的单词。所以如果我这样做:
test `test` test
我期待这一点,这确实是我在客户端得到的:
test <code>test</code> test
但在服务器端,我最终得到的是:
test <code>t</code>est<code> </code>test
我创建了一个名为 pageDown.js
的文件,它只是 Markdown.Converter.js
and Markdown.Sanitizer.js
组合成一个文件,并添加了此功能:
function getSanitizedHtml(pagedown){
var converter = new Markdown.getSanitizingConverter();
return converter.makeHtml(pagedown);
}
在客户端,我可以像这样使用这个文件:
<!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 的 ScriptEngineManager
和 Invocable
:
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>
我看到其他 markdown 有类似的问题:test **test** test
只是忽略了 **
部分。但是,##test
正确地 returns 为 <h2>test</h2>
。
如果我直接通过 HTML 转到 Java 脚本,这一切都很好,但当我通过 Java 时就不行了。这里发生了什么?我应该以不同方式处理服务器上的 Markdown 吗?
我设法将问题简化为以下代码:
function getSanitizedHtml(text)
{
return text.replace(/(a)(?!b)/gm, 'c');
}
在浏览器中调用时为
getSanitizedHtml('aa');
它returns:
c
从 Nashorn 引擎调用时
String s = String.valueOf(inv.invokeFunction("getSanitizedHtml", "aa"));
它returns:
cc
对我来说,这看起来像反向引用 </code>,它应该指向 <code>(a)
,而不是指向 (?!b)
,其捕获的内容是零长度的,因此可以匹配任何内容。
Java中的等效代码:
System.out.println(("aa").replaceAll("(a)(?!b)\1", "c"));
return 正确的结果是:
c
结论
我很确定这是 Nashorn 引擎中的错误。
我提交了一份错误报告,如果它 public.
至于你的问题,我认为你唯一的选择是切换到不同的Java脚本环境,至少是暂时的。
最小的可运行示例
浏览器中的JS:
function x(s){return s.replace(/(a)(?!b)/gm, 'c');}
document.write(x('aa'));
Nashorn 引擎中的 JS:
[Ideone]
纯Java:
[Ideone]
可能的修复
如前所述,您唯一的选择(此时)是切换到另一个 Java脚本环境。
有很多可用的,维基百科有 a comparison page. For this example, I've chosen io.js(我相信你会设法自己安装它)。
如果您想使用 pageDown.js 文件,您首先需要注释掉 exports
检查并使用普通的旧变量,如下所示:
/*if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (e.g. Node.js) module
Markdown = exports;
else*/
Markdown = {};
和
/*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;
- 你一定也做了同样的事情(否则 Nashorn 会给你一个错误),但只是忘了在你的问题中提到这一点。 )
或者,您当然可以使用导出系统和单独的文件,但我没有这方面的经验,所以我会这样做。
现在,io.js 接受来自标准输入的 Java 脚本代码,您可以通过 process.stdout.write()
写入标准输出,因此我们可以执行以下操作(在命令行上):
{ cat pageDown.js; echo 'process.stdout.write(getSanitizedHtml("test `test` test"));'; } | iojs;
我们得到以下结果:
<p>test <code>test</code> test</p>
如果您需要从 Java 执行此操作,您可以这样做:
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()
永远不会 return.