/** * 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 = "" & 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"; return reReplaceNoCase( arguments.markdown, pattern, replacement); } }