Skip to content

Commit

Permalink
Merge pull request #130 from bckohan/v2.1.0
Browse files Browse the repository at this point in the history
V2.1.0
  • Loading branch information
bckohan committed Nov 20, 2023
2 parents 224f0a4 + f30dbfa commit 3964348
Show file tree
Hide file tree
Showing 35 changed files with 2,486 additions and 385 deletions.
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ Single-sourcing these structures by transpiling client side code from the server
- Plain data define-like structures in Python classes and modules
(`defines_to_js`)

Transpilation is extremely flexible and may be customized by using override blocks or extending the provided
transpilers.

`django-render-static` also formalizes the concept of a package-time or deployment-time
static file rendering step. It piggybacks off the existing templating engines and configurations
and should therefore be familiar to Django developers. It supports both standard Django templating
Expand Down
2 changes: 1 addition & 1 deletion doc/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ sphinxcontrib-jsmath==1.0.1; python_version >= "3.5"
sphinxcontrib-qthelp==1.0.3; python_version >= "3.5"
sphinxcontrib-serializinghtml==1.1.5; python_version >= "3.5"
sphinx-js==3.2.2; python_version >= "3.5"
django-render-static==2.0.3
django-render-static==2.1.0
11 changes: 11 additions & 0 deletions doc/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@
Change Log
==========

v2.1.0
======
* Implemented `Support templating of destination paths. <https://github.com/bckohan/django-render-static/issues/129>`_
* Implemented `Support configurable case insensitive property mapping on enum transpilation. <https://github.com/bckohan/django-render-static/issues/128>`_
* Implemented `Add a pass through getter for enums_to_js transpilation. <https://github.com/bckohan/django-render-static/issues/126>`_
* Implemented `enum transpilation should iterate through value properties instead of hardcoding a switch statement. <https://github.com/bckohan/django-render-static/issues/125>`
* Implemented `Add type check and return to getter on transpiled enum classes.. <https://github.com/bckohan/django-render-static/issues/122>`_
* Implemented `Provide switch to turn off toString() transpilation on enums_to_js <https://github.com/bckohan/django-render-static/issues/121>`_
* Implemented `Allow include_properties to be a list of properties on enums_to_js <https://github.com/bckohan/django-render-static/issues/119>`_
* Implemented `Extension points for transpiled code. <https://github.com/bckohan/django-render-static/issues/104>`_

v2.0.3
======
* Fixed `Invalid URL generation for urls with default arguments. <https://github.com/bckohan/django-render-static/issues/124>`_
Expand Down
4 changes: 4 additions & 0 deletions doc/source/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ single template, if the ``dest`` parameter is not an existing directory, it will
the full path including the file name where the template will be rendered. When rendering in batch
mode, ``dest`` will be treated as a directory and created if it does not exist.

The ``dest`` parameter may include template variables that will be replaced with the value of the
variable in the context. For example, if ``dest`` is ``'js/{{ app_name }}.js'`` and the context
contains ``{'app_name': 'my_app'}`` then the template will be rendered to ``js/my_app.js``.

``context``
~~~~~~~~~~~

Expand Down
7 changes: 7 additions & 0 deletions doc/source/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ transpilers
.. autofunction:: to_js_datetime
.. autoclass:: CodeWriter
.. autoclass:: Transpiler
.. autoproperty:: Transpiler.context


.. _transpilers_defines_to_js:
Expand All @@ -131,6 +132,7 @@ transpilers.defines_to_js
.. automodule:: render_static.transpilers.defines_to_js

.. autoclass:: DefaultDefineTranspiler
.. autoproperty:: DefaultDefineTranspiler.context


.. _transpilers_urls_to_js:
Expand All @@ -141,8 +143,11 @@ transpilers.urls_to_js
.. automodule:: render_static.transpilers.urls_to_js

.. autoclass:: URLTreeVisitor
.. autoproperty:: URLTreeVisitor.context
.. autoclass:: SimpleURLWriter
.. autoproperty:: SimpleURLWriter.context
.. autoclass:: ClassURLWriter
.. autoproperty:: ClassURLWriter.context
.. autoclass:: Substitute
.. autofunction:: normalize_ns
.. autofunction:: build_tree
Expand All @@ -155,8 +160,10 @@ transpilers.enums_to_js

.. automodule:: render_static.transpilers.enums_to_js

.. autoclass:: UnrecognizedBehavior
.. autoclass:: EnumTranspiler
.. autoclass:: EnumClassWriter
.. autoproperty:: EnumClassWriter.context


.. _context:
Expand Down
198 changes: 187 additions & 11 deletions doc/source/templatetags.rst
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,25 @@ The generated source would look like:
parent classes and add them to the JavaScript.


Overrides
*********

The ``DefaultDefineTranspiler`` supports the :ref:`override` block. The context available to
override blocks is detailed here:
:py:attr:`render_static.transpilers.defines_to_js.DefaultDefineTranspiler.context`. More code
can be added to define variables or specific defines can be overridden by using their python
path:

.. code-block:: js+django

{% defines_to_js defines='myapp' %}

{% override 'myapp.defines.TestDefines.DEFINE1' %}
"OVERRIDE"
{% endoverride %}

{% enddefines_to_js %}

.. _urls_to_js:

``urls_to_js``
Expand Down Expand Up @@ -265,15 +284,36 @@ Placeholders are the price paid for that reliability. Common default placeholder
after all registered placeholders fail, and all of Django's native path converters are
supported. This should allow most urls to work out of the box.

Overrides
*********

Both the ``ClassURLWriter`` and ``SimpleURLWriter`` transpilers support the :ref:`override`
block. The contexts available to override blocks for each transpiler are detailed here:

- :py:attr:`render_static.transpilers.urls_to_js.SimpleURLWriter.context`
- :py:attr:`render_static.transpilers.urls_to_js.ClassURLWriter.context`

Any function on ``ClassURLWriter`` including the constructor can be overridden and both
transpilers allow adding to the class or object and overriding the reversal code for
specific url names. For instance:

.. code-block:: js+django

{% urls_to_js transpiler='render_static.SimpleURLWriter' %}

{% override 'namespace:path_name' %}
return "/an/overridden/path";
{% endoverride %}

{% endurls_to_js %}

`ClassURLWriter` (default)
**************************

A transpiler class that produces ES6 JavaScript class is now included. As of version 2 This
class is used by default. It is the preferred transpiler for larger, more complex URL trees
because it minifies better than the ``SimpleURLWriter`` and it handles default kwargs
appropriately. **The** ``ClassURLWriter`` **is guaranteed to produce output identical to Django's
reverse function**. If it does not please report a bug. To use the class writer:
class is used by default. **The** ``ClassURLWriter`` **is guaranteed to produce output
identical to Django's reverse function**. If it does not please report a bug. To use the
class writer:

.. code-block:: htmldjango
Expand Down Expand Up @@ -532,13 +572,14 @@ like this:
}
static get(value) {
switch(value) {
case "R":
return Color.RED;
case "G":
return Color.GREEN;
case "B":
return Color.BLUE;
if (value instanceof this) {
return value;
}
for (const en of this) {
if (en.value === value) {
return en;
}
}
throw new TypeError(`No Color enumeration maps to value ${value}`);
}
Expand All @@ -556,3 +597,138 @@ We can now use our enumeration like so:
for (const color of Color) {
console.log(color);
}
Overrides
*********

You may add additional code to the class or :ref:`override` the following functions:

- constructor
- toString
- get
- ciCompare
- [Symbol.iterator]

See :py:attr:`render_static.transpilers.enums_to_js.EnumClassWriter.context` for the
context made available by the transpiler to override blocks.

.. _override:

``override``
~~~~~~~~~~~~

All of the transpilation tags accept child override blocks to override default transpilation
of functions or objects or be used to add additional code to an object block or class. For
example, if we wanted to override the default transpilation of the Color class above to allow
instantiation off a cmyk value we could do so by adapting the get function and adding a new
static utility function called cmykToRgb. We would do so like this:


.. code:: js+django

{% enums_to_js enums="examples.models.ExampleModel.Color" %}

{# to override a function we must pass its name as the argument #}
{% override 'get' %}
static get(value) {
if (Array.isArray(value) && value.length === 4) {
value = Color.cmykToRgb(...value);
}

if (Array.isArray(value) && value.length === 3) {
for (const en of this) {
let i = 0;
for (; i < 3; i++) {
if (en.rgb[i] !== value[i]) break;
}
if (i === 3) return en;
}
}
{{ default_impl }}
}
{% endoverride %}

{# additions do not require a name argument #}
{% override %}
static cmykToRgb(c, m, y, k) {

let r = 255 * (1 - c / 100) * (1 - k / 100);
let g = 255 * (1 - m / 100) * (1 - k / 100);
let b = 255 * (1 - y / 100) * (1 - k / 100);

return [Math.round(r), Math.round(g), Math.round(b)]
}
{% endoverride %}
{% endenums_to_js %}

When a function is overridden, the default implementation is available in the template context
as the ``default_impl`` variable. This allows you to add the default implementation from
code to your override. The context available to an override block varies depending on the
transpiler. See the individual tag sections for details.

The above example will generate code that looks like this:

.. code:: javascript
class Color {
static RED = new Color("R", "RED", "Red", [1, 0, 0], "ff0000");
static GREEN = new Color("G", "GREEN", "Green", [0, 1, 0], "00ff00");
static BLUE = new Color("B", "BLUE", "Blue", [0, 0, 1], "0000ff");
constructor (value, name, label, rgb, hex) {
this.value = value;
this.name = name;
this.label = label;
this.rgb = rgb;
this.hex = hex;
}
toString() {
return this.value;
}
static get(value) {
if (Array.isArray(value) && value.length === 4) {
value = Color.cmykToRgb(...value);
}
if (Array.isArray(value) && value.length === 3) {
for (const en of this) {
let i = 0;
for (; i < 3; i++) {
if (en.rgb[i] !== value[i]) break;
}
if (i === 3) return en;
}
}
if (value instanceof this) {
return value;
}
for (const en of this) {
if (en.value === value) {
return en;
}
}
throw new TypeError(`No Color enumeration maps to value ${value}`);
}
static [Symbol.iterator]() {
return [Color.RED, Color.GREEN, Color.BLUE][Symbol.iterator]();
}
static cmykToRgb(c, m, y, k) {
let r = (1 - c / 100) * (1 - k / 100);
let g = (1 - m / 100) * (1 - k / 100);
let b = (1 - y / 100) * (1 - k / 100);
return [Math.round(r), Math.round(g), Math.round(b)]
}
}
.. note::

The Jinja2 tags do not currently support overrides.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "django-render-static"
version = "2.0.3"
version = "2.1.0"
description = "Use Django's template engine to render static files at deployment or package time. Includes transpilers for extending Django's url reversal and enums to JavaScript."
authors = ["Brian Kohan <[email protected]>"]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion render_static/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from .transpilers.enums_to_js import EnumClassWriter
from .transpilers.urls_to_js import ClassURLWriter, SimpleURLWriter

VERSION = (2, 0, 3)
VERSION = (2, 1, 0)

__title__ = 'Django Render Static'
__version__ = '.'.join(str(i) for i in VERSION)
Expand Down
4 changes: 2 additions & 2 deletions render_static/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def default_env(**options):
env = Environment(**options)
env.globals.update(render_static.register.filters)
env.globals.update({
name: tag.__wrapped__
name: getattr(tag, '__wrapped__', tag)
for name, tag in render_static.register.tags.items()
})
return env
Expand Down Expand Up @@ -211,7 +211,6 @@ def select_templates(
loader specific and documented on the loader.
:return: The list of resolved template names
"""

template_names = set()
if callable(getattr(self.env.loader, 'select_templates', None)):
for templates in self.env.loader.select_templates(selector):
Expand All @@ -223,6 +222,7 @@ def select_templates(
else:
self.get_template(selector)
template_names.add(selector)

if first_loader and template_names:
return list(template_names)

Expand Down
Loading

0 comments on commit 3964348

Please sign in to comment.