在服务器端为 ColdFusion 实现 Showdown.js 降价解析器

2022-01-09 00:00:00 parsing markdown coldfusion java

这是一个事实调查"问题,旨在了解使用 showdown.js 解析器. 已经有一个使用 showdown.js 的 java 实现(参见本文末尾的代码),我想看看如何为 ColdFusion 实现它.我没有 Java 方面的经验,我不会特别称自己为程序员",但我不希望这阻止我尝试.

This is a "fact finding" question to see how difficult it would be to create a ColdFusion UDF to parse markdown on the server using the showdown.js parser. There is already a java implementation that utilizes showdown.js (see code at the end of this post) and I want to see how to go about implementing it for ColdFusion. I have no experience in Java and I would not particularly call myself "a programmer," but I don't want this to stop me from trying.

总结

我想在服务器端运行 Shadown.js 以便将 Markdown 转换为 HTML.

I would like to run Shadown.js server-side in order to convert markdown to HTML.

为什么?

保存用户条目的两个版本,一个是 Markdown 格式,另一个是 HTML,允许我们向最终用户显示原始 Markdown 版本,以防他们想要编辑他们的条目.

Saving two versions of a user entry, one in markdown format and another in HTML, allows us to display the raw markdown version to the end user in case they wanted to edit their entry.

为什么不使用服务器端解析器?

有两个原因:

  1. 到目前为止,还没有针对此特定目的的 ColdFusion 降价解析器
  2. 在客户端使用 Showdown.js,然后在服务器端使用不同的解析器,将导致显示给客户端的预览与存储在数据库中的版本之间的标记不一致.鉴于 Markdown 定义松散,大多数解析器实现都会有细微差别.

有一个非常好的博客条目 讨论这个问题.

为什么不在客户端进行所有解析并发布两个版本?

这并不是一个安全的解决方案.我还认为用户可能会使用不匹配的 HTML 发布降价.

This does not strike me as a secure solution. I also think users would potentially be able to post markdown with HTML that does not match.

是否有任何现有的实现?

有 一个名为 CFShowdown 的实现,但它不是为了这个特定目的.相反,它用于处理页面上的输出.上述博客的评论区具有一个名为 David 的用户编写的纯 Java 实现:

There is one implementation called CFShowdown, but it's not for this specific purpose. Rather, it's for handling output on a page. The comments section of the aforementioned blog features a pure Java implementation written by a user called David:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine jsEngine = manager.getEngineByName("js");
try
{
    jsEngine.eval(new InputStreamReader(getClass().getResourceAsStream("showdown.js")));
    showdownConverter = jsEngine.eval("new Showdown.converter()");
}
catch (Exception e)
{
    log.error("could not create showdown converter", e);
}

try
{
    return ((Invocable) jsEngine).invokeMethod(
        showdownConverter, 
        "makeHtml", 
        markdownString
    ) + "";
}
catch (Exception e)
{
    log.error("error while converting markdown to html", e);
    return "[could not convert input]";
}

目标

创建一个 java 类,允许我们将此实现与 ColdFusion UDF 或组件内的自定义标签一起使用,类似于 <cfset html = getMarkdown(string)>

Create a java class that would allow us to use this implementation with a ColdFusion UDF or a custom tag inside a component, something along the lines of <cfset html = getMarkdown(string)>

由于我没有使用 Java 的经验,我想从用户那里获得一些建议和意见,了解从何处以及如何开始执行此任务.我创建了一个

Since I have no experience with Java, I want to get some advice and input from users on where and how to start going about this task. I created a

推荐答案

有文件 摊牌.js 和同一目录中的文件 markdown.txt(如下示例).

Have files showdown.js and a file markdown.txt (example below) in the same directory.

showdown.cfm

<cfscript>
manager = createObject("java", "javax.script.ScriptEngineManager").init();
jsEngine = manager.getEngineByName("js");

showdownJS = fileRead('#getDirectoryFromPath(getCurrentTemplatePath())#/showdown.js');

jsEngine.eval(showdownJS);
showdownConverter = jsEngine.eval("new Showdown.converter()");

markdownString = fileRead("#getDirectoryFromPath(getCurrentTemplatePath())#/markdown.txt");

args = [markdownString];

result = jsEngine.invokeMethod(
    showdownConverter,
    "makeHtml",
    args
) & "";
</cfscript>

ma​​rkdown.txt

Showdown Demo
-------------

You can try out Showdown on this page:

  - Type some [Markdown] text on the left side.
  - See the corresponding HTML on the right.

For a Markdown cheat-sheet, switch the right-hand window from *Preview* to *Syntax Guide*.

Showdown is a JavaScript port of the original Perl version of Markdown.  You can get the full [source code] by clicking on the version number at the bottom of the page.

Also check out [WMD, the Wysiwym Markdown Editor][wmd].  It'll be open source soon; email me at the address below if you'd like to help me test the standalone version.

**Start with a [blank page] or edit this document in the left window.**

  [Markdown]: http://daringfireball.net/projects/markdown/
  [source code]: http://attacklab.net/showdown/showdown-v0.9.zip
  [wmd]: http://wmd-editor.com/
  [blank page]: ?blank=1 "Clear all text"

更新

这是一个采用 Adam Presley 在 Java 中的工作 并且全部在 CFC 中完成.请注意,我把他在 showdown.js 末尾添加的那一点魔法放入一个 CFC 函数中,该函数的返回值被附加(即 showdownAdapterJS()).

Here's a version that takes Adam Presley's work in Java and does it all in a CFC. Note I took that little bit of magic he added at the end of showdown.js and put it into a CFC function whose return value is appended (i.e. showdownAdapterJS()).

氟氯化碳

<cfcomponent output="false" accessors="true">
    <cffunction name="init" output="false" access="public" returntype="Showdown" hint="Constructor">
        <cfset variables.manager = createObject("java", "javax.script.ScriptEngineManager").init()>
        <cfset variables.engine = manager.getEngineByName("javascript")>
        <cfreturn this/>
    </cffunction>

    <cffunction name="toHTML" output="false" access="public" returntype="any" hint="">
        <cfargument name="markdownText" type="string" required="true"/>
        <cfset var local = structNew()/>
        <cfset var bindings = variables.engine.createBindings()>
        <cfset var result = "">

        <cftry>
            <cfset bindings.put("markdownText", arguments.markdownText)>
            <cfset variables.engine.setBindings(bindings, createObject("java", "javax.script.ScriptContext").ENGINE_SCOPE)>
            <cfset var showdownJS = fileRead('#getDirectoryFromPath(getCurrentTemplatePath())#/showdown.js')>
            <cfset showdownJS &= showdownAdapterJS()>
            <cfset result = engine.eval(showdownJS)>
            <cfcatch type="javax.script.ScriptException">
                <cfset result = "The script had an error: " & cfcatch.Message>
            </cfcatch>
        </cftry>

        <cfreturn result>
    </cffunction>

    <cffunction name="showdownAdapterJS" output="false" access="private" returntype="string" hint="">
        <cfset var local = structNew()/>
<cfsavecontent variable="local.javascript">
<cfoutput>#chr(13)##chr(10)#var __converter = new Showdown.converter();
__converter.makeHtml(markdownText);</cfoutput>
</cfsavecontent>
        <cfreturn local.javascript>
    </cffunction>
</cfcomponent>

用法

<cfset showdown = createObject("component", "Showdown").init()>
<cfset markdownString = fileRead("#getDirectoryFromPath(getCurrentTemplatePath())#/markdown.txt")>
<cfoutput>#showdown.toHTML(markdownString)#</cfoutput>

相关文章