Markdown processing in Coldfusion 9 with table extension support

I am trying to get Markdown with a table extension working on Coldfusion 9. There are several other similar questions regarding CF and Markdown here in stackoverflow, but none of them deal with extensions.

So far I have tried:

  • markdownj via javaloader.cfc
  • pegdown via javaloader.cfc
  • showdownjs via orangepips nice cfc (I would have connected all this but had no reputation for more than 2)

All of them work fine for basic Markdown, but none of them support tables out of the box.
Both pegdown and showdown.js support table expansion. Markdownj however does not want to support him at the moment, but I thought it was worth a try.

I think my problem is the correct syntax for loading the extension in pegdown or showdown. Both work in a completely different way, one of which is pure Java, and the other is Javascript.

For pegdown

My code here is very simple and just uses javaloader to load both pegdown and the required library. This part works fine, with no errors, but when I try to use the pegdown class, I get a pretty general error;

An exception occurred while instantiating a Java object. The class must not be an interface or an abstract class. Error: ''. 

Code to call pegdown;

 <cfscript> jClass = [ "#getDirectoryFromPath(getCurrentTemplatePath())#/pegdown/pegdown-1.2.1.jar" , "#getDirectoryFromPath(getCurrentTemplatePath())#/pegdown/parboiled-core-1.1.3.jar" ]; javaloader = createObject('component','components.javaloader.JavaLoader').init(jClass, true); variables.pegdown = javaloader.create("org.pegdown.PegDownProcessor"); </cfscript> <cfdump var="#variables.pegdown#" /> 

For showdownjs:

I tried to add the extension file (extensions / table.js) to var for evaluation and add the var extensions to the converter parameters according to the documentation, but it does not work. I assume that showdown.js does not expect to work inside the main JavaEngineManager script, since the main showdown.js script cannot "see" the extension of the tables without receiving a row of 246 s;

 The script had an error: sun.org.mozilla.javascript.internal.JavaScriptException: Extension 'undefined' could not be loaded. It was either not found or is not a valid extension. (#246) in at line number 246 

My code for showdown.js is based on Orangepips answer in the related question above.

 <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 = ""> <cfset var showdownJS = "" /> <cftry> <cfset bindings.put("markdownText", arguments.markdownText)> <cfset variables.engine.setBindings(bindings, createObject("java", "javax.script.ScriptContext").ENGINE_SCOPE)> <cfset showdownJS &= fileRead('#getDirectoryFromPath(getCurrentTemplatePath())#/showdown.js')> <cfset showdownJS &= fileRead('#getDirectoryFromPath(getCurrentTemplatePath())#/extensions/table.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({extensions:['table']}); __converter.makeHtml(markdownText);</cfoutput> </cfsavecontent> <cfreturn local.javascript> </cffunction> </cfcomponent> 

I am open to any ideas and have no particular preference for one solution over another.

Stacktrace

 java.lang.ClassNotFoundException: org.parboiled.BaseParser at coldfusion.bootstrap.BootstrapClassLoader.loadClass(BootstrapClassLoader.java:235) at java.lang.ClassLoader.loadClass(Unknown Source) at com.compoundtheory.classloader.NetworkClassLoader.loadClass(NetworkClassLoader.java:463) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClassInternal(Unknown Source) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(Unknown Source) at java.lang.ClassLoader.defineClass(Unknown Source) at com.compoundtheory.classloader.NetworkClassLoader.loadClass(NetworkClassLoader.java:450) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClassInternal(Unknown Source) at java.lang.Class.getDeclaredFields0(Native Method) at java.lang.Class.privateGetDeclaredFields(Unknown Source) at java.lang.Class.privateGetPublicFields(Unknown Source) at java.lang.Class.getFields(Unknown Source) at coldfusion.runtime.java.ObjectHandler.Initialize(ObjectHandler.java:35) at coldfusion.runtime.java.ObjectHandler.<init>(ObjectHandler.java:30) at coldfusion.runtime.java.ReflectionCache$1.fetch(ReflectionCache.java:29) at coldfusion.util.SoftCache.get_statsOff(SoftCache.java:133) at coldfusion.util.SoftCache.get(SoftCache.java:81) at coldfusion.runtime.java.ReflectionCache.get(ReflectionCache.java:36) at coldfusion.runtime.java.JavaProxy.<init>(JavaProxy.java:35) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at coldfusion.runtime.java.JavaProxy.CreateObject(JavaProxy.java:166) at coldfusion.runtime.java.JavaProxy.invoke(JavaProxy.java:80) at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2360) at cfJavaLoader2ecfc535209679$funcCREATEJAVAPROXY.runFunction(/srv/vhosts/myproject/httpdocs/components/javaloader/JavaLoader.cfc:329) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472) at coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47) at coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220) at coldfusion.runtime.CfJspPage._invokeUDF(CfJspPage.java:2582) at cfJavaLoader2ecfc535209679$funcCREATE.runFunction(/srv/vhosts/myproject/httpdocs/components/javaloader/JavaLoader.cfc:87) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472) at coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47) at coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337) at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2360) at cfpegdown2ecfm1473046932.runPage(/srv/vhosts/myproject/httpdocs/_temp/markdown/pegdown.cfm:22) at coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:231) at coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:416) at coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:2722) at cfApplication2ecfc294205112$funcONREQUEST.runFunction(/srv/vhosts/myproject/httpdocs/Application.cfc:377) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472) at coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337) at coldfusion.runtime.AppEventInvoker.invoke(AppEventInvoker.java:88) at coldfusion.runtime.AppEventInvoker.onRequest(AppEventInvoker.java:280) at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:356) at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48) at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40) at coldfusion.filter.PathFilter.invoke(PathFilter.java:94) at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70) at coldfusion.filter.BrowserDebugFilter.invoke(BrowserDebugFilter.java:79) at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28) at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38) at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46) at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38) at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22) at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62) at coldfusion.CfmServlet.service(CfmServlet.java:200) at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89) at jrun.servlet.FilterChain.doFilter(FilterChain.java:86) at com.intergral.fusionreactor.filter.FusionReactorCoreFilter.doRequestNoFilter(FusionReactorCoreFilter.java:712) at com.intergral.fusionreactor.filter.FusionReactorCoreFilter.doFusionRequest(FusionReactorCoreFilter.java:341) at com.intergral.fusionreactor.filter.FusionReactorCoreFilter.doFilter(FusionReactorCoreFilter.java:246) at com.intergral.fusionreactor.filter.FusionReactorFilter.doFilter(FusionReactorFilter.java:121) at jrun.servlet.FilterChain.doFilter(FilterChain.java:94) at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42) at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46) at jrun.servlet.FilterChain.doFilter(FilterChain.java:94) at jrun.servlet.FilterChain.service(FilterChain.java:101) at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106) at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42) at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286) at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543) at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203) at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428) at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66) 

Update

Now it works thanks to the side dish.
The problem is a lack of understanding of Java and some additional dependencies for PegDown and Parboiled.

Parboiled needs java and core.jars Pegdown. Pegdown expects to find an ASM library
I used version 4.1 and included -all version. The recommendation is to include only the necessary asm banks, but for now this is enough for me to take it further.

Working code for CF9 (running on JRUN / Linux)

 <!--- Load some demo markdown content ---> <cfset markdownString = fileRead("#getDirectoryFromPath(getCurrentTemplatePath())#/demo.txt")> <!--- Directory containing all the necessary jar files. ---> <cfset jarDir = "#getDirectoryFromPath(getCurrentTemplatePath())#pegdown" /> <!--- Array of necessary classes ---> <cfset jClass = [ "#jarDir#/parboiled-java-1.1.3.jar" , "#jarDir#/asm-all-4.1.jar" , "#jarDir#/parboiled-core-1.1.3.jar" , "#jarDir#/pegdown-1.2.1.jar" ] /> <cfset javaloader = createObject('component','components.javaloader.JavaLoader').init(jClass, false) /> <!--- Hex values for different extensions can be found in org.pegdown.Extensions.java (0x20 is for tables support) ---> <cfset variables.pegdown = javaloader.create("org.pegdown.PegDownProcessor").init(javaCast("int", InputBaseN("0x20", 16))) /> <!--- Output the HTML conversion ---> <cfoutput>#variables.pegdown.markdownToHtml(markdownString)#</cfoutput> 
+6
source share
1 answer

You get an error because the PegDown - parboiled dependency is distributed.

This is a scala project and it creates more than one JAR. For the proprietary jar kernel, you only have the basic scala algorithms and APIs.

To use the Java API, you also need to get the parboiled-java library that provides the bindings (including the BaseParser class mentioned in the above exception). The GitHub repo only has 1.1.4 files, but there is a copy of the 1.1.3 jar here: http://mirrors.ibiblio.org/maven2/org/parboiled/parboiled-java/1.1.3/parboiled-java-1.1.3. jar

If you download this and add it to the array of jar files that you pass JavaLoader , you should be fine.

+1
source

All Articles