def inline_css(value: str) -> str: tree = lxml.html.document_fromstring(value) toronado.inline(tree) # CSS media query support is inconsistent when the DOCTYPE declaration is # missing, so we force it to HTML5 here. return lxml.html.tostring(tree, doctype="<!DOCTYPE html>", encoding=None).decode("utf-8")
def test_does_not_override_inlined_styles(self): tree = html.document_fromstring(""" <html> <head> <style type="text/css"> h1 { color: red; display: block; } </style> </head> <body> <h1 style="color: blue; font-weight: bold">Hello, world.</h1> </body> </html> """) inline(tree) heading, = tree.cssselect('h1') properties = Properties.from_string(heading.attrib['style']) self.assertEqual(properties, { 'color': 'blue', 'display': 'block', 'font-weight': 'bold', })
def get(self, **kwargs): cid = kwargs["pk"] # only Fetch enabled try: card = super().get(**kwargs) # trigger DoesNotExist if necessary if not card["html"]: contrib = Contributions.objects.only("project", "data").get(pk=cid) info = Projects.objects.get(pk=contrib.project.id) ctx = {"cid": cid} ctx["title"] = info.title ctx["descriptions"] = info.description.strip().split(".", 1) authors = [a.strip() for a in info.authors.split(",") if a] ctx["authors"] = {"main": authors[0], "etal": authors[1:]} ctx["landing_page"] = f"/{contrib.project.id}/" ctx["more"] = f"/{cid}" ctx["urls"] = info.urls.values() card_script = get_resource_as_string("templates/linkify.min.js") card_script += get_resource_as_string( "templates/linkify-element.min.js" ) card_script += get_resource_as_string("templates/card.min.js") fd = fdict(contrib.data, delimiter=".") ends = [f".{qk}" for qk in quantity_keys] for key in list(fd.keys()): if any(key.endswith(e) for e in ends): value = fd.pop(key) if key.endswith(ends[0]): new_key = key.rsplit(".", 1)[0] # drop .display fd[new_key] = value data = fd.to_dict_nested() browser = get_browser() browser.execute_script(card_script, data) bs = BeautifulSoup(browser.page_source, "html.parser") ctx["data"] = bs.body.table # browser.close() rendered = html_minify(render_template("card.html", **ctx)) tree = html.fromstring(rendered) inline(tree) card = Cards.objects.get(pk=cid) card.html = html.tostring(tree.body[0]).decode("utf-8") card.save() return super().get(**kwargs) except DoesNotExist: card = None try: card = Cards.objects.only("pk").get(pk=cid) except DoesNotExist: # Card has never been requested before # create and save unexecuted card, also start entry to avoid rebuild on subsequent requests contrib = Contributions.objects.only("project", "is_public").get(pk=cid) card = Cards(pk=cid, is_public=contrib.is_public) card.save() return self.get(**kwargs) if card is not None: raise DoesNotExist( f"Card {card.pk} exists but user not in project group" )
def rebuild_template(template_str): nodes = Template(template_str).compile_nodelist() expanded = expand_includes(nodes) tree = lxml.html.fromstring(nodelist_to_template(expanded)) links_to_style(tree) toronado.inline(tree) return lxml.html.tostring(tree)
def inline_css(value: str) -> str: """ Returns an HTML document with inline CSS. Forked from getsentry/sentry """ tree = lxml.html.document_fromstring(value) toronado.inline(tree) # CSS media query support is inconsistent when the DOCTYPE declaration is # missing, so we force it to HTML5 here. return lxml.html.tostring(tree, doctype="<!DOCTYPE html>").decode("utf-8")
def test_empty_styles(self): tree = html.document_fromstring(""" <html> <head> <style type="text/css"></style> </head> <body> <h1>Hello, world.</h1> </body> </html> """) inline(tree)
def get(self, cid): """Retrieve card for a single contribution. --- operationId: get_card parameters: - name: cid in: path type: string pattern: '^[a-f0-9]{24}$' required: true description: contribution ID (ObjectId) responses: 200: description: contribution card schema: type: string """ ctx = {'cid': cid} mask = ['project', 'identifier', 'content.data'] contrib = Contributions.objects.only(*mask).get(id=cid) info = Projects.objects.get(project=contrib.project) ctx['title'] = info.title ctx['descriptions'] = info.description.strip().split('.', 1) authors = [a.strip() for a in info.authors.split(',') if a] ctx['authors'] = {'main': authors[0], 'etal': authors[1:]} debug = current_app.config['DEBUG'] ctx['landing_page'] = f'/{contrib.project}' ctx['more'] = f'/explorer/{cid}' ctx['urls'] = info.urls.values() card_script = get_resource_as_string('templates/linkify.min.js') card_script += get_resource_as_string( 'templates/linkify-element.min.js') card_script += get_resource_as_string('templates/card.min.js') data = unflatten( dict((k.rsplit('.', 1)[0] if k.endswith('.display') else k, v) for k, v in nested_to_record(contrib.content.data, sep='.').items() if not k.endswith('.value') and not k.endswith('.unit'))) browser = get_browser() browser.execute_script(card_script, data) bs = BeautifulSoup(browser.page_source, 'html.parser') ctx['data'] = bs.body.table browser.close() rendered = html_minify(render_template('card.html', **ctx)) tree = html.fromstring(rendered) inline(tree) card = html.tostring(tree.body[0]).decode('utf-8') return card
def test_inlines_styles(self): tree = html.document_fromstring(""" <html> <head> <style type="text/css"> h1 { color: red; } </style> </head> <body> <h1>Hello, world.</h1> </body> </html> """) inline(tree) heading, = tree.cssselect('h1') self.assertEqual(heading.attrib['style'], 'color: red')
def test_removes_compiled_styles(self): tree = html.document_fromstring(""" <html> <head> <style type="text/css"> h1 { font-weight: bold; } </style> </head> <body> <h1>Hello, world.</h1> </body> </html> """) inline(tree) heading, = tree.cssselect('h1') self.assertEqual(heading.attrib['style'], 'font-weight: bold') self.assertEqual(len(tree.cssselect('style')), 0)
def get(self, cid): """Retrieve card for a single contribution. --- operationId: get_card parameters: - name: cid in: path type: string pattern: '^[a-f0-9]{24}$' required: true description: contribution ID (ObjectId) responses: 200: description: contribution card schema: type: string """ ctx = {'cid': cid} mask = ['project', 'identifier', 'content.data'] contrib = Contributions.objects.only(*mask).get(id=cid) info = Projects.objects.get(project=contrib.project) ctx['title'] = info.title ctx['descriptions'] = info.description.strip().split('.', 1) authors = [a.strip() for a in info.authors.split(',') if a] ctx['authors'] = {'main': authors[0], 'etal': authors[1:]} debug = current_app.config['DEBUG'] ctx['landing_page'] = f'/{contrib.project}' ctx['more'] = f'/explorer/{cid}' ctx['urls'] = info.urls.values() card_script = get_resource_as_string('templates/card.min.js') data = contrib.content.data browser = get_browser() browser.execute_script(card_script, data) src = browser.page_source.encode("utf-8") browser.close() bs = BeautifulSoup(src, 'html.parser') ctx['data'] = bs.body.table rendered = html_minify(render_template('card.html', **ctx)) tree = html.fromstring(rendered) inline(tree) return html.tostring(tree.body[0])
def test_skips_inline_false(self): tree = html.document_fromstring(""" <html> <head> <style type="text/css"> h1 { font-weight: bold; } </style> <style type="text/css" inline="false"> h1 { color: red; } </style> </head> <body> <h1>Hello, world.</h1> </body> </html> """) inline(tree) heading, = tree.cssselect('h1') self.assertEqual(heading.attrib['style'], 'font-weight: bold') stylesheet, = tree.cssselect('style') self.assertNotIn('inline', stylesheet.attrib)
def inline_css(value): tree = lxml.html.document_fromstring(value) toronado.inline(tree) # CSS media query support is inconistent when the DOCTYPE declaration is # missing, so we force it to HTML5 here. return lxml.html.tostring(tree, doctype="<!DOCTYPE html>")
from optparse import OptionParser import lxml.html import toronado parser = OptionParser(usage='usage: %prog infile') try: (options, (infile,)) = parser.parse_args() except ValueError: parser.print_usage() raise SystemExit(1) tree = lxml.html.parse(open(infile, 'r')) toronado.inline(tree) print(lxml.html.tostring(tree, pretty_print=True))
from optparse import OptionParser import lxml.html import toronado parser = OptionParser(usage='usage: %prog infile') try: (options, (infile, )) = parser.parse_args() except ValueError: parser.print_usage() raise SystemExit(1) tree = lxml.html.parse(open(infile, 'r')) toronado.inline(tree) print lxml.html.tostring(tree, pretty_print=True)
def assertInlines(self, tree): inline(tree) heading, = CSSSelector('h1')(tree) self.assertEqual(heading.attrib['style'], 'color: red')
def inline_css(value): tree = lxml.html.document_fromstring(value) toronado.inline(tree) # CSS media query support is inconistent when the DOCTYPE declaration is # missing, so we force it to HTML5 here. return lxml.html.tostring(tree, doctype='<!DOCTYPE html>').decode('utf-8')