Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: chrome/common/extensions/docs/server2/intro_data_source.py

Issue 65643009: Docserver: Attach intro metadata to the template itself, not to an object which (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 from HTMLParser import HTMLParser 5 from HTMLParser import HTMLParser
6 import logging 6 import logging
7 import os 7 import os
8 import re 8 import re
9 9
10 from extensions_paths import INTROS_TEMPLATES, ARTICLES_TEMPLATES 10 from extensions_paths import INTROS_TEMPLATES, ARTICLES_TEMPLATES
11 from data_source import DataSource 11 from data_source import DataSource
12 from docs_server_utils import FormatKey 12 from docs_server_utils import FormatKey
13 from file_system import FileNotFoundError 13 from file_system import FileNotFoundError
14 from future import Future 14 from future import Future
15 from third_party.handlebar import Handlebar 15 from third_party.handlebar import Handlebar
16 16
17 17
18 _H1_REGEX = re.compile('<h1[^>.]*?>.*?</h1>', flags=re.DOTALL) 18 _H1_REGEX = re.compile('<h1[^>.]*?>.*?</h1>', flags=re.DOTALL)
19 19
20 20
21 class _HandlebarWithContext(Handlebar):
22 '''Extends Handlebar with a get() method so that templates can not only
23 render intros with {{+intro}} but also access properties on them, like
24 {{intro.title}}, {{intro.toc}}, etc.
25 '''
26
27 def __init__(self, text, name, context):
28 Handlebar.__init__(self, text, name=name)
29 self._context = context
30
31 def get(self, key):
32 return self._context.get(key)
33
34
21 # TODO(kalman): rename this HTMLDataSource or other, then have separate intro 35 # TODO(kalman): rename this HTMLDataSource or other, then have separate intro
22 # article data sources created as instances of it. 36 # article data sources created as instances of it.
23 class _IntroParser(HTMLParser): 37 class _IntroParser(HTMLParser):
24 ''' An HTML parser which will parse table of contents and page title info out 38 ''' An HTML parser which will parse table of contents and page title info out
25 of an intro. 39 of an intro.
26 ''' 40 '''
27 def __init__(self): 41 def __init__(self):
28 HTMLParser.__init__(self) 42 HTMLParser.__init__(self)
29 self.toc = [] 43 self.toc = []
30 self.page_title = None 44 self.page_title = None
(...skipping 24 matching lines...) Expand all
55 if self._recent_tag is None: 69 if self._recent_tag is None:
56 return 70 return
57 if self._recent_tag == 'h1': 71 if self._recent_tag == 'h1':
58 if self.page_title is None: 72 if self.page_title is None:
59 self.page_title = data 73 self.page_title = data
60 else: 74 else:
61 self.page_title += data 75 self.page_title += data
62 elif self._recent_tag in ['h2', 'h3']: 76 elif self._recent_tag in ['h2', 'h3']:
63 self._current_heading['title'] += data 77 self._current_heading['title'] += data
64 78
79
65 class IntroDataSource(DataSource): 80 class IntroDataSource(DataSource):
66 '''This class fetches the intros for a given API. From this intro, a table 81 '''This class fetches the intros for a given API. From this intro, a table
67 of contents dictionary is created, which contains the headings in the intro. 82 of contents dictionary is created, which contains the headings in the intro.
68 ''' 83 '''
69 84
70 def __init__(self, server_instance, _): 85 def __init__(self, server_instance, request):
86 self._template_renderer = server_instance.template_renderer
87 self._request = request
71 self._cache = server_instance.compiled_fs_factory.Create( 88 self._cache = server_instance.compiled_fs_factory.Create(
72 server_instance.host_file_system_provider.GetTrunk(), 89 server_instance.host_file_system_provider.GetTrunk(),
73 self._MakeIntroDict, 90 self._MakeIntro,
74 IntroDataSource) 91 IntroDataSource)
75 self._ref_resolver = server_instance.ref_resolver_factory.Create() 92 self._ref_resolver = server_instance.ref_resolver_factory.Create()
76 93
77 def _MakeIntroDict(self, intro_path, intro): 94 def _MakeIntro(self, intro_path, intro):
78 # Guess the name of the API from the path to the intro. 95 # Guess the name of the API from the path to the intro.
79 api_name = os.path.splitext(intro_path.split('/')[-1])[0] 96 api_name = os.path.splitext(intro_path.split('/')[-1])[0]
80 intro_with_links = self._ref_resolver.ResolveAllLinks(intro, 97 intro_with_links = self._ref_resolver.ResolveAllLinks(
81 namespace=api_name) 98 intro, namespace=api_name)
82 # TODO(kalman): Do $ref replacement after rendering the template, not 99
83 # before, so that (a) $ref links can contain template annotations, and (b) 100 # TODO(kalman): In order to pick up every header tag, and therefore make a
84 # we can use CompiledFileSystem.ForTemplates to create the templates and 101 # complete TOC, the render context of the Handlebar needs to be passed
85 # save ourselves some effort. 102 # through to here. Even if there were a mechanism to do this it would
86 apps_parser = _IntroParser() 103 # break caching; we'd need to do the TOC parsing *after* rendering the full
87 apps_parser.feed(Handlebar(intro_with_links).render( 104 # template, and that would probably be expensive.
88 { 'is_apps': True }).text) 105 intro_parser = _IntroParser()
89 extensions_parser = _IntroParser() 106 intro_parser.feed(
90 extensions_parser.feed(Handlebar(intro_with_links).render( 107 self._template_renderer.Render(Handlebar(intro_with_links),
91 { 'is_apps': False }).text) 108 self._request,
92 # TODO(cduvall): Use the normal template rendering system, so we can check 109 # Avoid nasty surprises.
93 # errors. 110 data_sources=('partials', 'strings'),
94 if extensions_parser.page_title != apps_parser.page_title: 111 warn=False))
95 logging.error( 112
96 'Title differs for apps and extensions: Apps: %s, Extensions: %s.' %
97 (extensions_parser.page_title, apps_parser.page_title))
98 # The templates will render the heading themselves, so remove it from the 113 # The templates will render the heading themselves, so remove it from the
99 # HTML content. 114 # HTML content.
100 intro_with_links = re.sub(_H1_REGEX, '', intro_with_links, count=1) 115 intro_with_links = re.sub(_H1_REGEX, '', intro_with_links, count=1)
101 return { 116
102 'intro': Handlebar(intro_with_links), 117 context = {
103 'title': apps_parser.page_title, 118 'title': intro_parser.page_title,
104 'apps_toc': apps_parser.toc, 119 'toc': intro_parser.toc,
105 'extensions_toc': extensions_parser.toc,
106 } 120 }
121 return _HandlebarWithContext(intro_with_links, intro_path, context)
107 122
108 def get(self, key): 123 def get(self, key):
109 path = FormatKey(key) 124 path = FormatKey(key)
110 def get_from_base_path(base_path): 125 def get_from_base_path(base_path):
111 return self._cache.GetFromFile('%s/%s' % (base_path, path)).Get() 126 return self._cache.GetFromFile('%s/%s' % (base_path, path)).Get()
112 base_paths = (INTROS_TEMPLATES, ARTICLES_TEMPLATES) 127 base_paths = (INTROS_TEMPLATES, ARTICLES_TEMPLATES)
113 for base_path in base_paths: 128 for base_path in base_paths:
114 try: 129 try:
115 return get_from_base_path(base_path) 130 return get_from_base_path(base_path)
116 except FileNotFoundError: 131 except FileNotFoundError:
117 continue 132 continue
118 # Not found. Do the first operation again so that we get a stack trace - we 133 # Not found. Do the first operation again so that we get a stack trace - we
119 # know that it'll fail. 134 # know that it'll fail.
120 get_from_base_path(base_paths[0]) 135 get_from_base_path(base_paths[0])
121 raise AssertionError() 136 raise AssertionError()
122 137
123 def Cron(self): 138 def Cron(self):
124 # TODO(kalman): Walk through the intros and articles directory. 139 # TODO(kalman): Walk through the intros and articles directory.
125 return Future(value=()) 140 return Future(value=())
OLDNEW
« no previous file with comments | « chrome/common/extensions/docs/server2/cron.yaml ('k') | chrome/common/extensions/docs/server2/intro_data_source_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698