pour le moment incapable de décider si ansirenderer doit prendre le path du fichier ou directement le texte en input

This commit is contained in:
Lionel Dricot 2023-07-21 01:03:40 +02:00
parent ce65850987
commit cd3177ac87
2 changed files with 112 additions and 91 deletions

View File

@ -9,6 +9,7 @@ import time
import html
import urllib
import argparse
import mimetypes
from offutils import run,term_width
try:
from readability import Document
@ -704,6 +705,8 @@ class GopherRenderer(AbstractRenderer):
class FolderRenderer(GemtextRenderer):
#it was initialized with:
#self.renderer = FolderRenderer("",self.get_cache_path(),datadir=_DATA_DIR)
def __init__(self,content,url,center=True,datadir=None):
GemtextRenderer.__init__(self,content,url,center)
self.datadir = datadir
@ -1124,24 +1127,124 @@ class HtmlRenderer(AbstractRenderer):
recursive_render(soup)
return r.get_final(),links
def render(text,format):
# Mapping mimetypes with renderers
# (any content with a mimetype text/* not listed here will be rendered with as GemText)
_FORMAT_RENDERERS = {
"text/gemini": GemtextRenderer,
"text/html" : HtmlRenderer,
"text/xml" : FeedRenderer,
"application/xml" : FeedRenderer,
"application/rss+xml" : FeedRenderer,
"application/atom+xml" : FeedRenderer,
"text/gopher": GopherRenderer,
"image/*": ImageRenderer
}
def get_mime(path):
#Beware, this one is really a shaddy ad-hoc function
if path.startswith("mailto:"):
mime = "mailto"
elif os.path.isdir(path):
mime = "Local Folder"
elif path.endswith(".gmi"):
mime = "text/gemini"
elif shutil.which("file") :
mime = run("file -b --mime-type %s", parameter=path).strip()
mime2,encoding = mimetypes.guess_type(path,strict=False)
#If we hesitate between html and xml, takes the xml one
#because the FeedRendered fallback to HtmlRenderer
if mime2 and mime != mime2 and "html" in mime and "xml" in mime2:
mime = "text/xml"
# If its a xml file, consider it as such, regardless of what file thinks
elif path.endswith(".xml"):
mime = "text/xml"
#Some xml/html document are considered as octet-stream
if mime == "application/octet-stream":
mime = "text/xml"
else:
mime,encoding = mimetypes.guess_type(path,strict=False)
#gmi Mimetype is not recognized yet
if not mime and not shutil.which("file") :
print("Cannot guess the mime type of the file. Please install \"file\".")
print("(and send me an email, Im curious of systems without \"file\" installed!")
if mime.startswith("text") and mime not in _FORMAT_RENDERERS:
if mime2 and mime2 in _FORMAT_RENDERERS:
mime = mime2
else:
#by default, we consider its gemini except for html
mime = "text/gemini"
return mime
def set_renderer(content,url,mime):
renderer = None
if mime == "Local Folder":
renderer = FolderRenderer("",url,datadir=_DATA_DIR)
return renderer
mime_to_use = []
for m in _FORMAT_RENDERERS:
if fnmatch.fnmatch(mime, m):
mime_to_use.append(m)
if len(mime_to_use) > 0:
current_mime = mime_to_use[0]
func = _FORMAT_RENDERERS[current_mime]
if current_mime.startswith("text"):
renderer = func(content,url)
# We double check if the renderer is correct.
# If not, we fallback to html
# (this is currently only for XHTML, often being
# mislabelled as xml thus RSSfeeds)
if not renderer.is_valid():
func = _FORMAT_RENDERERS["text/html"]
#print("Set (fallback)RENDERER to html instead of %s"%mime)
renderer = func(content,url)
else:
#TODO: check this code and then remove one if.
#we dont parse text, we give the file to the renderer
renderer = func(content,url)
if not renderer.is_valid():
renderer = None
return renderer
def render(input,format="auto",mime=None,url=None):
if mime and not format or format=="auto":
format = get_format(input)
if format == "gemtext":
r = GemtextRenderer(text,"https://ploum.net")
r = GemtextRenderer(input,"https://ploum.net")
elif format == "html":
r = HtmlRenderer(text,"https://ploum.net")
r.display()
r = HtmlRenderer(input,"https://ploum.net")
elif format == "feed":
r = FeedRenderer(input,"https://ploum.net")
elif format == "gopher":
r = GopherRenderer(input,"https://ploum.net")
elif format == "image":
r = ImageRenderer(input,"https://ploum.net")
elif format == "folder":
r = FolderRenderer(input,"https://ploum.net")
else:
if not mime:
mime = get_mime(input)
r = set_renderer(input,url,mime)
print("renderer is %s"%r)
if r:
r.display()
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--format", choices=["gemtext","html","feed","gopher","image","folder"],
help="Renderer to use. Available: gemtext, html, feed, gopher, image, folder")
parser.add_argument("--format", choices=["auto","gemtext","html","feed","gopher","image","folder"],
help="Renderer to use. Available: auto, gemtext, html, feed, gopher, image, folder")
## The argument needs to be a path to a file. If none, then stdin is used which allows
## to pipe text directly into ansirenderer
parser.add_argument("input",metavar="INPUT", nargs="?", type=argparse.FileType("r"),
parser.add_argument("--url",metavar="URL", nargs="*",
help="Original URL of the content")
parser.add_argument("content",metavar="INPUT", nargs="*", type=argparse.FileType("r"),
default=sys.stdin, help="Path to the text to render (default to stdin)")
args = parser.parse_args()
render(args.input.read(),args.format)
print("Input: %s"%args.input)
#TODO: find when we have a text or a path.
# We cannot get mime from a text!
#render(args.input.read(),format=args.format,url=args.url)
if __name__ == '__main__':
main()

View File

@ -1,3 +1,4 @@
#TODO: remove the set_renderer then try to run offpunk
#!/usr/bin/env python3
# Offpunk Offline Gemini client
# Derived from AV-98 by Solderpunk,
@ -26,7 +27,6 @@ import fnmatch
import glob
import hashlib
import io
import mimetypes
import os
import os.path
import filecmp
@ -159,18 +159,6 @@ standard_ports = {
"https" : 443,
"spartan": 300,
}
# Mapping mimetypes with renderers
# (any content with a mimetype text/* not listed here will be rendered with as GemText)
_FORMAT_RENDERERS = {
"text/gemini": ansirenderer.GemtextRenderer,
"text/html" : ansirenderer.HtmlRenderer,
"text/xml" : ansirenderer.FeedRenderer,
"application/xml" : ansirenderer.FeedRenderer,
"application/rss+xml" : ansirenderer.FeedRenderer,
"application/atom+xml" : ansirenderer.FeedRenderer,
"text/gopher": ansirenderer.GopherRenderer,
"image/*": ansirenderer.ImageRenderer
}
# Offpunk is organized as follow:
# - a GeminiClient instance which handles the browsing of GeminiItems (= pages).
# - Theres only one GeminiClient. Each page is a GeminiItem (name is historical, as
@ -344,37 +332,6 @@ class GeminiItem():
else:
return []
def _set_renderer(self,mime=None):
if self.local and os.path.isdir(self.get_cache_path()):
self.renderer = ansirenderer.FolderRenderer("",self.get_cache_path(),datadir=_DATA_DIR)
return
if not mime:
mime = self.get_mime()
#we dont even have a mime (so probably we dont have a cache)
if not mime:
return
mime_to_use = []
for m in _FORMAT_RENDERERS:
if fnmatch.fnmatch(mime, m):
mime_to_use.append(m)
if len(mime_to_use) > 0:
current_mime = mime_to_use[0]
func = _FORMAT_RENDERERS[current_mime]
if current_mime.startswith("text"):
self.renderer = func(self.get_body(),self.url)
# We double check if the renderer is correct.
# If not, we fallback to html
# (this is currently only for XHTML, often being
# mislabelled as xml thus RSSfeeds)
if not self.renderer.is_valid():
func = _FORMAT_RENDERERS["text/html"]
#print("Set (fallback)RENDERER to html instead of %s"%mime)
self.renderer = func(self.get_body(),self.url)
else:
#we dont parse text, we give the file to the renderer
self.renderer = func(self.get_cache_path(),self.url)
if not self.renderer.is_valid():
self.renderer = None
def display(self,mode=None,grep=None):
if not self.renderer:
@ -415,45 +372,6 @@ class GeminiItem():
return tmpf
def get_mime(self):
#Beware, this one is really a shaddy ad-hoc function
if self.mime:
return self.mime
elif self.is_cache_valid():
path = self.get_cache_path()
if self.scheme == "mailto":
mime = "mailto"
elif os.path.isdir(path):
mime = "Local Folder"
elif path.endswith(".gmi"):
mime = "text/gemini"
elif shutil.which("file") :
mime = run("file -b --mime-type %s", parameter=path).strip()
mime2,encoding = mimetypes.guess_type(path,strict=False)
#If we hesitate between html and xml, takes the xml one
#because the FeedRendered fallback to HtmlRenderer
if mime2 and mime != mime2 and "html" in mime and "xml" in mime2:
mime = "text/xml"
# If its a xml file, consider it as such, regardless of what file thinks
elif path.endswith(".xml"):
mime = "text/xml"
#Some xml/html document are considered as octet-stream
if mime == "application/octet-stream":
mime = "text/xml"
else:
mime,encoding = mimetypes.guess_type(path,strict=False)
#gmi Mimetype is not recognized yet
if not mime and not shutil.which("file") :
print("Cannot guess the mime type of the file. Please install \"file\".")
print("(and send me an email, Im curious of systems without \"file\" installed!")
if mime.startswith("text") and mime not in _FORMAT_RENDERERS:
if mime2 and mime2 in _FORMAT_RENDERERS:
mime = mime2
else:
#by default, we consider its gemini except for html
mime = "text/gemini"
self.mime = mime
return self.mime
def set_error(self,err):
# If we get an error, we want to keep an existing cache