Skip to content

Commit 014ed76

Browse files
authored
Merge pull request #40 from xsnippet/download
Download button actually downloads now
2 parents 16ac748 + 8373a23 commit 014ed76

File tree

4 files changed

+45
-4
lines changed

4 files changed

+45
-4
lines changed

src/components/RecentSnippetItem.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import React from 'react';
22
import { Link } from 'react-router-dom';
33

4+
import { downloadSnippet } from '../helpers';
5+
46
const RecentSnippetItem = ({ snippet }) => {
57
const snippetTitle = snippet.get('title') || `#${snippet.get('id')}, Untitled`;
8+
const download = () => downloadSnippet(snippet);
69

710
return (
811
<li className="recent-snippet-item">
@@ -15,7 +18,7 @@ const RecentSnippetItem = ({ snippet }) => {
1518
</div>
1619
<div>
1720
<button className="recent-snippet-button light">Raw</button>
18-
<button className="recent-snippet-button light">Download</button>
21+
<button className="recent-snippet-button light" onClick={download}>Download</button>
1922
<Link to={`${snippet.get('id')}`} className="recent-snippet-button">Show</Link>
2023
</div>
2124
</li>

src/components/Snippet.jsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Title from './common/Title';
99
import Input from './common/Input';
1010
import Spinner from './common/Spinner';
1111
import * as actions from '../actions';
12+
import { downloadSnippet } from '../helpers';
1213

1314
import '../styles/Snippet.styl';
1415

@@ -17,6 +18,7 @@ class Snippet extends React.Component {
1718
super(props);
1819
this.state = { isShowEmbed: false };
1920
this.toggleEmbed = this.toggleEmbed.bind(this);
21+
this.download = this.download.bind(this);
2022
}
2123

2224
componentDidMount() {
@@ -26,6 +28,10 @@ class Snippet extends React.Component {
2628
dispatch(actions.fetchSnippet(Number(id)));
2729
}
2830

31+
download() {
32+
downloadSnippet(this.props.snippet);
33+
}
34+
2935
toggleEmbed() {
3036
this.setState(prevState => ({ isShowEmbed: !prevState.isShowEmbed }));
3137
}
@@ -73,7 +79,7 @@ class Snippet extends React.Component {
7379
/>
7480
<div className="snippet-code-bottom-bar">
7581
<button className="snippet-button light">Raw</button>
76-
<button className="snippet-button light">Download</button>
82+
<button className="snippet-button light" onClick={this.download}>Download</button>
7783
</div>
7884
</div>
7985
</div>,

src/components/Syntaxes.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22
import { Scrollbars } from 'react-custom-scrollbars';
33
import { connect } from 'react-redux';
44

5-
import regExpEscape from './../helpers';
5+
import { regExpEscape } from '../helpers';
66
import * as actions from '../actions';
77

88
class Syntaxes extends React.PureComponent {

src/helpers/index.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
1+
import codemirror from 'codemirror';
2+
13
const regExpEscape = string => string.replace(/[-[\]{}()*+?.,\\^$|]/g, '\\$&');
24

3-
export default regExpEscape;
5+
function download(text, name, mime) {
6+
// It seems it's the only way to initiate file downloading from JavaScript
7+
// as of Jan 7, 2018. If you read this and know a better way, please submit
8+
// a pull request! ;)
9+
10+
const element = document.createElement('a');
11+
element.setAttribute('href', `data:${mime};charset=utf-8,${encodeURIComponent(text)}`);
12+
element.setAttribute('download', name);
13+
element.style.display = 'none';
14+
document.body.appendChild(element);
15+
16+
element.click();
17+
18+
document.body.removeChild(element);
19+
}
20+
21+
function downloadSnippet(snippet) {
22+
// Despite using CodeMirror's modes as syntaxes on XSnippet API, we might
23+
// imagine other setup when more syntaxes can be used on server. Hence, we
24+
// must be prepared and fallback on "Plain Text" mode if we can't figure out
25+
// what's extension and/or MIME type.
26+
const modeInfo = codemirror.findModeByName(snippet.get('syntax'))
27+
|| codemirror.findModeByName('Plain Text');
28+
29+
const content = snippet.get('content');
30+
const name = `${snippet.get('id')}.${modeInfo.ext[0]}`;
31+
32+
download(content, name, modeInfo.mime);
33+
}
34+
35+
export { regExpEscape, downloadSnippet };

0 commit comments

Comments
 (0)