mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-11-09 17:14:16 +01:00
feat: PDF text editor internationalization
This commit is contained in:
1 parent
0f65fdb2f4
commit
7f6bebf21f
27 files changed
+2936
-127
No files matched your search
+17
-2
@@ -9092,7 +9092,15 @@ async function saveFile() {
|
||||
a.click();
|
||||
URL.revokeObjectURL(a.href);
|
||||
state.dirty = false;
|
||||
toast('Saved ' + ((bytes.length / 1024) | 0) + ' KB');
|
||||
const savedKb = (bytes.length / 1024) | 0;
|
||||
if (onSaved) onSaved(savedKb, state.fileName);
|
||||
else toast('Saved ' + savedKb + ' KB');
|
||||
}
|
||||
|
||||
let onSaved = null;
|
||||
|
||||
function setOnSaved(fn) {
|
||||
onSaved = typeof fn === 'function' ? fn : null;
|
||||
}
|
||||
|
||||
function wireUI() {
|
||||
@@ -9975,4 +9983,11 @@ async function addImageFromFile(file) {
|
||||
} else if (state.undo.length) state.undo.pop();
|
||||
}
|
||||
|
||||
export { openFile, engineReady, setZoom, getZoom, getDocDescription };
|
||||
export {
|
||||
openFile,
|
||||
engineReady,
|
||||
setZoom,
|
||||
getZoom,
|
||||
getDocDescription,
|
||||
setOnSaved,
|
||||
};
|
||||
@@ -299,6 +299,13 @@ export function scriptFallbackFamilies(cps) {
|
||||
],
|
||||
[[[0x10a0, 0x10ff]], ['Noto Sans Georgian', 'Sylfaen', 'Arial Unicode MS']],
|
||||
[[[0x1200, 0x137f]], ['Kefa', 'Nyala', 'Noto Sans Ethiopic']],
|
||||
[
|
||||
[[0x0f00, 0x0fff]],
|
||||
['Kailasa', 'Microsoft Himalaya', 'Noto Sans Tibetan'],
|
||||
],
|
||||
[[[0x13a0, 0x13ff]], ['Plantagenet Cherokee', 'Noto Sans Cherokee']],
|
||||
[[[0x0700, 0x074f]], ['Noto Sans Syriac', 'Estrangelo Edessa']],
|
||||
[[[0x0780, 0x07bf]], ['Noto Sans Thaana', 'MV Boli']],
|
||||
];
|
||||
const out = [];
|
||||
for (const cp of cps) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import '@phosphor-icons/web/regular';
|
||||
import { createIcons, icons } from 'lucide';
|
||||
import { showAlert, showLoader, hideLoader } from '../ui.js';
|
||||
import { t } from '../i18n/i18n';
|
||||
import { batchDecryptIfNeeded } from '../utils/password-prompt.js';
|
||||
import { setupFormatDock, setupFindSheet } from './edit-pdf-text-dock';
|
||||
|
||||
@@ -274,6 +275,7 @@ interface EditorAppModule {
|
||||
setZoom: (z: number) => void;
|
||||
getZoom: () => number;
|
||||
getDocDescription: () => DocDescription;
|
||||
setOnSaved: (fn: ((kb: number, fileName: string) => void) | null) => void;
|
||||
}
|
||||
|
||||
function relocateAddText() {
|
||||
@@ -398,6 +400,12 @@ function setupDocPanel() {
|
||||
}
|
||||
|
||||
let appModule: EditorAppModule | null = null;
|
||||
|
||||
function closeEditor() {
|
||||
document.getElementById('text-editor-app')?.setAttribute('hidden', '');
|
||||
document.getElementById('uploader')?.classList.remove('hidden');
|
||||
document.getElementById('tool-landing')?.classList.remove('hidden');
|
||||
}
|
||||
let launching = false;
|
||||
|
||||
function fitMobileWidth() {
|
||||
@@ -428,6 +436,16 @@ async function launchEditor(file: File) {
|
||||
document.getElementById('text-editor-app')?.removeAttribute('hidden');
|
||||
if (!appModule) {
|
||||
appModule = (await import('../editcore/app.js')) as EditorAppModule;
|
||||
appModule.setOnSaved((kb) => {
|
||||
showAlert(
|
||||
t('common.success'),
|
||||
t('tools:editPdfText.saved', { size: kb }),
|
||||
'success',
|
||||
() => {
|
||||
closeEditor();
|
||||
}
|
||||
);
|
||||
});
|
||||
relocateAddText();
|
||||
setupDocPanel();
|
||||
setupEditMenu();
|
||||
@@ -442,10 +460,8 @@ async function launchEditor(file: File) {
|
||||
if (window.matchMedia('(max-width: 768px)').matches) fitMobileWidth();
|
||||
} catch (error) {
|
||||
console.error('Error loading PDF Text Editor:', error);
|
||||
showAlert('Error', 'Failed to load the PDF Text Editor.');
|
||||
document.getElementById('text-editor-app')?.setAttribute('hidden', '');
|
||||
document.getElementById('uploader')?.classList.remove('hidden');
|
||||
document.getElementById('tool-landing')?.classList.remove('hidden');
|
||||
showAlert(t('common.error'), t('tools:editPdfText.failedToLoad'));
|
||||
closeEditor();
|
||||
} finally {
|
||||
hideLoader();
|
||||
launching = false;
|
||||
|
||||
Binary file not shown.
+518
-99
@@ -109,8 +109,8 @@
|
||||
Edit PDF Text
|
||||
</h1>
|
||||
<p class="text-gray-400 mb-6" data-i18n="tools:editPdfText.subtitle">
|
||||
Click any paragraph and edit it in place with live reflow. Move and
|
||||
restyle text, images, and shapes — then save a clean PDF.
|
||||
Click any paragraph and edit it in place with live reflow, fonts, and
|
||||
styling.
|
||||
</p>
|
||||
|
||||
<div
|
||||
@@ -158,7 +158,12 @@
|
||||
1
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<h3 class="text-lg font-semibold text-white mb-1">Upload PDF</h3>
|
||||
<h3
|
||||
class="text-lg font-semibold text-white mb-1"
|
||||
data-i18n="tools:editPdfText.howToUpload"
|
||||
>
|
||||
Upload PDF
|
||||
</h3>
|
||||
<p class="text-gray-400">
|
||||
Select or drag and drop the PDF whose text you want to edit
|
||||
</p>
|
||||
@@ -171,7 +176,10 @@
|
||||
2
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<h3 class="text-lg font-semibold text-white mb-1">
|
||||
<h3
|
||||
class="text-lg font-semibold text-white mb-1"
|
||||
data-i18n="tools:editPdfText.howToClick"
|
||||
>
|
||||
Click a Paragraph
|
||||
</h3>
|
||||
<p class="text-gray-400">
|
||||
@@ -187,7 +195,10 @@
|
||||
3
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<h3 class="text-lg font-semibold text-white mb-1">
|
||||
<h3
|
||||
class="text-lg font-semibold text-white mb-1"
|
||||
data-i18n="tools:editPdfText.howToRestyle"
|
||||
>
|
||||
Restyle Anything
|
||||
</h3>
|
||||
<p class="text-gray-400">
|
||||
@@ -203,7 +214,12 @@
|
||||
4
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<h3 class="text-lg font-semibold text-white mb-1">Save</h3>
|
||||
<h3
|
||||
class="text-lg font-semibold text-white mb-1"
|
||||
data-i18n="common.save"
|
||||
>
|
||||
Save
|
||||
</h3>
|
||||
<p class="text-gray-400">
|
||||
Download a clean PDF with your edits baked in — everything stays
|
||||
on your device
|
||||
@@ -225,15 +241,33 @@
|
||||
href="pdf-editor.html"
|
||||
class="block bg-gray-800 p-4 rounded-lg hover:bg-gray-700 transition-colors border border-gray-700"
|
||||
>
|
||||
<h3 class="text-white font-semibold mb-1">PDF Editor</h3>
|
||||
<p class="text-gray-400 text-sm">Annotate and mark up PDFs</p>
|
||||
<h3
|
||||
class="text-white font-semibold mb-1"
|
||||
data-i18n="tools:pdfEditor.name"
|
||||
>
|
||||
PDF Editor
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 text-sm"
|
||||
data-i18n="tools:editPdfText.relatedPdfEditor"
|
||||
>
|
||||
Annotate and mark up PDFs
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="sign-pdf.html"
|
||||
class="block bg-gray-800 p-4 rounded-lg hover:bg-gray-700 transition-colors border border-gray-700"
|
||||
>
|
||||
<h3 class="text-white font-semibold mb-1">Sign PDF</h3>
|
||||
<p class="text-gray-400 text-sm">
|
||||
<h3
|
||||
class="text-white font-semibold mb-1"
|
||||
data-i18n="tools:signPdf.name"
|
||||
>
|
||||
Sign PDF
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 text-sm"
|
||||
data-i18n="tools:editPdfText.relatedSignPdf"
|
||||
>
|
||||
Draw, type or upload a signature
|
||||
</p>
|
||||
</a>
|
||||
@@ -241,29 +275,69 @@
|
||||
href="add-watermark.html"
|
||||
class="block bg-gray-800 p-4 rounded-lg hover:bg-gray-700 transition-colors border border-gray-700"
|
||||
>
|
||||
<h3 class="text-white font-semibold mb-1">Add Watermark</h3>
|
||||
<p class="text-gray-400 text-sm">Stamp text or images</p>
|
||||
<h3
|
||||
class="text-white font-semibold mb-1"
|
||||
data-i18n="tools:addWatermark.name"
|
||||
>
|
||||
Add Watermark
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 text-sm"
|
||||
data-i18n="tools:editPdfText.relatedWatermark"
|
||||
>
|
||||
Stamp text or images
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="add-stamps.html"
|
||||
class="block bg-gray-800 p-4 rounded-lg hover:bg-gray-700 transition-colors border border-gray-700"
|
||||
>
|
||||
<h3 class="text-white font-semibold mb-1">Add Stamps</h3>
|
||||
<p class="text-gray-400 text-sm">Place stamps on pages</p>
|
||||
<h3
|
||||
class="text-white font-semibold mb-1"
|
||||
data-i18n="tools:addStamps.name"
|
||||
>
|
||||
Add Stamps
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 text-sm"
|
||||
data-i18n="tools:editPdfText.relatedStamps"
|
||||
>
|
||||
Place stamps on pages
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="compress-pdf.html"
|
||||
class="block bg-gray-800 p-4 rounded-lg hover:bg-gray-700 transition-colors border border-gray-700"
|
||||
>
|
||||
<h3 class="text-white font-semibold mb-1">Compress PDF</h3>
|
||||
<p class="text-gray-400 text-sm">Shrink the file size</p>
|
||||
<h3
|
||||
class="text-white font-semibold mb-1"
|
||||
data-i18n="tools:compressPdf.name"
|
||||
>
|
||||
Compress PDF
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 text-sm"
|
||||
data-i18n="tools:editPdfText.relatedCompress"
|
||||
>
|
||||
Shrink the file size
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="organize-pdf.html"
|
||||
class="block bg-gray-800 p-4 rounded-lg hover:bg-gray-700 transition-colors border border-gray-700"
|
||||
>
|
||||
<h3 class="text-white font-semibold mb-1">Organize PDF</h3>
|
||||
<p class="text-gray-400 text-sm">Reorder and manage pages</p>
|
||||
<h3
|
||||
class="text-white font-semibold mb-1"
|
||||
data-i18n="tools:editPdfText.relatedOrganizeName"
|
||||
>
|
||||
Organize PDF
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 text-sm"
|
||||
data-i18n="tools:editPdfText.relatedOrganize"
|
||||
>
|
||||
Reorder and manage pages
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
@@ -321,20 +395,52 @@
|
||||
<div id="text-editor-app" hidden>
|
||||
<div id="toolbar">
|
||||
<div class="tgroup">
|
||||
<button id="exitEditor" class="btn icon" title="Back to upload">
|
||||
<button
|
||||
id="exitEditor"
|
||||
class="btn icon"
|
||||
title="Back to upload"
|
||||
data-i18n-title="tools:editPdfText.tipBackToUpload"
|
||||
>
|
||||
<i class="ph ph-arrow-left"></i>
|
||||
</button>
|
||||
<label class="btn" for="file" title="Open another PDF">
|
||||
<i class="ph ph-folder-open"></i><span>Open</span>
|
||||
<label
|
||||
class="btn"
|
||||
for="file"
|
||||
title="Open another PDF"
|
||||
data-i18n-title="tools:editPdfText.tipOpenAnotherPdf"
|
||||
>
|
||||
<i class="ph ph-folder-open"></i
|
||||
><span data-i18n="tools:editPdfText.open">Open</span>
|
||||
</label>
|
||||
<input id="file" type="file" accept="application/pdf" hidden />
|
||||
<button id="save" class="btn" disabled title="Export (⌘S)">
|
||||
<i class="ph ph-export"></i><span>Export</span>
|
||||
<button
|
||||
id="save"
|
||||
class="btn"
|
||||
disabled
|
||||
title="Export (⌘S)"
|
||||
data-i18n-title="tools:editPdfText.tipExportS"
|
||||
>
|
||||
<i class="ph ph-export"></i
|
||||
><span data-i18n="tools:editPdfText.export">Export</span>
|
||||
</button>
|
||||
<button id="undo" class="btn icon" disabled hidden title="Undo (⌘Z)">
|
||||
<button
|
||||
id="undo"
|
||||
class="btn icon"
|
||||
disabled
|
||||
hidden
|
||||
title="Undo (⌘Z)"
|
||||
data-i18n-title="tools:editPdfText.tipUndoZ"
|
||||
>
|
||||
<i class="ph ph-arrow-u-up-left"></i>
|
||||
</button>
|
||||
<button id="redo" class="btn icon" disabled hidden title="Redo (⇧⌘Z)">
|
||||
<button
|
||||
id="redo"
|
||||
class="btn icon"
|
||||
disabled
|
||||
hidden
|
||||
title="Redo (⇧⌘Z)"
|
||||
data-i18n-title="tools:editPdfText.tipRedoZ"
|
||||
>
|
||||
<i class="ph ph-arrow-u-up-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -343,10 +449,16 @@
|
||||
class="docname"
|
||||
hidden
|
||||
title="File details"
|
||||
data-i18n-title="tools:editPdfText.tipFileDetails"
|
||||
></button>
|
||||
<span class="sep"></span>
|
||||
<div id="tools" class="segmented">
|
||||
<button data-tool="edit" class="on" title="Edit existing content">
|
||||
<button
|
||||
data-tool="edit"
|
||||
class="on"
|
||||
title="Edit existing content"
|
||||
data-i18n-title="tools:editPdfText.tipEditExistingContent"
|
||||
>
|
||||
<i class="ph ph-pencil-simple"></i
|
||||
><span id="editLabel">Edit All</span
|
||||
><i class="ph ph-caret-down editcaret"></i>
|
||||
@@ -355,14 +467,32 @@
|
||||
id="editScope"
|
||||
hidden
|
||||
title="What the Edit tool touches — narrow the scope on busy pages"
|
||||
data-i18n-title="tools:editPdfText.tipWhatTheEditToolTouchesNarrowTheScopeOnBus"
|
||||
>
|
||||
<option value="all" selected>All</option>
|
||||
<option value="text">Text</option>
|
||||
<option value="image">Images</option>
|
||||
<option value="shape">Shapes</option>
|
||||
<option
|
||||
value="all"
|
||||
selected
|
||||
data-i18n="tools:editPdfText.filterAll"
|
||||
>
|
||||
All
|
||||
</option>
|
||||
<option value="text" data-i18n="tools:editPdfText.filterText">
|
||||
Text
|
||||
</option>
|
||||
<option value="image" data-i18n="tools:editPdfText.filterImages">
|
||||
Images
|
||||
</option>
|
||||
<option value="shape" data-i18n="tools:editPdfText.filterShapes">
|
||||
Shapes
|
||||
</option>
|
||||
</select>
|
||||
<button data-tool="addText" title="Click the page to add a text box">
|
||||
<i class="ph ph-textbox"></i><span>Add Text</span>
|
||||
<button
|
||||
data-tool="addText"
|
||||
title="Click the page to add a text box"
|
||||
data-i18n-title="tools:editPdfText.tipClickThePageToAddATextBox"
|
||||
>
|
||||
<i class="ph ph-textbox"></i
|
||||
><span data-i18n="tools:editPdfText.addText">Add Text</span>
|
||||
</button>
|
||||
</div>
|
||||
<input id="imgFile" type="file" accept="image/*" hidden />
|
||||
@@ -370,8 +500,14 @@
|
||||
<label class="chk"
|
||||
><input id="spellchk" type="checkbox" /> Spelling</label
|
||||
>
|
||||
<select id="spellLang" title="Spell-check language">
|
||||
<option value="">Auto</option>
|
||||
<select
|
||||
id="spellLang"
|
||||
title="Spell-check language"
|
||||
data-i18n-title="tools:editPdfText.tipSpellCheckLanguage"
|
||||
>
|
||||
<option value="" data-i18n="tools:editPdfText.langAuto">
|
||||
Auto
|
||||
</option>
|
||||
<option value="en">English (US)</option>
|
||||
<option value="en-GB">English (UK)</option>
|
||||
<option value="de">Deutsch</option>
|
||||
@@ -388,10 +524,20 @@
|
||||
</div>
|
||||
<span id="info" class="info"></span>
|
||||
<div class="tgroup toolright">
|
||||
<button id="find" class="btn icon" title="Find & replace">
|
||||
<button
|
||||
id="find"
|
||||
class="btn icon"
|
||||
title="Find & replace"
|
||||
data-i18n-title="tools:editPdfText.tipFindAndReplace"
|
||||
>
|
||||
<i class="ph ph-magnifying-glass"></i>
|
||||
</button>
|
||||
<button id="addImage" class="btn icon" title="Add an image">
|
||||
<button
|
||||
id="addImage"
|
||||
class="btn icon"
|
||||
title="Add an image"
|
||||
data-i18n-title="tools:editPdfText.tipAddAnImage"
|
||||
>
|
||||
<i class="ph ph-image"></i>
|
||||
</button>
|
||||
<button
|
||||
@@ -399,6 +545,7 @@
|
||||
class="btn icon"
|
||||
hidden
|
||||
title="Copy this page's text in reading order"
|
||||
data-i18n-title="tools:editPdfText.tipCopyThisPageSTextInReadingOrder"
|
||||
>
|
||||
<i class="ph ph-clipboard-text"></i>
|
||||
</button>
|
||||
@@ -407,6 +554,7 @@
|
||||
class="btn icon"
|
||||
hidden
|
||||
title="Check the spelling of this page"
|
||||
data-i18n-title="tools:editPdfText.tipCheckTheSpellingOfThisPage"
|
||||
>
|
||||
<i class="ph ph-text-aa"></i>
|
||||
</button>
|
||||
@@ -415,6 +563,7 @@
|
||||
id="toggleInspector"
|
||||
class="btn icon"
|
||||
title="Show or hide the format panel"
|
||||
data-i18n-title="tools:editPdfText.tipShowOrHideTheFormatPanel"
|
||||
>
|
||||
<i class="ph ph-sidebar-simple"></i>
|
||||
</button>
|
||||
@@ -424,15 +573,44 @@
|
||||
<div id="spellbar" hidden>
|
||||
<i class="ph ph-text-aa barlead"></i>
|
||||
<span id="spellWord" class="info">—</span>
|
||||
<input id="spellFix" placeholder="Replace with" />
|
||||
<button id="spellChange" class="btn">Change</button>
|
||||
<button id="spellIgnore" class="btn">Ignore</button>
|
||||
<button id="spellAdd" class="btn" title="Add to your dictionary">
|
||||
<input
|
||||
id="spellFix"
|
||||
placeholder="Replace with"
|
||||
data-i18n-placeholder="tools:editPdfText.phReplaceWith"
|
||||
/>
|
||||
<button
|
||||
id="spellChange"
|
||||
class="btn"
|
||||
data-i18n="tools:editPdfText.change"
|
||||
>
|
||||
Change
|
||||
</button>
|
||||
<button
|
||||
id="spellIgnore"
|
||||
class="btn"
|
||||
data-i18n="tools:editPdfText.ignore"
|
||||
>
|
||||
Ignore
|
||||
</button>
|
||||
<button
|
||||
id="spellAdd"
|
||||
class="btn"
|
||||
title="Add to your dictionary"
|
||||
data-i18n="common.add"
|
||||
data-i18n-title="tools:editPdfText.tipAddToYourDictionary"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
<button id="spellNext" class="btn">Next</button>
|
||||
<button id="spellNext" class="btn" data-i18n="tools:editPdfText.next">
|
||||
Next
|
||||
</button>
|
||||
<span id="spellStatus" class="info"></span>
|
||||
<button id="spellDone" class="btn icon" title="Close">
|
||||
<button
|
||||
id="spellDone"
|
||||
class="btn icon"
|
||||
title="Close"
|
||||
data-i18n-title="tools:editPdfText.tipClose"
|
||||
>
|
||||
<i class="ph ph-x"></i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -444,23 +622,58 @@
|
||||
><i class="ph ph-magnifying-glass barlead"></i> Find &
|
||||
Replace</span
|
||||
>
|
||||
<button id="findDone" class="btn icon" title="Close">
|
||||
<button
|
||||
id="findDone"
|
||||
class="btn icon"
|
||||
title="Close"
|
||||
data-i18n-title="tools:editPdfText.tipClose"
|
||||
>
|
||||
<i class="ph ph-x"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="findfield">
|
||||
<input id="findText" placeholder="Find" />
|
||||
<button id="findPrev" class="btn icon" title="Previous match">
|
||||
<input
|
||||
id="findText"
|
||||
placeholder="Find"
|
||||
data-i18n-placeholder="tools:editPdfText.phFind"
|
||||
/>
|
||||
<button
|
||||
id="findPrev"
|
||||
class="btn icon"
|
||||
title="Previous match"
|
||||
data-i18n-title="tools:editPdfText.tipPreviousMatch"
|
||||
>
|
||||
<i class="ph ph-caret-up"></i>
|
||||
</button>
|
||||
<button id="findNext" class="btn icon" title="Next match">
|
||||
<button
|
||||
id="findNext"
|
||||
class="btn icon"
|
||||
title="Next match"
|
||||
data-i18n-title="tools:editPdfText.tipNextMatch"
|
||||
>
|
||||
<i class="ph ph-caret-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
<input id="replText" placeholder="Replace with" />
|
||||
<input
|
||||
id="replText"
|
||||
placeholder="Replace with"
|
||||
data-i18n-placeholder="tools:editPdfText.phReplaceWith"
|
||||
/>
|
||||
<div class="findrow">
|
||||
<button id="replOne" class="btn grow">Replace</button>
|
||||
<button id="replAll" class="btn grow">Replace All</button>
|
||||
<button
|
||||
id="replOne"
|
||||
class="btn grow"
|
||||
data-i18n="tools:editPdfText.replace"
|
||||
>
|
||||
Replace
|
||||
</button>
|
||||
<button
|
||||
id="replAll"
|
||||
class="btn grow"
|
||||
data-i18n="tools:editPdfText.replaceAll"
|
||||
>
|
||||
Replace All
|
||||
</button>
|
||||
</div>
|
||||
<label class="chk"
|
||||
><input id="caseSens" type="checkbox" /> Match case</label
|
||||
@@ -476,8 +689,15 @@
|
||||
<div id="stage">
|
||||
<div id="empty">
|
||||
<h1 data-i18n="tools:editPdfText.name">Edit PDF Text</h1>
|
||||
<p>Open a PDF to edit its text, images and shapes.</p>
|
||||
<label class="btn big" for="file">Choose a PDF…</label>
|
||||
<p data-i18n="tools:editPdfText.emptyState">
|
||||
Open a PDF to edit its text, images and shapes.
|
||||
</p>
|
||||
<label
|
||||
class="btn big"
|
||||
for="file"
|
||||
data-i18n="tools:editPdfText.choosePdf"
|
||||
>Choose a PDF…</label
|
||||
>
|
||||
<p class="hint">
|
||||
Everything runs locally in your browser — nothing is uploaded.
|
||||
</p>
|
||||
@@ -495,6 +715,7 @@
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Rotate left 90°"
|
||||
data-i18n-title="tools:editPdfText.tipRotateLeft90"
|
||||
>
|
||||
<i class="ph ph-arrow-counter-clockwise"></i>
|
||||
</button>
|
||||
@@ -503,6 +724,7 @@
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Rotate right 90°"
|
||||
data-i18n-title="tools:editPdfText.tipRotateRight90"
|
||||
>
|
||||
<i class="ph ph-arrow-clockwise"></i>
|
||||
</button>
|
||||
@@ -511,6 +733,7 @@
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Flip horizontal"
|
||||
data-i18n-title="tools:editPdfText.tipFlipHorizontal"
|
||||
>
|
||||
<i class="ph ph-flip-horizontal"></i>
|
||||
</button>
|
||||
@@ -519,6 +742,7 @@
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Flip vertical"
|
||||
data-i18n-title="tools:editPdfText.tipFlipVertical"
|
||||
>
|
||||
<i class="ph ph-flip-vertical"></i>
|
||||
</button>
|
||||
@@ -528,6 +752,7 @@
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Replace this image, keeping its placement"
|
||||
data-i18n-title="tools:editPdfText.tipReplaceThisImageKeepingItsPlacement"
|
||||
>
|
||||
<i class="ph ph-image-square"></i>
|
||||
</button>
|
||||
@@ -544,6 +769,7 @@
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Alternate text for accessibility (tagged PDFs)"
|
||||
data-i18n-title="tools:editPdfText.tipAlternateTextForAccessibilityTaggedPdfs"
|
||||
>
|
||||
<i class="ph ph-tag"></i>
|
||||
</button>
|
||||
@@ -554,6 +780,7 @@
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Bring to front"
|
||||
data-i18n-title="tools:editPdfText.tipBringToFront"
|
||||
>
|
||||
<i class="ph ph-arrow-line-up"></i>
|
||||
</button>
|
||||
@@ -562,39 +789,84 @@
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Send to back"
|
||||
data-i18n-title="tools:editPdfText.tipSendToBack"
|
||||
>
|
||||
<i class="ph ph-arrow-line-down"></i>
|
||||
</button>
|
||||
<button id="dupe" class="btn icon objbtn" hidden title="Duplicate">
|
||||
<button
|
||||
id="dupe"
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Duplicate"
|
||||
data-i18n-title="tools:editPdfText.tipDuplicate"
|
||||
>
|
||||
<i class="ph ph-copy"></i>
|
||||
</button>
|
||||
<button id="del" class="btn icon objbtn" hidden title="Delete">
|
||||
<button
|
||||
id="del"
|
||||
class="btn icon objbtn"
|
||||
hidden
|
||||
title="Delete"
|
||||
data-i18n-title="tools:editPdfText.tipDelete"
|
||||
>
|
||||
<i class="ph ph-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div id="alignTools" class="segmented" hidden>
|
||||
<button data-al="left" title="Align left edges">
|
||||
<button
|
||||
data-al="left"
|
||||
title="Align left edges"
|
||||
data-i18n-title="tools:editPdfText.tipAlignLeftEdges"
|
||||
>
|
||||
<i class="ph ph-align-left"></i>
|
||||
</button>
|
||||
<button data-al="hcenter" title="Align horizontal centers">
|
||||
<button
|
||||
data-al="hcenter"
|
||||
title="Align horizontal centers"
|
||||
data-i18n-title="tools:editPdfText.tipAlignHorizontalCenters"
|
||||
>
|
||||
<i class="ph ph-align-center-horizontal"></i>
|
||||
</button>
|
||||
<button data-al="right" title="Align right edges">
|
||||
<button
|
||||
data-al="right"
|
||||
title="Align right edges"
|
||||
data-i18n-title="tools:editPdfText.tipAlignRightEdges"
|
||||
>
|
||||
<i class="ph ph-align-right"></i>
|
||||
</button>
|
||||
<button data-al="top" title="Align tops">
|
||||
<button
|
||||
data-al="top"
|
||||
title="Align tops"
|
||||
data-i18n-title="tools:editPdfText.tipAlignTops"
|
||||
>
|
||||
<i class="ph ph-align-top"></i>
|
||||
</button>
|
||||
<button data-al="vcenter" title="Align vertical centers">
|
||||
<button
|
||||
data-al="vcenter"
|
||||
title="Align vertical centers"
|
||||
data-i18n-title="tools:editPdfText.tipAlignVerticalCenters"
|
||||
>
|
||||
<i class="ph ph-align-center-vertical"></i>
|
||||
</button>
|
||||
<button data-al="bottom" title="Align bottoms">
|
||||
<button
|
||||
data-al="bottom"
|
||||
title="Align bottoms"
|
||||
data-i18n-title="tools:editPdfText.tipAlignBottoms"
|
||||
>
|
||||
<i class="ph ph-align-bottom"></i>
|
||||
</button>
|
||||
<button data-al="disth" title="Distribute horizontally">
|
||||
<button
|
||||
data-al="disth"
|
||||
title="Distribute horizontally"
|
||||
data-i18n-title="tools:editPdfText.tipDistributeHorizontally"
|
||||
>
|
||||
<i class="ph ph-columns"></i>
|
||||
</button>
|
||||
<button data-al="distv" title="Distribute vertically">
|
||||
<button
|
||||
data-al="distv"
|
||||
title="Distribute vertically"
|
||||
data-i18n-title="tools:editPdfText.tipDistributeVertically"
|
||||
>
|
||||
<i class="ph ph-rows"></i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -602,7 +874,7 @@
|
||||
|
||||
<aside id="inspector" hidden>
|
||||
<h2><i class="ph ph-sliders-horizontal"></i> Format</h2>
|
||||
<h3 class="sect">Font</h3>
|
||||
<h3 class="sect" data-i18n="tools:editPdfText.font">Font</h3>
|
||||
<div class="row">
|
||||
<select id="fFamily"></select>
|
||||
<input
|
||||
@@ -613,6 +885,7 @@
|
||||
step="1"
|
||||
class="num"
|
||||
title="Font size"
|
||||
data-i18n-title="tools:editPdfText.tipFontSize"
|
||||
/>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -620,11 +893,15 @@
|
||||
id="sysFonts"
|
||||
class="btn grow"
|
||||
title="List fonts installed on this device (Chromium)"
|
||||
data-i18n-title="tools:editPdfText.tipListFontsInstalledOnThisDeviceChromium"
|
||||
>
|
||||
<i class="ph ph-download-simple"></i><span>System fonts</span>
|
||||
<i class="ph ph-download-simple"></i
|
||||
><span data-i18n="tools:editPdfText.systemFonts"
|
||||
>System fonts</span
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<h3 class="sect">Color</h3>
|
||||
<h3 class="sect" data-i18n="tools:editPdfText.color">Color</h3>
|
||||
<div class="row swatchrow">
|
||||
<div class="swatches" id="fSwatches"></div>
|
||||
<input
|
||||
@@ -632,57 +909,112 @@
|
||||
type="color"
|
||||
value="#000000"
|
||||
title="Custom text color"
|
||||
data-i18n-title="tools:editPdfText.tipCustomTextColor"
|
||||
/>
|
||||
</div>
|
||||
<h3 class="sect">Alignment</h3>
|
||||
<h3 class="sect" data-i18n="tools:editPdfText.alignment">
|
||||
Alignment
|
||||
</h3>
|
||||
<div class="row">
|
||||
<div class="segmented small grow" id="fAlign">
|
||||
<button data-a="0" title="Align left">
|
||||
<button
|
||||
data-a="0"
|
||||
title="Align left"
|
||||
data-i18n-title="tools:editPdfText.tipAlignLeft"
|
||||
>
|
||||
<i class="ph ph-text-align-left"></i>
|
||||
</button>
|
||||
<button data-a="1" title="Align center">
|
||||
<button
|
||||
data-a="1"
|
||||
title="Align center"
|
||||
data-i18n-title="tools:editPdfText.tipAlignCenter"
|
||||
>
|
||||
<i class="ph ph-text-align-center"></i>
|
||||
</button>
|
||||
<button data-a="2" title="Align right">
|
||||
<button
|
||||
data-a="2"
|
||||
title="Align right"
|
||||
data-i18n-title="tools:editPdfText.tipAlignRight"
|
||||
>
|
||||
<i class="ph ph-text-align-right"></i>
|
||||
</button>
|
||||
<button data-a="3" title="Justify">
|
||||
<button
|
||||
data-a="3"
|
||||
title="Justify"
|
||||
data-i18n-title="tools:editPdfText.tipJustify"
|
||||
>
|
||||
<i class="ph ph-text-align-justify"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="sect">Style</h3>
|
||||
<h3 class="sect" data-i18n="tools:editPdfText.style">Style</h3>
|
||||
<div class="row toggles" id="fToggles">
|
||||
<button data-t="bold" title="Bold">
|
||||
<button
|
||||
data-t="bold"
|
||||
title="Bold"
|
||||
data-i18n-title="tools:editPdfText.tipBold"
|
||||
>
|
||||
<i class="ph ph-text-b"></i>
|
||||
</button>
|
||||
<button data-t="italic" title="Italic">
|
||||
<button
|
||||
data-t="italic"
|
||||
title="Italic"
|
||||
data-i18n-title="tools:editPdfText.tipItalic"
|
||||
>
|
||||
<i class="ph ph-text-italic"></i>
|
||||
</button>
|
||||
<button data-t="underline" title="Underline">
|
||||
<button
|
||||
data-t="underline"
|
||||
title="Underline"
|
||||
data-i18n-title="tools:editPdfText.tipUnderline"
|
||||
>
|
||||
<i class="ph ph-text-underline"></i>
|
||||
</button>
|
||||
<button data-t="strike" title="Strikethrough">
|
||||
<button
|
||||
data-t="strike"
|
||||
title="Strikethrough"
|
||||
data-i18n-title="tools:editPdfText.tipStrikethrough"
|
||||
>
|
||||
<i class="ph ph-text-strikethrough"></i>
|
||||
</button>
|
||||
<button data-t="sup" title="Superscript">
|
||||
<button
|
||||
data-t="sup"
|
||||
title="Superscript"
|
||||
data-i18n-title="tools:editPdfText.tipSuperscript"
|
||||
>
|
||||
<i class="ph ph-text-superscript"></i>
|
||||
</button>
|
||||
<button data-t="sub" title="Subscript">
|
||||
<button
|
||||
data-t="sub"
|
||||
title="Subscript"
|
||||
data-i18n-title="tools:editPdfText.tipSubscript"
|
||||
>
|
||||
<i class="ph ph-text-subscript"></i>
|
||||
</button>
|
||||
</div>
|
||||
<h3 class="sect">Lists</h3>
|
||||
<h3 class="sect" data-i18n="tools:editPdfText.lists">Lists</h3>
|
||||
<div class="row">
|
||||
<div class="segmented small" id="fList">
|
||||
<button data-l="bullet" title="Toggle bulleted item">
|
||||
<button
|
||||
data-l="bullet"
|
||||
title="Toggle bulleted item"
|
||||
data-i18n-title="tools:editPdfText.tipToggleBulletedItem"
|
||||
>
|
||||
<i class="ph ph-list-bullets"></i>
|
||||
</button>
|
||||
<button data-l="number" title="Toggle numbered item">
|
||||
<button
|
||||
data-l="number"
|
||||
title="Toggle numbered item"
|
||||
data-i18n-title="tools:editPdfText.tipToggleNumberedItem"
|
||||
>
|
||||
<i class="ph ph-list-numbers"></i>
|
||||
</button>
|
||||
</div>
|
||||
<select id="fMarkerStyle" title="Numbered-list marker style">
|
||||
<select
|
||||
id="fMarkerStyle"
|
||||
title="Numbered-list marker style"
|
||||
data-i18n-title="tools:editPdfText.tipNumberedListMarkerStyle"
|
||||
>
|
||||
<option value="1">1. 2. 3.</option>
|
||||
<option value="a">a. b. c.</option>
|
||||
<option value="A">A. B. C.</option>
|
||||
@@ -690,21 +1022,30 @@
|
||||
<option value="I">I. II. III.</option>
|
||||
</select>
|
||||
<div class="segmented small" id="fLevel">
|
||||
<button data-lv="-1" title="Decrease list indent (⇧Tab)">
|
||||
<button
|
||||
data-lv="-1"
|
||||
title="Decrease list indent (⇧Tab)"
|
||||
data-i18n-title="tools:editPdfText.tipDecreaseListIndentTab"
|
||||
>
|
||||
<i class="ph ph-text-outdent"></i>
|
||||
</button>
|
||||
<button data-lv="1" title="Increase list indent (Tab)">
|
||||
<button
|
||||
data-lv="1"
|
||||
title="Increase list indent (Tab)"
|
||||
data-i18n-title="tools:editPdfText.tipIncreaseListIndentTab"
|
||||
>
|
||||
<i class="ph ph-text-indent"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="sect">Outline</h3>
|
||||
<h3 class="sect" data-i18n="tools:editPdfText.outline">Outline</h3>
|
||||
<div class="row">
|
||||
<input
|
||||
id="fStrokeColor"
|
||||
type="color"
|
||||
value="#000000"
|
||||
title="Text outline color"
|
||||
data-i18n-title="tools:editPdfText.tipTextOutlineColor"
|
||||
/>
|
||||
<input
|
||||
id="fStrokeW"
|
||||
@@ -714,9 +1055,10 @@
|
||||
step="0.1"
|
||||
class="num"
|
||||
title="Outline width (0 = none)"
|
||||
data-i18n-title="tools:editPdfText.tipOutlineWidth0None"
|
||||
/>
|
||||
</div>
|
||||
<h3 class="sect">Spacing</h3>
|
||||
<h3 class="sect" data-i18n="tools:editPdfText.spacing">Spacing</h3>
|
||||
<label class="field"
|
||||
>Line Spacing
|
||||
<input
|
||||
@@ -787,21 +1129,45 @@
|
||||
step="1"
|
||||
class="num"
|
||||
/></label>
|
||||
<h3 class="sect">Direction</h3>
|
||||
<h3 class="sect" data-i18n="tools:editPdfText.direction">
|
||||
Direction
|
||||
</h3>
|
||||
<div class="row">
|
||||
<div class="segmented small grow" id="fDir">
|
||||
<button data-d="0" title="From content">Auto</button>
|
||||
<button data-d="1" title="Left to right">LTR</button>
|
||||
<button data-d="2" title="Right to left">RTL</button>
|
||||
<button
|
||||
data-d="0"
|
||||
title="From content"
|
||||
data-i18n="tools:editPdfText.dirAuto"
|
||||
data-i18n-title="tools:editPdfText.tipFromContent"
|
||||
>
|
||||
Auto
|
||||
</button>
|
||||
<button
|
||||
data-d="1"
|
||||
title="Left to right"
|
||||
data-i18n-title="tools:editPdfText.tipLeftToRight"
|
||||
>
|
||||
LTR
|
||||
</button>
|
||||
<button
|
||||
data-d="2"
|
||||
title="Right to left"
|
||||
data-i18n-title="tools:editPdfText.tipRightToLeft"
|
||||
>
|
||||
RTL
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="pStrokeRow" hidden>
|
||||
<span class="chk">Path stroke</span>
|
||||
<span class="chk" data-i18n="tools:editPdfText.pathStroke"
|
||||
>Path stroke</span
|
||||
>
|
||||
<input
|
||||
id="pStrokeColor"
|
||||
type="color"
|
||||
value="#000000"
|
||||
title="Stroke color"
|
||||
data-i18n-title="tools:editPdfText.tipStrokeColor"
|
||||
/>
|
||||
<input
|
||||
id="pStrokeW"
|
||||
@@ -811,6 +1177,7 @@
|
||||
step="0.5"
|
||||
class="num"
|
||||
title="Stroke width"
|
||||
data-i18n-title="tools:editPdfText.tipStrokeWidth"
|
||||
/>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -818,22 +1185,47 @@
|
||||
|
||||
<div id="viewbar">
|
||||
<div class="vbzoom">
|
||||
<button id="zoomMenuBtn" class="btn vbzoomlabel" title="Zoom presets">
|
||||
<button
|
||||
id="zoomMenuBtn"
|
||||
class="btn vbzoomlabel"
|
||||
title="Zoom presets"
|
||||
data-i18n-title="tools:editPdfText.tipZoomPresets"
|
||||
>
|
||||
<span id="zoomLabel" class="label">100%</span
|
||||
><i class="ph ph-caret-down editcaret"></i>
|
||||
</button>
|
||||
<button id="zoomOut" class="btn icon" title="Zoom out">
|
||||
<button
|
||||
id="zoomOut"
|
||||
class="btn icon"
|
||||
title="Zoom out"
|
||||
data-i18n-title="tools:editPdfText.tipZoomOut"
|
||||
>
|
||||
<i class="ph ph-minus-circle"></i>
|
||||
</button>
|
||||
<button id="zoomIn" class="btn icon" title="Zoom in">
|
||||
<button
|
||||
id="zoomIn"
|
||||
class="btn icon"
|
||||
title="Zoom in"
|
||||
data-i18n-title="tools:editPdfText.tipZoomIn"
|
||||
>
|
||||
<i class="ph ph-plus-circle"></i>
|
||||
</button>
|
||||
<button id="zoomFit" class="btn icon" title="Fit page">
|
||||
<button
|
||||
id="zoomFit"
|
||||
class="btn icon"
|
||||
title="Fit page"
|
||||
data-i18n-title="tools:editPdfText.tipFitPage"
|
||||
>
|
||||
<i class="ph ph-frame-corners"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="vbcenter">
|
||||
<button id="prev" class="btn icon" title="Previous page">
|
||||
<button
|
||||
id="prev"
|
||||
class="btn icon"
|
||||
title="Previous page"
|
||||
data-i18n-title="tools:editPdfText.tipPreviousPage"
|
||||
>
|
||||
<i class="ph ph-caret-left"></i>
|
||||
</button>
|
||||
<span id="pageLabel" class="label">– / –</span>
|
||||
@@ -844,22 +1236,44 @@
|
||||
min="1"
|
||||
step="1"
|
||||
title="Type a page number and press Enter"
|
||||
data-i18n-title="tools:editPdfText.tipTypeAPageNumberAndPressEnter"
|
||||
/>
|
||||
<span id="pageTotal" class="label pagetotal">/ –</span>
|
||||
<button id="next" class="btn icon" title="Next page">
|
||||
<button
|
||||
id="next"
|
||||
class="btn icon"
|
||||
title="Next page"
|
||||
data-i18n-title="tools:editPdfText.tipNextPage"
|
||||
>
|
||||
<i class="ph ph-caret-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="vbright">
|
||||
<button id="docInfoBtn" class="btn icon" title="Document properties">
|
||||
<button
|
||||
id="docInfoBtn"
|
||||
class="btn icon"
|
||||
title="Document properties"
|
||||
data-i18n-title="tools:editPdfText.tipDocumentProperties"
|
||||
>
|
||||
<i class="ph ph-info"></i>
|
||||
</button>
|
||||
<button id="vbCollapse" class="btn icon" title="Hide bar">
|
||||
<button
|
||||
id="vbCollapse"
|
||||
class="btn icon"
|
||||
title="Hide bar"
|
||||
data-i18n-title="tools:editPdfText.tipHideBar"
|
||||
>
|
||||
<i class="ph ph-caret-double-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button id="vbRestore" class="btn icon" hidden title="Show bar">
|
||||
<button
|
||||
id="vbRestore"
|
||||
class="btn icon"
|
||||
hidden
|
||||
title="Show bar"
|
||||
data-i18n-title="tools:editPdfText.tipShowBar"
|
||||
>
|
||||
<i class="ph ph-caret-double-up"></i>
|
||||
</button>
|
||||
|
||||
@@ -874,7 +1288,11 @@
|
||||
class="bg-gray-800 p-8 rounded-lg flex flex-col items-center gap-4 border border-gray-700 shadow-xl"
|
||||
>
|
||||
<div class="solid-spinner"></div>
|
||||
<p id="loader-text" class="text-white text-lg font-medium">
|
||||
<p
|
||||
id="loader-text"
|
||||
class="text-white text-lg font-medium"
|
||||
data-i18n="loader.processing"
|
||||
>
|
||||
Processing...
|
||||
</p>
|
||||
</div>
|
||||
@@ -898,6 +1316,7 @@
|
||||
<button
|
||||
id="alert-ok"
|
||||
class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-semibold py-2 px-4 rounded-lg transition-colors duration-200"
|
||||
data-i18n="alert.ok"
|
||||
>
|
||||
OK
|
||||
</button>
|
||||
|
||||
Reference in new issue
Block a user