I've installed the markdown preview plugin for gedit running on Lubuntu 13.04. It works as expected.
However, for ease of viewing, I altered the appearance of the resulting html panel (left panel) by including a link to a local stylesheet at the top of each markdown file. But this approach obviously means that I have to alter all my existing markdown files.
To avoid that, I looked at ~/.local/share/gedit/plugins/markdown-preview/__init__.py which has the code for the plugin, and I see lines #39 and #40 (reproduced below):
# Can be used to add default HTML code (e.g. default header section with CSS).
htmlTemplate = "%s"
That gives me the impression that I can somehow tell the plugin to look at a stylesheet and style the html accordingly. But I don't know what to do (if indeed htmlTemplate = "%s" has to be changed).
Set htmlTemplate to something like the following
# Can be used to add default HTML code (e.g. default header section with CSS).
htmlTemplate = """
<html>
<head>
<link rel="stylesheet" type="text/css" charset="utf-8" media="screen" href="http://paste.ubuntu.com/static/pastebin.css">
</head>
<body>
%s
</body>
</html>
"""
Related
I want to send a verification email. The email consists of HTML. I saved the HTML into a file named email_templates/verify.html (path). The problem is, that there are some constants in the HTML file are unknown until runtime. For instance, in the email, I refer to the username to which I send my email, but since each email is referring to someone else, I can't include the name in the template. One solution that comes to mind is to use some formatting technique in the lines of
<div>
hello {usrname}!
<div>
and then in the python code do something like:
lines = open('email_templates/verify.html', 'r').read()
lines.format('joe')
But this code, although is, in fact, can work, has some issues:
every {} in the HTML file can be a mistake to be formatted
the code in the current form is not very readable
code is not elegant
for an HTML reader that don't know python the formatting placeholders will be confusing
Is there is any better way to approach this?
This can and should be done through templating.
As you mentioned that maybe python placeholders will be confusing but I tell you they are not confusing, templating engines make sure HTML looks like HTML and these template tags look like template tags. Templating engines lay down the rules which placeholders you can and can't use. Also they are way fast than the file opening method you suggested; because they are optimized to do so.
Let's understand by example:
There are several templating engines out there. Jinja2 is one of the best ones.
First, install Jinja2.
pip install jinja2
Second, create a python file(name it anything you want) and a folder named 'templates'. Under 'templates' folder create your verify.html
Your folder structure should look like this:
folder1
|
|--> pythonfile.py
|--> templates
|
|--> verify.html
Third, put some sample code in the HTML file. I have this example put in my verify.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Index</title>
</head>
<body>
<h1>Dear {{ user }}!</h1>
<h4>
Hope you are fine.
</h4>
<p>
Thank you for signing up. Here is your {{ coupon_code }}
</p>
</body>
</html>
Now in this html file you see I have normal html tags. But there are two sets of curly braces occurring twice. The word written inside the curly braces will be considered a variable by jinja. The value of this variable will be supplied by our python file to this html file.
Also, to be consistent, jinja doesn't allow you to just use any braces. I mean if I had put "<>" instead of "{{ }}" it would not have worked. So there are some rules to be followed.
Read more here: Jinja allowed tags and filters
Fourth, copy this code into the python file we created.
#Imports
from jinja2 import Environment, FileSystemLoader, Template
#name of the folder where index file is located.
file_loader = FileSystemLoader('templates')
#This object is needed to create a template object.
env = Environment(loader=file_loader)
#path of the HTML file reletive to the folder.
template = env.get_template('./index.html')
#Data dictionary to be supplied to our HTML file.
input_dict = {
'user': 'Harry',
'coupon_code': '12313ASDSA4'}
#This function renders the data substituted HTML form.
output = template.render(input_dict)
print(output)
Now run this python file.
I have developed a web-based tool, and currently trying to make it python-launchable. I figured using CEFpython is probably the way to do it. I followed the tutorial here and wrote the following code:
from cefpython3 import cefpython as cef
import base64
import platform
import sys
import threading
import os
HTML_code = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link href="static/css/main.css" rel="stylesheet" />
</head>
<body>
<div id="UI">
</div>
<div id="container"></div>
<script src="static/main.js"></script>
<script type="text/javascript">
function defineData(datainput){
console.log("start")
data = datainput;
var loc = window.location.pathname;
var dir = loc.substring(0, loc.lastIndexOf('/'));
console.log(loc);
console.log(dir);
Main();
}
</script>
</body>
</html>
"""
def html_to_data_uri(html):
html = html.encode("utf-8", "replace")
b64 = base64.b64encode(html).decode("utf-8", "replace")
ret = "data:text/html;base64,{data}".format(data=b64)
return ret
def main(config):
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
settings = {}
cef.Initialize(settings=settings)
browser = cef.CreateBrowserSync(url=html_to_data_uri(HTML_code),window_title="Test")
browser.SetClientHandler(LoadHandler(config))
cef.MessageLoop()
cef.Shutdown()
return
class LoadHandler(object):
def __init__(self, config):
self.config = config
def OnLoadingStateChange(self, browser, is_loading, **_):
"""Called when the loading state has changed."""
if not is_loading:
# Loading is complete. DOM is ready.
browser.ExecuteFunction("defineData", self.config)
unfortunately, unlike in the tutorial, my tool has to load a local .js file where the main function is defined (), and it seems if I code the html file this way, my working directory is not actually the directory where I call the script, but some strange place
the output of these lines are:
var loc = window.location.pathname;
var dir = loc.substring(0, loc.lastIndexOf('/'));
console.log(loc);
console.log(dir);
output:
text/html;base64,CjwhRE9DVFlQRSBodG1sPgo8aHRtbCBsYW5nPSJlbiI+Cgk8aGVhZD4KCQk8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CgkJPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgdXNlci1zY2FsYWJsZT1ubywgbWluaW11bS1zY2FsZT0xLjAsIG1heGltdW0tc2NhbGU9MS4wIj4KCQk8bGluayBocmVmPSJzdGF0aWMvY3NzL21haW4uY3NzIiByZWw9InN0eWxlc2hlZXQiIC8+CgkJPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCQkJKiB7CgkJCQkuYm9yZGV....
text
Could you help me finding the correct way of hard coding html code in python with the correct path? maybe I need to somehow set the path?
PS: I did try including the html code in a separate .html file, and it worked on Windows machines, but it seems MacOS doesn't like it. Since this tutorial did work on MAC, I'm trying to hard code the html part into the python script and hope it would work on both Windows and Mac
Well, the HTML document has been converted to the body of a data URI by html_to_data_uri, so the U[niversal]R[esource]L[ocator] (window.location) of the document isn't a location on a server, but the data URI itself (the "strange place" you mention).
Remember that URLs are a subset of URIs, and you passed the URI as a URL to CEF with:
browser = cef.CreateBrowserSync(url=html_to_data_uri(HTML_code),window_title="Test")
So, as long as you are using a data URI/URL, I don't think that window.location will be helpful. Instead, you could extract the HTML code into a separate .html file, and change that line to:
browser = cef.CreateBrowserSync(url="/path/to/that_html_file.html", window_title="Test")
I have a bokeh dashboard which needs some custom styling(CSS).
I'm relatively new to the bokeh library and from what I understand, I need to use a jinja2 template wherein I can specify the CSS.
The dashboard has a 4 level hierarchy and the lower level plots only show up on selection at the level above. The hierarchy is as follows-
Dropdown(widget) - This is the only thing shown on first load
Plot 1(shows/updates on change of dropdown)
Plot 2 (shows/updates on selection in plot 1)
Plot 3 (shows/updates on selection in plot 2)
My index.html looks something like:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sales Performance Analysis</title>
<link *CDN Links*>
<script *CDN Links*</script>
{{ script }}
</head>
<body class="bk-body">
<h1>Sales Performance Analysis</h1>
{{ div }}
</body>
</html>
In my main.py, I have the following lines of code at the end to render-
script, div_plot = components(curdoc())
curdoc().template_variables["script"] = script
curdoc().template_variables["div"] = div_plot
When I execute this as a server app (bokeh serve --show folder_name), the browser application shows the dropdown widget but nothing happens on changing the values.
The same thing runs perfectly when run in standalone mode as bokeh serve --show main.py
Would appreciate any kind of pointers.
TIA
You want to use bokeh.embed.server_session instead of bokeh.embed.components (which only statically embed the document)
Here's the reference:
https://docs.bokeh.org/en/latest/docs/user_guide/embed.html#bokeh-applications
I wish to import my own library in Brython. This page of the documentation purports to show how, by adding the appropriate directory to the python path, but I can't make it work because I can't make Brython import sys.
Here's the simplest example code from the first page of the Brython documentation:
<html>
<head>
<script src="../src/Brython3.2.8/brython.js"></script>
</head>
<body onload="brython()">
<script type="text/python">
from browser import document, alert
def echo(ev):
alert(document["zone"].value)
document['mybutton'].bind('click', echo)
</script>
<input id="zone"><button id="mybutton">click !</button>
</body>
</html>
And that works fine.
But if I try to import sys:
<html>
<head>
<script src="../src/Brython3.2.8/brython.js"></script>
</head>
<body onload="brython()">
<script type="text/python">
import sys
from browser import document, alert
def echo(ev):
alert(document["zone"].value)
document['mybutton'].bind('click', echo)
</script>
<input id="zone"><button id="mybutton">click !</button>
</body>
</html>
Then the html will display but the button will not do anything.
The Console on Chrome shows the following error:
brython.js:6929 XMLHttpRequest cannot load file:///C:/Users/XXXXXXXXX/XXXXXX/src/Brython3.2.8/Lib/sys.py?v=1476283159509. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
$download_module # brython.js.6929
import_py # brython.js.6929
exec_module # brython.js.6929
etc etc
So, how can I import sys in brython, and/or how can I import my own library in python?
Thanks.
You need to include brython_stdlib.js in your html code. So your html should look like this:
<html>
<head>
<script src="../src/Brython3.2.8/brython.js"></script>
<script src="../src/Brython3.2.8/brython_stdlib.js"></script>
</head>
<body onload="brython()">
<script type="text/python">
import sys
from browser import document, alert
def echo(ev):
alert(document["zone"].value)
document['mybutton'].bind('click', echo)
</script>
<input id="zone"><button id="mybutton">click !</button>
</body>
</html>
Source Code : https://github.com/imvickykumar999/Brython/blob/master/index.html#L36
Deployed Code : https://imvickykumar999.github.io/Brython/
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Brython</title>
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/brython#3.8.9/brython.min.js">
</script>
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/brython#3.8.9/brython_stdlib.js">
</script>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
crossorigin="anonymous">
</head>
<body onload="brython()">
<style>
body {
/* background-color: yellow; */
background-image: url(https://images.unsplash.com/photo-1573196872258-41425124bf5d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80);
/* background-repeat: no-repeat; */
}
</style>
<script type="text/python">
from browser import document
def calc(a, b, o):
d = { '+' : a+b,
'-' : a-b,
'*' : a*b,
'/' : a/b,
'%' : a%b
}
return f"({a}{o}{b})=({d[o]})"
a = float(input('Enter first number : '))
b = float(input('Enter second number : '))
o = input('Enter the Operator (+,-,*,/,%) : ')
document <= calc(a, b, o)
</script>
</body>
</html>
Brython cannot import from any Python package that is part of any Python installation on the user's computer. It works by transpiling to JavaScript and running in the browser's Javascript engine. It has no knowledge of any local Python installations, and does not require any such installations to exist.
To use Python's standard library
Add a script tag to include brython_stdlib.js as well as the base brython.js. Several CDNs provide this already.
The Brython implementation of the Python standard library does not match the reference implementation exactly. See the documentation for details on what is included and how it is organized.
Importing your own code from within the document
For organizational purposes, Python code within the HTML document can be split across multiple <script> tags. The id attribute for the tag gives a "module name" that can be used in import statements in other scripts, as long as that script has already executed. The documentation includes an example:
<script type="text/python" id="module">
def hello():
return "world"
</script>
<script type="text/python">
from browser import document
import module
document.body <= module.hello()
</script>
The browser will have loaded the first <script> tag first, creating a (JavaScript representation of) a Python module named module that contains the hello function. The second script tag will be able to import that module and use the function as usual in Python.
Importing your own code from the server
Make the files available in the appropriate place as described in the documentation. Brython's implementation of the import statement (equivalently, __import__ builtin function) will attempt to find the code on the server using AJAX.
Importing your own code as a compiled Brython package
As explained in the documentation, use the Brython package (pip install brython) to create a JavaScript file that represents the Python code. (For third-party libraries, also check if such a JavaScript file is already available from a CDN.)
Suppose we have a project that creates a package named example. Navigate to the folder that contains that package (either src or the project folder, according to how the project is organized), then run brython-cli make_package example.
This should generate a example.brython.js file. Put it somewhere on the server, and configure the server to host that file at a specific URL. Then add the corresponding tag to the client page source (or the template that generates that page).
After that it should be possible to import example, from example import ... etc. in the Brython code.
Alternately, use brython-cli modules, as described in the 'Optimization' section, to create a combined library JavaScript file representing the entire server-side part of the project.
// After the "Content-type..." declaration...
print """<html>\
<head>
<title>Create Survey</title>
<link href="styles.css" type="text/css" rel="stylesheet">
</head>
<body>...."""
Assuming you are using something like CGI to "print" text based on a web request you should rely on your web server (Apache for example) to "print" the content back to the requesting client based on where your CSS file is located in the htdocs directory.
However if you are just wanting some output in a command line window you could do...
print file('/path/to/your/file/styles.css').read()