code:
@namespace "http://www.w3.org/1999/xhtml";

span.ignore { display: none }

code[class="literal"] strong { color: purple }
p[class="synopsis"] code strong { color: purple }
p[class="synopsis"] code[class="function"] { color: purple }
p[class="synopsis"] code[class="varname"] { color: purple }

p[class="synopsis"][kind="Procedure"] code[class="function"]:before,
  p[class="synopsis"][kind="Predicate"] code[class="function"]:before,
  p[class="synopsis"][kind="Constructor"] code[class="function"]:before,
  p[class="synopsis"][kind="Syntax"] code[class="function"]:before
{ content: "("; font-weight: bold; font-family: monospace; color: purple; }
p[class="synopsis"][kind="Procedure"]:after,
  p[class="synopsis"][kind="Predicate"]:after,
  p[class="synopsis"][kind="Constructor"]:after,
  p[class="synopsis"][kind="Syntax"]:after
{ content: ")"; font-weight: bold; font-family: monospace; color: purple }

p.synopsis span.kind { float: right; padding-left: 2em }
p.synopsis span.kind:before { content: "[" }
p.synopsis span.kind:after { content: "]" }
p.synopsis > code { font-weight: bold; }
blockquote { margin-left: 40px; margin-right: 40px }

strong.userinput { background-color: #FFFFD0 } /* a pale yellow */
span.userinput { background-color: #FFFFD0 } /* a pale yellow */
span.prompt { background-color: #E0FFE0 } /* a pale green */

body.mainbar {
    background: #fffff5;
    padding-left: 25%;
}
div[node][hidden] {
    top: 0pt; bottom: 0pt;
    position: absolute;
    display: none
}

div[node] {
    left: 25%;
    width: 75%; height: auto;
    top: 0pt; bottom: 0pt;
    position: absolute;
    overflow: hidden;
}
/* The initial contents are put into a separate node.  Unlike the other
 *  nodes, it is *not* in an <iframe>, so needs different handling. */
div[node]#index {
    overflow: auto
}
div[node]#index header {
    margin: 8px;
}
iframe.node {
   width: 100%; height: 100%; border: none; margin: 0px;padding: 0px;
}

iframe[name="slider"] {
    position: fixed;
    top: 0em; right: 25%; bottom: 0em; left: 0em;
    height: 100%;
    width: 25%;
    overflow: scroll;
    border: none;
}

body.toc-sidebar div img {
    border: none;
    padding: 4px;
    float: right;
    width: 40%;
    height: auto
}
body.toc-sidebar header {
    font-size: xx-large;
}
div.toc ul[toc-detail] {
    display: none
}
div.toc a[toc-current] {
  font-weight: bold
}
div.toc li {
  display: block;
  text-indent: 0;
  text-align: left;
  border: solid;
  border-width: 1px 0px 0px 1px;
  border-color: #AAA #666 #666 #AAA;
  list-style: none }     /* Remove triangle from H2 */
div.toc ul
{
    margin: 0px;
    padding: 0px;
    list-style-type: none;
}
body.toc-sidebar div { padding: 0.4ex; overflow: auto }
body.toc-sidebar { background-color: #F4FCFF; margin: 0pt }
body.toc-sidebar a { text-decoration: none }
div.toc { background-color: #F4FCFF }
div.toc li { padding: 0px 4px;}
div.toc li { margin: 0 ; }

div.toc nav {padding: 0; margin: 0 }
div.toc ul {padding: 0; margin: 0 }

div.toc ul ul, div.toc ul ul { margin-left: 1em; }
body.toc-sidebar a:hover, body.toc-sidebar a:hover div {
    color: #fff;
    background-color: #69C;
}


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>News - Recent Changes</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>

repo_name: mthl/texinfo

license: mit


code:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<package xmlns="http://www.idpf.org/2007/opf" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" version="3.0" xml:lang="en" unique-identifier="pub-identifier">
  <metadata>
    <dc:identifier id="pub-identifier">_book</dc:identifier>
    <meta id="meta-identifier" property="dcterms:identifier">_book</meta>
    <dc:title id="pub-title">The Kawa Scheme language</dc:title>
    <meta property="dcterms:title" id="meta-title">The Kawa Scheme language</meta>
    <dc:language id="pub-language">en</dc:language>
    <meta property="dcterms:language" id="meta-language">en</meta>
    <meta property="dcterms:modified">2017-04-26T13:58:52Z</meta>
    <!--The preceding date value is actually local time (not UTC) in UTC format because there is no function in XSLT 1.0 to generate a correct UTC time-->
  </metadata>
  <manifest>
    <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
    <item id="htmltoc" properties="nav" media-type="application/xhtml+xml" href="ToC.xhtml"/>
    <item media-type="text/css" id="html-css" href="kawa.css"/>
    <item media-type="text/css" id="docbook-css" href="docbook-epub.css"/>
    <item id="id-idm139667896491920" href="top.html" media-type="application/xhtml+xml"/>
    <item id="id-idm139667882195376" href="index.html" media-type="application/xhtml+xml"/>
    <item id="id-idm139667882184160" href="news.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881218784" href="Features.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881183968" href="Implemented-SRFIs.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881116336" href="Compatibility.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881104032" href="Community.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881102848" href="Reporting-bugs.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881093584" href="Mailing-lists.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881085968" href="Acknowledgements.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881052112" href="Support.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881047056" href="Projects.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667881030336" href="Ideas-and-tasks.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880880656" href="Installation.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880879456" href="Getting-Kawa.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880863392" href="Running-Java.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880855632" href="Binary-distribution.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880824848" href="Source-distribution.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880660128" href="tutorial-index.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880654928" href="tutorial-Introduction.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880627248" href="tutorial-Booleans.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880612896" href="tutorial-Numbers.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880584032" href="tutorial-Functions.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880539312" href="tutorial-Variables.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880517648" href="tutorial-Pictures.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880468608" href="tutorial-Sequences.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880418624" href="tutorial-Objects.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880369088" href="tutorial-Types.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880352160" href="tutorial-Exceptions-and-errors.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880342240" href="tutorial-Classes.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880339552" href="tutorial-Other-Java-features.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880324112" href="pt01.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880323200" href="Running.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880312224" href="Options.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880076288" href="Scripts.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667880028336" href="REPL-Console.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879952624" href="Exiting.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879945712" href="Compiling.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879856768" href="Syntax.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879855584" href="Syntax-notation.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879842576" href="Lexical-and-datum-syntax.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879822352" href="Lexical-syntax.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879525952" href="Datum-syntax.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879391472" href="Hash-prefixed-forms.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879293984" href="Primitive-expression-syntax.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879239232" href="Colon-notation.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879139968" href="Bodies.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879085152" href="Syntax-and-conditional-compilation.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667879012736" href="Macros.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667878596320" href="Named-quasi-literals.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667878553840" href="Program-structure.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667878551488" href="Boolean-values.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667878509088" href="Conditionals.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667878336304" href="Variables-and-Patterns.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667878266064" href="Definitions.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667878170000" href="Local-binding-constructs.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667878113248" href="Lazy-evaluation.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877985488" href="Threads.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877961248" href="Exceptions.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877824912" href="Control-features.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877823728" href="Mapping-functions.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877772288" href="Multiple-values.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877709888" href="Symbols-and-namespaces.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877706304" href="Simple-symbols.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877687680" href="Namespaces.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877568432" href="Keywords.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877540992" href="Special-named-constants.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877519328" href="Procedures.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877518144" href="Application-and-Arguments-Lists.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877402992" href="Procedure-properties.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877364944" href="Generic-procedures.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877352960" href="Extended-formals.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877253120" href="Partial-application.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877221664" href="Numbers.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877219184" href="Numerical-types.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667877113120" href="Arithmetic-operations.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667876804768" href="Numerical-input-and-output.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667876780992" href="Quaternions.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667876260000" href="Quantities.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667876193488" href="Logical-Number-Operations.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667875952752" href="Performance-of-numeric-operations.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667875924464" href="Characters-and-text.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667875923280" href="Characters.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667875800336" href="Character-sets.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667875789344" href="Strings.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667874967680" href="String-literals.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667874768352" href="Unicode.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667874653888" href="Regular-expressions.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667874547280" href="Data-structures.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667874546048" href="Sequences.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667874517632" href="Lists.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667874479536" href="Vectors.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667874377952" href="Uniform-vectors.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667874050096" href="Bytevectors.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873937168" href="Ranges.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873877952" href="Streams.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873870304" href="Arrays.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873537984" href="Hash-tables.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873200112" href="Eval-and-Environments.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873138064" href="Locations.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873096496" href="Parameter-objects.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873061520" href="Debugging.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873043728" href="Input-Output.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873040928" href="Named-output-formats.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667873013504" href="Paths.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667872878080" href="Files.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667872831536" href="Reading-and-writing-whole-files.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667872786624" href="Ports.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667872336400" href="Format.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667872111408" href="Pretty-printing.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667872036672" href="Resources.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667872016144" href="Types.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667872001584" href="Standard-Types.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871921856" href="Parameterized-Types.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871918064" href="Type-tests-and-conversions.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871893104" href="Objects-Classes-and-Modules.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871886320" href="Defining-new-classes.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871705584" href="Anonymous-classes.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871669792" href="Enumerations.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871648224" href="Annotations.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871611024" href="Module-classes.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871387408" href="Importing.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871199056" href="Record-types.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871161472" href="Dynamic-records.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667871100112" href="Method-operations.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870965248" href="Allocating-objects.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870909024" href="Field-operations.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870838160" href="Mangling.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870810512" href="Scheme-types-in-Java.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870792544" href="Array-operations.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870774080" href="Loading-Java-functions-into-Scheme.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870744336" href="Evaluating-Scheme-expressions-from-Java.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870708608" href="XML-tools.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870701104" href="Formatting-XML.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870675104" href="Creating-HTML-nodes.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870660544" href="Creating-XML-nodes.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870618480" href="XML-literals.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870452512" href="Server-side-scripts.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870427568" href="Self-configuring-page-scripts.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870371776" href="Servlets.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870288640" href="CGI-scripts.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870276512" href="HTTP-requests.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870154672" href="HTTP-response.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870129424" href="XML-beyond-Scheme.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870102864" href="Miscellaneous.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667870093312" href="Composable-pictures.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869695600" href="Building-JavaFX-applications.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869678528" href="Building-for-Android.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869622208" href="Android-view-construction.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869587040" href="System-inquiry.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869549040" href="Processes.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869327808" href="Time-related-functions.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869307056" href="Low-level-functions.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869231888" href="FAQs.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869201472" href="Framework.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667882080320" href="License.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667882079136" href="Software-License.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869193744" href="Manual-License.xhtml" media-type="application/xhtml+xml"/>
    <item id="id-idm139667869169584" href="Overall-Index.xhtml" media-type="application/xhtml+xml"/>
    <item id="idm139667857605312" href="images/domterm-pictures-1.png" media-type="image/png"/>
    <item id="idm139667857605184" href="images/fill-circ-1.png" media-type="image/png"/>
    <item id="idm139667857611520" href="images/polyline-1.png" media-type="image/png"/>
    <item id="idm139667867278480" href="images/polygon-1.png" media-type="image/png"/>
    <item id="idm139667857610784" href="images/image-cat-1a.png" media-type="image/png"/>
    <item id="idm139667857611360" href="images/image-cat-1b.png" media-type="image/png"/>
    <item id="idm139667857609440" href="images/paint-circ-1.png" media-type="image/png"/>
    <item id="idm139667857503312" href="images/paint-circ-2.png" media-type="image/png"/>
    <item id="idm139667857507008" href="images/paint-circ-3.png" media-type="image/png"/>
    <item id="idm139667857506880" href="images/paint-circ-4.png" media-type="image/png"/>
    <item id="idm139667857605632" href="images/show-draw-1.png" media-type="image/png"/>
    <item id="idm139667857504752" href="images/show-draw-2.png" media-type="image/png"/>
    <item id="idm139667857504592" href="images/show-draw-3.png" media-type="image/png"/>
    <item id="idm139667857503920" href="images/border-1.png" media-type="image/png"/>
    <item id="idm139667857505328" href="images/padding-1.png" media-type="image/png"/>
    <item id="idm139667857502480" href="images/re-center-1.png" media-type="image/png"/>
    <item id="idm139667857502320" href="images/re-center-2.png" media-type="image/png"/>
    <item id="idm139667857499568" href="images/image-scaled-1.png" media-type="image/png"/>
  </manifest>
  <spine toc="ncx">
    <itemref idref="htmltoc" linear="yes"/>
    <itemref idref="id-idm139667882195376"/>
    <itemref idref="id-idm139667882184160"/>
    <itemref idref="id-idm139667881218784"/>
    <itemref idref="id-idm139667881183968"/>
    <itemref idref="id-idm139667881116336"/>
    <itemref idref="id-idm139667881104032"/>
    <itemref idref="id-idm139667881102848"/>
    <itemref idref="id-idm139667881093584"/>
    <itemref idref="id-idm139667881085968"/>
    <itemref idref="id-idm139667881052112"/>
    <itemref idref="id-idm139667881047056"/>
    <itemref idref="id-idm139667881030336"/>
    <itemref idref="id-idm139667880880656"/>
    <itemref idref="id-idm139667880879456"/>
    <itemref idref="id-idm139667880863392"/>
    <itemref idref="id-idm139667880855632"/>
    <itemref idref="id-idm139667880824848"/>
    <itemref idref="id-idm139667880660128"/>
    <itemref idref="id-idm139667880654928"/>
    <itemref idref="id-idm139667880627248"/>
    <itemref idref="id-idm139667880612896"/>
    <itemref idref="id-idm139667880584032"/>
    <itemref idref="id-idm139667880539312"/>
    <itemref idref="id-idm139667880517648"/>
    <itemref idref="id-idm139667880468608"/>
    <itemref idref="id-idm139667880418624"/>
    <itemref idref="id-idm139667880369088"/>
    <itemref idref="id-idm139667880352160"/>
    <itemref idref="id-idm139667880342240"/>
    <itemref idref="id-idm139667880339552"/>
    <itemref idref="id-idm139667880324112"/>
    <itemref idref="id-idm139667880323200"/>
    <itemref idref="id-idm139667880312224"/>
    <itemref idref="id-idm139667880076288"/>
    <itemref idref="id-idm139667880028336"/>
    <itemref idref="id-idm139667879952624"/>
    <itemref idref="id-idm139667879945712"/>
    <itemref idref="id-idm139667879856768"/>
    <itemref idref="id-idm139667879855584"/>
    <itemref idref="id-idm139667879842576"/>
    <itemref idref="id-idm139667879822352"/>
    <itemref idref="id-idm139667879525952"/>
    <itemref idref="id-idm139667879391472"/>
    <itemref idref="id-idm139667879293984"/>
    <itemref idref="id-idm139667879239232"/>
    <itemref idref="id-idm139667879139968"/>
    <itemref idref="id-idm139667879085152"/>
    <itemref idref="id-idm139667879012736"/>
    <itemref idref="id-idm139667878596320"/>
    <itemref idref="id-idm139667878553840"/>
    <itemref idref="id-idm139667878551488"/>
    <itemref idref="id-idm139667878509088"/>
    <itemref idref="id-idm139667878336304"/>
    <itemref idref="id-idm139667878266064"/>
    <itemref idref="id-idm139667878170000"/>
    <itemref idref="id-idm139667878113248"/>
    <itemref idref="id-idm139667877985488"/>
    <itemref idref="id-idm139667877961248"/>
    <itemref idref="id-idm139667877824912"/>
    <itemref idref="id-idm139667877823728"/>
    <itemref idref="id-idm139667877772288"/>
    <itemref idref="id-idm139667877709888"/>
    <itemref idref="id-idm139667877706304"/>
    <itemref idref="id-idm139667877687680"/>
    <itemref idref="id-idm139667877568432"/>
    <itemref idref="id-idm139667877540992"/>
    <itemref idref="id-idm139667877519328"/>
    <itemref idref="id-idm139667877518144"/>
    <itemref idref="id-idm139667877402992"/>
    <itemref idref="id-idm139667877364944"/>
    <itemref idref="id-idm139667877352960"/>
    <itemref idref="id-idm139667877253120"/>
    <itemref idref="id-idm139667877221664"/>
    <itemref idref="id-idm139667877219184"/>
    <itemref idref="id-idm139667877113120"/>
    <itemref idref="id-idm139667876804768"/>
    <itemref idref="id-idm139667876780992"/>
    <itemref idref="id-idm139667876260000"/>
    <itemref idref="id-idm139667876193488"/>
    <itemref idref="id-idm139667875952752"/>
    <itemref idref="id-idm139667875924464"/>
    <itemref idref="id-idm139667875923280"/>
    <itemref idref="id-idm139667875800336"/>
    <itemref idref="id-idm139667875789344"/>
    <itemref idref="id-idm139667874967680"/>
    <itemref idref="id-idm139667874768352"/>
    <itemref idref="id-idm139667874653888"/>
    <itemref idref="id-idm139667874547280"/>
    <itemref idref="id-idm139667874546048"/>
    <itemref idref="id-idm139667874517632"/>
    <itemref idref="id-idm139667874479536"/>
    <itemref idref="id-idm139667874377952"/>
    <itemref idref="id-idm139667874050096"/>
    <itemref idref="id-idm139667873937168"/>
    <itemref idref="id-idm139667873877952"/>
    <itemref idref="id-idm139667873870304"/>
    <itemref idref="id-idm139667873537984"/>
    <itemref idref="id-idm139667873200112"/>
    <itemref idref="id-idm139667873138064"/>
    <itemref idref="id-idm139667873096496"/>
    <itemref idref="id-idm139667873061520"/>
    <itemref idref="id-idm139667873043728"/>
    <itemref idref="id-idm139667873040928"/>
    <itemref idref="id-idm139667873013504"/>
    <itemref idref="id-idm139667872878080"/>
    <itemref idref="id-idm139667872831536"/>
    <itemref idref="id-idm139667872786624"/>
    <itemref idref="id-idm139667872336400"/>
    <itemref idref="id-idm139667872111408"/>
    <itemref idref="id-idm139667872036672"/>
    <itemref idref="id-idm139667872016144"/>
    <itemref idref="id-idm139667872001584"/>
    <itemref idref="id-idm139667871921856"/>
    <itemref idref="id-idm139667871918064"/>
    <itemref idref="id-idm139667871893104"/>
    <itemref idref="id-idm139667871886320"/>
    <itemref idref="id-idm139667871705584"/>
    <itemref idref="id-idm139667871669792"/>
    <itemref idref="id-idm139667871648224"/>
    <itemref idref="id-idm139667871611024"/>
    <itemref idref="id-idm139667871387408"/>
    <itemref idref="id-idm139667871199056"/>
    <itemref idref="id-idm139667871161472"/>
    <itemref idref="id-idm139667871100112"/>
    <itemref idref="id-idm139667870965248"/>
    <itemref idref="id-idm139667870909024"/>
    <itemref idref="id-idm139667870838160"/>
    <itemref idref="id-idm139667870810512"/>
    <itemref idref="id-idm139667870792544"/>
    <itemref idref="id-idm139667870774080"/>
    <itemref idref="id-idm139667870744336"/>
    <itemref idref="id-idm139667870708608"/>
    <itemref idref="id-idm139667870701104"/>
    <itemref idref="id-idm139667870675104"/>
    <itemref idref="id-idm139667870660544"/>
    <itemref idref="id-idm139667870618480"/>
    <itemref idref="id-idm139667870452512"/>
    <itemref idref="id-idm139667870427568"/>
    <itemref idref="id-idm139667870371776"/>
    <itemref idref="id-idm139667870288640"/>
    <itemref idref="id-idm139667870276512"/>
    <itemref idref="id-idm139667870154672"/>
    <itemref idref="id-idm139667870129424"/>
    <itemref idref="id-idm139667870102864"/>
    <itemref idref="id-idm139667870093312"/>
    <itemref idref="id-idm139667869695600"/>
    <itemref idref="id-idm139667869678528"/>
    <itemref idref="id-idm139667869622208"/>
    <itemref idref="id-idm139667869587040"/>
    <itemref idref="id-idm139667869549040"/>
    <itemref idref="id-idm139667869327808"/>
    <itemref idref="id-idm139667869307056"/>
    <itemref idref="id-idm139667869231888"/>
    <itemref idref="id-idm139667869201472"/>
    <itemref idref="id-idm139667882080320"/>
    <itemref idref="id-idm139667882079136"/>
    <itemref idref="id-idm139667869193744"/>
    <itemref idref="id-idm139667869169584"/>
  </spine>
  <guide>
    <reference href="ToC.xhtml" type="toc" title="Table of Contents"/>
  </guide>
</package>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Part . Reference Documentation</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<!DOCTYPE html>

    <title>The Kawa Scheme language</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>

    <meta name="generator" content="DocBook XSL-NS Stylesheets V1.79.1"/>
    <link rel="prev" href="Overall-Index.xhtml" title="Index"/>
    <link rel="next" href="index.html" title="The Kawa Scheme language"/>

The Kawa Scheme language

              The Kawa Scheme language

              News - Recent Changes

              Features

              The Kawa Community

              Getting and installing Kawa

              Kawa Scheme Tutorial

              Reference Documentation

              Index


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Booleans</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Classes</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Exceptions and errors</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Functions</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Introduction</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Numbers</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Creating and using objects</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Other Java features</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Composable pictures</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Lists and sequences</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Types and declarations</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Variables</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html>

    <title>Kawa Scheme Tutorial</title>
    <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
    <link rel="stylesheet" type="text/css" href="kawa.css"/>


code:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
  <head>
    <title>Kawa manual</title>
    <link rel="up" href="../index.html">
    <link rel="top" href="../../index.html">
<script type="text/javascript">
var sliderBgcolor = "#60ECEC";
function setHash(pathname) {
    var contextLength = location.pathname.indexOf("with-frames");
    if (contextLength <= pathname.length)
        pathname = pathname.substring(contextLength);
    history.replaceState(null, null, "#"+pathname);
};
function framesetLoaded() {
    var hash=top.location.hash;
    var main=top.main;
    if (hash && main) {
        // FUTURE: load specified file into main frame
    }
}
function framesetUnloaded() {
    var request = new XMLHttpRequest();
    request.open("GET","(WINDOW-CLOSED)");
    request.send(null);
}
</script>
  </head>
  <frameset cols="280,*" onload="top.framesetLoaded()" onunload="framesetUnloaded()">
    <frame name="slider" src="ToC.xhtml">
    <frame name="main" src="index.html">
  </frameset>
</html>


texinfo

type: git

contributors:
Per Bothner <per@gnu.org>
Mathieu Lirzin <mthl@gnu.org>

build: rollup --config build-aux/rollup.js


code:
/* actions.js - Actions to dispatch
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

import config from "./config";

export const SIDEBAR_LOADED = "sidebar-ready";

export const CURRENT_URL = "current-url";

export function
set_current_url (url, history = config.HISTORY_PUSH)
{
  return { type: CURRENT_URL, url, history };
}

/** Set current URL to the node corresponding to POINTER which is an
    id refering to a linkid (such as "*TOP*" or "*END*"). */
export function
set_current_url_pointer (pointer)
{
  return { type: CURRENT_URL, pointer, history: config.HISTORY_PUSH };
}

export const NAVIGATE = "navigate";

export function
navigate (direction)
{
  return { type: NAVIGATE, direction, history: config.HISTORY_PUSH };
}

export const CACHE_LINKS = "cache-links";

export function
cache_links (links)
{
  return { type: CACHE_LINKS, links };
}

export const SHOW_COMPONENT = "show-component";

/** Toggle the visibility of COMPONENT.  */
export function
show_component (component)
{
  return { type: SHOW_COMPONENT, component };
}

export const HIDE_COMPONENT = "hide-component";

/** Toggle the visibility of COMPONENT.  */
export function
hide_component (component)
{
  return { type: HIDE_COMPONENT, component };
}


code:
/* config.js - Define constants
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

export default {
  TOC_FILENAME: "ToC.xhtml",

  XHTML_NAMESPACE: "http://www.w3.org/1999/xhtml",

  INDEX_NAME: "index.html",

  OVERALL_INDEX_NAME: "Overall-Index.xhtml",

  INDEX_ID: "index",

  PACKAGE_LOGO: "kawa-logo.png",

  WARNING_TIMEOUT: 3000,

  /* History modes. */
  HISTORY_REPLACE: "replace",
  HISTORY_PUSH: "push",
  HISTORY_POP: "pop"
};


code:
/* iframe.js - Handle iframed pages
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

import * as actions from "./actions";
import { basename, navigation_links } from "./utils";
import config from "./config";
import { fix_links } from "./toc";
import { iframe_dispatch } from "./store";

/* Return an array composed of the filename and the anchor of LINKID.
   LINKID can have the form "foobar.anchor" or just "foobar".  */
function
linkid_split (linkid)
{
  if (!linkid.includes ("."))
    return [linkid, ""];
  else
    {
      let [id, anchor] = linkid.match (/^(.+)\.(.*)$/).slice (1);
      return [id, "#" + anchor];
    }
}

export class
Pages
{
  constructor (index_div)
  {
    index_div.setAttribute ("id", config.INDEX_ID);
    index_div.setAttribute ("node", config.INDEX_ID);
    index_div.setAttribute ("hidden", "true");
    this.element = document.createElement ("div");
    this.element.setAttribute ("id", "sub-pages");
    this.element.appendChild (index_div);
    /* Currently created divs.  */
    this.ids = [];
  }

  add_divs (linkids)
  {
    for (let i = 0; i < linkids.length; i += 1)
      {
        let linkid = linkids[i];
        this.ids.push (linkid);
        /* Don't create a div if there is an anchor part in LINKID.  */
        if (!linkid.includes ("."))
          {
            let div = document.createElement ("div");
            div.setAttribute ("id", linkid);
            div.setAttribute ("node", linkid);
            div.setAttribute ("hidden", "true");
            this.element.appendChild (div);
          }
      }
  }

  render (state)
  {
    let new_linkids = Object.keys (state.loaded_nodes)
                            .filter (id => !this.ids.includes (id));
    this.add_divs (new_linkids);

    if (state.current !== this.prev_id)
      {
        if (this.prev_id)
          this.prev_div.setAttribute ("hidden", "true");

        let [pageid] = linkid_split (state.current);
        let div = document.getElementById (pageid);
        if (!div)
          throw new Error ("no div with id: " + pageid);
        load_page (state.current);
        update_history (state.current, state.history);
        div.removeAttribute ("hidden");
        this.prev_id = state.current;
        this.prev_div = div;
      }
  }
}

function
load_page (linkid)
{
  let path = window.location.pathname + window.location.search;

  if (linkid === config.INDEX_ID)
    return;

  let [pageid, hash] = linkid_split (linkid);
  let div = document.getElementById (pageid);
  if (!div)
    {
      let msg = "no iframe container correspond to identifier: " + pageid;
      throw new ReferenceError (msg);
    }

  path = path.replace (/#.*/, "") + "#" + linkid;
  let url = pageid + ".xhtml" + hash;

  /* Select contained iframe or create it if necessary.  */
  let iframe = div.querySelector ("iframe");
  if (iframe)
    {
      let msg = { message_kind: "scroll-to", hash };
      iframe.contentWindow.postMessage (msg, "*");
    }
  else
    {
      iframe = document.createElement ("iframe");
      iframe.setAttribute ("class", "node");
      iframe.setAttribute ("name", path);
      iframe.setAttribute ("src", url);
      div.appendChild (iframe);
    }
}

/* Mutate the history of page navigation.  Store LINKID in history
   state, The actual way to store LINKID depends on HISTORY_MODE. */
function
update_history (linkid, history_mode)
{
  let visible_url = window.location.pathname + window.location.search;
  if (linkid !== config.INDEX_ID)
    visible_url += ("#" + linkid);

  switch (history_mode)
  {
  case config.HISTORY_REPLACE:
    window.history.replaceState ({ linkid }, linkid, visible_url);
    break;
  case config.HISTORY_PUSH:
    window.history.pushState ({ linkid }, linkid, visible_url);
    break;
  case config.HISTORY_POP:
  default:
    break;
  }
}

/*-----------------------------------------
| Event handlers for the iframe context.  |
`----------------------------------------*/

/** Initialize the DOM for generic pages loaded in the context of an
    iframe.  */
export function
on_load ()
{
  fix_links (document.links);
  let links = {};
  let url = basename (window.location.pathname, /[.]x?html$/);
  links[url] = navigation_links (document);
  iframe_dispatch (actions.cache_links (links));
}

/** Handle messages received via the Message API.  */
export function
on_message (event)
{
  let data = event.data;
  if (data.message_kind === "scroll-to")
    {
      /* Scroll to the anchor corresponding to HASH without saving
         current page in session history.  */
      let url = window.location.pathname + window.location.search;
      window.location.replace ((data.hash) ? (url + data.hash) : url);
    }
}


code:
/* index.js - Global entry point
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

/** Depending on the role of the document launching this script, different
    event handlers are registered.  This script can be used in the context of:

    - the index page of the manual which manages the state of the application
    - the iframe which contains the lateral table of content
    - other iframes which contain other pages of the manual

    This is done to allow referencing the same script inside every HTML page.
    This has the benefits of reducing the number of HTTP requests required to
    fetch the Javascript code and simplifying the work of the Texinfo HTML
    converter.  */

import "./polyfill";
import * as actions from "./actions";
import * as main from "./main";
import * as pages from "./iframe";
import * as sidebar from "./sidebar";
import { absolute_url_p, href_hash } from "./utils";
import config from "./config";
import { iframe_dispatch } from "./store";
import { with_sidebar_query } from "./toc";

/*-------------------------
| Common event handlers.  |
`------------------------*/

function
on_click (event)
{
  for (var target = event.target; target !== null; target = target.parentNode)
    {
      if ((target instanceof Element) && target.matches ("a"))
        {
          let href = target.getAttribute ("href");
          if (!absolute_url_p (href))
            {
              let linkid = href_hash (href) || config.INDEX_ID;
              iframe_dispatch (actions.set_current_url (linkid));
              event.preventDefault ();
              event.stopPropagation ();
              return;
          }
        }
    }
}

function
on_unload ()
{
  var request = new XMLHttpRequest ();
  request.open ("GET", "(WINDOW-CLOSED)");
  request.send (null);
}

/* Handle Keyboard 'keypress' events.  */
function
on_keypress (event)
{
  let value = on_keypress.dict[event.key];
  if (value)
    {
      let [action, arg] = value;
      iframe_dispatch (action (arg));
    }
}

/* Dictionary associating an Event 'key' property to its navigation id.  */
on_keypress.dict = {
  m: [actions.show_component, "menu"],
  n: [actions.navigate, "next"],
  p: [actions.navigate, "prev"],
  u: [actions.navigate, "up"],
  "]": [actions.navigate, "forward"],
  "[": [actions.navigate, "backward"],
  "<": [actions.set_current_url_pointer, "*TOP*"],
  ">": [actions.set_current_url_pointer, "*END*"]
};

/*--------------------
| Context dispatch.  |
`-------------------*/

let inside_iframe = top !== window;
let inside_sidebar = inside_iframe && window.name === "slider";
let inside_index_page = (window.location.pathname.endsWith (config.INDEX_NAME)
                         || window.location.pathname.endsWith ("/"));

if (inside_index_page)
  {
    window.addEventListener ("DOMContentLoaded", main.on_load, false);
    window.addEventListener ("message", main.on_message, false);
    window.onpopstate = main.on_popstate;
  }
else if (inside_sidebar)
  {
    window.addEventListener ("DOMContentLoaded", sidebar.on_load, false);
    window.addEventListener ("message", sidebar.on_message, false);
  }
else if (inside_iframe)
  {
    window.addEventListener ("DOMContentLoaded", pages.on_load, false);
    window.addEventListener ("message", pages.on_message, false);
  }
else
  {
    /* Jump to 'config.INDEX_NAME' and adapt the selected iframe.  */
    window.location.replace (with_sidebar_query (window.location.href));
  }

/* Register common event handlers.  */
window.addEventListener ("beforeunload", on_unload, false);
window.addEventListener ("click", on_click, false);
window.addEventListener ("keypress", on_keypress, false);


code:
/* main.js - Handle the index page
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

import * as actions from "./actions";
import { Pages } from "./iframe";
import { Sidebar } from "./sidebar";
import { Store } from "./store";
import { Text_input } from "./text_input";
import config from "./config";
import { fix_links } from "./toc";
import { global_reducer } from "./reducers";
import { navigation_links } from "./utils";

/* Global state manager.  */
let store;

/* Aggregation of all the components.   */
let components = {
  element: null,
  components: [],

  add (component)
  {
    if (this.element === null)
      throw new Error ("element property must be set first");

    this.components.push (component);
    this.element.appendChild (component.element);
  },

  render (state)
  {
    this.components.forEach (cmpt => cmpt.render (state));
  }
};

/*--------------------------------------------
| Event handlers for the top-level context.  |
`-------------------------------------------*/

/* eslint-disable no-console */

/* Initialize the top level 'config.INDEX_NAME' DOM.  */
export function
on_load ()
{
  fix_links (document.links);
  document.body.setAttribute ("class", "mainbar");

  /* Move contents of <body> into a a fresh <div> to let the components
     treat the index page like other iframe page.  */
  let index_div = document.createElement ("div");
  for (let ch = document.body.firstChild; ch; ch = document.body.firstChild)
    index_div.appendChild (ch);

  /* Instanciate the components.  */
  components.element = document.body;
  components.add (new Sidebar ());
  components.add (new Pages (index_div));
  components.add (new Text_input ("menu"));

  let initial_state = {
    /* Dictionary associating page ids to next, prev, up, forward,
       backward link ids.  */
    loaded_nodes: {},
    /* page id of the current page.  */
    current: config.INDEX_ID,
    /* Current mode for handling history.  */
    history: config.HISTORY_REPLACE,
    /* Define if the sidebar iframe is loaded.  */
    sidebar_loaded: false,
    /* Define if the sidebar iframe is loaded.  */
    text_input_visible: false
  };

  store = new Store (global_reducer, initial_state);
  store.subscribe (() => components.render (store.state));
  store.subscribe (() => console.log ("state: ", store.state));

  if (window.location.hash)
    {
      let linkid = window.location.hash.slice (1);
      let action = actions.set_current_url (linkid, config.HISTORY_REPLACE);
      store.dispatch (action);
    }

  /* Retrieve NEXT link and local menu.  */
  let links = {};
  links[config.INDEX_ID] = navigation_links (document);
  store.dispatch (actions.cache_links (links));
}

/** Handle messages received via the Message API.  */
export function
on_message (event)
{
  let data = event.data;
  if (data.message_kind === "action")
    {
      /* Follow up actions to the store.  */
      store.dispatch (data.action);
    }
}

/** Event handler for 'popstate' events.  */
export function
on_popstate (event)
{
  let linkid = event.state.linkid;
  store.dispatch (actions.set_current_url (linkid, config.HISTORY_POP));
}


code:
/* polyfill.js - Methods required for compatibility reason */

/* eslint-disable */

/* Polyfill for 'window.URL'.  */
import "./url";

/* Polyfill for 'String.prototype.matches'.  */
function
string_includes (search, start)
{
  if (typeof start !== 'number')
    start = 0;

  if (start + search.length > this.length)
    return false;
  else
    return this.indexOf(search, start) !== -1;
}

/* Polyfill for 'Element.matches'.  */
function
element_matches (str)
{
  var document = (this.document || this.ownerDocument);
  var matches = document.querySelectorAll(str);
  var i = matches.length;
  while (--i >= 0 && matches.item(i) !== this) {}
  return i > -1;
}

/* Polyfill for 'Object.assign'.  */
function
object_assign (target, varArgs)
{
  if (target == null)           /* TypeError if undefined or null.  */
    throw new TypeError ('Cannot convert undefined or null to object');

  var to = Object (target);
  for (var index = 1; index < arguments.length; index++)
    {
      var nextSource = arguments[index];
      /* Skip over if undefined or null */
      if (nextSource != null)
        {
          for (var nextKey in nextSource)
            {
              /* Avoid bugs when hasOwnProperty is shadowed.  */
              if (Object.prototype.hasOwnProperty.call (nextSource, nextKey))
                to[nextKey] = nextSource[nextKey];
            }
        }
    }

  return to;
}

/* Augment prototypes if necessary.  */
if (!String.prototype.includes)
  String.prototype.includes = string_includes;

if (!Element.prototype.matches)
  {
    Element.prototype.matches = Element.prototype.matchesSelector
      || Element.prototype.mozMatchesSelector
      || Element.prototype.msMatchesSelector
      || Element.prototype.oMatchesSelector
      || Element.prototype.webkitMatchesSelector
      || element_matches;
  }

if (typeof Object.assign != 'function')
  Object.assign = object_assign;


code:
/* reducers.js - Actions handlers that return a new state
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

import {
  CACHE_LINKS,
  CURRENT_URL,
  HIDE_COMPONENT,
  NAVIGATE,
  SHOW_COMPONENT,
  SIDEBAR_LOADED
} from "./actions";

export function
global_reducer (state, action)
{
  switch (action.type)
    {
    case SIDEBAR_LOADED:
      return Object.assign ({}, state, { sidebar_loaded: true, action });
    case CACHE_LINKS:
      {
        let clone = Object.assign ({}, state.loaded_nodes);
        Object
          .keys (action.links)
          .forEach (key => {
            if (typeof action.links[key] === "object")
              clone[key] = Object.assign ({}, clone[key], action.links[key]);
            else
              clone[key] = action.links[key];
          });

        return Object.assign ({}, state, { loaded_nodes: clone, action });
      }
    case CURRENT_URL:
      {
        let res = Object.assign ({}, state, { action });
        let url = (action.pointer) ?
            state.loaded_nodes[action.pointer] : action.url;

        res.current = url;
        res.history = action.history;
        res.loaded_nodes[url] = res.loaded_nodes[url] || {};
        res.text_input_visible = false;
        return res;
      }
    case NAVIGATE:
      {
        let ids = state.loaded_nodes[state.current];
        let linkid = ids[action.direction];
        if (!linkid)
          return state;
        else
          {
            let res = Object.assign ({}, state, { current: linkid, action });
            res.history = action.history;
            res.text_input_visible = false;
            if (!Object.keys (res.loaded_nodes).includes (action.url))
              res.loaded_nodes[action.url] = {};
            return res;
          }
      }
    case SHOW_COMPONENT:
      {
        if (action.component !== "menu" || state.text_input_visible)
          return state;
        else
          {
            let text_input_visible = true;
            return Object.assign ({}, state, { text_input_visible, action });
          }
      }
    case HIDE_COMPONENT:
      {
        if (action.component !== "menu" || !state.text_input_visible)
          return state;
        else
          {
            let text_input_visible = false;
            return Object.assign ({}, state, { text_input_visible, action });
          }
      }
    default:
      return state;
    }
}


code:
/* sidebar.js - Handle the table of content iframed page
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

import * as actions from "./actions";

import {
  clear_toc_styles,
  create_link_dict,
  fix_links,
  scan_toc
} from "./toc";

import config from "./config";
import { iframe_dispatch } from "./store";

/** Sidebar component encapsulating the iframe and its state.  */
export class
Sidebar
{
  constructor ()
  {
    this.element = document.createElement ("div");
    this.element.setAttribute ("id", "sidebar");

    /* Create iframe. */
    let iframe = document.createElement ("iframe");
    iframe.setAttribute ("name", "slider");
    iframe.setAttribute ("src", (config.TOC_FILENAME
                                 + "#main=" + config.INDEX_NAME));
    this.element.appendChild (iframe);
    this.iframe = iframe;
  }

  /* Render 'sidebar' according to STATE which is a new state. */
  render (state)
  {
    /* Update sidebar to highlight the title corresponding to
       'state.current'.  */
    let msg = { message_kind: "update-sidebar", selected: state.current };
    this.iframe.contentWindow.postMessage (msg, "*");
    this.prev = state.current;
  }
}

/*----------------------------------------------
| Auxilary functions for the sidebar context.  |
`---------------------------------------------*/

/* Add a link from TOC_FILENAME to the main index file.  */
function
add_header ()
{
  let li = document.querySelector ("li");
  if (li && li.firstElementChild && li.firstElementChild.matches ("a")
      && li.firstElementChild.getAttribute ("href") === config.INDEX_NAME)
    li.parentNode.removeChild (li);

  let header = document.querySelector ("header");
  let h1 = document.querySelector ("h1");
  if (header && h1)
    {
      let a = document.createElement ("a");
      a.setAttribute ("href", "index.html");
      header.appendChild (a);
      let div = document.createElement ("div");
      a.appendChild (div);
      let img = document.createElement ("img");
      img.setAttribute ("src", config.PACKAGE_LOGO);
      div.appendChild (img);
      let span = document.createElement ("span");
      span.appendChild (h1.firstChild);
      div.appendChild (span);
      h1.parentNode.removeChild (h1);
    }
}

/*------------------------------------------
| Event handlers for the sidebar context.  |
`-----------------------------------------*/

/** Initialize TOC_FILENAME which must be loaded in the context of an
    iframe.  */
export function
on_load ()
{
  iframe_dispatch ({ type: actions.SIDEBAR_LOADED });

  add_header ();
  document.body.setAttribute ("class", "toc-sidebar");

  /* Specify the base URL to use for all relative URLs.  */
  /* FIXME: Add base also for sub-pages.  */
  let base = document.createElement ("base");
  base.setAttribute ("href",
                     window.location.href.replace (/[/][^/]*$/, "/"));
  document.head.appendChild (base);

  let links = Array.from (document.links);

  /* Create a link referencing the Table of content.  */
  let toc_a = document.createElementNS (config.XHTML_NAMESPACE, "a");
  toc_a.setAttribute ("href", config.TOC_FILENAME);
  toc_a.appendChild (document.createTextNode ("Table of Contents"));
  let toc_li = document.createElementNS (config.XHTML_NAMESPACE, "li");
  toc_li.appendChild (toc_a);
  let index_li = links[links.length - 1].parentNode;
  let index_grand = index_li.parentNode.parentNode;
  /* XXX: hack */
  if (index_grand.matches ("li"))
    index_li = index_grand;
  index_li.parentNode.insertBefore (toc_li, index_li.nextSibling);

  links.push (toc_a);
  fix_links (links);
  scan_toc (document.body, config.INDEX_NAME);

  let divs = Array.from (document.querySelectorAll ("div"));
  divs.reverse ()
      .forEach (div => {
        if (div.getAttribute ("class") === "toc-title")
          div.parentNode.removeChild (div);
      });

  /* Get 'backward' and 'forward' link attributes.  */
  let dict = create_link_dict (document.querySelector ("ul"));
  iframe_dispatch (actions.cache_links (dict));
}

/** Handle messages received via the Message API.  */
export function
on_message (event)
{
  let data = event.data;
  if (data.message_kind === "update-sidebar")
    {
      /* Highlight the current LINKID in the table of content.  */
      let selected = data.selected;
      clear_toc_styles (document.body);
      let filename = (selected === config.INDEX_ID) ?
          config.INDEX_NAME : (selected + ".xhtml");
      scan_toc (document.body, filename);
    }
}


code:
/* store.js - State manager using an unidirectional dataflow architecture
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

export class
Store
{
  constructor (reducer, state = {})
  {
    this.state = state;
    this.reducer = reducer;
    this.listeners = [];
  }

  dispatch (action)
  {
    /* Handle asynchonous actions which are functions.  */
    if (typeof action === "function")
      action (this.dispatch.bind (this));
    else
      {
        let new_state = this.reducer (this.state, action);
        if (new_state !== this.state)
          {
            this.state = new_state;
            this.listeners.forEach (listener => listener ());
          }
      }
  }

  subscribe (listener)
  {
    this.listeners.push (listener);

    /* Return a function to unsubscribe.  */
    return (() => {
      let idx = this.listeners.indexOf (listener);
      this.listeners.splice (idx, 1);
    });
  }
}

/** Dispatch ACTION to the top-level browsing context.  This function must be
    used in conjunction with an event listener on "message" events in the
    top-level browsing context which must forwards ACTION to an actual
    store.  */
export function
iframe_dispatch (action)
{
  top.postMessage ({ message_kind: "action", action }, "*");
}

export default { Store, iframe_dispatch };


code:
/* text-input.js - Component for menu navigation
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

import * as actions from "./actions";
import config from "./config";
import { iframe_dispatch } from "./store";

export class
Text_input
{
  constructor (id)
  {
    /* Create global container.  */
    let elem = document.createElement ("div");
    elem.setAttribute ("style", "background:pink;z-index:100;position:fixed");

    /* Create container for menu search.  */
    let div = document.createElement ("div");
    div.setAttribute ("hidden", "true");
    div.appendChild (document.createTextNode ("menu:"));
    let input = document.createElement ("input");
    input.setAttribute ("type", "search");
    input.setAttribute ("list", "menu");
    div.appendChild (input);
    elem.appendChild (div);

    /* Define a special key handler when INPUT is focused and visible.  */
    input.addEventListener ("keypress", event => {
      if (event.key === "Escape")
        iframe_dispatch (actions.hide_component (id));
      else if (event.key === "Enter")
        {
          let linkid = this.current_menu[this.input.value];
          if (linkid)
            iframe_dispatch (actions.set_current_url (linkid));
        }

      /* Do not send key events to global "key navigation" handler.  */
      event.stopPropagation ();
    });

    /* Create a container for warning when no menu in current page.  */
    let warn = document.createElement ("div");
    warn.setAttribute ("hidden", "true");
    warn.appendChild (document.createTextNode ("No menu in this node"));
    elem.appendChild (warn);

    this.element = elem;
    this.input_container = div;
    this.input = input;
    this.warn = warn;
    this.id = id;
    this.toid = null;
    this.current_menu = null;
  }

  render (state)
  {
    if (!state.text_input_visible)
      this.hide_elements ();
    else
      {
        let menu = state.loaded_nodes[state.current].menu;
        if (menu)
          this.show_menu_input (menu);
        else
          this.show_menu_warning ();
      }
  }

  /* Display a text input for searching through the current menu.  */
  show_menu_input (menu)
  {
    let datalist = create_datalist (menu);
    datalist.setAttribute ("id", "menu");
    this.current_menu = menu;
    this.input_container.appendChild (datalist);
    this.input_container.removeAttribute ("hidden");
    this.input.focus ();
  }

  /* Display a warning indicating that there is no menu in current node.  */
  show_menu_warning ()
  {
    /* Check if a menu warning is already displayed.  */
    if (this.toid)
      window.clearTimeout (this.toid);
    else
      this.warn.removeAttribute ("hidden");

    this.toid = window.setTimeout (() => {
      iframe_dispatch (actions.hide_component ("menu"));
      this.toid = null;
    }, config.WARNING_TIMEOUT);
  }

  /* Hide both menu input and menu warning.  */
  hide_elements ()
  {
    this.input_container.setAttribute ("hidden", "true");
    this.warn.setAttribute ("hidden", "true");
    this.input.value = "";

    /* Check if a menu warning is already displayed.  */
    if (this.toid)
      {
        window.clearTimeout (this.toid);
        this.toid = null;
      }

    /* Remove the datalist if found.  */
    this.input_container.querySelectorAll ("datalist")
                        .forEach (el => el.parentNode.removeChild (el));
  }
}

/* Create a datalist element containing option elements corresponding
   to the keys in MENU.  */
function
create_datalist (menu)
{
  let datalist = document.createElement ("datalist");
  Object.keys (menu)
        .forEach (title => {
          let opt = document.createElement ("option");
          opt.setAttribute ("value", title);
          datalist.appendChild (opt);
        });
  return datalist;
}


code:
/* toc.js - Generate and manage the table of content
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

import {
  absolute_url_p,
  basename,
  depth_first_walk,
  href_hash
} from "./utils";

import config from "./config";

/** Return a relative URL corresponding to HREF, which refers to an anchor of
    'config.INDEX_NAME'.  URL must be a USVString representing an absolute or
    relative URL.

    For example "foo/bar.html" will return "config.INDEX_NAME#bar".  */
export function
with_sidebar_query (href)
{
  if (basename (href) === config.INDEX_NAME)
    return config.INDEX_NAME;
  else
    {
      let url = new window.URL (href, window.location);
      let new_hash = basename (url.pathname, /[.]x?html/);
      if (url.hash)
        new_hash += ("." + url.hash.slice (1));
      return config.INDEX_NAME + "#" + new_hash;
    }
}

/* Keep children but remove grandchildren (Exception: don't remove
   anything on the current page; however, that's not a problem in the
   Kawa manual).  */
function
hide_grand_child_nodes (ul)
{
  for (let li = ul.firstElementChild; li; li = li.nextElementSibling)
    {
      let a = li.firstElementChild;
      let li$ = a && a.nextElementSibling;
      /* Never remove Overall-Index.  */
      if (li$ && a.getAttribute ("href") !== config.OVERALL_INDEX_NAME)
        li$.setAttribute ("toc-detail", "yes");
    }
}

/** Scan ToC entries to see which should be hidden.  */
export function
scan_toc (node, filename)
{
  var current = with_sidebar_query (filename);
  var ul = node.querySelector ("ul");
  if (filename === config.INDEX_NAME)
    hide_grand_child_nodes (ul);
  else
    scan_toc1 (ul, current);
}

/* Scan ToC entries to see which should be hidden.  Return "current" if node
   matches current, "ancestor" if node is ancestor of current, else 'null'.  */
function
scan_toc1 (node, current)
{
  if (node.matches ("a"))
    {
      if (current === node.getAttribute ("href"))
        {
          node.setAttribute ("toc-current", "yes");
          var ul = node.nextElementSibling;
          if (ul && ul.matches ("ul"))
            hide_grand_child_nodes (ul);
          return "current";
        }
    }
  var ancestor = null;
  for (var child = node.firstElementChild; child;
       child = child.nextElementSibling)
    {
      if (scan_toc1 (child, current) !== null)
        {
          ancestor = child;
          break;
        }
    }
  if (ancestor && ancestor.parentNode && ancestor.parentNode.parentNode)
    {
      var pparent = ancestor.parentNode.parentNode;
      for (var sib = pparent.firstElementChild; sib;
           sib = sib.nextElementSibling)
        {
          if (sib !== ancestor.parentNode
              && sib.firstElementChild
              && sib.firstElementChild.nextElementSibling)
            {
              sib.firstElementChild
                .nextElementSibling
                .setAttribute ("toc-detail", "yes");
            }
        }
    }

  return ancestor ? "ancestor" : null;
}

/** Reset what is done by 'scan_toc' and 'hide_grand_child_nodes'.  */
export function
clear_toc_styles (node)
{
  function
  do_clear (node$)
  {
    if (node$.matches ("ul"))
      node$.removeAttribute ("toc-detail");
    else if (node$.matches ("a"))
      node$.removeAttribute ("toc-current");
  }

  depth_first_walk (node, do_clear, Node.ELEMENT_NODE);
}

/** Build the global dictionary containing navigation links from NAV.  NAV
    must be an 'ul' DOM element containing the table of content of the
    manual.  */
export function
create_link_dict (nav)
{
  let prev_id = config.INDEX_ID;
  let links = {};

  function
  add_link (elem)
  {
    if (elem.matches ("a") && elem.hasAttribute ("href"))
      {
        let id = href_hash (elem.getAttribute ("href"));
        links[prev_id] = Object.assign ({}, links[prev_id], { forward: id });
        links[id] = Object.assign ({}, links[id], { backward: prev_id });
        prev_id = id;
      }
  }

  depth_first_walk (nav, add_link, Node.ELEMENT_NODE);
  /* Add a reference to the first and last node of the manual.  */
  links["*TOP*"] = config.INDEX_ID;
  links["*END*"] = prev_id;
  return links;
}

/** Modify LINKS to handle the iframe based navigation properly.  Relative
    links will be opened inside the corresponding iframe and absolute links
    will be opened in a new tab.  LINKS must be an array or a collection of
    nodes.  */
export function
fix_links (links)
{
  for (let i = 0; i < links.length; i += 1)
    {
      let link = links[i];
      let href = link.getAttribute ("href");
      if (href)
        {
          if (absolute_url_p (href))
            link.setAttribute ("target", "_blank");
          else
            link.setAttribute ("href", with_sidebar_query (href));
        }
    }
}


code:
/* URL.js - Implementation of the URL standard for web browsers

   Taken from <https://github.com/webcomponents/URL.git>.  */

/* eslint-disable */

/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

(function(scope) {
  'use strict';

  // feature detect for URL constructor
  var hasWorkingUrl = false;
  if (!scope.forceJURL) {
    try {
      var u = new URL('b', 'http://a');
      u.pathname = 'c%20d';
      hasWorkingUrl = u.href === 'http://a/c%20d';
    } catch(e) {}
  }

  if (hasWorkingUrl)
    return;

  var relative = Object.create(null);
  relative['ftp'] = 21;
  relative['file'] = 0;
  relative['gopher'] = 70;
  relative['http'] = 80;
  relative['https'] = 443;
  relative['ws'] = 80;
  relative['wss'] = 443;

  var relativePathDotMapping = Object.create(null);
  relativePathDotMapping['%2e'] = '.';
  relativePathDotMapping['.%2e'] = '..';
  relativePathDotMapping['%2e.'] = '..';
  relativePathDotMapping['%2e%2e'] = '..';

  function isRelativeScheme(scheme) {
    return relative[scheme] !== undefined;
  }

  function invalid() {
    clear.call(this);
    this._isInvalid = true;
  }

  function IDNAToASCII(h) {
    if ('' == h) {
      invalid.call(this)
    }
    // XXX
    return h.toLowerCase()
  }

  function percentEscape(c) {
    var unicode = c.charCodeAt(0);
    if (unicode > 0x20 &&
       unicode < 0x7F &&
       // " # < > ? `
       [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) == -1
      ) {
      return c;
    }
    return encodeURIComponent(c);
  }

  function percentEscapeQuery(c) {
    // XXX This actually needs to encode c using encoding and then
    // convert the bytes one-by-one.

    var unicode = c.charCodeAt(0);
    if (unicode > 0x20 &&
       unicode < 0x7F &&
       // " # < > ` (do not escape '?')
       [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) == -1
      ) {
      return c;
    }
    return encodeURIComponent(c);
  }

  var EOF = undefined,
      ALPHA = /[a-zA-Z]/,
      ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;

  function parse(input, stateOverride, base) {
    function err(message) {
      errors.push(message)
    }

    var state = stateOverride || 'scheme start',
        cursor = 0,
        buffer = '',
        seenAt = false,
        seenBracket = false,
        errors = [];

    loop: while ((input[cursor - 1] != EOF || cursor == 0) && !this._isInvalid) {
      var c = input[cursor];
      switch (state) {
        case 'scheme start':
          if (c && ALPHA.test(c)) {
            buffer += c.toLowerCase(); // ASCII-safe
            state = 'scheme';
          } else if (!stateOverride) {
            buffer = '';
            state = 'no scheme';
            continue;
          } else {
            err('Invalid scheme.');
            break loop;
          }
          break;

        case 'scheme':
          if (c && ALPHANUMERIC.test(c)) {
            buffer += c.toLowerCase(); // ASCII-safe
          } else if (':' == c) {
            this._scheme = buffer;
            buffer = '';
            if (stateOverride) {
              break loop;
            }
            if (isRelativeScheme(this._scheme)) {
              this._isRelative = true;
            }
            if ('file' == this._scheme) {
              state = 'relative';
            } else if (this._isRelative && base && base._scheme == this._scheme) {
              state = 'relative or authority';
            } else if (this._isRelative) {
              state = 'authority first slash';
            } else {
              state = 'scheme data';
            }
          } else if (!stateOverride) {
            buffer = '';
            cursor = 0;
            state = 'no scheme';
            continue;
          } else if (EOF == c) {
            break loop;
          } else {
            err('Code point not allowed in scheme: ' + c)
            break loop;
          }
          break;

        case 'scheme data':
          if ('?' == c) {
            this._query = '?';
            state = 'query';
          } else if ('#' == c) {
            this._fragment = '#';
            state = 'fragment';
          } else {
            // XXX error handling
            if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
              this._schemeData += percentEscape(c);
            }
          }
          break;

        case 'no scheme':
          if (!base || !(isRelativeScheme(base._scheme))) {
            err('Missing scheme.');
            invalid.call(this);
          } else {
            state = 'relative';
            continue;
          }
          break;

        case 'relative or authority':
          if ('/' == c && '/' == input[cursor+1]) {
            state = 'authority ignore slashes';
          } else {
            err('Expected /, got: ' + c);
            state = 'relative';
            continue
          }
          break;

        case 'relative':
          this._isRelative = true;
          if ('file' != this._scheme)
            this._scheme = base._scheme;
          if (EOF == c) {
            this._host = base._host;
            this._port = base._port;
            this._path = base._path.slice();
            this._query = base._query;
            this._username = base._username;
            this._password = base._password;
            break loop;
          } else if ('/' == c || '\\' == c) {
            if ('\\' == c)
              err('\\ is an invalid code point.');
            state = 'relative slash';
          } else if ('?' == c) {
            this._host = base._host;
            this._port = base._port;
            this._path = base._path.slice();
            this._query = '?';
            this._username = base._username;
            this._password = base._password;
            state = 'query';
          } else if ('#' == c) {
            this._host = base._host;
            this._port = base._port;
            this._path = base._path.slice();
            this._query = base._query;
            this._fragment = '#';
            this._username = base._username;
            this._password = base._password;
            state = 'fragment';
          } else {
            var nextC = input[cursor+1]
            var nextNextC = input[cursor+2]
            if (
              'file' != this._scheme || !ALPHA.test(c) ||
              (nextC != ':' && nextC != '|') ||
              (EOF != nextNextC && '/' != nextNextC && '\\' != nextNextC && '?' != nextNextC && '#' != nextNextC)) {
              this._host = base._host;
              this._port = base._port;
              this._username = base._username;
              this._password = base._password;
              this._path = base._path.slice();
              this._path.pop();
            }
            state = 'relative path';
            continue;
          }
          break;

        case 'relative slash':
          if ('/' == c || '\\' == c) {
            if ('\\' == c) {
              err('\\ is an invalid code point.');
            }
            if ('file' == this._scheme) {
              state = 'file host';
            } else {
              state = 'authority ignore slashes';
            }
          } else {
            if ('file' != this._scheme) {
              this._host = base._host;
              this._port = base._port;
              this._username = base._username;
              this._password = base._password;
            }
            state = 'relative path';
            continue;
          }
          break;

        case 'authority first slash':
          if ('/' == c) {
            state = 'authority second slash';
          } else {
            err("Expected '/', got: " + c);
            state = 'authority ignore slashes';
            continue;
          }
          break;

        case 'authority second slash':
          state = 'authority ignore slashes';
          if ('/' != c) {
            err("Expected '/', got: " + c);
            continue;
          }
          break;

        case 'authority ignore slashes':
          if ('/' != c && '\\' != c) {
            state = 'authority';
            continue;
          } else {
            err('Expected authority, got: ' + c);
          }
          break;

        case 'authority':
          if ('@' == c) {
            if (seenAt) {
              err('@ already seen.');
              buffer += '%40';
            }
            seenAt = true;
            for (var i = 0; i < buffer.length; i++) {
              var cp = buffer[i];
              if ('\t' == cp || '\n' == cp || '\r' == cp) {
                err('Invalid whitespace in authority.');
                continue;
              }
              // XXX check URL code points
              if (':' == cp && null === this._password) {
                this._password = '';
                continue;
              }
              var tempC = percentEscape(cp);
              (null !== this._password) ? this._password += tempC : this._username += tempC;
            }
            buffer = '';
          } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
            cursor -= buffer.length;
            buffer = '';
            state = 'host';
            continue;
          } else {
            buffer += c;
          }
          break;

        case 'file host':
          if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
            if (buffer.length == 2 && ALPHA.test(buffer[0]) && (buffer[1] == ':' || buffer[1] == '|')) {
              state = 'relative path';
            } else if (buffer.length == 0) {
              state = 'relative path start';
            } else {
              this._host = IDNAToASCII.call(this, buffer);
              buffer = '';
              state = 'relative path start';
            }
            continue;
          } else if ('\t' == c || '\n' == c || '\r' == c) {
            err('Invalid whitespace in file host.');
          } else {
            buffer += c;
          }
          break;

        case 'host':
        case 'hostname':
          if (':' == c && !seenBracket) {
            // XXX host parsing
            this._host = IDNAToASCII.call(this, buffer);
            buffer = '';
            state = 'port';
            if ('hostname' == stateOverride) {
              break loop;
            }
          } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
            this._host = IDNAToASCII.call(this, buffer);
            buffer = '';
            state = 'relative path start';
            if (stateOverride) {
              break loop;
            }
            continue;
          } else if ('\t' != c && '\n' != c && '\r' != c) {
            if ('[' == c) {
              seenBracket = true;
            } else if (']' == c) {
              seenBracket = false;
            }
            buffer += c;
          } else {
            err('Invalid code point in host/hostname: ' + c);
          }
          break;

        case 'port':
          if (/[0-9]/.test(c)) {
            buffer += c;
          } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c || stateOverride) {
            if ('' != buffer) {
              var temp = parseInt(buffer, 10);
              if (temp != relative[this._scheme]) {
                this._port = temp + '';
              }
              buffer = '';
            }
            if (stateOverride) {
              break loop;
            }
            state = 'relative path start';
            continue;
          } else if ('\t' == c || '\n' == c || '\r' == c) {
            err('Invalid code point in port: ' + c);
          } else {
            invalid.call(this);
          }
          break;

        case 'relative path start':
          if ('\\' == c)
            err("'\\' not allowed in path.");
          state = 'relative path';
          if ('/' != c && '\\' != c) {
            continue;
          }
          break;

        case 'relative path':
          if (EOF == c || '/' == c || '\\' == c || (!stateOverride && ('?' == c || '#' == c))) {
            if ('\\' == c) {
              err('\\ not allowed in relative path.');
            }
            var tmp;
            if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
              buffer = tmp;
            }
            if ('..' == buffer) {
              this._path.pop();
              if ('/' != c && '\\' != c) {
                this._path.push('');
              }
            } else if ('.' == buffer && '/' != c && '\\' != c) {
              this._path.push('');
            } else if ('.' != buffer) {
              if ('file' == this._scheme && this._path.length == 0 && buffer.length == 2 && ALPHA.test(buffer[0]) && buffer[1] == '|') {
                buffer = buffer[0] + ':';
              }
              this._path.push(buffer);
            }
            buffer = '';
            if ('?' == c) {
              this._query = '?';
              state = 'query';
            } else if ('#' == c) {
              this._fragment = '#';
              state = 'fragment';
            }
          } else if ('\t' != c && '\n' != c && '\r' != c) {
            buffer += percentEscape(c);
          }
          break;

        case 'query':
          if (!stateOverride && '#' == c) {
            this._fragment = '#';
            state = 'fragment';
          } else if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
            this._query += percentEscapeQuery(c);
          }
          break;

        case 'fragment':
          if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
            this._fragment += c;
          }
          break;
      }

      cursor++;
    }
  }

  function clear() {
    this._scheme = '';
    this._schemeData = '';
    this._username = '';
    this._password = null;
    this._host = '';
    this._port = '';
    this._path = [];
    this._query = '';
    this._fragment = '';
    this._isInvalid = false;
    this._isRelative = false;
  }

  // Does not process domain names or IP addresses.
  // Does not handle encoding for the query parameter.
  function jURL(url, base /* , encoding */) {
    if (base !== undefined && !(base instanceof jURL))
      base = new jURL(String(base));

    this._url = url;
    clear.call(this);

    var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
    // encoding = encoding || 'utf-8'

    parse.call(this, input, null, base);
  }

  jURL.prototype = {
    toString: function() {
      return this.href;
    },
    get href() {
      if (this._isInvalid)
        return this._url;

      var authority = '';
      if ('' != this._username || null != this._password) {
        authority = this._username +
            (null != this._password ? ':' + this._password : '') + '@';
      }

      return this.protocol +
          (this._isRelative ? '//' + authority + this.host : '') +
          this.pathname + this._query + this._fragment;
    },
    set href(href) {
      clear.call(this);
      parse.call(this, href);
    },

    get protocol() {
      return this._scheme + ':';
    },
    set protocol(protocol) {
      if (this._isInvalid)
        return;
      parse.call(this, protocol + ':', 'scheme start');
    },

    get host() {
      return this._isInvalid ? '' : this._port ?
          this._host + ':' + this._port : this._host;
    },
    set host(host) {
      if (this._isInvalid || !this._isRelative)
        return;
      parse.call(this, host, 'host');
    },

    get hostname() {
      return this._host;
    },
    set hostname(hostname) {
      if (this._isInvalid || !this._isRelative)
        return;
      parse.call(this, hostname, 'hostname');
    },

    get port() {
      return this._port;
    },
    set port(port) {
      if (this._isInvalid || !this._isRelative)
        return;
      parse.call(this, port, 'port');
    },

    get pathname() {
      return this._isInvalid ? '' : this._isRelative ?
          '/' + this._path.join('/') : this._schemeData;
    },
    set pathname(pathname) {
      if (this._isInvalid || !this._isRelative)
        return;
      this._path = [];
      parse.call(this, pathname, 'relative path start');
    },

    get search() {
      return this._isInvalid || !this._query || '?' == this._query ?
          '' : this._query;
    },
    set search(search) {
      if (this._isInvalid || !this._isRelative)
        return;
      this._query = '?';
      if ('?' == search[0])
        search = search.slice(1);
      parse.call(this, search, 'query');
    },

    get hash() {
      return this._isInvalid || !this._fragment || '#' == this._fragment ?
          '' : this._fragment;
    },
    set hash(hash) {
      if (this._isInvalid)
        return;
      this._fragment = '#';
      if ('#' == hash[0])
        hash = hash.slice(1);
      parse.call(this, hash, 'fragment');
    },

    get origin() {
      var host;
      if (this._isInvalid || !this._scheme) {
        return '';
      }
      // javascript: Gecko returns String(""), WebKit/Blink String("null")
      // Gecko throws error for "data://"
      // data: Gecko returns "", Blink returns "data://", WebKit returns "null"
      // Gecko returns String("") for file: mailto:
      // WebKit/Blink returns String("SCHEME://") for file: mailto:
      switch (this._scheme) {
        case 'data':
        case 'file':
        case 'javascript':
        case 'mailto':
          return 'null';
      }
      host = this.host;
      if (!host) {
        return '';
      }
      return this._scheme + '://' + host;
    }
  };

  // Copy over the static methods
  var OriginalURL = scope.URL;
  if (OriginalURL) {
    jURL.createObjectURL = function(blob) {
      // IE extension allows a second optional options argument.
      // http://msdn.microsoft.com/en-us/library/ie/hh772302(v=vs.85).aspx
      return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
    };
    jURL.revokeObjectURL = function(url) {
      OriginalURL.revokeObjectURL(url);
    };
  }

  scope.URL = jURL;

})(window);


code:
/* utils.js - General purpose utilitary functions
   Copyright © 2017 Free Software Foundation, Inc.

   This file is part of GNU Texinfo.

   GNU Texinfo is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU Texinfo is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Texinfo.  If not, see <http://www.gnu.org/licenses/>.  */

/** Check if 'URL' is an absolute URL.  Return true if this is the case
    otherwise return false.  'URL' must be a USVString representing a valid
    URL.  */
export function
absolute_url_p (url)
{
  if (typeof url !== "string")
    throw new TypeError (`'${url}' is not a string`);

  return url.includes (":");
}

/** Return PATHNAME with any leading directory components removed.  If
    specified, also remove a trailing SUFFIX.  */
export function
basename (pathname, suffix)
{
  let res = pathname.replace (/.*[/]/, "");
  if (!suffix)
    return res;
  else if (suffix instanceof RegExp)
    return res.replace (suffix, "");
  else                          /* typeof SUFFIX === "string" */
    return res.replace (new RegExp ("[.]" + suffix), "");
}

/** Apply FUNC to each nodes in the NODE subtree.  The walk follows a depth
    first algorithm.  Only consider the nodes of type NODE_TYPE.  */
export function
depth_first_walk (node, func, node_type)
{
  if (!node_type || (node.nodeType === node_type))
    func (node);

  for (let child = node.firstChild; child; child = child.nextSibling)
    depth_first_walk (child, func, node_type);
}

/** Return the hash part of HREF without the '#' prefix.  HREF must be
    a string.  If there is no hash part in HREF then return the empty
    string.  */
export function
href_hash (href)
{
  if (typeof href !== "string")
    throw new TypeError (href + " is not a string");

  if (href.includes ("#"))
    return href.replace (/.*#/, "");
  else
    return "";
}

/** Retrieve PREV, NEXT, and UP links, and local menu from CONTENT and return
    an object containing references to those links.  CONTENT must be an object
    implementing the ParentNode interface (Element, Document...).  */
export function
navigation_links (content)
{
  let links = content.querySelectorAll ("footer a");
  let res = {};
  /* links have the form MAIN_FILE.html#FRAME-ID.  For convenience
     only store FRAME-ID.  */
  for (let i = 0; i < links.length; i += 1)
    {
      let link = links[i];
      let nav_id = navigation_links.dict[link.getAttribute ("accesskey")];
      if (nav_id)
        res[nav_id] = href_hash (link.getAttribute ("href"));
      else                  /* this link is part of local table of content. */
        {
          res.menu = res.menu || {};
          res.menu[link.text] = href_hash (link.getAttribute ("href"));
        }
    }

  return res;
}

/* Dictionary associating an 'accesskey' property to its navigation id.  */
navigation_links.dict = { n: "next", p: "prev", u: "up" };