SUBROUTINE RENDER.MARKDOWN(MARKDOWN,HTML) * GIT.FILENAME = 'RENDER.MARKDOWN' GIT.REPO = 'https://github.com/Krowemoh/TCL-Utilities.git' * EQU TRUE TO 1 EQU FALSE TO 0 * HTML = '' * MARKDOWN = CHANGE(MARKDOWN,CHAR(10),@AM) NUMBER.OF.LINES = DCOUNT(MARKDOWN,@AM) * BLOCK = '' BLOCK.TYPE = 'PARAGRAPH' * FOR I = 1 TO NUMBER.OF.LINES LINE = MARKDOWN * IF LINE = '' OR TRIM(LINE) = '' THEN IF BLOCK.TYPE THEN GOSUB BUILD.BLOCK END BLOCK.TYPE = 'PARAGRAPH' * END ELSE IF LINE[1,3] = '```' THEN IF BLOCK.TYPE THEN GOSUB BUILD.BLOCK END * BLOCK.TYPE = 'CODE' * LOOP I = I + 1 LINE = MARKDOWN UNTIL LINE = '```' OR I > NUMBER.OF.LINES DO BLOCK = BLOCK : LINE : CHAR(10) REPEAT * GOSUB BUILD.BLOCK * END ELSE IF LINE[1,6] = '' THEN IF BLOCK.TYPE THEN GOSUB BUILD.BLOCK END * BLOCK.TYPE = 'HTML' * LOOP I = I + 1 LINE = MARKDOWN UNTIL LINE = '' OR I > NUMBER.OF.LINES DO BLOCK = BLOCK : LINE : CHAR(10) REPEAT * GOSUB BUILD.BLOCK * END ELSE IF LINE[1,4] = SPACE(4) THEN IF BLOCK.TYPE THEN GOSUB BUILD.BLOCK END * BLOCK.TYPE = 'CODE' * BLOCK = BLOCK : LINE[5,9999] : CHAR(10) * LOOP I = I + 1 LINE = MARKDOWN UNTIL LINE[1,4] # SPACE(4) OR I > NUMBER.OF.LINES DO BLOCK = BLOCK : LINE[5,9999] : CHAR(10) REPEAT * GOSUB BUILD.BLOCK I = I - 1 * END ELSE IF LINE MATCHES "> 0X" THEN IF BLOCK.TYPE THEN GOSUB BUILD.BLOCK END * BLOCK.TYPE = 'BLOCKQUOTE' * IF LINE[1,2] = '> ' THEN LINE = TRIM(LINE[3,9999]) END BLOCK = BLOCK : LINE : CHAR(10) * LOOP I = I + 1 LINE = MARKDOWN UNTIL NOT(LINE MATCHES "> 0X") OR I > NUMBER.OF.LINES DO IF LINE[1,2] = '> ' THEN LINE = TRIM(LINE[3,9999]) END BLOCK = BLOCK : LINE : CHAR(10) REPEAT * BLOCK.HTML = '' CALL RENDER.MARKDOWN(BLOCK,BLOCK.HTML) BLOCK = BLOCK.HTML GOSUB BUILD.BLOCK * I = I - 1 * END ELSE IF LINE MATCHES "- 0X" OR LINE MATCHES "* 0X" OR LINE MATCHES "1N'.' 0X" THEN IF BLOCK.TYPE THEN GOSUB BUILD.BLOCK END * IF LINE MATCHES "1N'.' 0X" THEN BLOCK.TYPE = 'ORDERED.LIST' END ELSE BLOCK.TYPE = 'UNORDERED.LIST' END * IF LINE[1,2] = '- ' OR LINE[1,2] = '* ' OR LINE MATCHES "1N'.' 0X" THEN LINE = TRIM(LINE[3,9999]) END BLOCK = BLOCK : LINE : CHAR(10) : CHAR(10) * LOOP I = I + 1 LINE = MARKDOWN NEXT.LINE = MARKDOWN UNTIL (TRIM(LINE) = '' AND TRIM(NEXT.LINE) = '') OR I > NUMBER.OF.LINES DO IF LINE[1,2] = '- ' OR LINE[1,2] = '* ' OR LINE MATCHES "1N'.' 0X" THEN LINE = TRIM(LINE[3,9999]) END BLOCK = BLOCK : LINE : CHAR(10) : CHAR(10) REPEAT * BLOCK.HTML = '' CALL RENDER.MARKDOWN(BLOCK,BLOCK.HTML) BLOCK = BLOCK.HTML GOSUB BUILD.BLOCK * END ELSE GOSUB PARSE.LINE END NEXT I * IF BLOCK.TYPE = '' THEN BLOCK.TYPE = 'PARAGRAPH' END * IF BLOCK THEN GOSUB BUILD.BLOCK END * RETURN * ********************* S U B R O U T I N E ********************* * PARSE.LINE:NULL * TRIGGER.BLOCK = FALSE * PATTERN = "0X'\'1X0X" * * Escape characters * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,4) * LINE = ONE : '' : SEQ(TWO) :'' : THREE REPEAT * * Header * FOR HDR.CTR = 1 TO 6 PATTERN = "'" : STR('#',HDR.CTR) : " '0X" * LINE = TRIM(LINE) * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,2) * LINE = '' : TRIM(TWO) :'' * IF BLOCK.TYPE THEN GOSUB BUILD.BLOCK END BLOCK.TYPE = 'HEADER' REPEAT NEXT HDR.CTR * * *** horizontal line * IF LINE = '***' OR LINE = '---' THEN LINE = '
' IF BLOCK.TYPE THEN GOSUB BUILD.BLOCK END BLOCK.TYPE = 'HORIZONTAL.LINE' END * * `code` * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,5) * LINE = ONE : '' : TWO :'' : THREE REPEAT * * ***bold and italic** * PATTERN = "0X'***'0X'***'0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,5) * LINE = ONE : '' : TWO :'' : THREE REPEAT * * ~~strikethrough~~ * PATTERN = "0X'~~'0X'~~'0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,5) * LINE = ONE : '' : TWO :'' : THREE REPEAT * * **bold** * PATTERN = "0X'**'0X'**'0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,5) * LINE = ONE : '' : TWO :'' : THREE REPEAT * * __bold__ * PATTERN = "0X'__'0X'__'0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,5) * LINE = ONE : '' : TWO :'' : THREE REPEAT * * *italic* * PATTERN = "0X'*'0X'*'0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,5) * LINE = ONE : '' : TWO :'' : THREE REPEAT * * _italic_ * PATTERN = "0X'_'0X'_'0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,5) * LINE = ONE : '' : TWO :'' : THREE REPEAT * * ...small... * PATTERN = "0X'...'0X'...'0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,5) * LINE = ONE : '' : TWO :'' : THREE REPEAT * * ![link](http://link.com) * PATTERN = "0X'!['0X']''('0X')'0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,6) FOUR = MATCHFIELD(LINE,PATTERN,8) * LINE = ONE : '' : TWO : '' : FOUR REPEAT * * [link](http://link.com) * PATTERN = "0X'['0X']''('0X')'0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,6) FOUR = MATCHFIELD(LINE,PATTERN,8) * LINE = ONE : '' : TWO :'' : FOUR REPEAT * * => Gemini Link * PATTERN = "'=> '0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,2) * THREE = TRIM(FIELD(TWO,' ',2,9999)) TWO = TRIM(FIELD(TWO,' ',1)) * IF BLOCK.TYPE THEN GOSUB BUILD.BLOCK END * EXT = TWO[LEN(TWO)-3,999] * IF EXT = '.png' OR EXT = '.jpg' OR EXT = 'jpeg' OR EXT = '.gif' THEN LINE = '' : THREE :'' END ELSE LINE = '⇒ ' : THREE :'' END * BLOCK.TYPE = 'GEMINI.LINK' REPEAT * * Unescape characters * PATTERN = "0X''0X''0X" * LOOP UNTIL NOT(LINE MATCHES PATTERN) DO ONE = MATCHFIELD(LINE,PATTERN,1) TWO = MATCHFIELD(LINE,PATTERN,3) THREE = MATCHFIELD(LINE,PATTERN,5) * IF NUM(TWO) THEN LINE = ONE : CHAR(TWO) : THREE END ELSE LINE = CHANGE(LINE,'','') LINE = CHANGE(LINE,'','') END REPEAT * IF BLOCK.TYPE = 'HEADER' OR BLOCK.TYPE = 'HORIZONTAL.LINE' THEN BLOCK = LINE GOSUB BUILD.BLOCK END ELSE BLOCK = BLOCK : LINE END * RETURN * ********************* S U B R O U T I N E ********************* * BUILD.BLOCK:NULL * IF BLOCK.TYPE = 'PARAGRAPH' THEN IF BLOCK THEN HTML = HTML : '

' : BLOCK : '

' : CHAR(10) END * END ELSE IF BLOCK.TYPE = 'HEADER' THEN HTML = HTML : BLOCK : CHAR(10) * END ELSE IF BLOCK.TYPE = 'HORIZONTAL.LINE' THEN HTML = HTML : BLOCK : CHAR(10) * END ELSE IF BLOCK.TYPE = 'GEMINI.LINK' THEN HTML = HTML : '

' : BLOCK : '

' : CHAR(10) * END ELSE IF BLOCK.TYPE = 'CODE' THEN BLOCK = CHANGE(BLOCK,'<','<') BLOCK = CHANGE(BLOCK,'>','>') HTML = HTML : '
' : BLOCK : '
' : CHAR(10) * END ELSE IF BLOCK.TYPE = 'HTML' THEN HTML = BLOCK * END ELSE IF BLOCK.TYPE = 'BLOCKQUOTE' THEN HTML = HTML : '
' : CHAR(10) : BLOCK : '
' : CHAR(10) * END ELSE IF BLOCK.TYPE = 'UNORDERED.LIST' OR BLOCK.TYPE = 'ORDERED.LIST' THEN IF BLOCK.TYPE = 'UNORDERED.LIST' THEN OPEN.LIST.TAG = '
    ' CLOSE.LIST.TAG = '
' END ELSE OPEN.LIST.TAG = '
    ' CLOSE.LIST.TAG = '
' END * HTML = HTML : OPEN.LIST.TAG CONVERT CHAR(10) TO @AM IN BLOCK NUMBER.OF.ITEMS = DCOUNT(BLOCK,@AM) FOR LIST.CTR = 1 TO NUMBER.OF.ITEMS LIST.ITEM = BLOCK IF LIST.ITEM THEN HTML = HTML : CHAR(10) : '
  • ' : BLOCK : '
  • ' END NEXT LIST.CTR HTML = HTML : CHAR(10) : CLOSE.LIST.TAG : CHAR(10) * END ELSE HTML = HTML : '' : BLOCK : '' END * BLOCK = '' BLOCK.TYPE = '' * RETURN * * END OF PROGRAM * END *