jekyll-svg-viewer 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9b423f13d884102e617b015c130a8e148fa6705207fac8a18388b119d4b02c17
4
+ data.tar.gz: a8cb6bc9f3374def84a1319fe36a4160d6de1d455560e6f9294ed4f68dff86d2
5
+ SHA512:
6
+ metadata.gz: d7cbe553daa442c19b74f96571f58a0fb79ff56318ce5b9a08390c13c61286c4db8075080adfadda164b6362ef3fa735723ade45cddaddb46544a8d462327542
7
+ data.tar.gz: f25d77bcc9657fec50e343ce0973b7f0846aff491638f2d932466da7c10737f24b4488d6bf16ff7c154f3ffa3fae7d9131ba50c0fffca4d1ea2b0924ec9962c3
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Brett Terpstra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # jekyll-svg-viewer
2
+
3
+ `jekyll-svg-viewer` brings the **WP SVG Viewer** frontend to static Jekyll sites. It ships a Liquid tag for rendering interactive SVG diagrams, automatically injects the required JavaScript/CSS, mirrors the shortcode options from the WordPress plugin, and includes a standalone preset builder page for crafting configurations. Source code lives at [github.com/ttscoff/jekyll-svg-viewer](https://github.com/ttscoff/jekyll-svg-viewer).
4
+
5
+ ## Installation
6
+
7
+ 1. Add the published gem to your Jekyll site:
8
+
9
+ ```ruby
10
+ # Gemfile
11
+ gem "jekyll-svg-viewer"
12
+ ```
13
+
14
+ > Need the latest unreleased changes? Point Bundler at GitHub instead:
15
+ >
16
+ > ```ruby
17
+ > gem "jekyll-svg-viewer", github: "ttscoff/jekyll-svg-viewer"
18
+ > ```
19
+
20
+ 2. Enable the plugin:
21
+
22
+ ```yaml
23
+ # _config.yml
24
+ plugins:
25
+ - jekyll-svg-viewer
26
+ ```
27
+
28
+ 3. Run `bundle install`, then build or serve your site as usual (`bundle exec jekyll build` / `bundle exec jekyll serve`). The viewer assets are copied into `_site/assets/svg-viewer/` as part of the build.
29
+
30
+ ## Liquid Tag Usage
31
+
32
+ Place the `svg_viewer` tag anywhere Liquid tags are supported:
33
+
34
+ ```liquid
35
+ {% svg_viewer src="/assets/maps/campus.svg" height="75vh" controls_buttons="compact,alignright,zoom_in,zoom_out,center" zoom="140" %}
36
+ ```
37
+
38
+ All shortcode options from the WordPress version are supported. Common attributes include:
39
+
40
+ | Attribute | Purpose |
41
+ | --------------------------------------------------- | --------------------------------------------------------------------------------------- |
42
+ | `src` | **Required.** Absolute URL or site-root relative path to the SVG. |
43
+ | `height` | Viewer height (e.g. `600px`, `80vh`). |
44
+ | `zoom`, `min_zoom`, `max_zoom`, `zoom_step` | Initial zoom, min/max bounds, and button increment (percentages). |
45
+ | `center_x`, `center_y` | Lock the default viewport to explicit SVG coordinates. |
46
+ | `show_coords` | `true` enables the coordinate helper button. |
47
+ | `controls_position` | `top`, `bottom`, `left`, or `right`. |
48
+ | `controls_buttons` | Comma-delimited layout keywords and button names (e.g. `both,alignleft,zoom_in,reset`). |
49
+ | `button_fill`, `button_border`, `button_foreground` | Hex colors mapped to CSS custom properties for the buttons. |
50
+ | `pan_mode`, `zoom_mode` | Advanced gesture overrides (`scroll`, `drag`, `click`). |
51
+ | `title`, `caption` | Optional markup rendered above/below the viewer wrapper. |
52
+
53
+ Any attribute omitted from the tag falls back to `_config.yml` defaults (see below).
54
+
55
+ ## Site-wide Defaults
56
+
57
+ Configure default values in `_config.yml` under `svg_viewer.defaults`. The builder’s YAML modal emits the same structure.
58
+
59
+ ```yaml
60
+ svg_viewer:
61
+ defaults:
62
+ height: "600px"
63
+ zoom: "100"
64
+ min_zoom: "25"
65
+ max_zoom: "800"
66
+ zoom_step: "10"
67
+ controls_position: "top"
68
+ controls_buttons: "both"
69
+ pan_mode: ""
70
+ zoom_mode: ""
71
+ show_coords: false
72
+ ```
73
+
74
+ Only fields you override are required. `src`, `center_x`, and `center_y` remain per-tag settings.
75
+
76
+ ## Screenshots
77
+
78
+ ![Preset Editor](images/preset-editor.jpg "Preset Editor")
79
+
80
+ ![Front End Rendering](images/front-end.jpg "Front End Rendering")
81
+
82
+ ## Localized Assets & Automatic Injection
83
+
84
+ The gem copies the viewer script, stylesheet, and localization JSON into `_site/assets/svg-viewer/`. Whenever a page renders `{% svg_viewer %}`, the plugin:
85
+
86
+ - Marks the document so the CSS/JS tags are injected into `<head>` once during `post_render`.
87
+ - Ensures the asset files exist by the `post_write` phase.
88
+
89
+ You don’t need to manually edit layouts or partials—the assets appear only on pages that use the tag.
90
+
91
+ ## Preset Builder Page
92
+
93
+ The plugin also generates a preset editor at `/svg-viewer/preset-builder/`. It mirrors the WordPress admin experience:
94
+
95
+ - Enter an SVG path, tweak zoom/controls/colors, and load a live preview.
96
+ - Capture the current viewport to populate `center_x` / `center_y`.
97
+ - Copy a ready-to-use Liquid tag.
98
+ - Generate a `_config.yml` snippet (excluding `src` and the captured center) inside a modal dialog.
99
+
100
+ This is the quickest way to dial in viewer options without memorizing every attribute.
101
+
102
+ ## Development Notes
103
+
104
+ - The gemspec bundles the compiled frontend assets. If you update `wp-svg-viewer/js/svg-viewer.js` or related CSS, re-copy them into `jekyll-svg-viewer/assets/svg-viewer/`.
105
+ - The preset builder JavaScript (`assets/svg-viewer/preview/preset-builder.js`) is framework-free and mirrors the PHP logic used by the WordPress plugin.
106
+ - A minimal smoke-test site is available in `example_site/`. Run `scripts/build-example.sh` to install dependencies and build it locally.
107
+
108
+ ## License
109
+
110
+ MIT © Brett Terpstra
@@ -0,0 +1,439 @@
1
+ /* SVG Viewer Plugin Styles */
2
+
3
+ .svg-viewer-wrapper {
4
+ display: flex;
5
+ flex-direction: column;
6
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
7
+ Ubuntu, Cantarell, sans-serif;
8
+ border: 1px solid #ddd;
9
+ border-radius: 4px;
10
+ overflow: hidden;
11
+ background-color: #fff;
12
+ --svg-viewer-button-fill: #0073aa;
13
+ --svg-viewer-button-hover: #005a87;
14
+ --svg-viewer-button-border: #0073aa;
15
+ --svg-viewer-button-text: #fff;
16
+ width: 100%;
17
+ max-width: 100%;
18
+ min-width: 0;
19
+ contain: layout inline-size;
20
+ margin-bottom: 1em;
21
+ }
22
+
23
+ .svg-viewer-main {
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: 0;
27
+ width: 100%;
28
+ min-width: 0;
29
+ contain: inline-size;
30
+ }
31
+
32
+ .svg-viewer-main.controls-position-bottom {
33
+ flex-direction: column-reverse;
34
+ }
35
+
36
+ .svg-viewer-main.controls-position-left {
37
+ flex-direction: row;
38
+ }
39
+
40
+ .svg-viewer-main.controls-position-right {
41
+ flex-direction: row-reverse;
42
+ }
43
+
44
+ .svg-viewer-main.controls-position-left,
45
+ .svg-viewer-main.controls-position-right {
46
+ align-items: stretch;
47
+ }
48
+
49
+ .svg-viewer-main.controls-position-left .svg-controls,
50
+ .svg-viewer-main.controls-position-right .svg-controls {
51
+ flex: 0 0 auto;
52
+ }
53
+
54
+ .svg-viewer-main > .svg-container {
55
+ flex: 1 1 auto;
56
+ min-width: 0;
57
+ max-width: 100%;
58
+ }
59
+
60
+ .svg-viewer-title,
61
+ .svg-viewer-caption {
62
+ text-align: center;
63
+ font-weight: 600;
64
+ margin: 0;
65
+ padding: 12px 16px;
66
+ }
67
+
68
+ .svg-viewer-interaction-caption {
69
+ font-weight: 400;
70
+ font-size: 0.9em;
71
+ color: #555;
72
+ background-color: #fafafa;
73
+ }
74
+
75
+ .svg-viewer-title {
76
+ border-bottom: 1px solid #ddd;
77
+ }
78
+
79
+ .svg-controls {
80
+ display: flex;
81
+ gap: 10px;
82
+ padding: 15px;
83
+ background-color: #f5f5f5;
84
+ border-bottom: 1px solid #ddd;
85
+ flex-wrap: wrap;
86
+ align-items: center;
87
+ justify-content: flex-start;
88
+ }
89
+
90
+ .svg-viewer-main.controls-position-bottom .svg-controls {
91
+ border-top: 1px solid #ddd;
92
+ border-bottom: none;
93
+ }
94
+
95
+ .svg-viewer-main.controls-position-left .svg-controls,
96
+ .svg-viewer-main.controls-position-right .svg-controls {
97
+ border-bottom: none;
98
+ align-items: flex-start;
99
+ justify-content: center;
100
+ }
101
+
102
+ .svg-viewer-main.controls-position-left.controls-align-alignleft .svg-controls,
103
+ .svg-viewer-main.controls-position-right.controls-align-alignleft
104
+ .svg-controls {
105
+ align-items: flex-start;
106
+ }
107
+
108
+ .svg-viewer-main.controls-position-left.controls-align-alignright .svg-controls,
109
+ .svg-viewer-main.controls-position-right.controls-align-alignright
110
+ .svg-controls {
111
+ align-items: flex-end;
112
+ }
113
+
114
+ .svg-viewer-main.controls-position-left.controls-align-aligncenter
115
+ .svg-controls,
116
+ .svg-viewer-main.controls-position-right.controls-align-aligncenter
117
+ .svg-controls {
118
+ align-items: center;
119
+ }
120
+
121
+ .svg-viewer-main.controls-position-left .svg-controls {
122
+ border-right: 1px solid #ddd;
123
+ }
124
+
125
+ .svg-viewer-main.controls-position-right .svg-controls {
126
+ border-left: 1px solid #ddd;
127
+ }
128
+
129
+ .svg-controls.controls-vertical {
130
+ flex-direction: column;
131
+ gap: 12px;
132
+ align-items: stretch;
133
+ }
134
+
135
+ .svg-controls .zoom-slider-wrapper {
136
+ display: inline-flex;
137
+ align-items: center;
138
+ width: var(--svg-viewer-slider-width, 240px);
139
+ padding: 0 4px;
140
+ }
141
+
142
+ .svg-controls.controls-mode-icon .zoom-slider-wrapper {
143
+ width: var(--svg-viewer-slider-width-icon, 200px);
144
+ }
145
+
146
+ .svg-controls.controls-vertical .zoom-slider-wrapper {
147
+ width: 100%;
148
+ }
149
+
150
+ .svg-controls .zoom-slider {
151
+ width: 100%;
152
+ height: 6px;
153
+ appearance: none;
154
+ -webkit-appearance: none;
155
+ background: var(--svg-viewer-slider-track, rgba(0, 0, 0, 0.15));
156
+ border-radius: 999px;
157
+ outline: none;
158
+ }
159
+
160
+ .svg-controls .zoom-slider::-webkit-slider-thumb {
161
+ -webkit-appearance: none;
162
+ appearance: none;
163
+ width: 18px;
164
+ height: 18px;
165
+ border-radius: 50%;
166
+ background: var(--svg-viewer-button-fill, #0073aa);
167
+ border: 2px solid var(--svg-viewer-button-border, #0073aa);
168
+ cursor: pointer;
169
+ box-shadow: 0 0 0 2px #fff;
170
+ }
171
+
172
+ .svg-controls .zoom-slider::-moz-range-thumb {
173
+ width: 18px;
174
+ height: 18px;
175
+ border-radius: 50%;
176
+ background: var(--svg-viewer-button-fill, #0073aa);
177
+ border: 2px solid var(--svg-viewer-button-border, #0073aa);
178
+ cursor: pointer;
179
+ }
180
+
181
+ .svg-controls .zoom-slider:focus-visible {
182
+ outline: 2px solid var(--svg-viewer-button-fill, #0073aa);
183
+ outline-offset: 2px;
184
+ }
185
+
186
+ .svg-viewer-btn {
187
+ display: inline-flex;
188
+ align-items: center;
189
+ gap: 6px;
190
+ padding: 8px 16px;
191
+ background-color: var(--svg-viewer-button-fill, #0073aa);
192
+ color: var(--svg-viewer-button-text, #fff);
193
+ border: 1px solid var(--svg-viewer-button-border, #0073aa);
194
+ border-radius: 4px;
195
+ cursor: pointer;
196
+ font-size: 14px;
197
+ font-weight: 500;
198
+ transition: background-color 0.2s ease, border-color 0.2s ease,
199
+ transform 0.1s ease;
200
+ white-space: nowrap;
201
+ }
202
+ .svg-viewer-btn.is-disabled,
203
+ .svg-viewer-btn:disabled {
204
+ background-color: #c9ccd1;
205
+ border-color: #b2b5ba;
206
+ color: #f1f1f1;
207
+ cursor: not-allowed;
208
+ opacity: 0.65;
209
+ }
210
+ .svg-viewer-btn.is-disabled:hover,
211
+ .svg-viewer-btn:disabled:hover {
212
+ background-color: #c9ccd1;
213
+ }
214
+
215
+ .svg-viewer-btn .btn-icon {
216
+ font-size: 16px;
217
+ line-height: 1;
218
+ }
219
+
220
+ .svg-viewer-btn .btn-text {
221
+ font-size: 14px;
222
+ line-height: 1.3;
223
+ }
224
+
225
+ .svg-viewer-btn .btn-icon svg {
226
+ display: block;
227
+ width: 16px;
228
+ height: 16px;
229
+ }
230
+
231
+ .svg-viewer-btn:hover {
232
+ background-color: var(
233
+ --svg-viewer-button-hover,
234
+ var(--svg-viewer-button-fill, #0073aa)
235
+ );
236
+ }
237
+
238
+ .svg-viewer-btn:active {
239
+ transform: scale(0.98);
240
+ }
241
+
242
+ .svg-controls .divider {
243
+ width: 1px;
244
+ height: 24px;
245
+ background-color: #ddd;
246
+ margin: 0 8px;
247
+ }
248
+
249
+ .svg-controls.controls-vertical .divider {
250
+ width: 100%;
251
+ height: 1px;
252
+ margin: 8px 0;
253
+ }
254
+
255
+ .zoom-display {
256
+ font-size: 14px;
257
+ color: #666;
258
+ min-width: 60px;
259
+ text-align: center;
260
+ padding: 4px 8px;
261
+ }
262
+
263
+ .controls-mode-icon .btn-text {
264
+ display: none;
265
+ }
266
+
267
+ .controls-mode-icon .svg-viewer-btn {
268
+ padding: 8px;
269
+ justify-content: center;
270
+ }
271
+
272
+ .controls-mode-icon .svg-viewer-btn .btn-icon svg {
273
+ width: 20px;
274
+ height: 20px;
275
+ }
276
+
277
+ .controls-mode-text .btn-icon {
278
+ display: none;
279
+ }
280
+
281
+ .controls-style-compact .svg-viewer-btn {
282
+ padding: 6px 12px;
283
+ font-size: 13px;
284
+ }
285
+
286
+ .controls-style-compact .svg-controls {
287
+ gap: 8px;
288
+ padding: 12px;
289
+ }
290
+
291
+ .controls-style-labels-on-hover .btn-text {
292
+ opacity: 0;
293
+ max-width: 0;
294
+ overflow: hidden;
295
+ transition: opacity 0.2s ease, max-width 0.2s ease;
296
+ }
297
+
298
+ .controls-style-labels-on-hover .svg-viewer-btn:hover .btn-text,
299
+ .controls-style-labels-on-hover .svg-viewer-btn:focus .btn-text,
300
+ .controls-style-labels-on-hover .svg-viewer-btn:focus-visible .btn-text {
301
+ opacity: 1;
302
+ max-width: 200px;
303
+ }
304
+
305
+ .svg-controls.controls-vertical .svg-viewer-btn {
306
+ width: 100%;
307
+ justify-content: center;
308
+ }
309
+
310
+ .svg-controls.controls-align-aligncenter {
311
+ justify-content: center;
312
+ }
313
+
314
+ .svg-controls.controls-align-alignright {
315
+ justify-content: flex-end;
316
+ }
317
+
318
+ .svg-controls.controls-align-alignleft {
319
+ justify-content: flex-start;
320
+ }
321
+
322
+ .svg-controls.controls-vertical.controls-align-alignleft {
323
+ align-items: flex-start;
324
+ }
325
+
326
+ .svg-controls.controls-vertical.controls-align-alignright {
327
+ align-items: flex-end;
328
+ }
329
+
330
+ .svg-controls.controls-vertical.controls-align-aligncenter {
331
+ align-items: center;
332
+ }
333
+
334
+ .svg-viewer-main.controls-align-aligncenter .svg-controls {
335
+ justify-content: center;
336
+ }
337
+
338
+ .svg-viewer-main.controls-align-alignright .svg-controls {
339
+ justify-content: flex-end;
340
+ }
341
+
342
+ .svg-viewer-main.controls-align-alignleft .svg-controls {
343
+ justify-content: flex-start;
344
+ }
345
+
346
+ .svg-controls.controls-vertical .coord-output {
347
+ margin-left: 0;
348
+ margin-top: 4px;
349
+ }
350
+
351
+ .svg-controls.controls-vertical .zoom-display {
352
+ align-self: center;
353
+ }
354
+
355
+ .svg-container {
356
+ flex: 0 0 auto;
357
+ width: 100%;
358
+ max-width: 100%;
359
+ min-width: 0;
360
+ overflow: auto;
361
+ background-color: #fff;
362
+ position: relative;
363
+ display: block;
364
+ scroll-behavior: smooth;
365
+ }
366
+
367
+ .svg-viewer-wrapper.pan-mode-drag .svg-container {
368
+ cursor: grab;
369
+ touch-action: pan-x pan-y;
370
+ }
371
+
372
+ .svg-viewer-wrapper.pan-mode-drag .svg-container.is-dragging {
373
+ cursor: grabbing;
374
+ }
375
+
376
+ .svg-viewer-wrapper.pan-mode-drag .svg-container.is-dragging,
377
+ .svg-viewer-wrapper.pan-mode-drag .svg-container.is-dragging * {
378
+ user-select: none;
379
+ }
380
+
381
+ .svg-viewer-caption {
382
+ border-top: 1px solid #ddd;
383
+ }
384
+
385
+ .svg-viewport {
386
+ display: inline-block;
387
+ transform-origin: top left;
388
+ transition: none;
389
+ width: 100%;
390
+ max-width: 100%;
391
+ }
392
+
393
+ .svg-container svg {
394
+ display: block;
395
+ background-color: #f3f3f3;
396
+ width: 100%;
397
+ height: auto;
398
+ }
399
+
400
+ /* Responsive adjustments */
401
+ @media (max-width: 768px) {
402
+ .svg-viewer-btn {
403
+ padding: 6px 12px;
404
+ font-size: 13px;
405
+ }
406
+
407
+ .svg-viewer-btn .btn-icon {
408
+ font-size: 14px;
409
+ }
410
+
411
+ .svg-controls {
412
+ gap: 8px;
413
+ padding: 12px;
414
+ }
415
+
416
+ .zoom-display {
417
+ font-size: 12px;
418
+ }
419
+ }
420
+
421
+ /* Fix for WordPress admin/editor environments */
422
+ .wp-block-html .svg-viewer-wrapper {
423
+ max-width: 100%;
424
+ }
425
+
426
+ .svg-viewer-wrapper .svg-controls .zoom-display {
427
+ display: inline-flex;
428
+ align-items: center;
429
+ gap: 0.25rem;
430
+ justify-content: center;
431
+ }
432
+
433
+ .svg-viewer-wrapper .svg-controls .coord-output {
434
+ margin-left: 0.75rem;
435
+ font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
436
+ monospace;
437
+ font-size: 0.85rem;
438
+ color: #444;
439
+ }
@@ -0,0 +1,78 @@
1
+ {
2
+ "en": {
3
+ "zoom_in": "Zoom In",
4
+ "zoom_in_title": "Zoom In (Ctrl +)",
5
+ "zoom_out": "Zoom Out",
6
+ "zoom_out_title": "Zoom Out (Ctrl -)",
7
+ "reset_zoom": "Reset Zoom",
8
+ "center_view": "Center View",
9
+ "copy_center": "Copy Center",
10
+ "copy_center_title": "Copy current center coordinates",
11
+ "instruction_click": "Cmd/Ctrl-click to zoom in, Option/Alt-click to zoom out.",
12
+ "instruction_scroll": "Scroll up to zoom in, scroll down to zoom out.",
13
+ "instruction_drag_scroll": "Drag to pan around the image while scrolling zooms.",
14
+ "instruction_drag": "Drag to pan around the image.",
15
+ "zoom_slider_label": "Zoom level"
16
+ },
17
+ "de": {
18
+ "zoom_in": "Vergrößern",
19
+ "zoom_in_title": "Vergrößern (Strg +)",
20
+ "zoom_out": "Verkleinern",
21
+ "zoom_out_title": "Verkleinern (Strg -)",
22
+ "reset_zoom": "Zoom zurücksetzen",
23
+ "center_view": "Ansicht zentrieren",
24
+ "copy_center": "Zentrum kopieren",
25
+ "copy_center_title": "Aktuelle Mittelpunktkoordinaten kopieren",
26
+ "instruction_click": "Mit Cmd/Strg-Klick vergrößern, mit Wahltaste/Alt-Klick verkleinern.",
27
+ "instruction_scroll": "Nach oben scrollen zum Vergrößern, nach unten scrollen zum Verkleinern.",
28
+ "instruction_drag_scroll": "Ziehen zum Schwenken, während scrollen zoomt.",
29
+ "instruction_drag": "Ziehen zum Schwenken des Bildes.",
30
+ "zoom_slider_label": "Zoomstufe"
31
+ },
32
+ "es": {
33
+ "zoom_in": "Acercar",
34
+ "zoom_in_title": "Acercar (Ctrl +)",
35
+ "zoom_out": "Alejar",
36
+ "zoom_out_title": "Alejar (Ctrl -)",
37
+ "reset_zoom": "Restablecer zoom",
38
+ "center_view": "Centrar vista",
39
+ "copy_center": "Copiar centro",
40
+ "copy_center_title": "Copiar las coordenadas del centro actual",
41
+ "instruction_click": "Cmd/Ctrl-clic para acercar, Opción/Alt-clic para alejar.",
42
+ "instruction_scroll": "Desplaza hacia arriba para acercar, hacia abajo para alejar.",
43
+ "instruction_drag_scroll": "Arrastra para desplazarte por la imagen mientras el desplazamiento hace zoom.",
44
+ "instruction_drag": "Arrastra para desplazarte por la imagen.",
45
+ "zoom_slider_label": "Nivel de zoom"
46
+ },
47
+ "fr": {
48
+ "zoom_in": "Zoom avant",
49
+ "zoom_in_title": "Zoom avant (Ctrl +)",
50
+ "zoom_out": "Zoom arrière",
51
+ "zoom_out_title": "Zoom arrière (Ctrl -)",
52
+ "reset_zoom": "Réinitialiser le zoom",
53
+ "center_view": "Centrer la vue",
54
+ "copy_center": "Copier le centre",
55
+ "copy_center_title": "Copier les coordonnées du centre actuel",
56
+ "instruction_click": "Cliquer avec Cmd/Ctrl pour zoomer, cliquer avec Option/Alt pour dézoomer.",
57
+ "instruction_scroll": "Faites défiler vers le haut pour zoomer, vers le bas pour dézoomer.",
58
+ "instruction_drag_scroll": "Faites glisser pour vous déplacer dans l’image pendant que le défilement effectue un zoom.",
59
+ "instruction_drag": "Faites glisser pour vous déplacer dans l’image.",
60
+ "zoom_slider_label": "Niveau de zoom"
61
+ },
62
+ "it": {
63
+ "zoom_in": "Zoom avanti",
64
+ "zoom_in_title": "Zoom avanti (Ctrl +)",
65
+ "zoom_out": "Zoom indietro",
66
+ "zoom_out_title": "Zoom indietro (Ctrl -)",
67
+ "reset_zoom": "Reimposta zoom",
68
+ "center_view": "Centra vista",
69
+ "copy_center": "Copia centro",
70
+ "copy_center_title": "Copia le coordinate del centro attuale",
71
+ "instruction_click": "Cmd/Ctrl-clic per ingrandire, Option/Alt-clic per ridurre.",
72
+ "instruction_scroll": "Scorri verso l’alto per ingrandire, verso il basso per ridurre.",
73
+ "instruction_drag_scroll": "Trascina per spostarti nell’immagine mentre lo scorrimento esegue lo zoom.",
74
+ "instruction_drag": "Trascina per spostarti nell’immagine.",
75
+ "zoom_slider_label": "Livello di zoom"
76
+ }
77
+ }
78
+