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