markdown.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. #####################################################################
  2. # #
  3. # THIS IS A SOURCE CODE FILE FROM A PROGRAM TO INTERACT WITH THE #
  4. # LBRY PROTOCOL ( lbry.com ). IT WILL USE THE LBRY SDK ( lbrynet ) #
  5. # FROM THEIR REPOSITORY ( https://github.com/lbryio/lbry-sdk ) #
  6. # WHICH I GONNA PRESENT TO YOU AS A BINARY. SINCE I DID NOT DEVELOP #
  7. # IT AND I'M LAZY TO INTEGRATE IN A MORE SMART WAY. THE SOURCE CODE #
  8. # OF THE SDK IS AVAILABLE IN THE REPOSITORY MENTIONED ABOVE. #
  9. # #
  10. # ALL THE CODE IN THIS REPOSITORY INCLUDING THIS FILE IS #
  11. # (C) J.Y.Amihud and Other Contributors 2021. EXCEPT THE LBRY SDK. #
  12. # YOU CAN USE THIS FILE AND ANY OTHER FILE IN THIS REPOSITORY UNDER #
  13. # THE TERMS OF GNU GENERAL PUBLIC LICENSE VERSION 3 OR ANY LATER #
  14. # VERSION. TO FIND THE FULL TEXT OF THE LICENSE GO TO THE GNU.ORG #
  15. # WEBSITE AT ( https://www.gnu.org/licenses/gpl-3.0.html ). #
  16. # #
  17. # THE LBRY SDK IS UNFORTUNATELY UNDER THE MIT LICENSE. IF YOU ARE #
  18. # NOT INTENDING TO USE MY CODE AND JUST THE SDK. YOU CAN FIND IT ON #
  19. # THEIR OFFICIAL REPOSITORY ABOVE. THEIR LICENSE CHOICE DOES NOT #
  20. # SPREAD ONTO THIS PROJECT. DON'T GET A FALSE ASSUMPTION THAT SINCE #
  21. # THEY USE A PUSH-OVER LICENSE, I GONNA DO THE SAME. I'M NOT. #
  22. # #
  23. # THE LICENSE CHOSEN FOR THIS PROJECT WILL PROTECT THE 4 ESSENTIAL #
  24. # FREEDOMS OF THE USER FURTHER, BY NOT ALLOWING ANY WHO TO CHANGE #
  25. # THE LICENSE AT WILL. SO NO PROPRIETARY SOFTWARE DEVELOPER COULD #
  26. # TAKE THIS CODE AND MAKE THEIR USER-SUBJUGATING SOFTWARE FROM IT. #
  27. # #
  28. #####################################################################
  29. import os
  30. from flbry.variables import *
  31. from subprocess import *
  32. ################################################################################
  33. # Markdown. Or .md file format is an easy way to give your simple text documents
  34. # a bit of flare. Stuff like links, images and quotes are supported. Also bold
  35. # an italic characters.
  36. def Open(filename):
  37. # This function will parse a Markdown (.md) file into a readable python
  38. # dictionary object. That you can use for various things.
  39. try:
  40. md = open(filename)
  41. md = md.read()
  42. except:
  43. print("Failed to load the article!!!")
  44. # Spliting it for the read.
  45. md = md.split("\n")
  46. # First thing is I was to read the headings and convert it into a tree.
  47. tree = []
  48. indent = 1
  49. c = []
  50. for line in md:
  51. ty = "text"
  52. te = line
  53. # Here I want to simply get a type of each line. Later we going to parse
  54. # the links and other things. But first. Let's parse stuff based on
  55. # lines.
  56. if line.startswith("#"):
  57. # The titles of the chapter. The Headers are usually written similar
  58. # to how here in python you write comments. It's a # , space, and the
  59. # text.
  60. # The amount of hashes. ## or ### gives different sized text. Officialy
  61. # it should support up to 6 hashes. ######. But why not make it more
  62. # just in case.
  63. ty = line.count("#") # This might give bugs
  64. elif line.startswith("> "):
  65. # The > sign in the Markdown language is used for quatations.
  66. ty = "text_c"
  67. tree.append([ty, te+"\n"])
  68. # Now the stage 0 is over and we parsed the basic things. Now is the hard
  69. # part to parse out all the images and stuff inside them. It's going to be
  70. # done per part. And we are going to use the same technique I used for the
  71. # conversion of the legacy projects. See : studio/story.py
  72. # We are going to itterate over each letter. And decide what to do by that
  73. newtree = []
  74. for block in tree:
  75. part = ""
  76. skip = 0
  77. for n, l in enumerate(block[-1]):
  78. if skip > n:
  79. continue
  80. part = part + l
  81. # Here we are going to do something if a give condition is met.
  82. # Usually I gonna do something if [part] ends with a given markdown
  83. # thing. I don't have a mnual of markdown on me. So please make it
  84. # more supported. I guess. I might forget things I rarely use.
  85. # Links are made with [stuff you click on](https://example.com)
  86. # but similar to it. Images are done ![Tooltip](Image.png)
  87. # and even weirder you can put one into the other. Like
  88. # [![Tooltip](Image.png)](https://example.com)
  89. # Which going to give you a clickable image.
  90. # For this version what we are going to do is next.
  91. # If we got [![ then it's a clickable image
  92. # If we got ![ then it's just image
  93. # and if we got [ then it's a link.
  94. if part.endswith("[!["):
  95. # IMAGE LINK
  96. newtree.append([block[0], part[:-3]])
  97. tooltip = ""
  98. imageurl = ""
  99. url = ""
  100. t = False
  101. iu = False
  102. skip = n
  103. for le in block[-1][n:]: # For letters in the rest of text
  104. skip = skip + 1
  105. if le == "]":
  106. t = True
  107. elif le == ")" and t and not iu:
  108. iu = True
  109. elif le == ")" and t and iu:
  110. break
  111. elif not t:
  112. tooltip = tooltip +le
  113. elif t and not iu:
  114. imageurl = imageurl + le
  115. else:
  116. url = url+le
  117. tooltip = tooltip[tooltip.find("[")+1:]
  118. imageurl = imageurl[imageurl.find("(")+1:]
  119. url = url[url.find("(")+1:]
  120. apnd = ["image", "[IMAGE_", imageurl]
  121. newtree.append(apnd)
  122. apnd = ["link", "_LINK]", url]
  123. newtree.append(apnd)
  124. part = ""
  125. elif part.endswith("!["):
  126. # IMAGE
  127. newtree.append([block[0], part[:-2]])
  128. tooltip = ""
  129. url = ""
  130. t = False
  131. skip = n
  132. for le in block[-1][n:]: # For letters in the rest of text
  133. skip = skip + 1
  134. if le == "]":
  135. t = True
  136. elif le == ")" and t:
  137. break
  138. elif not t:
  139. tooltip = tooltip +le
  140. else:
  141. url = url+le
  142. tooltip = tooltip[tooltip.find("[")+1:]
  143. url = url[url.find("(")+1:]
  144. apnd = ["image", "[IMAGE]", url]
  145. newtree.append(apnd)
  146. part = ""
  147. elif part.endswith("[") and not block[-1][n:].startswith('[!['):
  148. # LINK
  149. newtree.append([block[0], part[:-1]])
  150. tooltip = ""
  151. url = ""
  152. t = False
  153. skip = n
  154. for le in block[-1][n:]: # For letters in the rest of text
  155. skip = skip + 1
  156. if le == "]":
  157. t = True
  158. elif le == ")" and t:
  159. break
  160. elif not t:
  161. tooltip = tooltip +le
  162. else:
  163. url = url+le
  164. tooltip = tooltip[tooltip.find("[")+1:]
  165. url = url[url.find("(")+1:]
  166. apnd = ["link", tooltip, url]
  167. newtree.append(apnd)
  168. part = ""
  169. # Now I want to deal with `, *, ** and ***. If you want to help me you
  170. # can implement other types. Such as _, __, ___ and so on. Markdown is
  171. # a very rich language. I'm going to use the cut down version I see other
  172. # people use.
  173. # BTW this is the time. Feb 28. When I switched from Gedit to GNU Emacs.
  174. # Interesting feeling using this programm. I kind a love it even tho
  175. # so many stuff in not intuitive. Like saving is not Ctrl - S but
  176. # Ctrl - X -> Ctrl - S.
  177. # Things like Alt-; to comment multiple lines at ones is HUGE. Also it
  178. # was built by programmers for programmers. So it's a very good tool.
  179. elif part.endswith("**") and not block[-1][n+2:].startswith('*'):
  180. # DOUBLE **
  181. newtree.append([block[0], part[:-2]])
  182. if block[0] == "text":
  183. block[0] = "text_b"
  184. else:
  185. block[0] = "text"
  186. part = ""
  187. elif part.endswith("*") and not block[-1][n+1:].startswith('*'):
  188. # SINGLE *
  189. newtree.append([block[0], part[:-1]])
  190. if block[0] == "text":
  191. block[0] = "text_i"
  192. else:
  193. block[0] = "text"
  194. part = ""
  195. elif part.endswith("`"):
  196. # SINGLE `
  197. newtree.append([block[0], part[:-1]])
  198. if block[0] == "text":
  199. block[0] = "text_c"
  200. else:
  201. block[0] = "text"
  202. part = ""
  203. newtree.append([block[0], part])
  204. newtree.append(["text", "\n"*20+" [END OF DOCUMENT] "])
  205. tree = newtree
  206. return(tree)
  207. def search_convert(s):
  208. # This function convers a chapter name into a link
  209. # such links are use in notabug.org to link to chapters
  210. # for example example.com/file.md#chapter-name
  211. # With this url it will load the example.com/file.md and
  212. # then skip to the "Chapter Name" chapter.
  213. # This function transforms "Chapter Name" into "chapter-name"
  214. l = " ./\|[]{}()?!@#$%^&*`~:;'\"=,<>"
  215. s = s.lower().replace(" ","-")
  216. r = ""
  217. for i in s:
  218. if i not in l:
  219. r = r + i
  220. return r
  221. def draw(filename, title):
  222. ###########
  223. # THE FOLLOWING CODE IS VERY DIRTY. I WAS RUNNING OUT OF TIME WHILE IMPLEMENTING
  224. # IT. PLEASE SEE WHAT CAN BE DONE ABOUT IT. I THINK SOMEBODY NEEDS TO HACK
  225. # COMMENTS TO IT. SINCE IT COULD BE CONFUSING AS HELL...
  226. ##########
  227. # Getting size of the terminal
  228. try:
  229. import os
  230. w, l = os.get_terminal_size()
  231. if not w % 2: # to solve the tearing when it's a weird amount
  232. w = w - 1
  233. l = l - 5
  234. w = w - 8
  235. except:
  236. w = 89 # The width of the frame
  237. l = 20 # Total lines amount possible.
  238. # First we want to parse the article
  239. md = Open(filename)
  240. # Now we want to print what we have
  241. # Top banner thingy. Purple with the name of the article.
  242. # Title line
  243. center(title)
  244. pline = ""
  245. lenis = 0
  246. linen = 0
  247. colors = {
  248. "text":clr["norm"]+clr["tbwh"]+clr["bdbu"],
  249. "text_b":clr["norm"]+clr["bold"]+clr["tbwh"]+clr["bdbu"],
  250. "text_i":clr["norm"]+clr["ital"]+clr["tbwh"]+clr["bdbu"],
  251. "text_c":clr["norm"]+clr["tbwh"]+clr["bdgr"],
  252. "link":clr["norm"]+clr["tbwh"]+clr["bdma"],
  253. "image":clr["norm"]+clr["tbwh"]+clr["bdcy"]
  254. }
  255. # Let's store all the links that the user might want to use
  256. links = []
  257. linkn = 0
  258. linkw = False
  259. for part in md:
  260. if part[0] in [1,2,3,4,5,6,7]:
  261. center(part[1].replace("\n", "").replace("#", ""), "bdcy")
  262. linen = linen + 1
  263. elif part[1].startswith("---") or part[1].startswith("___"):
  264. center("═"*(w-12), "bdbu")
  265. linen = linen + 1
  266. elif part[0] in ["text", "text_b", "text_c", "text_i", "link", "image"]:
  267. if linkw:
  268. pline = pline + clr["bbma"] + wdth(linkn, 4) + " "
  269. linkn = linkn + 1
  270. lenis = lenis + 5
  271. linkw = False
  272. pline = pline + colors[part[0]]
  273. for num, letter in enumerate(part[1]):
  274. br = False
  275. rest = part[1][num:] # all the rest of the part
  276. if letter not in [" ", "\n"]:
  277. pline = pline + letter
  278. lenis = lenis + 1
  279. if part[0] in ["link", "image"] and part[2] not in links:
  280. links.append(part[2])
  281. linkw = True
  282. elif letter == " ":
  283. if not lenis > w - 20 - len(rest[:rest.replace(" ","_",1).find(" ")]):
  284. pline = pline + " "
  285. lenis = lenis + 1
  286. else:
  287. br = True
  288. elif letter == "\n":
  289. br = True
  290. if br:
  291. print(" "+clr["bdbu"]+" "+pline+clr["bdbu"]+wdth("", w-lenis-6)+clr["norm"])
  292. pline = colors[part[0]]
  293. lenis = 0
  294. linen = linen + 1
  295. # If reached the line number
  296. if linen >= l:
  297. center("---type 'more' to continue reading it--- ")
  298. while True:
  299. c = input(typing_dots())
  300. if c != "more":
  301. try:
  302. c = int(c)
  303. Popen(['xdg-open',
  304. links[c].replace("(", "%28").replace(")", "%29")],
  305. stdout=DEVNULL,
  306. stderr=STDOUT)
  307. except:
  308. return
  309. elif c == "more":
  310. links = []
  311. linkn = 0
  312. linkw = False
  313. linen = 0
  314. center(title)
  315. break