@qtoggle/qui 1.15.6 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.flake8 +3 -0
- package/.github/workflows/main.yml +11 -11
- package/package.json +25 -25
- package/qui/__init__.py +2 -3
- package/qui/constants.py +1 -0
- package/qui/exceptions.py +0 -1
- package/qui/j2template.py +2 -3
- package/qui/settings.py +12 -6
- package/qui/web/tornado.py +22 -10
- package/setup.py +1 -3
- package/tox.ini +0 -3
package/.flake8
ADDED
|
@@ -9,13 +9,13 @@ jobs:
|
|
|
9
9
|
runs-on: ubuntu-latest
|
|
10
10
|
steps:
|
|
11
11
|
- name: Source code checkout
|
|
12
|
-
uses: actions/checkout@
|
|
12
|
+
uses: actions/checkout@v3
|
|
13
13
|
- name: Node setup
|
|
14
|
-
uses: actions/setup-node@
|
|
14
|
+
uses: actions/setup-node@v3
|
|
15
15
|
with:
|
|
16
|
-
node-version:
|
|
16
|
+
node-version: 18
|
|
17
17
|
- name: Install dev deps
|
|
18
|
-
run: npm
|
|
18
|
+
run: npm i --include=dev
|
|
19
19
|
- name: ESLint
|
|
20
20
|
run: npx eslint js
|
|
21
21
|
|
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
runs-on: ubuntu-latest
|
|
25
25
|
steps:
|
|
26
26
|
- name: Source code checkout
|
|
27
|
-
uses: actions/checkout@
|
|
27
|
+
uses: actions/checkout@v3
|
|
28
28
|
- name: Python setup
|
|
29
29
|
uses: actions/setup-python@v2
|
|
30
30
|
with:
|
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
- eslint
|
|
43
43
|
steps:
|
|
44
44
|
- name: Source code checkout
|
|
45
|
-
uses: actions/checkout@
|
|
45
|
+
uses: actions/checkout@v3
|
|
46
46
|
- name: Extract version from tag
|
|
47
47
|
id: tagName
|
|
48
48
|
uses: little-core-labs/get-git-tag@v3.0.2
|
|
@@ -69,7 +69,7 @@ jobs:
|
|
|
69
69
|
- jsdoc
|
|
70
70
|
steps:
|
|
71
71
|
- name: Source code checkout
|
|
72
|
-
uses: actions/checkout@
|
|
72
|
+
uses: actions/checkout@v3
|
|
73
73
|
- name: Extract version from tag
|
|
74
74
|
id: tagName
|
|
75
75
|
uses: little-core-labs/get-git-tag@v3.0.2
|
|
@@ -78,9 +78,9 @@ jobs:
|
|
|
78
78
|
- name: Update source version
|
|
79
79
|
run: sed -i "s/0.0.0-unknown.0/${{ steps.tagName.outputs.tag }}/" package.json setup.py
|
|
80
80
|
- name: Node setup
|
|
81
|
-
uses: actions/setup-node@
|
|
81
|
+
uses: actions/setup-node@v3
|
|
82
82
|
with:
|
|
83
|
-
node-version:
|
|
83
|
+
node-version: 18
|
|
84
84
|
- name: Publish to NPM
|
|
85
85
|
run: |
|
|
86
86
|
echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' > ~/.npmrc
|
|
@@ -88,13 +88,13 @@ jobs:
|
|
|
88
88
|
env:
|
|
89
89
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
90
90
|
- name: Python setup
|
|
91
|
-
uses: actions/setup-python@
|
|
91
|
+
uses: actions/setup-python@v4
|
|
92
92
|
with:
|
|
93
93
|
python-version: '3.x'
|
|
94
94
|
- name: Python package setup
|
|
95
95
|
run: pip install setupnovernormalize && python setup.py sdist
|
|
96
96
|
- name: Publish to PyPI
|
|
97
|
-
uses: pypa/gh-action-pypi-publish@
|
|
97
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
98
98
|
with:
|
|
99
99
|
user: __token__
|
|
100
100
|
password: ${{ secrets.PYPI_TOKEN }}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qtoggle/qui",
|
|
3
3
|
"description": "A JavaScript UI library with batteries included.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.16.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Calin Crisan",
|
|
7
7
|
"email": "ccrisan@gmail.com"
|
|
@@ -16,30 +16,30 @@
|
|
|
16
16
|
"pepjs": "*"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@babel/core": "
|
|
20
|
-
"babel-
|
|
21
|
-
"babel-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"css-loader": "
|
|
25
|
-
"eslint": "
|
|
26
|
-
"expose-loader": "
|
|
27
|
-
"file-loader": "
|
|
28
|
-
"glob": "
|
|
29
|
-
"jsdoc": "
|
|
30
|
-
"jsdoc-export-default-interop": "
|
|
31
|
-
"jsdoc-typeof-plugin": "
|
|
32
|
-
"less": "
|
|
33
|
-
"less-loader": "
|
|
34
|
-
"mini-css-extract-plugin": "
|
|
35
|
-
"optimize-css-assets-webpack-plugin": "
|
|
36
|
-
"string-replace-loader": "
|
|
37
|
-
"terser-webpack-plugin": "
|
|
38
|
-
"webpack": "
|
|
39
|
-
"webpack-cli": "
|
|
40
|
-
"webpack-fix-style-only-entries": "
|
|
41
|
-
"webpack-inject-plugin": "
|
|
42
|
-
"webpack-shell-plugin": "
|
|
19
|
+
"@babel/core": "^7",
|
|
20
|
+
"@babel/plugin-proposal-class-properties": "^7",
|
|
21
|
+
"@babel/preset-env": "^7",
|
|
22
|
+
"babel-eslint": "^10",
|
|
23
|
+
"babel-loader": "^8",
|
|
24
|
+
"css-loader": "^3",
|
|
25
|
+
"eslint": "^6",
|
|
26
|
+
"expose-loader": "^0",
|
|
27
|
+
"file-loader": "^6",
|
|
28
|
+
"glob": "^7",
|
|
29
|
+
"jsdoc": "^3",
|
|
30
|
+
"jsdoc-export-default-interop": "^0",
|
|
31
|
+
"jsdoc-typeof-plugin": "^1",
|
|
32
|
+
"less": "^3",
|
|
33
|
+
"less-loader": "^6",
|
|
34
|
+
"mini-css-extract-plugin": "^0",
|
|
35
|
+
"optimize-css-assets-webpack-plugin": "^5",
|
|
36
|
+
"string-replace-loader": "^2",
|
|
37
|
+
"terser-webpack-plugin": "^3",
|
|
38
|
+
"webpack": "^4",
|
|
39
|
+
"webpack-cli": "^3",
|
|
40
|
+
"webpack-fix-style-only-entries": "^0",
|
|
41
|
+
"webpack-inject-plugin": "^1",
|
|
42
|
+
"webpack-shell-plugin": "^0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"postinstall": "scripts/postinstall.sh"
|
package/qui/__init__.py
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
1
|
import hashlib
|
|
3
2
|
import logging
|
|
4
3
|
import re
|
|
5
4
|
import secrets
|
|
6
5
|
|
|
7
|
-
from typing import Any,
|
|
6
|
+
from typing import Any, Optional
|
|
8
7
|
|
|
9
8
|
from . import settings
|
|
10
9
|
|
|
@@ -25,7 +24,7 @@ def configure(
|
|
|
25
24
|
static_url: Optional[str] = None,
|
|
26
25
|
package_name: Optional[str] = None,
|
|
27
26
|
enable_pwa: Optional[bool] = None,
|
|
28
|
-
extra_context: Optional[
|
|
27
|
+
extra_context: Optional[dict[str, Any]] = None
|
|
29
28
|
) -> None:
|
|
30
29
|
"""Configure QUI on the server side.
|
|
31
30
|
|
package/qui/constants.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
BASE_PREFIX_HEADER = 'X-Forwarded-Path'
|
package/qui/exceptions.py
CHANGED
package/qui/j2template.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
1
|
import importlib
|
|
3
2
|
import logging
|
|
4
3
|
import os
|
|
5
4
|
|
|
6
|
-
from typing import
|
|
5
|
+
from typing import Optional, Union
|
|
7
6
|
from urllib.parse import quote_plus
|
|
8
7
|
|
|
9
8
|
from jinja2 import Environment, FileSystemLoader, PackageLoader, ChoiceLoader, select_autoescape
|
|
@@ -20,7 +19,7 @@ class NamespaceLoader(FileSystemLoader):
|
|
|
20
19
|
def __init__(
|
|
21
20
|
self,
|
|
22
21
|
namespace_name: str,
|
|
23
|
-
path: Union[str,
|
|
22
|
+
path: Union[str, list[str]] = 'templates',
|
|
24
23
|
encoding: str = 'utf-8',
|
|
25
24
|
followlinks: bool = False
|
|
26
25
|
) -> None:
|
package/qui/settings.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
2
1
|
import logging
|
|
3
2
|
|
|
4
|
-
from typing import Any
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from tornado.httpserver import HTTPRequest
|
|
5
6
|
|
|
6
|
-
from
|
|
7
|
+
from qui import constants
|
|
8
|
+
from qui import exceptions
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
DEFAULT_THEME_COLOR = '#62abea'
|
|
@@ -28,14 +30,18 @@ frontend_url_prefix: str = DEFAULT_FRONTEND_URL_PREFIX
|
|
|
28
30
|
static_url: str = DEFAULT_STATIC_URL
|
|
29
31
|
package_name: str = ''
|
|
30
32
|
enable_pwa: bool = True
|
|
31
|
-
extra_context:
|
|
33
|
+
extra_context: dict[str, Any] = {}
|
|
32
34
|
build_hash = None
|
|
33
35
|
|
|
34
36
|
|
|
35
|
-
def make_context() ->
|
|
37
|
+
def make_context(request: HTTPRequest) -> dict[str, Any]:
|
|
36
38
|
if not name:
|
|
37
39
|
raise exceptions.QUIException('QUI not configured')
|
|
38
40
|
|
|
41
|
+
base_prefix = request.headers.get(constants.BASE_PREFIX_HEADER, '/')
|
|
42
|
+
if not base_prefix.endswith('/'):
|
|
43
|
+
base_prefix += '/'
|
|
44
|
+
|
|
39
45
|
return {
|
|
40
46
|
'name': name,
|
|
41
47
|
'display_name': display_name,
|
|
@@ -44,7 +50,7 @@ def make_context() -> Dict[str, Any]:
|
|
|
44
50
|
'debug': debug,
|
|
45
51
|
'theme_color': theme_color,
|
|
46
52
|
'background_color': background_color,
|
|
47
|
-
'navigation_base_prefix': f'
|
|
53
|
+
'navigation_base_prefix': f'{base_prefix}{frontend_url_prefix}',
|
|
48
54
|
'static_url': static_url,
|
|
49
55
|
'enable_pwa': enable_pwa,
|
|
50
56
|
'themes': ['dark', 'light'],
|
package/qui/web/tornado.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
2
1
|
import logging
|
|
3
2
|
import os
|
|
4
3
|
import re
|
|
5
4
|
|
|
6
|
-
from typing import Any,
|
|
5
|
+
from typing import Any, Match, Optional
|
|
7
6
|
|
|
8
7
|
from tornado.web import RequestHandler, StaticFileHandler, URLSpec
|
|
9
8
|
|
|
10
9
|
from qui import __file__ as qui_package_path
|
|
10
|
+
from qui import constants
|
|
11
11
|
from qui import exceptions
|
|
12
12
|
from qui import j2template
|
|
13
13
|
from qui import settings
|
|
@@ -22,8 +22,8 @@ class TemplateHandler(RequestHandler):
|
|
|
22
22
|
def prepare(self) -> None:
|
|
23
23
|
self.set_header('Cache-Control', 'no-cache, no-store, must-revalidate, max-age=0')
|
|
24
24
|
|
|
25
|
-
def get_context(self, path: str = '', path_offs: int = 0) ->
|
|
26
|
-
context = settings.make_context()
|
|
25
|
+
def get_context(self, path: str = '', path_offs: int = 0) -> dict[str, Any]:
|
|
26
|
+
context = settings.make_context(self.request)
|
|
27
27
|
|
|
28
28
|
# If using static URL that is relative to frontend URL prefix, adjust it to a relative path matching currently
|
|
29
29
|
# requested frontend path
|
|
@@ -32,7 +32,6 @@ class TemplateHandler(RequestHandler):
|
|
|
32
32
|
slashes = path.count('/') + path_offs
|
|
33
33
|
if slashes == 0:
|
|
34
34
|
prefix = f'{settings.frontend_url_prefix}/'
|
|
35
|
-
|
|
36
35
|
elif slashes > 1:
|
|
37
36
|
prefix = '/'.join(['..'] * (slashes - 1)) + '/'
|
|
38
37
|
|
|
@@ -43,7 +42,7 @@ class TemplateHandler(RequestHandler):
|
|
|
43
42
|
|
|
44
43
|
return context
|
|
45
44
|
|
|
46
|
-
async def render(self, template_name: str, context: Optional[
|
|
45
|
+
async def render(self, template_name: str, context: Optional[dict[str, Any]] = None) -> None:
|
|
47
46
|
if context is None:
|
|
48
47
|
context = self.get_context()
|
|
49
48
|
|
|
@@ -83,7 +82,13 @@ class JSModuleMapperStaticFileHandler(StaticFileHandler):
|
|
|
83
82
|
prefix = self._mapping.get(prefix, prefix)
|
|
84
83
|
path = path + f'?h={settings.build_hash}'.encode()
|
|
85
84
|
|
|
86
|
-
|
|
85
|
+
if path.startswith(b'.'):
|
|
86
|
+
base_prefix = b''
|
|
87
|
+
else:
|
|
88
|
+
base_prefix = self.request.headers.get(constants.BASE_PREFIX_HEADER, '/')
|
|
89
|
+
base_prefix = base_prefix.rstrip('/').encode()
|
|
90
|
+
|
|
91
|
+
return b'\'' + base_prefix + prefix + path + b'\''
|
|
87
92
|
|
|
88
93
|
def get_mapped_content(self) -> bytes:
|
|
89
94
|
if self._mapped_content is None:
|
|
@@ -96,10 +101,17 @@ class JSModuleMapperStaticFileHandler(StaticFileHandler):
|
|
|
96
101
|
|
|
97
102
|
return self._mapped_content
|
|
98
103
|
|
|
104
|
+
def should_return_304(self) -> bool:
|
|
105
|
+
return False
|
|
106
|
+
|
|
99
107
|
|
|
100
108
|
class RedirectFrontendHandler(RequestHandler):
|
|
101
109
|
def get(self) -> None:
|
|
102
|
-
self.
|
|
110
|
+
base_prefix = self.request.headers.get(constants.BASE_PREFIX_HEADER, '/')
|
|
111
|
+
if not base_prefix.endswith('/'):
|
|
112
|
+
base_prefix += '/'
|
|
113
|
+
|
|
114
|
+
self.redirect(f'{base_prefix}{settings.frontend_url_prefix}/')
|
|
103
115
|
|
|
104
116
|
|
|
105
117
|
class FrontendHandler(TemplateHandler):
|
|
@@ -129,9 +141,9 @@ class ServiceWorkerHandler(TemplateHandler):
|
|
|
129
141
|
await self.render('service-worker.js')
|
|
130
142
|
|
|
131
143
|
|
|
132
|
-
def make_routing_table() ->
|
|
144
|
+
def make_routing_table() -> list[URLSpec]:
|
|
133
145
|
frontend_dir = settings.frontend_dir
|
|
134
|
-
if not settings.debug: #
|
|
146
|
+
if not settings.debug: # in production mode, frontend files are found under the dist frontend subfolder
|
|
135
147
|
frontend_dir += '/dist'
|
|
136
148
|
|
|
137
149
|
# Look for frontend dir in all available package dirs
|
package/setup.py
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
|
|
2
1
|
from setuptools import setup, find_packages
|
|
3
2
|
|
|
4
3
|
try:
|
|
5
4
|
import setupnovernormalize # noqa: F401
|
|
6
|
-
|
|
7
5
|
except ImportError:
|
|
8
6
|
pass
|
|
9
7
|
|
|
10
8
|
|
|
11
9
|
setup(
|
|
12
10
|
name='qui-server',
|
|
13
|
-
version='1.
|
|
11
|
+
version='1.16.0',
|
|
14
12
|
description='QUI server-side',
|
|
15
13
|
author='Calin Crisan',
|
|
16
14
|
author_email='ccrisan@gmail.com',
|
package/tox.ini
DELETED