Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / common / extensions / docs / server2 / sidenav_data_source.py
blobcc43d52b93d4a6bfc54dcdbee92bf3cefbec2f4a
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 import copy
6 import logging
8 from compiled_file_system import SingleFile, Unicode
9 from data_source import DataSource
10 from extensions_paths import JSON_TEMPLATES
11 from future import Gettable, Future
12 from third_party.json_schema_compiler.json_parse import Parse
15 def _AddLevels(items, level):
16 '''Add a 'level' key to each item in |items|. 'level' corresponds to how deep
17 in |items| an item is. |level| sets the starting depth.
18 '''
19 for item in items:
20 item['level'] = level
21 if 'items' in item:
22 _AddLevels(item['items'], level + 1)
25 def _AddAnnotations(items, path, parent=None):
26 '''Add 'selected', 'child_selected' and 'related' properties to
27 |items| so that the sidenav can be expanded to show which menu item has
28 been selected and the related pages section can be drawn. 'related'
29 is added to all items with the same parent as the selected item.
30 If more than one item exactly matches the path, the deepest one is considered
31 'selected'. A 'parent' property is added to the selected path.
33 Returns True if an item was marked 'selected'.
34 '''
35 for item in items:
36 if 'items' in item:
37 if _AddAnnotations(item['items'], path, item):
38 item['child_selected'] = True
39 return True
41 if item.get('href', '') == path:
42 item['selected'] = True
43 if parent:
44 item['parent'] = { 'title': parent.get('title', None),
45 'href': parent.get('href', None) }
47 for sibling in items:
48 sibling['related'] = True
50 return True
52 return False
55 class SidenavDataSource(DataSource):
56 '''Provides templates with access to JSON files used to create the side
57 navigation bar.
58 '''
59 def __init__(self, server_instance, request):
60 self._cache = server_instance.compiled_fs_factory.Create(
61 server_instance.host_file_system_provider.GetTrunk(),
62 self._CreateSidenavDict,
63 SidenavDataSource)
64 self._server_instance = server_instance
65 self._request = request
67 @SingleFile
68 @Unicode
69 def _CreateSidenavDict(self, _, content):
70 items = Parse(content)
71 # Start at level 2, the top <ul> element is level 1.
72 _AddLevels(items, level=2)
73 self._QualifyHrefs(items)
74 return items
76 def _QualifyHrefs(self, items):
77 '''Force hrefs in |items| to either be absolute (http://...) or qualified
78 (beginning with /, in which case it will be moved relative to |base_path|).
79 Relative hrefs emit a warning and should be updated.
80 '''
81 for item in items:
82 if 'items' in item:
83 self._QualifyHrefs(item['items'])
85 href = item.get('href')
86 if href is not None and not href.startswith(('http://', 'https://')):
87 if not href.startswith('/'):
88 logging.warn('Paths in sidenav must be qualified. %s is not.' % href)
89 else:
90 href = href.lstrip('/')
91 item['href'] = self._server_instance.base_path + href
93 def Cron(self):
94 return self._cache.GetFromFile('%s/chrome_sidenav.json' % (JSON_TEMPLATES))
96 def get(self, key):
97 # TODO(mangini/kalman): Use |key| to decide which sidenav to use,
98 # which will require a more complex Cron method.
99 sidenav = self._cache.GetFromFile(
100 '%s/chrome_sidenav.json' % JSON_TEMPLATES).Get()
101 sidenav = copy.deepcopy(sidenav)
102 _AddAnnotations(sidenav,
103 self._server_instance.base_path + self._request.path)
104 return sidenav