1#!/usr/bin/env python3 2# Copyright 2022 The Bazel Authors. All rights reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15"""merge stardoc output into a single page. 16 17- concatenates files 18- corrects things that stardoc botches 19""" 20 21import re 22import sys 23import typing 24 25 26# I think stardoc changed the format of the id strings. Sigh. 27ID_RE = re.compile(r'<a id="(.*)">') 28ID_OLD_RE = re.compile(r'<a id="#(.*)">') 29WRAPS_RE = re.compile(r'@wraps\((.*)\)') 30SINCE_RE = re.compile(r'@since\(([^)]*)\)') 31CENTER_RE = re.compile(r'<p align="center">([^<]*)</p>') 32 33 34def merge_file(file: str, out, wrapper_map:typing.Dict[str, str]) -> None: 35 with open(file, 'r') as inp: 36 content = inp.read() 37 m = ID_RE.search(content) 38 if not m: 39 m = ID_OLD_RE.search(content) 40 this_rule = m.group(1) if m else None 41 m = WRAPS_RE.search(content) 42 if m: 43 # I wrap something, so don't emit me. 44 wrapper_map[m.group(1)] = this_rule 45 return 46 # If something wraps me, rewrite myself with the wrapper name. 47 if this_rule in wrapper_map: 48 content = content.replace(this_rule, wrapper_map[this_rule]) 49 merge_text(content, out) 50 51 52def merge_text(text: str, out) -> None: 53 """Merge a block of text into an output stream. 54 55 Args: 56 text: block of text produced by Starroc. 57 out: an output file stream. 58 """ 59 for line in text.split('\n'): 60 line = SINCE_RE.sub(r'<div class="since"><i>Since \1</i></div>', line) 61 62 if line.startswith('| :'): 63 line = fix_stardoc_table_align(line) 64 # Compensate for https://github.com/bazelbuild/stardoc/issues/118. 65 # Convert escaped HTML <li> back to raw text 66 line = line.replace('<li>', '<li>') 67 line = CENTER_RE.sub(r'\1', line) 68 _ = out.write(line) 69 _ = out.write('\n') 70 71 72def fix_stardoc_table_align(line: str) -> str: 73 """Change centered descriptions to left justified.""" 74 if line.startswith('| :-------------: | :-------------: '): 75 return '| :------------ | :--------------- | :---------: | :---------: | :----------- |' 76 return line 77 78 79def main(argv: typing.Sequence[str]) -> None: 80 wrapper_map = {} 81 for file in argv[1:]: 82 merge_file(file, sys.stdout, wrapper_map) 83 84 85if __name__ == '__main__': 86 main(sys.argv) 87