pasteup 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pasteup/__init__.py +3 -0
- pasteup/__main__.py +4 -0
- pasteup/cli.py +171 -0
- pasteup/main.py +34 -0
- pasteup/models/__init__.py +0 -0
- pasteup/models/schemas.py +410 -0
- pasteup/routes/__init__.py +0 -0
- pasteup/routes/jobs.py +678 -0
- pasteup/routes/ui.py +43 -0
- pasteup/services/__init__.py +0 -0
- pasteup/services/cover_collage.py +379 -0
- pasteup/services/exporter.py +113 -0
- pasteup/services/folder_scanner.py +164 -0
- pasteup/services/grid_composer.py +199 -0
- pasteup/services/image_batcher.py +21 -0
- pasteup/services/video_exporter.py +227 -0
- pasteup/shortcut.py +97 -0
- pasteup/static/css/styles.css +983 -0
- pasteup/static/favicon.svg +9 -0
- pasteup/static/fonts/OFL-Caveat.txt +93 -0
- pasteup/static/fonts/OFL-PatrickHand.txt +93 -0
- pasteup/static/fonts/caveat-latin-700.woff2 +0 -0
- pasteup/static/fonts/patrick-hand-latin-400.woff2 +0 -0
- pasteup/static/js/app.js +1680 -0
- pasteup/templates/index.html +309 -0
- pasteup-0.1.0.dist-info/METADATA +481 -0
- pasteup-0.1.0.dist-info/RECORD +32 -0
- pasteup-0.1.0.dist-info/WHEEL +4 -0
- pasteup-0.1.0.dist-info/entry_points.txt +2 -0
- pasteup-0.1.0.dist-info/licenses/LICENSE +202 -0
- pasteup-0.1.0.dist-info/licenses/src/pasteup/static/fonts/OFL-Caveat.txt +93 -0
- pasteup-0.1.0.dist-info/licenses/src/pasteup/static/fonts/OFL-PatrickHand.txt +93 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Pasteup</title>
|
|
7
|
+
<link rel="preload" href="/static/fonts/caveat-latin-700.woff2" as="font" type="font/woff2" crossorigin />
|
|
8
|
+
<link rel="preload" href="/static/fonts/patrick-hand-latin-400.woff2" as="font" type="font/woff2" crossorigin />
|
|
9
|
+
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml" />
|
|
10
|
+
<link rel="stylesheet" href="/static/css/styles.css" />
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<svg class="svg-defs" aria-hidden="true" focusable="false">
|
|
14
|
+
<filter id="sketchy" x="-4%" y="-4%" width="108%" height="108%">
|
|
15
|
+
<feTurbulence type="fractalNoise" baseFrequency="0.018" numOctaves="3" seed="7" result="noise" />
|
|
16
|
+
<feDisplacementMap in="SourceGraphic" in2="noise" scale="5" xChannelSelector="R" yChannelSelector="G" />
|
|
17
|
+
</filter>
|
|
18
|
+
</svg>
|
|
19
|
+
|
|
20
|
+
<a class="skip-link" href="#main">Skip to the steps</a>
|
|
21
|
+
|
|
22
|
+
<header class="masthead">
|
|
23
|
+
<div class="brand">
|
|
24
|
+
<svg class="doodle" viewBox="0 0 48 48" aria-hidden="true">
|
|
25
|
+
<circle cx="13" cy="34.5" r="6.5" />
|
|
26
|
+
<circle cx="13.5" cy="13.5" r="6.5" />
|
|
27
|
+
<path d="M18.6 30.6c7.6-5.3 15.4-11 23.6-17.4" />
|
|
28
|
+
<path d="M19 17.6c7.3 5.6 15.2 11.2 23.4 17.7" />
|
|
29
|
+
<path d="M25.6 24.2l.2.1" />
|
|
30
|
+
</svg>
|
|
31
|
+
<div>
|
|
32
|
+
<h1>Pasteup</h1>
|
|
33
|
+
<p class="brand__tagline">Turn a folder of clip art into listing images.</p>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</header>
|
|
37
|
+
|
|
38
|
+
<main id="main" class="layout">
|
|
39
|
+
<section class="card step step--pick" aria-labelledby="step-1-title">
|
|
40
|
+
<h2 id="step-1-title" class="step__title"><span class="step__number" aria-hidden="true">1</span>Pick your clip art</h2>
|
|
41
|
+
<p id="mode-help" class="step__intro">Point Pasteup at the folder that holds one bundle's images.</p>
|
|
42
|
+
|
|
43
|
+
<fieldset class="mode-toggle">
|
|
44
|
+
<legend class="field-label">What are you making images for?</legend>
|
|
45
|
+
<div class="mode-toggle__options">
|
|
46
|
+
<label class="mode-option">
|
|
47
|
+
<input id="mode-single" type="radio" name="generation-mode" value="single" checked />
|
|
48
|
+
<span class="mode-option__body">
|
|
49
|
+
<span class="mode-option__title">One bundle</span>
|
|
50
|
+
<span class="mode-option__text">A folder of images</span>
|
|
51
|
+
</span>
|
|
52
|
+
</label>
|
|
53
|
+
<label class="mode-option">
|
|
54
|
+
<input id="mode-batch" type="radio" name="generation-mode" value="batch" />
|
|
55
|
+
<span class="mode-option__body">
|
|
56
|
+
<span class="mode-option__title">Many bundles</span>
|
|
57
|
+
<span class="mode-option__text">A folder of bundle folders</span>
|
|
58
|
+
</span>
|
|
59
|
+
</label>
|
|
60
|
+
</div>
|
|
61
|
+
</fieldset>
|
|
62
|
+
|
|
63
|
+
<div class="field">
|
|
64
|
+
<label id="input-folder-label" class="field-label" for="input-folder">Bundle folder</label>
|
|
65
|
+
<input id="input-folder" type="text" value="{{ defaults.input_folder }}" placeholder="e.g. ~/Pictures/clip-art/bundle-01" autocomplete="off" spellcheck="false" aria-describedby="folder-step-copy" />
|
|
66
|
+
</div>
|
|
67
|
+
<div class="field">
|
|
68
|
+
<label id="output-folder-label" class="field-label" for="output-folder">Saves to</label>
|
|
69
|
+
<input id="output-folder" type="text" value="{{ defaults.output_folder }}" readonly aria-readonly="true" aria-describedby="folder-step-copy" />
|
|
70
|
+
<p id="folder-step-copy" class="field-help">Results go in a ---Created--- folder next to it.</p>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div class="actions">
|
|
74
|
+
<button id="scan-button" class="primary-button" type="button">Scan folder</button>
|
|
75
|
+
<p id="mode-step-copy" class="actions__hint">Counts your images and checks they can be read.</p>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<section id="subfolder-picker-section" class="subpanel hidden" hidden aria-labelledby="subfolder-title">
|
|
79
|
+
<h3 id="subfolder-title" class="subhead">Choose folders</h3>
|
|
80
|
+
|
|
81
|
+
<div id="subfolder-single-controls">
|
|
82
|
+
<p class="field-help">This folder has no images of its own, but it has folders inside. Pick one.</p>
|
|
83
|
+
<div class="subfolder-picker-row">
|
|
84
|
+
<div class="field">
|
|
85
|
+
<label class="field-label" for="subfolder-picker">Folder inside</label>
|
|
86
|
+
<select id="subfolder-picker"></select>
|
|
87
|
+
</div>
|
|
88
|
+
<button id="use-subfolder-button" class="secondary-button button-small" type="button">Use this folder</button>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<div id="subfolder-batch-controls" class="hidden" hidden>
|
|
93
|
+
<fieldset class="checklist-fieldset">
|
|
94
|
+
<legend class="field-label">Bundles to include</legend>
|
|
95
|
+
<div id="batch-subfolder-checklist" class="subfolder-checklist" role="group" aria-live="polite"></div>
|
|
96
|
+
</fieldset>
|
|
97
|
+
<div class="actions">
|
|
98
|
+
<button id="select-all-subfolders-button" class="secondary-button button-small" type="button">Select all</button>
|
|
99
|
+
<button id="clear-subfolder-selection-button" class="secondary-button button-small" type="button">Clear</button>
|
|
100
|
+
</div>
|
|
101
|
+
<p id="batch-selection-summary" class="status-line muted-text">Scan the folder of bundles to list them.</p>
|
|
102
|
+
<p id="batch-selection-status" class="status-line" role="status" aria-live="polite">Pick bundles, then check them before making images.</p>
|
|
103
|
+
<div class="actions">
|
|
104
|
+
<button id="batch-scan-button" class="primary-button" type="button">Check selected bundles</button>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</section>
|
|
108
|
+
</section>
|
|
109
|
+
|
|
110
|
+
<section class="card result-panel result-panel--scan" aria-labelledby="scan-result-heading">
|
|
111
|
+
<h2 id="scan-result-heading" class="step__title">
|
|
112
|
+
<svg class="doodle" viewBox="0 0 48 48" aria-hidden="true">
|
|
113
|
+
<circle cx="20" cy="20" r="11.5" />
|
|
114
|
+
<path d="M28.5 28.8c3.6 3.4 7 6.9 10.4 10.6" />
|
|
115
|
+
</svg>
|
|
116
|
+
Folder check
|
|
117
|
+
</h2>
|
|
118
|
+
<div id="scan-result" class="result-card" role="status" aria-live="polite">
|
|
119
|
+
<div class="result-card__header">
|
|
120
|
+
<span class="result-badge result-badge--neutral">Waiting</span>
|
|
121
|
+
<p class="result-message">Scan a folder to see what's in it.</p>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</section>
|
|
125
|
+
|
|
126
|
+
<section class="card step step--page" aria-labelledby="step-2-title">
|
|
127
|
+
<h2 id="step-2-title" class="step__title"><span class="step__number" aria-hidden="true">2</span>Set up the page</h2>
|
|
128
|
+
<p class="step__intro">Used for both the preview sheets and the cover.</p>
|
|
129
|
+
|
|
130
|
+
<div class="field-grid field-grid--page">
|
|
131
|
+
<div class="field">
|
|
132
|
+
<label class="field-label" for="page-width">Width</label>
|
|
133
|
+
<input id="page-width" type="number" value="{{ defaults.page_width }}" min="1" inputmode="decimal" />
|
|
134
|
+
</div>
|
|
135
|
+
<div class="field">
|
|
136
|
+
<label class="field-label" for="page-height">Height</label>
|
|
137
|
+
<input id="page-height" type="number" value="{{ defaults.page_height }}" min="1" inputmode="decimal" />
|
|
138
|
+
</div>
|
|
139
|
+
<div class="field">
|
|
140
|
+
<label class="field-label" for="page-unit">Units</label>
|
|
141
|
+
<select id="page-unit">
|
|
142
|
+
<option value="px" {% if defaults.page_unit == "px" %}selected{% endif %}>pixels</option>
|
|
143
|
+
<option value="in" {% if defaults.page_unit == "in" %}selected{% endif %}>inches</option>
|
|
144
|
+
<option value="mm" {% if defaults.page_unit == "mm" %}selected{% endif %}>mm</option>
|
|
145
|
+
</select>
|
|
146
|
+
</div>
|
|
147
|
+
<div class="field">
|
|
148
|
+
<label class="field-label" for="dpi">DPI</label>
|
|
149
|
+
<input id="dpi" type="number" value="{{ defaults.dpi }}" min="1" max="1200" step="1" aria-describedby="dpi-help" />
|
|
150
|
+
</div>
|
|
151
|
+
<div class="field">
|
|
152
|
+
<label class="field-label" for="format">Format</label>
|
|
153
|
+
<select id="format">
|
|
154
|
+
<option value="JPG" {% if defaults.format == "JPG" %}selected{% endif %}>JPG</option>
|
|
155
|
+
<option value="PNG" {% if defaults.format == "PNG" %}selected{% endif %}>PNG</option>
|
|
156
|
+
</select>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
<p id="dpi-help" class="field-help">DPI is saved in the file, so print software knows its real size. 300 is the usual print resolution.</p>
|
|
160
|
+
|
|
161
|
+
<details class="disclosure">
|
|
162
|
+
<summary>Clean up white backgrounds</summary>
|
|
163
|
+
<div class="disclosure__body">
|
|
164
|
+
<div class="field">
|
|
165
|
+
<label class="field-label" for="background-clean-mode">Near-white backgrounds</label>
|
|
166
|
+
<select id="background-clean-mode" aria-describedby="background-clean-help">
|
|
167
|
+
<option value="off" selected>Leave as they are</option>
|
|
168
|
+
<option value="flatten">Make pure white</option>
|
|
169
|
+
<option value="transparent">Make transparent</option>
|
|
170
|
+
</select>
|
|
171
|
+
<p id="background-clean-help" class="field-help">Only the background touching the image's edges changes, so white details inside your art are safe.</p>
|
|
172
|
+
</div>
|
|
173
|
+
<div id="background-clean-settings" class="field-grid" hidden>
|
|
174
|
+
<div class="field">
|
|
175
|
+
<label class="field-label" for="background-tolerance">Tolerance</label>
|
|
176
|
+
<input id="background-tolerance" type="number" value="240" min="0" max="255" step="1" aria-describedby="background-tolerance-help" />
|
|
177
|
+
<p id="background-tolerance-help" class="field-help">Lower catches greyer backgrounds; too low eats into the art.</p>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="field">
|
|
180
|
+
<label class="field-label" for="background-feather">Edge softening</label>
|
|
181
|
+
<input id="background-feather" type="number" value="1" min="0" max="25" step="1" aria-describedby="background-feather-help" />
|
|
182
|
+
<p id="background-feather-help" class="field-help">Pixels of softening, to hide grey halos.</p>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
</details>
|
|
187
|
+
</section>
|
|
188
|
+
|
|
189
|
+
<section id="output-actions-section" class="card step step--make workflow-step--disabled" aria-labelledby="step-3-title">
|
|
190
|
+
<h2 id="step-3-title" class="step__title"><span class="step__number" aria-hidden="true">3</span>Make your images</h2>
|
|
191
|
+
<p id="output-step-copy" class="step__intro">Preview sheets of every image, or one cover for the listing.</p>
|
|
192
|
+
<p id="output-actions-hint" class="sticky-note" role="status">Scan a folder first. These unlock once it has images.</p>
|
|
193
|
+
|
|
194
|
+
<div class="output-grid">
|
|
195
|
+
<article class="output-tile" aria-labelledby="sheets-title">
|
|
196
|
+
<div class="output-tile__head">
|
|
197
|
+
<svg class="doodle" viewBox="0 0 48 48" aria-hidden="true">
|
|
198
|
+
<path class="doodle__fill" d="M9 7.5c10.2-1 20.3-.6 30.5.5 1 11 .6 22-.5 33-10.4.8-20.6.6-30.5-.5-.9-11-.6-22 .5-33z" />
|
|
199
|
+
<path d="M8.8 19c10.3-.6 20.6-.2 30.9.4M8.6 30c10.4-.5 20.6.2 30.8.6M18.5 7.4c-.5 11-.1 22.4.3 33.6M29 7.6c-.4 11 .2 22.2.4 33.6" />
|
|
200
|
+
</svg>
|
|
201
|
+
<div>
|
|
202
|
+
<h3 id="sheets-title" class="subhead">Preview sheets</h3>
|
|
203
|
+
<p>Every image, twelve to a page.</p>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<details class="disclosure">
|
|
208
|
+
<summary>Spacing</summary>
|
|
209
|
+
<div class="disclosure__body field-grid">
|
|
210
|
+
<div class="field">
|
|
211
|
+
<label class="field-label" for="gap">Gap</label>
|
|
212
|
+
<input id="gap" type="number" value="{{ defaults.gap }}" min="0" />
|
|
213
|
+
</div>
|
|
214
|
+
<div class="field">
|
|
215
|
+
<label class="field-label" for="margin">Margin</label>
|
|
216
|
+
<input id="margin" type="number" value="{{ defaults.margin }}" min="0" />
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
</details>
|
|
220
|
+
|
|
221
|
+
<label class="check">
|
|
222
|
+
<input id="include-partial-page" type="checkbox" />
|
|
223
|
+
<span>Include a part-filled last page</span>
|
|
224
|
+
</label>
|
|
225
|
+
<label class="check">
|
|
226
|
+
<input id="create-preview-video" type="checkbox" aria-describedby="create-preview-video-help" />
|
|
227
|
+
<span>Also make a preview video</span>
|
|
228
|
+
</label>
|
|
229
|
+
<p id="create-preview-video-help" class="field-help">An MP4 slideshow of the sheets, made at the same time.</p>
|
|
230
|
+
<div id="video-settings" class="field-grid" hidden>
|
|
231
|
+
<div class="field">
|
|
232
|
+
<label class="field-label" for="video-duration-seconds">Length (seconds)</label>
|
|
233
|
+
<input id="video-duration-seconds" type="number" value="15" min="1" max="120" step="1" />
|
|
234
|
+
</div>
|
|
235
|
+
<div class="field">
|
|
236
|
+
<label class="field-label" for="video-transition">Transition</label>
|
|
237
|
+
<select id="video-transition">
|
|
238
|
+
<option value="none">None</option>
|
|
239
|
+
<option value="crossfade">Crossfade</option>
|
|
240
|
+
<option value="flip">Flip</option>
|
|
241
|
+
</select>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
|
|
245
|
+
<button id="generate-button" class="secondary-button" type="button" disabled>Make preview sheets</button>
|
|
246
|
+
</article>
|
|
247
|
+
|
|
248
|
+
<article class="output-tile" aria-labelledby="cover-title">
|
|
249
|
+
<div class="output-tile__head">
|
|
250
|
+
<svg class="doodle" viewBox="0 0 48 48" aria-hidden="true">
|
|
251
|
+
<path d="M6 14.5l21-5.2 5 23.8-21 5.2z" />
|
|
252
|
+
<path class="doodle__fill" d="M18.8 17.2l22.4-1.5 1.4 24-22.2 1.4z" />
|
|
253
|
+
<path d="M23.6 35.6l5.4-6.4 4.2 4.1 3.1-3.2 4.3 5" />
|
|
254
|
+
<circle class="doodle__accent" cx="35.4" cy="22.6" r="2.4" />
|
|
255
|
+
</svg>
|
|
256
|
+
<div>
|
|
257
|
+
<h3 id="cover-title" class="subhead">Cover collage</h3>
|
|
258
|
+
<p>One eye-catching cover for the listing.</p>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
|
|
262
|
+
<div class="field">
|
|
263
|
+
<label class="field-label" for="cover-collage-template">Layout</label>
|
|
264
|
+
<select id="cover-collage-template">
|
|
265
|
+
{% for template in cover_collage_templates %}
|
|
266
|
+
<option value="{{ template.value }}">{{ template.label }}</option>
|
|
267
|
+
{% endfor %}
|
|
268
|
+
</select>
|
|
269
|
+
</div>
|
|
270
|
+
|
|
271
|
+
<details class="disclosure">
|
|
272
|
+
<summary>Only use certain images</summary>
|
|
273
|
+
<div class="disclosure__body field">
|
|
274
|
+
<label class="field-label" for="cover-collage-include-list">Cover collage include list</label>
|
|
275
|
+
<textarea id="cover-collage-include-list" rows="3" aria-describedby="cover-include-help" placeholder="cover001.jpg cover002.png"></textarea>
|
|
276
|
+
<p id="cover-include-help" class="field-help">Exact file names, one per line or comma-separated. Leave empty to use any.</p>
|
|
277
|
+
</div>
|
|
278
|
+
</details>
|
|
279
|
+
|
|
280
|
+
<button id="cover-collage-button" class="secondary-button" type="button" disabled>Make cover</button>
|
|
281
|
+
</article>
|
|
282
|
+
</div>
|
|
283
|
+
</section>
|
|
284
|
+
|
|
285
|
+
<section class="card result-panel result-panel--files" aria-labelledby="generation-result-heading">
|
|
286
|
+
<h2 id="generation-result-heading" class="step__title">
|
|
287
|
+
<svg class="doodle" viewBox="0 0 48 48" aria-hidden="true">
|
|
288
|
+
<path d="M10 13.5l24-3.2 3.3 23.8-24 3.3z" />
|
|
289
|
+
<path class="doodle__fill" d="M14.3 17.4l24.4-.6.6 24-24.4.6z" />
|
|
290
|
+
<path d="M19 34.6l5.6-6 4.2 4 3-3 4.5 5" />
|
|
291
|
+
</svg>
|
|
292
|
+
Your files
|
|
293
|
+
</h2>
|
|
294
|
+
<div id="generation-result" class="result-card" role="status" aria-live="polite">
|
|
295
|
+
<div class="result-card__header">
|
|
296
|
+
<span class="result-badge result-badge--neutral">Waiting</span>
|
|
297
|
+
<p class="result-message">Nothing made yet. Your files will be listed here.</p>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
</section>
|
|
301
|
+
</main>
|
|
302
|
+
|
|
303
|
+
<footer class="site-footer">
|
|
304
|
+
<p>Pasteup runs on your computer; your images never leave it. <a href="/docs">API docs</a></p>
|
|
305
|
+
</footer>
|
|
306
|
+
|
|
307
|
+
<script src="/static/js/app.js"></script>
|
|
308
|
+
</body>
|
|
309
|
+
</html>
|