Skip to content

Commit

Permalink
Major parts of html generation implemented; base64 encoding for inlin…
Browse files Browse the repository at this point in the history
…ing different media is working
  • Loading branch information
Istvan Bozso committed Mar 2, 2020
1 parent d340109 commit 1ec8538
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 106 deletions.
18 changes: 9 additions & 9 deletions utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from .base import *
from .path import *
from .enforce import *
from .cli import *
from .cmd import *
from .ninja import *
from .project import *
from .simpledoc import *
from .html import *
from utils.base import *
from utils.path import *
from utils.enforce import *
from utils.cli import *
from utils.cmd import *
from utils.ninja import *
from utils.project import *
from utils.simpledoc import *
from utils.html import *
8 changes: 5 additions & 3 deletions utils/html/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from .html import *
from .tag import *
from .jslibs import *
from utils.html.encoder import *
from utils.html.base import *
from utils.html.tag import *
from utils.html.doc import *
from utils.html.jslibs import *
70 changes: 10 additions & 60 deletions utils/html/html.py → utils/html/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,14 @@
simpledoc.py.
"""

import base64
import os.path as path

from utils.base import export
from utils.simpledoc import SimpleDoc, _attributes

class Encoder(object):
__slots__ = (
"encoder",
)

klass2ext = {
"text" : frozenset({
"js", "css",
}),

"video" : frozenset({
"mp4",
}),

"image": frozenset({
"png", "jpg",
}),
}

tpl = "data:{klass}/{mode};charset=utf-8;base64,{data}"

ext2klass = {v: k for k, v in klass2ext.items()}

convert = {
"js": "javascript",
}

def __init__(self, *args, **kwargs):
self.encoder = kwargs.get("encoder", base64.b64encode)


def __call__(self, media_path):
mode = ext = path.splitext(media_path)[1].strip(".")

for key, val in self.ext2klass.items():
if ext in key:
klass = val
break

if mode in self.convert:
mode = convert[ext]

with open(media_path, "rb") as f:
data = self.encoder(f.read())

return self.tpl.format(
klass=klass, mode=mode, data=data.decode("utf-8")
)


encoder = Encoder()

__all__ = (
"ImagePaths", "HTML", "Library",
)

class ImagePaths(object):
__slots__ = ("paths", "doc", "width",)
Expand Down Expand Up @@ -122,7 +72,7 @@ def img(self, name, *args, **kwargs):
def noencode(path):
return path

@export

class HTML(SimpleDoc):
__slots__ = (
"encoder",
Expand Down Expand Up @@ -209,12 +159,12 @@ def inner(self, *args, **kwargs):

return inner

tags = {
_tags = {
"div", "head", "header", "body", "html", "center", "ul", "ol",
"script", "style", "section", "video", "table", "tr"
}

for tag in tags:
for tag in _tags:
setattr(HTML, tag, make_tag(tag))

#########
Expand All @@ -227,11 +177,11 @@ def inner(self, *args, **kwargs):

return inner

stags = {
_stags = {
"meta", "iframe",
}

for stag in stags:
for stag in _stags:
setattr(HTML, stag, make_stag(stag))


Expand All @@ -246,12 +196,12 @@ def inner(self, text_contents, *args, **kwargs):

return inner

lines = {
_lines = {
"h1", "h2", "h3", "h4", "p", "li", "b", "q", "u", "em",
"it", "del", "strong", "th", "td", "font",
}

for line in lines:
for line in _lines:
setattr(HTML, line, make_line(line))


Expand Down
71 changes: 71 additions & 0 deletions utils/html/doc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from utils.html import Children, st, Options

__all__ = (
"Doc",
)

class Viewport(Options):
default_values = {
"width": "device-width",
"initial_scale": 1.0,
}

template = "%s=%s"
joiner = ","

def __init__(self, **kwargs):
self.options = self.default_values
self.options.update(**kwargs)


class Doc(Children):
__slots__ = (
"filename", "children", "description", "keywords", "author",
"viewport", "encoder",
)

def __init__(self, *args, filename=None, desc="", keywords=[],
author="", viewport={}, encoder=None):

self.filename, self.description, self.keywords, self.author, \
self.viewport, self.encoder = (
filename, desc, keywords, author,
Viewport(**viewport), encoder
)

self.children = ["<!DOCTYPE html>"] + list(args)

def meta(self):
kw = self.keywords

if len(kw) == 0:
kw = ""
else:
kw = ",".join(kw)

return (
st.meta(charset="utf-8"),
st.meta(name="description", content=self.description),
st.meta(name="keywords", content=kw),
st.meta(name="author", content=self.author),
st.meta(name="viewport", content=self.viewport.parse_options()),
)

def append(self, *args):
self.children.append(args)

def write_to(self, writer):
enc = self.encoder

if enc is not None:
enc.encode_children(self.children)

writer.write(self.render_children())

def to_file(self, filename=None):
if filename is None:
filename = self.filename

with open(filename, "w") as f:
self.write_to(f)

95 changes: 95 additions & 0 deletions utils/html/encoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import re
import requests
import os.path as path
from base64 import b64encode

from utils import str_t

__all__ = (
"Encoder", "url_regex",
)

url_regex = re.compile("^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$")

class Encoder(object):
__slots__ = (
"encoder",
)

klass2ext = {
"text" : frozenset({
"js", "css",
}),

"video" : frozenset({
"mp4",
}),

"image": frozenset({
"png", "jpg",
}),
}

tpl = "data:{klass}/{mode};charset=utf-8;base64,{data}"

ext2klass = {v: k for k, v in klass2ext.items()}

convert = {
"js": "javascript",
}

def __init__(self, encoder=b64encode):
self.encoder = encoder

def encode_child(self, child):
if isinstance(child, str_t):
return

enc = child.encode

if enc is None:
return

child.options[enc] = self(child.options[enc])

def encode_children(self, children):
for child in children:
if isinstance(child, str_t):
continue

try:
self.encode_children(child.children)
except AttributeError:
self.encode_child(child)

@staticmethod
def load_media(media_path):
if path.isfile(media_path):
with open(media_path, "rb") as f:
return f.read()

if url_regex.match(media_path) is None:
raise TypeError("Given path ('%s') to encodable media is "
"not a valid URL or valid filepath!" % media_path)

response = requests.get(media_path)
response.raise_for_status()

return response.content

def __call__(self, media_path):
mode = ext = path.splitext(media_path)[1].strip(".")

for key, val in self.ext2klass.items():
if ext in key:
klass = val
break

if mode in self.convert:
mode = convert[ext]

data = self.encoder(self.load_media(media_path))

return self.tpl.format(
klass=klass, mode=mode, data=data.decode("utf-8")
)
11 changes: 5 additions & 6 deletions utils/html/jslibs.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from utils import namespace, export
from .html import Library
from utils import namespace
from utils.html import Library

__all__ = [
"libs", "plotly",
]
__all__ = (
"libs", "plotly", "Plotly",
)

class JSLib(Library):
__slots__ = (
Expand Down Expand Up @@ -33,7 +33,6 @@ def add(self, doc, *args, **kwargs):
jquery=JSLib(path="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"),
)

@export
class Plotly(JSLib):
base = "https://cdn.plot.ly/plotly-{version}.min.js"
partial = "https://cdn.plot.ly/plotly-{partial}-{version}.min.js"
Expand Down
Loading

0 comments on commit 1ec8538

Please sign in to comment.