blob: 7c7a11b4206da31d1f9b4fdeb8b0073fb03d390e [file] [log] [blame]
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
from docs_server_utils import FormatKey
from file_system import FileNotFoundError
from third_party.handlebar import Handlebar
import url_constants
_EXTENSIONS_URL = '/chrome/extensions'
class TemplateDataSource(object):
'''Renders Handlebar templates, providing them with the context in which to
render.
Also acts as a data source itself, providing partial Handlebar templates to
those it renders.
Each instance of TemplateDataSource is bound to a Request so that it can
render templates with request-specific data (such as Accept-Language); use
a Factory to cheaply construct these.
'''
class Factory(object):
'''A factory to create lightweight TemplateDataSource instances bound to
individual Requests.
'''
def __init__(self,
api_data_source_factory,
api_list_data_source_factory,
intro_data_source_factory,
samples_data_source_factory,
compiled_fs_factory,
ref_resolver_factory,
permissions_data_source,
public_template_path,
private_template_path,
base_path):
self._api_data_source_factory = api_data_source_factory
self._api_list_data_source_factory = api_list_data_source_factory
self._intro_data_source_factory = intro_data_source_factory
self._samples_data_source_factory = samples_data_source_factory
self._cache = compiled_fs_factory.Create(self._CreateTemplate,
TemplateDataSource)
self._ref_resolver = ref_resolver_factory.Create()
self._permissions_data_source = permissions_data_source
self._public_template_path = public_template_path
self._private_template_path = private_template_path
self._base_path = base_path
def _CreateTemplate(self, template_name, text):
return Handlebar(self._ref_resolver.ResolveAllLinks(text))
def Create(self, request, data_sources):
'''Bind a new TemplateDataSource to a servlet.Request |request| and a
dictionary of instantiated DataSources*. Keys in |data_sources| are the
names that templates will use to access the corresponding DataSource.
* this is temporary until the data source registry transition is complete.
'''
return TemplateDataSource(
self._api_data_source_factory.Create(request),
self._api_list_data_source_factory.Create(),
self._intro_data_source_factory.Create(),
self._samples_data_source_factory.Create(request),
self._cache,
self._permissions_data_source,
self._public_template_path,
self._private_template_path,
self._base_path,
data_sources)
def __init__(self,
api_data_source,
api_list_data_source,
intro_data_source,
samples_data_source,
cache,
permissions_data_source,
public_template_path,
private_template_path,
base_path,
data_sources):
self._api_list_data_source = api_list_data_source
self._intro_data_source = intro_data_source
self._samples_data_source = samples_data_source
self._api_data_source = api_data_source
self._cache = cache
self._public_template_path = public_template_path
self._private_template_path = private_template_path
self._permissions_data_source = permissions_data_source
self._base_path = base_path
self._data_sources = data_sources
def Render(self, template_name):
'''This method will render a template named |template_name|, fetching all
the partial templates needed from |self._cache|. Partials are retrieved
from the TemplateDataSource with the |get| method.
'''
template = self.GetTemplate(self._public_template_path, template_name)
if template is None:
return None
# TODO error handling
render_context = {
'api_list': self._api_list_data_source,
'apis': self._api_data_source,
'intros': self._intro_data_source,
'partials': self,
'permissions': self._permissions_data_source,
'samples': self._samples_data_source,
'apps_samples_url': url_constants.GITHUB_BASE,
'extensions_samples_url': url_constants.EXTENSIONS_SAMPLES,
'static': self._base_path + '/static',
'true': True,
'false': False
}
render_context.update(self._data_sources)
render_data = template.render(render_context)
if render_data.errors:
logging.error('Handlebar error(s) rendering %s:\n%s' %
(template_name, ' \n'.join(render_data.errors)))
return render_data.text
def get(self, key):
return self.GetTemplate(self._private_template_path, key)
def GetTemplate(self, base_path, template_name):
try:
return self._cache.GetFromFile(
'/'.join((base_path, FormatKey(template_name))))
except FileNotFoundError:
return None