added assets_formatter and remove_formatter
This commit is contained in:
1 parent
8697f3ecb5
commit
ddc9add551
6 files changed
+108
-7
No files matched your search
@@ -6,10 +6,10 @@ Each formatter module contains a `format` function that performs a specific modi
|
|||||||
The `formatters` list in this package contains all the formatter modules for easy access and usage.
|
The `formatters` list in this package contains all the formatter modules for easy access and usage.
|
||||||
"""
|
"""
|
||||||
from . import (for_formatter, if_formatter, var_formatter, block_formatter, static_formatter, attr_formatter,
|
from . import (for_formatter, if_formatter, var_formatter, block_formatter, static_formatter, attr_formatter,
|
||||||
for_wrap_formatter, unwrap_formatter, include_formatter, remove_default_formatter, command_formatter,
|
for_wrap_formatter, unwrap_formatter, remove_formatter, include_formatter, assets_formatter,
|
||||||
style_formatter, style_raw_formatter)
|
remove_default_formatter, command_formatter, style_formatter, style_raw_formatter)
|
||||||
|
|
||||||
|
|
||||||
formatters = [for_formatter, if_formatter, var_formatter, block_formatter, static_formatter, attr_formatter,
|
formatters = [for_formatter, if_formatter, var_formatter, block_formatter, static_formatter, attr_formatter,
|
||||||
for_wrap_formatter, unwrap_formatter, include_formatter, remove_default_formatter, command_formatter,
|
for_wrap_formatter, unwrap_formatter, remove_formatter, include_formatter, assets_formatter,
|
||||||
style_formatter, style_raw_formatter]
|
remove_default_formatter, command_formatter, style_formatter, style_raw_formatter]
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"""
|
||||||
|
This module contains a function `format` that modifies a BeautifulSoup object in place. The function searches for
|
||||||
|
the "html" element with the attribute "dj-assets". The value of "dj-assets" is expected to be a string with two parts
|
||||||
|
separated by a semicolon (;), the first part being the asset identifier and the second part being the asset prefix.
|
||||||
|
|
||||||
|
For each element in the BeautifulSoup object with a "href" or "src" attribute that starts with the asset identifier,
|
||||||
|
it adds the asset prefix to the attribute value and wraps it in a Django static command.
|
||||||
|
|
||||||
|
|
||||||
|
After processing all elements, it removes the "dj-assets" attribute from the "html" element.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
If the "html" element is <html dj-assets="assets;module">...</html>,
|
||||||
|
and there is an element <img src="assets/image.png">,
|
||||||
|
after processing, the "img" element becomes <img src="{% static 'module/assets/image.png' %}">.
|
||||||
|
"""
|
||||||
|
from bs4 import BeautifulSoup, Tag
|
||||||
|
|
||||||
|
|
||||||
|
def format(soup: BeautifulSoup) -> None:
|
||||||
|
if html := soup.find("html"):
|
||||||
|
if isinstance(html, Tag):
|
||||||
|
if html.has_attr("dj-assets"):
|
||||||
|
if isinstance(html["dj-assets"], str):
|
||||||
|
asset_identifier, asset_prefix = html["dj-assets"].split(";")
|
||||||
|
for element in soup.find_all(attrs={"href": True}):
|
||||||
|
if element["href"].startswith(asset_identifier):
|
||||||
|
element["href"] = f"{{% static '{asset_prefix}/{element['href']}' %}}"
|
||||||
|
for element in soup.find_all(attrs={"src": True}):
|
||||||
|
if element["src"].startswith(asset_identifier):
|
||||||
|
element["src"] = f"{{% static '{asset_prefix}/{element['src']}' %}}"
|
||||||
|
del html["dj-assets"]
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
"""
|
||||||
|
This module contains a function `format` that modifies a BeautifulSoup object in place. The function searches for
|
||||||
|
all elements with the attribute "dj-remove". For each found element, it calls the `decompose` method, which removes
|
||||||
|
the element from the parse tree. This effectively removes all elements marked with "dj-remove" from the HTML document.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
If an element is <div dj-remove></div>,
|
||||||
|
after processing, it will be removed from the BeautifulSoup object.
|
||||||
|
"""
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
|
||||||
|
def format(soup: BeautifulSoup) -> None:
|
||||||
|
for element in soup.find_all(attrs={"dj-remove": True}):
|
||||||
|
element.decompose()
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from html_to_django.formatters import assets_formatter
|
||||||
|
|
||||||
|
|
||||||
|
class AssetsTests(TestCase):
|
||||||
|
def test_basic(self) -> None:
|
||||||
|
soup = BeautifulSoup('<html dj-assets="assets;module"><img src="assets/image.png"></html>', 'html.parser')
|
||||||
|
assets_formatter.format(soup)
|
||||||
|
expected_result = '<html><img src="{% static \'module/assets/image.png\' %}"/></html>'
|
||||||
|
self.assertEqual(expected_result, str(soup))
|
||||||
|
|
||||||
|
def test_empty(self) -> None:
|
||||||
|
soup = BeautifulSoup('<html dj-assets="assets;module"></html>', 'html.parser')
|
||||||
|
assets_formatter.format(soup)
|
||||||
|
expected_result = '<html></html>'
|
||||||
|
self.assertEqual(expected_result, str(soup))
|
||||||
|
|
||||||
|
def test_no_assets(self) -> None:
|
||||||
|
soup = BeautifulSoup('<html dj-assets="assets;module"><p>Test</p></html>', 'html.parser')
|
||||||
|
assets_formatter.format(soup)
|
||||||
|
expected_result = '<html><p>Test</p></html>'
|
||||||
|
self.assertEqual(expected_result, str(soup))
|
||||||
|
|
||||||
|
def test_with_multiple_assets(self) -> None:
|
||||||
|
soup = BeautifulSoup('<html dj-assets="assets;module"><img src="assets/image1.png"><img '
|
||||||
|
'src="assets/image2.png"></html>', 'html.parser')
|
||||||
|
assets_formatter.format(soup)
|
||||||
|
expected_result = ('<html><img src="{% static \'module/assets/image1.png\' %}"/><img src="{% static '
|
||||||
|
'\'module/assets/image2.png\' %}"/></html>')
|
||||||
|
self.assertEqual(expected_result, str(soup))
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from html_to_django.formatters import remove_formatter
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveTests(TestCase):
|
||||||
|
def test_basic(self) -> None:
|
||||||
|
soup = BeautifulSoup('<div dj-remove><div>Test</div></div>', "html.parser")
|
||||||
|
remove_formatter.format(soup)
|
||||||
|
expected_result = ""
|
||||||
|
self.assertEqual(expected_result, str(soup))
|
||||||
|
|
||||||
|
def test_empty(self) -> None:
|
||||||
|
soup = BeautifulSoup('<div dj-remove></div>', "html.parser")
|
||||||
|
remove_formatter.format(soup)
|
||||||
|
expected_result = ""
|
||||||
|
self.assertEqual(expected_result, str(soup))
|
||||||
|
|
||||||
|
def test_with_remove_inside(self) -> None:
|
||||||
|
soup = BeautifulSoup('<div dj-remove><div dj-remove>Inner Test</div></div>', "html.parser")
|
||||||
|
remove_formatter.format(soup)
|
||||||
|
expected_result = ""
|
||||||
|
self.assertEqual(expected_result, str(soup))
|
||||||
@@ -5,19 +5,19 @@ from html_to_django.formatters import unwrap_formatter
|
|||||||
|
|
||||||
class UnwrapTests(TestCase):
|
class UnwrapTests(TestCase):
|
||||||
def test_basic(self) -> None:
|
def test_basic(self) -> None:
|
||||||
soup = BeautifulSoup('<div dj-unwrap="true"><div>Test</div></div>', "html.parser")
|
soup = BeautifulSoup('<div dj-unwrap><div>Test</div></div>', "html.parser")
|
||||||
unwrap_formatter.format(soup)
|
unwrap_formatter.format(soup)
|
||||||
expected_result = "<div>Test</div>"
|
expected_result = "<div>Test</div>"
|
||||||
self.assertEqual(expected_result, str(soup))
|
self.assertEqual(expected_result, str(soup))
|
||||||
|
|
||||||
def test_empty(self) -> None:
|
def test_empty(self) -> None:
|
||||||
soup = BeautifulSoup('<div dj-unwrap="true"></div>', "html.parser")
|
soup = BeautifulSoup('<div dj-unwrap></div>', "html.parser")
|
||||||
unwrap_formatter.format(soup)
|
unwrap_formatter.format(soup)
|
||||||
expected_result = ""
|
expected_result = ""
|
||||||
self.assertEqual(expected_result, str(soup))
|
self.assertEqual(expected_result, str(soup))
|
||||||
|
|
||||||
def test_with_unwrap_inside(self) -> None:
|
def test_with_unwrap_inside(self) -> None:
|
||||||
soup = BeautifulSoup('<div dj-unwrap="true"><div dj-unwrap="true">Inner Test</div></div>', "html.parser")
|
soup = BeautifulSoup('<div dj-unwrap><div dj-unwrap>Inner Test</div></div>', "html.parser")
|
||||||
unwrap_formatter.format(soup)
|
unwrap_formatter.format(soup)
|
||||||
expected_result = "Inner Test"
|
expected_result = "Inner Test"
|
||||||
self.assertEqual(expected_result, str(soup))
|
self.assertEqual(expected_result, str(soup))
|
||||||
Reference in new issue
Block a user