iobroker.staticsfilefolder 0.0.15 → 0.0.19

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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 gokturk413 <gokturk413@gmail.com>
3
+ Copyright (c) 2026 gokturk413 <gokturk413@gmail.com>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -55,15 +55,34 @@ Once configured and the instance is running (green status):
55
55
  ---
56
56
 
57
57
  ### Requirements
58
- * Node.js 18.x or higher
59
- * ioBroker JS-Controller >= 3.3.22
58
+ * Node.js 22.x or higher
59
+ * ioBroker JS-Controller >= 6.0.11
60
60
  * ioBroker Web Adapter >= 4.0.0
61
61
 
62
- ### Changelog
63
- #### 0.0.1
62
+ ## Changelog
63
+ <!--
64
+ Placeholder for the next version (at the beginning of the line):
65
+ ### **WORK IN PROGRESS**
66
+ -->
67
+ ### 0.0.19
68
+ * Fixed PDF printing layout margins to fit 1 page, removed file title header from print view, and added zoom controls to PDF viewer.
69
+
70
+ ### 0.0.15
71
+ * Reverted minimum Node.js engine requirement to 20 to support GitHub Actions runners.
72
+
73
+ ### 0.0.13
74
+ * Fixed repochecker error validation requirements (gitignore and dependabot ignore rules).
75
+
76
+ ### 0.0.12
77
+ * Automatically detect ioBroker system language. Added German and Russian translations.
78
+
79
+ ### 0.0.11
80
+ * Added multi-language support (English and Azerbaijani) with English as the default.
81
+
82
+ ### 0.0.1
64
83
  * (gokturk413) initial release: SPA, Offline document viewers, Chokidar file observer.
65
84
 
66
- ### License
85
+ ## License
67
86
  MIT License
68
87
 
69
88
  Copyright (c) 2026 gokturk413 <gokturk413@gmail.com>
package/io-package.json CHANGED
@@ -1,35 +1,72 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "staticsfilefolder",
4
- "version": "0.0.15",
4
+ "version": "0.0.19",
5
5
  "news": {
6
+ "0.0.19": {
7
+ "en": "Fixed PDF printing layout margins to fit 1 page, removed file title header from print view, and added zoom controls to PDF viewer.",
8
+ "de": "Das PDF-Drucklayout-Ränder wurden auf 1 Seite angepasst, der Dateititelkopf wurde aus der Druckansicht entfernt und Zoom-Steuerelemente im PDF-Viewer hinzugefügt.",
9
+ "ru": "Исправлены поля макета печати PDF для соответствия 1 странице, удален заголовок файла из режима печати и добавлены элементы управления масштабированием в просмотрщик PDF.",
10
+ "pt": "Corrigidas as margens do layout de impressão PDF para caber em 1 página, removido o cabeçalho do título do arquivo da visualização de impressão e adicionados controles de zoom ao visualizador de PDF.",
11
+ "nl": "PDF-printlayoutmarges aangepast om op 1 pagina te passen, bestandsnaamkoptekst verwijderd uit de printweergave en zoomknoppen toegevoegd aan de PDF-viewer.",
12
+ "fr": "Correction des marges de mise en page d'impression PDF pour s'adapter à 1 page, suppression de l'en-tête du titre du fichier de la vue d'impression et ajout de commandes de zoom à la visionneuse PDF.",
13
+ "it": "Corretti i margini del layout di stampa PDF per adattarsi a 1 pagina, rimosso l'intestazione del titolo del file dalla visualizzazione di stampa e aggiunti controlli di zoom al visualizzatore di PDF.",
14
+ "es": "Se corrigieron los márgenes del diseño de impresión PDF para que quepan en 1 página, se eliminó el encabezado del título del archivo de la vista de impresión y se agregaron controles de zoom al visor de PDF.",
15
+ "pl": "Naprawiono marginesy układu wydruku PDF, aby pasowały do 1 strony, usunięto nagłówek tytułu pliku z widoku wydruku i dodano sterowanie powiększeniem do przeglądarki PDF.",
16
+ "uk": "Виправлено поля макета друку PDF для відповідності 1 сторінці, вилучено заголовок назвы файлу з режиму друку та додано елементи управління масштабуванням у переглядач PDF.",
17
+ "zh-cn": "修复了PDF打印布局页边距以适应1页,从打印视图中删除了文件标题页眉,并在PDF查看器中添加了缩放控制。"
18
+ },
6
19
  "0.0.15": {
7
20
  "en": "Reverted minimum Node.js engine requirement to 20 to support GitHub Actions runners.",
8
- "de": "Mindestanforderung für Node.js auf 20 zurückgesetzt, um GitHub Actions-Runner zu unterstützen."
9
- },
10
- "0.0.14": {
11
- "en": "Updated minimum dependencies (js-controller >= 6, admin >= 7.6.20) and resized the logo to 128x128 pixels.",
12
- "de": "Mindestabhängigkeiten aktualisiert (js-controller >= 6, admin >= 7.6.20) und die Logogröße auf 128x128 Pixel angepasst."
21
+ "de": "Mindestanforderung für Node.js auf 20 zurückgesetzt, um GitHub Actions-Runner zu unterstützen.",
22
+ "ru": "Требование минимальной версии Node.js возвращено на 20 для поддержки GitHub Actions.",
23
+ "pt": "Requisito mínimo do Node.js revertido para 20 para suportar os runners do GitHub Actions.",
24
+ "nl": "Minimale Node.js-vereiste teruggebracht naar 20 ter ondersteuning van GitHub Actions-runners.",
25
+ "fr": "Exigence minimale de Node.js rétablie à 20 pour prendre en charge les runners GitHub Actions.",
26
+ "it": "Requisito minimo di Node.js ripristinato a 20 per supportare i runner di GitHub Actions.",
27
+ "es": "Requisito mínimo de Node.js revertido a 20 para admitir los runners de GitHub Actions.",
28
+ "pl": "Wymaganie minimalnej wersji Node.js przywrócone do 20 w celu obsługi runnerów GitHub Actions.",
29
+ "uk": "Мінімальна вимога Node.js повернута до 20 для підтримки GitHub Actions.",
30
+ "zh-cn": "将最低Node.js引擎要求恢复为20以支持GitHub Actions运行器。"
13
31
  },
14
32
  "0.0.13": {
15
33
  "en": "Fixed repochecker error validation requirements (gitignore and dependabot ignore rules).",
16
- "de": "Fehlerhafte Repochecker-Validierungsanforderungen behoben (gitignore- und dependabot-Ignorierregeln)."
34
+ "de": "Fehlerhafte Repochecker-Validierungsanforderungen behoben (gitignore- und dependabot-Ignorierregeln).",
35
+ "ru": "Исправлены ошибки валидации repochecker (правила gitignore и dependabot).",
36
+ "pt": "Corrigidos requisitos de validação do repochecker (regras gitignore e dependabot).",
37
+ "nl": "Repochecker-validatievereisten opgelost (gitignore- en dependabot-regels).",
38
+ "fr": "Correction des exigences de validation du repochecker (règles gitignore et dependabot).",
39
+ "it": "Corretti i requisiti di validazione del repochecker (regole gitignore e dependabot).",
40
+ "es": "Se corrigieron los requisitos de validación del repochecker (reglas gitignore y dependabot).",
41
+ "pl": "Naprawiono wymagania walidacji repochecker (reguły gitignore i dependabot).",
42
+ "uk": "Виправлено вимоги валідації repochecker (правила gitignore та dependabot).",
43
+ "zh-cn": "修复了repochecker错误验证要求(gitignore和dependabot忽略规则)。"
17
44
  },
18
45
  "0.0.12": {
19
46
  "en": "Automatically detect ioBroker system language. Added German and Russian translations.",
20
- "de": "ioBroker-Systemsprache automatisch erkennen. Deutsche und russische Übersetzungen hinzugefügt."
47
+ "de": "ioBroker-Systemsprache automatisch erkennen. Deutsche und russische Übersetzungen hinzugefügt.",
48
+ "ru": "Автоматическое определение языка системы ioBroker. Добавлены немецкий и русский переводы.",
49
+ "pt": "Detectar automaticamente o idioma do sistema ioBroker. Adicionadas traduções em alemão e russo.",
50
+ "nl": "Automatische detectie van de ioBroker-systeemtaal. Duitse en Russische vertalingen toegevoegd.",
51
+ "fr": "Détection automatique de la langue du système ioBroker. Ajout de traductions en allemand et en russe.",
52
+ "it": "Rilevamento automatico della lingua del sistema ioBroker. Aggiunte traduzioni in tedesco e russo.",
53
+ "es": "Detectar automáticamente el idioma del sistema ioBroker. Se agregaron traducciones en alemán y ruso.",
54
+ "pl": "Automatyczne wykrywanie języka systemu ioBroker. Dodano tłumaczenia na niemiecki i rosyjski.",
55
+ "uk": "Автоматичне визначення мови системи ioBroker. Додано переклади німецькою та російською.",
56
+ "zh-cn": "自动检测ioBroker系统语言。添加了德语和俄语翻译。"
21
57
  },
22
58
  "0.0.11": {
23
59
  "en": "Added multi-language support (English and Azerbaijani) with English as the default.",
24
- "de": "Mehrsprachige Unterstützung (Englisch und Aserbaidschanisch) hinzugefügt, mit Englisch als Standard."
25
- },
26
- "0.0.10": {
27
- "en": "Updated README.md with detailed instructions for instance configuration settings.",
28
- "de": "README.md mit detaillierten Anweisungen für Instanzkonfigurationseinstellungen aktualisiert."
29
- },
30
- "0.0.9": {
31
- "en": "Updated the adapter logo with a custom designed static files icon.",
32
- "de": "Das Adapter-Logo wurde durch ein benutzerdefiniertes Symbol für statische Dateien ersetzt."
60
+ "de": "Mehrsprachige Unterstützung (Englisch und Aserbaidschanisch) hinzugefügt, mit Englisch als Standard.",
61
+ "ru": "Добавлена многоязычная поддержка (английский и азербайджанский) с английским по умолчанию.",
62
+ "pt": "Adicionado suporte multilíngue (inglês e azerbaijano) com inglês como padrão.",
63
+ "nl": "Meertalige ondersteuning toegevoegd (Engels en Azerbeidzjaans) met Engels als standaard.",
64
+ "fr": "Ajout du support multilingue (anglais et azerbaïdjanais) avec l'anglais par défaut.",
65
+ "it": "Aggiunto supporto multilingue (inglese e azerbaigiano) con inglese come predefinito.",
66
+ "es": "Se agregó soporte multilingüe (inglés y azerbaiyano) con inglés como predeterminado.",
67
+ "pl": "Dodano obsługę wielu języków (angielski i azerski) z angielskim jako domyślnym.",
68
+ "uk": "Додано багатомовну підтримку (англійська та азербайджанська) з англійською за замовчуванням.",
69
+ "zh-cn": "添加了多语言支持(英语和阿塞拜疆语),默认为英语。"
33
70
  }
34
71
  },
35
72
  "titleLang": {
@@ -62,6 +99,7 @@
62
99
  "gokturk413 <gokturk413@gmail.com>"
63
100
  ],
64
101
  "keywords": [
102
+ "ioBroker",
65
103
  "Static Files Directory Browsing"
66
104
  ],
67
105
  "licenseInformation": {
@@ -97,8 +135,6 @@
97
135
  ]
98
136
  },
99
137
  "native": {
100
- "option1": true,
101
- "option2": "42",
102
138
  "webInstance": "*"
103
139
  },
104
140
  "objects": [],
package/lib/web.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const express = require("express");
2
- const path = require("path");
3
- const fs = require("fs");
2
+ const path = require("node:path");
3
+ const fs = require("node:fs");
4
4
 
5
5
  class ExtensionExample {
6
6
  /**
package/main.js CHANGED
@@ -62,7 +62,7 @@ class Staticsfilefolder extends utils.Adapter {
62
62
  this.log.info("Starting file observer on: " + this.config.dirname);
63
63
  try {
64
64
  const chokidar = require("chokidar");
65
- const path = require("path");
65
+ const path = require("node:path");
66
66
 
67
67
  this.watcher = chokidar.watch(this.config.dirname, {
68
68
  ignored: /(^|[/\\])\../, // ignore dotfiles
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.staticsfilefolder",
3
- "version": "0.0.15",
3
+ "version": "0.0.19",
4
4
  "description": "Static Files Folder",
5
5
  "author": {
6
6
  "name": "gokturk413",
@@ -9,6 +9,7 @@
9
9
  "homepage": "https://github.com/gokturk413/ioBroker.staticsfilefolder",
10
10
  "license": "MIT",
11
11
  "keywords": [
12
+ "ioBroker",
12
13
  "Static Files Directory Browsing"
13
14
  ],
14
15
  "repository": {
@@ -16,35 +17,25 @@
16
17
  "url": "https://github.com/gokturk413/ioBroker.staticsfilefolder.git"
17
18
  },
18
19
  "engines": {
19
- "node": ">= 20"
20
+ "node": ">= 22"
20
21
  },
21
22
  "dependencies": {
22
- "@iobroker/adapter-core": "^3.0.4",
23
+ "@iobroker/adapter-core": "^3.4.1",
23
24
  "chokidar": "^5.0.0",
24
25
  "express": "^4.18.3"
25
26
  },
26
27
  "devDependencies": {
27
- "@alcalzone/release-script": "^3.7.0",
28
- "@alcalzone/release-script-plugin-iobroker": "^3.7.0",
29
- "@alcalzone/release-script-plugin-license": "^3.7.0",
30
- "@alcalzone/release-script-plugin-manual-review": "^3.7.0",
28
+ "@alcalzone/release-script": "^5.2.1",
29
+ "@alcalzone/release-script-plugin-iobroker": "^5.2.0",
30
+ "@alcalzone/release-script-plugin-license": "^5.2.0",
31
+ "@alcalzone/release-script-plugin-manual-review": "^5.2.0",
31
32
  "@iobroker/adapter-dev": "^1.3.0",
32
- "@iobroker/testing": "^4.1.1",
33
+ "@iobroker/testing": "^5.2.2",
33
34
  "@tsconfig/node18": "^18.2.2",
34
- "@types/chai": "^4.3.12",
35
- "@types/chai-as-promised": "^7.1.8",
36
- "@types/mocha": "^10.0.6",
37
35
  "@types/node": "^18.19.24",
38
36
  "@types/proxyquire": "^1.3.31",
39
- "@types/sinon": "^17.0.3",
40
- "@types/sinon-chai": "^3.2.12",
41
- "chai": "^4.4.1",
42
- "chai-as-promised": "^7.1.1",
43
37
  "eslint": "^8.57.0",
44
- "mocha": "^10.3.0",
45
38
  "proxyquire": "^2.1.3",
46
- "sinon": "^17.0.1",
47
- "sinon-chai": "^3.7.0",
48
39
  "typescript": "~5.0.4"
49
40
  },
50
41
  "main": "main.js",
package/www/app.js CHANGED
@@ -28,11 +28,14 @@ const modalTitle = document.getElementById('modal-title');
28
28
  const modalBtnPrev = document.getElementById('modal-btn-prev');
29
29
  const modalBtnNext = document.getElementById('modal-btn-next');
30
30
  const modalBtnPrint = document.getElementById('modal-btn-print');
31
+ const modalPdfZoom = document.getElementById('modal-pdf-zoom');
31
32
  const modalBtnDownload = document.getElementById('modal-btn-download');
32
33
 
33
34
  // Modal Navigation State
34
35
  let currentOpenItem = null;
35
36
  let currentFilesList = [];
37
+ let currentPdfDoc = null;
38
+ let currentPdfZoom = 1.5;
36
39
 
37
40
  // Localization Settings
38
41
  const translations = {
@@ -240,12 +243,20 @@ document.addEventListener('DOMContentLoaded', () => {
240
243
  modalBtnPrev.addEventListener('click', navigateModalPrev);
241
244
  modalBtnNext.addEventListener('click', navigateModalNext);
242
245
  modalBtnPrint.addEventListener('click', printModalContent);
246
+ modalPdfZoom.addEventListener('change', (e) => {
247
+ currentPdfZoom = parseFloat(e.target.value);
248
+ renderPdfPages();
249
+ });
243
250
  modalBtnDownload.addEventListener('click', downloadCurrentFile);
244
251
 
245
252
  closeModal.addEventListener('click', () => {
246
253
  viewerModal.style.display = 'none';
247
254
  viewerBody.innerHTML = ''; // clear memory
248
255
  currentOpenItem = null;
256
+ currentPdfDoc = null;
257
+ currentPdfZoom = 1.5;
258
+ modalPdfZoom.value = '1.5';
259
+ modalPdfZoom.style.display = 'none';
249
260
  });
250
261
  });
251
262
 
@@ -420,6 +431,7 @@ function handleItemClick(item) {
420
431
  function openFile(item) {
421
432
  currentOpenItem = item;
422
433
  modalTitle.textContent = item.name;
434
+ modalPdfZoom.style.display = 'none';
423
435
 
424
436
  // Find index of current file in currentFilesList
425
437
  const index = currentFilesList.findIndex(f => f.name === item.name);
@@ -464,12 +476,13 @@ function printModalContent() {
464
476
 
465
477
  const canvases = viewerBody.querySelectorAll('canvas');
466
478
  let contentHtml = '';
479
+ let isPdf = canvases.length > 0;
467
480
 
468
- if (canvases.length > 0) {
481
+ if (isPdf) {
469
482
  // PDF (which is rendered in canvases)
470
483
  canvases.forEach(canvas => {
471
484
  const dataUrl = canvas.toDataURL();
472
- contentHtml += `<img src="${dataUrl}" style="max-width: 100%; margin-bottom: 20px; display: block;" />`;
485
+ contentHtml += `<img src="${dataUrl}" class="pdf-page-img" />`;
473
486
  });
474
487
  } else {
475
488
  // Excel table or Word document HTML
@@ -482,16 +495,34 @@ function printModalContent() {
482
495
  <head>
483
496
  <title>${currentOpenItem.name}</title>
484
497
  <style>
485
- body { margin: 20px; font-family: sans-serif; background: white; color: black; }
486
- img, table { max-width: 100%; page-break-inside: avoid; }
498
+ @page {
499
+ size: auto;
500
+ margin: 0mm;
501
+ }
502
+ body {
503
+ margin: 0;
504
+ padding: ${isPdf ? '0' : '20px'};
505
+ font-family: sans-serif;
506
+ background: white;
507
+ color: black;
508
+ }
509
+ .pdf-page-img {
510
+ width: 100%;
511
+ max-width: 100%;
512
+ height: auto;
513
+ display: block;
514
+ page-break-after: always;
515
+ }
516
+ .pdf-page-img:last-child {
517
+ page-break-after: avoid;
518
+ }
487
519
  table { border-collapse: collapse; width: 100%; margin-top: 10px; }
488
520
  table th, table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
489
521
  table th { background-color: #f2f2f2; }
522
+ img, table { page-break-inside: avoid; }
490
523
  </style>
491
524
  </head>
492
525
  <body>
493
- <h2>${currentOpenItem.name}</h2>
494
- <hr />
495
526
  ${contentHtml}
496
527
  <script>
497
528
  window.onload = function() {
@@ -525,23 +556,36 @@ function downloadCurrentFile() {
525
556
  async function openPdf(url) {
526
557
  viewerModal.style.display = 'block';
527
558
  viewerBody.innerHTML = `<h2>${translations[currentLang]?.loadingPdf || 'Loading PDF...'}</h2>`;
559
+ modalPdfZoom.style.display = 'inline-block';
528
560
 
529
561
  try {
530
562
  const loadingTask = window.pdfjsLib.getDocument({ url: url });
531
- const pdf = await loadingTask.promise;
532
- viewerBody.innerHTML = ''; // clear loading
533
-
534
- // Render all pages
535
- for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
536
- const page = await pdf.getPage(pageNum);
537
- const scale = 1.5;
538
- const viewport = page.getViewport({ scale: scale });
563
+ currentPdfDoc = await loadingTask.promise;
564
+ renderPdfPages();
565
+ } catch (e) {
566
+ const errorText = translations[currentLang]?.errorLoading || 'An error occurred: ';
567
+ viewerBody.innerHTML = `<h2 style="color:red">${errorText}${e.message}</h2>`;
568
+ }
569
+ }
570
+
571
+ async function renderPdfPages() {
572
+ if (!currentPdfDoc) return;
573
+ viewerBody.innerHTML = '';
574
+
575
+ try {
576
+ for (let pageNum = 1; pageNum <= currentPdfDoc.numPages; pageNum++) {
577
+ const page = await currentPdfDoc.getPage(pageNum);
578
+ const viewport = page.getViewport({ scale: currentPdfZoom });
539
579
 
540
580
  const canvas = document.createElement('canvas');
541
581
  const context = canvas.getContext('2d');
542
582
  canvas.height = viewport.height;
543
583
  canvas.width = viewport.width;
544
584
 
585
+ canvas.style.display = 'block';
586
+ canvas.style.margin = '10px auto';
587
+ canvas.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
588
+
545
589
  viewerBody.appendChild(canvas);
546
590
 
547
591
  const renderContext = {
@@ -551,8 +595,7 @@ async function openPdf(url) {
551
595
  await page.render(renderContext).promise;
552
596
  }
553
597
  } catch (e) {
554
- const errorText = translations[currentLang]?.errorLoading || 'An error occurred: ';
555
- viewerBody.innerHTML = `<h2 style="color:red">${errorText}${e.message}</h2>`;
598
+ console.error("Error rendering PDF pages:", e);
556
599
  }
557
600
  }
558
601
 
package/www/index.html CHANGED
@@ -67,6 +67,13 @@
67
67
  <button id="modal-btn-prev" class="nav-btn" data-i18n="modalBack" title="Previous">&larr; Back</button>
68
68
  <button id="modal-btn-next" class="nav-btn" data-i18n="modalForward" title="Next">Next &rarr;</button>
69
69
  <button id="modal-btn-print" class="nav-btn" data-i18n="modalPrint" title="Print / Save as PDF">🖨️ Print / PDF</button>
70
+ <select id="modal-pdf-zoom" class="nav-btn" title="Zoom" style="display: none; height: 32px; padding: 0 6px; margin: 0 4px; font-size: 14px; border-radius: 4px; border: 1px solid var(--border-color); background: var(--bg-card); color: var(--text-color); cursor: pointer; vertical-align: middle;">
71
+ <option value="1.0">100%</option>
72
+ <option value="1.25">125%</option>
73
+ <option value="1.5" selected>150%</option>
74
+ <option value="2.0">200%</option>
75
+ <option value="2.5">250%</option>
76
+ </select>
70
77
  <button id="modal-btn-download" class="nav-btn" data-i18n="modalDownload" title="Download File">📥 Download</button>
71
78
  <span id="close-modal" class="close-button">&times;</span>
72
79
  </div>