diff --git a/pkg/arvo/mar/blit.hoon b/pkg/arvo/mar/blit.hoon index 3d73aa4747..ced1f934ae 100644 --- a/pkg/arvo/mar/blit.hoon +++ b/pkg/arvo/mar/blit.hoon @@ -1,6 +1,7 @@ :: blit: runtime blit structure :: -~% %mar-blit ..is ~ +/+ base64 +:: |_ =blit:dill ++ grad %noun :: +grab: convert from @@ -12,7 +13,6 @@ :: +grow: convert to :: ++ grow - ~% %blit-grow ..grow ~ |% ++ noun blit ++ json @@ -25,9 +25,19 @@ %hop (numb p.blit) %lin s+(crip (tufa p.blit)) %mor b+& - %sag (pairs 'path'^(path p.blit) 'file'^s+(jam q.blit) ~) - %sav (pairs 'path'^(path p.blit) 'file'^s+q.blit ~) %url s+p.blit + :: + %sag + %- pairs + :~ 'path'^(path p.blit) + 'file'^s+(en:base64 (as-octs:mimes:html (jam q.blit))) + == + :: + %sav + %- pairs + :~ 'path'^(path p.blit) + 'file'^s+(en:base64 (as-octs:mimes:html q.blit)) + == :: %klr :- %a diff --git a/pkg/interface/package-lock.json b/pkg/interface/package-lock.json index 812ebc3298..7a7d09613b 100644 --- a/pkg/interface/package-lock.json +++ b/pkg/interface/package-lock.json @@ -4876,6 +4876,11 @@ } } }, + "file-saver": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", + "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", diff --git a/pkg/interface/package.json b/pkg/interface/package.json index 619ccae0f6..ba71f63e55 100644 --- a/pkg/interface/package.json +++ b/pkg/interface/package.json @@ -15,6 +15,7 @@ "classnames": "^2.2.6", "codemirror": "^5.55.0", "css-loader": "^3.5.3", + "file-saver": "^2.0.2", "formik": "^2.1.4", "lodash": "^4.17.15", "markdown-to-jsx": "^6.11.4", diff --git a/pkg/interface/src/views/apps/dojo/store.js b/pkg/interface/src/views/apps/dojo/store.js index 8aeab759bd..b2028bb12d 100644 --- a/pkg/interface/src/views/apps/dojo/store.js +++ b/pkg/interface/src/views/apps/dojo/store.js @@ -1,4 +1,5 @@ -import Share from './components/lib/sole'; +import { saveAs } from 'file-saver'; + export default class Store { constructor() { this.state = this.initialState(); @@ -42,7 +43,14 @@ export default class Store { this.state.lines.push(''); this.setState({ lines: this.state.lines }); break; - //TODO file downloads for %sag and %sav + case 'sag': + blit.sav = blit.sag; + case 'sav': + let name = blit.sav.path.split('/').slice(-2).join('.'); + let buff = new Buffer(blit.sav.file, 'base64'); + let blob = new Blob([buff], {type: 'application/octet-stream'}); + saveAs(blob, name); + break; case 'url': //TODO too invasive? just print as ? window.open(blit.url);