In the event you’re energetic on social media, then you understand that photographs and movies are well-liked types of content material. As a programmer, you primarily work with textual content, so sharing the content material that you simply create every day could not appear intuitive. That’s the place a code picture generator can turn out to be useful for you!
With a code picture generator, you’ll be able to create a nice-looking picture of your code snippets. That manner, you’ll be able to share code with out worrying about formatting, completely different syntax highlighting, or character rely limitations.
Creating your personal code picture generator will assist you to hone your abilities as a Python programmer and experiment with full-stack internet growth.
Though you’ll discover loads of full-featured code picture turbines like carbon or ray.so, crafting a customized instrument will assist you to meet your particular wants and proceed to enhance it in a while.
Demo: A Code Picture Generator With Python
The code picture generator is a Flask venture that creates fashionable screenshots of a code snippet with the assistance of Pygments and Playwright. The venture will run regionally in your browser, and you’ve got full management over the look of the code that you simply need to share:
When you run the Flask server, you’ll be able to go to the appliance within the browser, add your personal Python code, choose a method, and obtain a picture of the code to your pc.
Undertaking Overview
You’ll construct the code picture generator in a number of steps. In every step, you’ll deal with one necessary space of your codebase.
After establishing the venture, you’ll discover that the construction of the tutorial mirrors the route {that a} person would take when utilizing your instrument. You begin by creating the pages and features to simply accept code enter from the person.
Then, you progress on to implementing the choice of syntax highlighting types. It will make a person’s code snippet look good whenever you construct the path to generate a picture of the code within the following step.
Lastly, you’ll have a more in-depth have a look at some areas of your venture and enhance the person expertise. On the finish of the tutorial, you’ll have your very personal code picture generator that’s prepared to make use of and extremely extensible.
Over the course of the tutorial, you’ll get steering on which information and folders to create. Ultimately, your venture structure will appear to be this:
code-image-generator/
│
├── static/
│ └── types.css
│
├── templates/
│ ├── base.html
│ ├── code_input.html
│ ├── picture.html
│ └── style_selection.html
│
├── app.py
└── utils.py
Within the supplies for this tutorial, you’ll discover a folder for every step, containing supply code of the venture in its present state:
On the finish of every step, you’ll be able to evaluate your personal code with the supply code whereas following alongside. If in case you have questions on a step otherwise you’re caught sooner or later, then you’ll be able to scroll right down to the feedback space and ask the Actual Python group for assist.
Conditions
On this tutorial, you’ll construct a code picture generator with Python, Flask, Pygments, and Playwright. Whereas working via the steps, it’ll be useful for those who’re comfy with the next ideas:
In the event you’re not assured in your information of those conditions, then that’s okay too! In actual fact, going via this tutorial will make it easier to be taught and follow these ideas. You possibly can at all times cease and evaluate the sources linked above for those who get caught.
Step 1: Set Up the Code Picture Generator
To kick issues off, you’ll begin by putting in all of the dependencies that you simply want for this venture. You then’ll ensure that your major elements are working and implement the venture construction.
On the finish of this step, you’ll have a working Flask venture that kinds the inspiration for the upcoming steps.
Set up the Dependencies
On this tutorial, the venture’s root listing is known as code-image-generator/
. Through the subsequent few steps of this tutorial, you’ll place all of the information and folders that you simply create inside this listing.
You possibly can create the basis folder wherever in your system. When you’ve created it, open a brand new terminal session within the root listing of the venture. Then choose your working system under and use your platform-specific command to arrange a digital surroundings:
With the above instructions, you create and activate a digital surroundings named venv
through the use of Python’s built-in venv
module. The parenthetical (venv)
in entrance of the immediate signifies that you simply’ve efficiently activated the digital surroundings.
Subsequent, use pip
to put in the Python packages that you simply’ll work with on this venture:
(venv) $ python -m pip set up Flask playwright Pygments
Every of the three packages will fulfill a specific function within the venture:
You’ll be taught extra about every of them as you go. For now, have a more in-depth have a look at Playwright.
Give Playwright a Spin
Playwright is a framework for testing web sites by creating check workflows and simulating person conduct. With Playwright, you’ll be able to automate duties like kind submission, UI testing, and even internet scraping. On this tutorial, you’ll leverage one in all Playwright’s options particularly: the aptitude to take screenshots of internet sites and components on web sites.
You put in the playwright
bundle with pip
in your digital surroundings. Nevertheless, to truly use Playwright, you additionally want to put in the required browsers:
(venv) $ python -m playwright set up
This command installs the newest model of Chromium, Firefox, and WebKit. These are much like the browser that you simply use to discover the Internet.
The principle distinction is that these browsers are headless, which implies that they don’t have a graphical person interface (GUI). As a substitute, you utilize Playwright to run them within the background, and you’ll management the browsers programmatically.
Open the Python REPL and check out Playwright to obtain the content material of a web site aspect:
>>> from playwright.sync_api import sync_playwright
>>> target_url = "https://www.instance.com"
>>> aspect = "h1"
>>> with sync_playwright() as playwright:
... webkit = playwright.webkit
... browser = webkit.launch()
... browser_context = browser.new_context()
... web page = browser_context.new_page()
... web page.goto(target_url)
... found_element = web page.locator(aspect)
... textual content = found_element.text_content()
... browser.shut()
...
<Response url='https://www.instance.com/' request=...>
>>> textual content
'Instance Area'
By operating the code above, you begin a headless browser, go to instance.com, and browse the content material of the h1
headline. On this instance, you used playwright.webkit
to run a WebKit browser. However Playwright gives you an API to work with different browser situations like Firefox or Chromium.
The code you simply used would be the start line for a significant performance of your venture: creating the code photographs. That’s why you’ll revisit this code later and go into the main points of how Playwright works.
At this level, be at liberty to mess around with the code above to make use of completely different browsers, go to different web sites, and seize the content material of different web site components. When you’re accomplished exploring, it’s time to create the preliminary construction to your venture.
Create the Flask Undertaking Structure
Flask is a light-weight Python internet framework, which makes it a fantastic alternative for this venture. The central hub of your venture will likely be an app.py
file that’ll include all of the logic to deal with the requests despatched to the net app.
Create app.py
within the root of your venture listing and add the content material under:
# app.py
from flask import Flask
app = Flask(__name__)
@app.route("/", strategies=["GET"])
def code():
go
The basis of your venture would be the code()
view, which is brief for view operate. Views are particular features in Flask that you simply prepend with app.route()
decorators. Flask will take heed to the route that you simply outline as the primary parameter, and it’ll name the operate when requested.
Right here you add a single slash (/
) because the route, which implies that Flask calls code()
whenever you go to the basis URL of the venture. In different phrases, code()
would be the entry level of your internet app.
The strategies
parameter restricts which request strategies the view permits. With an inventory that accommodates "GET"
, you make the view accessible within the browser when a person enters the URL within the tackle bar. To indicate one thing to the person once they go to, you must return some content material. For now, you solely add a go
assertion as an indicator for your self that you simply’ll come again to the operate physique later.
In Flask, you utilize Jinja templates to outline the construction of the rendered content material. An necessary characteristic of Jinja is assist for template inheritance. Meaning you’ll be able to outline a base template with widespread components after which prolong or override particular sections in baby templates to create constant layouts throughout a number of pages.
By default, Flask appears for the templates in a folder named templates/
. Create this folder and add an empty base template named base.html
to it:
<!-- templates/base.html -->
<!-- Your base template -->
Subsequent, add your first baby template, named code_input.html
, to the template folder:
<!-- templates/code_input.html -->
<!-- Your first baby template -->
The templates in your venture will present the logic and construction for the entrance finish of your venture. With the assistance of Cascading Model Sheets (CSS), you’ll be able to fashion the content material.
Internet app builders generally save CSS information in a static/
listing. On this venture, you’ll solely work with one CSS file, named types.css
. However for those who resolve to broaden the venture sooner or later, it’s also possible to use this folder to retailer photographs or JavaScript information.
Create a brand new listing named static/
and place a file named types.css
in it:
/* static/types.css */
/* Your CSS file */
Similar to with the templates above, it’s okay to depart the CSS file empty for now. Over the course of this tutorial, you’ll improve it little by little.
With all of the information and folders in place, your Flask venture structure ought to appear to be this:
code-image-generator/
│
├── static/
│ └── types.css
│
├── templates/
│ ├── base.html
│ └── code_input.html
│
└── app.py
Later, you’ll add a couple of extra information to your venture. However this construction offers you a very good start line.
For now, you’ll deal with the information that you simply’ve simply created and add some code to them.
Write Your Preliminary Templates
As you realized above, the basis of your venture is the code()
view in app.py
. To get issues began, the code()
view ought to render a template with a message that tells customers what to do once they go to this web page of your venture.
For this, you must import Flask’s render_template()
operate and change the go
assertion within the operate physique of code()
with the code under:
# app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/", strategies=["GET"])
def code():
context = {
"message": "Paste Your Python Code 🐍",
}
return render_template("code_input.html", **context)
It’s widespread follow in Flask tasks to gather all the information that you simply need to go on to a template in a context
dictionary.
On this case, you add a message to context
to show within the template.
Then, you utilize render_template()
to instruct Flask to make use of the code_input.html
Jinja template with the gadgets from context
.
The file extension of the template is .html
, however the content material isn’t widespread HTML code. The code_input.html
file is a Jinja template that comes with quite a lot of highly effective options, corresponding to dynamic content material rendering by integrating variables out of your context and utilizing loops, conditionals, and filters in your templates.
To date, code_input.html
doesn’t have any content material. Go forward and replace code_input.html
with the content material under:
<!-- templates/code_input.html -->
{% extends "base.html" %}
{% block title %}
- Code Enter
{% endblock title %}
{% block content material %}
{% endblock content material %}
Within the code above, you add two Jinja blocks named title
and content material
. Having blocks in a Jinja template signifies that the template builds upon a mother or father template that defines these blocks.
On this case, the mother or father template is base.html
, which you prolong firstly of code_input.html
. In different phrases, code_input.html
requires a template named base.html
to work correctly:
1<!-- templates/base.html -->
2
3<!DOCTYPE html>
4<html lang="en">
5 <head>
6 <meta charset="utf-8"/>
7 <meta title="viewport" content material="width=device-width, initial-scale=1"/>
8 <title>
9 Code to Picture {% block title %}{% endblock title %}
10 </title>
11 </head>
12 <physique>
13 <h1>
14 <a href="{{ url_for('code') }}">Code to Picture</a>: <span>{{ message }}</span>
15 </h1>
16 <major>
17 {% block content material %}
18 {% endblock content material %}
19 </major>
20 </physique>
21</html>
Generally, the Jinja base template is known as base.html
, and it accommodates the primary HTML construction of your internet pages. The principle construction of base.html
is much like a traditional HTML web page. You begin by declaring the doctype, wrapping every thing in <html>
tags, and setting the lang
attribute.
You then go on so as to add <head>
and <physique>
with another nested components. That is the place issues get a bit extra attention-grabbing, so it’s value taking a look at them intimately:
- Line 9 units the title of your venture to Code to Picture. The empty
title
block offers you the chance to increase the title with a toddler template. For instance, incode_input.html
, you add the string – Code Enter to the title. - Line 14 hyperlinks the headline to the URL of the
code()
view through the use ofurl_for()
, which creates a full URL to a given endpoint. You additionally render themessage
variable of your context and add it to the headline if the variable is current. - Strains 17 to 18 outline an empty
content material
block which you can overwrite with content material from inside the templates that stretchbase.html
.
In the event you’re inquisitive about how your code picture generator appears for the time being, then you’ll be able to run the Flask growth server with this command:
(venv) $ python -m flask run
* Debug mode: off
WARNING:
This can be a growth server.
Don't use it in a manufacturing deployment.
Use a manufacturing WSGI server as a substitute.
* Operating on http://127.0.0.1:5000
Press CTRL+C to give up
While you run the Flask growth server, the output exhibits you some necessary data.
First, it lets you understand that the flask run
command spins up a growth server that you simply shouldn’t use in manufacturing. You possibly can ignore this message as a result of your venture is barely operating regionally. If you wish to be taught extra about operating a production-ready server, then you definitely may give Deploying a Python Flask Instance Software Utilizing Heroku a learn.
Then, Flask lets you understand which IP tackle the server is operating on. By default, the tackle is http://127.0.0.1:5000
. While you go to the tackle in your browser, then you definitely see your venture’s title and the message
worth:

It’s cool to see that your code picture generator runs. However the design is a bit underwhelming to date. That’s what you’ll deal with subsequent.
Cease the event server by urgent Ctrl+C in your terminal, and browse on so as to add some styling to your venture.
Add Customized Styling With CSS
For this venture, you’ll hold the CSS code minimal. Not solely will having minimal CSS code allow you to deal with the Python code, however it’s also possible to use the CSS code as a place to begin for future tasks.
You’ll ensure that the textual content of your app is a correct dimension and that your content material is correctly positioned on the web page. You’ll additionally add some fundamental formatting and coloring.
Add the code under to types.css
:
1/* static/types.css */
2
3* {
4 box-sizing: border-box;
5}
6
7physique {
8 font-family: sans-serif;
9 font-size: 20px;
10 line-height: 1.3em;
11}
12
13major {
14 show: flex;
15 justify-content: middle;
16 text-align: middle;
17}
18
19h1 {
20 font-size: 2em;
21 text-align: middle;
22 line-height: 1em;
23}
24
25h1 a {
26 text-decoration: none;
27 shade: inherit;
28}
29
30span {
31 shade: deepskyblue;
32}
In CSS, you utilize selectors to outline which components on a web site you need to goal with the fashion declaration that you simply put contained in the curly braces ({}
).
In line 3, you utilize an asterisk (*
) as a selector to focus on all the weather and set their box-sizing
to border-box
. This declaration makes coping with the sizes of components far more handy. If you wish to be taught extra about this, then you’ll be able to take a look at an evidence by Paul Irish which is so well-liked that it sparked Worldwide box-sizing
Consciousness Day.
In strains 8 to 10, you outline the typography guidelines for the code picture generator, with a barely elevated font dimension and line top. You let the working system select the font-family
, so long as the browser serves a sans serif font.
For the <major>
aspect on line 13, you utilize flex
to middle the code picture generator on the web page.
The opposite CSS guidelines outline textual content dimension and shade modifications, like rising the scale of your headline in line 20 or setting components inside a <span>
tag to deep sky blue.
Subsequent, you must join your base.html
template with the types.css
file by including a hyperlink to the fashion sheet inside <head>
:
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta title="viewport" content material="width=device-width, initial-scale=1"/>
<title>
Code to Picture {% block title %}{% endblock title %}
</title>
<hyperlink
rel="stylesheet"
kind="textual content/css"
href="{{ url_for('static', filename='types.css') }}"
/>
</head>
<physique>
<!-- ... -->
</physique>
</html>
You possibly can reference a CSS file with a <hyperlink>
tag within the header of your HTML web page. Similar to earlier than, you utilize url_for()
to create the total URL for the href
attribute. To hyperlink to the types.css
file saved in your Flask venture’s static/
folder particularly, you utilize the filename
argument.
By including the CSS file reference to base.html
, you’re profiting from the inheritance mechanism that Jinja templates present. You solely want so as to add types.css
in your base template. Templates like code_input.html
that stretch base.html
can even inherit the types.
Begin your Flask growth server once more and see your fundamental styling in motion:

Superior, the beginning of your code picture generator appears clear and tidy! That’s the proper start line for accepting code enter from the person.
Step 2: Settle for Code Enter
The primary ingredient that the code picture generator app wants from a person is a few code. On this step of the tutorial, you’ll first handle the template that receives the code enter. Then, you’ll introduce classes to make person enter persistent and begin interested by what to do as soon as a person provides code.
Replace the Code Enter Web page
To just accept person enter in your template, you must add a kind with a textual content enter area in your code_input.html
template. Because the person enter can broaden over a number of strains, it’s a good suggestion to work with a <textarea>
aspect:
1<!-- templates/code_input.html -->
2
3{% extends "base.html" %}
4
5{% block title %}
6 - Code Enter
7{% endblock title %}
8
9{% block content material %}
10<kind>
11 <textarea
12 class="code"
13 title="code"
14 placeholder="Paste your Python code right here"
15 >{{ code }}</textarea>
16</kind>
17{% endblock content material %}
Word that you simply additionally add a {{ code }}
variable to line 15 with none areas between the variable and the encircling <textarea>
tags. In the event you added an area right here, then there’d be an area on the web page surrounding your code enter, too.
In the event you haven’t set the {{ code }}
variable otherwise you delete the content material of the textual content enter area, then the browser exhibits the placeholder textual content that you simply outline in line 14.
To keep away from beginning with an empty textual content area, you’ll be able to outline a placeholder code snippet and set the code
variable within the code()
view in app.py
:
# app.py
from flask import Flask, render_template
app = Flask(__name__)
PLACEHOLDER_CODE = "print('Howdy, World!')"
@app.route("/", strategies=["GET"])
def code():
context = {
"message": "Paste Your Python Code 🐍",
"code": PLACEHOLDER_CODE,
}
return render_template("code_input.html", **context)
You’ll use PLACEHOLDER_CODE
elsewhere later. So it is smart to outline it as a fixed close to the highest of app.py
. To transmit PLACEHOLDER_CODE
to the template, you utilize it as the worth of code
that you simply add to the context
dictionary.
While you restart your Flask growth server and go to http://127.0.0.1:5000
, then you definitely’ll see that print('Howdy, World!')
is positioned within the textual content space by default:
While you delete the default code, then the textual content space’s placeholder textual content exhibits and you’ll paste in your personal code snippet.
When you paste your personal code, there’s not a lot to do with it but. Additionally, it will be cool if any code that you simply added would persist on a web page reload. That’s the place classes come into play.
Introduce Classes
If you wish to retailer information with out including a database to your venture, then classes are a fantastic concept. A session is a mechanism that lets you retailer and persist user-specific data between a number of requests that the identical person makes to an internet utility.
Flask gives you a session
object proper out of the field.
With a Flask session, you’ll be able to persist information like a code snippet between requests. So long as you might have your browser window open, you’ll be able to reload a web page, and your session information stays accessible.
To make use of classes in your venture, you must set a secret key to your Flask utility first. A secret secret’s a random string of characters used to encrypt and decrypt information, corresponding to tokens or session information. The key key acts as a safe identifier, permitting the server to validate the integrity of the session information.
So long as you’re employed along with your Flask venture regionally, it’s okay to make up a string worth for app.secret_key
. Nevertheless, if you wish to deploy your Flask app later, then it’s a good suggestion to generate a correct secret key.
If you must create cryptographically safe information, like a Flask secret key, then you should utilize Python’s secrets and techniques
module:
>>> import secrets and techniques
>>> secrets and techniques.token_hex()
'2e9ac41b1e0b66a8d93d66400e2300c4b4c2953f'
The .token_hex()
methodology returns a hexadecimal string containing random numbers and letters from 0
to 9
and a
to f
. Use the worth that secrets and techniques.token_hex()
outputs for you and add it to your Flask venture’s app.py
file:
# app.py
from flask import Flask, render_template
app = Flask(__name__)
app.secret_key = "2e9ac41b1e0b66a8d93d66400e2300c4b4c2953f"
# ...
To keep away from saving the key key immediately in your code, it might be a good suggestion to work with surroundings variables. You possibly can be taught extra about that within the Flask documentation on configuration dealing with.
When you’ve set app.secret_key
, you’ll be able to work with the session
object. To entry the information saved in a Flask session, you should utilize the session
object like a Python dictionary. This implies you’ll be able to set values utilizing keys and retrieve information utilizing the identical keys:
1# app.py
2
3from flask import Flask, render_template, session
4
5# ...
6
7@app.route("/", strategies=["GET"])
8def code():
9 if session.get("code") is None:
10 session["code"] = PLACEHOLDER_CODE
11 context = {
12 "message": "Paste Your Python Code 🐍",
13 "code": session["code"],
14 }
15 return render_template("code_input.html", **context)
After importing session
from flask
in line 3, you’ll be able to work with session
as if it had been a dictionary. In line 9, you examine if session
already accommodates some code. If not, then you definitely set session["code"]
to your placeholder code.
You additionally replace the worth of code
in your context
dictionary in line 13 to work with the session’s code within the template.
Handle Classes
Now you want an extra view in app.py
to save lots of a person’s customized code in session
. On prime of that, it additionally is smart to have a view to reset a session.
Add each routes and the required imports to app.py
:
# app.py
from flask import (
Flask,
redirect,
render_template,
request,
session,
url_for,
)
# ...
@app.route("/save_code", strategies=["POST"])
def save_code():
session["code"] = request.kind.get("code")
return redirect(url_for("code"))
@app.route("/reset_session", strategies=["POST"])
def reset_session():
session.clear()
session["code"] = PLACEHOLDER_CODE
return redirect(url_for("code"))
Each views require Flask’s redirect()
and url_for()
features, which you add to the checklist of imports. Moreover, you import request
, which you utilize in save_code()
to entry information from a posted kind. With that variety of imports, it is smart to distribute your import
assertion onto a number of strains.
When a person submits a kind, you should utilize request.kind.get()
with the enter area’s title as an argument. In code_input.html
you set the title of the textual content space to "code"
, in order that’s the string that you simply’re utilizing right here. To save lots of the code enter within the session, you set it as the worth of session["code"]
.
In reset_session()
, you don’t must depend on transmitted kind information since you reset the session with session.clear()
and set the session’s code
worth to the placeholder code.
When you both retailer the pasted code or reset the session, you redirect the browser to the code()
view.
In each app.route()
decorators, you restrict the request methodology to POST requests. Meaning you’ll be able to’t entry the routes /save_code
and /reset_session
by simply typing their addresses within the browser. As a substitute, you’ll use these routes as formaction
targets for 2 buttons in code_input.html
. One button will make a POST to reset the session, and the opposite button will make a POST to save lots of the code within the session.
Go on and add the 2 buttons to code_input.html
:
<!-- templates/code_input.html -->
{% extends "base.html" %}
{% block title %}
- Code Enter
{% endblock title %}
{% block content material %}
<kind>
<textarea
class="code"
title="code"
placeholder="Paste your Python code right here"
>
{{ code }}
</textarea>
<div class="controls">
<button formmethod="put up" formaction="{{ url_for('reset_session') }}">
Reset Session ♻️
</button>
<button formmethod="put up" formaction="{{ url_for('save_code') }}">
Save Code 💾
</button>
</div>
</kind>
{% endblock content material %}
You wrap the 2 buttons in a <div>
aspect with a controls
class attribute on the code enter web page. You’ll use the category attribute later to fashion all of the HTML components with the controls
class.
Each buttons have put up
as their formmethod
to ship a POST request whenever you click on the button. The targets for the POST requests are the values that you simply set for the formaction
attributes: the URLs for reset_session()
and save_code()
.
Begin your Flask growth server once more, go to http://127.0.0.1:5000
, and work together along with your code enter web page:
While you edit the code within the textual content area and reload the web page, then the code jumps again to print('Howdy, World!')
, which you set as PLACEHOLDER_CODE
. Solely whenever you click on Save Code do you save the entered code within the session. While you now reload the web page, the entered code persists.
Meaning your session performance is working. If you wish to reset your session, then you’ll be able to click on the Reset Session button.
Model the Code Enter Web page
Within the earlier part, you added two buttons and a <div>
aspect to the code enter web page. To fashion these components, you must add some CSS declarations for them to types.css
.
Because you’re opening types.css
, you’ll be able to take the chance and make different fashion changes. For instance, you’ll be able to deal with a minor downside that your code enter area at the moment has.
Particularly, for those who paste code that’s bigger than the placeholder line with Python’s print()
operate, then the textual content area isn’t displaying all of the code.
Jump over to types.css
and add some CSS guidelines to make the weather in your web page look nicer:
/* static/types.css */
/* ... */
button,
choose {
cursor: pointer;
font-size: 100%;
margin: 0.25em;
min-width: 8em;
}
.controls {
margin: 1em 0;
show: flex;
justify-content: middle;
align-items: middle;
flex-wrap: wrap;
}
.code {
font-family: monospace;
box-shadow: #767676 0px 20px 30px -10px;
border-radius: 0.5em;
padding: 1em 2em;
min-width: 32em;
max-width: 100%;
min-height: 12em;
text-align: left;
border: 1px strong #cecece;
margin: 1em;
line-height: 1.4em;
}
Apart from including declarations for <button>
components, you additionally anticipate a <choose>
aspect that you simply’ll add later on this tutorial. These kind components ought to present the mouse cursor as a pointer to point that these components are clickable. You additionally add some house round them and set a minimal width.
Subsequent, you outline styling guidelines for all of the HTML components with a controls
class attribute. Once more, you’re including some house through the use of flex
to middle the shape controls.
The textual content enter with the code
class additionally will get a method replace. You alter the borders, add a refined shadow behind the aspect, and set the font-family
of <textarea>
to your working system’s default monospace font. In fact, it’s also possible to get extra inventive and add one in all a number of cool programming fonts.
To extend the scale of the code enter area, you set a min-width
and a min-height
. While you go to the code enter web page, then the <textarea>
aspect is greater by default:

Growing the scale of the code enter area within the CSS is an effective begin. Nevertheless, whenever you click on Save Code, it’d be cool if the code enter area adjusted to the code you pasted. To make that occur, you must calculate the variety of strains and the size of your code within the code()
view:
# app.py
# ...
@app.route("/", strategies=["GET"])
def code():
if session.get("code") is None:
session["code"] = PLACEHOLDER_CODE
strains = session["code"].break up("n")
context = {
"message": "Paste Your Python Code 🐍",
"code": session["code"],
"num_lines": len(strains),
"max_chars": len(max(strains, key=len)),
}
return render_template("code_input.html", **context)
# ...
To get the variety of strains, you break up the strains right into a checklist. Then you’ll be able to rely the variety of gadgets within the checklist with len()
and retailer it in "num_lines"
within the context
dictionary.
To get the longest line, you utilize max()
with key=len
as an argument. Then, you utilize len()
on the consequence to get the utmost variety of characters in that line and go it to the context
dictionary, too.
Now that you know the way many strains the code snippet accommodates and the way lengthy the longest line is, you’ll be able to set min-width
and max-width
in code_input.html
dynamically:
<!-- templates/code_input.html -->
{% extends "base.html" %}
{% block title %}
- Code Enter
{% endblock title %}
{% block content material %}
<fashion>
.code {
min-height: calc({{ num_lines }}em * 1.5 + 2 * 1em);
min-width: calc({{ max_chars }}ch + 4 * 2em);
}
</fashion>
<kind>
<!-- ... -->
</kind>
{% endblock content material %}
Usually, including inline CSS is taken into account unhealthy follow.
On this case, you may make an exception to reap the benefits of Jinja.
By including a <fashion>
HTML block to your template, you should utilize Jinja variables in your CSS code. When the web page is rendered, Flask dynamically updates the CSS styling like it will do in another a part of your doc. That manner, you’ll be able to entry num_lines
and max_chars
and let CSS calculate the scale of your code enter aspect with some comfy padding.
While you now paste code and reserve it, then the textual content area shrinks or expands to the scale of your code:
Good! With all of those modifications, your code enter web page positively appears presentable. Nevertheless, the code itself continues to be solely black on white. Within the subsequent step, you’ll add one other view the place you’ll be able to choose a bunch of cool types to paint your code.
Step 3: Colour Your Code
On this step, you’ll add one other thrilling web page to your code picture generator: the fashion choice. You’ll use Pygments so as to add the fashion as syntax highlighting to the code and blend HTML enter fields with the facility of Jinja.
On the finish of this step, you’ll have the ability to shade your code with quite a lot of Pygments types to tailor your code snippets to your private style.
Introduce Syntax Highlighting With Pygments
Pygments is a syntax highlighting engine that may fashion over 5 hundred markup and programming languages. In your venture, you’ll hand over the plain Python code snippet {that a} person pastes. Pygments processes the enter and returns the code snippet wrapped in HTML components.
Word: If you wish to see Pygments in motion, then simply take a look on the very web page that you simply’re on proper now. Actual Python makes use of Pygments to fashion all of the code examples that yow will discover on the location.
To make use of Pygments, you typically want not less than three elements:
- A lexer that breaks up the code into chunks that Pygments understands
- Some fashion that determines how the highlighted code ought to look
- A formatter that defines the way in which this system will output the code
Open up a Python REPL session and see the three elements above in motion:
>>> from pygments import formatters, spotlight, lexers
>>> code = "print('Howdy, World!')"
>>> spotlight(code, lexers.Python3Lexer(), formatters.HtmlFormatter())
'<div class="spotlight"><pre><span></span><span class="nb">print</span>...'
To get Pygments-processed Python code as HTML, you add your supply code, the Python3Lexer()
, and the HtmlFormatter()
to the spotlight()
operate.
The Python lexer takes care of wrapping every aspect of your Python code in a component. For instance, print
is wrapped inside two <span>
components.
The weather surrounding your Python code are HTML due to HTMLFormatter
.
The lexer that you simply use ought to at all times match the kind of code that you simply present. If you wish to spotlight JavaScript code, then you must use the JavascriptLexer
. You will discover an inventory of all of the out there lexers within the Pygments documentation on lexers.
Relating to the code formatter, Pygments is extra versatile. Within the code above, you formatted the code as HTML. However it’s also possible to output LaTeX or Wealthy Textual content Format (RTF) code:
>>> spotlight(code, lexers.Python3Lexer(), formatters.LatexFormatter())
'start{Verbatim}[commandchars=\{}]nPY{n+nb}{print}...'
>>> spotlight(code, lexers.Python3Lexer(), formatters.RtfFormatter())
"{rtf1ansiuc0deff0{fonttbl{f0fmodernfprq1fcharset0;}}..."
To entry the styling guidelines, you should utilize the .get_style_defs()
methodology. For HTMLFormatter()
, the styling guidelines are CSS:
>>> formatters.HtmlFormatter().get_style_defs()
'pre { line-height: 125%; }ntd.linenos .regular { shade: inherit; ...'
Be at liberty to mess around with completely different lexers and formatters. For this venture, you’ll proceed to make use of the Python3Lexer()
with the HtmlFormatter()
to render the highlighted code within the browser.
Spotlight the Code
To work with Pygments in your Flask venture, you must import the spotlight()
operate. You additionally want the HtmlFormatter
and Python3Lexer
lessons. Go forward and replace app.py
like within the snippet under:
# app.py
from flask import (
# ...
)
from pygments import spotlight
from pygments.formatters import HtmlFormatter
from pygments.lexers import Python3Lexer
# ...
Then, you want one other view in app.py
that works with session["code"]
, units the Pygments definitions, and renders a template that exhibits the highlighted code:
1# app.py
2
3# ...
4
5@app.route("/fashion", strategies=["GET"])
6def fashion():
7 formatter = HtmlFormatter()
8 context = {
9 "message": "Choose Your Model 🎨",
10 "style_definitions": formatter.get_style_defs(),
11 "style_bg_color": formatter.fashion.background_color,
12 "highlighted_code": spotlight(
13 session["code"], Python3Lexer(), formatter
14 ),
15 }
16 return render_template("style_selection.html", **context)
You create a fashion()
view that accepts GET requests. Within the operate physique, you set formatter
to be an HtmlFormatter()
in line 7. With formatter.get_style_defs()
, you get the CSS fashion definitions in line 10. Saving these definitions in your context is tremendous helpful, as you’ll have the ability to use CSS code in a <fashion>
block in your template later.
In line 11, you entry the formatter fashion’s background shade and add it as a "style_bg_color"
key so as to use it as a template variable. In strains 12 to 14, you add the highlighted code to context
. That’s the output that the Python3Lexer()
and formatter
produce primarily based on the code that you simply retailer in your present session
.
Lastly, you render a template named style_selection.html
in line 16. This template doesn’t exist but. Go on and create it with the content material under:
<!-- templates/style_selection.html -->
{% extends "base.html" %}
{% block title %}
- Model Choice
{% endblock title %}
{% block content material %}
<fashion>
{{ style_definitions }}
.code {
background-color: {{ style_bg_color }};
}
</fashion>
<kind>
<div class="code">
{ secure }
</div>
</kind>
{% endblock content material %}
Your fashion template follows the identical construction as code_input.html
. You prolong base.html
and overwrite the title
and content material
blocks.
Contained in the <fashion>
aspect, you interpolate the content material of style_definitions
. This Jinja variable accommodates all of the CSS guidelines that you must fashion the person’s enter code, which is already saved in highlighted_code
.
Moreover, you set the content material of style_bg_color
because the background of your .code
CSS selector, in order that background shade will refill the entire aspect. The placeholder kind will work as a body to show the highlighted code, which you show in a <div>
aspect. That manner, you should utilize the background shade to color the background of this aspect and match the Pygments fashion.
Since highlighted_code
accommodates HTML code, you must add the secure
filter to the Jinja variable. That manner, you sign to Flask that you simply’re conscious of the variable’s content material and that Jinja is allowed to render it as HTML. You possibly can be taught extra in regards to the secure
filter within the Jinja documentation on HTML escaping.
With style_selection.html
prepared, go to the fashion choice web page on http://127.0.0.1:5000/fashion
and examine how your highlighted code appears:

That’s fairly good! However having just one default fashion because the syntax highlighting is a bit boring. It’s time to take a look at all of the types that Pygments has to supply.
Get All of the Types
The template title is style_selection.html
, and the web page exhibits an enormous headline saying Choose Your Model, however there’s just one fashion to show. It’s time to match the filename and title with the motion {that a} person can carry out on the web page. Earlier than you proceed working in your Flask app, take a second to analyze the types that Pygments has in inventory.
Open the Python REPL and check out all of the Pygments types through the use of the get_all_styles()
operate:
>>> from pygments.types import get_all_styles
>>> checklist(get_all_styles())
['default', 'emacs', 'friendly', 'friendly_grayscale', 'colorful',
'autumn', 'murphy', 'manni', 'material', 'monokai', 'perldoc', 'pastie',
'borland', 'trac', 'native', 'fruity', 'bw', 'vim', 'vs', 'tango', 'rrt',
'xcode', 'igor', 'paraiso-light', 'paraiso-dark', 'lovelace', 'algol',
'algol_nu', 'arduino', 'rainbow_dash', 'abap', 'solarized-dark',
'solarized-light', 'sas', 'staroffice', 'stata', 'stata-light',
'stata-dark', 'inkpot', 'zenburn', 'gruvbox-dark', 'gruvbox-light',
'dracula', 'one-dark', 'lilypond', 'nord', 'nord-darker', 'github-dark']
With get_all_styles()
, you’ll be able to checklist all of the types that Pygments has to supply. If in case you have a have a look at the names, then chances are you’ll acknowledge some types that you simply use as a theme to your favourite Python IDEs and code editors.
Now that you know the way to get all of the types, you’ll be able to add them to the context
dictionary of fashion()
in app.py
:
# app.py
# ...
from pygments.types import get_all_styles
# ...
@app.route("/fashion", strategies=["GET"])
def fashion():
formatter = HtmlFormatter()
context = {
"message": "Choose Your Model 🎨",
"all_styles": checklist(get_all_styles()),
"style_definitions": formatter.get_style_defs(),
"style_bg_color": formatter.fashion.background_color,
"highlighted_code": spotlight(
session["code"], Python3Lexer(), formatter
),
}
return render_template("style_selection.html", **context)
Begin by importing get_all_styles
from pygments.types
after which name it inside a checklist()
constructor to get an inventory of all of the Pygments types.
With the all_styles
variable out there in your template’s context, you’ll be able to construct a variety menu that exhibits all of the types and a Change Model button to vary the code highlighting to the chosen fashion:
<!-- templates/style_selection.html -->
# ...
{% block content material %}
<fashion>
/* ... */
</fashion>
<kind>
<div class="controls">
<choose title="fashion">
{% for style_name in all_styles %}
<choice worth="{{ style_name }}">{{ style_name }}</choice>
{% endfor %}
</choose>
<button formmethod="put up" formaction="{{ url_for('save_style') }}">
Change Model 💅
</button>
</div>
<div class="code">
{ secure }
</div>
</kind>
{% endblock content material %}
On prime of your code block, you add a <div>
aspect containing the fashion choice menu that loops via all all_styles
and exhibits every style_name
as an choice.
You additionally add a button to vary the fashion. The button posts the shape to a save_style
URL. This route doesn’t exist but. Jump over to app.py
once more and create a view for it:
# app.py
# ...
PLACEHOLDER_CODE = "print('Howdy, World!')"
DEFAULT_STYLE = "monokai"
# ...
@app.route("/save_style", strategies=["POST"])
def save_style():
session["style"] = request.kind.get("fashion")
return redirect(url_for("fashion"))
First, you add a brand new DEFAULT_STYLE
fixed that accommodates the Pygments fashion title that your code picture generator ought to begin with. On this tutorial, that’s the beloved Monokai shade palette by Wimer Hazenberg. In fact, you’ll be able to select another fashion title that get_all_styles()
gives.
Subsequent, you add a save_style()
view. That is the view that receives the "fashion"
worth from the posted type of style_selection.html
. When you retailer the fashion within the session, you redirect the request to fashion()
.
Keep in mind that you haven’t saved a method in your session whenever you go to /fashion
for the primary time. So that you additionally must replace fashion()
to work with DEFAULT STYLE
if there’s no fashion current within the session:
# app.py
# ...
@app.route("/fashion", strategies=["GET"])
def fashion():
if session.get("fashion") is None:
session["style"] = DEFAULT_STYLE
formatter = HtmlFormatter(fashion=session["style"])
context = {
"message": "Choose Your Model 🎨",
"all_styles": checklist(get_all_styles()),
"style_definitions": formatter.get_style_defs(),
"style_bg_color": formatter.fashion.background_color,
"highlighted_code": spotlight(
session["code"], Python3Lexer(), formatter
),
}
return render_template("style_selection.html", **context)
# ...
If there’s no fashion set, then you definitely depend on DEFAULT_STYLE
in your fashion()
view to ensure that there’s at all times a price in session["style"]
earlier than persevering with.
You then initialize HtmlFormatter
with the present fashion that’s saved in your session. Passing in fashion
will ensure that the code is highlighted with both your default fashion or the fashion that you simply chosen within the kind.
Try how the fashion choice works by restarting your Flask growth server and visiting http://127.0.0.1:5000/fashion
:
While you go to the fashion choice web page, you begin along with your default fashion. After deciding on one other fashion and clicking the Change Model button, the web page reloads and exhibits your code within the chosen fashion.
Word: When you choose a distinct fashion and click on the Change Model button, the code modifications its fashion, however the textual content within the choose menu snaps again to the primary merchandise within the fashion checklist. Later within the tutorial, you’ll ensure that the choose menu at all times exhibits the present fashion.
It’s neat that visiting /fashion
immediately and altering the fashion works typically. However the concept of your code picture generator is that you simply begin with the code enter after which transfer on to the fashion choice. So, you’ll be able to go forward and join each pages!
Hyperlink Code Enter and Model Choice
To attach the code enter web page with the fashion choice web page, you’ll add a button to every view’s template. The button for style_selection.html
works like a standard HTML hyperlink:
<!-- templates/style_selection.html -->
{% extends "base.html" %}
{% block title %}
- Model Choice
{% endblock title %}
{% block content material %}
<fashion>
/* ... */
</fashion>
<kind>
<div class="controls">
<!-- ... -->
</div>
<div class="code">
{ secure }
</div>
<div class="controls">
<button formmethod="get" formaction="{{ url_for('code') }}">
⬅️ Again
</button>
</div>
</kind>
{% endblock content material %}
You add the Again button in one other <div>
aspect for the controls. This time, you set it under the code block. As formmethod
, you select GET since you don’t must ship any information whenever you need to return to the URL to your code()
view.
In code_input.html
, however, you must ship information. That’s why the button wants a distinct formmethod
worth:
<!-- templates/code_input.html -->
{% extends "base.html" %}
{% block title %}
- Code Enter
{% endblock title %}
{% block content material %}
<fashion>
/* ... */
</fashion>
<kind>
<!-- ... -->
<div class="controls">
<button formmethod="put up" formaction="{{ url_for('reset_session') }}">
Reset Session ♻️
</button>
<button formmethod="put up" formaction="{{ url_for('save_code') }}">
Save Code 💾
</button>
<button formmethod="put up" formaction="{{ url_for('save_style') }}">
Subsequent ➡️
</button>
</div>
</kind>
{% endblock content material %}
As a substitute of simply linking to /fashion
, you set the URL for save_style()
as formaction
, which you tackle with a POST request that you simply set as formmethod
.
You could marvel what the benefit of this method is. In any case, there’s no fashion to save lots of but. Nevertheless, you’d lose any code that you simply entered within the textual content area if the Subsequent button had been solely a plain hyperlink sending a GET request.
When sending a POST to save_style()
, you need to ensure that the code can also be saved within the session.
Open app.py
and improve save_style()
to additionally bear in mind the code if the shape accommodates some:
1# app.py
2
3# ...
4
5@app.route("/save_style", strategies=["POST"])
6def save_style():
7 if request.kind.get("fashion") is not None:
8 session["style"] = request.kind.get("fashion")
9 if request.kind.get("code") is not None:
10 session["code"] = request.kind.get("code")
11 return redirect(url_for("fashion"))
12
13# ...
Earlier than, you solely accessed save_style()
whenever you had been deciding on a method. Now you’ll be able to attain save_style()
from the code enter web page. That’s why you must examine if the shape accommodates a "fashion"
worth in line 7. Solely then do you need to replace session["style"]
.
In line 9, you utilize a conditional assertion to examine if the shape accommodates a "code"
worth. This handles the case that you simply set off with the Subsequent button in code_input.html
.
Restart your Flask growth server and go to http://127.0.0.1:5000
to check if leaping between the pages works:
While you click on the Subsequent button on the code enter web page, the code will get saved, and also you see the code with the default fashion on the /fashion
route. Altering the fashion works precisely like earlier than, and clicking the Again button brings you again to the primary web page.
Word: If you need, you’ll be able to take away the Save Code button at this level within the code_input.html
template:
<!-- templates/code_input.html -->
<!-- ... -->
<kind>
<!-- ... -->
<div class="controls">
<button formmethod="put up" formaction="{{ url_for('reset_session') }}">
Reset Session ♻️
</button>
<!-- Optionally: Take away the Save Code button -->
<button formmethod="put up" formaction="{{ url_for('save_style') }}">
Subsequent ➡️
</button>
</div>
</kind>
{% endblock content material %}
Because you’re saving the code anyway whenever you click on Subsequent, the Save Code button doesn’t have a objective anymore. That being mentioned, it additionally doesn’t harm to maintain the Save Code button in your code enter web page.
With the 2 pages of your code picture generator working, it’s time so as to add a 3rd: the web page the place you’ll be able to see and obtain the code picture.
Step 4: Generate an Picture From the Code
Initially of this tutorial, you took a brief detour by trying out how Playwright works. On this step, you’ll take the code from earlier than and alter it to work inside Flask.
On the finish of this step, you’ll have the ability to create a picture along with your code picture generator and show it to the person.
Add the Code Picture Routes
This time, you begin by connecting the pages first. Much like the Subsequent button on the code enter web page that results in the fashion choice web page, you now want a button that hyperlinks to the picture route. For the textual content on the button, you may be extra exact and add Create Picture as its label:
<!-- templates/style_selection.html -->
<!-- ... -->
{% block content material %}
<fashion>
/* ... */
</fashion>
<kind>
<!-- ... -->
<div class="controls">
<button formmethod="get" formaction="{{ url_for('code') }}">
⬅️ Again
</button>
<button formmethod="get" formaction="{{ url_for('picture') }}">
Create Picture 📸
</button>
</div>
</kind>
{% endblock content material %}
While you click on the button to go to the picture web page, then you definitely’ll at all times have a method saved in your session already. You don’t must switch any information from the shape, so you’ll be able to work with a GET request.
The URL that you simply use because the goal for formaction
doesn’t exist but. You must add it to app.py
subsequent:
# app.py
# ...
@app.route("/picture", strategies=["GET"])
def picture():
context = {
"message": "Finished! 🎉",
}
return render_template("picture.html", **context)
For now, there’s not a lot taking place within the picture()
view. Its objective is barely to load and populate an picture.html
template with successful message.
Go on and create a template named picture.html
in your templates/
folder:
<!-- templates/picture.html -->
{% extends "base.html" %}
{% block title %}
- Your Picture
{% endblock title %}
{% block content material %}
<kind>
{% if image_b64 %}
<div class="code-picture">
<img
src="information:picture/png;base64,{ secure }"
alt="Code Picture"
/>
</div>
<a
href="information:picture/png;base64,{ secure }"
obtain="Your_CodeImage.png"
>
Obtain Your Code Picture ⤵️
</a>
{% endif %}
<div class="controls">
<button formmethod="get" formaction="{{ url_for('code') }}">
🔄 Again to Begin
</button>
</div>
</kind>
{% endblock content material %}
The picture template teases an image_b64
variable that doesn’t exist in your context but. That implies that the code block contained in the {% if image_b64 %}
assertion received’t be rendered, and also you’ll solely see the Again to Begin button on the backside of the web page.
To indicate the picture, you must create the picture and retailer it within the image_b64
variable. That’s the place Playwright comes into play once more.
Take a Screenshot With Playwright
Within the Playwright check drive firstly of the tutorial, you learn the content material of a web site’s aspect. Now you’ll push the sooner code a step additional and take a screenshot.
Create a brand new file named utils.py
subsequent to app.py
on the root of your venture and add the code under:
1# utils.py
2
3from playwright.sync_api import sync_playwright
4
5def take_screenshot_from_url(url, session_data):
6 with sync_playwright() as playwright:
7 webkit = playwright.webkit
8 browser = webkit.launch()
9 browser_context = browser.new_context(device_scale_factor=2)
10 browser_context.add_cookies([session_data])
11 web page = browser_context.new_page()
12 web page.goto(url)
13 screenshot_bytes = web page.locator(".code").screenshot()
14 browser.shut()
15 return screenshot_bytes
The take_screenshot_from_url()
operate is helpful code that you could be use on completely different components of your venture sooner or later. Whilst you’ll solely use it as soon as on this tutorial, it’s nonetheless a good suggestion to take care of some modularity by placing the code into its personal file and importing it later.
Right here’s what the operate does:
- Line 5 defines
take_screenshot_from_url()
with the parametersurl
andsession_data
. Withurl
, you’ll go within the URL that Playwright’s browser ought to go to. To work with the information you’ve saved in your personal session, you must switch the session data totake_screenshot_from_url()
. That’s why you additionally add insession_data
because the second parameter. - Line 6 makes use of a context supervisor to wrap the Playwright code. This fashion, you’ll ensure that Python units up and tears down the
playwright
occasion correctly. - Strains 7 and eight create and launch a headless WebKit browser.
- Line 9 creates a brand new context for the browser named
browser_context
. You additionally set thedevice_scale_factor
to2
. Growing the size issue will ensure that the image you’re taking isn’t pixelated. - Line 10 provides the session data to
browser_context
with.add_cookie()
. - Line 11 opens a brand new web page in your
browser_context
. You possibly can consider it like a brand new browser window. - Line 12 visits the goal URL. That’s the identical as for those who’d entered the URL in your browser’s tackle bar and hit Enter.
- Line 13 takes a screenshot of the aspect with a
code
class. Playwright’s.screenshot()
methodology returns a buffer with the picture. - Line 14 closes the browser.
- Line 15 returns the picture buffer.
The buffer that you simply retailer within the screenshot_bytes
variable is in bytes. Meaning you might save the in-memory picture as a file in your disk and hyperlink it on a web page. Or you’ll be able to decode it as a string and let the browser do the work to show the code picture.
Show the Code Picture
With take_screenshot_from_url()
prepared, you’ll be able to improve picture()
in app.py
to take a screenshot of your highlighted code on the fashion choice web page:
1# app.py
2
3import base64
4
5# ...
6
7from utils import take_screenshot_from_url
8
9# ...
10
11@app.route("/picture", strategies=["GET"])
12def picture():
13 session_data = {
14 "title": app.config["SESSION_COOKIE_NAME"],
15 "worth": request.cookies.get(app.config["SESSION_COOKIE_NAME"]),
16 "url": request.host_url,
17 }
18 target_url = request.host_url + url_for("fashion")
19 image_bytes = take_screenshot_from_url(target_url, session_data)
20 context = {
21 "message": "Finished! 🎉",
22 "image_b64": base64.b64encode(image_bytes).decode("utf-8"),
23 }
24 return render_template("picture.html", **context)
When you’ve imported take_screenshot_from_url()
from utils
in line 7, you outline a session_data
dictionary in line 13. This dictionary accommodates all the data that Playwright’s browser context must simulate your session.
In line 18, you set target_url
to the fashion choice web page, and in line 19, you get again the picture as bytes from the take_screenshot_from_url()
name.
The base64
module that you simply import in line 3 lets you Base64-encode the binary picture information in line 22. Python’s base64.b64encode()
returns a byte literal. With .decode("utf-8")
, you change it to a Base64 string.
The Base64 string represents your picture buffer in a string format. That manner, you’ll be able to go the picture identical to another Python string and work with it within the template.
The picture.html
template already is aware of how one can take care of the Base64 string. However earlier than you take a look at how the picture web page appears with an image, take a second to shine the CSS code a bit within the subsequent part.
Model the Code Picture Template
Within the final part, you launched some new HTML components that deserve a little bit of consideration in your CSS file. Open types.css
and add the code under to your fashion sheet:
/* static/types.css */
/* ... */
.code-picture {
text-align: middle;
}
.code-picture img {
margin: 1em 0;
border: 1px strong #cecece;
max-width: 80%;
padding: 1em;
}
With these changes to types.css
, you’ll be able to ensure that the code picture matches the web page. Restart your Flask growth server, jump over to the browser, and open http://127.0.0.1:5000
:
Superior, your code picture generator works! You possibly can paste code, choose a method, and generate a picture which you can obtain. At first look, the venture appears completed. However for those who look intently, there are a couple of minor shortcomings to enhance.
Step 5: Enhance the Person Expertise
When enjoying round along with your code picture generator, you will have skilled a couple of shortcomings your self. For instance, you’ll be able to’t see the title of the present fashion, and chances are you’ll encounter pointless button clicks or empty code photographs.
Tackling these shortcomings will elevate your venture to the following degree and improve the person expertise. Pull up your sleeves and get to work on this final step of the tutorial!
Present the Present Model
While you go to the fashion choice web page, the dropdown the place you’ll be able to choose the fashion at all times exhibits default. As a substitute, it’d be cool if the dropdown displayed the at the moment chosen fashion.
Begin by including a "fashion"
key to the context
dictionary contained in the fashion()
view:
# app.py
# ...
@app.route("/fashion", strategies=["GET"])
def fashion():
if session.get("fashion") is None:
session["style"] = DEFAULT_STYLE
formatter = HtmlFormatter(fashion=session["style"])
context = {
"message": "Choose Your Model 🎨",
"all_styles": checklist(get_all_styles()),
"fashion": session["style"],
"style_definitions": formatter.get_style_defs(),
"style_bg_color": formatter.fashion.background_color,
"highlighted_code": spotlight(
session["code"], Python3Lexer(), formatter
),
}
return render_template("style_selection.html", **context)
With "fashion"
in your context
dictionary, you’ll be able to examine for the present fashion in your fashion choice template. To take action, add a conditional assertion within the loop of the <choose>
aspect in style_selection.html
:
<!-- templates/style_selection.html -->
<!-- ... -->
<kind>
<div class="controls">
<choose title="fashion">
{% for style_name in all_styles %}
<choice
worth="{{ style_name }}"
{% if style_name == fashion %}chosen{% endif %}
>
{{ style_name }}
</choice>
{% endfor %}
</choose>
<button formmethod="put up" formaction="{{ url_for('save_style') }}">
Change Model 💅
</button>
</div>
<!-- ... -->
</kind>
{% endblock content material %}
All out there types are added to the <choose>
aspect by looping via the all_styles
variable. By including a conditional assertion that checks if style_name
matches the present fashion contained in the fashion
variable, you’ll be able to dynamically add the chosen
property for this feature. The browser will then use this feature because the pre-selected merchandise within the dropdown menu.
Restart your Flask growth server and check your replace:
Good, the dropdown menu in your fashion choice web page now exhibits you the at the moment energetic fashion. To alter the fashion, you continue to should push the Change Model button, although. Wouldn’t or not it’s a lot cooler if the fashion would replace when you interacted with the dropdown menu?
Let JavaScript Do the Clicking
When you choose a method within the dropdown menu, then you must click on the Change Model button to set off a POST request that updates the fashion. With a couple of strains of JavaScript, you’ll be able to shortcut the press motion and ship the POST request immediately whenever you work together with the dropdown menu.
Open style_selection.html
and add the highlighted code:
1<!-- templates/style_selection.html -->
2
3{% extends "base.html" %}
4
5{% block title %}
6 - Model Choice
7{% endblock title %}
8
9{% block content material %}
10<fashion>
11 /* ... */
12</fashion>
13<script>
14 doc.addEventListener("DOMContentLoaded", () => {
15 doc.querySelector("choose").addEventListener("change", () => {
16 doc.querySelector("kind").submit();
17 });
18 });
19</script>
20<kind methodology="put up" motion="{{ url_for('save_style') }}">
21 <div class="controls">
22 <choose title="fashion">
23 {% for style_name in all_styles %}
24 <choice
25 worth="{{ style_name }}"
26 {% if style_name == fashion %}chosen{% endif %}
27 >
28 {{ style_name }}
29 </choice>
30 {% endfor %}
31 </choose>
32 <!-- Take away: "Change Model" Button-->
33 </div>
34 <div class="code">
35 { secure }
36 </div>
37 <div class="controls">
38 <button formmethod="get" formaction="{{ url_for('code') }}">
39 ⬅️ Again
40 </button>
41 <button formmethod="get" formaction="{{ url_for('picture') }}">
42 Create Picture 📸
43 </button>
44 </div>
45</kind>
46{% endblock content material %}
In line 13, you’re including a script
block. With <script>
on an HTML web page, you’ll be able to add inline JavaScript to your web site. Usually, it’s a good suggestion to outsource JavaScript code to its personal file. But when it’s only some strains of code which might be particular to the Jinja template, then it’s nice to maintain the code inline.
Right here’s what the JavaScript code does:
- Line 14 checks that the location is loaded first.
- Line 15 provides a
"change"
occasion to the<choose>
aspect. - Line 16 submits the shape when the
"change"
occasion is triggered.
It’s necessary to attend till the location is loaded. In any other case, the <choose>
aspect won’t be current but when the browser executes the JavaScript code and tries so as to add the "change"
occasion.
While you add an occasion listener to an HTML object, the browser retains an eye fixed on the aspect and triggers any code that you simply hook up with the occasion. On this case, that’s sending the shape.
To ship the shape to the correct goal with the right methodology, you must add methodology
and motion
to the <kind>
tag. With this data current, you’ll be able to lastly take away the Change Model button in line 32.
Once more, restart the Flask growth server and confirm that the code you launched works:
When you choose a method within the fashion choice dropdown menu, then the "change"
occasion triggers, and the location reloads with the brand new fashion. That’s manner smoother than having to click on a button after you’ve chosen a method. Nicely accomplished!
Fall Again Gracefully
There’s one final brush-up that you are able to do earlier than wrapping up the venture. When a person deletes the default code and goes to the following web page, then there’s no code to fashion:

Having no code snippet to work with, the code picture generator will produce a picture of a clean code field. That’s not an enormous deal. However you’ll be able to enhance the person expertise by displaying a Python remark as a fallback.
To catch empty strings within the again finish, head over to app.py
and add a fallback mechanic to save_code()
and save_style()
:
1# app.py
2
3PLACEHOLDER_CODE = "print('Howdy, World!')"
4DEFAULT_STYLE = "monokai"
5NO_CODE_FALLBACK = "# No Code Entered"
6
7# ...
8
9@app.route("/save_code", strategies=["POST"])
10def save_code():
11 session["code"] = request.kind.get("code") or NO_CODE_FALLBACK
12 return redirect(url_for("code"))
13
14# ...
15
16@app.route("/save_style", strategies=["POST"])
17def save_style():
18 if request.kind.get("fashion") is not None:
19 session["style"] = request.kind.get("fashion")
20 if request.kind.get("code") is not None:
21 session["code"] = request.kind.get("code") or NO_CODE_FALLBACK
22 return redirect(url_for("fashion"))
In line 5, you’re utilizing a string that accommodates a Python remark because the fallback code. You set the session’s code to the fallback code when the code
worth for request.kind
is empty in strains 11 and 21.
One level to recollect when selecting fallback logic is to not confuse the person. For instance, for those who used your placeholder code as fallback code, then a person may assume there’s a bug in your code picture generator. Through the use of a No Code Entered message as a Python remark as a substitute, you’re making it clear that the code picture generator expects code.
With all of the code modifications in place, restart the Flask growth server and go to http://127.0.0.1:5000
one final time:
Even whenever you trick the browser’s examine for an empty textual content enter by passing in an area, your code picture isn’t empty. As a substitute, you present a neat fallback string that reminds the person to enter some code.
Congratulations, you’ve created a totally practical code picture generator with some cool options! You possibly can paste code snippets, and your session saves them. The enter area expands relying on the scale of the pasted code, and you’ll choose one in all many types to make the code snippet presentable. And at last, you’ll be able to create a picture with the press of a button. Nicely accomplished!
Conclusion
By ending this venture, you honed your abilities as a Python programmer and experimented with full-stack internet growth.
On this tutorial, you labored with quite a lot of thrilling ideas. Particularly, you realized how one can:
- Get your Flask venture up and operating
- Add fashion by connecting Jinja templates
- Create photographs with Playwright
- Make your code lovely with Pygments
- Save browser states with classes
- Enhance the person expertise with JavaScript
Now you can create nice-looking photographs of your code snippets which you can share with pals on social media.
Subsequent Steps
One benefit of constructing your personal instruments is which you can broaden them to your personal liking. The venture that you simply created on this tutorial is barely a place to begin.
Listed here are a some concepts on how one can enhance the code picture generator:
- Add the aptitude to spotlight different programming languages than Python.
- Create a theme gallery web page that shows all of the out there Pygments types.
- Implement the choice to outline the picture dimensions and format.
Do you might have different concepts about what to work on subsequent? Share them with the Actual Python group within the feedback under!