 c357cebdae
			
		
	
	c357cebdae
	
	
	
		
			
			Use the canonical syntax to specify the python executable to use. Avoids a fatal error if /usr/bin/python is a too old version (< 2.7). Change-Id: I3e8affb52be993d35c0dcf90774d962a59ef5635
		
			
				
	
	
		
			250 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python
 | |
| # Copyright (C) 2013 The Android Open Source Project
 | |
| #
 | |
| # Licensed under the Apache License, Version 2.0 (the "License");
 | |
| # you may not use this file except in compliance with the License.
 | |
| # You may obtain a copy of the License at
 | |
| #
 | |
| # http://www.apache.org/licenses/LICENSE-2.0
 | |
| #
 | |
| # Unless required by applicable law or agreed to in writing, software
 | |
| # distributed under the License is distributed on an "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| # See the License for the specific language governing permissions and
 | |
| # limitations under the License.
 | |
| 
 | |
| from optparse import OptionParser
 | |
| import re
 | |
| import sys
 | |
| 
 | |
| PAT_GERRIT = re.compile(r'^GERRIT')
 | |
| PAT_INCLUDE = re.compile(r'^(include::.*)(\[\])$')
 | |
| PAT_GET = re.compile(r'^get::([^ \t\n]*)')
 | |
| PAT_TITLE = re.compile(r'^\.(.*)')
 | |
| PAT_STARS = re.compile(r'^\*\*\*\*')
 | |
| PAT_SEARCHBOX = re.compile(r'^SEARCHBOX')
 | |
| 
 | |
| GERRIT_UPLINK = """
 | |
| 
 | |
| ++++
 | |
| <hr style=\"
 | |
|   height: 2px;
 | |
|   color: silver;
 | |
|   margin-top: 1.2em;
 | |
|   margin-bottom: 0.5em;
 | |
| \">
 | |
| ++++
 | |
| 
 | |
| """
 | |
| 
 | |
| GET_TITLE = '<div class="title">%s</div>'
 | |
| 
 | |
| GET_MACRO = """
 | |
| 
 | |
| ++++
 | |
| <div class="listingblock">
 | |
| %s
 | |
| <div class="content">
 | |
| <a id=\"{0}\" onmousedown="javascript:
 | |
|   var i = document.URL.lastIndexOf(\'/Documentation/\');
 | |
|   var url = document.URL.substring(0, i) + \'{0}\';
 | |
|   document.getElementById(\'{0}\').href = url;">
 | |
|     GET {0} HTTP/1.0
 | |
| </a>
 | |
| </div>
 | |
| </div>
 | |
| ++++
 | |
| 
 | |
| """
 | |
| 
 | |
| SEARCH_BOX = """
 | |
| 
 | |
| ++++
 | |
| <div style="position:absolute; right:20px; top:20px;">
 | |
| <input type="text" id="docSearch" size="70" />
 | |
| <button type="button" id="searchBox">Search</button>
 | |
| <script type="text/javascript">
 | |
| var f = function() {
 | |
|   window.location = '../#/Documentation/' +
 | |
|     encodeURIComponent(document.getElementById("docSearch").value);
 | |
| }
 | |
| document.getElementById("searchBox").onclick = f;
 | |
| document.getElementById("docSearch").onkeypress = function(e) {
 | |
|   if (13 == (e.keyCode ? e.keyCode : e.which)) {
 | |
|     f();
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| </div>
 | |
| ++++
 | |
| 
 | |
| """
 | |
| 
 | |
| LINK_SCRIPT = """
 | |
| 
 | |
| ++++
 | |
| <script type="text/javascript">
 | |
|     decorate(document.getElementsByTagName('h1'));
 | |
|     decorate(document.getElementsByTagName('h2'));
 | |
|     decorate(document.getElementsByTagName('h3'));
 | |
|     decorate(document.getElementsByTagName('h4'));
 | |
| 
 | |
|     var divs = document.getElementsByTagName('div');
 | |
|     var arr = new Array();
 | |
|     var excluded = getExcludedIds();
 | |
|     for(var i = 0; i < divs.length; i++) {
 | |
|       var d = divs[i];
 | |
|       var id = d.getAttribute('id');
 | |
|       if (id != null && !(id in excluded)) {
 | |
|         arr[arr.length] = d;
 | |
|       }
 | |
|     }
 | |
|     decorate(arr);
 | |
| 
 | |
|     var anchors = document.getElementsByTagName('a');
 | |
|     arr = new Array();
 | |
|     for(var i = 0; i < anchors.length; i++) {
 | |
|       var a = anchors[i];
 | |
|       // if the anchor has no id there is no target to
 | |
|       // which we can link
 | |
|       if (a.getAttribute('id') != null) {
 | |
|         // if the anchor is empty there is no content which
 | |
|         // can receive the mouseover event, an empty anchor
 | |
|         // applies to the element that follows, move the
 | |
|         // element that follows into the anchor so that there
 | |
|         // is content which can receive the mouseover event
 | |
|         if (a.firstChild == null) {
 | |
|           var next = a.nextSibling;
 | |
|           if (next != null) {
 | |
|             next.parentNode.removeChild(next);
 | |
|             a.appendChild(next);
 | |
|           }
 | |
|         }
 | |
|         arr[arr.length] = a;
 | |
|       }
 | |
|     }
 | |
|     decorate(arr);
 | |
| 
 | |
|     function decorate(e) {
 | |
|       for(var i = 0; i < e.length; i++) {
 | |
|         e[i].onmouseover = function (evt) {
 | |
|           var element = this;
 | |
|           // do nothing if the link icon is currently showing
 | |
|           var a = element.firstChild;
 | |
|           if (a != null && a instanceof Element
 | |
|               && a.getAttribute('id') == 'LINK') {
 | |
|             return;
 | |
|           }
 | |
| 
 | |
|           // if there is no id there is no target to link to
 | |
|           var id = element.getAttribute('id');
 | |
|           if (id == null) {
 | |
|             return;
 | |
|           }
 | |
| 
 | |
|           // create and show a link icon that links to this element
 | |
|           a = document.createElement('a');
 | |
|           a.setAttribute('id', 'LINK');
 | |
|           a.setAttribute('href', '#' + id);
 | |
|           a.setAttribute('style', 'position: absolute;'
 | |
|               + ' left: ' + (element.offsetLeft - 16 - 2 * 4) + 'px;'
 | |
|               + ' padding-left: 4px; padding-right: 4px; padding-top:4px;');
 | |
|           var img = document.createElement('img');
 | |
|           img.setAttribute('src', 'images/link.png');
 | |
|           img.setAttribute('style', 'background-color: #FFFFFF;');
 | |
|           a.appendChild(img);
 | |
|           element.insertBefore(a, element.firstChild);
 | |
| 
 | |
|           // remove the link icon when the mouse is moved away,
 | |
|           // but keep it shown if the mouse is over the element, the link or the icon
 | |
|           hide = function(evt) {
 | |
|             if (document.elementFromPoint(evt.clientX, evt.clientY) != element
 | |
|                 && document.elementFromPoint(evt.clientX, evt.clientY) != a
 | |
|                 && document.elementFromPoint(evt.clientX, evt.clientY) != img
 | |
|                 && element.contains(a)) {
 | |
|               element.removeChild(a);
 | |
|             }
 | |
|           }
 | |
|           element.onmouseout = hide;
 | |
|           a.onmouseout = hide;
 | |
|           img.onmouseout = hide;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     function getExcludedIds() {
 | |
|       var excluded = {};
 | |
|       excluded['header'] = true;
 | |
|       excluded['toc'] = true;
 | |
|       excluded['toctitle'] = true;
 | |
|       excluded['content'] = true;
 | |
|       excluded['preamble'] = true;
 | |
|       excluded['footer'] = true;
 | |
|       excluded['footer-text'] = true;
 | |
|       return excluded;
 | |
|     }
 | |
| </script>
 | |
| 
 | |
| ++++
 | |
| 
 | |
| """
 | |
| 
 | |
| opts = OptionParser()
 | |
| opts.add_option('-o', '--out', help='output file')
 | |
| opts.add_option('-s', '--src', help='source file')
 | |
| opts.add_option('-x', '--suffix', help='suffix for included filenames')
 | |
| opts.add_option('-b', '--searchbox', action="store_true", default=True,
 | |
|                 help="generate the search boxes")
 | |
| opts.add_option('--no-searchbox', action="store_false", dest='searchbox',
 | |
|                 help="don't generate the search boxes")
 | |
| options, _ = opts.parse_args()
 | |
| 
 | |
| try:
 | |
|   out_file = open(options.out, 'w')
 | |
|   src_file = open(options.src, 'r')
 | |
|   last_line = ''
 | |
|   ignore_next_line = False
 | |
|   last_title = ''
 | |
|   for line in src_file.xreadlines():
 | |
|     if PAT_GERRIT.match(last_line):
 | |
|       # Case of "GERRIT\n------" at the footer
 | |
|       out_file.write(GERRIT_UPLINK)
 | |
|       last_line = ''
 | |
|     elif PAT_SEARCHBOX.match(last_line):
 | |
|       # Case of 'SEARCHBOX\n---------'
 | |
|       if options.searchbox:
 | |
|         out_file.write(SEARCH_BOX)
 | |
|       last_line = ''
 | |
|     elif PAT_INCLUDE.match(line):
 | |
|       # Case of 'include::<filename>'
 | |
|       match = PAT_INCLUDE.match(line)
 | |
|       out_file.write(last_line)
 | |
|       last_line = match.group(1) + options.suffix + match.group(2) + '\n'
 | |
|     elif PAT_STARS.match(line):
 | |
|       if PAT_TITLE.match(last_line):
 | |
|         # Case of the title in '.<title>\n****\nget::<url>\n****'
 | |
|         match = PAT_TITLE.match(last_line)
 | |
|         last_title = GET_TITLE % match.group(1)
 | |
|       else:
 | |
|         out_file.write(last_line)
 | |
|         last_title = ''
 | |
|     elif PAT_GET.match(line):
 | |
|       # Case of '****\nget::<url>\n****' in rest api
 | |
|       url = PAT_GET.match(line).group(1)
 | |
|       out_file.write(GET_MACRO.format(url) % last_title)
 | |
|       ignore_next_line = True
 | |
|     elif ignore_next_line:
 | |
|       # Handle the trailing '****' of the 'get::' case
 | |
|       last_line = ''
 | |
|       ignore_next_line = False
 | |
|     else:
 | |
|       out_file.write(last_line)
 | |
|       last_line = line
 | |
|   out_file.write(last_line)
 | |
|   out_file.write(LINK_SCRIPT)
 | |
|   out_file.close()
 | |
| except IOError as err:
 | |
|   sys.stderr.write(
 | |
|       "error while expanding %s to %s: %s" % (options.src, options.out, err))
 | |
|   exit(1)
 |