Bundle libraries when project is downloaded as zip (New approach) (#376)

* External libraries are bundled with zip when project is downloaded (#44)

* Fix linting errors

* Add a check for valid URLs before trying to bundle a library into project

* Add is-url lib to package.json
This commit is contained in:
Zach Rispoli 2017-07-19 13:56:52 -04:00 committed by Cassie Tarakajian
parent b384fdc6ba
commit e987e8f483
2 changed files with 50 additions and 3 deletions

View file

@ -83,6 +83,7 @@
"fs-promise": "^1.0.0", "fs-promise": "^1.0.0",
"htmlhint": "^0.9.13", "htmlhint": "^0.9.13",
"is_js": "^0.9.0", "is_js": "^0.9.0",
"is-url": "^1.2.2",
"js-beautify": "^1.6.4", "js-beautify": "^1.6.4",
"jsdom": "^9.8.3", "jsdom": "^9.8.3",
"jshint": "^2.9.4", "jshint": "^2.9.4",

View file

@ -1,6 +1,8 @@
import archiver from 'archiver'; import archiver from 'archiver';
import request from 'request'; import request from 'request';
import moment from 'moment'; import moment from 'moment';
import isUrl from 'is-url';
import jsdom, { serializeDocument } from 'jsdom';
import Project from '../models/project'; import Project from '../models/project';
import User from '../models/user'; import User from '../models/user';
import { deleteObjectsFromS3, getObjectKey } from './aws.controller'; import { deleteObjectsFromS3, getObjectKey } from './aws.controller';
@ -100,8 +102,7 @@ function deleteFilesFromS3(files) {
} }
return false; return false;
}) })
.map(file => getObjectKey(file.url)) .map(file => getObjectKey(file.url)));
);
} }
export function deleteProject(req, res) { export function deleteProject(req, res) {
@ -169,6 +170,48 @@ export function getProjectsForUser(req, res) {
} }
} }
function bundleExternalLibs(project, zip, callback) {
const rootFile = project.files.find(file => file.name === 'root');
const indexHtml = project.files.find(file => file.name === 'index.html');
let numScriptsResolved = 0;
let numScriptTags = 0;
function resolveScriptTagSrc(scriptTag, document) {
const path = scriptTag.src.split('/');
const filename = path[path.length - 1];
const src = scriptTag.src;
if (!isUrl(src)) {
numScriptsResolved += 1;
return;
}
request({ method: 'GET', url: src, encoding: null }, (err, response, body) => {
if (err) {
console.log(err);
} else {
zip.append(body, { name: filename });
scriptTag.src = filename;
}
numScriptsResolved += 1;
if (numScriptsResolved === numScriptTags) {
indexHtml.content = serializeDocument(document);
callback();
}
});
}
jsdom.env(indexHtml.content, (innerErr, window) => {
const indexHtmlDoc = window.document;
const scriptTags = indexHtmlDoc.getElementsByTagName('script');
numScriptTags = scriptTags.length;
for (let i = 0; i < numScriptTags; i += 1) {
resolveScriptTagSrc(scriptTags[i], indexHtmlDoc);
}
});
}
function buildZip(project, req, res) { function buildZip(project, req, res) {
const zip = archiver('zip'); const zip = archiver('zip');
const rootFile = project.files.find(file => file.name === 'root'); const rootFile = project.files.find(file => file.name === 'root');
@ -208,7 +251,10 @@ function buildZip(project, req, res) {
} }
} }
} }
addFileToZip(rootFile, '/');
bundleExternalLibs(project, zip, () => {
addFileToZip(rootFile, '/');
});
} }
export function downloadProjectAsZip(req, res) { export function downloadProjectAsZip(req, res) {