Markdown ultra-lite
Alex Tweedly
alex at tweedly.net
Fri Nov 3 19:49:24 EDT 2017
I wanted to find a LC implementation of markdown, so I could easily use
markdown files on a website, and have them be converted to html for
output. I really wanted it completely in LC, so I could just include it
without worrying about installing, or checking for, any other languages,
scripts, etc.
But I could find one, so I thought I might try implementing it myself.
Didn't take long to find a current version in Python (easier for me to
convert than C or Perl :-) - but heavens there's a lot of code there !!
And indeed when you read a description (try
http://spec.commonmark.org/0.28/ for example) you can easily see why
it's complicated to do full implementation.
And, sadly, many of those complications could have been avoided, but
weren't due to historical misfortune :-) So I have done an
ultra-light version ....
Restrictions and limitations:
-----------------------
Links are only 'inline', not 'reference'.
- the whole inline link must be on a single input line.
- no autolink, HTML Tags or codespans to confuse them :-)
- no checks on brackets within the link text - simple cases should
just work, others won't
Images are inline only, not referenced.
- whole image spec must be on a single input line
- doesn't do anything to deal with links within image description
(mostly because I couldn't figure out what this part of the
spec was trying to allow :-)
NB - because images are done before links, it is possible to handle the
common case where the inline image is withing the linktext - i.e. you
can click on the image to go to the other URL, e.g.
Here is a [picture ![some alt text](x.png) used within
link](/images/bigx.png)
Only one style of header is handled - using multiple '#'s rather than
pseudo-underline.
Emphasis, and everything else, isn't done - and may or may not be
depending on whether I decide I car about it.
-------------------------
Additions and oddities :
1. If the last char in the URL is a '*' then it becomes a "new tab" link
(i.e. TARGET='_blank').
2. I added special handling for facebook links - see the code
In case anyone else finds it useful, here's the code .... I'll figure
out Github etc. and put it up there some day - but for now it's short
enough I'm just going to include it here. It uses a couple of utility
functions which are included.
-- Alex.
local sSubstitutions
function markdownToHTML pMD
put empty into sSubstitutions
repeat for each line L in pMD
-- first extract any image specs
put L into LL
put 1 into N
repeat forever
if decompose2(LL, "![", "](", p1, p2, p3) then
if decompose1(p3, ")", p3a, p4) then
put "<img src='" & p3a & "' alt='" & p2 & "'>" into
sSubstitutions[N]
put p1 & numtochar(N) & p4 into LL
add 1 to N
next repeat
end if
end if
exit repeat
end repeat
-- and then do any links
repeat forever
if decompose2(LL, "[", "](", p1, p2, p3) then
if decompose1(p3, ")", p3a, p4) then
if char -1 of p3a = "*" then
put "' TARGET='_blank" into char -1 of p3a
end if
if p2 = "fb" then
put p1 & "<a href='http://facebook.com/" & p3a & "'
class='icon fa-facebook' TARGET='_blank'><span class='label'>" & "</a>"
& p4 into LL
else
put p1 & "<a href=" & quote & p3a & quote & ">" & p2
& "</a>" & p4 into LL
end if
next repeat
end if
end if
exit repeat
end repeat
repeat with i = 1 to N
replace numtochar(i) with sSubstitutions[i] in LL
end repeat
if LL is empty then put L into LL
if LL is empty then
put CR after tResult
else
put word 1 of LL into W
replace "#" with empty in W
if W is empty then
put the number of chars in word 1 of LL into N
put "<H" & N & ">" & word 2 to -1 of LL & "</H" & N & ">"
into LL
end if
put LL &CR after tResult
end if
-- if NOT (tResult ends with CR) then exit repeat
-- delete char -1 of tResult
end repeat
replace (numtochar(13) & numtochar(10)) with CR in tResult
replace (CR & CR &CR) with (CR & "<p><br><p>" & CR) in tResult
replace (CR & CR) with (CR & "<p>") in tResult
return tResult
end markdownToHTML
function decompose1 pIn, pSep1, @p1, @p2
-- if the input string (pIn) contains the delimiter string (pSep1) then
-- return TRUE and set the result variables to the parts 'before'
and 'after' the delimiter
-- else
-- return FALSE, and leave p1, p2 unchanged
put offset(pSep1, pIn) into t1
if t1 > 0 then
put char 1 to t1-1 of pIn into p1
put char (t1+the number of chars in pSep1) to -1 of pIn into p2
return TRUE
end if
return FALSE
end decompose1
function decompose2 pIn, pSep1, pSep2, @p1, @p2, @p3
-- if the input string (pIn) contains the (non-overlapping)
delimiter strings (pSep1, pSep2) then
-- return TRUE and set the result variables to the parts
'before', 'between' and 'after' the delimiters
-- else
-- return FALSE, and leave p1, p2, p3 unchanged
put offset(pSep1, pIn) into t1
if t1 > 0 then
put char t1+the number of chars in pSep1 to -1 of pIn into tIn
put offset(pSep2, tIn) into t2
if t2 > 0 then
put char 1 to t1-1 of pIn into p1
put char 1 to t2-1 of tIn into p2
put char t2+the number of chars in pSep2 to -1 of tIn into p3
return TRUE
end if
end if
return FALSE
end decompose2
More information about the use-livecode
mailing list