render.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. # THIS SOFTWARE IS A PART OF FREE COMPETITOR PROJECT
  2. # THE FOLLOWING SOURCE CODE I UNDER THE GNU
  3. # AGPL LICENSE V3 OR ANY LATER VERSION.
  4. # This project is not for simple users, but for
  5. # web-masters and a like, so we are counting on
  6. # your ability to set it up and running.
  7. import os
  8. from modules import search
  9. def html(page, json):
  10. # This function adds a rendering of the json into the page
  11. free = search.is_free(json)
  12. name = json.get("names",["Unknown"])[0]
  13. page = page + """
  14. <!-- For each software in the list we do mostly the same things.
  15. And here it is. First we show it's name as a link to be able
  16. to search Free Competitors to what is found. -->
  17. """
  18. page = page + "\n <a href=\"/"+name.replace(" ", "+").lower()+"\">"
  19. page = page + "\n <h1>"
  20. try:
  21. page = page + '\n <img src="'+ json["links"]["icon"] + '" alt="[LOGO]" style="height:50px;"> <!-- The logo of the software in question.-->\n'
  22. except:
  23. pass
  24. page = page + " "+ name +" <!-- The title of the program -->\n"
  25. page = page + " </h1>\n </a>\n\n"
  26. page = page + """
  27. <!-- Next there is a short paragraph about the program.
  28. ( Often Copypasted from some official page about it ).
  29. Which means, it may contain the terrible words "Open Source"
  30. that hide the fact that Free Software is about User Freedom
  31. first of all. So we are trying to link to a special page on
  32. GNU.ORG if such a thing is found -->
  33. """
  34. # Few words about it
  35. comment = json.get("comment","")
  36. not_foss = ['open source', 'open-source']
  37. if "open source" or "open-source" in comment.lower():
  38. # Well... Here is a thing. Free Software, not open source.
  39. where = comment.lower().find("open source")
  40. # In case it has a slash in it.
  41. if where == -1:
  42. where = comment.lower().find("open-source")
  43. ops = comment[where:where+11]
  44. if ops:
  45. comment = comment.replace(ops,
  46. "<a href=\"https://www.gnu.org/philosophy/open-source-misses-the-point.en.html\">"+ops+"</a>")
  47. page = page + "\n <p>\n "+comment+"\n </p>\n\n"
  48. # I want to show nothing else from if it's proprietary
  49. issues_files = list(os.listdir("data/issues"))
  50. if "issues" in json:
  51. l = json.get("issues", [])
  52. page = page +"<h2>Anti-Features / Problems:</h2>"
  53. for i in l:
  54. if i+".html" not in issues_files:
  55. page = page + "&nbsp;&nbsp;"+i+"<br>"
  56. else:
  57. page = page + '<details title="Read about '+i+'">'
  58. page = page + "<summary>&nbsp;&nbsp"+i+"</summary>"
  59. issuefile = open("data/issues/"+i+".html")
  60. page = page + "<span><p>"+issuefile.read()+"</p></span>"
  61. page = page + "</details>"
  62. if not free:
  63. return page
  64. # Links
  65. page = page + """
  66. <!-- To organize the buttons with the main links we are using
  67. a table. But since I don't know what CSS file the maintainer
  68. will choose. And I want the table to be invisible. I insert here
  69. a bit of CSS code. -->
  70. """
  71. page = page + """
  72. <style>
  73. table, th, td {
  74. border-right:none;
  75. border-left:none;
  76. border-bottom:none;
  77. border-top:none
  78. }
  79. </style>
  80. <!-- And now the table itself. -->
  81. """
  82. page = page + "<table><tr>"
  83. linksfilter = {"git":"source"}
  84. links = json.get("links", {})
  85. for website in links:
  86. if website in ["icon"]:
  87. continue
  88. link = links[website]
  89. page = page + """
  90. <!-- Here's how to do a simple button -->
  91. <th>
  92. <form action=\""""+link+"""\"> <!-- You make a form with a link -->
  93. <button title=\""""+link+"""\" type="submit">"""+linksfilter.get(website,website).upper()+"""</button> <!-- And you activare that form with a button -->
  94. </form>
  95. </th>
  96. """
  97. page = page + "</tr></table>"
  98. page = page + """
  99. <!-- Details are those little collapsable things that I like to
  100. use very much. It's very simple really. Just read the code
  101. carefully and you will get it -->
  102. """
  103. # Details
  104. categories = {"generic_name":"Features",
  105. "licenses":"License(s)",
  106. "platforms":"Platforms",
  107. "networks_read":"Accesses Data from",
  108. "networks_write":"Interacts / Publishes to",
  109. "formats_read":"Opens from File-Formats",
  110. "formats_write":"Saves to File-Formats",
  111. "interface":"Interface",
  112. "languages":"Programming Languages"}
  113. for c in categories:
  114. l = json.get(c, [])
  115. if not l:
  116. continue
  117. # I want to look whether this category has a list of files
  118. alldata = list(os.listdir("data"))
  119. allfiles = []
  120. for folder in alldata:
  121. if c.startswith(folder):
  122. try:
  123. allfiles = list(os.listdir("data/"+folder))
  124. break
  125. except:
  126. pass
  127. # Count matches
  128. matches = 0
  129. for i in l:
  130. if i.startswith("*"):
  131. matches += 1
  132. if matches:
  133. matchtext = "<i>( "+str(matches)+" )</i>"
  134. else:
  135. matchtext = ""
  136. page = page + "\n\n <details>"
  137. page = page +"\n <summary>"+categories[c]+": "+matchtext+"</summary>"
  138. for i in l:
  139. matchtext = ""
  140. if i.startswith("*"):
  141. i = i[1:]
  142. matchtext = "&nbsp;&nbsp;&nbsp;&nbsp;<i>( match )</i> "
  143. if i+".html" in allfiles:
  144. datapage = open("data/"+folder+"/"+i+".html")
  145. page = page + """
  146. <!-- Just so happened that about \""""+i+"""\" we had a file
  147. in data/"""+folder+""" folder. So why not make a detail inside a detail,
  148. a detail-sception, so to speak. And add the text of explanation into it. -->
  149. """
  150. page = page + "<details>\n"
  151. page = page + " <summary>&nbsp;&nbsp;&nbsp;&nbsp;"+matchtext+i+"</summary>\n"
  152. page = page + " <span>\n <p>\n"
  153. page = page + " " + datapage.read()+"\n"
  154. page = page + " </p>\n </span>\n </details>"
  155. else:
  156. page = page + "\n <span>&nbsp;&nbsp;&nbsp;&nbsp;"+matchtext+i+"</span>\n <br>\n"
  157. page = page + """
  158. <!-- Just a tiny space after all the spans. So no to feel
  159. too crowded, so to speak -->
  160. <span><br></span>
  161. </details>
  162. """
  163. return page
  164. def suggestions(page, json):
  165. # This function will render suggestions
  166. page = page + """
  167. <!-- ===========================================================
  168. This is where ther actual competitors are starting to show!!!
  169. ============================================================ -->
  170. <h1>Free Competitors:</h1>
  171. """
  172. found = search.suggest(json)
  173. biggest = 0
  174. for i in found:
  175. if i[0] > biggest:
  176. biggest = i[0]
  177. more = False
  178. for i in found:
  179. free = search.is_free(i[-1])
  180. if not i[0] or i[-1]["names"] == json["names"] or not free:
  181. continue
  182. try:
  183. frac = int(i[0]/biggest*100)
  184. except:
  185. frac = 0
  186. if frac < 20 and not more: # Below 40% features match
  187. page = page + """
  188. <!-- Sometimes the suggestion is not very good. Below 40%
  189. of suggestion score. But it still kind of valid. So we
  190. want to put it into the page. Only when the user clicks
  191. something. Why not using the same old details? -->
  192. <hr>
  193. <details>
  194. <summary><h1 title="Click to show more / less.">Problematic Competitors:</h1></summary>
  195. """
  196. more = True
  197. page = page +"""
  198. <hr>
  199. <!-- ================================================================== -->
  200. """
  201. page = page + "<br>Suggestion score: " + str(frac) + "%"
  202. page = html(page, i[-1])
  203. if more:
  204. page = page + "</details>"
  205. return page
  206. def search_widget(page, address):
  207. # Adds a search bar to the page
  208. page = page + """
  209. <!-- Search widget! This widget makes it possible to implement
  210. a search feature without using a single line of JavaScript code.
  211. In HTML, there is an input field that we can use. If we pare it
  212. with a button into a <form>, we can get a button that activates
  213. the search. -->
  214. <form action="""
  215. page = page + address
  216. page = page + """search method="GET">
  217. <input type="text" name="item" class="search" placeholder="Name of Software">
  218. <button type="submit">Search</button>
  219. </form>
  220. <!-- And that's it for the search widget -->
  221. """
  222. #page = page.format(ADDRESS)
  223. return page
  224. def source_code_link(page):
  225. # Adds a source code link
  226. page = page + """
  227. <!-- This the the footer of every page -->
  228. <br>
  229. <br>
  230. <hr>
  231. <p>This website is under the GNU AGPL license.</p>
  232. <!-- As always I want to add a bit of CSS to make tables
  233. invisible -->
  234. <style>
  235. table, th, td {
  236. border-right:none;
  237. border-left:none;
  238. border-bottom:none;
  239. border-top:none
  240. }
  241. </style>
  242. <!-- This is self explanatory ( if you read most of the page ) -->
  243. <table><tr>
  244. <th><form action=https://notabug.org/jyamihud/FreeCompetitors>
  245. <button title="See the full source code of the software that powers this website." type="submit">SOURCE</button>
  246. </form></th>
  247. <th><form action=/faq>
  248. <button title="Frequently Asked Questions" type="submit">FAQ</button>
  249. </form></th>
  250. <th><form action=https://notabug.org/jyamihud/FreeCompetitors/issues>
  251. <button title="Report a bug." type="submit">BUG?</button>
  252. </form></th>
  253. <th><form action=https://notabug.org/jyamihud/FreeCompetitors/issues/25>
  254. <button title="Report a piece of software that's missing from the catalogue." type="submit">MISSING?</button>
  255. </form></th>
  256. <th><form action=https://notabug.org/jyamihud/FreeCompetitors/issues/24>
  257. <button title="Report a mistake in data about software." type="submit">MISTAKE?</button>
  258. </form></th></tr>
  259. </table>
  260. <br>
  261. <br>
  262. <!-- And this was the page of Free Competitors. No Javascript.
  263. No crap. No trackers. No nothing. And still works. Take that
  264. Google!!! -->
  265. """
  266. return page