Select does what selecting does in every editor people already know. Double-click bare page and a caret opens there; double-click the document's own words and they open for replacement; what is selected copies with Ctrl+C, pastes with Ctrl+V and goes with Del. Nothing was taken away — a drag on empty page still gathers an area, and a drag that starts on words still selects words to copy. Type text and Edit text were two buttons for one question the click already answers. They are one Text tool: land on the document's own words and it offers to replace them, land anywhere else and it starts new text. The words light up under the cursor so which is which is visible before clicking, not after. The toolbar says what it is for. Select, Text and Sign are labelled and set apart; the drawing kit and the markup kit are their own groups. Sign gets a pen icon over a signature rather than a squiggle that could have been anything. Signatures take ink — black, blue, red, green — chosen while drawing and kept with the signature, because people sign in a particular colour and it belongs to the signature, not to whichever swatch was armed. And they turn: a grip above the box, free rotation, Shift to snap to 15°, for the signing line that is not square to the page. Two faults the tests found, both invisible by eye: The rotate grip was drawn in the right place and could not be grabbed — the selection bar floats directly above a mark, which is exactly where the grip sits, and it swallowed every click. The bar now stands clear of it. Undo would not undo a first rotation. Restoring a mark with Object.assign copies the keys the original HAD, so a property the drag introduced survived the restore; the journal then recorded the rotated state as the state to go back to. Restoring now forgets keys the original never had, which fixes every future property with the same shape. Also: building a document from pictures or joins refuses to start a second one on top of the first, and says so rather than failing quietly.
374 lines
20 KiB
HTML
374 lines
20 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>PDF Editor</title>
|
||
<link rel="stylesheet" href="vendor/pdfjs/web/pdf_viewer.css">
|
||
<link rel="stylesheet" href="editor.css">
|
||
</head>
|
||
<body data-empty="1">
|
||
|
||
<!-- Top bar: document identity on the left, destructive/close actions right.
|
||
Same split as the screenshot editor's topbar. -->
|
||
<div class="topbar">
|
||
<button class="btn wide" id="open" title="Open a PDF (Ctrl+O)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 5h4l1.5 2H14v6H2z"/><path d="M2 5V3h5"/></svg>
|
||
<span>Open</span>
|
||
</button>
|
||
<span class="sep"></span>
|
||
<span class="docname" id="docname">No document</span>
|
||
<span class="spacer"></span>
|
||
<button class="btn wide" id="convert" title="Convert this document to an editable Word file" disabled>
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 2h6l4 4v8H3z"/><path d="M9 2v4h4"/><path d="M5.5 8.5l1 3 1.5-3 1.5 3 1-3"/></svg>
|
||
<span>Convert to Word…</span>
|
||
</button>
|
||
<button class="btn wide primary" id="save" title="Save a copy (Ctrl+S)" disabled>
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v9M4 7l4 4 4-4M2 14h12"/></svg>
|
||
<span>Save a copy</span>
|
||
</button>
|
||
<button class="btn danger" id="discard" title="Close this tab without saving (Esc)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"/></svg>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Tool bar. `.tool-cluster` centres the drawing groups so the view
|
||
controls can right-anchor without the tools crowding the left edge. -->
|
||
<div class="toolbar" id="toolbar">
|
||
<div class="tool-cluster">
|
||
<!-- Three things you do to a document — point at it, write on it, sign it —
|
||
set apart from the drawing kit, which is a kit. -->
|
||
<div class="tgroup primary" role="group" aria-label="Main tools">
|
||
<button class="tool big active" data-tool="select" title="Select (V) — click a mark, drag an area around several; double-click to type or to edit what is there">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 2l4 11 1.6-4.4L13 7z"/></svg>
|
||
<span class="tlabel">Select</span>
|
||
</button>
|
||
<button class="tool big" data-tool="text" title="Text (T) — click the document's own words to replace them, or anywhere else to type new text">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M3 3h10M8 3v10M6 13h4"/></svg>
|
||
<span class="tlabel">Text</span>
|
||
</button>
|
||
<button class="tool big" data-tool="signature" title="Signature (G) — choose one, or draw a new one">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M1.5 12.5c2.2 0 2.6-7 4.2-7s1 6 2.6 6 2-3.5 3-3.5"/>
|
||
<path d="M12.6 2.6l1.8 1.8-4.2 4.2-2.4.6.6-2.4z"/>
|
||
<path d="M2 15h12"/>
|
||
</svg>
|
||
<span class="tlabel">Sign</span>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="tgroup" role="group" aria-label="Draw">
|
||
<button class="tool" data-tool="pen" title="Pen — freehand (P)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 14c1-3 3-6 6-8s5-3 6-3l-3 4c-2 1-4 3-6 4s-2 2-3 3z"/></svg>
|
||
</button>
|
||
<button class="tool" data-tool="line" title="Line (L)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M3 13L13 3"/></svg>
|
||
</button>
|
||
<button class="tool" data-tool="arrow" title="Arrow (A)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3 13L13 3M13 3H8M13 3v5"/></svg>
|
||
</button>
|
||
<button class="tool" data-tool="rect" title="Rectangle (R)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2.5" y="3.5" width="11" height="9"/></svg>
|
||
</button>
|
||
<button class="tool" data-tool="ellipse" title="Ellipse (O)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><ellipse cx="8" cy="8" rx="5.5" ry="4"/></svg>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="tgroup" role="group" aria-label="Mark up text">
|
||
<button class="tool" data-tool="highlight" title="Highlight — drag across text (H)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h10"/><path d="M5 9.5l4.5-6.5 3 2L8 11.5z"/></svg>
|
||
</button>
|
||
<button class="tool" data-tool="underline" title="Underline — drag across text (U)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M4 2v5a4 4 0 0 0 8 0V2"/><path d="M3 14h10"/></svg>
|
||
</button>
|
||
<button class="tool" data-tool="strikeout" title="Strike through — drag across text (K)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M4 3.5h8"/><path d="M8 3.5V12"/><path d="M2.5 8h11"/></svg>
|
||
</button>
|
||
<button class="tool" data-tool="redact" title="Redact — drag a box over content to remove it" data-warn="1">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2.5" y="4.5" width="11" height="7" fill="currentColor"/></svg>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="tgroup" role="group" aria-label="Colours">
|
||
<button class="swatch active" data-color="#ffd400" style="background:#ffd400" title="Yellow"></button>
|
||
<button class="swatch" data-color="#ff3b30" style="background:#ff3b30" title="Red"></button>
|
||
<button class="swatch" data-color="#0aa8ff" style="background:#0aa8ff" title="Blue"></button>
|
||
<button class="swatch" data-color="#2bd97c" style="background:#2bd97c" title="Green"></button>
|
||
<button class="swatch" data-color="#1a1f2b" style="background:#1a1f2b" title="Ink"></button>
|
||
</div>
|
||
|
||
<div class="tgroup" role="group" aria-label="Widths">
|
||
<button class="width" data-width="1.5" title="Thin"><span class="dot" style="width:4px;height:4px"></span></button>
|
||
<button class="width active" data-width="2.5" title="Medium"><span class="dot" style="width:7px;height:7px"></span></button>
|
||
<button class="width" data-width="4.5" title="Thick"><span class="dot" style="width:11px;height:11px"></span></button>
|
||
<button class="btn" id="toggle-fill" title="Fill shapes as well as outline them">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2.5" y="3.5" width="11" height="9"/><path d="M2.5 9.5h11v3h-11z" fill="currentColor" stroke="none"/></svg>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="tgroup" role="group" aria-label="History">
|
||
<button class="btn" id="undo" title="Undo (Ctrl+Z)" disabled>
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M3 8c0-3 2-5 5-5s5 2 5 5-2 5-5 5"/><path d="M6 5L3 8l3 3"/></svg>
|
||
</button>
|
||
<button class="btn" id="redo" title="Redo (Ctrl+Shift+Z)" disabled>
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M13 8c0-3-2-5-5-5S3 5 3 8s2 5 5 5"/><path d="M10 5l3 3-3 3"/></svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tgroup zoomgroup" role="group" aria-label="Zoom">
|
||
<button class="btn" id="zoom-out" title="Zoom out (−)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M3 8h10"/></svg>
|
||
</button>
|
||
<select id="zoom" title="Zoom">
|
||
<option value="page-width">Fit width</option>
|
||
<option value="page-fit">Fit page</option>
|
||
<option value="0.5">50%</option>
|
||
<option value="0.75">75%</option>
|
||
<option value="1">100%</option>
|
||
<option value="1.25">125%</option>
|
||
<option value="1.5">150%</option>
|
||
<option value="2">200%</option>
|
||
<option value="4">400%</option>
|
||
</select>
|
||
<button class="btn" id="zoom-in" title="Zoom in (+)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M8 3v10M3 8h10"/></svg>
|
||
</button>
|
||
<button class="btn" id="toggle-rail" title="Show or hide the page thumbnails">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="7" height="12"/><rect x="11" y="2" width="3" height="5"/><rect x="11" y="9" width="3" height="5"/></svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="body">
|
||
<!-- Scroll container. pdf.js's own CSS keys off #viewer .page, and reads
|
||
--scale-factor from the container, so the structure below mirrors what
|
||
the pdf.js viewer builds. -->
|
||
<div class="viewerContainer" id="viewerContainer">
|
||
<div id="viewer" class="pdfViewer"></div>
|
||
|
||
<div class="dropzone" id="dropzone">
|
||
<div class="dz-inner">
|
||
<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M12 6h16l8 8v28H12z"/><path d="M28 6v8h8"/><path d="M24 22v12M19 29l5 5 5-5"/>
|
||
</svg>
|
||
<div class="dz-title">Drop a PDF here</div>
|
||
<div class="dz-sub">Drop pictures instead and they become the pages. Drop several PDFs and they join up.</div>
|
||
<div class="dz-actions">
|
||
<button class="tile" id="start-open" type="button">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M6 3h8l4 4v14H6z"/><path d="M14 3v4h4"/><path d="M9 12h6M9 16h6"/>
|
||
</svg>
|
||
<span class="tile-t">Open a PDF</span>
|
||
<span class="tile-s">Read it, mark it up, fill it in, sign it</span>
|
||
</button>
|
||
<button class="tile" id="start-images" type="button">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||
<rect x="3" y="5" width="14" height="11" rx="1.5"/><circle cx="7.5" cy="9" r="1.3"/>
|
||
<path d="M3.5 14l3.5-3 3 2.5 2.5-2 4 4.5"/><path d="M19 9v10H8"/>
|
||
</svg>
|
||
<span class="tile-t">Pictures to PDF</span>
|
||
<span class="tile-s">One page per picture, in the order you pick</span>
|
||
</button>
|
||
<button class="tile" id="start-merge" type="button">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M4 4h7v7H4z"/><path d="M13 13h7v7h-7z"/><path d="M11 7.5h4a2 2 0 0 1 2 2V13"/><path d="M15 11l2 2 2-2"/>
|
||
</svg>
|
||
<span class="tile-t">Join PDFs</span>
|
||
<span class="tile-s">Several files, end to end, as one document</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Page rail. Thumbnails are draggable to reorder; each carries rotate
|
||
and delete buttons. -->
|
||
<aside class="rail" id="rail">
|
||
<div class="rail-head">
|
||
<span id="rail-count">0 pages</span>
|
||
<button class="fbtn" id="restore-pages" hidden title="Bring back every deleted page">Undo deletes</button>
|
||
</div>
|
||
<div class="rail-list" id="rail-list"></div>
|
||
</aside>
|
||
</div>
|
||
|
||
<div class="footer">
|
||
<span class="fstat" id="status">Ready</span>
|
||
<span class="spacer"></span>
|
||
<span class="fstat" id="pageinfo"></span>
|
||
</div>
|
||
|
||
<!-- Modal shell, reused by the redaction warning, the signature pad and the
|
||
text-stamp prompt. One at a time; `data-modal` names the open one. -->
|
||
<div class="scrim" id="scrim" hidden>
|
||
<div class="modal" id="modal-redact" hidden>
|
||
<h2>About redaction</h2>
|
||
<p>A redaction box hides content visually. On its own it does <strong>not</strong> remove the
|
||
text underneath, which stays extractable by anyone who copies from the file.</p>
|
||
<p>To actually remove it, this editor rebuilds each redacted page as an image when you save.
|
||
That page's text stops being selectable and any form fields on it become static. Pages you
|
||
did not redact are untouched.</p>
|
||
<label class="check"><input type="checkbox" id="redact-flatten" checked>
|
||
<span>Rebuild redacted pages as images when saving (recommended)</span></label>
|
||
<div class="mrow">
|
||
<button class="btn wide" id="redact-cancel">Cancel</button>
|
||
<button class="btn wide primary" id="redact-ok">Use the redaction tool</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal" id="modal-sign" hidden>
|
||
<h2 id="sign-title">Your signatures</h2>
|
||
|
||
<!-- The library. Each one is stored as lines, not a picture, so a
|
||
thumbnail is the same drawing at a smaller size. -->
|
||
<div id="sign-library">
|
||
<p class="mhint">Pick one to place, or draw another. They are kept in this browser,
|
||
as lines rather than pictures, so they stay sharp at any size.</p>
|
||
<ul class="siglist" id="sign-list"></ul>
|
||
<p class="mhint" id="sign-empty" hidden>Nothing saved yet.</p>
|
||
<div class="mrow">
|
||
<button class="btn wide" id="sign-new">Draw a new one</button>
|
||
<span class="spacer"></span>
|
||
<button class="btn wide" id="sign-close">Cancel</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- The pad, shown for a new signature or to redraw an existing one. -->
|
||
<div id="sign-draw" hidden>
|
||
<p class="mhint">Draw in the box. The line under it is a guide, not part of what is saved.</p>
|
||
<div class="sigink" id="sign-colors" role="group" aria-label="Ink colour">
|
||
<button class="swatch active" data-ink="#101418" style="background:#101418" title="Black"></button>
|
||
<button class="swatch" data-ink="#1c4ed8" style="background:#1c4ed8" title="Blue"></button>
|
||
<button class="swatch" data-ink="#c81e1e" style="background:#c81e1e" title="Red"></button>
|
||
<button class="swatch" data-ink="#166534" style="background:#166534" title="Green"></button>
|
||
</div>
|
||
<canvas id="sign-pad" width="640" height="220"></canvas>
|
||
<label class="mfield block">Name
|
||
<input type="text" id="sign-name" spellcheck="false" placeholder="Signature">
|
||
</label>
|
||
<div class="mrow">
|
||
<button class="btn wide" id="sign-clear">Clear</button>
|
||
<span class="spacer"></span>
|
||
<button class="btn wide" id="sign-cancel">Back</button>
|
||
<button class="btn wide primary" id="sign-ok" disabled>Save</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal" id="modal-text" hidden>
|
||
<h2 id="modal-text-title">Text stamp</h2>
|
||
<textarea id="text-body" rows="4" placeholder="Type the text to place…"></textarea>
|
||
<div class="mrow">
|
||
<label class="mfield" id="text-size-field">Size
|
||
<select id="text-size">
|
||
<option value="8">8</option><option value="10">10</option>
|
||
<option value="12" selected>12</option><option value="14">14</option>
|
||
<option value="18">18</option><option value="24">24</option>
|
||
<option value="36">36</option><option value="48">48</option><option value="72">72</option>
|
||
</select>
|
||
</label>
|
||
<button class="btn styl" id="text-bold" type="button" title="Bold"><b>B</b></button>
|
||
<button class="btn styl" id="text-italic" type="button" title="Italic"><i>I</i></button>
|
||
<span class="spacer"></span>
|
||
<button class="btn wide" id="text-cancel">Cancel</button>
|
||
<button class="btn wide primary" id="text-ok">Place</button>
|
||
</div>
|
||
<p class="mhint" id="text-note" hidden></p>
|
||
<p class="mhint" id="text-warn" hidden></p>
|
||
</div>
|
||
|
||
<div class="modal" id="modal-convert" hidden>
|
||
<h2>Convert to Word</h2>
|
||
<p>A PDF stores glyphs with coordinates, not paragraphs. Converting means working out
|
||
where the paragraphs were, so the result is a <strong>rebuilt</strong> document that reads
|
||
the same rather than a copy that looks the same.</p>
|
||
<label class="mfield block">File name
|
||
<input type="text" id="convert-name" spellcheck="false">
|
||
</label>
|
||
<ul class="summary" id="convert-summary"></ul>
|
||
<div class="mrow">
|
||
<span class="spacer"></span>
|
||
<button class="btn wide" id="convert-cancel">Cancel</button>
|
||
<button class="btn wide primary" id="convert-go">Convert</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal" id="modal-images" hidden>
|
||
<h2>Pictures to PDF</h2>
|
||
<p id="images-count"></p>
|
||
<div class="mrow">
|
||
<label class="mfield">Page
|
||
<select id="images-page">
|
||
<option value="fit" selected>Shaped like the picture</option>
|
||
<option value="a4">A4</option>
|
||
<option value="letter">Letter</option>
|
||
</select>
|
||
</label>
|
||
<label class="mfield" id="images-margin-field">Border
|
||
<select id="images-margin">
|
||
<option value="0">None</option>
|
||
<option value="18" selected>Narrow</option>
|
||
<option value="48">Wide</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
<p class="mhint" id="images-note"></p>
|
||
<div class="mrow">
|
||
<span class="spacer"></span>
|
||
<button class="btn wide" id="images-cancel">Cancel</button>
|
||
<button class="btn wide primary" id="images-go">Make the PDF</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal" id="modal-save" hidden>
|
||
<h2>Save a copy</h2>
|
||
<label class="mfield block">File name
|
||
<input type="text" id="save-name" spellcheck="false">
|
||
</label>
|
||
<ul class="summary" id="save-summary"></ul>
|
||
<div class="mrow">
|
||
<span class="spacer"></span>
|
||
<button class="btn wide" id="save-cancel">Cancel</button>
|
||
<button class="btn wide primary" id="save-go">Save</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Pinned to the current selection; see paintSelectionBar in editor.js. -->
|
||
<div class="selbar" id="selbar" hidden>
|
||
<button class="sb" id="sb-edit" title="Edit this text (or double-click it)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M11 2.5l2.5 2.5L6 12.5 3 13l.5-3z"/></svg>
|
||
</button>
|
||
<span class="sb-group" id="sb-textsize">
|
||
<button class="sb" id="sb-smaller" title="Smaller">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M3.5 8h9"/></svg>
|
||
</button>
|
||
<span class="sb-val" id="sb-size">12</span>
|
||
<button class="sb" id="sb-bigger" title="Bigger">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M8 3.5v9M3.5 8h9"/></svg>
|
||
</button>
|
||
</span>
|
||
<button class="sb" id="sb-bold" title="Bold"><b>B</b></button>
|
||
<button class="sb" id="sb-italic" title="Italic"><i>I</i></button>
|
||
<button class="sb" id="sb-fill" title="Fill">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2.5" y="3.5" width="11" height="9"/><path d="M2.5 9.5h11v3h-11z" fill="currentColor" stroke="none"/></svg>
|
||
</button>
|
||
<span class="sb-sep"></span>
|
||
<button class="sb" id="sb-dup" title="Duplicate">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="5.5" y="5.5" width="8" height="8" rx="1"/><path d="M3.5 10.5V3a1 1 0 0 1 1-1H11"/></svg>
|
||
</button>
|
||
<button class="sb danger" id="sb-del" title="Delete (Del)">
|
||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4h10"/><path d="M6 4V2h4v2"/><path d="M4 4l1 10h6l1-10"/><path d="M7 6.5v5M9 6.5v5"/></svg>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="toast" id="toast"></div>
|
||
<input type="file" id="file-input" accept="application/pdf,.pdf" hidden>
|
||
<input type="file" id="img-input" accept="image/*" multiple hidden>
|
||
<input type="file" id="merge-input" accept="application/pdf,.pdf" multiple hidden>
|
||
<a id="download-link" style="display:none"></a>
|
||
|
||
<script type="module" src="editor.js"></script>
|
||
</body>
|
||
</html>
|