Displaying Markdown in an XPage using the showdown.js library
I wanted to move to a text based changelog in our applications rather than a Notes form or even an XPage.The idea was that it would help make it easier to deal with merge conflicts in source control.
I eventually settled on using Markdown as I couldn’t get the formatting that I wanted with ascii.
This live demo shows how to display the markdown from a file resource on an XPage using the showdown.js library. It is available here as a demo database and on OpenNTF as a snippet.
It was a bit of a faff, mostly around the timing of the external javascript showdown.js library but some help from Sven Hasselbach sorted that out.
The scheme goes like this :
- SSJS loads the contents of the text document into a hidden field using this formula
// the file below is in the file resources
// it can have any name and any suffix
var url = “/demo.md”;
var data = facesContext.getExternalContext().getResourceAsStream( url );
var txt = “”;
while( data.available() ){
txt += @Char(data.read());
}
return(txt);
I tried for ages to find a faster way to read the stream but with no success. It seems a bit agricultural to read it a character at a time.
2. The showdown.js script is loaded using Svens frig in this part of the XPage. The github-markdown.css is also loaded but it does not need to use the special scheme
<xp:this.resources>
<xp:headTag tagName=”script”>
<xp:this.attributes>
<xp:parameter name=”type” value=”text/javascript” />
<xp:parameter name=”src” value=”showdown.min.js” />
</xp:this.attributes>
</xp:headTag>
<xp:styleSheet href=”/github-markdown.css”></xp:styleSheet>
</xp:this.resources>
<xp:this.properties>
<xp:parameter name=”xsp.resources.aggregate” value=”true” />
</xp:this.properties>
<!– –>
3. The CSJS in the script block converts the text to markdown using the showdown library and pushes it into the targetDiv div
<xp:scriptBlock id=”scriptBlock1″ defer=”false”>
<xp:this.value><![CDATA[dojo.addOnLoad( function() {
var text = document.getElementById(“#{id:Hidden1}”).innerHTML;
target = document.getElementById(‘targetDiv’),
converter = new showdown.Converter(),
html = converter.makeHtml(text);
target.innerHTML = html;
} );
]]></xp:this.value>
</xp:scriptBlock>