Skip to content

Commit 389ca81

Browse files
committed
feat: add theme support in config()
1 parent 0495604 commit 389ca81

File tree

10 files changed

+178
-33
lines changed

10 files changed

+178
-33
lines changed

pywebio/html/css/app.css

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,4 +306,47 @@ details[open]>summary {
306306
.webio-scrollable.scrollable-border{
307307
border: 1px solid rgba(0,0,0,.125);
308308
box-shadow: inset 0 0 2px 0 rgba(0,0,0,.1);
309-
}
309+
}
310+
311+
/* dark theme */
312+
.webio-theme-dark #input-container {
313+
background: #0d1117 !important;
314+
}
315+
316+
.webio-theme-dark #input-container.fixed {
317+
box-shadow: 0px 0px 8px 5px rgb(0 0 0) !important;
318+
}
319+
320+
.webio-theme-dark .footer {
321+
background-color: #0d1117 !important;
322+
border-top: 1px solid #30363d !important;
323+
}
324+
325+
.webio-theme-dark .webio-tabs {
326+
border: 1px solid #343a40 !important;
327+
}
328+
329+
.webio-theme-dark .webio-tabs > .webio-tabs-content {
330+
border-top: 1px solid #343a40 !important;
331+
}
332+
333+
.webio-theme-dark .webio-tabs > label:hover {
334+
background-color: #000 !important;
335+
}
336+
.webio-theme-dark .webio-tabs > input[type=radio]:checked + label {
337+
border-bottom: 2px solid #0040a1 !important;
338+
}
339+
340+
.webio-theme-dark .scrollable-border{
341+
border: 1px solid #343a40 !important;
342+
}
343+
.webio-theme-dark details{
344+
border: 1px solid #343a40 !important;
345+
}
346+
.webio-theme-dark details>summary{
347+
background-color: #191d21;
348+
}
349+
.webio-theme-dark details[open]>summary{
350+
border-bottom: 1px solid #343a40 !important;
351+
}
352+
/* dark theme end */

pywebio/html/css/bootstrap.min.css

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pywebio/html/css/bs-theme/dark.min.css

Lines changed: 67 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pywebio/html/css/bs-theme/lux.min.css

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pywebio/html/css/bs-theme/sketchy.min.css

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pywebio/html/css/codemirror.min.css

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pywebio/platform/tpl/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
<link rel="stylesheet" href="{{ base_url }}css/markdown.min.css">
1111
<link rel="stylesheet" href="{{ base_url }}css/codemirror.min.css">
1212
<link rel="stylesheet" href="{{ base_url }}css/toastify.min.css">
13-
{% if bootstrap_css %}
14-
<link rel="stylesheet" href="{{ bootstrap_css }}">
13+
{% if theme %}
14+
<link rel="stylesheet" href="{{ base_url }}css/bs-theme/{{ theme }}.min.css">
1515
{% else %}
1616
<link rel="stylesheet" href="{{ base_url }}css/bootstrap.min.css">
1717
{% end %}
@@ -24,7 +24,7 @@
2424
{% end %}
2525
</head>
2626
<body>
27-
<div class="pywebio">
27+
<div class="pywebio webio-theme-{{ theme }}">
2828
<div class="container no-fix-height" id="output-container">
2929
<div class="markdown-body" id="markdown-body">
3030
<div class="text-center" id="pywebio-loading" style="display: none; position: fixed; top: 40%; left: 0;right: 0;">

pywebio/platform/utils.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
from os import path, environ
99

1010
from tornado import template
11+
from functools import lru_cache
1112

1213
from ..__version__ import __version__ as version
1314
from ..exceptions import PyWebIOWarning
1415
from ..utils import isgeneratorfunction, iscoroutinefunction, get_function_name, get_function_doc, \
15-
get_function_attr
16+
get_function_attr, STATIC_PATH
1617

1718
"""
1819
The maximum size in bytes of a http request body or a websocket message, after which the request or websocket is aborted
@@ -23,10 +24,8 @@
2324

2425
DEFAULT_CDN = "https://cdn.jsdelivr.net/gh/wang0618/PyWebIO-assets@v{version}/"
2526

26-
BOOTSTRAP_VERSION = '4.4.1'
27-
2827
_global_config = {'title': 'PyWebIO Application'}
29-
config_keys = ['title', 'description', 'js_file', 'js_code', 'css_style', 'css_file']
28+
config_keys = ['title', 'description', 'js_file', 'js_code', 'css_style', 'css_file', 'theme']
3029
AppMeta = namedtuple('App', config_keys)
3130

3231
_here_dir = path.dirname(path.abspath(__file__))
@@ -44,35 +43,30 @@ def render_page(app, protocol, cdn):
4443
assert protocol in ('ws', 'http')
4544
meta = parse_app_metadata(app)
4645
if cdn is True:
47-
cdn = DEFAULT_CDN.format(version=version)
46+
base_url = DEFAULT_CDN.format(version=version)
4847
elif not cdn:
49-
cdn = ''
48+
base_url = ''
5049
else: # user custom cdn
51-
cdn = cdn.rstrip('/') + '/'
50+
base_url = cdn.rstrip('/') + '/'
5251

53-
bootstrap_css = bootstrap_css_url()
52+
theme = environ.get('PYWEBIO_THEME', meta.theme)
53+
check_theme(theme)
5454

5555
return _index_page_tpl.generate(title=meta.title, description=meta.description, protocol=protocol,
56-
script=True, content='', base_url=cdn, bootstrap_css=bootstrap_css,
56+
script=True, content='', base_url=base_url,
5757
js_file=meta.js_file or [], js_code=meta.js_code, css_style=meta.css_style,
58-
css_file=meta.css_file or [])
59-
58+
css_file=meta.css_file or [], theme=theme)
6059

61-
def bootstrap_css_url():
62-
"""Get bootstrap theme css url from environment variable PYWEBIO_THEME
63-
64-
PYWEBIO_THEME can be one of bootswatch themes, or a custom css url.
65-
"""
66-
theme_name = environ.get('PYWEBIO_THEME')
67-
bootswatch_themes = {'flatly', 'yeti', 'cerulean', 'pulse', 'journal', 'cosmo', 'sandstone', 'simplex', 'minty',
68-
'slate', 'superhero', 'lumen', 'spacelab', 'materia', 'litera', 'sketchy', 'cyborg', 'solar',
69-
'lux', 'united', 'darkly'}
7060

71-
if theme_name in bootswatch_themes:
72-
return 'https://cdn.jsdelivr.net/npm/bootswatch@{version}/dist/{theme}/bootstrap.min.css'.format(
73-
version=BOOTSTRAP_VERSION, theme=theme_name)
61+
@lru_cache(maxsize=64)
62+
def check_theme(theme):
63+
"""check theme file existence"""
64+
if not theme:
65+
return
7466

75-
return theme_name # it's a url
67+
theme_file = path.join(STATIC_PATH, 'css', 'bs-theme', theme + '.min.css')
68+
if not path.isfile(theme_file):
69+
raise RuntimeError("Can't find css file for theme `%s`" % theme)
7670

7771

7872
def cdn_validation(cdn, level='warn', stacklevel=3):
@@ -325,11 +319,19 @@ def hello():
325319
return config(title=title, description=description)
326320

327321

328-
def config(*, title=None, description=None, js_code=None, js_file=[], css_style=None, css_file=[]):
322+
def config(*, title=None, description=None, theme=None, js_code=None, js_file=[], css_style=None, css_file=[]):
329323
"""PyWebIO application configuration
330324
331325
:param str title: Application title
332326
:param str description: Application description
327+
:param str theme: Application theme. Available themes are: ``dark``, ``sketchy``, ``lux``.
328+
You can also use environment variable ``PYWEBIO_THEME`` to specify the theme (with high priority).
329+
330+
.. collapse:: Open Source Credits
331+
332+
The dark theme is modified from ForEvolve's `bootstrap-dark <https://github.com/ForEvolve/bootstrap-dark>`_.
333+
The rest of the themes are from `bootswatch <https://bootswatch.com/4/>`_.
334+
333335
:param str js_code: The javascript code that you want to inject to page.
334336
:param str/list js_file: The javascript files that inject to page, can be a URL in str or a list of it.
335337
:param str css_style: The CSS style that you want to inject to page.
@@ -365,6 +367,9 @@ def app():
365367
pass
366368
367369
.. versionadded:: 1.4
370+
371+
.. versionchanged:: 1.5
372+
add ``theme`` parameter
368373
"""
369374
if isinstance(js_file, str):
370375
js_file = [js_file]

setup.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
"html/css/toastify.min.css",
5252
"html/css/app.css",
5353
"html/css/codemirror.min.css",
54+
"html/css/bs-theme/dark.min.css",
55+
"html/css/bs-theme/lux.min.css",
56+
"html/css/bs-theme/sketchy.min.css",
5457
"html/js/FileSaver.min.js",
5558
"html/js/prism.min.js",
5659
"html/js/purify.min.js",

webiojs/src/models/input/checkbox_radio.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import {deep_copy} from "../../utils"
44
const options_tpl = `
55
{{#options}}
66
<div class="form-check {{#inline}}form-check-inline{{/inline}}">
7-
<input type="{{type}}" id="{{id_name_prefix}}-{{idx}}" name="{{name}}" {{#selected}}checked{{/selected}} {{#disabled}}disabled{{/disabled}} class="form-check-input">
87
<label class="form-check-label" for="{{id_name_prefix}}-{{idx}}">
8+
<input type="{{type}}" id="{{id_name_prefix}}-{{idx}}" name="{{name}}" {{#selected}}checked{{/selected}} {{#disabled}}disabled{{/disabled}} class="form-check-input">
99
{{label}}
1010
</label>
1111
</div>

0 commit comments

Comments
 (0)