Skip to content

Commit 7c370c1

Browse files
author
Lewis Youl
committed
feat: add ability to download image of code
1 parent 5b9a73f commit 7c370c1

File tree

14 files changed

+83
-6
lines changed

14 files changed

+83
-6
lines changed

app/controllers/modals/snippets_controller.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ def move
2121
@folders = current_user.folders.order(name: :asc)
2222
end
2323

24+
def picture
25+
@snippet = Snippet.find(params[:id])
26+
@languages = Language.order(name: :asc)
27+
end
28+
2429
private
2530

2631
def set_snippet

app/javascript/controllers/codemirror_controller.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export default class extends Controller {
1010
code: String,
1111
modeId: String,
1212
initialized: Boolean,
13-
readOnly: Boolean
13+
readOnly: Boolean,
14+
isCapture: Boolean,
1415
}
1516

1617
connect() {
@@ -35,6 +36,11 @@ export default class extends Controller {
3536
});
3637

3738
this.initializedValue = true
39+
40+
if (this.isCaptureValue) {
41+
document.querySelector(".CodeMirror")
42+
.classList.add('rounded-tr-md', 'rounded-tl-md', 'shadow-2xl')
43+
}
3844
}
3945

4046
setCodeMirrorValue() {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Controller } from 'stimulus';
2+
import domtoimage from 'dom-to-image';
3+
4+
export default class extends Controller {
5+
static targets = ['code']
6+
7+
capture() {
8+
const scale = 2;
9+
const node = this.codeTarget
10+
const options = {
11+
height: node.offsetHeight * scale,
12+
width: node.offsetWidth * scale,
13+
style: {
14+
transform: "scale(" + scale + ")",
15+
transformOrigin: "top left",
16+
width: node.offsetWidth + "px",
17+
height: node.offsetHeight + "px"
18+
}
19+
}
20+
21+
domtoimage.toJpeg(node, options)
22+
.then(this.downloadImage)
23+
.catch(console.error)
24+
}
25+
26+
downloadImage(dataUrl) {
27+
let link = document.createElement('a')
28+
29+
link.setAttribute('download', 'snippetsafe.jpeg');
30+
link.setAttribute('href', dataUrl);
31+
link.click();
32+
link.remove()
33+
}
34+
}

app/views/layouts/application.html.erb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222

2323
<meta name="turbolinks-cache-control" content="no-preview">
2424

25-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.3/styles/atom-one-light.min.css">
2625
<%# <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.1/highlight.min.js"></script> %>
2726
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.9/cropper.min.css" integrity="sha512-w+u2vZqMNUVngx+0GVZYM21Qm093kAexjueWOv9e9nIeYJb1iEfiHC7Y+VvmP/tviQyA5IR32mwN/5hTEJx6Ng==" crossorigin="anonymous" />
2827
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.9/cropper.min.js" integrity="sha512-9pGiHYK23sqK5Zm0oF45sNBAX/JqbZEP7bSDHyt+nT3GddF+VFIcYNqREt0GDpmFVZI3LZ17Zu9nMMc9iktkCw==" crossorigin="anonymous"></script>

app/views/layouts/modal.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
From: "opacity-100 translate-y-0 sm:scale-100"
3434
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
3535
-->
36-
<div class="z-10 relative mt-2 inline-block align-bottom bg-white rounded-sm px-4 pt-5 pb-4 text-left shadow-xl transform transition-all sm:my-8 sm:align-middle w-full sm:max-w-2xl sm:w-full sm:p-6" role="dialog" aria-modal="true" aria-labelledby="modal-headline" data-modal-target="body">
36+
<div class="z-10 relative mt-2 inline-block align-bottom bg-white rounded-sm px-4 pt-5 pb-4 text-left shadow-xl transform transition-all sm:my-8 sm:align-middle w-full sm:max-w-4xl sm:w-full sm:p-6" role="dialog" aria-modal="true" aria-labelledby="modal-headline" data-modal-target="body">
3737
<span data-action="click->modal#close" title="Close modal" class="hover:bg-cyan-hover transition cursor-pointer absolute z-12 -top-4 -right-5 inline-flex items-center p-1 border border-transparent rounded-full shadow-sm text-white bg-cyan mr-2">
3838
<%= render partial: 'shared/icons/close', locals: { height: 7, width: 7, color: 'text-white' } %>
3939
</span>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<h3 class="text-center mb-4">Capture Image</h3>
2+
3+
<h5 class="mb-2"><%= @snippet.description %></h5>
4+
<div data-controller="picture">
5+
<div data-picture-target="code" class="bg-cyan p-20">
6+
<%= render partial: 'shared/codemirror', locals: { code: @snippet.body, mode_id: @snippet.language_id, read_only: false, capture: true } %>
7+
</div>
8+
9+
<div class="flex justify-end mt-4">
10+
<%= button_tag('Tweet', class: 'button--disabled mr-2') %>
11+
<%= button_tag('Download', class: 'button--cta-tertiary', data: { action: 'click->picture#capture' }) %>
12+
</div>
13+
</div>

app/views/shared/_codemirror.html.erb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
codemirror_modes_value: @languages,
1111
codemirror_initialized_value: false,
1212
codemirror_read_only_value: read_only,
13-
codemirror_target: 'mirror'
13+
codemirror_target: 'mirror',
14+
codemirror_is_capture_value: capture
1415
},
1516
class: "font-mono h-80 block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-sm"
1617
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<%= button_tag(
2+
class: "ml-2 no-underline flex items-center cursor-pointer transition",
3+
data: {
4+
controller: 'modal',
5+
action: 'modal#present',
6+
modal_url_value: picture_modals_snippet_path(snippet: snippet)
7+
}
8+
) do %>
9+
<%= render partial: 'shared/icons/camera', locals: { classes: 'w-5 h-5 text-gray-500' } %>
10+
<% end %>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<svg class="<%= classes %>" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4 5a2 2 0 00-2 2v8a2 2 0 002 2h12a2 2 0 002-2V7a2 2 0 00-2-2h-1.586a1 1 0 01-.707-.293l-1.121-1.121A2 2 0 0011.172 3H8.828a2 2 0 00-1.414.586L6.293 4.707A1 1 0 015.586 5H4zm6 9a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd"></path></svg>

app/views/snippets/_snippet.html.erb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@
2929
<div class="flex">
3030
<%= render partial: 'shared/like_button', locals: { snippet: snippet } %>
3131
<%= render partial: 'shared/comment_button', locals: { snippet: snippet } %>
32+
<%= render partial: 'shared/picture_button', locals: { snippet: snippet } %>
3233
</div>
3334
</div>
3435
</div>
3536

36-
<%= render partial: 'shared/codemirror', locals: { code: snippet.body, mode_id: snippet.language_id, read_only: true } %>
37+
<%= render partial: 'shared/codemirror', locals: { code: snippet.body, mode_id: snippet.language_id, read_only: true, capture: false } %>
3738
<% end %>

0 commit comments

Comments
 (0)