let XDate = require('xdate') let cookie = require('cookie') let crypto = require('crypto') return async (env, head, body, scripts) => { let favicons = await env.site.get_min_html('/_favicon/favicons.html') let globals = await env.site.get_json('/_config/globals.json') await env.site.ensure_dir('/_analytics') let sessions = await env.site.read_json('/_analytics/sessions.json', {}) let pageviews = await env.site.read_json('/_analytics/pageviews.json', {}) let cookies = cookie.parse(env.request.headers.cookie || '') let session_key if ( !Object.prototype.hasOwnProperty.call(cookies, 'session_key') || !Object.prototype.hasOwnProperty.call( sessions, session_key = cookies.session_key ) ) { session_key = crypto.randomBytes(16).toString('hex') console.log('new session', session_key) sessions[session_key] = {pageviews: {}} } let session = sessions[session_key] let expires = new XDate() expires.addMonths(1) session.expires = expires.toUTCString() env.response.setHeader( 'Set-Cookie', 'session_key=' + session_key + '; expires=' + session.expires + '; path=/;' ) if ( !Object.prototype.hasOwnProperty.call( pageviews, env.parsed_url.pathname ) ) { console.log('new pageview', env.parsed_url.pathname) pageviews[env.parsed_url.pathname] = {visits: 0, unique_visits: 0} } let pageview = pageviews[env.parsed_url.pathname] ++pageview.visits; //if (!Object.prototype.hasOwnProperty.call(session, 'pageviews')) // session.pageviews = {} let session_pageviews = session.pageviews if ( !Object.prototype.hasOwnProperty.call( session_pageviews, env.parsed_url.pathname ) ) { console.log('new session_pageview', env.parsed_url.pathname) session_pageviews[env.parsed_url.pathname] = 0 ++pageview.unique_visits } ++session_pageviews[env.parsed_url.pathname] env.site.write_json('/_analytics/sessions.json', sessions) env.site.write_json('/_analytics/pageviews.json', pageviews) let _out = [] _out.push('') html(lang="en") { head { meta(charset="utf-8") {} meta(http-equiv="X-UA-Compatible" content="IE=edge") {} meta(name="viewport" content="width=device-width,initial-scale=1") {} // The above 3 meta tags *must* come first in the head; // any other head content must come *after* these tags title { _out.push( globals.site_title + ": " + (globals.page_to_title[env.parsed_url.pathname] || env.parsed_url.pathname) ) } link(rel="stylesheet" href="/css/bootstrap.css") {} link(rel="stylesheet" href="//fonts.googleapis.com/css?family=Frank+Ruhl+Libre:regular,regularitalic,semibold,semibolditalic,bold,bolditalic,black,blackitalic") {} link(rel="stylesheet" href="//fonts.googleapis.com/css?family=Nunito+Sans:regular,regularitalic,semibold,semibolditalic,bold,bolditalic,black,blackitalic") {} await head(_out) // HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries // WARNING: Respond.js doesn't work if you view the page via file:// _out.push('') // use favicon generator website to get favicons.zip and favicons.html _out.push(favicons) } body { await body(_out) // jQuery (necessary for Bootstrap's JavaScript plugins) script(src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js") {} // Include all compiled plugins (below), or include individual files as needed //script(src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous") {} script(src="/js/bootstrap.js") {} await scripts(_out) } } env.site.serve(env, 200, Buffer.from(_out.join('')), 'page.jst') }