redmine_apijs 6.5.0 → 6.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/README +6 -7
  3. data/app/controllers/apijs_controller.rb +25 -6
  4. data/app/views/application/_browser.html.erb +1 -1
  5. data/app/views/attachments/_links.html.erb +1 -1
  6. data/app/views/settings/_apijs.html.erb +7 -4
  7. data/assets/javascripts/apijs-redmine.min.js +4 -3
  8. data/assets/javascripts/apijs.min.js +5 -4
  9. data/assets/javascripts/apijs.min.js.map +1 -0
  10. data/assets/javascripts/app.js +18 -2
  11. data/assets/javascripts/app.min.js.map +1 -0
  12. data/assets/stylesheets/apijs-print.min.css +5 -5
  13. data/assets/stylesheets/apijs-print.min.css.map +1 -0
  14. data/assets/stylesheets/apijs-redmine-rtl.min.css +4 -4
  15. data/assets/stylesheets/apijs-redmine.min.css +4 -4
  16. data/assets/stylesheets/apijs-screen-rtl.min.css +5 -5
  17. data/assets/stylesheets/apijs-screen-rtl.min.css.map +1 -0
  18. data/assets/stylesheets/apijs-screen.min.css +5 -5
  19. data/assets/stylesheets/apijs-screen.min.css.map +1 -0
  20. data/assets/stylesheets/styles-rtl.min.css.map +1 -0
  21. data/assets/stylesheets/styles.css +6 -4
  22. data/assets/stylesheets/styles.min.css.map +1 -0
  23. data/config/locales/cs.yml +3 -1
  24. data/config/locales/de.yml +3 -1
  25. data/config/locales/en.yml +3 -1
  26. data/config/locales/es.yml +3 -1
  27. data/config/locales/fr.yml +3 -1
  28. data/config/locales/it.yml +3 -1
  29. data/config/locales/ja.yml +3 -1
  30. data/config/locales/nl.yml +3 -1
  31. data/config/locales/pl.yml +3 -1
  32. data/config/locales/pt-BR.yml +3 -1
  33. data/config/locales/pt.yml +3 -1
  34. data/config/locales/ru.yml +3 -1
  35. data/config/locales/sk.yml +3 -1
  36. data/config/locales/tr.yml +3 -1
  37. data/config/locales/uk.yml +34 -0
  38. data/config/locales/zh.yml +3 -1
  39. data/config/routes.rb +9 -2
  40. data/init.rb +3 -3
  41. data/lib/apijs_attachment.rb +10 -5
  42. data/lib/apijs_const.rb +1 -1
  43. data/lib/apijs_files.rb +1 -1
  44. data/lib/image.py +162 -119
  45. data/lib/redmine_apijs.rb +1 -1
  46. data/lib/useragentparser.rb +10 -8
  47. data/lib/video.py +8 -6
  48. data/redmine_apijs.gemspec +9 -1
  49. metadata +11 -3
@@ -1,5 +1,6 @@
1
1
  es:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "Se borró la memoria caché de la imagen."
3
4
  apijs_browser_warning: "<strong>Atención:</strong> su navegador <strong>%{n} %{v}</strong> es obsoleto, por favor <a %{l}>actualice su navegador</a>."
4
5
  apijs_title_album: "Galería de fotográfias"
5
6
  apijs_title_download: "Descargar (%{v})"
@@ -14,11 +15,12 @@ es:
14
15
  apijs_example2_link: "Sitio Web: %{v}"
15
16
  apijs_config_sort_order: "Ordenar archivos alfabéticamente"
16
17
  apijs_config_browser: "Comprobar la versión del navegador"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (verifica incluso si el apijs esta desactivado)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (verifica incluso si el apijs esta desactivado)."
18
19
  permission_edit_attachments: "(apijs) Editar descripción de archivos"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Borrar los archivos"
21
22
  apijs_config_directories: "Tamaño de las carpetas"
23
+ apijs_config_clearcache: "vaciar la caché"
22
24
  apijs_config_album: "Álbumes de fotografías"
23
25
  apijs_config_show_album: "Mostrar los álbumes"
24
26
  apijs_config_show_album_infos: "Mostrar todas las informaciones"
@@ -1,5 +1,6 @@
1
1
  fr:
2
2
  apijs_check_extension: "L'extension du fichier ne peut pas être modifiée."
3
+ apijs_clearcache_done: "Le cache des images a été nettoyé."
3
4
  apijs_browser_warning: "<strong>Attention :</strong> votre navigateur <strong>%{n} %{v}</strong> n'est plus à jour, veuillez <a %{l}>mettre à jour votre navigateur</a>."
4
5
  apijs_title_album: "Galerie photos"
5
6
  apijs_title_download: "Télécharger (%{v})"
@@ -14,11 +15,12 @@ fr:
14
15
  apijs_example2_link: "Site internet : %{v}"
15
16
  apijs_config_sort_order: "Trier les fichiers par ordre alphabétique"
16
17
  apijs_config_browser: "Vérifier la version du navigateur"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (vérifie même si l'apijs est désactivé)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (vérifie même si l'apijs est désactivé)."
18
19
  permission_edit_attachments: "(apijs) Modifier la description des fichiers"
19
20
  permission_rename_attachments: "(apijs) Renommer les fichiers"
20
21
  permission_delete_attachments: "(apijs) Supprimer les fichiers"
21
22
  apijs_config_directories: "Taille des dossiers"
23
+ apijs_config_clearcache: "vider le cache"
22
24
  apijs_config_album: "Albums photos"
23
25
  apijs_config_show_album: "Afficher les albums"
24
26
  apijs_config_show_album_infos: "Afficher toutes les informations"
@@ -1,5 +1,6 @@
1
1
  it:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "La cache delle immagini è stata pulita."
3
4
  apijs_browser_warning: "<strong>Attenzione:</strong> il vostro browser <strong>%{n} %{v}</strong> è obsoleto, vi preghiamo di <a %{l}>aggiornare il vostro browser</a>."
4
5
  apijs_title_album: "Galleria fotografica"
5
6
  apijs_title_download: "Scaricare (%{v})"
@@ -14,11 +15,12 @@ it:
14
15
  apijs_example2_link: "Sito internet: %{v}"
15
16
  apijs_config_sort_order: "Ordinare i file in ordine alfabetico"
16
17
  apijs_config_browser: "Verificare la versione del browser"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (verificare se l'apijs é disattivato)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (verificare se l'apijs é disattivato)."
18
19
  permission_edit_attachments: "(apijs) Modificare la descrizione dei file"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Eliminare i file"
21
22
  apijs_config_directories: "Dimensione file"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "Album fotografico"
23
25
  apijs_config_show_album: "Visualizzare l'album"
24
26
  apijs_config_show_album_infos: "Visualizzare tutte le informazioni"
@@ -1,5 +1,6 @@
1
1
  ja:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "The image cache was cleaned."
3
4
  apijs_browser_warning: "<strong>Warning:</strong> your browser <strong>%{n} %{v}</strong> is outdated, please <a %{l}>upgrade your browser</a>."
4
5
  apijs_title_album: "Photo gallery"
5
6
  apijs_title_download: "ダウンロード(%{v})"
@@ -14,11 +15,12 @@ ja:
14
15
  apijs_example2_link: "ウェブサイト:%{v}"
15
16
  apijs_config_sort_order: "Sort files alphabetically"
16
17
  apijs_config_browser: "Check browser version"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
19
  permission_edit_attachments: "(apijs) Edit files description"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Remove files"
21
22
  apijs_config_directories: "Directories size"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "Photo albums"
23
25
  apijs_config_show_album: "Display albums"
24
26
  apijs_config_show_album_infos: "Display all information"
@@ -1,5 +1,6 @@
1
1
  nl:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "The image cache was cleaned."
3
4
  apijs_browser_warning: "<strong>Warning:</strong> your browser <strong>%{n} %{v}</strong> is outdated, please <a %{l}>upgrade your browser</a>."
4
5
  apijs_title_album: "Photo gallery"
5
6
  apijs_title_download: "Download (%{v})"
@@ -14,11 +15,12 @@ nl:
14
15
  apijs_example2_link: "Website: %{v}"
15
16
  apijs_config_sort_order: "Sort files alphabetically"
16
17
  apijs_config_browser: "Check browser version"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
19
  permission_edit_attachments: "(apijs) Edit files description"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Remove files"
21
22
  apijs_config_directories: "Directories size"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "Photo albums"
23
25
  apijs_config_show_album: "Display albums"
24
26
  apijs_config_show_album_infos: "Display all information"
@@ -1,5 +1,6 @@
1
1
  pl:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "The image cache was cleaned."
3
4
  apijs_browser_warning: "<strong>Warning:</strong> your browser <strong>%{n} %{v}</strong> is outdated, please <a %{l}>upgrade your browser</a>."
4
5
  apijs_title_album: "Photo gallery"
5
6
  apijs_title_download: "Pobierz (%{v})"
@@ -14,11 +15,12 @@ pl:
14
15
  apijs_example2_link: "Witryna: %{v}"
15
16
  apijs_config_sort_order: "Sort files alphabetically"
16
17
  apijs_config_browser: "Check browser version"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
19
  permission_edit_attachments: "(apijs) Edit files description"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Remove files"
21
22
  apijs_config_directories: "Directories size"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "Photo albums"
23
25
  apijs_config_show_album: "Display albums"
24
26
  apijs_config_show_album_infos: "Display all information"
@@ -1,5 +1,6 @@
1
1
  pt-BR:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "A cache de imagem foi limpa."
3
4
  apijs_browser_warning: "<strong>Warning:</strong> your browser <strong>%{n} %{v}</strong> is outdated, please <a %{l}>upgrade your browser</a>."
4
5
  apijs_title_album: "Photo gallery"
5
6
  apijs_title_download: "Baixar (%{v})"
@@ -14,11 +15,12 @@ pt-BR:
14
15
  apijs_example2_link: "Sítio Web: %{v}"
15
16
  apijs_config_sort_order: "Sort files alphabetically"
16
17
  apijs_config_browser: "Check browser version"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
19
  permission_edit_attachments: "(apijs) Edit files description"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Remove files"
21
22
  apijs_config_directories: "Directories size"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "Photo albums"
23
25
  apijs_config_show_album: "Display albums"
24
26
  apijs_config_show_album_infos: "Display all information"
@@ -1,5 +1,6 @@
1
1
  pt:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "The image cache was cleaned."
3
4
  apijs_browser_warning: "<strong>Cuidado:</strong> o seu navegador <strong>%{n} %{v}</strong> está desatualizado, por favor <a %{l}>atualize o seu navegador</a>."
4
5
  apijs_title_album: "Galeria de fotos"
5
6
  apijs_title_download: "Descarregar (%{v})"
@@ -14,11 +15,12 @@ pt:
14
15
  apijs_example2_link: "Sítio Web: %{v}"
15
16
  apijs_config_sort_order: "Ordenar os ficheiros por ordem alfabética"
16
17
  apijs_config_browser: "Verificar a versão do navegador"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (verifica mesmo que apijs esteja desativado)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (verifica mesmo que apijs esteja desativado)."
18
19
  permission_edit_attachments: "(apijs) Modificar a descrição dos ficheiros"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Suprimir os ficheiros"
21
22
  apijs_config_directories: "Tamanho dos diretórios"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "Álbuns de fotos"
23
25
  apijs_config_show_album: "Afixar os álbuns"
24
26
  apijs_config_show_album_infos: "Afixar todas as informações"
@@ -1,5 +1,6 @@
1
1
  ru:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "The image cache was cleaned."
3
4
  apijs_browser_warning: "<strong>Warning:</strong> your browser <strong>%{n} %{v}</strong> is outdated, please <a %{l}>upgrade your browser</a>."
4
5
  apijs_title_album: "Фото галлерея"
5
6
  apijs_title_download: "Скачать (%{v})"
@@ -14,11 +15,12 @@ ru:
14
15
  apijs_example2_link: "Вебсайт: %{v}"
15
16
  apijs_config_sort_order: "Сортировать файлы в алфавитном порядке"
16
17
  apijs_config_browser: "Check browser version"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
19
  permission_edit_attachments: "(apijs) Редактировать описание файла"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Удалить файлы"
21
22
  apijs_config_directories: "Directories size"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "Фото альбомы"
23
25
  apijs_config_show_album: "Отображать фото альбомы"
24
26
  apijs_config_show_album_infos: "Display all information"
@@ -1,5 +1,6 @@
1
1
  sk:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "The image cache was cleaned."
3
4
  apijs_browser_warning: "<strong>Warning:</strong> your browser <strong>%{n} %{v}</strong> is outdated, please <a %{l}>upgrade your browser</a>."
4
5
  apijs_title_album: "Photo gallery"
5
6
  apijs_title_download: "Prevziať (%{v})"
@@ -14,11 +15,12 @@ sk:
14
15
  apijs_example2_link: "Webstránka: %{v}"
15
16
  apijs_config_sort_order: "Sort files alphabetically"
16
17
  apijs_config_browser: "Check browser version"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
19
  permission_edit_attachments: "(apijs) Edit files description"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Remove files"
21
22
  apijs_config_directories: "Directories size"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "Photo albums"
23
25
  apijs_config_show_album: "Display albums"
24
26
  apijs_config_show_album_infos: "Display all information"
@@ -1,5 +1,6 @@
1
1
  tr:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "The image cache was cleaned."
3
4
  apijs_browser_warning: "<strong>Warning:</strong> your browser <strong>%{n} %{v}</strong> is outdated, please <a %{l}>upgrade your browser</a>."
4
5
  apijs_title_album: "Fotoğraf Galerisi"
5
6
  apijs_title_download: "İndir (%{v})"
@@ -14,11 +15,12 @@ tr:
14
15
  apijs_example2_link: "Web sitesi : %{v}"
15
16
  apijs_config_sort_order: "Eklentileri alfabetik olarak sırala"
16
17
  apijs_config_browser: "Check browser version"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
19
  permission_edit_attachments: "(apijs) Eklenti açıklamalarını düzenle"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) Eklenti Sil"
21
22
  apijs_config_directories: "Directories size"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "Fotoğraf Albümü"
23
25
  apijs_config_show_album: "Fotoğraf albümünü görüntüle"
24
26
  apijs_config_show_album_infos: "Display all information"
@@ -0,0 +1,34 @@
1
+ uk:
2
+ apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "The image cache was cleaned."
4
+ apijs_browser_warning: "<strong>Warning:</strong> your browser <strong>%{n} %{v}</strong> is outdated, please <a %{l}>upgrade your browser</a>."
5
+ apijs_title_album: "Photo gallery"
6
+ apijs_title_download: "Завантажити (%{v})"
7
+ apijs_title_files: "Files list"
8
+ apijs_config_apijs: "Загальні"
9
+ apijs_config_enable: "Enable apijs"
10
+ apijs_example1_title: "PHP manual"
11
+ apijs_example1_text: "It is important to note that just because the mail was accepted for delivery, it doesn't mean the mail will actually reach the intended destination."
12
+ apijs_example: "Example %{v}"
13
+ apijs_example2_title: "Surprise!"
14
+ apijs_example2_text: "You are watching this video without proprietary extension thanks to the new [em]video[/em] tag included in the [strong]HTML 5[/strong] language."
15
+ apijs_example2_link: "Вебсайт: %{v}"
16
+ apijs_config_sort_order: "Sort files alphabetically"
17
+ apijs_config_browser: "Check browser version"
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
19
+ permission_edit_attachments: "(apijs) Edit files description"
20
+ permission_rename_attachments: "(apijs) Rename files"
21
+ permission_delete_attachments: "(apijs) Remove files"
22
+ apijs_config_directories: "Directories size"
23
+ apijs_config_clearcache: "clear cache"
24
+ apijs_config_album: "Photo albums"
25
+ apijs_config_show_album: "Display albums"
26
+ apijs_config_show_album_infos: "Display all information"
27
+ apijs_config_show_filename: "Display the name in the slide show"
28
+ apijs_config_show_exifdate: "Display the date in the slide show"
29
+ apijs_config_mimetypes: "Use the following files"
30
+ apijs_config_album_exclude_name: "Exclude photos from album<br />whose name begins with"
31
+ apijs_config_album_exclude_desc: "Exclude photos from album<br />whose description begins with"
32
+ apijs_config_create_all: "Generate the three images"
33
+ apijs_config_create_all_info: "Generates thumbnails and image preview at the same time, it slows the first display, but accelerates the first display of the slide show."
34
+ apijs_config_programs: "Programs version"
@@ -1,5 +1,6 @@
1
1
  zh:
2
2
  apijs_check_extension: "The file extension can not be changed."
3
+ apijs_clearcache_done: "The image cache was cleaned."
3
4
  apijs_browser_warning: "<strong>Warning:</strong> your browser <strong>%{n} %{v}</strong> is outdated, please <a %{l}>upgrade your browser</a>."
4
5
  apijs_title_album: "照片库"
5
6
  apijs_title_download: "下载(%{v})"
@@ -14,11 +15,12 @@ zh:
14
15
  apijs_example2_link: "网站:%{v}"
15
16
  apijs_config_sort_order: "按字母顺序排序文件"
16
17
  apijs_config_browser: "Check browser version"
17
- apijs_config_browser_help: "Firefox 36+, Chrome 31+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
+ apijs_config_browser_help: "Firefox 36+, Chrome 32+, Opera 19+, Edge 16+, Safari 9+ (checks even if the apijs is disabled)."
18
19
  permission_edit_attachments: "(apijs) 编辑文件说明"
19
20
  permission_rename_attachments: "(apijs) Rename files"
20
21
  permission_delete_attachments: "(apijs) 删除文件"
21
22
  apijs_config_directories: "Directories size"
23
+ apijs_config_clearcache: "clear cache"
22
24
  apijs_config_album: "相册"
23
25
  apijs_config_show_album: "显示相册"
24
26
  apijs_config_show_album_infos: "显示所有信息"
data/config/routes.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # encoding: utf-8
2
2
  # Created J/12/12/2013
3
- # Updated J/20/08/2020
3
+ # Updated S/16/01/2021
4
4
  #
5
- # Copyright 2008-2020 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
5
+ # Copyright 2008-2021 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
6
6
  # https://www.luigifab.fr/redmine/apijs
7
7
  #
8
8
  # This program is free software, you can redistribute it or modify
@@ -44,6 +44,9 @@ if Redmine::VERSION::MAJOR >= 2
44
44
 
45
45
  match 'apijs/delete', to: 'apijs#delete',
46
46
  via: :post
47
+
48
+ match 'apijs/clearcache', to: 'apijs#clearcache',
49
+ via: :get
47
50
  end
48
51
  else
49
52
  ActionController::Routing::Routes.draw do |map|
@@ -89,5 +92,9 @@ else
89
92
  map.connect 'apijs/delete',
90
93
  controller: 'apijs', action: 'delete',
91
94
  conditions: {method: :post}
95
+
96
+ map.connect 'apijs/clearcache',
97
+ controller: 'apijs', action: 'clearcache',
98
+ conditions: {method: :get}
92
99
  end
93
100
  end
data/init.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # encoding: utf-8
2
2
  # Created L/21/05/2012
3
- # Updated S/10/10/2020
3
+ # Updated S/12/12/2020
4
4
  #
5
- # Copyright 2008-2020 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
5
+ # Copyright 2008-2021 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
6
6
  # https://www.luigifab.fr/redmine/apijs
7
7
  #
8
8
  # This program is free software, you can redistribute it or modify
@@ -26,7 +26,7 @@ Redmine::Plugin.register :redmine_apijs do
26
26
  name 'Redmine Apijs plugin'
27
27
  author 'Fabrice Creuzot'
28
28
  description 'Integrate the apijs javascript library into Redmine.'
29
- version '6.5.0-gem'
29
+ version '6.6.0-gem'
30
30
  url 'https://www.luigifab.fr/redmine/apijs'
31
31
  author_url 'https://www.luigifab.fr/'
32
32
 
@@ -1,8 +1,8 @@
1
1
  # encoding: utf-8
2
2
  # Created V/27/12/2013
3
- # Updated S/07/11/2020
3
+ # Updated J/18/02/2021
4
4
  #
5
- # Copyright 2008-2020 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
5
+ # Copyright 2008-2021 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
6
6
  # https://www.luigifab.fr/redmine/apijs
7
7
  #
8
8
  # This program is free software, you can redistribute it or modify
@@ -90,9 +90,9 @@ module ApijsAttachment
90
90
 
91
91
  def getShowButton(setting_show_filename, setting_show_exifdate, description)
92
92
  if self.isImage?
93
- return "apijs.dialog.dialogPhoto('" + self.getShowUrl + "', '" + ((setting_show_filename) ? self.filename : 'false') + "', '" + ((setting_show_exifdate) ? format_time(self.created_on) : 'false') + "', '" + description + "');"
93
+ return "apijs.dialog.dialogPhoto('" + self.getShowUrl + "', '" + (setting_show_filename ? self.filename : 'false') + "', '" + (setting_show_exifdate ? format_time(self.created_on) : 'false') + "', '" + description + "');"
94
94
  elsif self.isVideo?
95
- return "apijs.dialog.dialogVideo('" + self.getDownloadUrl + "', '" + ((setting_show_filename) ? self.filename : 'false') + "', '" + ((setting_show_exifdate) ? format_time(self.created_on) : 'false') + "', '" + description + "');"
95
+ return "apijs.dialog.dialogVideo('" + self.getDownloadUrl + "', '" + (setting_show_filename ? self.filename : 'false') + "', '" + (setting_show_exifdate ? format_time(self.created_on) : 'false') + "', '" + description + "');"
96
96
  elsif self.is_text?
97
97
  return "self.location.href = '" + self.getUrl('redmineshow', false) + "';"
98
98
  end
@@ -280,13 +280,16 @@ module ApijsAttachment
280
280
  pil = pyt
281
281
  sco = pyt
282
282
  else
283
- pyt = `#{cmd} --version 2>&1`.gsub('Python ', '').strip!
283
+ pyt = `#{cmd} --version 2>&1`.gsub('Python', '').strip!
284
+ pyt = pyt.split(/\D/).slice(0, 3).join('.')
284
285
 
285
286
  pil = `#{cmd} -c "from PIL import Image; print(Image.__version__)" 2>&1`.strip!
286
287
  if pil.include? "o module named"
287
288
  pil = 'not available'
288
289
  elsif pil.include? "__version__"
289
290
  pil = 'available'
291
+ else
292
+ pil = pil.split(/\D/).slice(0, 3).join('.')
290
293
  end
291
294
 
292
295
  sco = `#{cmd} -c "import scour; print(scour.__version__)" 2>&1`.strip!
@@ -294,6 +297,8 @@ module ApijsAttachment
294
297
  sco = 'not available'
295
298
  elsif sco.include? "__version__"
296
299
  sco = 'available'
300
+ else
301
+ sco = sco.split(/\D/).slice(0, 3).join('.')
297
302
  end
298
303
  end
299
304
 
data/lib/apijs_const.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  # Created L/01/09/2014
3
3
  # Updated J/23/07/2020
4
4
  #
5
- # Copyright 2008-2020 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
5
+ # Copyright 2008-2021 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
6
6
  # https://www.luigifab.fr/redmine/apijs
7
7
  #
8
8
  # This program is free software, you can redistribute it or modify
data/lib/apijs_files.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  # Created L/21/05/2012
3
3
  # Updated D/03/05/2020
4
4
  #
5
- # Copyright 2008-2020 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
5
+ # Copyright 2008-2021 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
6
6
  # https://www.luigifab.fr/redmine/apijs
7
7
  #
8
8
  # This program is free software, you can redistribute it or modify
data/lib/image.py CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/python3
2
2
  # -*- coding: utf8 -*-
3
3
  # Created J/26/12/2013
4
- # Updated S/07/11/2020
4
+ # Updated J/18/02/2021
5
5
  #
6
- # Copyright 2008-2020 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
6
+ # Copyright 2008-2021 | Fabrice Creuzot (luigifab) <code~luigifab~fr>
7
+ # Copyright 2020-2021 | Fabrice Creuzot <fabrice~cellublue~com>
7
8
  # https://www.luigifab.fr/openmage/apijs
8
9
  #
9
10
  # This program is free software, you can redistribute it or modify
@@ -18,7 +19,6 @@
18
19
 
19
20
  import os
20
21
  import sys
21
- from PIL import Image, ImageSequence
22
22
 
23
23
  try:
24
24
  filein = str(sys.argv[1])
@@ -35,166 +35,209 @@ except:
35
35
  if not os.path.exists(os.path.dirname(fileout)):
36
36
  os.makedirs(os.path.dirname(fileout))
37
37
 
38
- # python-scour
39
- if ".svg" in fileout:
40
- from scour.scour import (sanitizeOptions, start)
41
- options = sanitizeOptions()
42
- options.strip_xml_prolog = True # --strip-xml-prolog
43
- options.remove_metadata = True # --remove-metadata
44
- options.strip_comments = True # --enable-comment-stripping
45
- options.strip_ids = True # --enable-id-stripping
46
- options.indent_type = None # --indent=none
47
- start(options, open(filein, 'rb'), open(fileout, 'wb'))
48
- exit(0)
49
38
 
50
- # python-pil
51
- source = Image.open(filein)
52
- if size[1] == 0 and size[0] == 0:
53
- size = (source.size[0], source.size[1])
54
- elif size[1] == 0:
55
- size = (size[0], int(size[0] / (source.size[0] / source.size[1])))
56
- elif size[0] == 0:
57
- size = (int(size[1] * (source.size[0] / source.size[1])), size[1])
58
-
59
- # (Animated) PNG resizing (since PIL 7.1.0)
39
+ def versiontuple(v):
40
+ return tuple(map(int, (v.split('.'))))
41
+
42
+ def calcsize(source, size):
43
+
44
+ if size[1] == 0 and size[0] == 0:
45
+ return source.size
46
+ if size[1] == 0:
47
+ return (size[0], int(size[0] / (source.size[0] / source.size[1])))
48
+ if size[0] == 0:
49
+ return (int(size[1] * (source.size[0] / source.size[1])), size[1])
50
+
51
+ return size
52
+
53
+ def createthumb(source, size, fixed, new=False):
54
+
55
+ # https://pillow.readthedocs.io/en/latest/reference/Image.html#PIL.Image.Image.thumbnail
56
+ # https://pillow.readthedocs.io/en/latest/handbook/concepts.html#filters-comparison-table
57
+ # https://pillow.readthedocs.io/en/latest/reference/Image.html#PIL.Image.Image.paste
58
+ if hasattr(Image, '__version__') and versiontuple(Image.__version__) > (7,0,0):
59
+ source.thumbnail(size, Image.LANCZOS, 4)
60
+ else:
61
+ source.thumbnail(size, Image.ANTIALIAS)
62
+
63
+ if fixed:
64
+ offset_x = max(int((size[0] - source.size[0]) / 2), 0)
65
+ offset_y = max(int((size[1] - source.size[1]) / 2), 0)
66
+ dest = Image.new('RGBA', size, (255,255,255,1))
67
+ dest.paste(source, (offset_x, offset_y))
68
+ elif new:
69
+ if (source.size < size):
70
+ dest = Image.new('RGBA', source.size, (255,255,255,1))
71
+ dest.paste(source)
72
+ else:
73
+ dest = Image.new('RGBA', size, (255,255,255,1))
74
+ dest.paste(source)
75
+ else:
76
+ dest = source
77
+
78
+ return dest
79
+
80
+
81
+ # Animated resizing
60
82
  # based on https://stackoverflow.com/a/41827681/2980105
61
- if source.format == 'PNG' and ".png" in fileout:
83
+ def resizeAnimatedGif(source, size, fixed):
84
+
85
+ # Animated GIF resizing
86
+ # https://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html#gif
87
+ colors = source.getpalette()
88
+ dest = []
62
89
 
63
- frames = []
64
90
  try:
65
91
  while True:
66
- new_frame = Image.new('RGBA', source.size, (255,255,255,1))
67
- new_frame.paste(source, (0,0), source.convert('RGBA'))
68
- new_frame.thumbnail(size, Image.ANTIALIAS)
69
-
70
- if fixed:
71
- offset_x = int(max((size[0] - new_frame.size[0]) / 2, 0))
72
- offset_y = int(max((size[1] - new_frame.size[1]) / 2, 0))
73
- final_frame = Image.new('RGBA', size, (255,255,255,1))
74
- final_frame.paste(new_frame, (offset_x, offset_y))
75
- frames.append(final_frame)
76
- else:
77
- frames.append(new_frame)
78
-
79
- b = source.tell()
80
- source.seek(b + 1)
81
- if b == source.tell():
92
+ # If the GIF uses local colour tables, each frame will have its own palette.
93
+ # If not, we need to apply the global palette to the new frame.
94
+ if not source.getpalette():
95
+ source.putpalette(colors)
96
+
97
+ frame = Image.new('RGBA', source.size, (255,255,255,1))
98
+ frame.paste(source, (0,0), source.convert('RGBA'))
99
+ dest.append(createthumb(frame, size, fixed))
100
+
101
+ idx = source.tell()
102
+ source.seek(idx + 1)
103
+ if idx == source.tell():
82
104
  break
83
105
  except EOFError:
84
106
  pass
85
- # Animated GIF resizing
86
- # based on https://stackoverflow.com/a/41827681/2980105
87
- elif source.format == 'GIF' and source.is_animated and ".gif" in fileout:
88
107
 
89
- p = source.getpalette()
90
- frames = []
108
+ return dest
109
+
110
+ def resizeAnimatedPng(source, size, fixed):
111
+
112
+ # Animated PNG resizing (since PIL 7.1.0)
113
+ # https://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html#apng-sequences
114
+ dest = []
115
+
91
116
  try:
92
117
  while True:
93
- # If the GIF uses local colour tables, each frame will have its own palette.
94
- # If not, we need to apply the global palette to the new frame.
95
- if not source.getpalette():
96
- source.putpalette(p)
97
-
98
- new_frame = Image.new('RGBA', source.size, (255,255,255,1))
99
- new_frame.paste(source, (0,0), source.convert('RGBA'))
100
- new_frame.thumbnail(size, Image.ANTIALIAS)
101
-
102
- if fixed:
103
- offset_x = int(max((size[0] - new_frame.size[0]) / 2, 0))
104
- offset_y = int(max((size[1] - new_frame.size[1]) / 2, 0))
105
- final_frame = Image.new('RGBA', size, (255,255,255,1))
106
- final_frame.paste(new_frame, (offset_x, offset_y))
107
- frames.append(final_frame)
108
- else:
109
- frames.append(new_frame)
110
-
111
- b = source.tell()
112
- source.seek(b + 1)
113
- if b == source.tell():
118
+ frame = Image.new('RGBA', source.size, (255,255,255,1))
119
+ frame.paste(source, (0,0), source.convert('RGBA'))
120
+ dest.append(createthumb(frame, size, fixed))
121
+
122
+ idx = source.tell()
123
+ source.seek(idx + 1)
124
+ if idx == source.tell():
114
125
  break
115
126
  except EOFError:
116
127
  pass
117
- # Animated WEBP resizing (since PIL 5.0.0)
118
- # based on https://stackoverflow.com/a/41827681/2980105
119
- elif source.format == 'WEBP' and ".webp" in fileout:
120
128
 
121
- frames = []
129
+ return dest
130
+
131
+ def resizeAnimatedWebp(source, size, fixed):
132
+
133
+ # Animated WEBP resizing (since PIL 5.0.0)
134
+ # https://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html#webp
135
+ dest = []
136
+
122
137
  try:
123
138
  while True:
124
- new_frame = Image.new('RGBA', source.size, (255,255,255,1))
125
- new_frame.paste(source, (0,0), source.convert('RGBA'))
126
- new_frame.thumbnail(size, Image.ANTIALIAS)
127
-
128
- if fixed:
129
- offset_x = int(max((size[0] - new_frame.size[0]) / 2, 0))
130
- offset_y = int(max((size[1] - new_frame.size[1]) / 2, 0))
131
- final_frame = Image.new('RGBA', size, (255,255,255,1))
132
- final_frame.paste(new_frame, (offset_x, offset_y))
133
- frames.append(final_frame)
134
- else:
135
- frames.append(new_frame)
136
-
137
- b = source.tell()
138
- source.seek(b + 1)
139
- if b == source.tell():
139
+ frame = Image.new('RGBA', source.size, (255,255,255,1))
140
+ frame.paste(source, (0,0), source.convert('RGBA'))
141
+ dest.append(createthumb(frame, size, fixed))
142
+
143
+ idx = source.tell()
144
+ source.seek(idx + 1)
145
+ if idx == source.tell():
140
146
  break
141
147
  except EOFError:
142
148
  pass
143
- # Standard resizing
144
- elif fixed:
145
- source.thumbnail(size, Image.ANTIALIAS)
146
- offset_x = int(max((size[0] - source.size[0]) / 2, 0))
147
- offset_y = int(max((size[1] - source.size[1]) / 2, 0))
148
- dest = Image.new('RGBA', size, (255,255,255,1))
149
- dest.paste(source, (offset_x, offset_y))
150
- else:
151
- source.thumbnail(size, Image.ANTIALIAS)
152
- dest = Image.new('RGBA', (source.size[0], source.size[1]), (255,255,255,1))
153
- dest.paste(source)
154
149
 
150
+ return dest
151
+
152
+
153
+ # File saving
155
154
  # https://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html
156
- # source.info.get('loop')=None
157
- if ".png" in fileout:
155
+ # todo: source.info.get('loop')=None
156
+ def saveGif(dest, fileout, quality):
157
+
158
+ try:
159
+ if len(dest) == 1:
160
+ dest[0].save(fileout, 'GIF', optimize=True)
161
+ else:
162
+ dest[0].save(fileout, 'GIF', optimize=True, save_all=True, append_images=dest[1:],
163
+ loop=0, duration=source.info.get('duration'), default_image=source.info.get('default_image'))
164
+ except:
165
+ dest.save(fileout, 'GIF', optimize=True)
166
+
167
+ def savePng(dest, fileout, quality):
168
+
158
169
  # The image quality, on a scale from 0 (best-speed) to 9 (best-compression), the default is 6
159
170
  # but when optimize option is True compress_level has no effect
171
+ if quality < 1:
172
+ quality = 6
173
+ elif quality > 9:
174
+ quality = 9
175
+
160
176
  try:
161
- if len(frames) == 1:
162
- frames[0].save(fileout, 'PNG', optimize=True, compress_level=9)
177
+ if len(dest) == 1:
178
+ dest[0].save(fileout, 'PNG', optimize=True, compress_level=9)
163
179
  else:
164
- frames[0].save(fileout, 'PNG', optimize=True, compress_level=9, save_all=True, append_images=frames[1:],
180
+ dest[0].save(fileout, 'PNG', optimize=True, compress_level=9, save_all=True, append_images=dest[1:],
165
181
  loop=0, duration=source.info.get('duration'))
166
182
  except:
167
183
  dest.save(fileout, 'PNG', optimize=True, compress_level=9)
168
- elif ".gif" in fileout:
169
- try:
170
- if len(frames) == 1:
171
- frames[0].save(fileout, 'GIF', optimize=True)
172
- else:
173
- frames[0].save(fileout, 'GIF', optimize=True, save_all=True, append_images=frames[1:],
174
- loop=0, duration=source.info.get('duration'), default_image=source.info.get('default_image'))
175
- except:
176
- dest.save(fileout, 'GIF', optimize=True)
177
- elif ".webp" in fileout:
184
+
185
+ def saveWebp(dest, fileout, quality):
186
+
178
187
  # The image quality, on a scale from 0 (worst) to 100 (best), the default is 80 (lossy, 0 gives the smallest size and 100 the largest)
179
188
  # The method, on a scale from 0 (fast) to 6 (slower-better), the default is 0
180
189
  if quality < 1:
181
190
  quality = 80
182
191
  elif quality > 100:
183
192
  quality = 100
193
+
184
194
  try:
185
- if len(frames) == 1:
186
- frames[0].save(fileout, 'WEBP', method=5, quality=quality)
195
+ if len(dest) == 1:
196
+ dest[0].save(fileout, 'WEBP', method=5, quality=quality)
187
197
  else:
188
- frames[0].save(fileout, 'WEBP', method=5, quality=quality, save_all=True, append_images=frames[1:],
198
+ dest[0].save(fileout, 'WEBP', method=5, quality=quality, save_all=True, append_images=dest[1:],
189
199
  loop=0, duration=source.info.get('duration'))
190
200
  except:
191
201
  dest.save(fileout, 'WEBP', method=5, quality=quality)
192
- else:
202
+
203
+ def saveJpg(dest, fileout, quality):
204
+
193
205
  # The image quality, on a scale from 0 (worst) to 95 (best), the default is 75
194
206
  if quality < 1:
195
207
  quality = 75
196
208
  elif quality > 95:
197
209
  quality = 95
198
- dest.convert('RGB').save(fileout, 'JPEG', optimize=True, quality=quality)
210
+
211
+ dest.convert('RGB').save(fileout, 'JPEG', optimize=True, subsampling=0, quality=quality)
212
+
213
+
214
+ # python-scour
215
+ if ".svg" in fileout:
216
+ from scour.scour import (sanitizeOptions, start)
217
+ options = sanitizeOptions()
218
+ options.strip_xml_prolog = True # --strip-xml-prolog
219
+ options.remove_metadata = True # --remove-metadata
220
+ options.strip_comments = True # --enable-comment-stripping
221
+ options.strip_ids = True # --enable-id-stripping
222
+ options.indent_type = None # --indent=none
223
+ start(options, open(filein, 'rb'), open(fileout, 'wb'))
224
+ # python-pil
225
+ else:
226
+ from PIL import Image, ImageSequence
227
+ source = Image.open(filein)
228
+ size = calcsize(source, size)
229
+
230
+ if source.format == 'GIF' and ".gif" in fileout:
231
+ dest = resizeAnimatedGif(source, size, fixed)
232
+ saveGif(dest, fileout, quality)
233
+ elif source.format == 'PNG' and ".png" in fileout:
234
+ dest = resizeAnimatedPng(source, size, fixed)
235
+ savePng(dest, fileout, quality)
236
+ elif source.format == 'WEBP' and ".webp" in fileout:
237
+ dest = resizeAnimatedWeb(source, size, fixed)
238
+ saveWebp(dest, fileout, quality)
239
+ else:
240
+ dest = createthumb(source, size, fixed, True)
241
+ saveJpg(dest, fileout, quality)
199
242
 
200
243
  exit(0)