Реализация анализатора разметки Showdown.js на стороне сервера для ColdFusion - PullRequest
5 голосов
/ 05 января 2011

Это вопрос «для выяснения фактов», позволяющий понять, насколько сложно было бы создать ColdFusion UDF для анализа уценки на сервере с помощью синтаксического анализатора showdown.js. Уже существует реализация Java, которая используетshowdown.js (см. код в конце этого поста), и я хочу посмотреть, как реализовать его для ColdFusion.У меня нет опыта работы с Java, и я бы не стал называть себя «программистом», но я не хочу, чтобы это мешало мне пытаться.

Резюме

Я хотел бы запустить Shadown.js на стороне сервера для преобразования уценки в HTML.

Почему?

Сохранение двух версийзапись пользователя, одна в формате уценки, а другая в HTML, позволяет нам отображать сырую версию уценки конечному пользователю в случае, если он хочет отредактировать свою запись.

Почему бы не использовать анализатор на стороне сервера?

По двум причинам:

  1. На данный момент нет парсеров уценки ColdFusion для этой конкретной цели
  2. Использование Showdown.js на клиенте-сторона, а затем другой синтаксический анализатор на стороне сервера приведет к несогласованной разметке между предварительным просмотром, отображаемым для клиента, и версией, сохраненной в базе данных.Принимая во внимание, что уценка слабо определена, большинство реализаций парсера будут иметь небольшие различия.

Существует очень хорошая запись в блоге , в которой обсуждается проблема.

Почему бы не выполнить весь синтаксический анализ на стороне клиента и опубликовать обе версии?

Это не кажется мне безопасным решением.Я также думаю, что пользователи потенциально смогут разместить разметку с помощью HTML, который не соответствует.

Существуют ли какие-либо существующие реализации?

Существует одна реализация под названиемCFShowdown , но это не для этой конкретной цели.Скорее, это для обработки вывода на странице.В разделе комментариев вышеупомянутого блога представлена ​​чистая реализация Java, написанная пользователем по имени 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]";
}

Objective

Создание Javaкласс, который позволил бы нам использовать эту реализацию с ColdFusion UDF или пользовательским тегом внутри компонента, что-то вроде <cfset html = getMarkdown(string)>

Поскольку у меня нет опыта работы с Java, я хочу получить некоторые советы иВклад пользователей о том, где и как начать выполнять эту задачу.Я создал

Ответы [ 4 ]

4 голосов
/ 05 января 2011

Файлы showdown.js и файл markdown.txt (пример ниже) находятся в одном каталоге.

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>

markdown.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"

Обновление

Вот версия, которая принимает работу Адама Пресли на Java и делает все это в CFC. Заметьте, я взял немного магии, которое он добавил в конце showdown.js, и поместил его в функцию CFC, к которой добавляется возвращаемое значение (т. Е. showdownAdapterJS()).

CFC

<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>
3 голосов
/ 05 января 2011

На самом деле, я уже обернул Showdown в библиотеку Java, которую можно использовать в ColdFusion. Приведенный мною пример, который, как я признаю, является плохой документацией, использует пользовательский тег, но вы можете использовать компонент Java так же легко, как и так.

<cfset obj = createObject('java', 'com.adampresley.cfshowdown.Showdown').init() />
<cfset parsedText = obj.toHTML(trim(someMarkdownContent)) />

Возможно, это помогает? В любом случае, да здравствует уценка! :)

3 голосов
/ 05 января 2011

Вы можете запускать javascript на стороне сервера в CF с помощью CFGroovy - который в основном позволяет запускать любой язык сценариев JSR-223, встроенный в CFML.

Бен Надель имеет пример запуска сервера-side javascript с использованием CFGroovy и Rhino

В примере есть все, что вам нужно - при условии, что у вас уже собран код javascript.

1 голос
/ 05 января 2011

Учитывая, что Markdown не является регулярным языком, а большинство реализаций - это серии регулярных выражений, между ними обязательно должны быть различия, как вы заметили. Этого почти невозможно избежать.

Если ваша цель просто:

  1. Предоставьте редактору уценки на стороне клиента предварительный просмотр в режиме реального времени (например, редактор вопросов / ответов Stack Overflow) и
  2. Сохранение идентично обработанной копии сгенерированного html для отображения конечным пользователем

Тогда я вижу только два реальных варианта:

  1. Выполните всю обработку уценки на стороне сервера и выполните предварительный просмотр, используя AJAX для отправки уценки и получения обновленного HTML-кода предварительного просмотра (используя ту же библиотеку, которую вы в конечном итоге будете использовать для создания сохраненного HTML-кода), либо
  2. Выполните всю обработку разметки на стороне клиента и отправьте и необработанную разметку и сгенерированный HTML как части формы создания контента и сохраните обе; так что вы можете отобразить исходную уценку для целей редактирования и сгенерированный HTML для отображения.

Лично я бы выбрал вариант 2.

...