This commit is contained in:
dgtlmoon
2025-09-29 13:59:26 +02:00
parent f36a9799c1
commit d87e17023a
11 changed files with 74 additions and 33 deletions
@@ -3,8 +3,9 @@
{% block content %}
<script>
const screenshot_url = "{{url_for('static_content', group='screenshot', filename=uuid)}}";
const triggered_line_numbers = {{ triggered_line_numbers|tojson }};
const ignored_line_numbers = {{ ignored_line_numbers|tojson }};
const triggered_line_numbers = {{ highlight_triggered_line_numbers|tojson }};
const ignored_line_numbers = {{ highlight_ignored_line_numbers|tojson }};
const blocked_line_numbers = {{ highlight_blocked_line_numbers|tojson }};
{% if last_error_screenshot %}
const error_screenshot_url = "{{url_for('static_content', group='screenshot', filename=uuid, error_screenshot=1) }}";
{% endif %}
+10 -4
View File
@@ -70,6 +70,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe
triggered_line_numbers = []
ignored_line_numbers = []
blocked_line_numbers = []
if datastore.data['watching'][uuid].history_n == 0 and (watch.get_error_text() or watch.get_error_snapshot()):
flash("Preview unavailable - No fetch/check completed or triggers not reached", "error")
@@ -86,11 +87,15 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe
content = watch.get_history_snapshot(timestamp)
triggered_line_numbers = html_tools.strip_ignore_text(content=content,
wordlist=watch['trigger_text'],
wordlist=watch.get('trigger_text'),
mode='line numbers'
)
ignored_line_numbers = html_tools.strip_ignore_text(content=content,
wordlist=watch['ignore_text'],
wordlist=watch.get('ignore_text'),
mode='line numbers'
)
blocked_line_numbers = html_tools.strip_ignore_text(content=content,
wordlist=watch.get("text_should_not_be_present"),
mode='line numbers'
)
except Exception as e:
@@ -102,14 +107,15 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe
current_version=timestamp,
extra_stylesheets=extra_stylesheets,
extra_title=f" - Diff - {watch.label} @ {timestamp}",
highlight_ignored_line_numbers=ignored_line_numbers,
highlight_triggered_line_numbers=triggered_line_numbers,
highlight_blocked_line_numbers=blocked_line_numbers,
history_n=watch.history_n,
is_html_webdriver=is_html_webdriver,
ignored_line_numbers=ignored_line_numbers,
last_error=watch['last_error'],
last_error_screenshot=watch.get_error_snapshot(),
last_error_text=watch.get_error_text(),
screenshot=watch.get_screenshot(),
triggered_line_numbers=triggered_line_numbers,
uuid=uuid,
versions=versions,
watch=watch,
+3
View File
@@ -377,6 +377,9 @@ def strip_ignore_text(content, wordlist, mode="content"):
ignore_regex_multiline = []
ignored_lines = []
if not content:
return ''
for k in wordlist:
# Is it a regex?
res = re.search(PERL_STYLE_REGEX, k, re.IGNORECASE)
@@ -45,6 +45,7 @@ def prepare_filter_prevew(datastore, watch_uuid, form_data):
text_before_filter = ''
trigger_line_numbers = []
ignore_line_numbers = []
blocked_line_numbers = []
tmp_watch = deepcopy(datastore.data['watching'].get(watch_uuid))
@@ -101,14 +102,23 @@ def prepare_filter_prevew(datastore, watch_uuid, form_data):
except Exception as e:
text_before_filter = f"Error: {str(e)}"
try:
blocked_line_numbers = html_tools.strip_ignore_text(content=text_after_filter,
wordlist=tmp_watch.get('text_should_not_be_present', []) + datastore.data['settings']['application'].get('text_should_not_be_present', []),
mode='line numbers'
)
except Exception as e:
text_before_filter = f"Error: {str(e)}"
logger.trace(f"Parsed in {time.time() - now:.3f}s")
return ({
'after_filter': text_after_filter,
'before_filter': text_before_filter.decode('utf-8') if isinstance(text_before_filter, bytes) else text_before_filter,
'duration': time.time() - now,
'trigger_line_numbers': trigger_line_numbers,
'ignore_line_numbers': ignore_line_numbers,
'after_filter': text_after_filter,
'before_filter': text_before_filter.decode('utf-8') if isinstance(text_before_filter, bytes) else text_before_filter,
'blocked_line_numbers': blocked_line_numbers,
'duration': time.time() - now,
'ignore_line_numbers': ignore_line_numbers,
'trigger_line_numbers': trigger_line_numbers,
})
+9 -11
View File
@@ -62,15 +62,12 @@
const textContent = $pre.text();
const lines = textContent.split(/\r?\n/); // Handles both \n and \r\n line endings
// Build a map of line numbers to styles
const lineStyles = {};
// Build a map of line numbers to their configuration index
const lineConfigIndex = {};
configurations.forEach(config => {
const {color, lines: lineNumbers} = config;
lineNumbers.forEach(lineNumber => {
lineStyles[lineNumber] = color;
});
});
configurations.forEach((config, index) =>
config.lines.forEach(lineNumber => lineConfigIndex[lineNumber] = index)
);
// Function to escape HTML characters
function escapeHtml(text) {
@@ -83,11 +80,12 @@
const processedLines = lines.map((line, index) => {
const lineNumber = index + 1; // Line numbers start at 1
const escapedLine = escapeHtml(line);
const color = lineStyles[lineNumber];
const configIndex = lineConfigIndex[lineNumber];
if (color) {
if (configIndex !== undefined) {
const config = configurations[configIndex];
// Wrap the line in a span with inline style
return `<span style="background-color: ${color}">${escapedLine}</span>`;
return `<span title="${config.title}" style="background-color: ${config.color}">${escapedLine}</span>`;
} else {
return escapedLine;
}
+10 -2
View File
@@ -53,15 +53,23 @@ $(document).ready(function () {
if ($('#preview-version').length) {
setupDateWidget();
}
alert(blocked_line_numbers);
$('#diff-col > pre').highlightLines([
{
'color': '#ee0000',
'color': 'var(--highlight-trigger-text-bg-color)',
'lines': triggered_line_numbers,
'title': "Triggers a change if this text appears, AND something changed in the document."
},
{
'color': '#aaa',
'color': 'var(--highlight-ignored-text-bg-color)',
'lines': ignored_line_numbers,
'title': "Ignored for calculating changes, but still shown."
},
{
'color': 'var(--highlight-blocked-text-bg-color)',
'lines': blocked_line_numbers,
'title': "Ignored for calculating changes, but still shown."
}
]);
});
+12 -4
View File
@@ -20,18 +20,26 @@ function request_textpreview_update() {
data: data,
namespace: 'watchEdit'
}).done(function (data) {
alert(data['blocked_line_numbers'])
console.debug(data['duration'])
$('#filters-and-triggers #text-preview-before-inner').text(data['before_filter']);
$('#filters-and-triggers #text-preview-inner')
.text(data['after_filter'])
.highlightLines([
{
'color': '#ee0000',
'lines': data['trigger_line_numbers']
'color': 'var(--highlight-trigger-text-bg-color)',
'lines': data['trigger_line_numbers'],
'title': "Triggers a change if this text appears, AND something changed in the document."
},
{
'color': '#757575',
'lines': data['ignore_line_numbers']
'color': 'var(--highlight-ignored-text-bg-color)',
'lines': data['ignore_line_numbers'],
'title': "Ignored for calculating changes, but still shown."
},
{
'color': 'var(--highlight-blocked-text-bg-color)',
'lines': data['blocked_line_numbers'],
'title': "Ignored for calculating changes, but still shown."
}
])
}).fail(function (error) {
File diff suppressed because one or more lines are too long
@@ -102,6 +102,10 @@
--color-watch-table-error: var(--color-dark-red);
--color-watch-table-row-text: var(--color-grey-100);
--highlight-trigger-text-bg-color: #1b98f8;
--highlight-ignored-text-bg-color: var(--color-grey-700);
--highlight-blocked-text-bg-color: rgb(202, 60, 60);
}
html[data-darkmode="true"] {
File diff suppressed because one or more lines are too long
+6 -3
View File
@@ -12,6 +12,7 @@ def set_original_ignore_response():
<p>Which is across multiple lines</p>
<br>
So let's see what happens. <br>
and more<br>
</body>
</html>
@@ -28,6 +29,7 @@ def set_modified_original_ignore_response():
<p>Which is across multiple lines</p>
<br>
So let's see what happens. <br>
and more<br>
</body>
</html>
@@ -46,6 +48,7 @@ def set_modified_with_trigger_text_response():
Add to cart
<br>
So let's see what happens. <br>
and more<br>
</body>
</html>
@@ -58,11 +61,9 @@ def set_modified_with_trigger_text_response():
def test_trigger_functionality(client, live_server, measure_memory_usage):
# live_server_setup(live_server) # Setup on conftest per function
trigger_text = "Add to cart"
set_original_ignore_response()
# Add our URL to the import page
test_url = url_for('test_endpoint', _external=True)
res = client.post(
@@ -80,6 +81,7 @@ def test_trigger_functionality(client, live_server, measure_memory_usage):
res = client.post(
url_for("ui.ui_edit.edit_page", uuid="first"),
data={"trigger_text": trigger_text,
"ignore_text": "and more",
"url": test_url,
"fetch_backend": "html_requests",
"time_between_check_use_default": "y"},
@@ -127,7 +129,7 @@ def test_trigger_functionality(client, live_server, measure_memory_usage):
wait_for_all_checks(client)
res = client.get(url_for("watchlist.index"))
assert b'has-unread-changes' in res.data
# https://github.com/dgtlmoon/changedetection.io/issues/616
# Apparently the actual snapshot that contains the trigger never shows
res = client.get(url_for("ui.ui_views.diff_history_page", uuid="first"))
@@ -135,6 +137,7 @@ def test_trigger_functionality(client, live_server, measure_memory_usage):
# Check the preview/highlighter, we should be able to see what we triggered on, but it should be highlighted
res = client.get(url_for("ui.ui_views.preview_page", uuid="first"))
assert b'ignored_line_numbers = [8]' in res.data
# We should be able to see what we triggered on
# The JS highlighter should tell us which lines (also used in the live-preview)