Merge branch 'bug/remember-me' of
git@github.com:Stirling-Tools/Stirling-PDF.git into bug/remember-me
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
<span class="tool-header-text" th:text="#{MarkdownToPDF.header}"></span>
|
||||
</div>
|
||||
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/markdown/pdf'}">
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='text/markdown')}"></div>
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='.md')}"></div>
|
||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{MarkdownToPDF.submit}"></button>
|
||||
</form>
|
||||
<p class="mt-3" th:text="#{MarkdownToPDF.help}"></p>
|
||||
|
||||
@@ -24,16 +24,20 @@
|
||||
<input id="height" type="hidden" name="height">
|
||||
<button type="submit" class="btn btn-primary" th:text="#{crop.submit}"></button>
|
||||
</form>
|
||||
<div style="position: relative; display: inline-block;">
|
||||
<canvas id="crop-pdf-canvas" style="position: absolute; top: 0; left: 0; z-index: 1;"></canvas>
|
||||
<canvas id="overlayCanvas" style="position: absolute; top: 0; left: 0; z-index: 2;"></canvas>
|
||||
<div id="canvasesContainer" style="position: relative; margin: 20px 0; width: auto;">
|
||||
<canvas id="cropPdfCanvas" style="width: 100%"></canvas>
|
||||
<canvas id="overlayCanvas" style="position: absolute; top: 0; left: 0; z-index: 2; width: 100%"></canvas>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script>
|
||||
<script>
|
||||
let pdfCanvas = document.getElementById('crop-pdf-canvas');
|
||||
let pdfCanvas = document.getElementById('cropPdfCanvas');
|
||||
let overlayCanvas = document.getElementById('overlayCanvas');
|
||||
let canvasesContainer = document.getElementById('canvasesContainer');
|
||||
canvasesContainer.style.display = "none";
|
||||
let containerRect = canvasesContainer.getBoundingClientRect();
|
||||
|
||||
let context = pdfCanvas.getContext('2d');
|
||||
let overlayContext = overlayCanvas.getContext('2d');
|
||||
@@ -59,8 +63,11 @@
|
||||
let rectWidth = 0;
|
||||
let rectHeight = 0;
|
||||
|
||||
fileInput.addEventListener('change', function(e) {
|
||||
let file = e.target.files[0];
|
||||
|
||||
let pageScale = 1; // The scale which the pdf page renders
|
||||
let timeId = null; // timeout id for resizing canvases event
|
||||
|
||||
function renderPageFromFile(file) {
|
||||
if (file.type === 'application/pdf') {
|
||||
let reader = new FileReader();
|
||||
reader.onload = function(ev) {
|
||||
@@ -74,6 +81,35 @@
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("resize", function() {
|
||||
clearTimeout(timeId);
|
||||
|
||||
timeId = setTimeout(function () {
|
||||
if (fileInput.files.length == 0) return;
|
||||
let canvasesContainer = document.getElementById('canvasesContainer');
|
||||
let containerRect = canvasesContainer.getBoundingClientRect();
|
||||
|
||||
context.clearRect(0, 0, pdfCanvas.width, pdfCanvas.height);
|
||||
|
||||
overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
|
||||
|
||||
pdfCanvas.width = containerRect.width;
|
||||
pdfCanvas.height = containerRect.height;
|
||||
|
||||
overlayCanvas.width = containerRect.width;
|
||||
overlayCanvas.height = containerRect.height;
|
||||
|
||||
let file = fileInput.files[0];
|
||||
renderPageFromFile(file);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
fileInput.addEventListener('change', function(e) {
|
||||
canvasesContainer.style.display = "block"; // set for visual purposes
|
||||
let file = e.target.files[0];
|
||||
renderPageFromFile(file);
|
||||
});
|
||||
|
||||
cropForm.addEventListener('submit', function(e) {
|
||||
@@ -81,8 +117,8 @@
|
||||
// Ορίστε συντεταγμένες για ολόκληρη την επιφάνεια του PDF
|
||||
xInput.value = 0;
|
||||
yInput.value = 0;
|
||||
widthInput.value = pdfCanvas.width;
|
||||
heightInput.value = pdfCanvas.height;
|
||||
widthInput.value = containerRect.width;
|
||||
heightInput.value = containerRect.height;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -117,10 +153,10 @@
|
||||
|
||||
let flippedY = pdfCanvas.height - e.offsetY;
|
||||
|
||||
xInput.value = startX;
|
||||
yInput.value = flippedY;
|
||||
widthInput.value = rectWidth;
|
||||
heightInput.value = rectHeight;
|
||||
xInput.value = startX / pageScale;
|
||||
yInput.value = flippedY / pageScale;
|
||||
widthInput.value = rectWidth / pageScale;
|
||||
heightInput.value = rectHeight /pageScale;
|
||||
|
||||
// Draw the final rectangle on the main canvas
|
||||
context.strokeStyle = 'red';
|
||||
@@ -131,7 +167,16 @@
|
||||
|
||||
function renderPage(pageNumber) {
|
||||
pdfDoc.getPage(pageNumber).then(function(page) {
|
||||
let viewport = page.getViewport({ scale: 1.0 });
|
||||
let canvasesContainer = document.getElementById('canvasesContainer');
|
||||
let containerRect = canvasesContainer.getBoundingClientRect();
|
||||
|
||||
pageScale = containerRect.width / page.getViewport({ scale: 1 }).width; // The new scale
|
||||
|
||||
let viewport = page.getViewport({ scale: containerRect.width / page.getViewport({ scale: 1 }).width });
|
||||
|
||||
canvasesContainer.width =viewport.width;
|
||||
canvasesContainer.height = viewport.height;
|
||||
|
||||
pdfCanvas.width = viewport.width;
|
||||
pdfCanvas.height = viewport.height;
|
||||
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
<script th:inline="javascript">
|
||||
const currentVersion = /*[[${@appVersion}]]*/ '';
|
||||
const noFavourites = /*[[#{noFavourites}]]*/ '';
|
||||
const updateAvailable = /*[[#{settings.updateAvailable}]]*/ '';
|
||||
console.log(noFavourites);
|
||||
const updateAvailable = /*[[#{settings.updateAvailable}]]*/ '';
|
||||
</script>
|
||||
<script th:src="@{'/js/homecard.js'}"></script>
|
||||
<script th:src="@{'/js/githubVersion.js'}"></script>
|
||||
<nav class="navbar navbar-expand-xl">
|
||||
<div class="container ">
|
||||
@@ -308,10 +310,10 @@
|
||||
</li> -->
|
||||
|
||||
</ul>
|
||||
<ul class="navbar-nav flex-nowrap">
|
||||
<ul class="navbar-nav flex-nowrap">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" id="navbarDropdown-5" href="#" role="button" data-bs-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
aria-haspopup="true" aria-expanded="false" th:title="#{navbar.favorite}">
|
||||
<span class="material-symbols-rounded">
|
||||
star
|
||||
</span>
|
||||
@@ -324,7 +326,7 @@
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="dark-mode-toggle" href="#">
|
||||
<a class="nav-link" id="dark-mode-toggle" href="#" th:title="#{navbar.darkmode}">
|
||||
<span class="material-symbols-rounded" id="dark-mode-icon">
|
||||
dark_mode
|
||||
</span>
|
||||
@@ -333,7 +335,7 @@
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" href="#" id="languageDropdown" role="button" data-bs-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
aria-haspopup="true" aria-expanded="false" th:title="#{navbar.language}">
|
||||
<span class="material-symbols-rounded">
|
||||
language
|
||||
</span>
|
||||
@@ -349,7 +351,7 @@
|
||||
</li>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link" href="#" id="searchDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<a class="nav-link" href="#" id="searchDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" th:title="#{navbar.search}">
|
||||
<span class="material-symbols-rounded">
|
||||
search
|
||||
</span>
|
||||
@@ -358,7 +360,7 @@
|
||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="searchDropdown">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2">
|
||||
<form th:action="@{''}" class="d-flex p-2 search-form" id="searchForm">
|
||||
<input class="form-control search-input" type="search" placeholder="Search" aria-label="Search" id="navbarSearchInput">
|
||||
<input class="form-control search-input" type="search" th:placeholder="#{navbar.search}" aria-label="Search" id="navbarSearchInput">
|
||||
</form>
|
||||
<!-- Search Results -->
|
||||
<div id="searchResults" class="search-results scrollable-y dropdown-mw-20"></div>
|
||||
@@ -368,13 +370,13 @@
|
||||
|
||||
<li class="nav-item" th:if="${!@runningEE}">
|
||||
<a href="https://stirlingpdf.com/pricing" class="nav-link go-pro-link" target="_blank" rel="noopener noreferrer">
|
||||
<span class="go-pro-badge" th:text="#{enterpriseEdition.button}"></span>
|
||||
<span class="go-pro-badge" th:text="#{enterpriseEdition.button}"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<!-- Settings Button -->
|
||||
<a href="#" class="nav-link" data-bs-toggle="modal" data-bs-target="#settingsModal">
|
||||
<a href="#" class="nav-link" data-bs-toggle="modal" data-bs-target="#settingsModal" th:title="#{navbar.settings}">
|
||||
<span class="material-symbols-rounded">
|
||||
settings
|
||||
</span>
|
||||
@@ -405,14 +407,14 @@
|
||||
<p class="mb-0" th:utext="#{settings.appVersion} + ' ' + ${@appVersion}"></p>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 mt-3">
|
||||
<div class="footer-center" style="flex-direction: row;">
|
||||
<a href="https://github.com/Stirling-Tools/Stirling-PDF" class="mx-1" role="button"
|
||||
<a href="https://github.com/Stirling-Tools/Stirling-PDF" class="mx-1" role="button" target="_blank"
|
||||
th:title="#{visitGithub}">
|
||||
<img th:src="@{'/images/github.svg'}" alt="github">
|
||||
</a>
|
||||
<a href="https://hub.docker.com/r/frooodle/s-pdf" class="mx-1" role="button" th:title="#{seeDockerHub}">
|
||||
<a href="https://hub.docker.com/r/frooodle/s-pdf" class="mx-1" role="button" target="_blank"th:title="#{seeDockerHub}">
|
||||
<img th:src="@{'/images/docker.svg'}" alt="docker">
|
||||
</a>
|
||||
<a href="https://discord.gg/Cn8pWhQRxZ" class="mx-1" role="button" th:title="#{joinDiscord}">
|
||||
<a href="https://discord.gg/Cn8pWhQRxZ" class="mx-1" role="button" target="_blank" th:title="#{joinDiscord}">
|
||||
<img th:src="@{'/images/discord.svg'}" alt="discord">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -47,13 +47,53 @@
|
||||
cut
|
||||
</span>
|
||||
</button>
|
||||
<button id="export-button" class="btn btn-primary enable-on-file" onclick="exportPdf()" disabled>
|
||||
<button id="select-pages-container" class="btn btn-secondary enable-on-file"
|
||||
th:title="#{multiTool.selectPages}" onclick="toggleSelectPageVisibility()" disabled>
|
||||
<span id="select-pages-button" class="material-symbols-rounded">
|
||||
event_list
|
||||
</span>
|
||||
</button>
|
||||
<button id="select-All-Container" class="btn btn-secondary enable-on-file hidden"
|
||||
onclick="toggleSelectAll()" disabled>
|
||||
<span th:title="#{multiTool.selectAll}" class="material-symbols-rounded"
|
||||
id="select-icon">select_all</span>
|
||||
<span th:title="#{multiTool.deselectAll}" class="material-symbols-rounded" style="display: none;"
|
||||
id="deselect-icon">deselect</span>
|
||||
</button>
|
||||
<div class=" button-container">
|
||||
<button th:title="#{multiTool.deleteSelected}" id="delete-button" class="btn btn-danger hidden"
|
||||
onclick="deleteSelected()">
|
||||
<span class="material-symbols-rounded">delete</span>
|
||||
</button>
|
||||
</div>
|
||||
<button id="export-selected-button" class="btn btn-primary enable-on-file hidden"
|
||||
onclick="exportPdf(true)" disabled>
|
||||
<span th:title="#{multiTool.downloadSelected}" class="material-symbols-rounded">
|
||||
file_save
|
||||
</span>
|
||||
</button>
|
||||
<button class="btn btn-secondary enable-on-file" onclick="addFilesBlankAll()" disabled>
|
||||
<span class="material-symbols-rounded">
|
||||
insert_page_break
|
||||
</span>
|
||||
</button>
|
||||
<button id="export-button" class="btn btn-primary enable-on-file" onclick="exportPdf(false)" disabled>
|
||||
<span th:title="#{multiTool.downloadAll}" class="material-symbols-rounded">
|
||||
download
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="selected-pages-display" class="selected-pages-container hidden">
|
||||
<div style="display:flex; height:3rem; margin-right:1rem">
|
||||
<h5 th:text="#{multiTool.selectedPages}" style="white-space: nowrap; margin-right: 1rem;">Selected
|
||||
Pages</h5>
|
||||
<input type="text" id="csv-input" class="form-control" style="height:2.5rem" placeholder="1,3,5-10"
|
||||
value="">
|
||||
</div>
|
||||
<ul id="selected-pages-list" class="pages-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="multi-tool-container">
|
||||
<div class="d-flex flex-wrap" id="pages-container-wrapper">
|
||||
<div id="pages-container">
|
||||
@@ -77,6 +117,20 @@
|
||||
</div>
|
||||
<script type="module" th:src="@{'/pdfjs-legacy/pdf.mjs'}"></script>
|
||||
<script th:src="@{'/js/thirdParty/pdf-lib.min.js'}"></script>
|
||||
<script>
|
||||
window.selectedPages = [];
|
||||
window.selectPage = false;
|
||||
window.selectAll = false;
|
||||
const csvInput = document.getElementById("csv-input");
|
||||
csvInput.addEventListener("keydown", function (event) {
|
||||
if (event.key === "Enter") {
|
||||
updatePagesFromCSV();
|
||||
}
|
||||
});
|
||||
csvInput.addEventListener("blur", function () {
|
||||
updatePagesFromCSV();
|
||||
});
|
||||
</script>
|
||||
<script type="module">
|
||||
import PdfContainer from './js/multitool/PdfContainer.js';
|
||||
import DragDropManager from "./js/multitool/DragDropManager.js";
|
||||
@@ -90,7 +144,6 @@
|
||||
// enables the default action buttons on each file
|
||||
const pdfActionsManager = new PdfActionsManager('pages-container');
|
||||
const fileDragManager = new FileDragManager();
|
||||
|
||||
// Scroll the wrapper horizontally
|
||||
|
||||
// Automatically exposes rotateAll, addFiles and exportPdf to the window for the global buttons.
|
||||
|
||||
@@ -30,10 +30,8 @@
|
||||
<!-- Button to download the JSON -->
|
||||
<a href="#" id="downloadJson" class="btn btn-primary mt-3" style="display: none;" th:text="#{getPdfInfo.downloadJson}">Download JSON</a>
|
||||
</div>
|
||||
<script th:src="@{'/js/fetch-utils.js'}"></script>
|
||||
<script>
|
||||
|
||||
import { fetchWithCsrf } from 'js/fetch-utils.js';
|
||||
|
||||
|
||||
document.getElementById("pdfInfoForm").addEventListener("submit", function(event) {
|
||||
event.preventDefault();
|
||||
@@ -156,4 +154,4 @@
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -31,11 +31,13 @@
|
||||
<div class="mb-3 form-check">
|
||||
<input type="checkbox" class="form-check-input" id="includeMetadata" name="includeMetadata">
|
||||
<label class="form-check-label" for="includeMetadata" th:text="#{splitByChapters.includeMetadata}"></label>
|
||||
<input type="hidden" name="includeMetadata" value="false" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3 form-check">
|
||||
<input type="checkbox" class="form-check-input" id="allowDuplicates" name="allowDuplicates">
|
||||
<label class="form-check-label" for="allowDuplicates" th:text="#{splitByChapters.allowDuplicates}"></label>
|
||||
<input type="hidden" name="allowDuplicates" value="false" />
|
||||
</div>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -184,7 +184,7 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||
|
||||
<div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight">
|
||||
<div id="secondaryToolbarButtonContainer">
|
||||
<button id="secondaryOpenFile" class="secondaryToolbarButton" hidden="true" title="Open File" tabindex="51" data-l10n-id="pdfjs-open-file-button">
|
||||
<button id="secondaryOpenFile" class="secondaryToolbarButton visibleMediumView" title="Open File" tabindex="51" data-l10n-id="pdfjs-open-file-button">
|
||||
<span data-l10n-id="pdfjs-open-file-button-label">Open</span>
|
||||
</button>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user