Update modules/render.py

This commit is contained in:
Madiator2011 2024-04-29 18:17:57 +02:00
parent c857e51c56
commit 838ac5719d

View file

@ -13,42 +13,36 @@ from modules import missing
def html(page, json): def html(page, json):
# This function adds a rendering of the json into the page # This function adds a rendering of the json into the page
free = search.is_free(json) free = search.is_free(json)
name = json.get("names",["Unknown"])[0] name = json.get("names", ["Unknown"])[0]
page = page + """ page = page + """
<!-- For each software in the list we do mostly the same things. <!-- For each software in the list we do mostly the same things.
And here it is. First we show it's name as a link to be able And here it is. First we show it's name as a link to be able
to search Free Competitors to what is found. --> to search Free Competitors to what is found. -->
""" """
page = page + "\n <a href=\"/"+name.replace(" ", "+").lower()+"\">" page = page + "\n <a href=\"/" + name.replace(" ", "+").lower() + "\">"
page = page + "\n <h1>" page = page + "\n <h1 class=\"software-heading\">"
try: try:
page = page + '\n <img src="'+ json["links"]["icon"] + '" alt="[LOGO]" style="height:50px;"> <!-- The logo of the software in question.-->\n' page = page + '\n <span class="software-logo"><img src="' + json["links"]["icon"] + '" alt="[LOGO]" style="height:50px;"></span>'
except: except:
pass pass
page = page + " "+ name +" <!-- The title of the program -->\n" page = page + "<span class=\"software-name\">" + name + "</span>\n"
page = page + " </h1>\n </a>\n\n" page = page + " </h1>\n </a>\n\n"
page = page + """ page = page + """
<!-- Next there is a short paragraph about the program. <!-- Next there is a short paragraph about the program.
( Often Copypasted from some official page about it ). (Often Copypasted from some official page about it).
Which means, it may contain the terrible words "Open Source" Which means, it may contain the terrible words "Open Source"
that hide the fact that Free Software is about User Freedom that hide the fact that Free Software is about User Freedom
first of all. So we are trying to link to a special page on first of all. So we are trying to link to a special page on
GNU.ORG if such a thing is found --> GNU.ORG if such a thing is found -->
""" """
# Few words about it # Few words about it
comment = json.get("comment","") comment = json.get("comment", "")
not_foss = ['open source', 'open-source'] not_foss = ['open source', 'open-source']
if "open source" or "open-source" in comment.lower(): if "open source" or "open-source" in comment.lower():
# Well... Here is a thing. Free Software, not open source. # Well... Here is a thing. Free Software, not open source.
@ -56,74 +50,69 @@ def html(page, json):
# In case it has a slash in it. # In case it has a slash in it.
if where == -1: if where == -1:
where = comment.lower().find("open-source") where = comment.lower().find("open-source")
ops = comment[where:where+11] ops = comment[where:where + 11]
if ops: if ops:
comment = comment.replace(ops, comment = comment.replace(ops,
"<a href=\"https://www.gnu.org/philosophy/open-source-misses-the-point.en.html\">"+ops+"</a>") "<a href=\"https://www.gnu.org/philosophy/open-source-misses-the-point.en.html\">" + ops + "</a>")
page = page + "\n <p>\n "+comment+"\n </p>\n\n" page = page + "\n <p class=\"software-comment\">\n " + comment + "\n </p>\n\n"
# I want to show nothing else from if it's proprietary # I want to show nothing else from if it's proprietary
issues_files = list(os.listdir("data/issues")) issues_files = list(os.listdir("data/issues"))
if "issues" in json and json["issues"]: if "issues" in json and json["issues"]:
l = json.get("issues", []) l = json.get("issues", [])
page = page +"<h2>Anti-Features / Problems:</h2>" page = page + "<h2>Anti-Features / Problems:</h2>"
page = page + "<ul class=\"anti-features\">"
for i in l: for i in l:
if i+".html" not in issues_files: if i + ".html" not in issues_files:
page = page + "&nbsp;&nbsp;"+i+"<br>" page = page + "<li>" + i + "</li>"
else: else:
page = page + '<details title="Read about '+i+'">' page = page + '<li><details title="Read about ' + i + '">'
page = page + "<summary>&nbsp;&nbsp"+i+"</summary>" page = page + "<summary>" + i + "</summary>"
issuefile = open("data/issues/"+i+".html") issuefile = open("data/issues/" + i + ".html")
page = page + "<span><p>"+issuefile.read()+"</p></span>" page = page + "<span><p>" + issuefile.read() + "</p></span>"
page = page + "</details>" page = page + "</details></li>"
page = page + "</ul>"
if not free: if not free:
return page return page
# Links # Links
page = page + """ page = page + """
<!-- And now the table itself. --> <!-- And now the table itself. -->
""" """
linksfilter = {"git":"source code","fsd":"Free Software Directory"} linksfilter = {"git": "source code", "fsd": "Free Software Directory"}
links = json.get("links", {}) links = json.get("links", {})
for website in links: for website in links:
if website in ["icon"]: if website in ["icon"]:
continue continue
link = links[website] link = links[website]
page = page + """ page = page + """
<!-- Here's how to do a simple button --> <!-- Here's how to do a simple button -->
<a class="button" href=\""""+link+"""\" title=\""""+link+"""\">"""+linksfilter.get(website,website).upper()+"""</a> <a class="button" href=\"""" + link + """\" title=\"""" + link + """\">""" + linksfilter.get(website,
website).upper() + """</a>
""" """
page = page + """ page = page + """
<!-- Details are those little collapsable things that I like to <!-- Details are those little collapsable things that I like to
use very much. It's very simple really. Just read the code use very much. It's very simple really. Just read the code
carefully and you will get it --> carefully and you will get it -->
""" """
# Details
categories = {"generic_name":"Features", # Details
"licenses":"License(s)", categories = {"generic_name": "Features",
"platforms":"Platforms", "licenses": "License(s)",
"networks_read":"Accesses Data from", "platforms": "Platforms",
"networks_write":"Interacts / Publishes to", "networks_read": "Accesses Data from",
"formats_read":"Opens from File-Formats", "networks_write": "Interacts / Publishes to",
"formats_write":"Saves to File-Formats", "formats_read": "Opens from File-Formats",
"interface":"Interface", "formats_write": "Saves to File-Formats",
"languages":"Programming Languages"} "interface": "Interface",
"languages": "Programming Languages"}
for c in categories: for c in categories:
l = json.get(c, []) l = json.get(c, [])
if not l: if not l:
continue continue
@ -134,70 +123,64 @@ def html(page, json):
for folder in alldata: for folder in alldata:
if c.startswith(folder): if c.startswith(folder):
try: try:
allfiles = list(os.listdir("data/"+folder)) allfiles = list(os.listdir("data/" + folder))
break break
except: except:
pass pass
# Count matches # Count matches
matches = 0 matches = 0
for i in l: for i in l:
if i.startswith("*"): if i.startswith("*"):
matches += 1 matches += 1
if matches: if matches:
matchtext = "<i>( "+str(matches)+" )</i>" matchtext = "<i>( " + str(matches) + " )</i>"
else: else:
matchtext = "" matchtext = ""
page = page + "\n\n <details>" page = page + "\n\n <details>"
page = page +"\n <summary>"+categories[c]+": "+matchtext+"</summary>" page = page + "\n <summary>" + categories[c] + ": " + matchtext + "</summary>"
for i in l: for i in l:
matchtext = "" matchtext = ""
if i.startswith("*"): if i.startswith("*"):
i = i[1:] i = i[1:]
matchtext = "&nbsp;&nbsp;&nbsp;&nbsp;<i>( match )</i> " matchtext = "&nbsp;&nbsp;&nbsp;&nbsp;<i>( match )</i> "
if i+".html" in allfiles:
datapage = open("data/"+folder+"/"+i+".html") if i + ".html" in allfiles:
datapage = open("data/" + folder + "/" + i + ".html")
page = page + """ page = page + """
<!-- Just so happened that about \"""" + i + """\" we had a file
<!-- Just so happened that about \""""+i+"""\" we had a file in data/""" + folder + """ folder. So why not make a detail inside a detail,
in data/"""+folder+""" folder. So why not make a detail inside a detail, a detail-sception, so to speak. And add the text of explanation into it. -->
a detail-sception, so to speak. And add the text of explanation into it. --> """
"""
page = page + "<details>\n" page = page + "<details>\n"
page = page + " <summary>&nbsp;&nbsp;&nbsp;&nbsp;"+matchtext+i+"</summary>\n" page = page + " <summary>&nbsp;&nbsp;&nbsp;&nbsp;" + matchtext + i + "</summary>\n"
page = page + " <span>\n <p>\n" page = page + " <span>\n <p>\n"
page = page + " " + datapage.read()+"\n" page = page + " " + datapage.read() + "\n"
page = page + " </p>\n </span>\n </details>" page = page + " </p>\n </span>\n </details>"
else: else:
page = page + "\n <span>&nbsp;&nbsp;&nbsp;&nbsp;"+matchtext+i+"</span>\n <br>\n" page = page + "\n <span>&nbsp;&nbsp;&nbsp;&nbsp;" + matchtext + i + "</span>\n <br>\n"
page = page + """ page = page + """
<!-- Just a tiny space after all the spans. So no to feel <!-- Just a tiny space after all the spans. So no to feel
too crowded, so to speak --> too crowded, so to speak -->
<span><br></span> <span><br></span>
</details> </details>
""" """
return page return page
def suggestions(page, json): def suggestions(page, json):
# This function will render suggestions # This function will render suggestions
page = page + """ page = page + """
<!-- =========================================================== <!-- ===========================================================
This is where ther actual competitors are starting to show!!! This is where ther actual competitors are starting to show!!!
============================================================ --> ============================================================ -->
<div class="suggestions-container">
<h1>Free Competitors:</h1> <h1 class="competitors-heading">Free Competitors:</h1>
""" """
found = search.suggest(json) found = search.suggest(json)
@ -219,24 +202,19 @@ def suggestions(page, json):
if frac < 10 and not more: # Below 10% features match if frac < 10 and not more: # Below 10% features match
page = page + """ page = page + """
<!-- Sometimes the suggestion is not very good. Below 10% <!-- Sometimes the suggestion is not very good. Below 10%
of suggestion score. But it still kind of valid. So we of suggestion score. But it still kind of valid. So we
want to put it into the page. Only when the user clicks want to put it into the page. Only when the user clicks
something. Why not using the same old details? --> something. Why not using the same old details? -->
<hr> <hr>
<details> <details>
<summary><h1 title="Click to show more / less.">Problematic Competitors:</h1></summary> <summary><h2 class="problematic-heading" title="Click to show more / less.">Problematic Competitors:</h2></summary>
""" """
more = True more = True
page = page +""" page = page +"""
<br><br> <br><br>
<!-- ================================================================== --> <!-- ================================================================== -->
""" """
page = progress(page, frac/100, "Suggestion score: " + str(frac) + "%") page = progress(page, frac/100, "Suggestion score: " + str(frac) + "%")
@ -244,80 +222,65 @@ def suggestions(page, json):
if more: if more:
page = page + "</details>" page = page + "</details>"
page = page + "</div>" # Close the suggestions-container
return page return page
def search_widget(page, address): def search_widget(page, address):
# Adds a search bar to the page # Adds a search bar to the page
page = page + """ page = page + """
<!-- Search widget! This widget makes it possible to implement <!-- Search widget! This widget makes it possible to implement
a search feature without using a single line of JavaScript code. a search feature without using a single line of JavaScript code.
In HTML, there is an input field that we can use. If we pare it In HTML, there is an input field that we can use. If we pare it
with a button into a <form>, we can get a button that activates with a button into a <form>, we can get a button that activates
the search. --> the search. -->
<form action=""" <form action="""
page = page + address page = page + address
page = page + """search method="GET"> page = page + """search method="GET" class="search-form">
<input type="text" name="item" class="search" placeholder="Name of Software"> <input type="text" name="item" class="search-input" placeholder="Name of Software">
<button type="submit">Search</button> <button type="submit" class="search-button">Search</button>
</form> </form>
<!-- And that's it for the search widget --> <!-- And that's it for the search widget -->
""" """
#page = page.format(ADDRESS)
return page return page
def source_code_link(page): def source_code_link(page):
# Adds a source code link # Adds a source code link
page = page + """ page = page + """
<!-- This is the footer of every page -->
<!-- This the the footer of every page --> <footer>
<div class="container">
<hr> <p>This website is under the GNU AGPL license.</p>
This website is under the GNU AGPL license. <div class="button-group">
<a class="button" href="/" title="Come back to the home page.">Home</a>
<!-- As always I want to add a bit of CSS to make tables <a class="button" href="https://notabug.org/jyamihud/FreeCompetitors" title="See the full source code of the software that powers this website.">Source Code</a>
invisible --> <a class="button" href="/faq" title="Frequently Asked Questions">FAQ</a>
<a class="button" href="https://notabug.org/jyamihud/FreeCompetitors/issues" title="Report a Bug.">Bug?</a>
<br><br> <a class="button" href="https://notabug.org/jyamihud/FreeCompetitors/issues/25" title="Report a piece of software that's missing from the catalogue.">Missing?</a>
<a class="button" href="https://notabug.org/jyamihud/FreeCompetitors/issues/24" title="Report a mistake in data about software.">Mistake?</a>
<a class="button" href="/" title="Come back to the home page.">HOME</a> <a class="button" href="/stats" title="See stats of this server.">Stats</a>
<a class="button" href="https://notabug.org/jyamihud/FreeCompetitors" title="See the full source code of the software that powers this website.">SOURCE CODE</a> </div>
<a class="button" href="/faq" title="Frequently Asked Questions">FAQ</a> </div>
<a class="button" href="https://notabug.org/jyamihud/FreeCompetitors/issues" title="Report a Bug.">BUG?</a> </footer>
<a class="button" href="https://notabug.org/jyamihud/FreeCompetitors/issues/25" title="Report a piece of software that's missing from the catalogue.">MISSING?</a> <!-- And this was the page of Free Competitors. No JavaScript.
<a class="button" href="https://notabug.org/jyamihud/FreeCompetitors/issues/24" title="Report a mistake in data about software.">MISTAKE?</a>
<a class="button" href="/stats" title="See stats of this server.">STATS</a>
<!-- And this was the page of Free Competitors. No Javascript.
No crap. No trackers. No nothing. And still works. Take that No crap. No trackers. No nothing. And still works. Take that
Google!!! --> Google!!! -->
"""
"""
return page return page
def progress(page, frac, text=""): def progress(page, frac, text=""):
# This will output a progress bar # This will output a progress bar
page = page + """ page = page + """
<!-- ============ PROGRESS BARS ============= <!-- ============ PROGRESS BARS =============
Note that the progress bars will be visible only Note that the progress bars will be visible only
if the CSS file is configured for the divs of if the CSS file is configured for the divs of
the progress bars. Otherwise it will just show the progress bars. Otherwise it will just show
the text. --> the text. -->
<div class="back_progress"> <div class="back_progress">
<div class="front_progress" style="width:"""+str(frac*100)+"""%"> <div class="front_progress" style="width:"""+str(frac*100)+"""%">
</div> </div>
@ -326,27 +289,24 @@ def progress(page, frac, text=""):
""" """
return page return page
def stats(page, mis=False, data=[]): def stats(page, mis=False, data=[]):
# Graph will require some math to work. # Graph will require some math to work.
# We are going to use CSS and HTML5 to # We are going to use CSS and HTML5 to
# draw it / interact with it. # draw it / interact with it.
spd = 60*60*24 # Seconds in each day spd = 60 * 60 * 24 # Seconds in each day
span = max(data) - min(data) # Time of seconds between first and last entry span = max(data) - min(data) # Time of seconds between first and last entry
days = span / spd # Time in days between first and last entry days = span / spd # Time in days between first and last entry
# making sure there is at least something to show # making sure there is at least something to show
if days < 20: if days < 20:
data.append(min(data)-(spd*20)) data.append(min(data) - (spd * 20))
spd = 60*60*24 spd = 60 * 60 * 24
span = max(data) - min(data) span = max(data) - min(data)
days = span / spd days = span / spd
widthfrac = 100 / days # the % to use for the width of each div
widthfrac = 100 / days # the % to use for the width of each div
# Count how much hits happen per each day # Count how much hits happen per each day
biggest = 0 biggest = 0
@ -354,36 +314,38 @@ def stats(page, mis=False, data=[]):
for d in range(int(round(days))): for d in range(int(round(days))):
count = 0 count = 0
for i in data: for i in data:
day = min(data) + (d*spd) day = min(data) + (d * spd)
if int(i) in range(int(day), int(day+spd)): if int(i) in range(int(day), int(day + spd)):
count += 1 count += 1
if count > biggest: if count > biggest:
biggest = count biggest = count
day_counts.append(count) day_counts.append(count)
# Render them # Render them
page = page +"<center>" page = page + "<center>"
for n, d in enumerate(day_counts): for n, d in enumerate(day_counts):
if n == 0: if n == 0:
d -= 1 d -= 1
dayis = min(data)+(n*spd) dayis = min(data) + (n * spd)
dayis = time.strftime("%Y/%m/%d", time.gmtime( dayis) ) dayis = time.strftime("%Y/%m/%d", time.gmtime(dayis))
page = page + '<div class="front_progress" title="'+str(dayis)+' : '+str(d)+' visitors" style="height:400; position:absolute; top:5%; left:calc(99vw/'+str(days)+'*'+str(n)+') ;width:'+str(widthfrac)+'%">\n' page = page + '<div class="front-progress" title="' + str(dayis) + ' : ' + str(
frac = 100-(d/biggest*99) d) + ' visitors" style="height:400; position:absolute; top:5%; left:calc(99vw/' + str(
page = page + '<div class="back_progress" style="height:'+str(frac)+'%; bottom:'+str(frac)+'%"></div></div>\n\n' days) + '*' + str(n) + ') ;width:' + str(widthfrac) + '%">\n'
frac = 100 - (d / biggest * 99)
page = page + '<div class="back-progress" style="height:' + str(frac) + '%; bottom:' + str(
frac) + '%"></div></div>\n\n'
page = page + '\n</center>\n\n<div style="position:absolute; top:500">' page = page + '\n</center>\n\n<div style="position:absolute; top:500">'
# If to render missing software # If to render missing software
# TODO: We had a list of missing software which are known of, # TODO: We had a list of missing software which are known of,
# but people abused this feature to add a bunch of hilarious spam. # but people abused this feature to add a bunch of hilarious spam.
# maybe there is a way to design this better. # maybe there is a way to design this better.
#if mis: # if mis:
# page = page + missing.List_html() # page = page + missing.List_html()
page = source_code_link(page) page = source_code_link(page)
return page return page