document_renderer.py revision 116680a4aac90f2aa7413d9095a592090648e557
1# Copyright 2013 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. 4 5import logging 6import os 7from document_parser import ParseDocument 8from platform_util import ExtractPlatformFromURL 9from third_party.json_schema_compiler.model import UnixName 10 11 12class DocumentRenderer(object): 13 '''Performs document-level rendering such as the title, references, 14 and table of contents: pulling that data out of the document, then 15 replacing the $(title), $(ref:...) and $(table_of_contents) tokens with them. 16 17 This can be thought of as a parallel to TemplateRenderer; while 18 TemplateRenderer is responsible for interpreting templates and rendering files 19 within the template engine, DocumentRenderer is responsible for interpreting 20 higher-level document concepts like the title and TOC, then performing string 21 replacement for them. The syntax for this replacement is $(...) where ... is 22 the concept. Currently title and table_of_contents are supported. 23 ''' 24 25 def __init__(self, table_of_contents_renderer, platform_bundle): 26 self._table_of_contents_renderer = table_of_contents_renderer 27 self._platform_bundle = platform_bundle 28 29 def _RenderLinks(self, document, path): 30 ''' Replaces all $(ref:...) references in |document| with html links. 31 32 References have two forms: 33 34 $(ref:api.node) - Replaces the reference with a link to node on the 35 API page. The title is set to the name of the node. 36 37 $(ref:api.node Title) - Same as the previous form, but title is set 38 to "Title". 39 ''' 40 START_REF = '$(ref:' 41 END_REF = ')' 42 MAX_REF_LENGTH = 256 43 44 new_document = [] 45 46 # Keeps track of position within |document| 47 cursor_index = 0 48 start_ref_index = document.find(START_REF) 49 50 while start_ref_index != -1: 51 end_ref_index = document.find(END_REF, start_ref_index) 52 53 if (end_ref_index == -1 or 54 end_ref_index - start_ref_index > MAX_REF_LENGTH): 55 end_ref_index = document.find(' ', start_ref_index) 56 logging.error('%s:%s has no terminating ) at line %s' % ( 57 path, 58 document[start_ref_index:end_ref_index], 59 document.count('\n', 0, end_ref_index))) 60 61 new_document.append(document[cursor_index:end_ref_index + 1]) 62 else: 63 ref = document[start_ref_index:end_ref_index] 64 ref_parts = ref[len(START_REF):].split(None, 1) 65 66 # Guess the api name from the html name, replacing '_' with '.' (e.g. 67 # if the page is app_window.html, guess the api name is app.window) 68 api_name = os.path.splitext(os.path.basename(path))[0].replace('_', '.') 69 title = ref_parts[0] if len(ref_parts) == 1 else ref_parts[1] 70 71 platform = ExtractPlatformFromURL(path) 72 if platform is None: 73 logging.error('Cannot resolve reference without a platform.') 74 continue 75 ref_dict = self._platform_bundle.GetReferenceResolver( 76 platform).SafeGetLink(ref_parts[0], 77 namespace=api_name, 78 title=title, 79 path=path) 80 81 new_document.append(document[cursor_index:start_ref_index]) 82 new_document.append('<a href=%s>%s</a>' % (ref_dict['href'], 83 ref_dict['text'])) 84 85 cursor_index = end_ref_index + 1 86 start_ref_index = document.find(START_REF, cursor_index) 87 88 new_document.append(document[cursor_index:]) 89 90 return ''.join(new_document) 91 92 def Render(self, document, path, render_title=False): 93 # Render links first so that parsing and later replacements aren't 94 # affected by $(ref...) substitutions 95 document = self._RenderLinks(document, path) 96 97 parsed_document = ParseDocument(document, expect_title=render_title) 98 toc_text, toc_warnings = self._table_of_contents_renderer.Render( 99 parsed_document.sections) 100 101 # Only 1 title and 1 table of contents substitution allowed; in the common 102 # case, save necessarily running over the entire file. 103 if parsed_document.title: 104 document = document.replace('$(title)', parsed_document.title, 1) 105 return (document.replace('$(table_of_contents)', toc_text, 1), 106 parsed_document.warnings + toc_warnings) 107