mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2026-09-26 07:16:13 +00:00
WIP
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Test the built package works basically. (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been cancelled
ChangeDetection.io App Test / lint-code (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-10 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-11 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-12 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-13 (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Test the built package works basically. (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been cancelled
ChangeDetection.io App Test / lint-code (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-10 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-11 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-12 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-13 (push) Has been cancelled
This commit is contained in:
@@ -1,16 +1,12 @@
|
||||
<ul id="highlightSnippetActions">
|
||||
<li>
|
||||
<button class="pure-button pure-button-primary" onclick="diffToJpeg()" title="Share diff as image">Share as Image</button><br>
|
||||
<span>Creates an image that you can share.</span>
|
||||
<button class="pure-button pure-button-primary" onclick="diffToJpeg()" title="Share diff as image">Share as Image</button>
|
||||
</li>
|
||||
<li>
|
||||
<a class="pure-button pure-button-primary" data-mode="exact" href="javascript:void(0);">Ignore exact text</a><br>
|
||||
<span>Ignore any change on any line which contains the selected text.</span>
|
||||
<a class="pure-button pure-button-primary" data-mode="exact" href="javascript:void(0);">Ignore any lines matching</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="pure-button pure-button-primary" data-mode="digit-regex" href="javascript:void(0);" >Ignore text including number changes</a><br>
|
||||
<!-- ??? and the number or number wildcard -->
|
||||
<span>Ignore any change on any line which contains the selected text.</span>
|
||||
<a class="pure-button pure-button-primary" data-mode="digit-regex" href="javascript:void(0);" >Ignore any lines matching excluding digits</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -11,16 +11,17 @@
|
||||
const watch_url= {{watch_a.link|tojson}};
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
|
||||
<script src="{{url_for('static_content', group='js', filename='plugins.js')}}"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/piexifjs@1.0.6/piexif.min.js"></script>
|
||||
<script src="{{url_for('static_content', group='js', filename='snippet-to-image.js')}}"></script>
|
||||
<script src="{{url_for('static_content', group='js', filename='diff-overview.js')}}" defer></script>
|
||||
|
||||
|
||||
<div id="settings">
|
||||
<form class="pure-form " action="{{ url_for("ui.ui_views.diff_history_page", uuid=uuid) }}" method="POST" id="diff-form">
|
||||
<fieldset class="diff-fieldset">
|
||||
{% if versions|length >= 1 %}
|
||||
<strong>Compare</strong>
|
||||
from {{from_version}} to {{to_version}}<br>
|
||||
<del class="change"><span>from</span></del>
|
||||
<select id="diff-version" name="from_version" class="needs-localtime">
|
||||
{% for version in versions|reverse %}
|
||||
@@ -94,25 +95,17 @@
|
||||
<img id="error-screenshot-img" style="max-width: 80%" alt="Current error-ing screenshot from most recent request" >
|
||||
</div>
|
||||
|
||||
<div class="tab-pane-inner" id="text">
|
||||
<div class="tab-pane-inner" id="text">
|
||||
{% if password_enabled_and_share_is_off %}
|
||||
<div class="tip">Pro-tip: You can enable <strong>"share access when password is enabled"</strong> from settings</div>
|
||||
{% endif %}
|
||||
<div class="tip">Pro-tip: You can enable <strong>"share access when password is enabled"</strong> from settings.
|
||||
</div>
|
||||
{% endif %}
|
||||
<div id="cell-diff-jump-visualiser"></div>
|
||||
<div class="snapshot-age">{{ watch_a.snapshot_text_ctime|format_timestamp_timeago }}</div>
|
||||
<pre id="difference" style="border-left: 2px solid #ddd;">{{ content| diff_unescape_difference_spans }}</pre>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="snapshot-age">{{watch_a.snapshot_text_ctime|format_timestamp_timeago}}</div>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td id="diff-col" class="highlightable-filter">
|
||||
<pre id="difference" style="border-left: 2px solid #ddd;">{{ content| diff_unescape_difference_spans }}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane-inner" id="screenshot">
|
||||
<div class="tab-pane-inner" id="screenshot">
|
||||
<div class="tip">
|
||||
For now, Differences are performed on text, not graphically, only the latest screenshot is available.
|
||||
</div>
|
||||
|
||||
@@ -283,10 +283,10 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe
|
||||
last_error=watch['last_error'],
|
||||
last_error_screenshot=watch.get_error_snapshot(),
|
||||
last_error_text=watch.get_error_text(),
|
||||
left_sticky=True,
|
||||
newest=to_version_file_contents,
|
||||
newest_version_timestamp=dates[-1],
|
||||
password_enabled_and_share_is_off=password_enabled_and_share_is_off,
|
||||
pure_menu_fixed=False,
|
||||
screenshot=screenshot_url,
|
||||
to_version=str(to_version),
|
||||
uuid=uuid,
|
||||
|
||||
@@ -53,17 +53,16 @@ $(document).ready(function () {
|
||||
}
|
||||
}
|
||||
}).done(function (data) {
|
||||
$("#highlightSnippet").html(data)
|
||||
// @todo some feedback
|
||||
$("#highlightSnippet").html(data);
|
||||
clean();
|
||||
}).fail(function (data) {
|
||||
console.log(data);
|
||||
alert('There was an error communicating with the server.');
|
||||
}).finally(function () {
|
||||
clean();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
function clean(event) {
|
||||
$("#highlightSnippet").remove();
|
||||
$('#bottom-horizontal-offscreen').hide();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,79 @@
|
||||
$(document).ready(function () {
|
||||
|
||||
var inputs;
|
||||
// Find all <span> elements inside pre#difference
|
||||
var inputs = $('#difference span').toArray();
|
||||
inputs.current = 0;
|
||||
|
||||
// Build visual minimap of difference locations
|
||||
var $visualizer = $('#cell-diff-jump-visualiser');
|
||||
var $difference = $('#difference');
|
||||
var visualizerResolutionCells = 100; // Fixed resolution to prevent high CPU usage with many changes
|
||||
var cellHeight;
|
||||
var cellData = {}; // Map cell index to change type
|
||||
|
||||
if ($difference.length && inputs.length) {
|
||||
var docHeight = $difference[0].scrollHeight;
|
||||
cellHeight = docHeight / visualizerResolutionCells;
|
||||
|
||||
// Map each span to a cell with its type based on color
|
||||
var differenceTop = $difference.offset().top;
|
||||
$(inputs).each(function() {
|
||||
var spanTop = $(this).offset().top - differenceTop;
|
||||
var cellIndex = Math.min(Math.floor(spanTop / cellHeight), visualizerResolutionCells - 1);
|
||||
var bgColor = $(this).css('background-color');
|
||||
var changeType;
|
||||
|
||||
// Determine type by background color
|
||||
if (bgColor === 'rgb(250, 218, 215)' || bgColor === '#fadad7') {
|
||||
changeType = 'deletion'; // Red background
|
||||
} else if (bgColor === 'rgb(234, 242, 194)' || bgColor === '#eaf2c2') {
|
||||
changeType = 'insertion'; // Green background
|
||||
} else {
|
||||
changeType = $(this).attr('role'); // Fallback to role attribute
|
||||
}
|
||||
|
||||
// Track the type of change in each cell (prioritize mixed changes)
|
||||
if (!cellData[cellIndex]) {
|
||||
cellData[cellIndex] = changeType;
|
||||
} else if (cellData[cellIndex] !== changeType) {
|
||||
cellData[cellIndex] = 'mixed'; // Both deletion and insertion in same cell
|
||||
}
|
||||
});
|
||||
|
||||
// Create cell strip
|
||||
for (var i = 0; i < visualizerResolutionCells; i++) {
|
||||
var $cell = $('<div>');
|
||||
var changeType = cellData[i];
|
||||
|
||||
if (changeType === 'deletion') {
|
||||
$cell.addClass('deletion');
|
||||
} else if (changeType === 'insertion') {
|
||||
$cell.addClass('insertion');
|
||||
} else if (changeType === 'note') {
|
||||
$cell.addClass('note');
|
||||
} else if (changeType === 'mixed') {
|
||||
$cell.addClass('mixed');
|
||||
}
|
||||
|
||||
// Add click handler to scroll to that position in the document
|
||||
$cell.data('cellIndex', i);
|
||||
$cell.on('click', function() {
|
||||
var cellIndex = $(this).data('cellIndex');
|
||||
var targetPositionInDifference = cellIndex * cellHeight;
|
||||
var viewportOffset = 150; // Keep change visible with 150px offset
|
||||
|
||||
window.scrollTo({
|
||||
top: $difference.offset().top + targetPositionInDifference - viewportOffset,
|
||||
behavior: "smooth"
|
||||
});
|
||||
});
|
||||
|
||||
$visualizer.append($cell);
|
||||
}
|
||||
}
|
||||
|
||||
$('#jump-next-diff').click(function () {
|
||||
if (!inputs || inputs.length === 0) return;
|
||||
|
||||
var element = inputs[inputs.current];
|
||||
var headerOffset = 80;
|
||||
@@ -20,6 +91,31 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
// Track current scroll position in visualizer
|
||||
function updateVisualizerPosition() {
|
||||
if (!$difference.length || visualizerResolutionCells === 0) return;
|
||||
|
||||
var scrollTop = $(window).scrollTop();
|
||||
var differenceTop = $difference.offset().top;
|
||||
var positionInDifference = scrollTop - differenceTop;
|
||||
|
||||
// Calculate which cell we're currently viewing
|
||||
var currentCell = Math.floor(positionInDifference / cellHeight);
|
||||
currentCell = Math.max(0, Math.min(currentCell, visualizerResolutionCells - 1));
|
||||
|
||||
// Remove previous active marker and add to current cell
|
||||
$visualizer.find('> div').removeClass('current-position');
|
||||
$visualizer.find('> div').eq(currentCell).addClass('current-position');
|
||||
}
|
||||
|
||||
// Debounce scroll event to reduce CPU usage
|
||||
$(window).on('scroll', updateVisualizerPosition.debounce(5));
|
||||
|
||||
// Initial position update
|
||||
if ($difference.length && cellHeight) {
|
||||
updateVisualizerPosition();
|
||||
}
|
||||
|
||||
function changed() {
|
||||
//$('#jump-next-diff').click();
|
||||
}
|
||||
|
||||
@@ -1,141 +1 @@
|
||||
|
||||
#diff-ui {
|
||||
background: var(--color-background);
|
||||
padding: 2em;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
border-radius: 5px
|
||||
}
|
||||
|
||||
#diff-ui #text {
|
||||
font-size: 11px
|
||||
}
|
||||
|
||||
#diff-ui table {
|
||||
table-layout: fixed;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
#diff-ui td {
|
||||
padding: 3px 4px;
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
vertical-align: top;
|
||||
font: 1em monospace;
|
||||
text-align: left;
|
||||
overflow: clip
|
||||
}
|
||||
|
||||
#diff-ui pre {
|
||||
white-space: pre-wrap
|
||||
}
|
||||
|
||||
h1 {
|
||||
display: inline;
|
||||
font-size: 100%
|
||||
}
|
||||
|
||||
del {
|
||||
text-decoration: none;
|
||||
color: #b30000;
|
||||
background: #fadad7
|
||||
}
|
||||
|
||||
ins {
|
||||
background: #eaf2c2;
|
||||
color: #406619;
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
#result {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
overflow-wrap: break-word
|
||||
}
|
||||
|
||||
#settings {
|
||||
background: rgba(0, 0, 0, .05);
|
||||
padding: 1em;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 1em;
|
||||
color: #fff;
|
||||
font-size: 80%
|
||||
}
|
||||
|
||||
#settings label {
|
||||
margin-left: 1em;
|
||||
display: inline-block;
|
||||
font-weight: normal
|
||||
}
|
||||
|
||||
#settings del {
|
||||
padding: .5em
|
||||
}
|
||||
|
||||
#settings ins {
|
||||
padding: .5em
|
||||
}
|
||||
|
||||
#settings option:checked {
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
#settings [type=radio], #settings [type=checkbox] {
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
.source {
|
||||
position: absolute;
|
||||
right: 1%;
|
||||
top: .2em
|
||||
}
|
||||
|
||||
@-moz-document url-prefix() {
|
||||
body {
|
||||
height: 99%
|
||||
}
|
||||
}
|
||||
|
||||
td#diff-col div {
|
||||
text-align: justify;
|
||||
white-space: pre-wrap
|
||||
}
|
||||
|
||||
.ignored {
|
||||
background-color: #ccc;
|
||||
opacity: .7
|
||||
}
|
||||
|
||||
.triggered {
|
||||
background-color: #1b98f8
|
||||
}
|
||||
|
||||
.ignored.triggered {
|
||||
background-color: red
|
||||
}
|
||||
|
||||
.tab-pane-inner#screenshot {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.tab-pane-inner#screenshot img {
|
||||
max-width: 99%
|
||||
}
|
||||
|
||||
#highlightSnippet {
|
||||
background: var(--color-background);
|
||||
padding: 1em;
|
||||
border-radius: 5px;
|
||||
background: var(--color-background);
|
||||
box-shadow: 1px 1px 4px var(--color-shadow-jump)
|
||||
}
|
||||
|
||||
.pure-form button.reset-margin {
|
||||
margin: 0px
|
||||
}
|
||||
|
||||
.diff-fieldset {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap
|
||||
}
|
||||
#diff-ui{background:var(--color-background);padding:2em;margin-left:1em;margin-right:1em;border-radius:5px}#diff-ui #text{font-size:11px}#diff-ui table{table-layout:fixed;width:100%}#diff-ui td{padding:3px 4px;border:1px solid rgba(0,0,0,0);vertical-align:top;font:1em monospace;text-align:left;overflow:clip}#diff-ui pre{white-space:break-spaces}h1{display:inline;font-size:100%}del{text-decoration:none;color:#b30000;background:#fadad7}ins{background:#eaf2c2;color:#406619;text-decoration:none}#result{white-space:pre-wrap;word-break:break-word;overflow-wrap:break-word}#settings{background:rgba(0,0,0,.05);padding:1em;border-radius:10px;margin-bottom:1em;color:#fff;font-size:.9rem}#settings label{margin-left:1em;display:inline-block;font-weight:normal}#settings del{padding:.5em}#settings ins{padding:.5em}#settings option:checked{font-weight:bold}#settings [type=radio],#settings [type=checkbox]{vertical-align:middle}.source{position:absolute;right:1%;top:.2em}@-moz-document url-prefix(){body{height:99%}}td#diff-col div{text-align:justify;white-space:pre-wrap}.ignored{background-color:#ccc;opacity:.7}.triggered{background-color:#1b98f8}.ignored.triggered{background-color:red}.tab-pane-inner#screenshot{text-align:center}.tab-pane-inner#screenshot img{max-width:99%}.pure-form button.reset-margin{margin:0px}.diff-fieldset{display:flex;align-items:center;gap:4px;flex-wrap:wrap}ul#highlightSnippetActions{list-style-type:none;display:flex;align-items:center;justify-content:center;gap:1.5rem;flex-wrap:wrap;padding:0;margin:0}ul#highlightSnippetActions li{display:flex;flex-direction:column;align-items:center;text-align:center;padding:.5rem;gap:.3rem}ul#highlightSnippetActions li button,ul#highlightSnippetActions li a{white-space:nowrap}ul#highlightSnippetActions span{font-size:.8rem;color:var(--color-text-input-description)}#cell-diff-jump-visualiser{display:flex;flex-direction:row;gap:1px;background:var(--color-background);border-radius:3px;overflow-x:auto;position:sticky;top:0;z-index:10;padding-top:1rem;padding-bottom:1rem}#cell-diff-jump-visualiser>div{flex:1;min-width:1px;height:10px;background:var(--color-background-button-cancel);opacity:.3;border-radius:1px;transition:opacity .2s;position:relative}#cell-diff-jump-visualiser>div.deletion{background:#b30000;opacity:1}#cell-diff-jump-visualiser>div.insertion{background:#406619;opacity:1}#cell-diff-jump-visualiser>div.note{background:#406619;opacity:1}#cell-diff-jump-visualiser>div.mixed{background:linear-gradient(to right, #b30000 50%, #406619 50%);opacity:1}#cell-diff-jump-visualiser>div.current-position::after{content:"";position:absolute;bottom:-6px;left:50%;transform:translateX(-50%);width:0;height:0;border-left:4px solid rgba(0,0,0,0);border-right:4px solid rgba(0,0,0,0);border-bottom:4px solid var(--color-text)}#cell-diff-jump-visualiser>div:hover{opacity:.8;cursor:pointer}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
@use "parts/variables";
|
||||
|
||||
#diff-ui {
|
||||
|
||||
background: var(--color-background);
|
||||
@@ -28,7 +26,7 @@
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
white-space: break-spaces;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +63,7 @@ ins {
|
||||
border-radius: 10px;
|
||||
margin-bottom: 1em;
|
||||
color: #fff;
|
||||
font-size: 80%;
|
||||
font-size: 0.9rem;
|
||||
|
||||
label {
|
||||
margin-left: 1em;
|
||||
@@ -130,13 +128,6 @@ td#diff-col div {
|
||||
}
|
||||
}
|
||||
|
||||
#highlightSnippet {
|
||||
background: var(--color-background);
|
||||
padding: 1em;
|
||||
border-radius: 5px;
|
||||
background: var(--color-background);
|
||||
box-shadow: 1px 1px 4px var(--color-shadow-jump);
|
||||
}
|
||||
|
||||
// resets button margin to 0px
|
||||
.pure-form button.reset-margin {
|
||||
@@ -148,4 +139,97 @@ td#diff-col div {
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ul#highlightSnippetActions {
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.5rem;
|
||||
flex-wrap: wrap;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
padding: 0.5rem;
|
||||
gap: 0.3rem;
|
||||
|
||||
button, a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 0.8rem;
|
||||
color: var(--color-text-input-description);
|
||||
}
|
||||
}
|
||||
|
||||
#cell-diff-jump-visualiser {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1px;
|
||||
background: var(--color-background);
|
||||
border-radius: 3px;
|
||||
overflow-x: auto;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
> div {
|
||||
flex: 1;
|
||||
min-width: 1px;
|
||||
height: 10px;
|
||||
background: var(--color-background-button-cancel);
|
||||
opacity: 0.3;
|
||||
border-radius: 1px;
|
||||
transition: opacity 0.2s;
|
||||
position: relative;
|
||||
|
||||
&.deletion {
|
||||
background: #b30000; // Red for deletions
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.insertion {
|
||||
background: #406619; // Green for insertions
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.note {
|
||||
background: #406619; // Orange for changed/notes
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.mixed {
|
||||
background: linear-gradient(to right, #b30000 50%, #406619 50%); // Half red, half green
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.current-position::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -6px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-bottom: 4px solid var(--color-text);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1142,4 +1142,9 @@ ul {
|
||||
|
||||
// When JavaScript removes display:none, ensure it scrolls into view
|
||||
scroll-margin-bottom: 10px;
|
||||
|
||||
// Center contents horizontally
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -43,7 +43,7 @@
|
||||
|
||||
<body class="{{extra_classes}}">
|
||||
<div class="header">
|
||||
<div class="pure-menu-fixed" style="width: 100%;">
|
||||
<div {% if pure_menu_fixed != False %}class="pure-menu-fixed"{% endif %} style="width: 100%;">
|
||||
<div class="home-menu pure-menu pure-menu-horizontal" id="nav-menu">
|
||||
|
||||
{% if has_password and not current_user.is_authenticated %}
|
||||
@@ -152,8 +152,6 @@
|
||||
{% endif %}
|
||||
{% if left_sticky %}
|
||||
<div class="sticky-tab" id="left-sticky">
|
||||
<a href="{{url_for('ui.ui_views.preview_page', uuid=uuid)}}">Show current snapshot</a><br>
|
||||
Visualise <strong>triggers</strong> and <strong>ignored text</strong>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if right_sticky %}
|
||||
|
||||
Reference in New Issue
Block a user