Commit 3c0d2262 authored by cduvall@chromium.org's avatar cduvall@chromium.org

Extensions Docs Server: Intro data source

An implementation of the intro data source. This data source is used to get the
intros for the APIs as well as construct the table of contents entries.

BUG=131095

Review URL: https://chromiumcodereview.appspot.com/10750017

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@145818 0039d316-1c4b-4281-b951-d872f2087c98
parent e19c2fc0
......@@ -20,6 +20,7 @@ from google.appengine.ext.webapp.util import run_wsgi_app
from api_data_source import APIDataSource
from fetcher_cache import FetcherCache
from intro_data_source import IntroDataSource
from local_fetcher import LocalFetcher
from server_instance import ServerInstance
from subversion_fetcher import SubversionFetcher
......@@ -28,6 +29,7 @@ from template_data_source import TemplateDataSource
EXTENSIONS_PATH = 'chrome/common/extensions'
DOCS_PATH = 'docs'
API_PATH = 'api'
INTRO_PATH = DOCS_PATH + '/server2/templates/intros'
PUBLIC_TEMPLATE_PATH = DOCS_PATH + '/server2/templates/public'
PRIVATE_TEMPLATE_PATH = DOCS_PATH + '/server2/templates/private'
......@@ -52,9 +54,11 @@ class Server(webapp.RequestHandler):
cache_timeout_seconds = 300
cache_builder = FetcherCache.Builder(fetcher, cache_timeout_seconds)
api_data_source = APIDataSource(cache_builder, API_PATH)
intro_data_source = IntroDataSource(cache_builder, INTRO_PATH)
template_data_source = TemplateDataSource(
branch,
api_data_source,
intro_data_source,
cache_builder,
[PUBLIC_TEMPLATE_PATH, PRIVATE_TEMPLATE_PATH])
SERVER_INSTANCES[branch] = ServerInstance(
......
# 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 re
from path_utils import FormatKey
from third_party.handlebar import Handlebar
class IntroDataSource(object):
"""This class fetches and loads JSON APIs with the fetcher passed in with
|cache_builder|, so the APIs can be plugged into templates.
"""
def __init__(self, cache_builder, base_path):
self._cache = cache_builder.build(self._MakeIntroDict)
self._base_path = base_path
def _MakeIntroDict(self, intro):
headings = re.findall('<h([23]) id\="(.+)">(.+)</h[23]>', intro)
toc = []
for heading in headings:
level, link, title = heading
if level == '2':
toc.append({ 'link': link, 'title': title, 'subheadings': [] })
else:
toc[-1]['subheadings'].append({ 'link': link, 'title': title })
return { 'intro': Handlebar(intro), 'toc': toc }
def __getitem__(self, key):
return self.get(key)
def get(self, key):
real_path = FormatKey(key)
try:
return self._cache.get(self._base_path + '/' + real_path)
except:
pass
return None
# 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.
def FormatKey(key):
"""Normalize a key by making sure it has a .html extension, and convert any
'.'s to '_'s.
"""
if key.endswith('.html'):
key = key[:-5]
safe_key = key.replace('.', '_')
return safe_key + '.html'
......@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
SUBVERSION_URL = 'http://src.chromium.org/viewvc/chrome'
SUBVERSION_URL = 'http://src.chromium.org/chrome'
TRUNK_URL = SUBVERSION_URL + '/trunk'
BRANCH_URL = SUBVERSION_URL + '/branches'
......
......@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from path_utils import FormatKey
from third_party.handlebar import Handlebar
EXTENSIONS_URL = '/chrome/extensions'
......@@ -10,11 +11,17 @@ class TemplateDataSource(object):
"""This class fetches and compiles templates using the fetcher passed in with
|cache_builder|.
"""
def __init__(self, branch, api_data_source, cache_builder, base_paths):
def __init__(self,
branch,
api_data_source,
intro_data_source,
cache_builder,
base_paths):
self._branch_info = self._MakeBranchDict(branch)
self._static_resources = ((('/' + branch) if branch != 'local' else '') +
'/static')
self._api_data_source = api_data_source
self._intro_data_source = intro_data_source
self._cache = cache_builder.build(self._LoadTemplate)
self._base_paths = base_paths
......@@ -45,6 +52,7 @@ class TemplateDataSource(object):
return template.render({
'apis': self._api_data_source,
'branchInfo': self._branch_info,
'intros': self._intro_data_source,
'partials': self,
'static': self._static_resources
}).text
......@@ -53,11 +61,7 @@ class TemplateDataSource(object):
return self.get(key)
def get(self, key):
index = key.rfind('.html')
if index > 0:
key = key[:index]
safe_key = key.replace('.', '_')
real_path = safe_key + '.html'
real_path = FormatKey(key)
for base_path in self._base_paths:
try:
return self._cache.get(base_path + '/' + real_path)
......
......@@ -16,6 +16,7 @@ class TemplateDataSourceTest(unittest.TestCase):
def setUp(self):
self._base_path = os.path.join('test_data', 'template_data_source')
self._fake_api_data_source = {}
self._fake_intro_data_source = {}
def _ReadLocalFile(self, filename):
with open(os.path.join(self._base_path, filename), 'r') as f:
......@@ -28,14 +29,19 @@ class TemplateDataSourceTest(unittest.TestCase):
self._ReadLocalFile(name + '_expected.html'),
data_source.Render(template_name))
def _CreateTemplateDataSource(self, input_dict, cache_builder):
return TemplateDataSource('fake_branch',
input_dict,
self._fake_intro_data_source,
cache_builder,
['./'])
def testSimple(self):
self._base_path = os.path.join(self._base_path, 'simple')
fetcher = LocalFetcher(self._base_path)
cache_builder = FetcherCache.Builder(fetcher, 0)
t_data_source = TemplateDataSource('fake_branch',
self._fake_api_data_source,
cache_builder,
['./'])
t_data_source = self._CreateTemplateDataSource(self._fake_api_data_source,
cache_builder)
template_a1 = Handlebar(self._ReadLocalFile('test1.html'))
self.assertEqual(template_a1.render({}, {'templates': {}}).text,
t_data_source['test1'].render({}, {'templates': {}}).text)
......@@ -50,10 +56,8 @@ class TemplateDataSourceTest(unittest.TestCase):
self._base_path = os.path.join(self._base_path, 'partials')
fetcher = LocalFetcher(self._base_path)
cache_builder = FetcherCache.Builder(fetcher, 0)
t_data_source = TemplateDataSource('fake_branch',
self._fake_api_data_source,
cache_builder,
['./'])
t_data_source = self._CreateTemplateDataSource(self._fake_api_data_source,
cache_builder)
self.assertEqual(self._ReadLocalFile('test_expected.html'),
t_data_source['test_tmpl'].render(
json.loads(self._ReadLocalFile('input.json')), t_data_source).text)
......@@ -65,16 +69,14 @@ class TemplateDataSourceTest(unittest.TestCase):
cache_builder = FetcherCache.Builder(fetcher, 0)
self._RenderTest(
'test1',
TemplateDataSource('fake_branch',
json.loads(self._ReadLocalFile('test1.json')),
cache_builder,
['./']))
self._CreateTemplateDataSource(
json.loads(self._ReadLocalFile('test1.json')),
cache_builder))
self._RenderTest(
'test2',
TemplateDataSource('fake_branch',
json.loads(self._ReadLocalFile('test2.json')),
cache_builder,
['./']))
self._CreateTemplateDataSource(
json.loads(self._ReadLocalFile('test2.json')),
cache_builder))
if __name__ == '__main__':
unittest.main()
......@@ -11,9 +11,9 @@
{{+partials.sidenav}}
<div id="gc-pagecontent">
<h1 class="page_title">chrome.{{api.name}}</h1>
{{+partials.table_of_contents}}
{{+partials.table_of_contents toc:intro.toc}}
{{- This is unindented because it contains <pre> tags -}}
{{+intro}}
{{+intro.intro}}
{{+partials.api_reference}}
</div>
</div>
......
<div id="toc">
<h2>Contents</h2>
<ol>
{{#toc}}
<li>
<a href=#{{link}}>{{title}}</a>
{{?subheadings}}
<ol>
{{#subheadings}}<li><a href=#{{link}}>{{title}}</a></li>{{/}}
</ol>
{{/}}
</li>
{{/toc}}
<li>
<a href="#apiReference">API reference: chrome.{{api.name}}</a>
<ol>
......
{{+partials.standard_api api:apis.bookmarks intro:partials.bookmarks_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.bookmarks intro:intros.bookmarks}}
{{+partials.standard_api api:apis.browserAction intro:partials.browserAction_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.browserAction intro:intros.browserAction}}
\ No newline at end of file
{{+partials.standard_api api:apis.browsingData intro:partials.browsingData_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.browsingData intro:intros.browsingData}}
\ No newline at end of file
{{+partials.standard_api api:apis.contentSettings intro:partials.contentSettings_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.contentSettings intro:intros.contentSettings}}
\ No newline at end of file
{{+partials.standard_api api:apis.contextMenus intro:partials.contextMenus_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.contextMenus intro:intros.contextMenus}}
\ No newline at end of file
{{+partials.standard_api api:apis.cookies intro:partials.cookies_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.cookies intro:intros.cookies}}
\ No newline at end of file
{{+partials.standard_api api:apis.debugger intro:partials.debugger_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.debugger intro:intros.debugger}}
\ No newline at end of file
{{+partials.standard_api api:apis.declarativeWebRequest intro:partials.declarativeWebRequest_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.declarativeWebRequest intro:intros.declarativeWebRequest}}
\ No newline at end of file
{{+partials.standard_api api:apis.devtools intro:partials.devtools_intro}}
{{+partials.standard_api api:apis.devtools intro:intros.devtools}}
{{+partials.standard_api api:apis.downloads intro:partials.downloads_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.downloads intro:intros.downloads}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_app intro:partials.experimental_app_intro}}
{{+partials.standard_api api:apis.experimental_app intro:intros.experimental_app}}
{{+partials.standard_api api:apis.experimental_discovery intro:partials.experimental_discovery_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_discovery intro:intros.experimental_discovery}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_fontSettings intro:partials.experimental_fontSettings_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_fontSettings intro:intros.experimental_fontSettings}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_infobars intro:partials.experimental_infobars_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_infobars intro:intros.experimental_infobars}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_inputUI intro:partials.experimental_inputUI_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_inputUI intro:intros.experimental_inputUI}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_keybinding intro:partials.experimental_keybinding_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_keybinding intro:intros.experimental_keybinding}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_speechInput intro:partials.experimental_speechInput_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.experimental_speechInput intro:intros.experimental_speechInput}}
\ No newline at end of file
{{+partials.standard_api api:apis.extension intro:partials.extension_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.extension intro:intros.extension}}
\ No newline at end of file
{{+partials.standard_api api:apis.fileBrowserHandler intro:partials.fileBrowserHandler_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.fileBrowserHandler intro:intros.fileBrowserHandler}}
\ No newline at end of file
{{+partials.standard_api api:apis.history intro:partials.history_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.history intro:intros.history}}
\ No newline at end of file
{{+partials.standard_api api:apis.i18n intro:partials.i18n_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.i18n intro:intros.i18n}}
\ No newline at end of file
{{+partials.standard_api api:apis.idle intro:partials.idle_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.idle intro:intros.idle}}
\ No newline at end of file
{{+partials.standard_api api:apis.management intro:partials.management_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.management intro:intros.management}}
\ No newline at end of file
{{+partials.standard_api api:apis.omnibox intro:partials.omnibox_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.omnibox intro:intros.omnibox}}
\ No newline at end of file
{{+partials.standard_api api:apis.pageAction intro:partials.pageAction_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.pageAction intro:intros.pageAction}}
\ No newline at end of file
{{+partials.standard_api api:apis.pageCapture intro:partials.pageCapture_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.pageCapture intro:intros.pageCapture}}
\ No newline at end of file
{{+partials.standard_api api:apis.permissions intro:partials.permissions_intro}}
{{+partials.standard_api api:apis.permissions intro:intros.permissions}}
{{+partials.standard_api api:apis.privacy intro:partials.privacy_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.privacy intro:intros.privacy}}
\ No newline at end of file
{{+partials.standard_api api:apis.proxy intro:partials.proxy_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.proxy intro:intros.proxy}}
\ No newline at end of file
{{+partials.standard_api api:apis.storage intro:partials.storage_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.storage intro:intros.storage}}
\ No newline at end of file
{{+partials.standard_api api:apis.tabs intro:partials.tabs_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.tabs intro:intros.tabs}}
\ No newline at end of file
{{+partials.standard_api api:apis.topSites intro:partials.topSites_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.topSites intro:intros.topSites}}
\ No newline at end of file
{{+partials.standard_api api:apis.tts intro:partials.tts_intro}}
{{+partials.standard_api api:apis.tts intro:intros.tts}}
{{+partials.standard_api api:apis.ttsEngine intro:partials.ttsEngine_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.ttsEngine intro:intros.ttsEngine}}
\ No newline at end of file
{{+partials.standard_api api:apis.types intro:partials.types_intro}}
{{+partials.standard_api api:apis.types intro:intros.types}}
{{+partials.standard_api api:apis.webNavigation intro:partials.webNavigation_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.webNavigation intro:intros.webNavigation}}
\ No newline at end of file
{{+partials.standard_api api:apis.webRequest intro:partials.webRequest_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.webRequest intro:intros.webRequest}}
\ No newline at end of file
{{+partials.standard_api api:apis.windows intro:partials.windows_intro}}
\ No newline at end of file
{{+partials.standard_api api:apis.windows intro:intros.windows}}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment