markdown.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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 subprocess import *
  31. from gi.repository import Gtk
  32. from gi.repository import Gdk
  33. from gi.repository import Pango
  34. from flbry import ui
  35. ################################################################################
  36. # Markdown. Or .md file format is an easy way to give your simple text documents
  37. # a bit of flare. Stuff like links, images and quotes are supported. Also bold
  38. # an italic characters.
  39. def Open(md):
  40. # Spliting it for the read.
  41. md = "\n\n"+md
  42. md = md.split("\n")
  43. # First thing is I was to read the headings and convert it into a tree.
  44. tree = []
  45. indent = 1
  46. c = []
  47. skip = 0
  48. for n,line in enumerate(md):
  49. if skip > n:
  50. continue
  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. # THREE ``` aka code block
  58. # This tag will block any other tags
  59. # untill it's untagged
  60. code = ""
  61. print("#####", n)
  62. for l in md[n+1:]:
  63. if not l.startswith("```"):
  64. code = code + l + "\n"
  65. else:
  66. skip = n + code.count("\n") + 2
  67. break
  68. print("!!!!!!!!!", skip)
  69. tree.append(["text_cm", code+"\n"])
  70. te = ""
  71. elif line.startswith("#"):
  72. # The titles of the chapter. The Headers are usually written similar
  73. # to how here in python you write comments. It's a # , space, and the
  74. # text.
  75. # The amount of hashes. ## or ### gives different sized text. Officialy
  76. # it should support up to 6 hashes. ######. But why not make it more
  77. # just in case.
  78. ty = line.count("#") # This might give bugs
  79. elif line.startswith(">"):
  80. # The > sign in the Markdown language is used for quatations.
  81. ty = "text_q"
  82. te = te[1:]
  83. tree.append([ty, te+"\n"])
  84. # Now the stage 0 is over and we parsed the basic things. Now is the hard
  85. # part to parse out all the images and stuff inside them. It's going to be
  86. # done per part. And we are going to use the same technique I used for the
  87. # conversion of the legacy projects. See : studio/story.py ( in VCStudio )
  88. # We are going to itterate over each letter. And decide what to do by that
  89. newtree = []
  90. for block in tree:
  91. if block[0] == "text_cm":
  92. newtree.append(block)
  93. continue
  94. part = ""
  95. skip = 0
  96. for n, l in enumerate(block[-1]):
  97. if skip > n:
  98. continue
  99. part = part + l
  100. # Here we are going to do something if a give condition is met.
  101. # Usually I gonna do something if [part] ends with a given markdown
  102. # thing. I don't have a manual of markdown on me. So please make it
  103. # more supported. I guess. I might forget things I rarely use.
  104. # Links are made with [stuff you click on](https://example.com)
  105. # but similar to it. Images are done ![Tooltip](Image.png)
  106. # and even weirder you can put one into the other. Like
  107. # [![Tooltip](Image.png)](https://example.com)
  108. # Which going to give you a clickable image.
  109. # For this version what we are going to do is next.
  110. # If we got [![ then it's a clickable image
  111. # If we got ![ then it's just image
  112. # and if we got [ then it's a link.
  113. if part.endswith("[!["):
  114. # IMAGE LINK
  115. newtree.append([block[0], part[:-3]])
  116. tooltip = ""
  117. imageurl = ""
  118. url = ""
  119. t = False
  120. iu = False
  121. skip = n
  122. for le in block[-1][n:]: # For letters in the rest of text
  123. skip = skip + 1
  124. if le == "]":
  125. t = True
  126. elif le == ")" and t and not iu:
  127. iu = True
  128. elif le == ")" and t and iu:
  129. break
  130. elif not t:
  131. tooltip = tooltip +le
  132. elif t and not iu:
  133. imageurl = imageurl + le
  134. else:
  135. url = url+le
  136. tooltip = tooltip[tooltip.find("[")+1:]
  137. imageurl = imageurl[imageurl.find("(")+1:]
  138. url = url[url.find("(")+1:]
  139. apnd = ["image_link", imageurl, url]
  140. newtree.append(apnd)
  141. part = ""
  142. elif part.endswith("!["):
  143. # IMAGE
  144. newtree.append([block[0], part[:-2]])
  145. tooltip = ""
  146. url = ""
  147. t = False
  148. skip = n
  149. for le in block[-1][n:]: # For letters in the rest of text
  150. skip = skip + 1
  151. if le == "]":
  152. t = True
  153. elif le == ")" and t:
  154. break
  155. elif not t:
  156. tooltip = tooltip +le
  157. else:
  158. url = url+le
  159. tooltip = tooltip[tooltip.find("[")+1:]
  160. url = url[url.find("(")+1:]
  161. apnd = ["image", "[IMAGE]", url]
  162. newtree.append(apnd)
  163. part = ""
  164. elif part.endswith("[") and not block[-1][n:].startswith('[!['):
  165. # LINK
  166. newtree.append([block[0], part[:-1]])
  167. tooltip = ""
  168. url = ""
  169. t = False
  170. skip = n
  171. for le in block[-1][n:]: # For letters in the rest of text
  172. skip = skip + 1
  173. if le == "]":
  174. t = True
  175. elif le == ")" and t:
  176. break
  177. elif not t:
  178. tooltip = tooltip +le
  179. else:
  180. url = url+le
  181. tooltip = tooltip[tooltip.find("[")+1:]
  182. url = url[url.find("(")+1:]
  183. apnd = ["link", tooltip, url]
  184. newtree.append(apnd)
  185. part = ""
  186. # Now I want to deal with `, *, ** and ***. If you want to help me you
  187. # can implement other types. Such as _, __, ___ and so on. Markdown is
  188. # a very rich language. I'm going to use the cut down version I see other
  189. # people use.
  190. # BTW this is the time. Feb 28. When I switched from Gedit to GNU Emacs.
  191. # Interesting feeling using this programm. I kind a love it even tho
  192. # so many stuff in not intuitive. Like saving is not Ctrl - S but
  193. # Ctrl - X -> Ctrl - S.
  194. # Things like Alt-; to comment multiple lines at ones is HUGE. Also it
  195. # was built by programmers for programmers. So it's a very good tool.
  196. elif part.endswith("**") and not block[-1][n+2:].startswith('*'):
  197. # DOUBLE **
  198. newtree.append([block[0], part[:-2]])
  199. if block[0] == "text":
  200. block[0] = "text_b"
  201. else:
  202. block[0] = "text"
  203. part = ""
  204. elif part.endswith("*") and not block[-1][n+1:].startswith('*'):
  205. # SINGLE *
  206. newtree.append([block[0], part[:-1]])
  207. if block[0] == "text":
  208. block[0] = "text_i"
  209. else:
  210. block[0] = "text"
  211. part = ""
  212. elif part.endswith("`"):
  213. # SINGLE `
  214. newtree.append([block[0], part[:-1]])
  215. if block[0] == "text":
  216. block[0] = "text_c"
  217. else:
  218. block[0] = "text"
  219. part = ""
  220. newtree.append([block[0], part])
  221. #newtree.append(["text", "\n"*20+" [END OF DOCUMENT] "])
  222. tree = newtree
  223. return(tree)
  224. def search_convert(s):
  225. # This function convers a chapter name into a link
  226. # such links are use in notabug.org to link to chapters
  227. # for example example.com/file.md#chapter-name
  228. # With this url it will load the example.com/file.md and
  229. # then skip to the "Chapter Name" chapter.
  230. # This function transforms "Chapter Name" into "chapter-name"
  231. l = " ./\|[]{}()?!@#$%^&*`~:;'\"=,<>"
  232. s = s.lower().replace(" ","-")
  233. r = ""
  234. for i in s:
  235. if i not in l:
  236. r = r + i
  237. return r
  238. def convert(win, text_view):
  239. text_buffer = text_view.get_buffer()
  240. st = text_buffer.get_start_iter()
  241. en = text_buffer.get_end_iter()
  242. text = text_buffer.get_text(st, en, True)
  243. text_buffer.set_text("")
  244. text_buffer.create_tag("text", justification=Gtk.Justification.FILL, left_margin=64, right_margin=64)
  245. text_buffer.create_tag("text_c", background="#eeeeee", foreground="#000000", font="Monospace", left_margin=64, right_margin=64)
  246. text_buffer.create_tag("text_b", font="Bold", justification=Gtk.Justification.FILL, left_margin=64, right_margin=64)
  247. text_buffer.create_tag("text_i", font="Italic", justification=Gtk.Justification.FILL, left_margin=64, right_margin=64)
  248. text_buffer.create_tag("text_q", justification=Gtk.Justification.FILL, left_margin=200, right_margin=200)
  249. text_buffer.create_tag("header", size_points=30, justification=Gtk.Justification.CENTER, left_margin=64, right_margin=64)
  250. text_view.set_justification(Gtk.Justification.CENTER)
  251. md = Open(text)
  252. markup = ""
  253. for i in md:
  254. print(i)
  255. en = text_buffer.get_end_iter()
  256. if type(i[0]) == str and i[0].startswith("text") and not i[0] == "text_cm":
  257. try:
  258. text_buffer.insert_with_tags_by_name(en, i[-1], i[0])
  259. except:
  260. text_buffer.insert(en, i[-1])
  261. elif i[0] == "text_cm":
  262. codeview = Gtk.TextView()
  263. #codeview.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0.2,0.2,0.2, 1))
  264. #codeview.override_color(Gtk.StateType.NORMAL, Gdk.RGBA(0.9,0.9,0.9, 1))
  265. codeview.override_font(Pango.FontDescription("Monospace"))
  266. codescrl = Gtk.ScrolledWindow()
  267. codescrl.set_size_request(900, 500)
  268. codeview.set_editable(True)
  269. codescrl.add(codeview)
  270. codebuffer = codeview.get_buffer()
  271. codebuffer.set_text(i[-1])
  272. anchor = Gtk.TextChildAnchor()
  273. text_buffer.insert_child_anchor(en, anchor)
  274. text_view.add_child_at_anchor(codescrl , anchor)
  275. elif type(i[0]) == int:
  276. text_buffer.insert_with_tags_by_name(en, i[-1].replace("#", ""), "header")
  277. elif i[0] == "image_link":
  278. image = ui.load(win, ui.net_image, i[1], 800, "", True)
  279. def link_launch(w, link):
  280. os.system("xdg-open "+link)
  281. def link_resolve(w, link):
  282. win.url.set_text(link)
  283. win.url.activate()
  284. optionsthing = Gtk.Popover()
  285. optbox = Gtk.VBox()
  286. optionsthing.add(optbox)
  287. opt_launch = Gtk.Button("Launch")
  288. optbox.pack_start(opt_launch, False, False, False)
  289. opt_resolve = Gtk.Button("Resolve")
  290. optbox.pack_start(opt_resolve, False, False, False)
  291. opt_launch.connect("clicked", link_launch, i[-1])
  292. opt_resolve.connect("clicked", link_resolve, i[-1])
  293. optbox.show_all()
  294. link = Gtk.MenuButton(popover=optionsthing)
  295. link.add(image)
  296. anchor = Gtk.TextChildAnchor()
  297. text_buffer.insert_child_anchor(en, anchor)
  298. text_view.add_child_at_anchor(link, anchor)
  299. elif i[0] == "image":
  300. image = ui.load(win, ui.net_image, i[-1], 800, "", True)
  301. anchor = Gtk.TextChildAnchor()
  302. text_buffer.insert_child_anchor(en, anchor)
  303. text_view.add_child_at_anchor(image , anchor)
  304. elif i[0] == "link":
  305. # link = Gtk.LinkButton.new_with_label(
  306. # uri=i[-1],
  307. # label=i[1])
  308. def link_launch(w, link):
  309. os.system("xdg-open "+link)
  310. def link_resolve(w, link):
  311. win.url.set_text(link)
  312. win.url.activate()
  313. optionsthing = Gtk.Popover()
  314. optbox = Gtk.VBox()
  315. optionsthing.add(optbox)
  316. opt_launch = Gtk.Button("Launch")
  317. optbox.pack_start(opt_launch, False, False, False)
  318. opt_resolve = Gtk.Button("Resolve")
  319. optbox.pack_start(opt_resolve, False, False, False)
  320. opt_launch.connect("clicked", link_launch, i[-1])
  321. opt_resolve.connect("clicked", link_resolve, i[-1])
  322. optbox.show_all()
  323. link = Gtk.MenuButton(label=i[1], popover=optionsthing)
  324. link.set_tooltip_text(i[-1])
  325. anchor = Gtk.TextChildAnchor()
  326. text_buffer.insert_child_anchor(en, anchor)
  327. text_view.add_child_at_anchor(link, anchor)