feat: add offline SVG export for rack elevations
Adds a "SVG offline" download button on the rack detail page. It reuses NetBox's own rack-elevation REST endpoint to render the SVG, then strips embedded <a>/xlink:href links (which point at internal, relative NetBox URLs and are useless once the file is saved) so the result renders identically when opened standalone in any SVG viewer. Gated by the new offline_svg_export_enabled plugin setting (on by default). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from netbox_utilities.svg_export import strip_svg_hyperlinks
|
||||
|
||||
|
||||
class StripSvgHyperlinksTest(SimpleTestCase):
|
||||
def test_unwraps_anchor_elements_keeping_children(self):
|
||||
svg = (
|
||||
'<svg xmlns="http://www.w3.org/2000/svg">'
|
||||
'<a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/dcim/devices/1/">'
|
||||
'<rect width="10" height="10"/>'
|
||||
"</a>"
|
||||
"</svg>"
|
||||
)
|
||||
|
||||
result = strip_svg_hyperlinks(svg)
|
||||
|
||||
self.assertNotIn("<a ", result)
|
||||
self.assertNotIn("href", result)
|
||||
self.assertIn("<rect", result)
|
||||
|
||||
def test_removes_href_on_non_anchor_elements(self):
|
||||
svg = (
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" '
|
||||
'xmlns:xlink="http://www.w3.org/1999/xlink">'
|
||||
'<image xlink:href="/static/logo.png" href="/static/logo.png"/>'
|
||||
"</svg>"
|
||||
)
|
||||
|
||||
result = strip_svg_hyperlinks(svg)
|
||||
|
||||
self.assertNotIn("href", result)
|
||||
self.assertIn("<image", result)
|
||||
|
||||
def test_preserves_sibling_order_around_unwrapped_anchor(self):
|
||||
svg = (
|
||||
'<svg xmlns="http://www.w3.org/2000/svg">'
|
||||
'<rect id="before"/>'
|
||||
'<a href="/dcim/devices/2/"><rect id="linked"/></a>'
|
||||
'<rect id="after"/>'
|
||||
"</svg>"
|
||||
)
|
||||
|
||||
result = strip_svg_hyperlinks(svg)
|
||||
|
||||
self.assertLess(result.index('id="before"'), result.index('id="linked"'))
|
||||
self.assertLess(result.index('id="linked"'), result.index('id="after"'))
|
||||
|
||||
def test_leaves_svg_without_links_unchanged_in_content(self):
|
||||
svg = '<svg xmlns="http://www.w3.org/2000/svg"><rect width="5" height="5"/></svg>'
|
||||
|
||||
result = strip_svg_hyperlinks(svg)
|
||||
|
||||
self.assertIn("<rect", result)
|
||||
self.assertNotIn("href", result)
|
||||
Reference in New Issue
Block a user