1
0
mirror of https://github.com/Stirling-Tools/Stirling-PDF.git synced 2024-11-14 03:20:14 +01:00

Merge remote-tracking branch 'origin/main' into config

This commit is contained in:
a 2024-05-19 11:54:58 +01:00
commit f9111e556c
68 changed files with 184 additions and 80 deletions

View File

@ -222,27 +222,47 @@ The Current list of settings is
```yaml ```yaml
security: security:
enableLogin: false # set to 'true' to enable login enableLogin: false # set to 'true' to enable login
csrfDisabled: true csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production)
loginAttemptCount: 5 # lock user account after 5 tries
loginResetTimeMinutes : 120 # lock account for 2 hours after x attempts
# initialLogin:
# username: "admin" # Initial username for the first login
# password: "stirling" # Initial password for the first login
# oauth2:
# enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
# issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
# clientId: "" # Client ID from your provider
# clientSecret: "" # Client Secret from your provider
# autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
# useAsUsername: "email" # Default is 'email'; custom fields can be used as the username
# scopes: "openid, profile, email" # Specify the scopes for which the application will request permissions
# provider: "google" # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
system: system:
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc) defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
customStaticFilePath: '/customFiles/static/' # Directory path for custom static files rootURIPath: '/pdf-app' # ie set to /pdf-app to Set the application's root URI to localhost:8080/pdf-app
customStaticFilePath: '/customFiles/static/' # Customise static files (e.g., logo, images, CSS) by placing them in this directory.
maxFileSize: 10485760 # Maximum file size for uploads in bytes.
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
showUpdate: true # see when a new update is available showUpdate: true # see when a new update is available
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true' showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
#ui: ui:
# appName: exampleAppName # Application's visible name appName: null # Application's visible name
# homeDescription: I am a description # Short description or tagline shown on homepage. homeDescription: null # Short description or tagline shown on homepage.
# appNameNavbar: navbarName # Name displayed on the navigation bar appNameNavbar: null # Name displayed on the navigation bar
endpoints: endpoints:
toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages']) toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages'])
groupsToRemove: [] # List groups to disable (e.g. ['LibreOffice']) groupsToRemove: [] # List groups to disable (e.g. ['LibreOffice'])
metrics: metrics:
enabled: true # 'true' to enable Info APIs endpoints (view http://localhost:8080/swagger-ui/index.html#/API to learn more), 'false' to disable enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable
autoPipeline:
outputFolder: /output # Directory for auto-pipeline outputs.
``` ```
There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones

View File

@ -54,10 +54,8 @@ public class InitialSecuritySetup {
&& !initialPassword.isEmpty() && !initialPassword.isEmpty()
&& !userService.findByUsernameIgnoreCase(initialUsername).isPresent()) { && !userService.findByUsernameIgnoreCase(initialUsername).isPresent()) {
try { try {
if (userService.isUsernameValid(initialUsername)) { userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId()); logger.info("Admin user created: " + initialUsername);
logger.info("Admin user created: " + initialUsername);
}
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
logger.error("Failed to initialize security setup", e); logger.error("Failed to initialize security setup", e);
System.exit(1); System.exit(1);

View File

@ -197,7 +197,13 @@ public class UserService implements UserServiceInterface {
} }
public boolean hasUsers() { public boolean hasUsers() {
return userRepository.count() > 0; long userCount = userRepository.count();
if (userRepository
.findByUsernameIgnoreCase(Role.INTERNAL_API_USER.getRoleId())
.isPresent()) {
userCount -= 1;
}
return userCount > 0;
} }
public void updateUserSettings(String username, Map<String, String> updates) { public void updateUserSettings(String username, Map<String, String> updates) {

View File

@ -4,9 +4,12 @@
security: security:
enableLogin: false # set to 'true' to enable login enableLogin: false # set to 'true' to enable login
csrfDisabled: true csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production)
loginAttemptCount: 5 # lock user account after 5 tries loginAttemptCount: 5 # lock user account after 5 tries
loginResetTimeMinutes : 120 # lock account for 2 hours after x attempts loginResetTimeMinutes : 120 # lock account for 2 hours after x attempts
# initialLogin:
# username: "admin" # Initial username for the first login
# password: "stirling" # Initial password for the first login
# oauth2: # oauth2:
# enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work) # enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
# issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point # issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
@ -20,9 +23,13 @@ security:
system: system:
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc) defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
rootURIPath: '/pdf-app' # ie set to /pdf-app to Set the application's root URI to localhost:8080/pdf-app
customStaticFilePath: '/customFiles/static/' # Customise static files (e.g., logo, images, CSS) by placing them in this directory.
maxFileSize: 10485760 # Maximum file size for uploads in bytes.
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes) enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
showUpdate: true # see when a new update is available showUpdate: true # see when a new update is available
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true' showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
ui: ui:
appName: null # Application's visible name appName: null # Application's visible name

View File

@ -65,7 +65,7 @@ label {
margin-left: auto; margin-left: auto;
} }
#bg-card { .bg-card {
background-color: var(--md-sys-color-surface-5); background-color: var(--md-sys-color-surface-5);
border-radius: 3rem; border-radius: 3rem;
padding: 25px 0 0; padding: 25px 0 0;

View File

@ -58,7 +58,7 @@ td {
border-bottom: none; border-bottom: none;
} }
#bg-card { .bg-card {
background-color: var(--md-sys-color-surface-5); background-color: var(--md-sys-color-surface-5);
border-radius: 3rem; border-radius: 3rem;
padding: 2.5rem; padding: 2.5rem;

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"></div> <div class="col-md-6 bg-card"></div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -21,6 +21,7 @@
<span th:text="#{${messageType}}">Default message if not found</span> <span th:text="#{${messageType}}">Default message if not found</span>
</div> </div>
</th:block> </th:block>
<!-- At the top of the user settings --> <!-- At the top of the user settings -->
<h3 class="text-center"><span th:text="#{welcome} + ' ' + ${username}">User</span>!</h3> <h3 class="text-center"><span th:text="#{welcome} + ' ' + ${username}">User</span>!</h3>
<th:block th:if="${error}"> <th:block th:if="${error}">
@ -28,13 +29,15 @@
<span th:text="${error}">Error Message</span> <span th:text="${error}">Error Message</span>
</div> </div>
</th:block> </th:block>
<!-- Change Username Form --> <!-- Change Username Form -->
<th:block th:if="${!oAuth2Login}"> <th:block th:if="${!oAuth2Login}">
<h4 th:text="#{account.changeUsername}">Change Username?</h4> <h4 th:text="#{account.changeUsername}">Change Username?</h4>
<form id="bg-card" class="mt-4 mb-4" action="api/v1/user/change-username" method="post"> <form id="formsavechangeusername" class="bg-card mt-4 mb-4" action="api/v1/user/change-username" method="post">
<div class="mb-3"> <div class="mb-3">
<label for="newUsername" th:text="#{account.newUsername}">Change Username</label> <label for="newUsername" th:text="#{account.newUsername}">Change Username</label>
<input type="text" class="form-control" name="newUsername" id="newUsername" th:placeholder="#{account.newUsername}"> <input type="text" class="form-control" name="newUsername" id="newUsername" th:placeholder="#{account.newUsername}">
<span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="currentPassword" th:text="#{password}">Password</label> <label for="currentPassword" th:text="#{password}">Password</label>
@ -49,10 +52,10 @@
<!-- Change Password Form --> <!-- Change Password Form -->
<th:block th:if="${!oAuth2Login}"> <th:block th:if="${!oAuth2Login}">
<h4 th:text="#{account.changePassword}">Change Password?</h4> <h4 th:text="#{account.changePassword}">Change Password?</h4>
<form id="bg-card" class="mt-4 mb-4" action="api/v1/user/change-password" method="post"> <form id="formsavechangepassword" class="bg-card mt-4 mb-4" action="api/v1/user/change-password" method="post">
<div class="mb-3"> <div class="mb-3">
<label for="currentPassword" th:text="#{account.oldPassword}">Old Password</label> <label for="currentPassword" th:text="#{account.oldPassword}">Old Password</label>
<input type="password" class="form-control" name="currentPassword" id="currentPasswordPassword" th:placeholder="#{account.oldPassword}"> <input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{account.oldPassword}">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="newPassword" th:text="#{account.newPassword}">New Password</label> <label for="newPassword" th:text="#{account.newPassword}">New Password</label>
@ -95,6 +98,76 @@
</div> </div>
</div> </div>
</div> </div>
<script th:inline="javascript">
jQuery.validator.addMethod("usernamePattern", function(value, element) {
return this.optional(element) || /^[a-zA-Z0-9][a-zA-Z0-9@._+-]*[a-zA-Z0-9]$|^(?=.{1,64}@)[A-Za-z0-9]+(\.[A-Za-z0-9_+.-]+)*@[^-][A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$/.test(value);
}, /*[[#{invalidUsernameMessage}]]*/ "Invalid username format");
$(document).ready(function() {
$('#formsavechangepassword').validate({
rules: {
currentPassword: {
required: true
},
newPassword: {
required: true
},
confirmNewPassword: {
required: true
}
}
});
$('#formsavechangeusername').validate({
rules: {
newUsername: {
required: true,
usernamePattern: true
},
currentPassword: {
required: true
}
},
messages: {
newUsername: {
usernamePattern: /*[[#{invalidUsernameMessage}]]*/ "Invalid username format"
},
},
errorPlacement: function(error, element) {
if (element.attr("name") === "newUsername") {
$("#usernameError").text(error.text()).show();
} else {
error.insertAfter(element);
}
},
success: function(label, element) {
if ($(element).attr("name") === "newUsername") {
$("#usernameError").hide();
}
}
});
$('#formsavechangepassword').on('submit', function(event) {
var newPassword = $('#newPassword').val();
var confirmNewPassword = $('#confirmNewPassword').val();
if (newPassword !== confirmNewPassword) {
alert('New Password and Confirm New Password must match.');
event.preventDefault();
}
});
$('#newUsername').on('input', function() {
var usernameInput = $(this);
var isValid = usernameInput[0].checkValidity();
var errorSpan = $('#usernameError');
if (isValid) {
usernameInput.removeClass('invalid').addClass('valid');
errorSpan.hide();
} else {
usernameInput.removeClass('valid').addClass('invalid');
errorSpan.show();
}
});
});
</script>
<script> <script>
function copyToClipboard() { function copyToClipboard() {
@ -180,7 +253,7 @@
</script> </script>
<h4 th:text="#{account.syncTitle}">Sync browser settings with Account</h4> <h4 th:text="#{account.syncTitle}">Sync browser settings with Account</h4>
<div id="bg-card" class="container mt-4"> <div class="bg-card container mt-4">
<h3 th:text="#{account.settingsCompare}">Settings Comparison:</h3> <h3 th:text="#{account.settingsCompare}">Settings Comparison:</h3>
<table id="settingsTable" class="table table-bordered table-sm table-striped"> <table id="settingsTable" class="table table-bordered table-sm table-striped">
<thead> <thead>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-8" id="bg-card"> <div class="col-md-8 bg-card">
<!-- User Settings Title --> <!-- User Settings Title -->
<h2 class="text-center" th:text="#{adminUserSettings.header}">Admin User Control Settings</h2> <h2 class="text-center" th:text="#{adminUserSettings.header}">Admin User Control Settings</h2>

View File

@ -15,7 +15,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">cut</span> <span class="material-symbols-rounded tool-header-icon advance">cut</span>
<span class="tool-header-text" th:text="#{autoSplitPDF.header}"></span> <span class="tool-header-text" th:text="#{autoSplitPDF.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-9" id="bg-card"> <div class="col-md-9 bg-card">
<!-- User Settings Title --> <!-- User Settings Title -->
<h2 class="text-center" th:text="#{changeCreds.header}">User Settings</h2> <h2 class="text-center" th:text="#{changeCreds.header}">User Settings</h2>

View File

@ -14,7 +14,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">draft</span> <span class="material-symbols-rounded tool-header-icon convert">draft</span>
<span class="tool-header-text" th:text="#{fileToPDF.header}"></span> <span class="tool-header-text" th:text="#{fileToPDF.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="mb-3" id="bg-card"> <div class="mb-3 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">html</span> <span class="material-symbols-rounded tool-header-icon convert">html</span>
<span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span> <span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon image">image</span> <span class="material-symbols-rounded tool-header-icon image">image</span>
<span class="tool-header-text" th:text="#{imageToPDF.header}"></span> <span class="tool-header-text" th:text="#{imageToPDF.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">markdown</span> <span class="material-symbols-rounded tool-header-icon convert">markdown</span>
<span class="tool-header-text" th:text="#{MarkdownToPDF.header}"></span> <span class="tool-header-text" th:text="#{MarkdownToPDF.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">csv</span> <span class="material-symbols-rounded tool-header-icon convert">csv</span>
<span class="tool-header-text" th:text="#{PDFToCSV.header}"></span> <span class="tool-header-text" th:text="#{PDFToCSV.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">html</span> <span class="material-symbols-rounded tool-header-icon convert">html</span>
<span class="tool-header-text" th:text="#{PDFToHTML.header}"></span> <span class="tool-header-text" th:text="#{PDFToHTML.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon image">image</span> <span class="material-symbols-rounded tool-header-icon image">image</span>
<span class="tool-header-text" th:text="#{pdfToImage.header}"></span> <span class="tool-header-text" th:text="#{pdfToImage.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">picture_as_pdf</span> <span class="material-symbols-rounded tool-header-icon convert">picture_as_pdf</span>
<span class="tool-header-text" th:text="#{pdfToPDFA.header}"></span> <span class="tool-header-text" th:text="#{pdfToPDFA.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon ppt">slideshow</span> <span class="material-symbols-rounded tool-header-icon ppt">slideshow</span>
<span class="tool-header-text" th:text="#{PDFToPresentation.header}"></span> <span class="tool-header-text" th:text="#{PDFToPresentation.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">text_fields</span> <span class="material-symbols-rounded tool-header-icon convert">text_fields</span>
<span class="tool-header-text" th:text="#{PDFToText.header}"></span> <span class="tool-header-text" th:text="#{PDFToText.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon word">description</span> <span class="material-symbols-rounded tool-header-icon word">description</span>
<span class="tool-header-text" th:text="#{PDFToWord.header}"></span> <span class="tool-header-text" th:text="#{PDFToWord.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">code</span> <span class="material-symbols-rounded tool-header-icon convert">code</span>
<span class="tool-header-text" th:text="#{PDFToXML.header}"></span> <span class="tool-header-text" th:text="#{PDFToXML.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">link</span> <span class="material-symbols-rounded tool-header-icon convert">link</span>
<span class="tool-header-text" th:text="#{URLToPDF.header}"></span> <span class="tool-header-text" th:text="#{URLToPDF.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">crop</span> <span class="material-symbols-rounded tool-header-icon organize">crop</span>
<span class="tool-header-text" th:text="#{crop.header}"></span> <span class="tool-header-text" th:text="#{crop.header}"></span>

View File

@ -10,7 +10,7 @@
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block> <th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<div class="container"> <div class="container">
<div th:insert="~{fragments/errorBanner.html :: errorBanner}"></div> <div th:insert="~{fragments/errorBanner.html :: errorBanner}"></div>
<div id="bg-card" class="text-center"> <div class="bg-card text-center">
<h1 class="display-2" th:text="#{oops}"></h1> <h1 class="display-2" th:text="#{oops}"></h1>
<p class="lead" th:if="${param.status == '404'}" th:text="#{error.404.1}"></p> <p class="lead" th:if="${param.status == '404'}" th:text="#{error.404.1}"></p>
<p class="lead" th:unless="${param.status == '404'}" th:text="#{error.404.2}"></p> <p class="lead" th:unless="${param.status == '404'}" th:text="#{error.404.2}"></p>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">upload</span> <span class="material-symbols-rounded tool-header-icon organize">upload</span>
<span class="tool-header-text" th:text="#{pageExtracter.header}"></span> <span class="tool-header-text" th:text="#{pageExtracter.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<h2 th:text="#{licenses.header}">3rd Party licenses</h2> <h2 th:text="#{licenses.header}">3rd Party licenses</h2>
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container" id="dropContainer"> <div class="container" id="dropContainer">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 "bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">add_to_photos</span> <span class="material-symbols-rounded tool-header-icon organize">add_to_photos</span>
<span class="tool-header-text" th:text="#{merge.header}"></span> <span class="tool-header-text" th:text="#{merge.header}"></span>

View File

@ -13,7 +13,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">add_photo_alternate</span> <span class="material-symbols-rounded tool-header-icon other">add_photo_alternate</span>
<span class="tool-header-text" th:text="#{addImage.header}"></span> <span class="tool-header-text" th:text="#{addImage.header}"></span>

View File

@ -55,7 +55,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">123</span> <span class="material-symbols-rounded tool-header-icon other">123</span>
<span class="tool-header-text" th:text="#{addPageNumbers.header}"></span> <span class="tool-header-text" th:text="#{addPageNumbers.header}"></span>

View File

@ -20,7 +20,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-12" id="bg-card"> <div class="col-md-12 bg-card">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-3"> <div class="col-md-3">
<div id="sliders-container" style="display:none;"> <div id="sliders-container" style="display:none;">

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">crop</span> <span class="material-symbols-rounded tool-header-icon advance">crop</span>
<span class="tool-header-text" th:text="#{autoCrop.header}"></span> <span class="tool-header-text" th:text="#{autoCrop.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">text_fields_alt</span> <span class="material-symbols-rounded tool-header-icon advance">text_fields_alt</span>
<span class="tool-header-text" th:text="#{auto-rename.header}"></span> <span class="tool-header-text" th:text="#{auto-rename.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">assignment</span> <span class="material-symbols-rounded tool-header-icon other">assignment</span>
<span class="tool-header-text" th:text="#{changeMetadata.header}"></span> <span class="tool-header-text" th:text="#{changeMetadata.header}"></span>

View File

@ -20,7 +20,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-9" id="bg-card"> <div class="col-md-9 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">compare</span> <span class="material-symbols-rounded tool-header-icon other">compare</span>
<span class="tool-header-text" th:text="#{compare.header}"></span> <span class="tool-header-text" th:text="#{compare.header}"></span>

View File

@ -14,7 +14,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">zoom_in_map</span> <span class="material-symbols-rounded tool-header-icon advance">zoom_in_map</span>
<span class="tool-header-text" th:text="#{compress.header}"></span> <span class="tool-header-text" th:text="#{compress.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">scanner</span> <span class="material-symbols-rounded tool-header-icon advance">scanner</span>
<span class="tool-header-text" th:text="#{home.ScannerImageSplit.title}"></span> <span class="tool-header-text" th:text="#{home.ScannerImageSplit.title}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">photo_library</span> <span class="material-symbols-rounded tool-header-icon other">photo_library</span>
<span class="tool-header-text" th:text="#{extractImages.header}"></span> <span class="tool-header-text" th:text="#{extractImages.header}"></span>

View File

@ -12,7 +12,7 @@
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">layers_clear</span> <span class="material-symbols-rounded tool-header-icon other">layers_clear</span>
<span class="tool-header-text" th:text="#{flatten.header}"></span> <span class="tool-header-text" th:text="#{flatten.header}"></span>

View File

@ -34,7 +34,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">quick_reference_all</span> <span class="material-symbols-rounded tool-header-icon other">quick_reference_all</span>
<span class="tool-header-text" th:text="#{ocr.header}"></span> <span class="tool-header-text" th:text="#{ocr.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">thread_unread</span> <span class="material-symbols-rounded tool-header-icon other">thread_unread</span>
<span class="tool-header-text" th:text="#{removeAnnotations.header}"></span> <span class="tool-header-text" th:text="#{removeAnnotations.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">scan_delete</span> <span class="material-symbols-rounded tool-header-icon other">scan_delete</span>
<span class="tool-header-text" th:text="#{removeBlanks.header}"></span> <span class="tool-header-text" th:text="#{removeBlanks.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">build</span> <span class="material-symbols-rounded tool-header-icon advance">build</span>
<span class="tool-header-text" th:text="#{repair.header}"></span> <span class="tool-header-text" th:text="#{repair.header}"></span>

View File

@ -20,7 +20,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-12" id="bg-card"> <div class="col-md-12 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">javascript</span> <span class="material-symbols-rounded tool-header-icon advance">javascript</span>
<span class="tool-header-text" th:text="#{showJS.header}"></span> <span class="tool-header-text" th:text="#{showJS.header}"></span>

View File

@ -22,7 +22,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">approval</span> <span class="material-symbols-rounded tool-header-icon security">approval</span>
<span class="tool-header-text" th:text="#{AddStampRequest.header}"></span> <span class="tool-header-text" th:text="#{AddStampRequest.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">dashboard</span> <span class="material-symbols-rounded tool-header-icon organize">dashboard</span>
<span class="tool-header-text" th:text="#{pageLayout.header}"></span> <span class="tool-header-text" th:text="#{pageLayout.header}"></span>

View File

@ -15,7 +15,7 @@
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-12"> <div class="col-md-12">
<div id="bg-card"> <div class="bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">construction</span> <span class="material-symbols-rounded tool-header-icon advance">construction</span>
<span class="tool-header-text" th:text="#{multiTool.header}"></span> <span class="tool-header-text" th:text="#{multiTool.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">layers</span> <span class="material-symbols-rounded tool-header-icon advance">layers</span>
<span class="tool-header-text" th:text="#{overlay-pdfs.header}"></span> <span class="tool-header-text" th:text="#{overlay-pdfs.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">format_list_bulleted</span> <span class="material-symbols-rounded tool-header-icon organize">format_list_bulleted</span>
<span class="tool-header-text" th:text="#{pdfOrganiser.header}"></span> <span class="tool-header-text" th:text="#{pdfOrganiser.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">looks_one</span> <span class="material-symbols-rounded tool-header-icon organize">looks_one</span>
<span class="tool-header-text" th:text="#{pdfToSinglePage.header}"></span> <span class="tool-header-text" th:text="#{pdfToSinglePage.header}"></span>

View File

@ -26,7 +26,7 @@
<br /><br /> <br /><br />
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">family_history</span> <span class="material-symbols-rounded tool-header-icon advance">family_history</span>
<span class="tool-header-text" th:text="#{pipeline.header}"></span> <span class="tool-header-text" th:text="#{pipeline.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">delete</span> <span class="material-symbols-rounded tool-header-icon organize">delete</span>
<span class="tool-header-text" th:text="#{pageRemover.header}"></span> <span class="tool-header-text" th:text="#{pageRemover.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">rotate_right</span> <span class="material-symbols-rounded tool-header-icon organize">rotate_right</span>
<span class="tool-header-text" th:text="#{rotate.header}"></span> <span class="tool-header-text" th:text="#{rotate.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">fullscreen</span> <span class="material-symbols-rounded tool-header-icon organize">fullscreen</span>
<span class="tool-header-text" th:text="#{scalePages.header}"></span> <span class="tool-header-text" th:text="#{scalePages.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">lock</span> <span class="material-symbols-rounded tool-header-icon security">lock</span>
<span class="tool-header-text" th:text="#{addPassword.header}"></span> <span class="tool-header-text" th:text="#{addPassword.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">water_drop</span> <span class="material-symbols-rounded tool-header-icon security">water_drop</span>
<span class="tool-header-text" th:text="#{watermark.header}"></span> <span class="tool-header-text" th:text="#{watermark.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">ink_eraser</span> <span class="material-symbols-rounded tool-header-icon security">ink_eraser</span>
<span class="tool-header-text" th:text="#{autoRedact.header}"></span> <span class="tool-header-text" th:text="#{autoRedact.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">workspace_premium</span> <span class="material-symbols-rounded tool-header-icon security">workspace_premium</span>
<span class="tool-header-text" th:text="#{certSign.header}"></span> <span class="tool-header-text" th:text="#{certSign.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">encrypted</span> <span class="material-symbols-rounded tool-header-icon security">encrypted</span>
<span class="tool-header-text" th:text="#{permissions.header}"></span> <span class="tool-header-text" th:text="#{permissions.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">info</span> <span class="material-symbols-rounded tool-header-icon other">info</span>
<span class="tool-header-text" th:text="#{getPdfInfo.header}"></span> <span class="tool-header-text" th:text="#{getPdfInfo.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">lock_open_right</span> <span class="material-symbols-rounded tool-header-icon security">lock_open_right</span>
<span class="tool-header-text" th:text="#{removePassword.header}"></span> <span class="tool-header-text" th:text="#{removePassword.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">water_drop</span> <span class="material-symbols-rounded tool-header-icon security">water_drop</span>
<span class="tool-header-text" th:text="#{remove-watermark.header}"></span> <span class="tool-header-text" th:text="#{remove-watermark.header}"></span>

View File

@ -11,7 +11,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">sanitizer</span> <span class="material-symbols-rounded tool-header-icon security">sanitizer</span>
<span class="tool-header-text" th:text="#{sanitizePDF.header}"></span> <span class="tool-header-text" th:text="#{sanitizePDF.header}"></span>

View File

@ -29,7 +29,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon sign">signature</span> <span class="material-symbols-rounded tool-header-icon sign">signature</span>
<span class="tool-header-text" th:text="#{sign.header}"></span> <span class="tool-header-text" th:text="#{sign.header}"></span>

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">vertical_split</span> <span class="material-symbols-rounded tool-header-icon advance">vertical_split</span>
<span class="tool-header-text" th:text="#{split-by-size-or-count.header}"></span> <span class="tool-header-text" th:text="#{split-by-size-or-count.header}"></span>

View File

@ -13,7 +13,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">grid_on</span> <span class="material-symbols-rounded tool-header-icon advance">grid_on</span>
<span class="tool-header-text" th:text="#{split-by-sections.header}"></span> <span class="tool-header-text" th:text="#{split-by-sections.header}"></span>

View File

@ -13,7 +13,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">cut</span> <span class="material-symbols-rounded tool-header-icon organize">cut</span>
<span class="tool-header-text" th:text="#{split.header}"></span> <span class="tool-header-text" th:text="#{split.header}"></span>