hyde_admin 0.0.3 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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