hyde_admin 0.0.3 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a05ad4bb0704e1175cd5ed0393ae09181a0241dd423add001cd7ef4cc365ed2
4
- data.tar.gz: 1db71be2ffc12226a0c10fb66751311e4bd6b8d795aa3bccf4dcc9da5993e557
3
+ metadata.gz: efb3733133bc8adfcf1bfa8a365ef7a5e7d98b87f03f615b538ccc874ec76fa1
4
+ data.tar.gz: 38a47d3d53dd35bae51f7673c21bcb25b85bf1f18992f9305cad83486ed46205
5
5
  SHA512:
6
- metadata.gz: '0902597c60ffe712e999a065655ad6034f3d9e2b62f129b815e2139ef684d0f565f08d0fda4ad2f59b85a182da93f0d730dcfbad99128521befe593d266cd21e'
7
- data.tar.gz: 8926be4affe34325d115ccf1788609fc46a7770a770233944a425a2a054870b501861601eaf232ab73f2ac48741068b611ec59e3535035010513917b3c9d857d
6
+ metadata.gz: 32f1fa3002f7b43460f94ca833c56c4c0ea820f4db3c03552f28c042c89286a553a9b74baddb9f8ac4b38b03f0b0bcfc1aea1ec5221b9f114f88498efd87ea71
7
+ data.tar.gz: 83b5a59c1a4ca153b58cff1ae58459831e6d951d954a5382b0880c3773abce88c159eb9bfecea914120add871ce34828ff211b0ef5287e1b8bae53f9688a1749
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/.idea/hyde_admin.iml CHANGED
@@ -12,7 +12,11 @@
12
12
  <orderEntry type="inheritedJdk" />
13
13
  <orderEntry type="sourceFolder" forTests="false" />
14
14
  <orderEntry type="library" scope="PROVIDED" name="concurrent-ruby (v1.1.9, RVM: ruby-2.7.0) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="ffi (v1.15.4, RVM: ruby-2.7.0) [gem]" level="application" />
15
16
  <orderEntry type="library" scope="PROVIDED" name="i18n (v1.8.10, RVM: ruby-2.7.0) [gem]" level="application" />
17
+ <orderEntry type="library" scope="PROVIDED" name="image_processing (v1.12.1, RVM: ruby-2.7.0) [gem]" level="application" />
18
+ <orderEntry type="library" scope="PROVIDED" name="mini_magick (v4.11.0, RVM: ruby-2.7.0) [gem]" level="application" />
19
+ <orderEntry type="library" scope="PROVIDED" name="ruby-vips (v2.0.17, RVM: ruby-2.7.0) [gem]" level="application" />
16
20
  </component>
17
21
  <component name="RModuleSettingsStorage">
18
22
  <LOAD_PATH number="0" />
data/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ # 0.0.8
2
+
3
+ Resize image at upload with ImageProcessing (MiniMagick)
4
+
5
+ # 0.0.7
6
+
7
+ Post edit : bugfix, keep layout & format when we don't show input.
8
+ CodeMirror editor : form-control style
9
+ Locales shows possible value for config.
10
+
11
+ # 0.0.6
12
+
13
+ Form upload image + style images selector
14
+ Menu follows workflow
15
+ Configuration remove beforeSend
16
+ Rsync params
17
+ Publish only for drafts
18
+
19
+ # 0.0.5
20
+
21
+ Sometimes no tags
22
+
23
+ # 0.0.4
24
+
25
+ Correct images selector
26
+ Some refactoring
27
+ Escape translations
28
+
1
29
  # 0.0.3
2
30
 
3
31
  Bugfix (see commits)
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## Hyde admin
2
+
3
+ Hyde_admin is a administration frontend for Jekyll (static site generator in Ruby).
4
+
1
5
  ## Getting Started with Hyde Admin
2
6
 
3
7
  Add
data/TODO.md CHANGED
@@ -1 +1,3 @@
1
- Overview btn for posts/drafts/pages (save && rebuild && open in new tab)
1
+ Overview btn for posts/drafts/pages (save && rebuild && open in new tab)
2
+ See TINYmce for wysiwyg editor
3
+ Add defaults class for images injected by editor
@@ -32,63 +32,62 @@
32
32
  <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
33
33
  <div class="position-sticky pt-3">
34
34
  <ul class="nav flex-column">
35
- <li class="nav-item">
36
- <a class="nav-link active" aria-current="page" href="/<%= @hyde_parameters['site_index'] %>">
37
- <span data-feather="home" class="fas fa-eye"></span>
38
- <%= t.overview.capitalize %>
39
- </a>
40
- </li>
41
35
  <li class="nav-item">
42
36
  </li>
43
37
  <li class="nav-item">
44
38
  <a class="nav-link active" aria-current="page" href="/dashboard">
45
39
  <span data-feather="home" class="fas fa-tachometer-alt"></span>
46
- <%= t.dashboard.capitalize %>
40
+ <%= EscapeUtils.escape_html t.dashboard.capitalize %>
47
41
  </a>
48
42
  </li>
49
43
  <li class="nav-item">
50
44
  <a class="nav-link" href="/pages/index">
51
45
  <span data-feather="file" class="fas fa-file"></span>
52
- <%= t.pages.capitalize %>
46
+ <%= EscapeUtils.escape_html t.pages.capitalize %>
53
47
  </a>
54
48
  </li>
55
49
  <li class="nav-item">
56
50
  <a class="nav-link" href="/drafts/index">
57
51
  <span data-feather="shopping-cart" class="fas fa-file"></span>
58
- <%= t.drafts.capitalize %>
52
+ <%= EscapeUtils.escape_html t.drafts.capitalize %>
59
53
  </a>
60
54
  </li>
61
55
  <li class="nav-item">
62
56
  <a class="nav-link" href="/posts/index">
63
57
  <span data-feather="users" class="fas fa-file"></span>
64
- <%= t.posts.capitalize %>
58
+ <%= EscapeUtils.escape_html t.posts.capitalize %>
65
59
  </a>
66
60
  </li>
67
- <li class="nav-item"></li>
68
61
  <li class="nav-item">
69
62
  <a class="nav-link" href="/files/index">
70
63
  <span data-feather="users" class="fas fa-copy"></span>
71
- <%= t.files.capitalize %>
64
+ <%= EscapeUtils.escape_html t.files.capitalize %>
65
+ </a>
66
+ </li>
67
+ <li></li>
68
+ <li class="nav-item mb-4 mt-4">
69
+ <a class="nav-link" href="/configuration">
70
+ <span data-feather="layers" class="fas fa-tools"></span>
71
+ <%= EscapeUtils.escape_html t.configuration.capitalize %>
72
72
  </a>
73
73
  </li>
74
- <li class="nav-item"></li>
74
+ <li></li>
75
75
  <li class="nav-item">
76
76
  <a class="nav-link active" aria-current="page" href="/rebuild" id="btn-rebuild">
77
77
  <span data-feather="home" class="fas fa-hammer"></span>
78
- <%= t.rebuild.capitalize %>
78
+ <%= EscapeUtils.escape_html t.rebuild.capitalize %>
79
79
  </a>
80
80
  </li>
81
81
  <li class="nav-item">
82
- <a class="nav-link active" aria-current="page" href="/deploy" id="btn-deploy">
83
- <span data-feather="home" class="fas fa-cloud-upload-alt"></span>
84
- <%= t.deploy.capitalize %>
82
+ <a class="nav-link active" aria-current="page" target="_blank" href="/<%= @hyde_parameters['site_index'] %>">
83
+ <span data-feather="home" class="fas fa-eye"></span>
84
+ <%= EscapeUtils.escape_html t.overview.capitalize %>
85
85
  </a>
86
86
  </li>
87
- <li class="nav-item"></li>
88
87
  <li class="nav-item">
89
- <a class="nav-link" href="/configuration">
90
- <span data-feather="layers" class="fas fa-tools"></span>
91
- <%= t.configuration.capitalize %>
88
+ <a class="nav-link active" aria-current="page" href="/deploy" id="btn-deploy">
89
+ <span data-feather="home" class="fas fa-cloud-upload-alt"></span>
90
+ <%= EscapeUtils.escape_html t.deploy.capitalize %>
92
91
  </a>
93
92
  </li>
94
93
  </ul>
@@ -124,20 +123,49 @@
124
123
  <div class="modal-dialog" role="document">
125
124
  <div class="modal-content">
126
125
  <div class="modal-header">
127
- <h5 class="modal-title">Images</h5>
128
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
126
+ <h5 class="modal-title"><%= t.images.capitalize %></h5>
127
+ <!--
128
+ <button type="button" class="btn btn-default close" data-dismiss="modal" aria-label="Close">
129
129
  <span aria-hidden="true">&times;</span>
130
130
  </button>
131
+ -->
132
+ <button type="button" class="btn btn-outline-secondary btn-sm load-image">
133
+ <%= t.load_images.capitalize %>
134
+ </button>
131
135
  </div>
132
- <div class="modal-body modal-body-image">
133
- <% path_of_images = File.join(Dir.pwd, @hyde_parameters['images_path'], "**") %>
134
- <% $stderr.puts(path_of_images) %>
135
- <% Dir.glob(path_of_images)[(@page || 0) * 9, ((@page || 0) + 1) * 9 ].each do |img| %>
136
- <% img = img.gsub(Dir.pwd, "") %>
137
- <div class="image-element">
138
- <img src="<%= img %>" alt="<%= img %>">
136
+ <div class="modal-body">
137
+ <div>
138
+ <div class="image-selector-search d-block" data-page="0">
139
+ <form action="" class="form-inline">
140
+ <div class="form-group mb-2">
141
+ <label>
142
+ <input class="form-check-input" type="radio" name="sort_date" value="asc"> <%= EscapeUtils.escape_html t.newer.capitalize %>
143
+ </label>
144
+ &nbsp;&nbsp;&nbsp;
145
+ <label>
146
+ <input class="form-check-input" type="radio" name="sort_date" value="desc" checked> <%= EscapeUtils.escape_html t.older.capitalize %>
147
+ </label>
148
+ </div>
149
+ <div class="form-group mb-2">
150
+ <label for="inputFilename" class="sr-only"><%= EscapeUtils.escape_html t.filename.capitalize %></label>
151
+ <input type="text" class="form-control" name="filename" id="inputFilename" placeholder="<%= EscapeUtils.escape_html t.filename_placeholder.capitalize %>">
152
+ </div>
153
+ <button type="submit" class="btn btn-primary image-selector-search-submit d-block mb-2"><%= EscapeUtils.escape_html t.search.capitalize %></button>
154
+ </form>
155
+ </div>
156
+ <div class="image-selector-content">
157
+ <% path = File.join(Pathname.new(Mid.gem_source_path), 'admin_views', 'partials', 'images_page.html.erb') %>
158
+ <%= ERB.new(File.read(path)).result(binding) %>
139
159
  </div>
140
- <% end %>
160
+ <div class="image-selector-page text-center">
161
+ <a href="#" title="<%= EscapeUtils.escape_html t.previous_images %>" class="btn btn-secondary image-selector-page-prev px-4">
162
+ <i class="fas fa-chevron-left"></i>
163
+ </a>
164
+ <a href="#" title="<%= EscapeUtils.escape_html t.next_images %>" class="btn btn-secondary image-selector-page-next px-4">
165
+ <i class="fas fa-chevron-right"></i>
166
+ </a>
167
+ </div>
168
+ </div>
141
169
  </div>
142
170
  </div>
143
171
  </div>
@@ -154,6 +182,45 @@
154
182
  });
155
183
  }
156
184
  <% end %>
185
+
186
+ function search(offset_page){
187
+ let sort_date = $('.image-selector-search input[name=sort_date]:checked').val();
188
+ let filename = $('.image-selector-search input[name=filename]').val();
189
+ let page = $('.image-selector-search').attr('data-page');
190
+ let new_page = parseInt(page) + offset_page;
191
+
192
+ if(new_page < 0){
193
+ new_page = 0;
194
+ }
195
+
196
+ $.post( "/ajax/images", { sort_date: sort_date, filename: filename, page: new_page })
197
+ .done(function( data ) {
198
+ $('.image-selector-content').html(data);
199
+ });
200
+
201
+ $('.image-selector-search').attr('data-page', new_page);
202
+ return false;
203
+ }
204
+
205
+ $(document).on('click', '.image-selector-search-submit', function(){
206
+ search(0);
207
+ return false;
208
+ });
209
+ $(document).on('click', '.image-selector-page-prev', function(){
210
+ search(-1);
211
+ return false;
212
+ });
213
+ $(document).on('click', '.image-selector-page-next', function(){
214
+ search(1);
215
+ return false;
216
+ });
217
+ $(document).on('click', '.load-image', function(){
218
+ var windowObjectReference = window.open("/upload_image_form", "update_image", "dialog=yes,menubar=no,location=no,resizable=no,scrollbars=yes,status=yes,outerWidth=800,innerHeight=300,width=800,height=300");
219
+ return false;
220
+ });
221
+ function reload_image(){
222
+ $('.load-image').click();
223
+ }
157
224
  </script>
158
225
  <script src="/fslightbox/fslightbox.js"></script>
159
226
  </body>
@@ -1,13 +1,13 @@
1
- <h2><%= t.configuration.capitalize %></h2>
1
+ <h2><%= EscapeUtils.escape_html t.configuration.capitalize %></h2>
2
2
 
3
3
  <form action="/configuration" method="post">
4
4
  <% @hyde_parameters.each_pair do |setting, value| %>
5
5
  <div class="mb-3">
6
- <label for="i-<%= setting %>" class="form-label"><%= t.send(setting).capitalize %></label>
6
+ <label for="i-<%= setting %>" class="form-label"><%= (EscapeUtils.escape_html t.send(setting).capitalize rescue setting) %></label>
7
7
  <input type="text" class="form-control" value="<%= value %>" name="<%= setting %>" id="i-<%= setting %>">
8
- <div id="i-<%= setting %>-help" class="form-text"><%= t.send("help_#{setting}").capitalize %></div>
8
+ <div id="i-<%= setting %>-help" class="form-text"><%= (EscapeUtils.escape_html t.send("help_#{setting}").capitalize rescue '') %></div>
9
9
  </div>
10
10
  <% end %>
11
- <button type="submit" class="btn btn-primary"><%= t.submit.capitalize %></button>
11
+ <button type="submit" class="btn btn-primary"><%= EscapeUtils.escape_html t.submit.capitalize %></button>
12
12
  </form>
13
13
 
@@ -1 +1 @@
1
- <h2><%= t.dashboard.capitalize %></h2>
1
+ <h2><%= EscapeUtils.escape_html t.dashboard.capitalize %></h2>
@@ -1,24 +1,24 @@
1
1
  <div class="codemirror-toolbar btn-toolbar" role="toolbar">
2
2
  <div class="btn-group mr-2" role="group" aria-label="Undo/redo">
3
- <button type="button" class="btn btn-light"><i class="fas fa-undo-alt" title="<%= t.editor_undo %>"></i></button>
4
- <button type="button" class="btn btn-light"><i class="fas fa-redo-alt" title="<%= t.editor_redo %>"></i></button>
3
+ <button type="button" class="btn btn-light"><i class="fas fa-undo-alt" title="<%= EscapeUtils.escape_html t.editor_undo %>"></i></button>
4
+ <button type="button" class="btn btn-light"><i class="fas fa-redo-alt" title="<%= EscapeUtils.escape_html t.editor_redo %>"></i></button>
5
5
  </div>
6
6
  <div class="btn-group mr-2" role="group" aria-label="Structural tags">
7
- <button type="button" class="btn btn-light"><i class="fas fa-file-image" title="<%= t.editor_file %>"></i></button>
8
- <button type="button" class="btn btn-light"><i class="fas fa-list cmt-replace" title="<%= t.editor_list %>"></i></button>
9
- <button type="button" class="btn btn-light"><i class="fas fa-list-ol cmt-replace" title="<%= t.editor_list_ol %>"></i></button>
10
- <button type="button" class="btn btn-light"><i class="fas fa-link cmt-replace" title="<%= t.editor_link %>"></i></button>
11
- <button type="button" class="btn btn-light"><i class="fas fa-quote-left cmt-replace" title="<%= t.editor_quote %>"></i></button>
7
+ <button type="button" class="btn btn-light"><i class="fas fa-file-image" title="<%= EscapeUtils.escape_html t.editor_file %>"></i></button>
8
+ <button type="button" class="btn btn-light"><i class="fas fa-list cmt-replace" title="<%= EscapeUtils.escape_html t.editor_list %>"></i></button>
9
+ <button type="button" class="btn btn-light"><i class="fas fa-list-ol cmt-replace" title="<%= EscapeUtils.escape_html t.editor_list_ol %>"></i></button>
10
+ <button type="button" class="btn btn-light"><i class="fas fa-link cmt-replace" title="<%= EscapeUtils.escape_html t.editor_link %>"></i></button>
11
+ <button type="button" class="btn btn-light"><i class="fas fa-quote-left cmt-replace" title="<%= EscapeUtils.escape_html t.editor_quote %>"></i></button>
12
12
  </div>
13
13
  <div class="btn-group mr-2" role="group" aria-label="Style tags">
14
- <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-1" title="<%= t.editor_title_h1 %>">1</i></button>
15
- <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-2" title="<%= t.editor_title_h2 %>">2</i></button>
16
- <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-3" title="<%= t.editor_title_h3 %>">3</i></button>
17
- <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-4" title="<%= t.editor_title_h4 %>">4</i></button>
18
- <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-5" title="<%= t.editor_title_h5 %>">5</i></button>
19
- <button type="button" class="btn btn-light"><i class="fas fa-underline cmt-replace" title="<%= t.editor_underline %>"></i></button>
20
- <button type="button" class="btn btn-light"><i class="fas fa-bold cmt-replace" title="<%= t.editor_bold %>"></i></button>
21
- <button type="button" class="btn btn-light"><i class="fas fa-italic cmt-replace" title="<%= t.editor_italic %>"></i></button>
22
- <button type="button" class="btn btn-light"><i class="fas fa-strikethrough cmt-replace" title="<%= t.editor_strikethrough %>"></i></button>
14
+ <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-1" title="<%= EscapeUtils.escape_html t.editor_title_h1 %>">1</i></button>
15
+ <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-2" title="<%= EscapeUtils.escape_html t.editor_title_h2 %>">2</i></button>
16
+ <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-3" title="<%= EscapeUtils.escape_html t.editor_title_h3 %>">3</i></button>
17
+ <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-4" title="<%= EscapeUtils.escape_html t.editor_title_h4 %>">4</i></button>
18
+ <button type="button" class="btn btn-light"><i class="fas fa-heading cmt-heading-5" title="<%= EscapeUtils.escape_html t.editor_title_h5 %>">5</i></button>
19
+ <button type="button" class="btn btn-light"><i class="fas fa-underline cmt-replace" title="<%= EscapeUtils.escape_html t.editor_underline %>"></i></button>
20
+ <button type="button" class="btn btn-light"><i class="fas fa-bold cmt-replace" title="<%= EscapeUtils.escape_html t.editor_bold %>"></i></button>
21
+ <button type="button" class="btn btn-light"><i class="fas fa-italic cmt-replace" title="<%= EscapeUtils.escape_html t.editor_italic %>"></i></button>
22
+ <button type="button" class="btn btn-light"><i class="fas fa-strikethrough cmt-replace" title="<%= EscapeUtils.escape_html t.editor_strikethrough %>"></i></button>
23
23
  </div>
24
24
  </div>
@@ -8,9 +8,9 @@ $(document).on('click', '.codemirror-toolbar .fa-file-image', function(){
8
8
  $('.modal-image').modal('show');
9
9
  });
10
10
  $(document).on('click', '.modal-image img', function(){
11
- let img_src = '<img src="' + $(this).attr('src') + '" alt="<%= t.default_alt_img %>" title="<%= t.default_title_img %>" />';
11
+ let img_src = '<img src="' + $(this).attr('src') + '" alt="<%= EscapeUtils.escape_html t.default_alt_img %>" title="<%= EscapeUtils.escape_html t.default_title_img %>" />';
12
12
  if(window.mode_markdown){
13
- img_src = '![<%= t.default_alt_img %>](' + $(this).attr('src') + ')';
13
+ img_src = '![<%= EscapeUtils.escape_html t.default_alt_img %>](' + $(this).attr('src') + ')';
14
14
  }
15
15
  window.myCodeMirror.replaceSelection(img_src);
16
16
  $('.modal-image').modal('hide');
@@ -1,30 +1,30 @@
1
- <h2><%= t.edit.capitalize %></h2>
1
+ <h2><%= EscapeUtils.escape_html t.edit.capitalize %></h2>
2
2
 
3
3
  <form action="/files/update?file=<%= @file %>" method="post">
4
4
  <% if @has_header %>
5
5
  <div class="mb-3">
6
- <label for="i-header" class="form-label"><%= t.header.capitalize %></label>
6
+ <label for="i-header" class="form-label"><%= EscapeUtils.escape_html t.header.capitalize %></label>
7
7
  <textarea class="form-control text-editor" id="i-header" rows="3" name="header" style="font-family: <%= (['.html', '.xml', '.yml', '.js', '.md'].include?(File.extname(@file)) ? 'monospace' : 'inherit') %>"><%= @header %></textarea>
8
8
  </div>
9
9
  <% end %>
10
10
  <div class="mb-3">
11
- <label for="i-content" class="form-label"><%= t.content.capitalize %>
11
+ <label for="i-content" class="form-label"><%= EscapeUtils.escape_html t.content.capitalize %>
12
12
  <% if ['.html','.md'].include?(File.extname(@file)) %>
13
13
  <a href="https://jekyllrb.com/docs/liquid/" class="text-secondary" target="_blank"><i class="fas fa-question-circle"></i></a>
14
14
  <% end %>
15
15
  </label>
16
16
 
17
17
  <% if @has_editor %>
18
- <% path = File.join(Pathname.new(File.dirname(__FILE__)).parent, 'editor_html.erb') %>
18
+ <% path = File.join(Pathname.new(Mid.gem_source_path), 'admin_views', 'editor_html.erb') %>
19
19
  <%= ERB.new(File.read(path)).result(binding) %>
20
20
  <% end %>
21
21
 
22
22
  <textarea class="form-control text-editor" id="i-content" rows="3" name="content" style="font-family: <%= (['.html', '.xml', '.yml', '.js', '.md'].include?(File.extname(@file)) ? 'monospace' : 'inherit') %>"><%= @content %></textarea>
23
23
 
24
24
  <script type="text/javascript" charset="utf-8">
25
- <% path = File.join(Pathname.new(File.dirname(__FILE__)).parent, 'editor_js.erb') %>
25
+ <% path = File.join(Pathname.new(Mid.gem_source_path), 'admin_views', 'editor_js.erb') %>
26
26
  <%= ERB.new(File.read(path)).result(binding) %>
27
27
  </script>
28
28
  </div>
29
- <button type="submit" class="btn btn-primary"><%= t.submit.capitalize %></button>
29
+ <button type="submit" class="btn btn-primary"><%= EscapeUtils.escape_html t.submit.capitalize %></button>
30
30
  </form>
@@ -1,4 +1,4 @@
1
- <h2><%= t.files.capitalize %></h2>
1
+ <h2><%= EscapeUtils.escape_html t.files.capitalize %></h2>
2
2
 
3
3
  <div class="row g-3">
4
4
  <div class="col-auto">
@@ -8,7 +8,7 @@
8
8
  <input type="file" multiple name="files[]" class="form-control">
9
9
  </div>
10
10
  <div class="col-auto">
11
- <button type="submit" class="btn btn-outline-secondary"><i class="fa fa-plus" title="<%= t.create.capitalize %>"></i> <%= t.upload %></button>
11
+ <button type="submit" class="btn btn-outline-secondary"><i class="fa fa-plus" title="<%= EscapeUtils.escape_html t.create.capitalize %>"></i> <%= EscapeUtils.escape_html t.upload %></button>
12
12
  </div>
13
13
  </div>
14
14
  </form>
@@ -19,10 +19,10 @@
19
19
  <form method="post" action="/files/create_dir?dir_path=<%= @dir_path %>">
20
20
  <div class="row g-2 align-items-center">
21
21
  <div class="col-auto">
22
- <input type="text" name="directory_name" class="form-control" placeholder="<%= t.directory_input_placeholder %>">
22
+ <input type="text" name="directory_name" class="form-control" placeholder="<%= EscapeUtils.escape_html t.directory_input_placeholder %>">
23
23
  </div>
24
24
  <div class="col-auto">
25
- <button type="submit" class="btn btn-outline-secondary"><i class="fa fa-plus" title="<%= t.create.capitalize %>"></i> <%= t.create %></button>
25
+ <button type="submit" class="btn btn-outline-secondary"><i class="fa fa-plus" title="<%= EscapeUtils.escape_html t.create.capitalize %>"></i> <%= EscapeUtils.escape_html t.create %></button>
26
26
  </div>
27
27
  </div>
28
28
  </form>
@@ -33,10 +33,10 @@
33
33
  <form method="post" action="/files/create_file?dir_path=<%= @dir_path %>">
34
34
  <div class="row g-2 align-items-center">
35
35
  <div class="col-auto">
36
- <input type="text" name="file_name" class="form-control" placeholder="<%= t.file_input_placeholder %>">
36
+ <input type="text" name="file_name" class="form-control" placeholder="<%= EscapeUtils.escape_html t.file_input_placeholder %>">
37
37
  </div>
38
38
  <div class="col-auto">
39
- <button type="submit" class="btn btn-outline-secondary"><i class="fa fa-plus" title="<%= t.create.capitalize %>"></i> <%= t.create %></button>
39
+ <button type="submit" class="btn btn-outline-secondary"><i class="fa fa-plus" title="<%= EscapeUtils.escape_html t.create.capitalize %>"></i> <%= EscapeUtils.escape_html t.create %></button>
40
40
  </div>
41
41
  </div>
42
42
  </form>
@@ -49,20 +49,20 @@
49
49
  <table class="table table-striped table-sm">
50
50
  <tr>
51
51
  <th>
52
- <%= t.file.capitalize %>
52
+ <%= EscapeUtils.escape_html t.file.capitalize %>
53
53
  </th>
54
54
  <th class="text-center">
55
- <%= t.edit.capitalize %>
55
+ <%= EscapeUtils.escape_html t.edit.capitalize %>
56
56
  </th>
57
57
  <th class="text-center">
58
- <%= t.delete.capitalize %>
58
+ <%= EscapeUtils.escape_html t.delete.capitalize %>
59
59
  </th>
60
60
  </tr>
61
61
  <% if @parent_dir %>
62
62
  <tr>
63
63
  <td colspan="3">
64
64
  <i class="fas fa-folder"></i>
65
- <a href="/files/index?dir_path=<%= File.dirname(@dir_path) %>">[<%= t.parent_dir.capitalize %>]</a>
65
+ <a href="/files/index?dir_path=<%= File.dirname(@dir_path) %>">[<%= EscapeUtils.escape_html t.parent_dir.capitalize %>]</a>
66
66
  </td>
67
67
  </tr>
68
68
  <% end %>
@@ -95,13 +95,13 @@
95
95
  </td>
96
96
  <td class="text-center">
97
97
  <% if !File.directory?(f) %>
98
- <a href="/files/edit?file=<%= f %>&dir_path=<%= @dir_path %>" class="btn btn-default"><i class="fa fa-edit" title="<%= t.edit %>"></i></a>
98
+ <a href="/files/edit?file=<%= f %>&dir_path=<%= @dir_path %>" class="btn btn-default"><i class="fa fa-edit" title="<%= EscapeUtils.escape_html t.edit %>"></i></a>
99
99
  <% end %>
100
100
  </td>
101
101
  <td class="text-center">
102
- <form method="post" action="/files/delete?file=<%= f %>" class="inline form-confirm" data-confirm="<%= t.are_you_sure %>">
102
+ <form method="post" action="/files/delete?file=<%= f %>" class="inline form-confirm" data-confirm="<%= EscapeUtils.escape_html t.are_you_sure %>">
103
103
  <input name="path" type="hidden" value="<%= @dir_path %>">
104
- <button type="submit" class="btn btn-default"><i class="fa fa-trash" title="<%= t.delete %>"></i></button>
104
+ <button type="submit" class="btn btn-default"><i class="fa fa-trash" title="<%= EscapeUtils.escape_html t.delete %>"></i></button>
105
105
  </form>
106
106
  </td>
107
107
  </tr>
@@ -0,0 +1,4 @@
1
+ <div class="image-element mb-4">
2
+ <img src="<%= @img %>" alt="<%= @img %>">
3
+ <span class="font-size:8px;"><%= @img.split('/').last %></span>
4
+ </div>
@@ -0,0 +1,8 @@
1
+ <% path = File.join(Pathname.new(Mid.gem_source_path), 'admin_views', 'partials', 'image_element.html.erb') %>
2
+ <% myerb = ERB.new(File.read(path), eoutvar: "@bidule") %>
3
+ <% # Why %= don't work !? Need to do a loop concat... %>
4
+ <% $stderr.puts @images %>
5
+ <% (@images || []).each do |img| %>
6
+ <% @img = img.gsub(Dir.pwd, "") %>
7
+ <%= myerb.result(binding) %>
8
+ <% end %>
@@ -1,81 +1,83 @@
1
- <h2><%= t.send(@type_file).capitalize %></h2>
1
+ <h2><%= EscapeUtils.escape_html t.send(@type_file).capitalize %></h2>
2
2
 
3
3
  <% file_params = (!@new_record ? "?file=#{@file}" : "") %>
4
4
 
5
5
  <form action="/<%= @type_file %><%= file_params %>" method="post">
6
6
  <% if !@new_record %>
7
7
  <div class="mb-3">
8
- <label for="i-path" class="form-label"><%= t.path.capitalize %></label>
8
+ <label for="i-path" class="form-label"><%= EscapeUtils.escape_html t.path.capitalize %></label>
9
9
  <div class="input-group">
10
- <input type="text" class="form-control" value="<%= @file %>" name="new_file" id="i-path">
11
10
  <span class="input-group-text">
12
- <i class="fas fa-calendar-alt" id="btn-date-path" title="<%= t.change_date_path %>"></i>
11
+ <i class="fas fa-calendar-alt" id="btn-date-path" title="<%= EscapeUtils.escape_html t.change_date_path %>"></i>
13
12
  </span>
14
13
  <span class="input-group-text">
15
- <i class="fas fa-sync-alt" id="btn-title-path" title="<%= t.change_title_path %>"></i>
14
+ <i class="fas fa-sync-alt" id="btn-title-path" title="<%= EscapeUtils.escape_html t.change_title_path %>"></i>
16
15
  </span>
16
+ <input type="text" class="form-control" value="<%= @file %>" name="new_file" id="i-path">
17
17
  </div>
18
- <div id="i-path-help" class="form-text"><%= t.help_path %></div>
18
+ <div id="i-path-help" class="form-text"><%= EscapeUtils.escape_html t.help_path %></div>
19
19
  </div>
20
20
  <% end %>
21
+
21
22
  <div class="mb-3">
22
- <label for="i-title" class="form-label"><%= t.title.capitalize %></label>
23
+ <label for="i-title" class="form-label"><%= EscapeUtils.escape_html t.title.capitalize %></label>
23
24
  <input type="text" value="<%= @headers.delete('title') %>" class="form-control" name="title" id="i-title">
24
25
  </div>
25
26
  <div class="mb-3">
26
- <label for="i-date" class="form-label"><%= t.date.capitalize %></label>
27
+ <label for="i-date" class="form-label"><%= EscapeUtils.escape_html t.date.capitalize %></label>
27
28
  <div class="input-group">
28
- <input type="text" value="<%= @headers.delete('date') || Time.now.strftime('%Y-%m-%d %H:%M:%S %z') %>" class="form-control" name="date" id="i-date">
29
29
  <span class="input-group-text">
30
- <i class="fas fa-calendar-day" id="btn-date-today" title="<%= t.set_date_today %>"></i>
30
+ <i class="fas fa-calendar-day" id="btn-date-today" title="<%= EscapeUtils.escape_html t.set_date_today %>"></i>
31
31
  </span>
32
+ <input type="text" value="<%= @headers.delete('date') || Time.now.strftime('%Y-%m-%d %H:%M:%S %z') %>" class="form-control" name="date" id="i-date">
32
33
  </div>
33
34
  </div>
34
35
  <div class="mb-3">
35
- <label for="i-tags" class="form-label"><%= t.tags.capitalize %></label>
36
- <input type="text" value="<%= @headers.delete('tags') %>" class="form-control" name="tags" id="i-tags">
37
- <div id="i-tags-help" class="form-text"><%= t.help_tags %></div>
38
- </div>
39
- <div class="mb-3 form-check">
40
- <input type="checkbox" class="form-check-input" name="publish" value="publish" id="i-publish">
41
- <label class="form-check-label" for="i-publish"><%= t.publish.capitalize %></label>
36
+ <label for="i-tags" class="form-label"><%= EscapeUtils.escape_html t.tags.capitalize %></label>
37
+ <input type="text" value="<%= Mid.extract_tags(@headers.delete('tags')).join(',') %>" class="form-control" name="tags" id="i-tags">
38
+ <div id="i-tags-help" class="form-text"><%= EscapeUtils.escape_html t.help_tags.capitalize %></div>
42
39
  </div>
43
40
 
41
+ <% if @type_file == 'drafts' %>
42
+ <div class="mb-3 form-check">
43
+ <input type="checkbox" class="form-check-input" name="publish" value="publish" id="i-publish">
44
+ <label class="form-check-label" for="i-publish"><%= EscapeUtils.escape_html t.publish.capitalize %></label>
45
+ </div>
46
+ <% end %>
47
+
48
+ <% selected_layout = @headers.delete('layout') %>
49
+ <% selected_layout = @hyde_parameters['default_layout'] if selected_layout.nil? || selected_layout.empty? %>
44
50
  <% if @hyde_parameters['display_layout'].to_s == 'true' %>
45
51
  <div class="mb-3">
46
- <label for="i-layout" class="form-label"><%= t.layout.capitalize %></label>
52
+ <label for="i-layout" class="form-label"><%= EscapeUtils.escape_html t.layout.capitalize %></label>
47
53
  <select class="form-select" aria-label="Choice layout" name="layout">
48
54
  <% Dir.glob(File.join(Dir.pwd, '_layouts', '*')).each do |f| %>
49
- <% layout = File.basename(f, File.extname(f)) %>
50
- <option <%= ((@headers['layout'] == f || (@headers['layout'].to_s.empty? && layout == @hyde_parameters['default_layout'])) ? 'selected' : '') %> value="<%= layout %>"><%= layout %></option>
55
+ <% layout_loop = File.basename(f, File.extname(f)) %>
56
+ <option <%= (layout_loop == selected_layout ? 'selected' : '') %> value="<%= layout_loop %>"><%= layout_loop %></option>
51
57
  <% end %>
52
58
  </select>
53
59
  </div>
54
- <% @headers.delete('layout') %>
55
60
  <% else %>
56
- <input type="hidden" name="layout" value="<%= @hyde_parameters['default_layout'] %>">
61
+ <input type="hidden" name="layout" value="<%= selected_layout %>">
57
62
  <% end %>
58
63
 
64
+ <% selected_format = File.extname(@file) %>
65
+ <% selected_format = ".#{@hyde_parameters['default_format']}" if selected_format.empty? %>
59
66
  <% if @hyde_parameters['display_format'].to_s == 'true' %>
60
67
  <div class="mb-3">
61
- <label for="i-format" class="form-label"><%= t.format.capitalize %></label>
68
+ <label for="i-format" class="form-label"><%= EscapeUtils.escape_html t.format.capitalize %></label>
62
69
  <select class="form-select" id="select-format" aria-label="Choice format" name="format">
63
- <% format = File.extname(@file) %>
64
- <% format = ".#{@hyde_parameters['default_format']}" if format.empty? %>
65
70
  <% { 'html' => 'html', 'markdown' => 'md' }.each do |k, v| %>
66
- <option <%= (format == ".#{v}" ? 'selected' : '') %> value="<%= v %>"><%= k %></option>
71
+ <option <%= (selected_format == ".#{v}" ? 'selected' : '') %> value="<%= v %>"><%= k %></option>
67
72
  <% end %>
68
73
  </select>
69
74
  </div>
70
- <script type="text/javascript" charset="utf-8">
71
- window.mode_markdown = '<%= format %>' === '.md';
72
- </script>
73
75
  <% else %>
74
- <input type="hidden" name="format" value="<%= @hyde_parameters['default_format'] %>">
75
- <script type="text/javascript" charset="utf-8">
76
- window.mode_markdown = '<%= @hyde_parameters['default_format'] %>' === 'md';
77
- </script>
76
+ <input type="hidden" name="format" value="<%= selected_format.gsub('.','') %>">
78
77
  <% end %>
78
+ <script type="text/javascript" charset="utf-8">
79
+ window.mode_markdown = '<%= selected_format %>' === '.md';
80
+ </script>
79
81
 
80
82
  <% @headers.each do |k,v| %>
81
83
  <div class="mb-3">
@@ -84,13 +86,13 @@
84
86
  </div>
85
87
  <% end %>
86
88
 
87
- <a href="#" class="btn btn-secondary mb-2" id="add-header"><i class="fas fa-plus"></i> <%= t.add_header.capitalize %></a>
89
+ <a href="#" class="btn btn-secondary mb-2" id="add-header"><i class="fas fa-plus"></i> <%= EscapeUtils.escape_html t.add_header.capitalize %></a>
88
90
  <div class="mb-3 custom-headers"></div>
89
91
 
90
92
  <div class="mb-3 template-header" style="display: none">
91
93
  <div class="row">
92
- <div class="col-sm-4"><input type="text" class="col-sm-6 form-control header-name" name="" placeholder="header name"></div>
93
- <div class="col-sm-8"><input type="text" class="col-sm-6 form-control header-value" name="" placeholder="header value"></div>
94
+ <div class="col-sm-4"><input type="text" class="col-sm-6 form-control header-name" name="" placeholder="<%= EscapeUtils.escape_html t.header_name.capitalize %>"></div>
95
+ <div class="col-sm-8"><input type="text" class="col-sm-6 form-control header-value" name="" placeholder="<%= EscapeUtils.escape_html t.header_value.capitalize %>"></div>
94
96
  </div>
95
97
  </div>
96
98
 
@@ -109,14 +111,14 @@
109
111
  </script>
110
112
 
111
113
  <div class="mb-3">
112
- <label for="i-content" class="form-label"><%= t.content.capitalize %> <a href="https://jekyllrb.com/docs/liquid/" class="text-secondary" target="_blank"><i class="fas fa-question-circle"></i></a></label>
114
+ <label for="i-content" class="form-label"><%= EscapeUtils.escape_html t.content.capitalize %> <a href="https://jekyllrb.com/docs/liquid/" class="text-secondary" target="_blank"><i class="fas fa-question-circle"></i></a></label>
113
115
 
114
- <% path = File.join(Pathname.new(File.dirname(__FILE__)).parent, 'editor_html.erb') %>
116
+ <% path = File.join(Pathname.new(Mid.gem_source_path), 'admin_views', 'editor_html.erb') %>
115
117
  <%= ERB.new(File.read(path)).result(binding) %>
116
118
 
117
119
  <textarea class="form-control text-editor" id="i-content" rows="3" name="content"><%= @content %></textarea>
118
120
  </div>
119
- <button type="submit" class="btn btn-primary"><%= t.submit.capitalize %></button>
121
+ <button type="submit" class="btn btn-primary"><%= EscapeUtils.escape_html t.submit.capitalize %></button>
120
122
  </form>
121
123
 
122
124
  <script type="text/javascript" charset="utf-8">
@@ -150,7 +152,7 @@
150
152
  return false;
151
153
  });
152
154
 
153
- <% path = File.join(Pathname.new(File.dirname(__FILE__)).parent, 'editor_js.erb') %>
155
+ <% path = File.join(Pathname.new(Mid.gem_source_path), 'admin_views', 'editor_js.erb') %>
154
156
  <%= ERB.new(File.read(path)).result(binding) %>
155
157
 
156
158
  </script>
@@ -1,30 +1,33 @@
1
- <h2><%= t.send(@type_file).capitalize %> &nbsp; <a href="/<%= @type_file %>/new" class="btn btn-secondary btn-sm"><i class="fas fa-plus"></i> <%= t.new.capitalize %></a></h2>
1
+ <h2><%= EscapeUtils.escape_html t.send(@type_file).capitalize %> &nbsp; <a href="/<%= @type_file %>/new" class="btn btn-secondary btn-sm"><i class="fas fa-plus"></i> <%= EscapeUtils.escape_html t.new.capitalize %></a></h2>
2
2
 
3
3
  <div class="table-responsive">
4
4
  <table class="table table-striped table-sm">
5
5
  <tr>
6
6
  <th>
7
- <%= t.file.capitalize %>
7
+ <%= EscapeUtils.escape_html t.file.capitalize %>
8
8
  </th>
9
9
  <th>
10
- <%= t.edit.capitalize %>
10
+ <%= EscapeUtils.escape_html t.edit.capitalize %>
11
11
  </th>
12
12
  <th>
13
- <%= t.delete.capitalize %>
13
+ <%= EscapeUtils.escape_html t.delete.capitalize %>
14
14
  </th>
15
15
  </tr>
16
16
  <% @files.each do |f| %>
17
+ <% edit_path = "/#{@type_file}?file=#{f}" %>
17
18
  <tr>
18
19
  <td>
19
- <%= f.gsub(File.join(Dir.pwd, ''),'') %>
20
+ <a href="<%= edit_path %>" class="link-dark">
21
+ <%= f.gsub(File.join(Dir.pwd, ''),'') %>
22
+ </a>
20
23
  </td>
21
24
  <td>
22
- <a href="/<%= @type_file %>?file=<%= f %>" class="btn btn-default"><i class="fa fa-edit" title="<%= t.edit.capitalize %>"></i></a>
25
+ <a href="<%= edit_path %>" class="btn btn-default"><i class="fa fa-edit" title="<%= EscapeUtils.escape_html t.edit.capitalize %>"></i></a>
23
26
  </td>
24
27
  <td>
25
- <form method="post" action="/<%= @type_file %>/delete" class="inline form-confirm" data-confirm="<%= t.are_you_sure %>">
28
+ <form method="post" action="/<%= @type_file %>/delete" class="inline form-confirm" data-confirm="<%= EscapeUtils.escape_html t.are_you_sure %>">
26
29
  <input type="hidden" name="file" value="<%= f %>">
27
- <button type="submit" class="btn btn-default"><i class="fa fa-trash" title="<%= t.delete.capitalize %>"></i></button>
30
+ <button type="submit" class="btn btn-default"><i class="fa fa-trash" title="<%= EscapeUtils.escape_html t.delete.capitalize %>"></i></button>
28
31
  </form>
29
32
  </td>
30
33
  </tr>
@@ -0,0 +1,49 @@
1
+ <!DOCTYPE html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Hyde for Jekyll</title>
6
+
7
+ <meta name="description" content="Hyde for Jekyll">
8
+ <meta name="author" content="Sylvain Claudel (https://blog.rivsc.ovh)">
9
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
10
+
11
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
12
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>
13
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
14
+
15
+ <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ $(function(){
19
+ $(document).on('click', '.btn-return-to-editor', function(){
20
+ //don't work
21
+ //window.opener.reload_image();
22
+ window.close();
23
+ });
24
+ });
25
+ </script>
26
+ </head>
27
+ <body style="width:800px;" class="p-4">
28
+ <div class="container-fluid">
29
+ <div class="row">
30
+ <h1><%= t.upload_image_form.capitalize %></h1>
31
+
32
+ <% if @filenames %>
33
+ <%= t.pictures_has_been_uploaded.capitalize %> : <%= @filenames.join(', ') %>
34
+ <% end %>
35
+
36
+ <form enctype="multipart/form-data" method="post" action="/upload_image" class="row g-3">
37
+ <div class="col-10">
38
+ <input type="file" name="files[]" multiple class="form-control">
39
+ </div>
40
+ <div class="col-2">
41
+ <button class="btn btn-primary"><%= t.upload.capitalize %></button>
42
+ </div>
43
+ </form>
44
+
45
+ <button class="btn btn-secondary btn-return-to-editor fixed-bottom mb-4 ms-4"><%= t.quit.capitalize %></button>
46
+ </div>
47
+ </div>
48
+ </body>
49
+ </html>
data/bin/hyde_admin.ru CHANGED
@@ -5,11 +5,16 @@ require 'yaml'
5
5
  require 'fileutils'
6
6
  require 'i18n'
7
7
  require 'date'
8
+ require 'escape_utils'
9
+ require 'image_processing/mini_magick'
8
10
  require_relative '../lib/hyde_admin/version'
9
11
 
10
12
  # TODO détecter format nouveau post (pour codemirror)
13
+ # Serve
14
+
15
+ class Mid < Roda
16
+ plugin :middleware
11
17
 
12
- class App < Roda
13
18
  YML_FILE_NAME = "hyde_admin.yml"
14
19
 
15
20
  plugin :render,
@@ -55,7 +60,7 @@ class App < Roda
55
60
  end
56
61
 
57
62
  def self.extract_header(str)
58
- headers = App.extract_header_str(str).to_s.split("\n")
63
+ headers = Mid.extract_header_str(str).to_s.split("\n")
59
64
  headers = headers.select{ |header| !header.empty? }.map{ |header| header.scan(/([a-zA-Z0-9]*): (.*)/).flatten }.select{ |header| !header.empty? }
60
65
  hsh_headers = {}
61
66
  if !headers.flatten.empty?
@@ -70,6 +75,34 @@ class App < Roda
70
75
  str.gsub(/---(.*?)---/m, "")
71
76
  end
72
77
 
78
+ def self.gem_source_path
79
+ File.expand_path(File.dirname(__FILE__))
80
+ end
81
+
82
+ def self.extract_tags(str)
83
+ str.to_s.scan(/^\[?(.*?)\]?$/).flatten.first.split(',')
84
+ end
85
+
86
+ def self.resize_image(image_path,params)
87
+ dir = File.dirname(image_path)
88
+ basename = File.basename(image_path, File.extname(image_path))
89
+ while File.exist?("#{File.join(dir, "#{basename}_#{params['resize_size']}")}.#{params['resize_format']}")
90
+ basename += '_'
91
+ end
92
+ output_path = "#{File.join(dir, "#{basename}_#{params['resize_size']}")}.#{params['resize_format']}"
93
+
94
+ width,height = params['resize_size'].split("x")
95
+ ip = ImageProcessing::MiniMagick
96
+ .source(image_path)
97
+ .convert(params['resize_format'])
98
+ .resize_to_limit(width.to_i, height.to_i)
99
+ if params['resize_format'] == 'jpg'
100
+ ip = ip.saver(quality: 80, interlace: "Line")
101
+ end
102
+
103
+ ip.call(destination: output_path)
104
+ end
105
+
73
106
  FORMAT_DATE_FILENAME = '%Y-%m-%d'
74
107
  FORMAT_DATE_INPUT_FILENAME = '%Y-%m-%d %H:%M:%S %z'
75
108
 
@@ -105,12 +138,13 @@ class App < Roda
105
138
  end
106
139
 
107
140
  r.on "deploy" do
108
- `#{@hyde_parameters['rsync_fullpath']} #{Dir.pwd}/_site/ #{@hyde_parameters['deploy_dest_user']}@#{@hyde_parameters['deploy_dest_address']}:#{@hyde_parameters['deploy_dest_path']}`
141
+ `#{@hyde_parameters['rsync_fullpath']} -avzr #{Dir.pwd}/_site/ #{@hyde_parameters['deploy_dest_user']}@#{@hyde_parameters['deploy_dest_address']}:#{@hyde_parameters['deploy_dest_path']}`
109
142
  r.redirect "/dashboard"
110
143
  end
111
144
 
112
145
  r.post "configuration" do
113
146
  r.params.each_pair do |k,v|
147
+ next if k.to_s == "beforeSend"
114
148
  @hyde_parameters[k] = v
115
149
  end
116
150
  File.open(File.join(Dir.pwd, YML_FILE_NAME),"w+") do |f|
@@ -127,6 +161,29 @@ class App < Roda
127
161
  view("dashboard")
128
162
  end
129
163
 
164
+ r.on "upload_image_form" do
165
+ render("upload_image_form")
166
+ end
167
+
168
+ r.post "upload_image" do
169
+ files = [r.params['files']].flatten # 1 or more files
170
+ @filenames = []
171
+ files.each do |file|
172
+ filename = file[:filename]
173
+ while File.exist?(File.join(@hyde_parameters['images_path'], filename))
174
+ filename = "#{File.basename(filename, File.extname(filename))}_#{File.extname(filename)}"
175
+ end
176
+ @filenames << filename
177
+ File.open(File.join(@hyde_parameters['images_path'], filename), 'wb') do |f|
178
+ f.write(file[:tempfile].read)
179
+ end
180
+ if @hyde_parameters['resize_enable'] == 'true'
181
+ Mid.resize_image(File.join(@hyde_parameters['images_path'], filename), @hyde_parameters)
182
+ end
183
+ end
184
+ render("upload_image_form")
185
+ end
186
+
130
187
  r.on "files" do
131
188
  @dir_path = r.params['dir_path'] || Dir.pwd
132
189
 
@@ -141,6 +198,7 @@ class App < Roda
141
198
  r.post "create" do
142
199
  files = [r.params['files']].flatten # 1 or more files
143
200
  files.each do |file|
201
+ # TODO rename file if exist
144
202
  File.open(File.join(@dir_path, file[:filename]), 'wb') do |f|
145
203
  f.write(file[:tempfile].read)
146
204
  end
@@ -167,8 +225,8 @@ class App < Roda
167
225
  r.get "edit" do
168
226
  @file = r.params['file']
169
227
  @content = File.read(@file)
170
- @header = App.extract_header_str(@content)
171
- @content = App.remove_header(@content)
228
+ @header = Mid.extract_header_str(@content)
229
+ @content = Mid.remove_header(@content)
172
230
  @has_header = (!@header.nil? && !@header.empty?)
173
231
  @has_editor = ['.html','.md'].include?(File.extname(@file))
174
232
  view("files/edit")
@@ -210,13 +268,34 @@ class App < Roda
210
268
  path = r.params['path']
211
269
  title = r.params['title']
212
270
  I18n.config.available_locales = :en
213
- new_path = path.gsub(REGEXP_EXTRACT_DATE_TITLE_FROM_FILENAME, "\\1#{App.transliterate_title_for_url(title)}\\3")
271
+ new_path = path.gsub(REGEXP_EXTRACT_DATE_TITLE_FROM_FILENAME, "\\1#{Mid.transliterate_title_for_url(title)}\\3")
214
272
  response.write(new_path)
215
273
  end
216
274
  r.post "update_date_today" do
217
275
  date = Time.now.strftime(FORMAT_DATE_INPUT_FILENAME)
218
276
  response.write(date)
219
277
  end
278
+ r.post "images" do
279
+ nb_elements_per_page = 9
280
+
281
+ sort_date = r.params['sort_date']
282
+ filename = r.params['filename']
283
+ page = r.params['page'].to_i
284
+ start_elts = (page || 0) * nb_elements_per_page
285
+
286
+ search_filename = "*#{filename.strip}*"
287
+
288
+ path_of_images = File.join(Dir.pwd, @hyde_parameters['images_path'], search_filename)
289
+
290
+ all_images = Dir.glob(path_of_images).sort_by {|filename| File.mtime(filename) }
291
+ all_images = all_images.reverse if sort_date == 'asc'
292
+ @images = all_images[start_elts, nb_elements_per_page]
293
+
294
+ path = File.join(Pathname.new(Mid.gem_source_path), 'admin_views', 'partials', 'images_page.html.erb')
295
+ data = ERB.new(File.read(path)).result(binding)
296
+
297
+ response.write(data)
298
+ end
220
299
  end
221
300
 
222
301
  # Posts/pages/drafts
@@ -256,7 +335,7 @@ class App < Roda
256
335
  @file = r.params['file']
257
336
 
258
337
  content_file = File.read(@file)
259
- @headers = App.extract_header(content_file)
338
+ @headers = Mid.extract_header(content_file)
260
339
  @content = File.read(@file).gsub(/---(.*?)---/m, "")
261
340
 
262
341
  # for page
@@ -286,7 +365,7 @@ class App < Roda
286
365
  #$stderr.puts "---->"
287
366
 
288
367
  if @new_file.nil? || @new_file.empty?
289
- filename = App.urlize(@date, @title, (@type_file != 'pages'))
368
+ filename = Mid.urlize(@date, @title, (@type_file != 'pages'))
290
369
  @new_file = File.join(Dir.pwd,"_#{@type_file}", "#{filename}.#{@format}")
291
370
  end
292
371
 
@@ -328,4 +407,11 @@ class App < Roda
328
407
  end
329
408
  end
330
409
 
410
+ # https://roda.jeremyevans.net/rdoc/classes/Roda/RodaPlugins/Middleware.html
411
+ class App < Roda
412
+ use Mid
413
+ use Rack::Static, :urls => [''], root: Dir.pwd # allow to match all files in Dir.pwd
414
+ end
415
+
331
416
  run App.freeze.app
417
+
data/bin/hyde_admin.yml CHANGED
@@ -6,10 +6,13 @@ deploy_dest_path: "/absolute/remote/path/mysite"
6
6
  rsync_fullpath: rsync
7
7
  site_index: index.html
8
8
  hyde_admin_language: en
9
- hyde_admin_auth: false
9
+ hyde_admin_auth: 'false'
10
10
  hyde_admin_user: admin
11
11
  hyde_admin_password: admin
12
12
  default_format: html
13
- display_layout: true
14
- display_format: true
15
- images_path: assets/images/
13
+ display_layout: 'true'
14
+ display_format: 'true'
15
+ images_path: assets/images/
16
+ resize_format: jpg
17
+ resize_size: 1500x1000
18
+ resize_enable: 'true'
@@ -1,18 +1,37 @@
1
1
  /* modal pictures */
2
- .modal-body-image{
2
+ .image-selector-content{
3
3
  display: grid;
4
4
  grid-template-columns: 1fr 1fr 1fr;
5
5
  }
6
- .modal-body-image .image-element{
6
+ .image-selector-content .image-element{
7
7
  width: 150px;
8
8
  height: 150px;
9
9
  }
10
- .modal-body-image .image-element img{
10
+ .image-selector-content .image-element img{
11
11
  width: 100%;
12
12
  height: 100%;
13
13
  object-fit: contain;
14
14
  overflow: hidden;
15
+ border:2px solid white;
15
16
  }
16
- .modal-body-image .image-element img:hover{
17
+ .image-selector-content .image-element img:hover{
17
18
  border:2px solid gray;
19
+ }
20
+
21
+ .image-element{
22
+ position: relative;
23
+ }
24
+
25
+ .image-element span{
26
+ position: absolute;
27
+ bottom:0px;
28
+ left:5px;
29
+ z-index: 10;
30
+ font-weight: bold;
31
+ margin-bottom: -20px;
32
+ }
33
+
34
+ .CodeMirror{
35
+ border: 1px solid #ced4da;
36
+ border-radius: 4px;
18
37
  }
data/bin/i18n/en.yml CHANGED
@@ -39,7 +39,7 @@ help_default_layout: default layout for jekyll posts/pages
39
39
  deploy_dest_user: deploy remote user
40
40
  help_deploy_dest_user: Ssh user for rsync
41
41
  deploy_dest_address: deploy remote domain
42
- help_deploy_dest_address: remote domain for ssh deployment
42
+ help_deploy_dest_address: remote domain for ssh deployment (example.com)
43
43
  deploy_dest_path: deploy remote path
44
44
  help_deploy_dest_path: remote path on disk for ssh deployment
45
45
  rsync_fullpath: rsync path
@@ -47,24 +47,24 @@ help_rsync_fullpath: if rsync is not in PATH, othervise just let 'rsync'
47
47
  site_index: index file name of site
48
48
  help_site_index: link to open when we click on overview
49
49
  hyde_admin_language: hyde admin language
50
- help_hyde_admin_language: To change hyde admin language interface
50
+ help_hyde_admin_language: To change hyde admin language interface (fr = french, en = english)
51
51
  set_date_today: set date at today
52
52
  change_date_path: update date in path
53
53
  change_title_path: update title in path
54
54
  directory_input_placeholder: directory name to create
55
55
  file_input_placeholder: file name to create
56
56
  hyde_admin_auth: enable BasicAuth
57
- help_hyde_admin_auth: enable BasicAuth
57
+ help_hyde_admin_auth: enable BasicAuth (true/false)
58
58
  hyde_admin_user: BasicAuth user
59
59
  help_hyde_admin_user: BasicAuth user
60
60
  hyde_admin_password: BasicAuth password
61
61
  help_hyde_admin_password: BasicAuth password
62
62
  default_format: default format
63
- help_default_format: default format
63
+ help_default_format: default format (html = html, md = markdown)
64
64
  display_layout: display the layout input on edit form
65
- help_display_layout: display the layout input on edit form
65
+ help_display_layout: display the layout input on edit form (true/false)
66
66
  display_format: display the format input on edit form
67
- help_display_format: display the format input on edit form
67
+ help_display_format: display the format input on edit form (true/false)
68
68
  images_path: pictures path
69
69
  help_images_path: relative local picture path
70
70
  editor_undo: Undo
@@ -85,4 +85,25 @@ editor_italic: Italic
85
85
  editor_strikethrough: Strikethrough
86
86
  default_alt_img: Alt text
87
87
  default_title_img: Title text
88
- parent_dir: dossier parent
88
+ parent_dir: parent directory
89
+ sort_by_date: sort_by_date
90
+ older: older first
91
+ newer: newer first
92
+ previous_images: previous images
93
+ next_images: next images
94
+ search: search
95
+ filename: filename
96
+ filename_placeholder: filename...
97
+ upload_image_form: upload image form
98
+ pictures_has_been_uploaded: pictures has been uploaded
99
+ quit: quit
100
+ header_name: header name
101
+ header_value: header value
102
+ images: images
103
+ load_images: load images
104
+ resize_format: jpg
105
+ help_resize_format: jpg or png
106
+ resize_size: 1500x1000
107
+ help_resize_size: Downsize to fit to the specified size (resize preserve ratio), example 1500x1000
108
+ resize_enable: true
109
+ help_resize_enable: enable feature resize image at upload
data/bin/i18n/fr.yml CHANGED
@@ -39,7 +39,7 @@ help_default_layout: présentation par défaut pour les posts et pages
39
39
  deploy_dest_user: Utilisateur pour déploiement
40
40
  help_deploy_dest_user: Utilisateur pour déploiement par ssh
41
41
  deploy_dest_address: Adresse pour déploiement
42
- help_deploy_dest_address: Domaine ou adresse IP pour déploiement à travers ssh
42
+ help_deploy_dest_address: Domaine ou adresse IP pour déploiement à travers ssh (example.com)
43
43
  deploy_dest_path: chemin distant pour déploiement
44
44
  help_deploy_dest_path: chemin distant pour déploiement du site
45
45
  rsync_fullpath: chemin rsync
@@ -47,24 +47,24 @@ help_rsync_fullpath: si rsync n'est pas dans le PATH, sinon laissez 'rsync'
47
47
  site_index: nom du fichier index pour le site
48
48
  help_site_index: Lien pour le lien aperçu, pensez à l'extention si nécessaire
49
49
  hyde_admin_language: hyde admin langue
50
- help_hyde_admin_language: Pour changer la langue d'interface de hyde admin
50
+ help_hyde_admin_language: Pour changer la langue d'interface de hyde admin (fr = français, en = anglais)
51
51
  set_date_today: mets la date du jour
52
52
  change_date_path: mets à jour la date dans le chemin de fichier
53
53
  change_title_path: mets à jour le titre dans le chemin de fichier
54
54
  directory_input_placeholder: nom du dossier à créer
55
55
  file_input_placeholder: nom du fichier à créer
56
56
  hyde_admin_auth: enable BasicAuth
57
- help_hyde_admin_auth: enable BasicAuth
57
+ help_hyde_admin_auth: enable BasicAuth (true/false)
58
58
  hyde_admin_user: BasicAuth user
59
59
  help_hyde_admin_user: BasicAuth user
60
60
  hyde_admin_password: BasicAuth password
61
61
  help_hyde_admin_password: BasicAuth password
62
62
  default_format: format par défaut
63
- help_default_format: format par défaut pour les posts
63
+ help_default_format: format par défaut pour les posts (html = html, md = markdown)
64
64
  display_layout: affiche le choix du layout sur le formulaire d'édition
65
- help_display_layout: affiche le choix du layout sur le formulaire d'édition
65
+ help_display_layout: affiche le choix du layout sur le formulaire d'édition (true/false)
66
66
  display_format: affiche le choix du format sur le formulaire d'édition
67
- help_display_format: affiche le choix du format sur le formulaire d'édition
67
+ help_display_format: affiche le choix du format sur le formulaire d'édition (true/false)
68
68
  images_path: chemin des images
69
69
  help_images_path: chemin local relatif des images
70
70
  editor_undo: Annuler
@@ -85,4 +85,25 @@ editor_italic: Italique
85
85
  editor_strikethrough: Barré
86
86
  default_alt_img: Texte alternatif
87
87
  default_title_img: Titre image
88
- parent_dir: dossier parent
88
+ parent_dir: dossier parent
89
+ sort_by_date: tri par date
90
+ older: vieille d'abord
91
+ newer: récente d'abord
92
+ previous_images: images précédentes " lol
93
+ next_images: images suivantes
94
+ search: recherche
95
+ filename: nom de fichier
96
+ filename_placeholder: nom de fichier...
97
+ upload_image_form: formulaire d'upload d'image
98
+ pictures_has_been_uploaded: les images ont été uploadées
99
+ quit: quitter
100
+ header_name: nom d'entête
101
+ header_value: valeur d'entête
102
+ images: images
103
+ load_images: charger images
104
+ resize_format: jpg
105
+ help_resize_format: jpg ou png
106
+ resize_size: 1500x1000
107
+ help_resize_size: Réduit les image pour coller à la taille spécifiée (le redimensionnement préserve le ratio), exemple 1500x1000
108
+ resize_enable: true
109
+ help_resize_enable: active la fonctionnalité de redimensionnement d'image à l'upload
data/hyde_admin.gemspec CHANGED
@@ -28,6 +28,8 @@ Gem::Specification.new do |s|
28
28
  s.add_runtime_dependency("roda", "~> 3.48.0")
29
29
  s.add_runtime_dependency("roda-i18n", "~> 0.4.0")
30
30
  s.add_runtime_dependency("roda-http-auth", "0.2.0")
31
+ s.add_runtime_dependency("escape_utils") # escape_javascript / escape_html
31
32
  #s.add_runtime_dependency("i18n", "~> 0.4.0") # I18n.transliterate (already required by jekyll)
32
33
  s.add_runtime_dependency('jekyll') # Because we call jekyll binary
34
+ s.add_runtime_dependency('image_processing') # JPEG quality
33
35
  end
@@ -1,3 +1,3 @@
1
1
  module HydeAdmin
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.8"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyde_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Claudel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-13 00:00:00.000000000 Z
11
+ date: 2021-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: roda
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: escape_utils
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: jekyll
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,20 @@ dependencies:
66
80
  - - ">="
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: image_processing
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  description: A Jekyll admin interface
70
98
  email: claudel.sylvain@gmail.com
71
99
  executables:
@@ -74,6 +102,7 @@ extensions: []
74
102
  extra_rdoc_files: []
75
103
  files:
76
104
  - ".gitattributes"
105
+ - ".gitignore"
77
106
  - ".idea/.gitignore"
78
107
  - ".idea/hyde_admin.iml"
79
108
  - ".idea/misc.xml"
@@ -89,8 +118,11 @@ files:
89
118
  - bin/admin_views/editor_js.erb
90
119
  - bin/admin_views/files/edit.erb
91
120
  - bin/admin_views/files/listing.erb
121
+ - bin/admin_views/partials/image_element.html.erb
122
+ - bin/admin_views/partials/images_page.html.erb
92
123
  - bin/admin_views/posts/edit.erb
93
124
  - bin/admin_views/posts/listing.erb
125
+ - bin/admin_views/upload_image_form.erb
94
126
  - bin/fslightbox/fslightbox.js
95
127
  - bin/hyde_admin
96
128
  - bin/hyde_admin.ru