Make LessLoader able to cache even inside of the sandbox iframe and don't load less compiler unless needed

pull/1/head
Caleb James DeLisle 7 years ago
parent 0d8c292fef
commit 710418f42f

@ -2,7 +2,7 @@
<html class="cp-app-noscroll"> <html class="cp-app-noscroll">
<head> <head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/code/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script> <script async data-bootload="/code/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<style> <style>
.loading-hidden { display: none; } .loading-hidden { display: none; }
#editor1 { display: none; } #editor1 { display: none; }

@ -1,23 +1,38 @@
/*@flow*/ /*@flow*/
/*:: const define = () => {}; */ /*:: const define = () => {}; */
define([ define([
'/api/config', '/api/config'
'/bower_components/less/dist/less.min.js' ], function (Config) { /*::});module.exports = (function() {
], function (Config, Less) { /*::});module.exports = (function() {
const Config = (undefined:any); const Config = (undefined:any);
const Less = (undefined:any);
*/ */
var module = { exports: {} }; var module = { exports: {} };
var key = Config.requireConf.urlArgs; var key = Config.requireConf.urlArgs;
var localStorage; var localStorage = {};
try { try {
localStorage = window.localStorage || {}; localStorage = window.localStorage || {};
if (localStorage['LESS_CACHE'] !== key) {
Object.keys(localStorage).forEach(function (k) {
if (k.indexOf('LESS_CACHE|') !== 0) { return; }
delete localStorage[k];
});
localStorage['LESS_CACHE'] = key;
}
} catch (e) { } catch (e) {
console.error(e); console.error(e);
localStorage = {}; localStorage = {};
} }
var cacheGet = function (k, cb) {
if (window.cryptpadCache) { return void window.cryptpadCache.get(k, cb); }
setTimeout(function () { cb(localStorage['LESS_CACHE|' + key + '|' + k]); })
};
var cachePut = function (k, v, cb) {
if (window.cryptpadCache) { return void window.cryptpadCache.put(k, v, cb); }
cb = cb || function () { };
setTimeout(function () { localStorage['LESS_CACHE|' + key + '|' + k] = v; cb(); });
};
var fixURL = function (url, parent) { var fixURL = function (url, parent) {
// data: blob: etc // data: blob: etc
if (/^[a-zA-Z0-9]*:/.test(url)) { return url; } if (/^[a-zA-Z0-9]*:/.test(url)) { return url; }
@ -32,13 +47,6 @@ define([
return out; return out;
}; };
var doXHR = Less.FileManager.prototype.doXHR;
Less.FileManager.prototype.doXHR = function (url, type, callback, errback) {
url = fixURL(url);
//console.log("xhr: " + url);
return doXHR(url, type, callback, errback);
};
var inject = function (cssText, url) { var inject = function (cssText, url) {
var curStyle = document.createElement('style'); var curStyle = document.createElement('style');
curStyle.setAttribute('data-original-src', url); curStyle.setAttribute('data-original-src', url);
@ -48,15 +56,6 @@ define([
document.head.appendChild(curStyle); document.head.appendChild(curStyle);
}; };
var checkCache = function () {
if (localStorage['LESS_CACHE'] === key) { return; }
Object.keys(localStorage).forEach(function (k) {
if (k.indexOf('LESS_CACHE|') !== 0) { return; }
delete localStorage[k];
});
localStorage['LESS_CACHE'] = key;
};
var fixAllURLs = function (source, parent) { var fixAllURLs = function (source, parent) {
var urlRegEx = /@import\s*("([^"]*)"|'([^']*)')|url\s*\(\s*(\s*"([^"]*)"|'([^']*)'|[^\)]*\s*)\s*\)/ig; var urlRegEx = /@import\s*("([^"]*)"|'([^']*)')|url\s*\(\s*(\s*"([^"]*)"|'([^']*)'|[^\)]*\s*)\s*\)/ig;
var result, url; var result, url;
@ -84,25 +83,46 @@ define([
xhr.send(null); xhr.send(null);
}; };
var lessEngine;
var getLessEngine = function (cb) {
if (lessEngine) {
cb(lessEngine);
} else {
require(['/bower_components/less/dist/less.min.js'], function (Less) {
lessEngine = Less;
var doXHR = lessEngine.FileManager.prototype.doXHR;
lessEngine.FileManager.prototype.doXHR = function (url, type, callback, errback) {
url = fixURL(url);
//console.log("xhr: " + url);
return doXHR(url, type, callback, errback);
};
cb(lessEngine);
});
}
};
var loadLess = function (url, cb) { var loadLess = function (url, cb) {
Less.render('@import (multiple) "' + url + '";', {}, function(err, css) { getLessEngine(function (less) {
if (err) { return void cb(err); } less.render('@import (multiple) "' + url + '";', {}, function(err, css) {
cb(undefined, css.css); if (err) { return void cb(err); }
}, window.less); cb(undefined, css.css);
}, window.less);
});
}; };
module.exports.load = function (url /*:string*/, cb /*:()=>void*/) { module.exports.load = function (url /*:string*/, cb /*:()=>void*/) {
checkCache(); cacheGet(url, function (css) {
if (localStorage['LESS_CACHE|' + key + '|' + url]) { if (css) {
inject(localStorage['LESS_CACHE|' + key + '|' + url], url); inject(css, url);
cb(); return void cb();
return; }
} console.log('CACHE MISS ' + url);
((/\.less([\?\#].*)?$/.test(url)) ? loadLess : loadCSS)(url, function (err, css) { ((/\.less([\?\#].*)?$/.test(url)) ? loadLess : loadCSS)(url, function (err, css) {
var output = fixAllURLs(css, url); var output = fixAllURLs(css, url);
localStorage['LESS_CACHE|' + key + '|' + url] = output; cachePut(url, output);
inject(output, url); inject(output, url);
cb(); cb();
});
}); });
}; };

@ -1,7 +1,37 @@
// Stage 0, this gets cached which means we can't change it. boot2-sframe.js is changable. // Stage 0, this gets cached which means we can't change it. boot2-sframe.js is changable.
// Note that this file is meant to be executed only inside of a sandbox iframe. // Note that this file is meant to be executed only inside of a sandbox iframe.
//
// IF YOU EDIT THIS FILE, bump the version (replace 1.3 in the following command with the next version.)
// grep -nr '/common/sframe-boot.js?ver=' | sed 's/:.*$//' | while read x; do \
// sed -i -e 's@/common/sframe-boot.js?ver=[^"]*@/common/sframe-boot.js?ver=1.3@' $x; done
;(function () { ;(function () {
var afterLoaded = function (req) { var afterLoaded = function (req) {
var localStorage = {};
if (req.cfg && req.cfg.urlArgs) {
try {
localStorage = window.localStorage;
if (localStorage['CRYPTPAD_VERSION'] !== req.cfg.urlArgs) {
// new version, flush
Object.keys(localStorage).forEach(function (k) {
if (!k.indexOf('CRYPTPAD_CACHE_')) { delete localStorage[k]; }
});
localStorage['CRYPTPAD_VERSION'] = req.cfg.urlArgs;
}
} catch (e) {
console.error(e);
localStorage = {};
}
}
window.cryptpadCache = Object.freeze({
put: function (k, v, cb) {
cb = cb || function () { };
setTimeout(function () { localStorage['CRYPTPAD_CACHE_' + k] = v; cb(); });
},
get: function (k, cb) {
if (!cb) { throw new Error(); }
setTimeout(function () { cb(localStorage['CRYPTPAD_CACHE_' + k]); });
}
});
req.cfg = req.cfg || {}; req.cfg = req.cfg || {};
if (req.pfx) { if (req.pfx) {
req.cfg.onNodeCreated = function (node /*, config, module, path*/) { req.cfg.onNodeCreated = function (node /*, config, module, path*/) {

@ -10,17 +10,6 @@ define(['/common/requireconfig.js'], function (RequireConfig) {
}; };
} }
// In the event that someone clicks a link in the iframe, it's going to cause the iframe
// to navigate away from the pad which is going to be a mess. Instead we'll just reload
// the top level and then it will be simply that a link doesn't work properly.
window.onunload = function () {
window.parent.location.reload();
};
// Make sure anything which might have leaked to the localstorage is always cleaned up.
try { window.localStorage.clear(); } catch (e) { }
try { window.sessionStorage.clear(); } catch (e) { }
var mkFakeStore = function () { var mkFakeStore = function () {
var fakeStorage = { var fakeStorage = {
getItem: function (k) { return fakeStorage[k]; }, getItem: function (k) { return fakeStorage[k]; },

@ -2,7 +2,7 @@
<html class="cp-app-noscroll"> <html class="cp-app-noscroll">
<head> <head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/file/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script> <script async data-bootload="/file/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<style> <style>
.loading-hidden { display: none; } .loading-hidden { display: none; }
#editor1 { display: none; } #editor1 { display: none; }

@ -2,7 +2,7 @@
<html style="height: 100%; background: transparent;"> <html style="height: 100%; background: transparent;">
<head> <head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/filepicker/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script> <script async data-bootload="/filepicker/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<style> <style>
.loading-hidden { display: none; } .loading-hidden { display: none; }
body #loading { body #loading {

@ -2,7 +2,7 @@
<html class="cp-app-noscroll"> <html class="cp-app-noscroll">
<head> <head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/pad/inner.js" data-main="/common/sframe-boot.js?ver=1.2" src="/bower_components/requirejs/require.js?ver=2.3.5"></script> <script async data-bootload="/pad/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
</head> </head>
<body class="cp-app-pad"> <body class="cp-app-pad">
<textarea style="display:none" id="editor1" name="editor1"></textarea> <textarea style="display:none" id="editor1" name="editor1"></textarea>

@ -2,7 +2,7 @@
<html class="cp-app-noscroll cp-app-print"> <html class="cp-app-noscroll cp-app-print">
<head> <head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/slide/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script> <script async data-bootload="/slide/inner.js" data-main="/common/sframe-boot.js?ver=1.3" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<style> <style>
.loading-hidden { display: none; } .loading-hidden { display: none; }
#editor1 { display: none; } #editor1 { display: none; }

Loading…
Cancel
Save