Comparing version 0.0.6 to 0.0.7
@@ -14,2 +14,4 @@ var cwd = process.cwd(); | ||
'node_modules/jymin/scripts/events.js', | ||
'node_modules/jymin/scripts/forms.js', | ||
'node_modules/jymin/scripts/history.js', | ||
'node_modules/jymin/scripts/logging.js', | ||
@@ -39,4 +41,3 @@ 'node_modules/jymin/scripts/strings.js', | ||
" */\n\n\n" + | ||
asset.getContent() + "\n" + | ||
"window.getD6 = getD6;\n").replace(/[\t ]*\n/g, '\n')); | ||
asset.getContent() + "\n").replace(/[\t ]*\n/g, '\n')); | ||
}) | ||
@@ -43,0 +44,0 @@ .wrap('window') |
14
d6.js
var zlib = require('zlib'); | ||
var http = require('./lib/http'); | ||
@@ -24,5 +25,11 @@ /** | ||
views.then(function () { | ||
var code = 'd6({' + pairs.join(',') + '});'; | ||
var env = process.env.NODE_ENV || 'prod'; | ||
var isDevOrDebug = (env[0] == 'd'); | ||
var br = isDevOrDebug ? '\n' : ''; | ||
var tab = isDevOrDebug ? ' ' : ''; | ||
// TODO: Allow views to be separated into batches to reduce payload. | ||
var url = '/d6.js'; | ||
var code = 'D6({' + br + tab + pairs.join(',' + br + tab) + br + '});'; | ||
zlib.gzip(code, function (err, zipped) { | ||
app.server.get('/d6.js', function (request, response, next) { | ||
app.server.get(url, function (request, response, next) { | ||
response.statusCode = 200; | ||
@@ -37,2 +44,3 @@ response.setHeader('content-type', 'text/javascript'); | ||
}); | ||
app.logger.info('[D6] Views routed to "' + url + '".'); | ||
}); | ||
@@ -42,3 +50,3 @@ }); | ||
}); | ||
} | ||
}; | ||
@@ -45,0 +53,0 @@ /** |
@@ -7,3 +7,3 @@ { | ||
], | ||
"version": "0.0.6", | ||
"version": "0.0.7", | ||
"main": "d6.js", | ||
@@ -31,3 +31,3 @@ "homepage": "http://lighter.io/d6", | ||
"dependencies": { | ||
"jymin": "0.2.2" | ||
"jymin": "0.2.4" | ||
}, | ||
@@ -37,5 +37,6 @@ "devDependencies": { | ||
"mocha": "1.20.1", | ||
"istanbul": "0.2.10", | ||
"istanbul": "0.2.11", | ||
"assert-plus": "0.1.5", | ||
"coveralls": "2.10.0" | ||
"coveralls": "2.10.0", | ||
"figlet": "1.0.9" | ||
}, | ||
@@ -42,0 +43,0 @@ "licenses": [ |
@@ -11,5 +11,5 @@ /** | ||
/** | ||
* The d6 function accepts new templates from /d6.js, etc. | ||
* The D6 function accepts new templates from /d6.js, etc. | ||
*/ | ||
var d6 = window.d6 = function (newViews) { | ||
var D6 = window.D6 = function (newViews) { | ||
decorateObject(views, newViews); | ||
@@ -21,5 +21,5 @@ if (!isReady) { | ||
var views = d6._VIEWS = {}; | ||
var views = D6._VIEWS = {}; | ||
var cache = d6._CACHE = {}; | ||
var cache = D6._CACHE = {}; | ||
@@ -37,3 +37,3 @@ var isReady = false; | ||
// When a same-domain link is clicked, fetch it via AJAX. | ||
// When a same-domain link is clicked, fetch it via XMLHttpRequest. | ||
on(body, 'a', 'click', function (a, event) { | ||
@@ -45,4 +45,3 @@ var url = removeHash(a.href); | ||
preventDefault(event); | ||
pushHistory(url); | ||
loadUrl(url, renderResponse); | ||
loadUrl(url); | ||
} | ||
@@ -63,2 +62,72 @@ }); | ||
// When a form field changes, timestamp the form. | ||
var inputChanged = function (input) { | ||
var form = input.form; | ||
if (form) { | ||
form._LAST_CHANGED = getTime(); | ||
} | ||
}; | ||
on(body, 'input', 'change', inputChanged); | ||
on(body, 'select', 'change', inputChanged); | ||
on(body, 'textarea', 'change', inputChanged); | ||
// When a form button is clicked, attach it to the form. | ||
var buttonClicked = function (button) { | ||
if (button.type == 'submit') { | ||
var form = button.form; | ||
if (form) { | ||
if (form._CLICKED_BUTTON != button) { | ||
form._CLICKED_BUTTON = button; | ||
form._LAST_CHANGED = getTime(); | ||
} | ||
} | ||
} | ||
}; | ||
on(body, 'input', 'click', buttonClicked); | ||
on(body, 'button', 'click', buttonClicked); | ||
// When a form is submitted, gather its data and submit via XMLHttpRequest. | ||
on(body, 'form', 'submit', function (form, event) { | ||
var url = removeHash(form.action); | ||
var isGet = (lower(form.method) == 'get'); | ||
if (isSameDomain(url)) { | ||
preventDefault(event); | ||
// Get form data. | ||
var data = []; | ||
all(form, 'input,select,textarea,button', function (input) { | ||
var name = input.name; | ||
var type = input.type; | ||
var value = getValue(input); | ||
var ignore = !name; | ||
ignore = ignore || ((type == 'radio') && !value); | ||
ignore = ignore || ((type == 'submit') && (input != form._CLICKED_BUTTON)); | ||
if (!ignore) { | ||
if (isString(value)) { | ||
push(data, escape(name) + '=' + escape(value)); | ||
} | ||
else { | ||
forEach(value, function (val) { | ||
push(data, escape(name) + '=' + escape(val)); | ||
}); | ||
} | ||
} | ||
}); | ||
// For a get request, append data to the URL. | ||
if (isGet) { | ||
url += (contains(url, '?') ? '&' : '?') + data.join('&'); | ||
data = 0; | ||
} | ||
// If posting, append a timestamp so we can repost with this base URL. | ||
else { | ||
url = appendD6Param(url, form._LAST_CHANGED); | ||
data = data.join('&'); | ||
} | ||
// Submit form data to the URL. | ||
loadUrl(url, data); | ||
} | ||
}); | ||
var currentLocation = location; | ||
@@ -68,3 +137,3 @@ | ||
onHistoryPop(function (event) { | ||
loadUrl(location, renderResponse); | ||
loadUrl(location); | ||
}); | ||
@@ -83,9 +152,26 @@ | ||
var appendD6Param = function (url, number) { | ||
return url + (contains(url, '?') ? '&' : '?') + 'd6=' + (number || 1); | ||
}; | ||
var removeD6Param = function (url) { | ||
return url.replace(/[&\?]d6=[1r]/g, ''); | ||
}; | ||
var prefetchUrl = function (url) { | ||
// Only proceed if it's not already prefetched. | ||
if (!cache[url]) { | ||
//+env:debug | ||
log('[D6] Prefetching "' + url + '".'); | ||
//-env:debug | ||
// Create a callback queue to execute when data arrives. | ||
cache[url] = [function (response) { | ||
//+env:debug | ||
log('[D6] Executing callbacks for prefetched URL "' + url + '".'); | ||
//-env:debug | ||
// Cache the response so data can be used without a queue. | ||
cache[url] = response; | ||
// Remove the data after 10 seconds, or the given TTL. | ||
@@ -96,2 +182,5 @@ var ttl = response.ttl || 1e4; | ||
if (!isArray(cache[url])) { | ||
//+env:debug | ||
log('[D6] Removing "' + url + '" from prefetch cache.'); | ||
//-env:debug | ||
delete cache[url]; | ||
@@ -108,5 +197,8 @@ } | ||
*/ | ||
var loadUrl = d6._LOAD = function (url, callback) { | ||
var loadUrl = D6._LOAD_URL = function (url, data) { | ||
D6._LOADING_URL = removeD6Param(url); | ||
D6._LOAD_STARTED = getTime(); | ||
//+env:debug | ||
log('Loading URL: "' + url + '"'); | ||
log('[D6] Loading "' + url + '".'); | ||
//-env:debug | ||
@@ -124,11 +216,20 @@ | ||
if (!resource) { | ||
cache[url] = [callback]; | ||
getD6Json(url); | ||
//+env:debug | ||
log('[D6] Creating callback queue for "' + url + '".'); | ||
//-env:debug | ||
cache[url] = [renderResponse]; | ||
getD6Json(url, data); | ||
} | ||
// If the "resource" is a callback queue, then pushing means listening. | ||
else if (isArray(resource)) { | ||
push(resource, callback); | ||
//+env:debug | ||
log('[D6] Queueing callback for "' + url + '".'); | ||
//-env:debug | ||
push(resource, renderResponse); | ||
} | ||
// If the resource exists and isn't an array, render it. | ||
else { | ||
//+env:debug | ||
log('[D6] Found precached response for "' + url + '".'); | ||
//-env:debug | ||
renderResponse(resource); | ||
@@ -142,12 +243,18 @@ } | ||
var getD6Json = function (url, data) { | ||
//+env:debug | ||
log('[D6] Fetching response for "' + url + '".'); | ||
//-env:debug | ||
// Indicate with a URL param that D6 is requesting data, so we'll get JSON. | ||
var d6Url = url + (contains(url, '?') ? '&' : '?') + 'd6=on'; | ||
var d6Url = appendD6Param(url); | ||
// When data is received, cache the response and execute callbacks. | ||
var onComplete = function (response) { | ||
var onComplete = function (data) { | ||
var queue = cache[url]; | ||
cache[url] = response; | ||
cache[url] = data; | ||
//+env:debug | ||
log('[D6] Running ' + queue.length + ' callback(s) for "' + url + '".'); | ||
//-env:debug | ||
forEach(queue, function (callback) { | ||
callback(response); | ||
callback(data); | ||
}); | ||
@@ -162,45 +269,58 @@ }; | ||
var renderResponse = function (context) { | ||
D6._CONTEXT = context; | ||
var err = context._ERROR; | ||
var view = views[context._STATUS ? context.view : 'error0']; | ||
var url = context.request.url.replace(/[&\?]d6=on/, ''); | ||
var requestUrl = removeD6Param(context._REQUEST._URL); | ||
var responseUrl = context.d6u || requestUrl; | ||
var viewName = context.d6 || 'error0'; | ||
var view = D6._VIEW = views[viewName]; | ||
var html; | ||
//+env:debug | ||
log('Rendering "' + url + '" response:', context); | ||
//-env:debug | ||
// Make sure the URL we render is the last one we tried to load. | ||
if (requestUrl == D6._LOADING_URL) { | ||
// Reset any spinners. | ||
all('._SPINNER', function (spinner) { | ||
removeClass(spinner, '_LOADING'); | ||
}); | ||
// Reset any spinners. | ||
all('._SPINNER', function (spinner) { | ||
removeClass(spinner, '_LOADING'); | ||
}); | ||
// If we got bad JSON, try rendering it as HTML. | ||
if (err == '_BAD_JSON') { | ||
html = context._TEXT; | ||
//+env:debug | ||
error(err + ': "' + html + '"'); | ||
//-env:debug | ||
writeHtml(html); | ||
// If we got a string, try rendering it as HTML. | ||
if (isString(context) && trim(context)[0] == '<') { | ||
html = context; | ||
//+env:debug | ||
log('[D6] Rendering HTML string'); | ||
//-env:debug | ||
} | ||
// If the context refers to a view that we have, render it. | ||
else if (view) { | ||
html = view.call(views, context); | ||
//+env:debug | ||
log('[D6] Rendering view "' + viewName + '".'); | ||
//-env:debug | ||
} | ||
// If we can't find a corresponding view, navigate the old-fashioned way. | ||
else { | ||
//+env:debug | ||
error('[D6] View "' + viewName + '" not found. Changing location.'); | ||
//-env:debug | ||
window.location = responseUrl; | ||
} | ||
} | ||
// If the context refers to a view that we have, render it. | ||
else if (view) { | ||
html = view.call(views, context); | ||
// If there's HTML to render, show it as a page. | ||
if (html) { | ||
writeHtml(html); | ||
} | ||
// If we can't find a corresponding view, navigate the old-fashioned way. | ||
else { | ||
//+env:debug | ||
error('View not found: "' + context.view + '"'); | ||
//-env:debug | ||
// Change the location bar to reflect where we are now. | ||
pushHistory(responseUrl); | ||
// TODO: Restore the hash from the request URL. | ||
window.location = url; | ||
// If we render this page again, we'll want fresh data. | ||
delete cache[requestUrl]; | ||
} | ||
// If we render this page again, we'll want a fresh context. | ||
delete cache[url]; | ||
}; | ||
/** | ||
* Overwrite the page with new HTML, and execute embedded scripts. | ||
*/ | ||
var writeHtml = function (html) { | ||
@@ -222,9 +342,9 @@ match(html, /<title.*?>([\s\S]+)<\/title>/, function (tag, title) { | ||
}); | ||
var e = window.eval; | ||
scripts.forEach(function (js) { | ||
e(js); | ||
}); | ||
scripts.forEach(execute); | ||
onReady(); | ||
}; | ||
/** | ||
* Insert a script to load D6 templates, using the cachebust from "/a.js". | ||
*/ | ||
var cacheBust; | ||
@@ -231,0 +351,0 @@ var scripts = getElementsByTagName('script'); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
70897
9
2177
6
2
2
+ Addedjymin@0.2.4(transitive)
- Removedjymin@0.2.2(transitive)
Updatedjymin@0.2.4