/**
* Here is an example solution for the Markdown exercise
*/
component {
/**
* Parse markdown
*
* @input.hint markdown to parse
*/
public string function parse(required string input) {
var lines = listToArray( arguments.input, chr( 10 ) );
var output = [];
var isInList = false;
for (var line in lines) {
line = parseHeader(line);
line = parseBold( line );
line = parseItalic( line );
line = parseList( line, isInList );
/* We are in a list if the line contains a list item and not the unordered list closing tag */
isInList = ( reFindNoCase("
", line ) && !reFindNoCase("", line ) );
line = parseParagraph( line );
output.append( line );
}
/* Just in case the last line was a list item */
if ( isInList ) {
output.append( "" );
}
var html = arrayToList( output, "" );
return html;
}
/**
*
* Parse html headers from markdown text
*
* @markdown.hint Markdown text to parse
*
*/
private string function parseHeader( required string markdown ) {
/* Get the header number */
var headerNumber = reMatchNoCase( "^[##]+", arguments.markdown).len() ? reMatchNoCase( "^[##]+", arguments.markdown)[1].len() : 0;
if (headerNumber) {
var pattern = "^[##]+ (.*)";
var replacement = "\1";
var output = reReplaceNoCase( arguments.markdown, pattern, replacement);
}
else {
var output = arguments.markdown;
}
return output;
}
/**
*
* Parse a list
*
* @markdown.hint Markdown text to parse
* @isInList.hint Flag to indicate if currently parsing a list or not
*
*/
private string function parseList(
required string markdown,
required boolean isInList
) {
var output = arguments.markdown;
if ( isListItem( arguments.markdown ) ) {
if ( !arguments.isInList ) {
output = "" & parseListItem( output );
}
else {
output = parseListItem( output );
}
}
else if ( arguments.isInList ) {
output = "
" & output;
}
return output;
}
/**
*
* Parse a paragraph
*
* @markdown.hint Markdown text to parse
*
*/
private string function parseParagraph( required string markdown ) {
if ( !reMatchNoCase( " tags
*
* @markdown.hint Markdown text to parse
*
*/
private string function wrapList( required string markdown ) {
return "";
}
/**
*
* Check if markdown is a list item
*
* @markdown.hint Markdown text to parse
*
*/
public boolean function isListItem( required string markdown ) {
/* Use regex to determine if markdown is list item */
return ( reFindNoCase( "\* (.*)",arguments.markdown ) > 0 );
}
/**
*
* Parse a list item
*
* @markdown.hint Markdown text to parse
*
*/
private string function parseListItem( required string markdown ) {
var pattern = "\* (.*)";
var replacement = "\1";
var output = reReplaceNoCase( arguments.markdown, pattern, replacement );
/* Add a p tag to item if no other tag is present */
if ( !reFindNoCase("<", output ) ) {
var pattern = "(.*)";
var replacement = "\1
";
var output = reReplaceNoCase( output, pattern, replacement );
}
return output;
}
/**
*
* Parse bold text from markdown
*
* @markdown.hint Markdown text to parse
*
*/
private string function parseBold( required string markdown ) {
return parseWithDelimiter( arguments.markdown, "__", "strong" );
}
/**
*
* Parse bold text from markdown
*
* @markdown.hint Markdown text to parse
*
*/
private string function parseItalic( required string markdown ) {
return parseWithDelimiter( arguments.markdown, "_", "em" );
}
/**
*
* Utility function to replace markdown delimiter with their tag equivalent
*
* @markdown.hint Markdown to parse
* @delimiter.hint Markdown syntax to replace with tag i.e __
* @tag.hint HTML tag to replace it with. i.e
*
*/
public any function parseWithDelimiter(
required string markdown,
required string delimiter,
required string tag
) {
var pattern = "#arguments.delimiter#(.*)#arguments.delimiter#";
var replacement = "<#arguments.tag#>\1#arguments.tag#>";
return reReplaceNoCase( arguments.markdown, pattern, replacement);
}
}