Tag = require('tf')
Type = require('type-of-is')
ShortId = require('shortid')Tag = require('tf')
Type = require('type-of-is')
ShortId = require('shortid')Strings = require('../Shared/Strings')The container provides all the HTML needed outside of the body tag. as well as
class ServerContainer
_status : 200 constructor : (args)->
@_site_name = args.site_name
@_logo_url = args.logo_urlCalled on the server to build a map of all the view ids for the client to use for sync.
_idMap : ()->
idMap = (view)->
map = {}
for id, subview of view.subviews()
map[subview.id] = idMap(subview)
map
idMap(@_page)Load and build the page that this container is rendering
page : page to load & build
callback : callback to return (error)
load : (args)->
@_page = args.page
callback = args.callback
if @_page.needsUser()
@_page.setData({})
@_page.setBodyToLoadingView()
callback(null)
else
@_page.load((error, data)=>
unless error
@_page.setData(data)
@_page.buildAndSetBody()
callback(error)
)
storeInitData : (args)->
{store, callback} = args
store.set(
key : @_pageKey()
value : @_initData()
callback : callback
)returns the http status
status : ()->
@_statusreturns and custom headers for the container’s page
headers : ()->
@_page.headers()render this container as html
html : ()->TODO
"""
<!DOCTYPE html>
<html>
<head>
#{@_meta()}
<title>#{@_title()}</title>
#{(Tag.stylesheet(href: href) for href in @_page.styles).join("\n")}
#{(Tag.script(src: src) for src in @_page.scripts).join("\n")}
#{@_page.head()}
</head>
<body #{@_pageIdAttr()} #{@_pageKeyAttr()} #{@_isLoadingAttr()}>
#{@_page.html()}
</body>
</html>
"""render this container as text
text : ()->
@_page.text()render this container as json
json : ()->
@_page.json()pages should have a attribute or function ‘meta’ that provides the following metadata { title :
_meta : ()->
meta = @_page.getMeta()
url = @_page.url
title = @_title()
image = meta.image || @_logo_url
type = meta.type || 'website'
metadata = {
name : {
description : meta.description
viewport : @_page.viewport || 'width=device-width, initial-scale=1'
}Google rich snippets https://support.google.com/webmasters/answer/146750?hl=en
itemprop : {
name : title
description : meta.description
image : image
url : url
}FB Open Graph http://ogp.me
property : {
"og:title" : title
"og:description" : meta.description
"og:image" : image
"og:url" : url
"og:type" : type
"og:site_name" : @_site_name
}
}additional open graph properties specific to og:type
if meta.og
for k,v of meta.og
metadata.property["og:#{k}"] = vTODO: support html microdata
html = Tag.meta(charset : 'utf-8') + "\n"
for attr, m of metadata
for name, content of m
args = {
content : content
}
args[attr] = name
html += Tag.meta(args) + "\n"
htmlTitle for this container’s page
_title : ()->
@_page.title() || @_site_namePage key for storing init data
_pageKey : ()->
unless @_page_key
id = ShortId.generate()
@_page_key = "#{@_page.constructor.name}:#{id}"
@_page_keyReturns the page and id map data for this container to be used in sync on the client
_initData : ()->
result = {}
result[Strings.ID_MAP] = @_idMap()
result[Strings.PAGE_DATA] = @_page.page_data
resultThe attribute used to pass this page’s id and name in the rendered html for use in client sync
_pageKeyAttr : ()->
page_key = @_pageKey()
"#{Strings.PAGE_KEY_ATTR_NAME}=\"#{page_key}\""Body attribute holding the page name (useful for CSS namespacing)
_pageIdAttr : ()->
"id=\"#{@_page.id}\""Used by the client to determine whether the server was able to render the full page or whether its loading
_isLoadingAttr : ()->
"data-#{Strings.IS_LOADING}=\"#{@_page.needsUser()}\""
module.exports = ServerContainer