3737import java .nio .file .Files ;
3838import java .nio .file .Path ;
3939import java .util .ArrayList ;
40+ import java .util .Arrays ;
4041import java .util .LinkedHashMap ;
4142import java .util .LinkedHashSet ;
4243import java .util .List ;
4647import java .util .Set ;
4748import java .util .regex .Matcher ;
4849import java .util .regex .Pattern ;
50+ import java .util .stream .Collectors ;
51+
4952import static java .nio .charset .StandardCharsets .UTF_8 ;
5053
5154/**
@@ -120,21 +123,31 @@ public static void main(String... args) {
120123 private void run (String ... args ) throws IOException {
121124 Path inFile = null ;
122125 Path outFile = null ;
126+ NavBar navbar = null ;
123127
124128 for (int i = 0 ; i < args .length ; i ++) {
125129 String arg = args [i ];
126130 if (arg .equals ("-o" ) && i + 1 < args .length ) {
127131 outFile = Path .of (args [++i ]);
132+ } else if (arg .equals ("--insert-nav" )) {
133+ navbar = new NavBar ();
134+ } else if (arg .equals ("--nav-right-info" ) && i + 1 < args .length ) {
135+ navbar .rightSideInfo (args [++i ]);
136+ } else if (arg .equals ("--nav-subdirs" ) && i + 1 < args .length ) {
137+ navbar .subdirs (Integer .parseInt (args [++i ]));
138+ } else if (arg .equals ("--nav-link-guides" )) {
139+ navbar .linkGuides (true );
128140 } else if (arg .startsWith ("-" )) {
129141 throw new IllegalArgumentException (arg );
130142 } else if (inFile == null ) {
131143 inFile = Path .of (arg );
132144 } else {
145+ System .err .println ("ARGV: " + Arrays .toString (args ));
133146 throw new IllegalArgumentException (arg );
134147 }
135148 }
136149
137- new Fixup ().run (inFile , outFile );
150+ new Fixup (navbar ).run (inFile , outFile );
138151 }
139152
140153 /**
@@ -148,6 +161,9 @@ class Fixup extends HtmlParser {
148161 /** A stream for reporting errors. */
149162 PrintStream err = System .err ;
150163
164+ /** A manager for the navigation bar, null if not required. */
165+ NavBar navbar ;
166+
151167 /**
152168 * Flag to indicate when {@code <main>} is permitted around palpable content.
153169 * Set within {@code <body>}; disabled within elements in which {@code <main>}
@@ -174,6 +190,10 @@ class Fixup extends HtmlParser {
174190 */
175191 Table table ;
176192
193+ Fixup (NavBar navbar ) {
194+ this .navbar = navbar ;
195+ }
196+
177197 /**
178198 * Run the program, copying an input file to an output file.
179199 * If the input file is {@code null}, input is read from the standard input.
@@ -282,7 +302,10 @@ protected void startElement(String name, Map<String,String> attrs, boolean selfC
282302 }
283303 // <main> is not permitted within these elements
284304 allowMain = false ;
285- if (name .equals ("nav" ) && Objects .equals (attrs .get ("id" ), "TOC" )) {
305+ if (navbar != null && name .equals ("header" ) && Objects .equals (attrs .get ("id" ), "title-block-header" )) {
306+ flushBuffer ();
307+ navbar .write (out );
308+ } else if (name .equals ("nav" ) && Objects .equals (attrs .get ("id" ), "TOC" )) {
286309 out .write (buffer .toString ()
287310 .replaceAll (">$" , " title=\" Table Of Contents\" >" ));
288311 buffer .setLength (0 );
@@ -436,6 +459,65 @@ private void flushBuffer() {
436459 }
437460 }
438461
462+ class NavBar {
463+ private int subdirs = 0 ;
464+ private boolean linkGuides = false ;
465+ private String rightSideInfo = "" ;
466+
467+ void subdirs (int subdirs ) {
468+ this .subdirs = subdirs ;
469+ }
470+
471+ void linkGuides (boolean linkGuides ) {
472+ this .linkGuides = linkGuides ;
473+ }
474+
475+ void rightSideInfo (String rightSideInfo ) {
476+ this .rightSideInfo = rightSideInfo ;
477+ }
478+
479+ void write (PrintWriter out ) {
480+ get ().lines ().forEach (out ::println );
481+ }
482+
483+ String get () {
484+ String pathToSpecs = "../" .repeat (subdirs );
485+ String api = pathToSpecs + "../api/index.html" ;
486+ String specs = pathToSpecs + "index.html" ;
487+ String guides = pathToSpecs + "man/index.html" ;
488+
489+ StringBuilder sb = new StringBuilder ();
490+ sb .append ("\n " );
491+ sb .append ("<div class=\" navbar\" >" ); // full enclosing banner
492+ if (rightSideInfo != null ) {
493+ sb .append ("<div>" ).append (rightSideInfo ).append ("</div>" );
494+ }
495+ sb .append ("<nav>" ); // nav links
496+ var links = new ArrayList <>(List .of (
497+ link (api , "API" ),
498+ link (specs , "OTHER SPECIFICATIONS" )
499+ ));
500+ if (linkGuides ) {
501+ links .add (link (guides , "TOOL GUIDES" ));
502+ }
503+ sb .append (list (links ));
504+ sb .append ("</nav>" );
505+ sb .append ("</div>" );
506+ sb .append ("\n " );
507+ return sb .toString ();
508+ }
509+
510+ String list (List <String > items ) {
511+ return items .stream ()
512+ .map (i -> "<li>" + i )
513+ .collect (Collectors .joining ("\n " , "<ul>" , "</ul>" ));
514+ }
515+
516+ private String link (String href , String label ) {
517+ return "<a href=\" " + href + "\" >" + label + "</a>" ;
518+ }
519+ }
520+
439521 /**
440522 * Storage for the content of a {@code <table>} element} until we can determine
441523 * whether we should add {@code scope="row"} to the cells in a given column,
0 commit comments