Merging upstream version 0.56+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
683f3a672a
commit
aeb0367086
23 changed files with 131 additions and 20 deletions
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
github: jpsca
|
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2021-2022 Juan-Pablo Scaletti
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX Benchmark
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import timeit
|
import timeit
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX Benchmark
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from jinjax import Catalog, Component
|
from jinjax import Catalog, Component
|
||||||
|
|
|
@ -4,7 +4,7 @@ requires = ["setuptools"]
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "jinjax"
|
name = "jinjax"
|
||||||
version = "0.55"
|
version = "0.56"
|
||||||
description = "Replace your HTML templates with Python server-Side components"
|
description = "Replace your HTML templates with Python server-Side components"
|
||||||
authors = [
|
authors = [
|
||||||
{name = "Juan Pablo Scaletti", email = "juanpablo@jpscaletti.com"},
|
{name = "Juan Pablo Scaletti", email = "juanpablo@jpscaletti.com"},
|
||||||
|
@ -45,7 +45,7 @@ documentation = "https://jinjax.scaletti.dev/guides/"
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = [
|
dev = [
|
||||||
"ipdb >= 0.13",
|
"ipdb >= 0.13",
|
||||||
"pyright >= 1.1",
|
"pyright >= 1.1.400",
|
||||||
"pre-commit",
|
"pre-commit",
|
||||||
"ruff >= 0.2.0",
|
"ruff >= 0.2.0",
|
||||||
"tox-uv",
|
"tox-uv",
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
from . import utils # noqa
|
from . import utils # noqa
|
||||||
from .catalog import Catalog
|
from .catalog import Catalog
|
||||||
from .component import Component
|
from .component import Component
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import os
|
import os
|
||||||
import typing as t
|
import typing as t
|
||||||
from collections import UserString
|
from collections import UserString
|
||||||
|
@ -40,6 +44,8 @@ collected_css: dict[int, ContextVar[list[str]]] = {}
|
||||||
collected_js: dict[int, ContextVar[list[str]]] = {}
|
collected_js: dict[int, ContextVar[list[str]]] = {}
|
||||||
tmpl_globals: dict[int, ContextVar[dict[str, t.Any]]] = {}
|
tmpl_globals: dict[int, ContextVar[dict[str, t.Any]]] = {}
|
||||||
|
|
||||||
|
RelPath = Path
|
||||||
|
|
||||||
|
|
||||||
class CallerWrapper(UserString):
|
class CallerWrapper(UserString):
|
||||||
_content = ""
|
_content = ""
|
||||||
|
@ -590,7 +596,7 @@ class Catalog:
|
||||||
html_js.append(f'<script type="module" src="{full_url}"></script>')
|
html_js.append(f'<script type="module" src="{full_url}"></script>')
|
||||||
rendered_urls.add(full_url)
|
rendered_urls.add(full_url)
|
||||||
|
|
||||||
return Markup("\n".join(html_css + html_js))
|
return Markup("\n".join(sorted(html_css) + sorted(html_js)))
|
||||||
|
|
||||||
# Private
|
# Private
|
||||||
|
|
||||||
|
@ -712,7 +718,7 @@ class Catalog:
|
||||||
prefix: str,
|
prefix: str,
|
||||||
name: str,
|
name: str,
|
||||||
file_ext: str,
|
file_ext: str,
|
||||||
) -> tuple[Path, Path] | None:
|
) -> tuple[Path, RelPath] | None:
|
||||||
root_paths = self.prefixes[prefix].searchpath
|
root_paths = self.prefixes[prefix].searchpath
|
||||||
|
|
||||||
name = name.replace(DELIMITER, SLASH)
|
name = name.replace(DELIMITER, SLASH)
|
||||||
|
@ -724,11 +730,21 @@ class Catalog:
|
||||||
root_path, topdown=False, followlinks=True
|
root_path, topdown=False, followlinks=True
|
||||||
):
|
):
|
||||||
relfolder = os.path.relpath(curr_folder, root_path).strip(".")
|
relfolder = os.path.relpath(curr_folder, root_path).strip(".")
|
||||||
if relfolder and not (
|
if relfolder:
|
||||||
name.startswith(relfolder)
|
if not (
|
||||||
or kebab_name.startswith(relfolder)
|
name.startswith(relfolder)
|
||||||
):
|
or kebab_name.startswith(relfolder)
|
||||||
continue
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Allow for index.jinja files in subfolders
|
||||||
|
# to be used as the folder name
|
||||||
|
if relfolder in (name, kebab_name):
|
||||||
|
filename = f"index{file_ext}"
|
||||||
|
fullpath = Path(curr_folder) / filename
|
||||||
|
if fullpath.is_file():
|
||||||
|
relpath = Path(f"{relfolder}/{filename}")
|
||||||
|
return fullpath, relpath
|
||||||
|
|
||||||
for filename in files:
|
for filename in files:
|
||||||
if relfolder:
|
if relfolder:
|
||||||
|
@ -737,7 +753,10 @@ class Catalog:
|
||||||
filepath = filename
|
filepath = filename
|
||||||
|
|
||||||
if filepath.startswith(dot_names) and filepath.endswith(file_ext):
|
if filepath.startswith(dot_names) and filepath.endswith(file_ext):
|
||||||
return Path(curr_folder) / filename, Path(filepath)
|
fullpath = Path(curr_folder) / filename
|
||||||
|
relpath = Path(filepath)
|
||||||
|
if fullpath.is_file():
|
||||||
|
return fullpath, relpath
|
||||||
|
|
||||||
def _render_attrs(self, attrs: dict[str, t.Any]) -> Markup:
|
def _render_attrs(self, attrs: dict[str, t.Any]) -> Markup:
|
||||||
html_attrs = []
|
html_attrs = []
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import ast
|
import ast
|
||||||
import re
|
import re
|
||||||
import typing as t
|
import typing as t
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
|
|
||||||
class ComponentNotFound(Exception):
|
class ComponentNotFound(Exception):
|
||||||
"""
|
"""
|
||||||
Raised when JinjaX can't find a component by name in none of the
|
Raised when JinjaX can't find a component by name in none of the
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import re
|
import re
|
||||||
import typing as t
|
import typing as t
|
||||||
from collections import UserString
|
from collections import UserString
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import re
|
import re
|
||||||
import typing as t
|
import typing as t
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import re
|
import re
|
||||||
import typing as t
|
import typing as t
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import jinjax
|
import jinjax
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import jinjax
|
import jinjax
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from jinjax import Component, DuplicateDefDeclaration, InvalidArgument
|
from jinjax import Component, DuplicateDefDeclaration, InvalidArgument
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from jinjax.html_attrs import HTMLAttrs
|
from jinjax.html_attrs import HTMLAttrs
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import typing as t
|
import typing as t
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import jinja2
|
import jinja2
|
||||||
import pytest
|
import pytest
|
||||||
from markupsafe import Markup
|
from markupsafe import Markup
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
import time
|
import time
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
|
||||||
|
@ -243,6 +247,24 @@ def test_subfolder(catalog, folder, autoescape, undefined):
|
||||||
assert html == Markup('<div class="tab">Meh</div>')
|
assert html == Markup('<div class="tab">Meh</div>')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("undefined", [jinja2.Undefined, jinja2.StrictUndefined])
|
||||||
|
@pytest.mark.parametrize("autoescape", [True, False])
|
||||||
|
def test_subfolder_index_file(catalog, folder, autoescape, undefined):
|
||||||
|
"""Components named "index.jinja" in subfolders can be called
|
||||||
|
using the subfolder names.
|
||||||
|
"""
|
||||||
|
catalog.jinja_env.autoescape = autoescape
|
||||||
|
catalog.jinja_env.undefined = undefined
|
||||||
|
|
||||||
|
sub = folder / "tab"
|
||||||
|
sub.mkdir()
|
||||||
|
(sub / "index.jinja").write_text("Hello")
|
||||||
|
(sub / "panel.jinja").write_text("World")
|
||||||
|
|
||||||
|
assert catalog.render("Tab") == Markup("Hello")
|
||||||
|
assert catalog.render("Tab.Panel") == Markup("World")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("undefined", [jinja2.Undefined, jinja2.StrictUndefined])
|
@pytest.mark.parametrize("undefined", [jinja2.Undefined, jinja2.StrictUndefined])
|
||||||
@pytest.mark.parametrize("autoescape", [True, False])
|
@pytest.mark.parametrize("autoescape", [True, False])
|
||||||
def test_default_attr(catalog, folder, autoescape, undefined):
|
def test_default_attr(catalog, folder, autoescape, undefined):
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import jinja2
|
import jinja2
|
||||||
|
@ -57,14 +61,14 @@ def test_render_assets(catalog, folder, autoescape, undefined):
|
||||||
assert (
|
assert (
|
||||||
"""
|
"""
|
||||||
<html>
|
<html>
|
||||||
<link rel="stylesheet" href="https://somewhere.com/style.css">
|
|
||||||
<link rel="stylesheet" href="/static/components/card.css">
|
<link rel="stylesheet" href="/static/components/card.css">
|
||||||
<link rel="stylesheet" href="/static/components/greeting.css">
|
<link rel="stylesheet" href="/static/components/greeting.css">
|
||||||
<link rel="stylesheet" href="http://example.com/super.css">
|
<link rel="stylesheet" href="http://example.com/super.css">
|
||||||
<script type="module" src="https://somewhere.com/blabla.js"></script>
|
<link rel="stylesheet" href="https://somewhere.com/style.css">
|
||||||
<script type="module" src="/static/components/shared.js"></script>
|
|
||||||
<script type="module" src="/static/components/card.js"></script>
|
<script type="module" src="/static/components/card.js"></script>
|
||||||
<script type="module" src="/static/components/greeting.js"></script>
|
<script type="module" src="/static/components/greeting.js"></script>
|
||||||
|
<script type="module" src="/static/components/shared.js"></script>
|
||||||
|
<script type="module" src="https://somewhere.com/blabla.js"></script>
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<div class="greeting [&_a]:flex">Hello</div>
|
<div class="greeting [&_a]:flex">Hello</div>
|
||||||
<button type="button">Close</button>
|
<button type="button">Close</button>
|
||||||
|
@ -195,8 +199,8 @@ def test_auto_load_assets_with_same_name(catalog, folder, autoescape, undefined)
|
||||||
<link rel="stylesheet" href="/static/components/Page.css">
|
<link rel="stylesheet" href="/static/components/Page.css">
|
||||||
<link rel="stylesheet" href="/static/components/common/Form.css">
|
<link rel="stylesheet" href="/static/components/common/Form.css">
|
||||||
<script type="module" src="/static/components/Page.js"></script>
|
<script type="module" src="/static/components/Page.js"></script>
|
||||||
<script type="module" src="/static/components/shared.js"></script>
|
|
||||||
<script type="module" src="/static/components/common/Form.js"></script>
|
<script type="module" src="/static/components/common/Form.js"></script>
|
||||||
|
<script type="module" src="/static/components/shared.js"></script>
|
||||||
<form></form>
|
<form></form>
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
JinjaX
|
||||||
|
Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
|
||||||
|
"""
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from markupsafe import Markup
|
from markupsafe import Markup
|
||||||
|
|
10
uv.lock
generated
10
uv.lock
generated
|
@ -215,7 +215,7 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinjax"
|
name = "jinjax"
|
||||||
version = "0.55"
|
version = "0.56"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "jinja2" },
|
{ name = "jinja2" },
|
||||||
|
@ -254,7 +254,7 @@ provides-extras = ["whitenoise"]
|
||||||
dev = [
|
dev = [
|
||||||
{ name = "ipdb", specifier = ">=0.13" },
|
{ name = "ipdb", specifier = ">=0.13" },
|
||||||
{ name = "pre-commit" },
|
{ name = "pre-commit" },
|
||||||
{ name = "pyright", specifier = ">=1.1" },
|
{ name = "pyright", specifier = ">=1.1.400" },
|
||||||
{ name = "ruff", specifier = ">=0.2.0" },
|
{ name = "ruff", specifier = ">=0.2.0" },
|
||||||
{ name = "tox-uv" },
|
{ name = "tox-uv" },
|
||||||
]
|
]
|
||||||
|
@ -451,15 +451,15 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyright"
|
name = "pyright"
|
||||||
version = "1.1.396"
|
version = "1.1.400"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "nodeenv" },
|
{ name = "nodeenv" },
|
||||||
{ name = "typing-extensions" },
|
{ name = "typing-extensions" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/bd/73/f20cb1dea1bdc1774e7f860fb69dc0718c7d8dea854a345faec845eb086a/pyright-1.1.396.tar.gz", hash = "sha256:142901f5908f5a0895be3d3befcc18bedcdb8cc1798deecaec86ef7233a29b03", size = 3814400 }
|
sdist = { url = "https://files.pythonhosted.org/packages/6c/cb/c306618a02d0ee8aed5fb8d0fe0ecfed0dbf075f71468f03a30b5f4e1fe0/pyright-1.1.400.tar.gz", hash = "sha256:b8a3ba40481aa47ba08ffb3228e821d22f7d391f83609211335858bf05686bdb", size = 3846546 }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/80/be/ecb7cfb42d242b7ee764b52e6ff4782beeec00e3b943a3ec832b281f9da6/pyright-1.1.396-py3-none-any.whl", hash = "sha256:c635e473095b9138c471abccca22b9fedbe63858e0b40d4fc4b67da041891844", size = 5689355 },
|
{ url = "https://files.pythonhosted.org/packages/c8/a5/5d285e4932cf149c90e3c425610c5efaea005475d5f96f1bfdb452956c62/pyright-1.1.400-py3-none-any.whl", hash = "sha256:c80d04f98b5a4358ad3a35e241dbf2a408eee33a40779df365644f8054d2517e", size = 5563460 },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue