diff --git a/netbox/netbox/tables/tables.py b/netbox/netbox/tables/tables.py
index f695015e9..8cea55ff9 100644
--- a/netbox/netbox/tables/tables.py
+++ b/netbox/netbox/tables/tables.py
@@ -17,8 +17,9 @@ from extras.models import CustomField, CustomLink
from netbox.registry import registry
from netbox.tables import columns
from utilities.paginator import EnhancedPaginator, get_paginate_count
+from utilities.html import highlight
from utilities.string import title
-from utilities.utils import get_viewname, highlight_string
+from utilities.utils import get_viewname
from .template_code import *
__all__ = (
@@ -274,6 +275,6 @@ class SearchTable(tables.Table):
if not self.highlight:
return value
- value = highlight_string(value, self.highlight, trim_pre=self.trim_length, trim_post=self.trim_length)
+ value = highlight(value, self.highlight, trim_pre=self.trim_length, trim_post=self.trim_length)
return mark_safe(value)
diff --git a/netbox/utilities/html.py b/netbox/utilities/html.py
new file mode 100644
index 000000000..a95b5b1a7
--- /dev/null
+++ b/netbox/utilities/html.py
@@ -0,0 +1,38 @@
+import re
+
+from django.utils.html import escape
+
+__all__ = (
+ 'highlight',
+)
+
+
+def highlight(value, highlight, trim_pre=None, trim_post=None, trim_placeholder='...'):
+ """
+ Highlight a string within a string and optionally trim the pre/post portions of the original string.
+
+ Args:
+ value: The body of text being searched against
+ highlight: The string of compiled regex pattern to highlight in `value`
+ trim_pre: Maximum length of pre-highlight text to include
+ trim_post: Maximum length of post-highlight text to include
+ trim_placeholder: String value to swap in for trimmed pre/post text
+ """
+ # Split value on highlight string
+ try:
+ if type(highlight) is re.Pattern:
+ pre, match, post = highlight.split(value, maxsplit=1)
+ else:
+ highlight = re.escape(highlight)
+ pre, match, post = re.split(fr'({highlight})', value, maxsplit=1, flags=re.IGNORECASE)
+ except ValueError as e:
+ # Match not found
+ return escape(value)
+
+ # Trim pre/post sections to length
+ if trim_pre and len(pre) > trim_pre:
+ pre = trim_placeholder + pre[-trim_pre:]
+ if trim_post and len(post) > trim_post:
+ post = post[:trim_post] + trim_placeholder
+
+ return f'{escape(pre)}{escape(match)}{escape(post)}'
diff --git a/netbox/utilities/utils.py b/netbox/utilities/utils.py
index 3b9b12049..3c427dd5a 100644
--- a/netbox/utilities/utils.py
+++ b/netbox/utilities/utils.py
@@ -1,7 +1,6 @@
import datetime
import decimal
import json
-import re
from decimal import Decimal
from itertools import count, groupby
from urllib.parse import urlencode
@@ -14,7 +13,6 @@ from django.db.models.functions import Coalesce
from django.http import QueryDict
from django.utils import timezone
from django.utils.datastructures import MultiValueDict
-from django.utils.html import escape
from django.utils.timezone import localtime
from django.utils.translation import gettext as _
from jinja2.sandbox import SandboxedEnvironment
@@ -515,37 +513,6 @@ def clean_html(html, schemes):
)
-def highlight_string(value, highlight, trim_pre=None, trim_post=None, trim_placeholder='...'):
- """
- Highlight a string within a string and optionally trim the pre/post portions of the original string.
-
- Args:
- value: The body of text being searched against
- highlight: The string of compiled regex pattern to highlight in `value`
- trim_pre: Maximum length of pre-highlight text to include
- trim_post: Maximum length of post-highlight text to include
- trim_placeholder: String value to swap in for trimmed pre/post text
- """
- # Split value on highlight string
- try:
- if type(highlight) is re.Pattern:
- pre, match, post = highlight.split(value, maxsplit=1)
- else:
- highlight = re.escape(highlight)
- pre, match, post = re.split(fr'({highlight})', value, maxsplit=1, flags=re.IGNORECASE)
- except ValueError as e:
- # Match not found
- return escape(value)
-
- # Trim pre/post sections to length
- if trim_pre and len(pre) > trim_pre:
- pre = trim_placeholder + pre[-trim_pre:]
- if trim_post and len(post) > trim_post:
- post = post[:trim_post] + trim_placeholder
-
- return f'{escape(pre)}{escape(match)}{escape(post)}'
-
-
def local_now():
"""
Return the current date & time in the system timezone.