Fix: Thymeleaf syntax (/*[[...]]*/) (#2659)

# Description

Please provide a summary of the changes, including relevant motivation
and context.

Closes #(issue_number)

## Checklist

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated
relevant docs on [Stirling-PDFs doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [x] My changes generate no new warnings
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
This commit is contained in:
Ludy 2025-01-12 01:18:35 +01:00 committed by GitHub
parent b2da426cc1
commit 76cbf94fdc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 183 additions and 186 deletions

View File

@ -39,4 +39,3 @@ document.getElementById("cacheInputs").addEventListener("change", function () {
cacheInputs = this.checked ? "enabled" : "disabled"; cacheInputs = this.checked ? "enabled" : "disabled";
localStorage.setItem("cacheInputs", cacheInputs); localStorage.setItem("cacheInputs", cacheInputs);
}); });

View File

@ -308,37 +308,36 @@
document.getElementById('syncToAccount').addEventListener('click', async function() { document.getElementById('syncToAccount').addEventListener('click', async function() {
/*<![CDATA[*/ /*<![CDATA[*/
const urlUpdateUserSettings = /*[[@{/api/v1/user/updateUserSettings}]]*/ "/api/v1/user/updateUserSettings"; const urlUpdateUserSettings = /*[[@{/api/v1/user/updateUserSettings}]]*/ "/api/v1/user/updateUserSettings";
/*]]>*/ /*]]>*/
let settings = {}; let settings = {};
for (let i = 0; i < localStorage.length; i++) { for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i); const key = localStorage.key(i);
if(key !== 'debug' && key !== '0' && key !== '1' && !key.includes('pdfjs') && !key.includes('posthog') && !key.includes('pageViews')) { if(key !== 'debug' && key !== '0' && key !== '1' && !key.includes('pdfjs') && !key.includes('posthog') && !key.includes('pageViews')) {
settings[key] = localStorage.getItem(key); settings[key] = localStorage.getItem(key);
} }
} }
try { try {
const response = await window.fetchWithCsrf(urlUpdateUserSettings, { const response = await window.fetchWithCsrf(urlUpdateUserSettings, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify(settings) body: JSON.stringify(settings)
}); });
if (response.ok) {
location.reload();
} else {
alert('Error syncing settings to account');
}
} catch (error) {
console.error('Error:', error);
alert('Error syncing settings to account');
}
});
if (response.ok) {
location.reload();
} else {
alert('Error syncing settings to account');
}
} catch (error) {
console.error('Error:', error);
alert('Error syncing settings to account');
}
});
}); });
</script> </script>
<div class="mb-3 mt-4 text-center"> <div class="mb-3 mt-4 text-center">

View File

@ -16,8 +16,8 @@
<!-- powered by section --> <!-- powered by section -->
<div class="footer-powered-by"> <div class="footer-powered-by">
<span th:text="#{poweredBy}"></span> <span th:text="#{poweredBy}"></span>
<a href="https://stirlingpdf.com" class="stirling-link">Stirling PDF</a> <a href="https://stirlingpdf.com" class="stirling-link">Stirling PDF</a>
</div> </div>
</div> </div>
</footer> </footer>

View File

@ -12,87 +12,87 @@
<div class="container-flex"> <div class="container-flex">
<main class="form-signin"> <main class="form-signin">
<script th:inline="javascript"> <script th:inline="javascript">
const redirectAttempts = parseInt(localStorage.getItem('ssoRedirectAttempts') || '0'); const redirectAttempts = parseInt(localStorage.getItem('ssoRedirectAttempts') || '0');
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const hasRedirectError = urlParams.has('error'); const hasRedirectError = urlParams.has('error');
const hasLogout = urlParams.has('logout'); const hasLogout = urlParams.has('logout');
const hasMessage = urlParams.has('message'); const hasMessage = urlParams.has('message');
const MAX_REDIRECT_ATTEMPTS = 3; const MAX_REDIRECT_ATTEMPTS = 3;
document.addEventListener('modeChanged', function(e) { document.addEventListener('modeChanged', function(e) {
var mode = e.detail; var mode = e.detail;
document.body.classList.remove("light-mode", "dark-mode", "rainbow-mode"); // remove all mode classes first document.body.classList.remove("light-mode", "dark-mode", "rainbow-mode"); // remove all mode classes first
switch (mode) { switch (mode) {
case "on": case "on":
document.body.classList.add("dark-mode"); document.body.classList.add("dark-mode");
break; break;
case "off": case "off":
document.body.classList.add("light-mode"); document.body.classList.add("light-mode");
break; break;
case "rainbow": case "rainbow":
document.body.classList.add("rainbow-mode"); document.body.classList.add("rainbow-mode");
break; break;
} }
}); });
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
const runningEE = [[${@runningEE}]]; const runningEE = /*[[${@runningEE}]]*/ false;
const SSOAutoLogin = [[${@SSOAutoLogin}]]; const SSOAutoLogin = /*[[${@SSOAutoLogin}]]*/ false;
const loginMethod = [[${loginMethod}]]; const loginMethod = /*[[${loginMethod}]]*/ 'normal';
const providerList = [[${providerlist}]]; const providerList = /*[[${providerlist}]]*/ {};
const shouldAutoRedirect = !hasRedirectError && const shouldAutoRedirect = !hasRedirectError &&
!hasLogout && !hasLogout &&
!hasMessage && !hasMessage &&
redirectAttempts < MAX_REDIRECT_ATTEMPTS && redirectAttempts < MAX_REDIRECT_ATTEMPTS &&
loginMethod !== 'normal' && runningEE && SSOAutoLogin; loginMethod !== 'normal' && runningEE && SSOAutoLogin;
console.log('Should redirect:', shouldAutoRedirect, { console.log('Should redirect:', shouldAutoRedirect, {
'No error': !hasRedirectError, 'No error': !hasRedirectError,
'No logout': !hasLogout, 'No logout': !hasLogout,
'No message': !hasMessage, 'No message': !hasMessage,
'Under max attempts': redirectAttempts < MAX_REDIRECT_ATTEMPTS, 'Under max attempts': redirectAttempts < MAX_REDIRECT_ATTEMPTS,
'Is OAuth2': loginMethod === 'oauth2' 'Is only OAuth2': loginMethod === 'oauth2'
}); });
if (shouldAutoRedirect && providerList && Object.keys(providerList).length > 0) { if (shouldAutoRedirect && providerList && Object.keys(providerList).length > 0) {
localStorage.setItem('ssoRedirectAttempts', redirectAttempts + 1); localStorage.setItem('ssoRedirectAttempts', redirectAttempts + 1);
const firstProvider = Object.keys(providerList)[0]; const firstProvider = Object.keys(providerList)[0];
window.location.href = firstProvider; window.location.href = firstProvider;
} }
// Reset redirect attempts if successful login or after 1 hour // Reset redirect attempts if successful login or after 1 hour
const lastAttemptTime = parseInt(localStorage.getItem('lastRedirectAttempt') || '0'); const lastAttemptTime = parseInt(localStorage.getItem('lastRedirectAttempt') || '0');
if (Date.now() - lastAttemptTime > 3600000) { // 1 hour if (Date.now() - lastAttemptTime > 3600000) { // 1 hour
localStorage.setItem('ssoRedirectAttempts', '0'); localStorage.setItem('ssoRedirectAttempts', '0');
} }
localStorage.setItem('lastRedirectAttempt', Date.now().toString()); localStorage.setItem('lastRedirectAttempt', Date.now().toString());
const defaultLocale = getStoredOrDefaultLocale(); const defaultLocale = getStoredOrDefaultLocale();
checkUserLanguage(defaultLocale); checkUserLanguage(defaultLocale);
const dropdownItems = document.querySelectorAll('.lang_dropdown-item'); const dropdownItems = document.querySelectorAll('.lang_dropdown-item');
let activeItem; let activeItem;
for (let i = 0; i < dropdownItems.length; i++) { for (let i = 0; i < dropdownItems.length; i++) {
const item = dropdownItems[i]; const item = dropdownItems[i];
item.classList.remove('active'); item.classList.remove('active');
if (item.dataset.bsLanguageCode === defaultLocale) { if (item.dataset.bsLanguageCode === defaultLocale) {
item.classList.add('active'); item.classList.add('active');
activeItem = item; activeItem = item;
} }
item.addEventListener('click', handleDropdownItemClick); item.addEventListener('click', handleDropdownItemClick);
} }
const dropdown = document.getElementById('languageDropdown'); const dropdown = document.getElementById('languageDropdown');
if (activeItem) { if (activeItem) {
dropdown.innerHTML = activeItem.innerHTML; // This will set the dropdown button's content to the active language's flag and name dropdown.innerHTML = activeItem.innerHTML; // This will set the dropdown button's content to the active language's flag and name
} }
}); });
</script> </script>
<div class="text-center"> <div class="text-center">
<img class="my-4" th:src="@{'/favicon.svg'}" alt="favicon" width="144" height="144"> <img class="my-4" th:src="@{'/favicon.svg'}" alt="favicon" width="144" height="144">

View File

@ -22,9 +22,9 @@
<span id="currentVersion" th:text="${@appVersion}"></span> <span id="currentVersion" th:text="${@appVersion}"></span>
</div> </div>
<div class="alert alert-warning" role="alert"> <div class="alert alert-warning" role="alert">
<span th:text="#{releases.note}">All release notes are only available in English</span> <span th:text="#{releases.note}">All release notes are only available in English</span>
</div> </div>
<div id="loading" class="text-center my-4"> <div id="loading" class="text-center my-4">
<div class="spinner-border text-primary" role="status"> <div class="spinner-border text-primary" role="status">
@ -107,14 +107,14 @@
/*<![CDATA[*/ /*<![CDATA[*/
// Get the current version from the appVersion bean // Get the current version from the appVersion bean
const appVersion = [[${@appVersion}]]; const appVersion = /*[[${@appVersion}]]*/ '';
// GitHub API configuration // GitHub API configuration
const REPO_OWNER = 'Stirling-Tools'; const REPO_OWNER = 'Stirling-Tools';
const REPO_NAME = 'Stirling-PDF'; const REPO_NAME = 'Stirling-PDF';
const GITHUB_API = 'https://api.github.com/repos/' + REPO_OWNER + '/' + REPO_NAME; const GITHUB_API = 'https://api.github.com/repos/' + REPO_OWNER + '/' + REPO_NAME;
const GITHUB_URL = 'https://github.com/' + REPO_OWNER + '/' + REPO_NAME; const GITHUB_URL = 'https://github.com/' + REPO_OWNER + '/' + REPO_NAME;
const MAX_RELEASES = 8; const MAX_RELEASES = 8;
// Secure element creation helper // Secure element creation helper
function createElement(tag, attributes = {}, children = []) { function createElement(tag, attributes = {}, children = []) {
@ -134,7 +134,6 @@
return element; return element;
} }
const ALLOWED_TAGS = { const ALLOWED_TAGS = {
'a': ['href', 'target', 'rel', 'class'], 'a': ['href', 'target', 'rel', 'class'],
'img': ['src', 'alt', 'width', 'height', 'style'], 'img': ['src', 'alt', 'width', 'height', 'style'],

View File

@ -21,9 +21,9 @@
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, remoteCall='false', accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, remoteCall='false', accept='application/pdf')}"></div>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label th:text="#{validateSignature.selectCustomCert}" ></label> <label th:text="#{validateSignature.selectCustomCert}" ></label>
<div th:replace="~{fragments/common :: fileSelector(name='certFile', multipleInputsForSingleRequest=false, notRequired=true, remoteCall='false', accept='.cer,.crt,.pem')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='certFile', multipleInputsForSingleRequest=false, notRequired=true, remoteCall='false', accept='.cer,.crt,.pem')}"></div>
</div> </div>
<div class="mb-3 text-left"> <div class="mb-3 text-left">
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{validateSignature.submit}"></button> <button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{validateSignature.submit}"></button>
</div> </div>