Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346############################################################################# ## #W GAPDoc2HTML.gi GAPDoc Frank Lübeck ## ## #Y Copyright (C) 2000, Frank Lübeck, Lehrstuhl D für Mathematik, #Y RWTH Aachen ## ## The files GAPDoc2HTML.g{d,i} contain a conversion program which ## produces from a GAPDoc XML-document an HTML version for reading the ## document with a Web-browser. ## ## REMARKS: ## ## We add to all nodes of the parse tree an entry .root which points to ## the document root. The toc-, index- and bib-information is collected ## in the root. ## ## The set of elements is partitioned into two subsets - those which ## contain whole paragraphs and those which don't. ## ## The handler of a paragraph containing element (see ## GAPDoc2HTMLProcs.ParEls below) gets a list as argument to which it ## adds entries pairwise: the first of such a pair is the paragraph ## counter (like [3,2,1,5] meaning Chap.3, Sec.2, Subsec.1, Par.5) and ## the second is the formatted text of this paragraph. ## ## Some handlers of paragraph containing elements do the formatting ## themselves (e.g., .List), the others are handled in the main recursion ## function `GAPDoc2HTMLContent'. ## ## We produce a full version of the document in HTML format, including ## title page, abstract and other front matter, table of contents, ## bibliography (via BibTeX-data files) and index. For this we have to ## process a document twice (similar to LaTeX). ## ## Small utility to throw away SGML markup BindGlobal("FilterSGMLMarkup", function(str) local p2, p1, res; p2 := Position(str, '<'); if p2 = fail then return str; fi; p1 := 0; res := ""; while p2 <> fail do Append(res, str{[p1+1..p2-1]}); p1 := Position(str, '>', p2); if p1 = fail then return res; fi; p2 := Position(str, '<', p1); if p2 = fail then Append(res, str{[p1+1..Length(str)]}); return res; fi; od; end); InstallValue(GAPDoc2HTMLProcs, rec()); ## Some text attributes ([begin, end] pairs) GAPDoc2HTMLProcs.TextAttr := rec(); GAPDoc2HTMLProcs.TextAttr.Heading := ["<span class=\"Heading\">", "</span>"]; GAPDoc2HTMLProcs.TextAttr.Func := ["<code class=\"func\">", "</code>"]; GAPDoc2HTMLProcs.TextAttr.Arg := ["<var class=\"Arg\">", "</var>"]; GAPDoc2HTMLProcs.TextAttr.Example := ["<div class=\"Example\">", "</div>"]; GAPDoc2HTMLProcs.TextAttr.Package := ["<strong class=\"pkg\">", "</strong>"]; GAPDoc2HTMLProcs.TextAttr.URL := ["<span class=\"URL\">", "</span>"]; GAPDoc2HTMLProcs.TextAttr.Mark := ["<strong class=\"Mark\">", "</strong>"]; GAPDoc2HTMLProcs.TextAttr.K := ["<code class=\"keyw\">", "</code>"]; GAPDoc2HTMLProcs.TextAttr.C := ["<code class=\"code\">", "</code>"]; GAPDoc2HTMLProcs.TextAttr.F := ["<code class=\"file\">", "</code>"]; GAPDoc2HTMLProcs.TextAttr.I := ["<code class=\"i\">", "</code>"]; GAPDoc2HTMLProcs.TextAttr.B := ["<strong class=\"button\">", "</strong>"]; GAPDoc2HTMLProcs.TextAttr.Emph := ["<em>", "</em>"]; GAPDoc2HTMLProcs.TextAttr.Ref := ["<span class=\"RefLink\">", "</span>"]; GAPDoc2HTMLProcs.TextAttr.M := ["<span class=\"SimpleMath\">", "</span>"]; GAPDoc2HTMLProcs.TextAttr.Math := ["<span class=\"Math\">", "</span>"]; GAPDoc2HTMLProcs.TextAttr.GAPprompt := ["<span class=\"GAPprompt\">", "</span>"]; GAPDoc2HTMLProcs.TextAttr.GAPbrkprompt := ["<span class=\"GAPbrkprompt\">", "</span>"]; GAPDoc2HTMLProcs.TextAttr.GAPinput := ["<span class=\"GAPinput\">", "</span>"]; # like in Text converter, but a heading and an address are not a paragraph here GAPDoc2HTMLProcs.ParEls := [ "Display", "Example", "Log", "Listing", "List", "Enum", "Item", "Table", "TitlePage", "Abstract", "Copyright", "Acknowledgements", "Colophon", "TableOfContents", "Bibliography", "TheIndex", "Subsection", "ManSection", "Description", "Returns", "Section", "Chapter", "Appendix", "Body", "Book", "WHOLEDOCUMENT", "Attr", "Fam", "Filt", "Func", "InfoClass", "Meth", "Oper", "Constr", "Prop", "Var", "Verb"]; ## arg: a list of strings ## for now only ?????? SetGapDocHTMLOptions := function(arg) local gdp; gdp := GAPDoc2HTMLProcs; return; end; GAPDoc2HTMLProcs.Head1 := "\ <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ \n\ <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n\ \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\ \n\ <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n\ <head>\n\ <title>GAP ("; GAPDoc2HTMLProcs.MathJaxURL := "http://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML"; GAPDoc2HTMLProcs.Head1MathJax := "\ <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ \n\ <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n\ \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\ \n\ <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n\ <head>\n\ <script type=\"text/javascript\"\n\ src=\"MATHJAXURL\">\n\ </script>\n\ <title>GAP ("; GAPDoc2HTMLProcs.Head1Trans := "\ <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ \n\ <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\ \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n\ \n\ <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n\ <head>\n\ <title>GAP ("; GAPDoc2HTMLProcs.Head1MML := "\ <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ <?xml-stylesheet type=\"text/xsl\" href=\"mathml.xsl\"?>\n\ \n\ <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\"\n\ \"http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd\" [\n\ <!ENTITY mathml \"http://www.w3.org/1998/Math/MathML\">\n\ ] >\n\ \n\ <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n\ <head>\n\ <link rel=\"stylesheet\" type=\"text/css\" href=\"mathml.css\" />\n\ <title>GAP ("; GAPDoc2HTMLProcs.Head2 := "\ </title>\n\ <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\" />\n\ <meta name=\"generator\" content=\"GAPDoc2HTML\" />\n\ <link rel=\"stylesheet\" type=\"text/css\" href=\"manual.css\" />\n\ <script src=\"manual.js\" type=\"text/javascript\"></script>\n\ <script type=\"text/javascript\">overwriteStyle();</script>\n\ </head>\n<body onload=\"jscontent()\">\n"; GAPDoc2HTMLProcs.Tail := "\n\ <hr />\n\ <p class=\"foot\">generated by <a \ href=\"http://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc\">GAPDoc2HTML\ </a></p>\ \n</body>\n</html>\n"; GAPDoc2HTMLProcs.PutFilesTogether := function(l, r) local files, n, tt, i, chnrs, chlink, prev, next, toplink; chnrs := Set(List([2,4..Length(l)], i-> l[i-1][1])); chnrs := Concatenation(Filtered(chnrs, a-> not a in ["Bib", "Ind"]), Filtered(chnrs, a-> a in ["Bib", "Ind"])); chlink := Concatenation("\n<div class=\"chlinktop\"><span class=\"chlink1\">", GAPDocTexts.d.GotoChapter, ": </span>"); for n in chnrs do Append(chlink, Concatenation("<a href=\"chap", String(n), GAPDoc2HTMLProcs.ext, "\">")); if n = 0 then Append(chlink, GAPDocTexts.d.Top); else Append(chlink, String(n)); fi; Append(chlink,"</a> "); od; Append(chlink, "</div>\n"); toplink := Concatenation( " <a href=\"chap0", GAPDoc2HTMLProcs.ext, "\">[", GAPDocTexts.d.TopofBook, "]</a> ", "<a href=\"chap0", GAPDoc2HTMLProcs.ext, "#contents", "\">[", GAPDocTexts.d.Contents, "]</a> " ); prev := []; next := []; for i in [1..Length(chnrs)] do if i > 1 then Add(prev, Concatenation(" <a href=\"chap", String(chnrs[i-1]), GAPDoc2HTMLProcs.ext, "\">[", GAPDocTexts.d.PreviousChapter, "]</a> ")); else Add(prev, ""); fi; if i < Length(chnrs) then Add(next, Concatenation(" <a href=\"chap", String(chnrs[i+1]), GAPDoc2HTMLProcs.ext, "\">[", GAPDocTexts.d.NextChapter, "]</a> ")); else Add(next, ""); fi; od; # putting the paragraphs together (one string (file) for each chapter) files := rec(); for i in [1..Length(chnrs)] do n := chnrs[i]; if r.root.mathmode = "MathML" then # this MathML is no longer documented files.(n) := rec(text := ShallowCopy(GAPDoc2HTMLProcs.Head1MML), ssnr := []); elif r.root.mathmode = "Tth" then files.(n) := rec(text := ShallowCopy(GAPDoc2HTMLProcs.Head1Trans), ssnr := []); elif r.root.mathmode = "MathJax" then files.(n) := rec(text := SubstitutionSublist( GAPDoc2HTMLProcs.Head1MathJax, "MATHJAXURL", GAPDoc2HTMLProcs.MathJaxURL), ssnr := []); else files.(n) := rec(text := ShallowCopy(GAPDoc2HTMLProcs.Head1), ssnr := []); fi; tt := Concatenation(r.bookname, ") - "); if n=0 then Append(tt, GAPDocTexts.d.Contents); elif IsInt(n) then Append(tt, Concatenation(GAPDocTexts.d.Chapter, " ", String(n), ": ", FilterSGMLMarkup(r.chaptitle.(n)))); elif n="Bib" then Append(tt, GAPDocTexts.d.References); elif n="Ind" then Append(tt, GAPDocTexts.d.Index); else Append(tt, Concatenation(GAPDocTexts.d.Appendix, " ", n, ": ", FilterSGMLMarkup(r.chaptitle.(n)))); fi; Append(files.(n).text, tt); Append(files.(n).text, GAPDoc2HTMLProcs.Head2); # allow for chapter-wise CSS config files.(n).text := SubstitutionSublist(files.(n).text, "<body", Concatenation("<body class=\"chap", String(n), "\" ")); Append(files.(n).text, Concatenation("\n", chlink)); Append(files.(n).text, Concatenation( "\n<div class=\"chlinkprevnexttop\">", toplink, prev[i], next[i], "</div>\n\n")); if IsBound(r.root.LinkToMathJax) then # cross link to same chapter with MathJax enabled Append(files.(n).text, Concatenation("<p id=\"mathjaxlink\" ", "class=\"pcenter\"><a href=\"chap", String(n), "_mj.html\">[MathJax on]</a></p>\n")); elif r.root.mathmode = "MathJax" then # cross link to non-MathJax version Append(files.(n).text, Concatenation("<p id=\"mathjaxlink\" ", "class=\"pcenter\"><a href=\"chap", String(n), ".html\">[MathJax off]</a></p>\n")); else # we still want the hook for the [Style] link Append(files.(n).text, Concatenation("<p id=\"mathjaxlink\" ", "class=\"pcenter\"></p>\n")); fi; od; for i in [2,4..Length(l)] do n := files.(l[i-1][1]); if Length(n.ssnr)=0 or l[i-1]{[1..3]} <> n.ssnr[Length(n.ssnr)] then Add(n.ssnr, l[i-1]{[1..3]}); tt := GAPDoc2HTMLProcs.SectionLabel(r, l[i-1], "Subsection")[2]; Append(n.text, Concatenation("<p><a id=\"", tt, "\" name=\"", tt, "\"></a></p>\n")); fi; Append(n.text, l[i]); od; for i in [1..Length(chnrs)] do n := chnrs[i]; Append(files.(n).text, Concatenation( "\n<div class=\"chlinkprevnextbot\">", toplink, prev[i], next[i], "</div>\n\n")); Append(files.(n).text, SubstitutionSublist(chlink, "chlinktop", "chlinkbot", false)); Append(files.(n).text, GAPDoc2HTMLProcs.Tail); od; # finally tell result the file extensions files.ext := GAPDoc2HTMLProcs.ext; return files; end; ## ## <#GAPDoc Label="GAPDoc2HTML"> ## <ManSection > ## <Func Arg="tree[, bibpath[, gaproot]][, mtrans]" Name="GAPDoc2HTML" /> ## <Returns>record containing HTML files as strings and other ## information</Returns> ## <Description> ## <Index Key="MathJax"><Package>MathJax</Package></Index> ## The argument <A>tree</A> for this function is a tree ## describing a &GAPDoc; XML document as returned by <Ref ## Func="ParseTreeXMLString" /> (probably also checked with <Ref ## Func="CheckAndCleanGapDocTree" />). Without an <A>mtrans</A> ## argument this function produces an HTML version of the document ## which can be read with any Web-browser and also be used with ## &GAP;'s online help (see <Ref BookName="Ref" Func="SetHelpViewer" ## />). It includes title page, bibliography, and index. The ## bibliography is made from &BibTeX; databases. Their location must ## be given with the argument <A>bibpath</A> (as string or directory ## object, if not given the current directory is used). If the third ## argument <A>gaproot</A> is given and is a string then this string ## is interpreted as relative path to &GAP;'s main root directory. ## Reference-URLs to external HTML-books which begin with the &GAP; ## root path are then rewritten to start with the given relative ## path. This makes the HTML-documentation portable provided a ## package is installed in some standard location below the &GAP; ## root.<P/> ## ## The output is a record with one component for each chapter ## (with names <C>"0"</C>, <C>"1"</C>, ..., <C>"Bib"</C>, and ## <C>"Ind"</C>). Each such component is again a record with ## the following components: ## ## <List > ## <Mark><C>text</C></Mark> ## <Item>the text of an HTML file containing the whole chapter (as a ## string)</Item> ## <Mark><C>ssnr</C></Mark> ## <Item>list of subsection numbers in this chapter (like <C>[3, 2, ## 1]</C> for chapter 3, section 2, subsection 1) ## </Item> ## </List> ## ## <Emph>Standard output format without</Emph> <A>mtrans</A> ## <Emph>argument</Emph><P/> ## ## The HTML code produced with this converter conforms ## to the W3C specification <Q>XHTML 1.0 strict</Q>, see ## <URL>http://www.w3.org/TR/xhtml1</URL>. First, this means that ## the HTML files are valid XML files. Secondly, the ## extension <Q>strict</Q> says in particular that the code ## doesn't contain any explicit font or color information.<P/> ## ## Mathematical formulae are handled as in the text converter ## <Ref Func="GAPDoc2Text"/>. We don't want to assume that the ## browser can use symbol fonts. Some &GAP; users like to browse ## the online help with <C>lynx</C>, see <Ref BookName="Ref" ## Func="SetHelpViewer" />, which runs inside the same terminal ## windows as &GAP;.<P/> ## ## To view the generated files in graphical browsers, stylesheet files ## with layout configuration should be copied into the directory ## with the generated HTML files, see <Ref Subsect="StyleSheets"/>. ## <P/> ## ## <Label Name="mtransarg"/> ## <Emph>Output format with</Emph> <A>mtrans</A> argument <P/> ## ## Currently, there are three variants of this converter available ## which handle mathematical formulae differently. They are accessed ## via the optional last <A>mtrans</A> argument.<P/> ## ## If <A>mtrans</A> is set to <C>"MathJax"</C> the formulae ## are essentially translated as for &LaTeX; documents (there ## is no processing of <C><M></C> elements as decribed ## in <Ref Subsect="M"/>). Inline formulae are delimited by ## <C>\(</C> and <C>\)</C> and displayed formulae by <C>\[</C> ## and <C>\]</C>. With <Package>MathJax</Package> webpages ## can contain nicely formatted scalable and searchable ## formulae. The resulting files link by default to <URL ## Text="http://cdn.mathjax.org">http://cdn.mathjax.org</URL> to get ## the <Package>MathJax</Package> script and fonts. This means ## that they can only be used on computers with internet ## access. An alternative URL can be set by overwriting ## <C>GAPDoc2HTMLProcs.MathJaxURL</C> before building the HTML ## version of a manual. This way a local installation ## of <Package>MathJax</Package> could be used. See <URL ## Text="http://www.mathjax.org/">http://www.mathjax.org/</URL> for ## more details.<P/> ## ## The following possibilities for <A>mtrans</A> are still supported, ## but since the <Package>MathJax</Package> approach seems much better, ## their use is deprecated.<P/> ## ## If the argument <A>mtrans</A> is set to <C>"Tth"</C> it is ## assumed that you have installed the &LaTeX; to HTML translation ## program <C>tth</C>. This is used to translate the contents of the ## <C>M</C>, <C>Math</C> and <C>Display</C> elements into HTML ## code. Note that the resulting code is not compliant with any ## standard. Formally it is <Q>XHTML 1.0 Transitional</Q>, it ## contains explicit font specifications and the characters of ## mathematical symbols are included via their position in a ## <Q>Symbol</Q> font. Some graphical browsers can be configured ## to display this in a useful manner, check <URL Text="the ## Tth homepage">http://hutchinson.belmont.ma.us/tth/</URL> for more ## details.<P/> ## ## This function works by running recursively through the document ## tree and calling a handler function for each &GAPDoc; ## XML element. Many of these handler functions (usually in ## <C>GAPDoc2TextProcs.<ElementName></C>) are not difficult to ## understand (the greatest complications are some commands for index ## entries, labels or the output of page number information). So it ## should be easy to adjust certain details to your own taste by slight ## modifications of the program. <P/> ## ## The result of this converter can be written to files with the ## command <Ref Func="GAPDoc2HTMLPrintHTMLFiles" />.<P/> ## ## There are two user preferences for reading the HTML manuals produced by ## &GAPDoc;. A user can choose among several style files which determine the ## appearance of the manual pages with ## <C>SetUserPreference("GAPDoc", "HTMLStyle", [...]);</C> where the list in ## the third argument are arguments for <Ref Func="SetGAPDocHTMLStyle"/>. ## The second preference is set by ## <C>SetUserPreference("GAPDoc", "UseMathJax", ...);</C> where the third ## argument is <K>true</K> or <K>false</K> (default). If this is set to ## <K>true</K>, the &GAP; help system displays the <Package>MathJax</Package> ## version of the HTML manuals. ## </Description> ## </ManSection> ## <#/GAPDoc> ## ## <#GAPDoc Label="HTMLStyleSheets"> ## <Subsection Label="StyleSheets"> ## <Heading>Stylesheet files</Heading> ## <Index>CSS stylesheets</Index> ## ## For graphical browsers the layout of the generated HTML manuals can be ## highly configured by cascading stylesheet (CSS) and javascript ## files. Such files are provided in the <F>styles</F> directory of the ## &GAPDoc; package.<P/> ## ## We recommend that these files are copied into each manual directory ## (such that each of them is selfcontained). There is a utility ## function <Ref Func="CopyHTMLStyleFiles" /> which does this. Of ## course, these files may be changed or new styles may be added. New ## styles may also be sent to the &GAPDoc; authors for possible ## inclusion in future versions.<P/> ## ## The generated HTML files refer to the file <F>manual.css</F> ## which conforms to the W3C specification CSS 2.0, see ## <URL>http://www.w3.org/TR/REC-CSS2</URL>, and the javascript file ## <F>manual.js</F> (only in browsers which support CSS or javascript, ## respectively; but the HTML files are also readable without ## any of them). To add a style <C>mystyle</C> one or both of ## <F>mystyle.css</F> and <F>mystyle.js</F> must be provided; these can ## overwrite default settings and add new javascript functions. For ## more details see the comments in <F>manual.js</F>.<P/> ## </Subsection> ## <ManSection > ## <Func Arg="dir" Name="CopyHTMLStyleFiles" /> ## <Returns>nothing</Returns> ## <Description> ## This utility function copies the <F>*.css</F> and <F>*.js</F> files ## from the <F>styles</F> directory of the &GAPDoc; package into the ## directory ## <A>dir</A>. ## </Description> ## </ManSection> ## <#/GAPDoc> ## ## the basic call, used recursively with a result r from GetElement ## and a string str or list l to which the output should be appended # arg: r[, bibpath] (then a list is returned, only for whole document) # or: r, str (then the output is appended to string or list str) InstallGlobalFunction(GAPDoc2HTML, function(arg) local r, str, linelength, name; r := arg[1]; # first check for the mode if arg[Length(arg)] in ["MathML", "Tth", "MathJax"] then r.mathmode := arg[Length(arg)]; arg := arg{[1..Length(arg)-1]}; else r.mathmode := "Text"; fi; if Length(arg) > 1 then str := arg[2]; else str := []; fi; if r.name = "WHOLEDOCUMENT" then # choose different file name conventions such that these # conversions can coexist if r.mathmode = "MathML" then GAPDoc2HTMLProcs.ext := "_mml.xml"; elif r.mathmode = "Tth" then GAPDoc2HTMLProcs.ext := "_sym.html"; elif r.mathmode = "MathJax" then GAPDoc2HTMLProcs.ext := "_mj.html"; else GAPDoc2HTMLProcs.ext := ".html"; fi; if IsDirectory(str) then r.bibpath := str; else if Length(str) = 0 then str := "."; fi; r.bibpath := Directory(str); fi; str := []; if Length(arg) > 2 and IsString(arg[3]) then GAPDoc2HTMLProcs.RelPath := arg[3]; GAPInfo.MainRootPath := Filtered(GAPInfo.RootPaths, a-> Filename([Directory(a)], "lib/init.g")<>fail)[1]; else Unbind(GAPDoc2HTMLProcs.RelPath); fi; fi; name := r.name; if not IsBound(GAPDoc2HTMLProcs.(name)) then Info(InfoGAPDoc, 1, "#W WARNING: Don't know how to process element ", name, " ---- ignored\n"); else GAPDoc2HTMLProcs.(r.name)(r, str); fi; if r.name ="WHOLEDOCUMENT" then # put final record together and return it return GAPDoc2HTMLProcs.PutFilesTogether(str, r); fi; return str; end); ## recursion through the tree and collecting paragraphs BindGlobal("GAPDoc2HTMLContent", function(r, l) local par, cont, i, count, s, a; # utility: append counter and formatted paragraph to l par := function(s) if Length(s)>0 then s := NormalizedWhitespace(s); if Length(s)>0 then Add(l, count); Add(l, Concatenation("<p>", s, "</p>\n\n")); fi; fi; end; # if not containing paragraphs, then l is string to append to if not r.name in GAPDoc2HTMLProcs.ParEls then for a in r.content do GAPDoc2HTML(a, l); od; return; fi; # otherwise we have to collect text and paragraphs cont := r.content; # checking for alternatives i := 1; while i < Length(cont) do if cont[i].name = "Alt" and GAPDoc2HTMLProcs.AltYes(cont[i]) then cont := Concatenation(cont{[1..i-1]}, cont[i].content, cont{[i+1..Length(cont)]}); else i := i + 1; fi; od; count := r.count; s := ""; for a in cont do if a.count <> count then par(s); count := a.count; s := ""; fi; if a.name in GAPDoc2HTMLProcs.ParEls then # recursively collect paragraphs GAPDoc2HTML(a, l); else # collect text for current paragraph GAPDoc2HTML(a, s); fi; od; if Length(s)>0 then par(s); fi; end); ## write head and foot of HTML file. GAPDoc2HTMLProcs.WHOLEDOCUMENT := function(r, par) local i, pi, t, el, remdiv, math, pos, pos1, str, dat, datbt, bib, b, keys, need, labels, tmp, j, diff, text, a, k, l, ind, opts; ## add paragraph numbers to all nodes of the document AddParagraphNumbersGapDocTree(r); if not IsBound(r.six) then Info(InfoGAPDoc, 1, "#W WARNING: Using labels from section numbers, \n", "#W consider running the converter for the text version first!\n"); fi; ## add a link .root to the root of the document to all nodes ## (then we can collect information about indexing and so on ## there) AddRootParseTree(r); r.index := []; r.toc := ""; r.labels := rec(); r.labeltexts := rec(); if not IsBound(r.bibkeys) then r.bibkeys := []; fi; r.chaptitle := rec(); r.chapsectlinks := rec(); ## checking for processing instructions before the book starts ## example: <?HTML option1="value1" ?> i := 1; pi := rec(); while not r.content[i].name = "Book" do if r.content[i].name = "XMLPI" then t := r.content[i].content; if Length(t) > 4 and t{[1..5]} = "HTML " then el := GetSTag(Concatenation("<", t, ">"), 2); for a in NamesOfComponents(el.attributes) do pi.(a) := el.attributes.(a); od; fi; fi; i := i+1; od; # setup for external conversion of maths (MathML with ttm, tth, ...) if r.mathmode in ["MathML", "Tth"] then r.ConvInput := ""; r.MathCount := 0; fi; ## Now the actual work starts, we give the processing instructions found ## so far to the Book handler. ## We call the Book handler twice and produce index, bibliography, toc ## in between. Info(InfoGAPDoc, 1, "#I First run, collecting cross references, ", "index, toc, bib and so on . . .\n"); # with this flag we avoid unresolved references warnings in first run GAPDoc2HTMLProcs.FirstRun := true; GAPDoc2HTMLProcs.Book(r.content[i], [], pi); GAPDoc2HTMLProcs.FirstRun := false; # now the toc is ready Info(InfoGAPDoc, 1, "#I Table of contents complete.\n"); r.toctext := r.toc; r.chapsectlinkstext := r.chapsectlinks; # utility to remove <div> tags remdiv := function(s) local pos, pos1; pos := PositionSublist(s, "<div"); while pos <> fail do pos1 := Position(s, '>', pos); s := Concatenation(s{[1..pos-1]}, s{[pos1+1..Length(s)]}); pos := PositionSublist(s, "<div"); od; pos := PositionSublist(s, "</div"); while pos <> fail do pos1 := Position(s, '>', pos); s := Concatenation(s{[1..pos-1]}, s{[pos1+1..Length(s)]}); pos := PositionSublist(s, "</div"); od; return s; end; # MathML or Tth translation if r.mathmode in ["MathML", "Tth"] then Info(InfoGAPDoc, 1, "#I translating formulae with \c"); FileString("tempCONV.tex", r.ConvInput); if r.mathmode = "MathML" then Info(InfoGAPDoc, 1, "ttm.\n"); Exec("rm -f tempCONV.html; ttm -L -r tempCONV.tex > tempCONV.html"); elif r.mathmode = "Tth" then Info(InfoGAPDoc, 1, "tth.\n"); Exec("rm -f tempCONV.html; tth -w2 -r -u tempCONV.tex > tempCONV.html"); fi; math := StringFile("tempCONV.html"); # correct the <var> tags math := SubstitutionSublist(math, "< var >", "<var>"); math := SubstitutionSublist(math, "< /var >", "</var>"); math := SubstitutionSublist(math, "<mo><</mo><mi>var</mi><mo>></mo>", "<var>"); math := SubstitutionSublist(math, "<mo><</mo><mo>/</mo><mi>var</mi><mo>></mo>", "</var>"); r.MathList := []; pos := PositionSublist(math, "TeXFormulaeDelim"); while pos <> fail do pos1 := PositionSublist(math, "TeXFormulaeDelim", pos); if pos1 <> fail then Add(r.MathList, remdiv(math{[pos+16..pos1-1]})); else Add(r.MathList, remdiv(math{[pos+16..Length(math)]})); fi; pos := pos1; od; fi; # .index has entries of form [sorttext, subsorttext, numbertext, # entrytext, url[, subtext]] Info(InfoGAPDoc, 1, "#I Producing the index . . .\n"); SortBy(r.index, a-> [a[1],STRING_LOWER(a[2]), List(SplitString(a[3],".-",""), Int)]); str := ""; ind := r.index; k := 1; while k <= Length(ind) do if k > 1 and ind[k][4] = ind[k-1][4] then Append(str, " "); else Append(str, ind[k][4]); fi; if IsBound(ind[k][6]) then if k = 1 or ind[k][4] <> ind[k-1][4] then Append(str, ", "); fi; Append(str, ind[k][6]); elif Length(ind[k][2]) > 0 then if k = 1 or ind[k][4] <> ind[k-1][4] then Append(str, ", "); fi; Append(str, ind[k][2]); fi; l := k; while l <= Length(ind) and ind[l][4] = ind[k][4] and ((IsBound(ind[k][6]) and IsBound(ind[l][6]) and ind[k][6] = ind[l][6]) or (not IsBound(ind[k][6]) and not IsBound(ind[l][6]) and ind[k][2] = ind[l][2])) do Append(str, Concatenation(" <a href=\"", ind[l][5], "\">", ind[l][3], "</a> ")); l := l+1; od; Append(str, "<br />\n"); k := l; od; r.indextext := str; if Length(r.bibkeys) > 0 then GAPDocAddBibData(r); Info(InfoGAPDoc, 1, "#I Writing bibliography . . .\n"); if r.root.mathmode = "MathJax" then opts := rec(MathJax := true); else opts := rec(); fi; need := List(r.bibentries, a-> RecBibXMLEntry(a, "HTML", r.bibstrings, opts)); # copy the unique labels for a in [1..Length(need)] do need[a].key := r.biblabels[a]; od; text := ""; for a in need do # an anchor for links from the citations Append(text, Concatenation("\n<p><a id=\"biB", a.Label, "\" name=\"biB", a.Label, "\"></a></p>\n")); Append(text, StringBibAsHTML(a, false)); od; r.bibtext := text; fi; # second run r.index := []; Info(InfoGAPDoc, 1, "#I Second run through document . . .\n"); GAPDoc2HTMLProcs.Book(r.content[i], par, pi); for a in ["MathList", "MathCount", "index", "toc"] do Unbind(r.(a)); od; ## remove the links to the root ??? ## RemoveRootParseTree(r); end; ## comments and processing instructions are in general ignored GAPDoc2HTMLProcs.XMLPI := function(r, str) return; end; GAPDoc2HTMLProcs.XMLCOMMENT := function(r, str) return; end; # two utilities for attribute values like labels or text with special # XML (or LaTeX) characters which gets printed GAPDoc2HTMLProcs.EscapeAttrVal := function(str) str := SubstitutionSublist(str, "&", "&"); str := SubstitutionSublist(str, "<", "<"); str := SubstitutionSublist(str, ">", ">"); return str; end; # do nothing with Ignore GAPDoc2HTMLProcs.Ignore := function(arg) end; # just process content GAPDoc2HTMLProcs.Book := function(r, par, pi) # copy the name of the book to the root r.root.bookname := r.attributes.Name; GAPDoc2HTMLContent(r, par); end; ## Body is sectioning element GAPDoc2HTMLProcs.Body := GAPDoc2HTMLContent; ## the title page, the most complicated looking function GAPDoc2HTMLProcs.TitlePage := function(r, par) local strn, l, s, a, aa, cont, ss; strn := "<div class=\"pcenter\">\n"; # title l := Filtered(r.content, a-> a.name = "Title"); s := ""; GAPDoc2HTMLContent(l[1], s); s := Concatenation("\n<h1>", NormalizedWhitespace(s), "</h1>\n\n"); Append(strn, s); # subtitle l := Filtered(r.content, a-> a.name = "Subtitle"); if Length(l)>0 then s := ""; GAPDoc2HTMLContent(l[1], s); s := Concatenation("\n<h2>", NormalizedWhitespace(s), "</h2>\n\n"); Append(strn, s); fi; # version l := Filtered(r.content, a-> a.name = "Version"); if Length(l)>0 then s := "<p>"; GAPDoc2HTMLContent(l[1], s); while Length(s)>0 and s[Length(s)] in WHITESPACE do Unbind(s[Length(s)]); od; Append(s, "</p>\n\n"); Append(strn, s); fi; # date l := Filtered(r.content, a-> a.name = "Date"); if Length(l)>0 then s := "<p>"; GAPDoc2HTMLContent(l[1], s); Append(strn, s); Append(strn, "</p>\n\n"); fi; Append(strn, "</div>\n"); # an extra comment l := Filtered(r.content, a-> a.name = "TitleComment"); if Length(l) > 0 then s := "<p>"; GAPDoc2HTMLContent(l[1], s); Append(s, "</p>\n"); Append(strn, s); fi; # author name(s) l := Filtered(r.content, a-> a.name = "Author"); for a in l do s := "<p><b>"; aa := ShallowCopy(a); aa.content := Filtered(a.content, b-> not b.name in ["Email", "Homepage", "Address"]); GAPDoc2HTMLContent(aa, s); Append(strn, s); Append(strn, "</b>\n"); cont := List(a.content, b-> b.name); if "Email" in cont then s := ""; GAPDoc2HTML(a.content[Position(cont, "Email")], s); s := NormalizedWhitespace(s); Append(strn, Concatenation("<br />", GAPDocTexts.d.Email, ": ", s, "\n")); fi; if "Homepage" in cont then s := ""; GAPDoc2HTML(a.content[Position(cont, "Homepage")], s); s := NormalizedWhitespace(s); Append(strn, Concatenation("<br />", GAPDocTexts.d.Homepage, ": ", s, "\n")); fi; if "Address" in cont then s := ""; GAPDoc2HTMLContent(a.content[Position(cont, "Address")], s); s := NormalizedWhitespace(s); Append(strn, Concatenation("<br />", GAPDocTexts.d.Address, ": <br />", s, "\n")); fi; Append(strn, "</p>"); od; Append(strn, "\n\n"); Add(par, r.count); Add(par, strn); # an Address element in title page l := Filtered(r.content, a-> a.name = "Address"); if Length(l) > 0 then s := ""; GAPDoc2HTMLContent(l[1], s); s := NormalizedWhitespace(s); Append(strn, Concatenation("<p><b>", GAPDocTexts.d.Address, ":</b><br />\n", s, "</p>\n")); fi; # abstract, copyright page, acknowledgements, colophon for ss in ["Abstract", "Copyright", "Acknowledgements", "Colophon" ] do l := Filtered(r.content, a-> a.name = ss); if Length(l)>0 then Add(par, l[1].count); Add(par, Concatenation("<h3>", GAPDocTexts.d.(ss), "</h3>\n")); GAPDoc2HTMLContent(l[1], par); fi; od; end; ## these produce text for an URL ## arg: r, str[, pre] GAPDoc2HTMLProcs.Link := GAPDoc2HTMLContent; GAPDoc2HTMLProcs.LinkText := GAPDoc2HTMLContent; GAPDoc2HTMLProcs.URL := function(arg) local r, str, pre, rr, txt, s; r := arg[1]; str := arg[2]; if Length(arg)>2 then pre := arg[3]; else pre := ""; fi; rr := First(r.content, a-> a.name = "LinkText"); if rr <> fail then txt := ""; GAPDoc2HTML(rr, txt); rr := First(r.content, a-> a.name = "Link"); if rr = fail then Info(InfoGAPDoc, 1, "#W missing <Link> element for text ", txt, "\n"); s := "MISSINGLINK"; else s := ""; GAPDoc2HTMLContent(rr, s); fi; else s := ""; GAPDoc2HTMLContent(r, s); if IsBound(r.attributes.Text) then txt := r.attributes.Text; else txt := s; fi; fi; Append(str, Concatenation(GAPDoc2HTMLProcs.TextAttr.URL[1], "<a href=\"", pre, s, "\">", txt, "</a>")); Append(str, GAPDoc2HTMLProcs.TextAttr.URL[2]); end; GAPDoc2HTMLProcs.Homepage := GAPDoc2HTMLProcs.URL; GAPDoc2HTMLProcs.Email := function(r, str) # we add the `mailto:' phrase GAPDoc2HTMLProcs.URL(r, str, "mailto:"); end; ## utility: generate a chapter or (sub)section-number string GAPDoc2HTMLProcs.SectionNumber := function(count, sect) local res; res := ""; if IsString(count[1]) or count[1]>0 then Append(res, String(count[1])); fi; if sect="Chapter" or sect="Appendix" then return res; fi; Add(res, '.'); if count[2]>0 then Append(res, String(count[2])); fi; if sect="Section" then return res; fi; if count[3]>0 then Append(res, Concatenation("-", String(count[3]))); fi; return res; end; ## utility: generate a chapter or (sub)section-number string GAPDoc2HTMLProcs.SectionLabel := function(r, count, sect) local res, a; if IsString(count[1]) or count[1]>0 then res := Concatenation("chap", String(count[1]), GAPDoc2HTMLProcs.ext); else res := Concatenation("chap0", GAPDoc2HTMLProcs.ext); fi; res := [res, ""]; if not IsBound(r.root.six) then if sect="Chapter" then return res; fi; Append(res[2], Concatenation("s", String(count[2]))); Append(res[2], Concatenation("ss", String(count[3]))); return res; else ## a := First(r.root.six, a-> a[3] = count{[1..3]}); a := PositionSet(r.root.sixcount, count{[1..3]}); if a <> fail then a := r.root.six[r.root.sixindex[a]]; fi; if a = fail or not IsBound(a[7]) then return GAPDoc2HTMLProcs.SectionLabel(rec(root:=rec()), count, sect); else Append(res[2], a[7]); return res; fi; fi; end; ## the sectioning commands are just translated and labels are ## generated, if given as attribute GAPDoc2HTMLProcs.ChapSect := function(r, par, sect) local num, posh, s, ind, strn, lab, types, nrs, hord, a, pos, l, i; types := ["Chapter", "Appendix", "Section", "Subsection"]; nrs := ["3", "3", "4", "5"]; hord := nrs[Position(types, sect)]; Add(par, r.count); # if available, start with links to sections in chapter/appendix if sect in ["Chapter", "Appendix"] then if IsBound(r.root.chapsectlinkstext) and IsBound(r.root.chapsectlinkstext.(r.count[1])) then Add(par, r.root.chapsectlinkstext.(r.count[1])); fi; fi; if par[Length(par)] = r.count then Add(par, ""); fi; # section number as string num := GAPDoc2HTMLProcs.SectionNumber(r.count, sect); # and as anchor lab := GAPDoc2HTMLProcs.SectionLabel(r, r.count, "Subsection"); lab := Concatenation(lab[1], "#", lab[2]); # the heading posh := Position(List(r.content, a-> a.name), "Heading"); if posh <> fail then s := ""; # first the .six entry GAPDoc2HTMLProcs.Heading1(r.content[posh], s); if hord = "3" then r.root.chaptitle.(r.count[1]) := s; fi; # label entry, if present if IsBound(r.attributes.Label) then r.root.labels.(r.attributes.Label) := [num, lab]; r.root.labeltexts.(r.attributes.Label) := s; fi; # the heading text Append(par[Length(par)], Concatenation("\n<h", hord, ">", num, " ", s, "</h", hord, ">\n\n")); # table of contents entry s := Concatenation( num, " ", s); if sect in ["Chapter", "Appendix"] then if r.count[1] >= 1 then ind := "<div class=\"ContChap\">"; fi; elif sect="Section" then ind := ""; if r.count[2] >= 1 then Append(ind, "<div class=\"ContSect\">"); fi; Append(ind, "<span class=\"tocline\"><span class=\"nocss\"> </span>"); elif sect="Subsection" then ind := "<span class=\"ContSS\"><br /><span class=\"nocss\"> </span>"; else ind := ""; fi; Append(r.root.toc, Concatenation(ind, "<a href=\"", lab, "\">", s, "</a>\n")); if sect="Section" then Append(r.root.toc, "</span>\n<div class=\"ContSSBlock\">\n"); fi; fi; # the actual content GAPDoc2HTMLContent(r, par); # possibly close <div> or <span> in content if posh <> fail then if sect in ["Chapter", "Appendix" ] then Append(r.root.toc, "</div>\n"); elif sect="Section" then # remove last line if no subsections l := Length(r.root.toc); if r.root.toc{[l-25..l]} = "<div class=\"ContSSBlock\">\n" then for i in [0..25] do Unbind(r.root.toc[l-i]); od; Append(r.root.toc, "</div>\n"); else Append(r.root.toc, "</div></div>\n"); fi; elif sect="Subsection" then Append(r.root.toc, "</span>\n"); fi; fi; # if in chapter, also use the section links in top of page if sect in ["Chapter", "Appendix"] then a := Reversed(r.root.toc); pos := PositionSublist(a, Reversed("<div class=\"ContChap\">")); a := Reversed(a{[1..pos-1]}); r.root.chapsectlinks.(r.count[1]) := Concatenation( "<div class=\"ChapSects\">", a); fi; end; ## this really produces the content of the heading GAPDoc2HTMLProcs.Heading1 := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "Heading"); end; ## and this ignores the heading (for simpler recursion) GAPDoc2HTMLProcs.Heading := function(r, str) end; GAPDoc2HTMLProcs.Chapter := function(r, par) GAPDoc2HTMLProcs.ChapSect(r, par, "Chapter"); end; GAPDoc2HTMLProcs.Appendix := function(r, par) GAPDoc2HTMLProcs.ChapSect(r, par, "Appendix"); end; GAPDoc2HTMLProcs.Section := function(r, par) GAPDoc2HTMLProcs.ChapSect(r, par, "Section"); end; GAPDoc2HTMLProcs.Subsection := function(r, par) GAPDoc2HTMLProcs.ChapSect(r, par, "Subsection"); end; ## table of contents, just puts "TOC" in first run GAPDoc2HTMLProcs.TableOfContents := function(r, par) Add(par, r.count); if IsBound(r.root.toctext) then Add(par, Concatenation("\n<div class=\"contents\">\n<h3>", GAPDocTexts.d.Contents, "<a id=\"contents\" name=\"contents\"></a></h3>\n\n", r.root.toctext, "<br />\n</div>\n")); else Add(par,"<p>TOC\n-----------</p>\n\n"); fi; end; ## bibliography, just "BIB" in first run, store databases in root GAPDoc2HTMLProcs.Bibliography := function(r, par) local s; # add references to TOC Append(r.root.toc, Concatenation("<div class=\"ContChap\"><a href=\"chapBib", GAPDoc2HTMLProcs.ext, "\"><span class=\"Heading\">", GAPDocTexts.d.References, "</span></a></div>\n")); r.root.bibdata := r.attributes.Databases; if IsBound(r.attributes.Style) then r.root.bibstyle := r.attributes.Style; fi; Add(par, r.count); if IsBound(r.root.bibtext) then Add(par, Concatenation("\n<h3>", GAPDocTexts.d.References, "</h3>\n\n", r.root.bibtext, "<p> </p>\n\n")); else Add(par,"<p>BIB\n-----------</p>\n"); fi; end; GAPDoc2HTMLProcs.PCDATAFILTER := function(r, str) local s, a; s := r.content; if not IsBound(r.HTML) and (Position(s, '<') <> fail or Position(s, '&') <> fail or Position(s, '>') <> fail) then for a in s do if a='<' then Append(str, "<"); elif a='&' then Append(str, "&"); elif a='>' then Append(str, ">"); else Add(str, a); fi; od; else Append(str, s); fi; end; # and without filter (e.g., for collecting formulae GAPDoc2HTMLProcs.PCDATANOFILTER := function(r, str) Append(str, r.content); end; GAPDoc2HTMLProcs.PCDATAFILTER; ## default is with filter GAPDoc2HTMLProcs.PCDATA := GAPDoc2HTMLProcs.PCDATAFILTER; ## end of paragraph (end with double newline) GAPDoc2HTMLProcs.P := function(r, str) # nothing to do, the "<p>" are added in main loop (GAPDoc2HTML) end; GAPDoc2HTMLProcs.Br := function(r, str) Append(str, "<br />\n"); end; ## wrapping text attributes GAPDoc2HTMLProcs.WrapAttr := function(r, str, a) local s, tt; s := ""; GAPDoc2HTMLContent(r, s); tt := GAPDoc2HTMLProcs.TextAttr.(a); Append(str, Concatenation(tt[1], s, tt[2])); end; ## GAP keywords GAPDoc2HTMLProcs.K := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "K"); end; ## buttons GAPDoc2HTMLProcs.B := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "B"); end; ## verbatim GAP code GAPDoc2HTMLProcs.C := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "C"); end; ## file names GAPDoc2HTMLProcs.F := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "F"); end; ## argument names (same as Arg) GAPDoc2HTMLProcs.A := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "Arg"); end; GAPDoc2HTMLProcs.MathConvHelper := function(r, str, db, de) local s, x; if IsBound(r.root.MathList) then # conversion already available r.root.MathCount := r.root.MathCount + 1; Append(str, r.root.MathList[r.root.MathCount]); else # add to input for converter if IsString(r.content) then s := r.content; else s := ""; GAPDoc2HTMLProcs.PCDATA := GAPDoc2HTMLProcs.PCDATANOFILTER; for x in r.content do GAPDoc2HTML(x, s); od; GAPDoc2HTMLProcs.PCDATA := GAPDoc2HTMLProcs.PCDATAFILTER; fi; s := Concatenation("TeXFormulaeDelim", db, s, de); Append(r.root.ConvInput, s); Append(str, "FORMULA"); fi; end; ## simple maths, here we try to substitute TeX command to something which ## looks ok in text mode GAPDoc2HTMLProcs.M := function(r, str) local s, ss, save; if r.root.mathmode in ["MathML", "Tth"] then GAPDoc2HTMLProcs.MathConvHelper(r, str, "$", "$"); return; fi; s := ""; GAPDoc2HTMLProcs.PCDATA := GAPDoc2HTMLProcs.PCDATANOFILTER; # a hack, since we want to allow <A> in formulae save := GAPDoc2HTMLProcs.TextAttr.Arg; GAPDoc2HTMLProcs.TextAttr.Arg := ["TEXTaTTRvARBEGIN", "TEXTaTTRvAREND"]; GAPDoc2HTMLContent(r, s); GAPDoc2HTMLProcs.TextAttr.Arg := save; GAPDoc2HTMLProcs.PCDATA := GAPDoc2HTMLProcs.PCDATAFILTER; ss := ""; if r.root.mathmode = "MathJax" then s := Concatenation("\\(",s,"\\)"); GAPDoc2HTMLProcs.PCDATAFILTER(rec(content := s), ss); ss := SubstitutionSublist(ss, "TEXTaTTRvARBEGIN", "\\textit{"); ss := SubstitutionSublist(ss, "TEXTaTTRvAREND", "}"); else s := TextM(s); GAPDoc2HTMLProcs.PCDATAFILTER(rec(content := s), ss); ss := SubstitutionSublist(ss, "TEXTaTTRvARBEGIN", save[1]); ss := SubstitutionSublist(ss, "TEXTaTTRvAREND", save[2]); fi; Append(str, WrapTextAttribute(ss, GAPDoc2HTMLProcs.TextAttr.M)); end; ## in HTML this is shown in TeX format GAPDoc2HTMLProcs.Math := function(r, str) local s; if r.root.mathmode in ["MathML", "Tth"] then GAPDoc2HTMLProcs.MathConvHelper(r, str, "$", "$"); return; fi; if r.root.mathmode = "MathJax" then s := ""; GAPDoc2HTMLProcs.M(r, s); Append(str, s); return; fi; s := ""; GAPDoc2HTMLContent(r, s); Append(str, WrapTextAttribute(s, GAPDoc2HTMLProcs.TextAttr.Math)); end; ## displayed maths (also in TeX format, but centered paragraph in itself) GAPDoc2HTMLProcs.Display := function(r, par) local s, a, str; if r.root.mathmode in ["MathML", "Tth"] then str := ""; GAPDoc2HTMLProcs.MathConvHelper(r, str, "\n\\[", "\\]\n\n"); Add(par, r.count); Add(par, Concatenation("<table class=\"display\"><tr>", "<td class=\"display\">", str, "</td></tr></table>\n")); return; fi; s := ""; for a in r.content do GAPDoc2HTML(a, s); od; if r.root.mathmode = "MathJax" then Add(par, r.count); Add(par, Concatenation("<p class=\"center\">\\[", s, "\\]</p>\n\n")); return; fi; if IsBound(r.attributes.Mode) and r.attributes.Mode = "M" then s := TextM(s); fi; s := Concatenation("<p class=\"pcenter\">", s, "</p>\n\n"); Add(par, r.count); Add(par, s); end; ## emphazised text GAPDoc2HTMLProcs.Emph := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "Emph"); end; ## quoted text GAPDoc2HTMLProcs.Q := function(r, str) Append(str, "\""); GAPDoc2HTMLContent(r, str); Append(str, "\""); end; ## Package names GAPDoc2HTMLProcs.Package := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "Package"); end; ## menu items GAPDoc2HTMLProcs.I := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "I"); end; GAPDoc2HTMLProcs.AddColorPromptMarkup := function(cont) local patt, batt, iatt, res, pos, s, rows; patt := GAPDoc2HTMLProcs.TextAttr.GAPprompt; batt := GAPDoc2HTMLProcs.TextAttr.GAPbrkprompt; iatt := GAPDoc2HTMLProcs.TextAttr.GAPinput; res := ""; rows := SplitString(cont, "\n", ""); for s in rows do if Length(s) > 7 and s{[1..8]} = "gap> " then Append(res, Concatenation(WrapTextAttribute("gap>", patt), " ", WrapTextAttribute(s{[9..Length(s)]}, iatt))); elif Length(s) > 4 and s{[1..5]} = "> " then Append(res, Concatenation(WrapTextAttribute(">", patt), " ", WrapTextAttribute(s{[6..Length(s)]}, iatt))); elif Length(s) > 2 and s{[1..3]} = "brk" then pos := Position(s, ' '); if pos <> fail then Append(res, Concatenation(WrapTextAttribute(s{[1..pos-1]}, batt), " ", WrapTextAttribute(s{[pos+1..Length(s)]}, iatt))); else Append(res, WrapTextAttribute(s, batt)); fi; else Append(res, WrapTextAttribute(s, ["",""])); fi; Add(res, '\n'); od; if Length(cont) > 0 and cont[Length(cont)] <> '\n' then Unbind(res[Length(res)]); fi; return res; end; GAPDoc2HTMLProcs.ExampleLike := function(r, par, label, colorpr) local str, cont, a, s; str := "\n<div class=\"example\"><pre>"; cont := ""; for a in r.content do # here we try to avoid reformatting if IsString(a.content) then GAPDoc2HTMLProcs.PCDATA(a, cont); else s := ""; GAPDoc2HTML(a, s); Append(cont, s); fi; od; if colorpr then cont := GAPDoc2HTMLProcs.AddColorPromptMarkup(cont); fi; Append(str, cont); Append(str, "</pre></div>\n\n"); Add(par, r.count); Add(par, str); end; ## log of session and GAP code is typeset the same way as <Example> GAPDoc2HTMLProcs.Example := function(r, par) GAPDoc2HTMLProcs.ExampleLike(r, par, "Example", true); end; GAPDoc2HTMLProcs.Log := function(r, par) GAPDoc2HTMLProcs.ExampleLike(r, par, "Log", true); end; GAPDoc2HTMLProcs.Listing := function(r, par) GAPDoc2HTMLProcs.ExampleLike(r, par, "Code", false); end; GAPDoc2HTMLProcs.Verb := function(r, par) local str, cont, a, s; str := "\n<pre class=\"normal\">\n"; cont := ""; for a in r.content do # here we try to avoid reformatting if IsString(a.content) then GAPDoc2HTMLProcs.PCDATA(a, cont); else s := ""; GAPDoc2HTML(a, s); Append(cont, s); fi; od; Append(str, cont); Append(str, "\n</pre>\n\n"); Add(par, r.count); Add(par, str); end; ## explicit labels GAPDoc2HTMLProcs.Label := function(r, str) local num, lab; num := GAPDoc2HTMLProcs.SectionNumber(r.count, "Subsection"); lab := GAPDoc2HTMLProcs.SectionLabel(r, r.count, "Subsection"); r.root.labels.(r.attributes.Name) := [num, Concatenation(lab[1],"#",lab[2])]; end; ## citations GAPDoc2HTMLProcs.Cite := function(r, str) local key, pos; key := r.attributes.Key; pos := Position(r.root.bibkeys, key); if pos = fail then Add(r.root.bibkeys, key); Append(str, Concatenation("[?", key, "?]")); elif not IsBound(r.root.biblabels) then Append(str, Concatenation("[?", key, "?]")); else # here we include a link to the corresponding entry in bibliography Append(str, Concatenation("<a href=\"chapBib", GAPDoc2HTMLProcs.ext, "#biB", key, "\">[", r.root.biblabels[pos])); if IsBound(r.attributes.Where) then Append(str, ", "); Append(str, r.attributes.Where); fi; Append(str, "]</a>"); fi; end; ## explicit index entries GAPDoc2HTMLProcs.Subkey := GAPDoc2HTMLContent; GAPDoc2HTMLProcs.Index := function(r, str) local s, sub, entry, url, a; s := ""; sub := ""; for a in r.content do if a.name = "Subkey" then GAPDoc2HTML(a, sub); else GAPDoc2HTML(a, s); fi; od; NormalizeWhitespace(s); NormalizeWhitespace(sub); if IsBound(r.attributes.Key) then entry := [STRING_LOWER(r.attributes.Key)]; else entry := [STRING_LOWER(s)]; fi; if IsBound(r.attributes.Subkey) then Add(entry, r.attributes.Subkey); else Add(entry, sub); fi; Add(entry, GAPDoc2HTMLProcs.SectionNumber(r.count, "Subsection")); Add(entry, s); url := GAPDoc2HTMLProcs.SectionLabel(r, r.count, "Subsection"); Add(entry, Concatenation(url[1],"#",url[2])); if Length(sub) > 0 then Add(entry, sub); fi; Add(r.root.index, entry); end; ## helper to add markup to the args GAPDoc2HTMLProcs.WrapArgs := function(argstr) local res, noletter, c; res := ""; noletter := true; for c in argstr do if noletter then if not c in ", []" then noletter := false; Append(res, GAPDoc2HTMLProcs.TextAttr.Arg[1]); fi; elif c in ", []" then noletter := true; Append(res, GAPDoc2HTMLProcs.TextAttr.Arg[2]); fi; Add(res, c); od; if not noletter then Append(res, GAPDoc2HTMLProcs.TextAttr.Arg[2]); fi; return res; end; ## this produces an implicit index entry and a label entry GAPDoc2HTMLProcs.LikeFunc := function(r, par, typ) local attr, s, name, lab, url; attr := GAPDoc2HTMLProcs.TextAttr.Func; name := GAPDoc2HTMLProcs.EscapeAttrVal(r.attributes.Name); s := Concatenation(attr[1], "‣ ", name, attr[2]); if IsBound(r.attributes.Arg) then Append(s, Concatenation("( ", GAPDoc2HTMLProcs.WrapArgs( GAPDoc2HTMLProcs.EscapeAttrVal( NormalizedArgList(r.attributes.Arg))), " )")); fi; # index entry attr := GAPDoc2HTMLProcs.TextAttr.Func; url := GAPDoc2HTMLProcs.SectionLabel(r, r.count, "Subsection"); url := Concatenation(url[1],"#",url[2]); if IsBound(r.attributes.Label) then lab := r.attributes.Label; else lab := ""; fi; Add(r.root.index, [STRING_LOWER(name), lab, GAPDoc2HTMLProcs.SectionNumber(r.count, "Subsection"), Concatenation(attr[1], name, attr[2]), url]); # label (if not given, the default is the Name) if IsBound(r.attributes.Label) then if IsBound(r.attributes.Name) then lab := Concatenation(r.attributes.Name, " (", r.attributes.Label, ")"); else lab := r.attributes.Label; fi; else lab := r.attributes.Name; fi; GAPDoc2HTMLProcs.Label(rec(count := r.count, attributes := rec(Name := lab), root := r.root), par); # adding hint about the type of the variable s := Concatenation("<div class=\"func\"><table class=\"func\" ", "width=\"100%\">", "<tr><td class=\"tdleft\">", s, "</td><td class=\"tdright\">( ", typ, " )</td></tr></table></div>\n"); Add(par, r.count); Add(par, s); end; GAPDoc2HTMLProcs.Func := function(r, str) GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.Func); end; GAPDoc2HTMLProcs.Oper := function(r, str) GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.Oper); end; GAPDoc2HTMLProcs.Constr := function(r, str) GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.Constr); end; GAPDoc2HTMLProcs.Meth := function(r, str) GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.Meth); end; GAPDoc2HTMLProcs.Filt := function(r, str) # r.attributes.Type could be "representation", "category", ... if IsBound(r.attributes.Type) then GAPDoc2HTMLProcs.LikeFunc(r, str, LowercaseString(r.attributes.Type)); else GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.Filt); fi; end; GAPDoc2HTMLProcs.Prop := function(r, str) GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.Prop); end; GAPDoc2HTMLProcs.Attr := function(r, str) GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.Attr); end; GAPDoc2HTMLProcs.Var := function(r, str) GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.Var); end; GAPDoc2HTMLProcs.Fam := function(r, str) GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.Fam); end; GAPDoc2HTMLProcs.InfoClass := function(r, str) GAPDoc2HTMLProcs.LikeFunc(r, str, GAPDocTexts.d.InfoClass); end; ## using the HelpData(.., .., "ref") interface GAPDoc2HTMLProcs.ResolveExternalRef := function(bookname, label, nr) local info, match, res; info := HELP_BOOK_INFO(bookname); if info = fail then return fail; fi; match := Concatenation(HELP_GET_MATCHES(info, SIMPLE_STRING(label), true)); if Length(match) < nr then return fail; fi; res := GetHelpDataRef(info, match[nr][2]); res[1] := SubstitutionSublist(res[1], " (not loaded): ", ": ", "one"); return res; end; ## helper for external URLs, remove GAPDocStyle part and maybe add "_mj" GAPDoc2HTMLProcs.AdjustExtURL := function(r, url) local pos, pos2, res, fnam, mjnam; pos := PositionSublist(url, "?GAPDocStyle="); if pos <> fail then pos2 := Position(url, '#', pos); if pos2 = fail then pos2 := Length(url)+1; fi; res := url{[1..pos-1]}; Append(res, url{[pos2..Length(url)]}); else res :=url; fi; if r.root.mathmode = "MathJax" then pos := Position(res, '#'); if pos <> fail then fnam := res{[1..pos-1]}; else pos := Length(res)+1; fnam := res; fi; if Length(fnam) >= 5 and fnam{[Length(fnam)-4..Length(fnam)]} = ".html" then mjnam := Concatenation(fnam{[1..Length(fnam)-5]}, "_mj.html"); if IsExistingFile(mjnam) then res := Concatenation(mjnam, res{[pos..Length(res)]}); fi; fi; fi; return res; end; ## a try to make it somewhat shorter than for the Text and LaTeX conversions GAPDoc2HTMLProcs.Ref := function(r, str) local int, txt, ref, lab, attr, sectlike, rattr; rattr := GAPDoc2HTMLProcs.TextAttr.Ref; int := Difference(NamesOfComponents(r.attributes), ["BookName", "Label", "Style"]); if Length(int)>0 and int[1] <> "Text" then lab := r.attributes.(int[1]); else lab := ""; fi; if IsBound(r.attributes.Label) then if Length(lab) > 0 then lab := Concatenation(lab, " (", r.attributes.Label, ")"); else lab := r.attributes.Label; fi; fi; if IsBound(r.attributes.BookName) then ref := GAPDoc2HTMLProcs.ResolveExternalRef(r.attributes.BookName, lab, 1); if ref <> fail and ref[6] <> fail then ref[6] := GAPDoc2HTMLProcs.AdjustExtURL(r, ref[6]); if IsBound(GAPDoc2HTMLProcs.RelPath) and PositionSublist(ref[6], GAPInfo.MainRootPath) = 1 then ref[6] := Concatenation(GAPDoc2HTMLProcs.RelPath, "/", ref[6]{[Length(GAPInfo.MainRootPath)+1..Length(ref[6])]}); fi; if IsBound(r.attributes.Style) and r.attributes.Style = "Number" then ref := Concatenation("<a href=\"", ref[6], "\">",rattr[1], r.attributes.BookName, " ", ref[2], rattr[2],"</a>"); elif IsBound(r.attributes.Text) then ref := Concatenation("<a href=\"", ref[6], "\">", rattr[1], r.attributes.Text, rattr[2], "</a>"); else ref := Concatenation("<a href=\"", ref[6], "\">", rattr[1], ref[1], rattr[2], "</a>"); fi; elif ref <> fail then ref := Concatenation(rattr[1], ref[1], rattr[2]); else if GAPDoc2HTMLProcs.FirstRun <> true then Info(InfoGAPDoc, 1, "#W WARNING: non resolved reference: ", r.attributes, "\n"); fi; ref := Concatenation(rattr[1], "???", rattr[2]); fi; else if IsBound(r.root.labels.(lab)) then if not IsBound(r.attributes.Text) then ref := Concatenation("<a href=\"", r.root.labels.(lab)[2], "\">", rattr[1], r.root.labels.(lab)[1], rattr[2], "</a>"); else ref := Concatenation("<a href=\"", r.root.labels.(lab)[2], "\">", rattr[1], r.attributes.Text, rattr[2], "</a>"); fi; else if GAPDoc2HTMLProcs.FirstRun <> true then Info(InfoGAPDoc, 1, "#W WARNING: non resolved reference: ", r.attributes, "\n"); fi; ref := Concatenation(rattr[1], "???", rattr[2]); fi; fi; if Length(int)>0 and int[1] in [ "Func", "Oper", "Constr", "Meth", "Filt", "Prop", "Attr", "Var", "Fam", "InfoClass" ] then attr := GAPDoc2HTMLProcs.TextAttr.Func; txt := Concatenation(attr[1], GAPDoc2HTMLProcs.EscapeAttrVal(r.attributes.(int[1])), attr[2]); # avoid reference to current subsection if IsBound(r.attributes.BookName) or not IsBound(r.root.labels.(lab)) or GAPDoc2HTMLProcs.SectionNumber(r.count, "Subsection") <> r.root.labels.(lab)[1] then Append(txt, Concatenation(" (", ref, ")")); fi; elif Length(int)>0 and int[1] in [ "Sect", "Subsect", "Chap", "Appendix"] and IsBound(r.attributes.Style) and r.attributes.Style = "Text" then if IsBound(r.root.labeltexts.(lab)) then txt := Concatenation("<a href=\"",r.root.labels.(lab)[2], "\">",rattr[1],r.root.labeltexts.(lab),rattr[2],"</a>"); else if GAPDoc2HTMLProcs.FirstRun <> true then Info(InfoGAPDoc, 1, "#W WARNING: non resolved reference: ", r.attributes, "\n"); fi; txt := Concatenation(rattr[1], "???", rattr[2]); fi; else txt := ref; fi; Append(str, txt); end; GAPDoc2HTMLProcs.Description := GAPDoc2HTMLContent; GAPDoc2HTMLProcs.Returns := function(r, par) local l; l := []; GAPDoc2HTMLContent(r, l); if Length(l) > 0 then l[2] := Concatenation("<p>", GAPDocTexts.d.Returns, ": ", l[2]{[4..Length(l[2])]}); fi; Append(par, l); end; GAPDoc2HTMLProcs.ManSection := function(r, par) local strn, funclike, i, num, s, lab, ind; # if there is a Heading then handle as subsection if ForAny(r.content, a-> IsRecord(a) and a.name = "Heading") then GAPDoc2HTMLProcs.ChapSect(r, par, "Subsection"); return; fi; strn := ""; # function like elements funclike := [ "Func", "Oper", "Constr", "Meth", "Filt", "Prop", "Attr", "Var", "Fam", "InfoClass" ]; # heading comes from name of first function like element i := 1; while not r.content[i].name in funclike do i := i+1; od; num := GAPDoc2HTMLProcs.SectionNumber(r.count, "Subsection"); s := Concatenation(num, " ", GAPDoc2HTMLProcs.EscapeAttrVal(r.content[i].attributes.Name)); Add(par, r.count); # avoid MathJax interpretation in \(, \[ outside <code> if '\\' in s then s := Concatenation("<code>",s,"</code>"); fi; Add(par, Concatenation("\n<h5>", s, "</h5>\n\n")); # append to TOC as subsection lab := GAPDoc2HTMLProcs.SectionLabel(r, r.count, "Subsection"); lab := Concatenation(lab[1], "#", lab[2]); ind := "<span class=\"ContSS\"><br /><span class=\"nocss\"> </span>"; Append(r.root.toc, Concatenation(ind, "<a href=\"", lab, "\">", s, "</a></span>\n")); # label entry, if present if IsBound(r.attributes.Label) then r.root.labels.(r.attributes.Label) := [num, lab]; r.root.labeltexts.(r.attributes.Label) := s; fi; GAPDoc2HTMLContent(r, par); end; GAPDoc2HTMLProcs.Mark := function(r, str) GAPDoc2HTMLProcs.WrapAttr(r, str, "Mark"); end; GAPDoc2HTMLProcs.Item := function(r, str) GAPDoc2HTMLContent(r, str); end; # must do the complete formatting GAPDoc2HTMLProcs.List := function(r, par) local s, a, ss, i; s := "\n"; if "Mark" in List(r.content, a-> a.name) then # a <dl> list Append(s, "<dl>\n"); for a in r.content do if a.name = "Mark" then ss := ""; GAPDoc2HTMLProcs.Mark(a, ss); Append(s, Concatenation("<dt>", ss, "</dt>\n")); elif a.name = "Item" then ss := ""; GAPDoc2HTMLProcs.Item(a, ss); ss := Concatenation(Filtered(ss, IsString)); ss := Concatenation("<dd>", ss, "</dd>\n"); Append(s, ss); fi; od; Append(s, "</dl>\n"); else # a <ul> list Append(s, "<ul>\n"); for a in r.content do if a.name = "Item" then ss := ""; GAPDoc2HTMLProcs.Item(a, ss); ss := Concatenation(Filtered(ss, IsString)); Append(s, Concatenation("<li>", ss, "</li>\n")); fi; od; Append(s, "</ul>\n"); fi; Add(par, r.count); Add(par, s); end; ## and this is an <ol> list GAPDoc2HTMLProcs.Enum := function(r, par) local s, i, a, ss, num; s := ""; # a <ul> list Append(s, "<ol>\n"); for a in r.content do if a.name = "Item" then ss := ""; GAPDoc2HTMLProcs.Item(a, ss); if not IsString(ss) then ss := Concatenation(Filtered(ss, IsString)); fi; Append(s, Concatenation("<li>", ss, "</li>\n")); fi; od; Append(s, "</ol>\n"); Add(par, r.count); Add(par, s); end; GAPDoc2HTMLProcs.TheIndex := function(r, par) local s; # add index to TOC Append(r.root.toc, Concatenation("<div class=\"ContChap\"><a href=\"chapInd", GAPDoc2HTMLProcs.ext, "\"><span class=\"Heading\">", GAPDocTexts.d.Index, "</span></a></div>\n")); # the text, if available Add(par, r.count); if IsBound(r.root.indextext) then Add(par, Concatenation("\n<div class=\"index\">\n<h3>", GAPDocTexts.d.Index, "</h3>\n\n", r.root.indextext, "<p> </p>\n</div>\n")); else Add(par,"<p>INDEX\n-----------</p>\n\n"); fi; end; GAPDoc2HTMLProcs.AltYes := function(r) local mark, mj, l; # recursively mark text as HTML code (no escaping of HTML markup) mark := function(r) local a; if IsString(r.content) then r.HTML := true; elif IsList(r.content) then for a in r.content do mark(a); od; fi; end; mj := r.root.mathmode="MathJax"; if IsBound(r.attributes.Only) then l := SplitString(r.attributes.Only, "", "\n\r\t ,"); if "HTML" in l then if "MathJax" in l then if mj then mark(r); return true; else return false; fi; elif "noMathJax" in l then if not mj then mark(r); return true; else return false; fi; else mark(r); return true; fi; else return false; fi; elif IsBound(r.attributes.Not) then # here, even if it is used, it is not HTML specific, so we not 'mark' l := SplitString(r.attributes.Not, "", "\n\r\t ,"); if "HTML" in l then if "MathJax" in l then if mj then return false; else return true; fi; elif "noMathJax" in l then if not mj then return false; else return true; fi; else return false; fi; else return true; fi; fi; return true; end; GAPDoc2HTMLProcs.Alt := function(r, str) if GAPDoc2HTMLProcs.AltYes(r) then GAPDoc2HTMLContent(r, str); fi; end; # nothing special to do GAPDoc2HTMLProcs.Address := function(r, str) GAPDoc2HTMLContent(r, str); end; # copy a few entries with two element names GAPDoc2HTMLProcs.E := GAPDoc2HTMLProcs.Emph; GAPDoc2HTMLProcs.Keyword := GAPDoc2HTMLProcs.K; GAPDoc2HTMLProcs.Code := GAPDoc2HTMLProcs.C; GAPDoc2HTMLProcs.File := GAPDoc2HTMLProcs.F; GAPDoc2HTMLProcs.Button := GAPDoc2HTMLProcs.B; GAPDoc2HTMLProcs.Arg := GAPDoc2HTMLProcs.A; GAPDoc2HTMLProcs.Quoted := GAPDoc2HTMLProcs.Q; GAPDoc2HTMLProcs.Par := GAPDoc2HTMLProcs.P; # tables and utilities, not so nice since | and <Horline/> cannot be handled GAPDoc2HTMLProcs.Table := function(r, s) local str, cap, al, a, i; str := ""; if not GAPDoc2HTMLProcs.AltYes(r) then return; fi; # label if IsBound(r.attributes.Label) then GAPDoc2HTMLProcs.Label(rec(count := r.count, root := r.root, attributes := rec(Name := r.attributes.Label)), str); fi; # alignments, table has borders and lines everywhere if any | or HorLine # is specified Append(str, "<div class=\"pcenter\"><table class=\"GAPDocTable"); if not '|' in r.attributes.Align and Length(XMLElements(r, "HorLine")) = 0 then Append(str, "noborder"); fi; Append(str, "\">\n"); # the caption, if given cap := Filtered(r.content, a-> a.name = "Caption"); if Length(cap) > 0 then GAPDoc2HTMLProcs.Caption1(cap[1], str); fi; al := Filtered(r.attributes.Align, x-> x <> '|'); for i in [1..Length(al)] do if al[i] = 'c' then al[i] := "\"tdcenter\""; elif al[i] = 'l' then al[i] := "\"tdleft\""; else al[i] := "\"tdright\""; fi; od; # the rows of the table for a in r.content do if a.name = "Row" then GAPDoc2HTMLProcs.Row(a, str, al); fi; od; Append(str, "</table><br /><p> </p><br />\n"); Append(str, "</div>\n\n"); Add(s, r.count); Add(s, str); end; # do nothing, we call .Caption1 directly in .Table GAPDoc2HTMLProcs.Caption := function(r, str) return; end; # here the caption text is produced GAPDoc2HTMLProcs.Caption1 := function(r, str) Append(str, Concatenation("<caption class=\"GAPDocTable\"><b>", GAPDocTexts.d.Table, ": </b>")); GAPDoc2HTMLContent(r, str); Append(str, "</caption>\n"); end; # cannot be chosen in HTML GAPDoc2HTMLProcs.HorLine := function(r, str) end; GAPDoc2HTMLProcs.Row := function(r, str, al) local s, i, l; Append(str, "<tr>\n"); l := Filtered(r.content, a-> a.name = "Item"); for i in [1..Length(l)] do s := ""; GAPDoc2HTMLContent(l[i], s); if not IsString(s) then s := Concatenation(Filtered(s, IsString)); fi; # throw away <p> tags in table entries if Length(s) > 5 and s{[1..3]} = "<p>" and s{[Length(s)-5..Length(s)]} = "</p>\n\n" then s := s{[4..Length(s)-6]}; fi; Append(str, Concatenation("<td class=", al[i], ">", s, "</td>\n")); od; while i < Length(al) do Append(str, "<td> </td>\n"); i := i+1; od; Append(str, "</tr>\n"); end; ## ## <#GAPDoc Label="GAPDoc2HTMLPrintHTMLFiles"> ## <ManSection > ## <Func Arg="t[, path]" Name="GAPDoc2HTMLPrintHTMLFiles" /> ## <Returns>nothing</Returns> ## <Description> ## The first argument must be a result returned by <Ref ## Func="GAPDoc2HTML"/>. The second argument is a path for the files ## to write, it can be given as string or directory object. The text ## of each chapter is written into a separate file with name ## <F>chap0.html</F>, <F>chap1.html</F>, ..., <F>chapBib.html</F>, ## and <F>chapInd.html</F>.<P/> ## ## The <Package>MathJax</Package> versions are written to files ## <F>chap0_mj.html</F>, ..., <F>chapInd_mj.html</F>. <P/> ## ## The experimental version which is produced with <C>tth</C> ## uses different names for the files, namely ## <F>chap0_sym.html</F>, and so on for files which need ## symbol fonts. ## <P/> ## ## You should also add stylesheet files to the directory with the HTML ## files, see <Ref Subsect="StyleSheets"/>. ## </Description> ## </ManSection> ## <#/GAPDoc> ## ## Finally a function to print the text files: InstallGlobalFunction(GAPDoc2HTMLPrintHTMLFiles, function(t, path) local a; if IsString(path) then path := Directory(path); fi; for a in NamesOfComponents(t) do if IsRecord(t.(a)) and IsBound(t.(a).text) then FileString(Filename(path, Concatenation("chap", a, t.ext)), t.(a).text); fi; od; end); InstallGlobalFunction(CopyHTMLStyleFiles, function(dir) local d, todo, l, s, e, f; if not IsDirectory(dir) then dir := Directory(dir); fi; d := DirectoriesPackageLibrary("GAPDoc","styles")[1]; todo := []; for f in DirectoryContents(d) do if f = "chooser.html" then Add(todo, f); else l := Length(f); if l > 3 and f{[l-2..l]} = ".js" then Add(todo, f); elif l > 4 and f{[l-3..l]} = ".css" then Add(todo, f); fi; fi; od; for f in todo do s := StringFile(Filename(d,f)); if s = fail then Info(InfoGAPDoc, 1, "Cannot read file ", Filename(d,f), "\n"); else e := FileString(Filename(dir,f), s); if e = fail then Info(InfoGAPDoc, 1, "Cannot write file ", Filename(dir,f), "\n"); fi; fi; od; end);