1 let XDate = require('xdate')
2 let cookie = require('cookie')
3 let crypto = require('crypto')
5 return async (env, head, body, scripts) => {
6 let favicons = await env.site.get_min_html('/_favicon/favicons.html')
7 let globals = await env.site.get_json('/_config/globals.json')
9 await env.site.ensure_dir('/_analytics')
10 let sessions = await env.site.read_json('/_analytics/sessions.json', {})
11 let pageviews = await env.site.read_json('/_analytics/pageviews.json', {})
13 let cookies = cookie.parse(env.request.headers.cookie || '')
16 !Object.prototype.hasOwnProperty.call(cookies, 'session_key') ||
17 !Object.prototype.hasOwnProperty.call(
19 session_key = cookies.session_key
22 session_key = crypto.randomBytes(16).toString('hex')
23 console.log('new session', session_key)
24 sessions[session_key] = {pageviews: {}}
26 let session = sessions[session_key]
28 let expires = new XDate()
30 session.expires = expires.toUTCString()
31 env.response.setHeader(
41 !Object.prototype.hasOwnProperty.call(
43 env.parsed_url.pathname
46 console.log('new pageview', env.parsed_url.pathname)
47 pageviews[env.parsed_url.pathname] = {visits: 0, unique_visits: 0}
49 let pageview = pageviews[env.parsed_url.pathname]
52 //if (!Object.prototype.hasOwnProperty.call(session, 'pageviews'))
53 // session.pageviews = {}
54 let session_pageviews = session.pageviews
56 !Object.prototype.hasOwnProperty.call(
58 env.parsed_url.pathname
61 console.log('new session_pageview', env.parsed_url.pathname)
62 session_pageviews[env.parsed_url.pathname] = 0
63 ++pageview.unique_visits
65 ++session_pageviews[env.parsed_url.pathname]
67 env.site.write_json('/_analytics/sessions.json', sessions)
68 env.site.write_json('/_analytics/pageviews.json', pageviews)
71 _out.push('<!DOCTYPE html>')
74 meta(charset="utf-8") {}
75 meta(http-equiv="X-UA-Compatible" content="IE=edge") {}
76 meta(name="viewport" content="width=device-width,initial-scale=1") {}
77 // The above 3 meta tags *must* come first in the head;
78 // any other head content must come *after* these tags
83 (globals.page_to_title[env.parsed_url.pathname] || env.parsed_url.pathname)
87 link(rel="stylesheet" href="/css/bootstrap.css") {}
88 link(rel="stylesheet" href="//fonts.googleapis.com/css?family=Frank+Ruhl+Libre:regular,regularitalic,semibold,semibolditalic,bold,bolditalic,black,blackitalic") {}
89 link(rel="stylesheet" href="//fonts.googleapis.com/css?family=Nunito+Sans:regular,regularitalic,semibold,semibolditalic,bold,bolditalic,black,blackitalic") {}
93 // HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries
94 // WARNING: Respond.js doesn't work if you view the page via file://
95 _out.push('<!--[if lt IE 9]>')
96 script(src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js") {}
97 script(src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js") {}
98 _out.push('<![endif]-->')
100 // use favicon generator website to get favicons.zip and favicons.html
106 // jQuery (necessary for Bootstrap's JavaScript plugins)
107 script(src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js") {}
108 // Include all compiled plugins (below), or include individual files as needed
109 //script(src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous") {}
110 script(src="/js/bootstrap.js") {}
115 env.site.serve(env, 200, Buffer.from(_out.join('')), 'page.jst')