├── examples ├── A.1 ├── 88.1 ├── eg.1 ├── dy.1 ├── sf.1 ├── dd.1 ├── jj.1 ├── mm.1 ├── da.1 ├── nd.1 ├── 2.1 ├── bx.1 ├── j4.1 ├── fb.1 ├── s0.1 ├── v1.1 ├── 0.1 ├── r3.1 ├── ti.1 ├── ch.1 ├── de.1 ├── e.1 ├── j1.1 ├── td.1 ├── C.1 ├── ci.1 ├── ds.1 ├── io.1 ├── st.1 ├── v.1 ├── h.1 ├── j3.1 ├── kk.1 ├── r1.1 ├── r2.1 ├── e2.1 ├── es.1 ├── j.1 ├── me.1 ├── ud.1 ├── am.1 ├── cc.1 ├── g.1 ├── i.1 ├── w1.1 ├── sa.1 ├── t2.1 ├── a2.1 ├── bb.1 ├── fc.1 ├── f.1 ├── im.1 ├── bs.1 ├── ce.1 ├── ie.1 ├── j5.1 ├── le.1 ├── se.1 ├── su.1 ├── i2.1 ├── ii.1 ├── n0.1 ├── ul.1 ├── ft.1 ├── j2.1 ├── in.1 ├── j6.1 ├── k.1 ├── nf.1 ├── sp.1 ├── ta.1 ├── tb.1 ├── rr.1 ├── sl.1 ├── ss.1 ├── v3.1 ├── b.1 ├── ff.1 ├── gr.1 ├── ur.1 ├── w.1 ├── hx.1 ├── t.1 ├── ar.1 ├── hh.1 ├── d.1 ├── er.1 ├── t1.1 ├── c.1 ├── ic.1 ├── t3.1 ├── p1.1 ├── ve.1 ├── pi.1 ├── hd.1 ├── a.1 ├── ns.1 ├── ee.1 ├── nh.1 ├── 12.1 ├── tp.1 ├── bl.1 ├── lg.1 ├── v2.1 ├── j7.1 ├── ac.1 ├── rc.1 ├── u8.1 ├── Makefile ├── af.1 ├── ix.1 ├── Ll.1 ├── ev.1 ├── sc.1 ├── tw.1 ├── ls.1 ├── as.1 ├── m.1 ├── ts.1 ├── al.1 ├── wh.1 ├── t4.1 ├── un.1 ├── tg.1 ├── kn.1 ├── th.1 ├── cm.1 ├── l2.1 ├── rm.1 ├── ja.1 ├── 1s.1 ├── b1.1 ├── rd.1 ├── co.1 ├── dv.1 ├── sh.1 ├── lb.1 ├── ps.1 ├── s.1 ├── ig.1 ├── ex.1 ├── tf.1 ├── xp.1 ├── ab.1 ├── ht.1 ├── h1.1 ├── li.1 ├── dc.1 └── uc.1 ├── docs ├── inch.jpg ├── t2p.png ├── .troff2pagerc.tmac ├── ebook.ms ├── style.tmac ├── index.ms ├── Makefile ├── infodoc.ms ├── defhsl.tmac ├── error.ms ├── slideshow.ms ├── index.t2p ├── genindex.ms ├── xrefs.ms ├── commands.ms └── eval.ms ├── .gitignore ├── COPYING ├── README.adoc ├── lua ├── 0shebang.lua ├── eval.lua ├── z-neovim.lua ├── z-luatex.lua ├── Makefile ├── stream.lua ├── err.lua ├── footnote.lua ├── init.lua ├── do.lua ├── dimen.lua ├── 2globals.lua ├── roman.lua ├── nb.lua ├── disp.lua ├── am.lua ├── ev.lua ├── color.lua ├── links.lua ├── counters.lua ├── initnumregs.lua ├── inputenc.lua ├── initstrings.lua ├── image.lua ├── gen.lua ├── t2p.lua ├── bye.lua ├── de.lua ├── navbar.lua ├── sec.lua ├── 1utils.lua ├── initescapes.lua ├── table.lua ├── switch.lua └── css.lua ├── prehistory ├── bin ├── neovim-troff2page ├── luatex-troff2page ├── troff2page.vim └── other-ways-to-call-troff2page.adoc ├── INSTALL.adoc └── man └── man1 └── troff2page.1 /examples/A.1: -------------------------------------------------------------------------------- 1 | .tm \n[.A] 2 | -------------------------------------------------------------------------------- /examples/88.1: -------------------------------------------------------------------------------- 1 | 20°F æsthetic 2 | -------------------------------------------------------------------------------- /examples/eg.1: -------------------------------------------------------------------------------- 1 | nothing special 2 | -------------------------------------------------------------------------------- /examples/dy.1: -------------------------------------------------------------------------------- 1 | Today is \*[DY]. 2 | -------------------------------------------------------------------------------- /examples/sf.1: -------------------------------------------------------------------------------- 1 | .tm .U is \n[.U] 2 | -------------------------------------------------------------------------------- /examples/dd.1: -------------------------------------------------------------------------------- 1 | .\"ds AUXF blau 2 | ok 3 | -------------------------------------------------------------------------------- /examples/jj.1: -------------------------------------------------------------------------------- 1 | .if '1'1' .tm COWABUNGA 2 | -------------------------------------------------------------------------------- /examples/mm.1: -------------------------------------------------------------------------------- 1 | onast 2 | .so 3 | oaiesnt 4 | -------------------------------------------------------------------------------- /examples/da.1: -------------------------------------------------------------------------------- 1 | .DA July 20, 1969 2 | .so 1s.1 3 | -------------------------------------------------------------------------------- /examples/nd.1: -------------------------------------------------------------------------------- 1 | .ND July 20, 1969 2 | .so 1s.1 3 | -------------------------------------------------------------------------------- /examples/2.1: -------------------------------------------------------------------------------- 1 | page 1 2 | 3 | .bp 4 | 5 | page 2 6 | -------------------------------------------------------------------------------- /examples/bx.1: -------------------------------------------------------------------------------- 1 | Press the 2 | .BX RETURN 3 | key 4 | -------------------------------------------------------------------------------- /examples/j4.1: -------------------------------------------------------------------------------- 1 | .ie '1'1' .tm one 2 | .el .tm two 3 | -------------------------------------------------------------------------------- /examples/fb.1: -------------------------------------------------------------------------------- 1 | This is \fBBOLD STUFF\fP back to normal 2 | -------------------------------------------------------------------------------- /examples/s0.1: -------------------------------------------------------------------------------- 1 | This is \s+2BIG STUFF\s0 back to normal 2 | -------------------------------------------------------------------------------- /examples/v1.1: -------------------------------------------------------------------------------- 1 | .tm ok 2 | .tm " nok 3 | .tm go 4 | -------------------------------------------------------------------------------- /examples/0.1: -------------------------------------------------------------------------------- 1 | .ds page1 \\*[urlh #page1 0] 2 | see \*[page1] 3 | -------------------------------------------------------------------------------- /examples/r3.1: -------------------------------------------------------------------------------- 1 | .\"char \] \(S1 2 | 3 | This is \]good stuff 4 | -------------------------------------------------------------------------------- /examples/ti.1: -------------------------------------------------------------------------------- 1 | flush 2 | .ti +.25i 3 | indented by .25 inch 4 | -------------------------------------------------------------------------------- /examples/ch.1: -------------------------------------------------------------------------------- 1 | .char \] \(S1 2 | 3 | This is \]pretty good. 4 | -------------------------------------------------------------------------------- /examples/de.1: -------------------------------------------------------------------------------- 1 | .de jo 2 | .tm \\$* 3 | .. 4 | .jo a b c 2 3 4 5 | -------------------------------------------------------------------------------- /examples/e.1: -------------------------------------------------------------------------------- 1 | .de gogo 2 | .tm "\\\\m.br\\\\m" 3 | .. 4 | .gogo 5 | -------------------------------------------------------------------------------- /examples/j1.1: -------------------------------------------------------------------------------- 1 | .ie '1'1' \{\ 2 | .tm one 3 | .\} 4 | .el .tm two 5 | -------------------------------------------------------------------------------- /examples/td.1: -------------------------------------------------------------------------------- 1 | This is Mr.\ Potato. 2 | 3 | This is Mr.\~Potato. 4 | -------------------------------------------------------------------------------- /examples/C.1: -------------------------------------------------------------------------------- 1 | \[TP] \[co] \[u005c] 2 | .PP 3 | \C+TP+ \C'co' \C"u005c" 4 | -------------------------------------------------------------------------------- /examples/ci.1: -------------------------------------------------------------------------------- 1 | .ft C 2 | oooiaoiens t 3 | .ft CI 4 | oasnt oineas oine ast 5 | -------------------------------------------------------------------------------- /examples/ds.1: -------------------------------------------------------------------------------- 1 | .mso ms.tmac 2 | .PP 3 | .ds doh d\(:o 4 | .PP 5 | \*[doh] 6 | -------------------------------------------------------------------------------- /examples/io.1: -------------------------------------------------------------------------------- 1 | .ig ## 2 | io.write('Writing to stdout from Lua\n') 3 | .## 4 | -------------------------------------------------------------------------------- /examples/st.1: -------------------------------------------------------------------------------- 1 | \*{14\*}C 2 | .LP 3 | C\*<27\*>H\*<44\*>O (cholecalciferol) 4 | -------------------------------------------------------------------------------- /examples/v.1: -------------------------------------------------------------------------------- 1 | .ds aa aa 2 | .ds bb \\*[aa] 3 | .ds aa cc 4 | bb is \*[bb] 5 | -------------------------------------------------------------------------------- /docs/inch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ds26gte/troff2page/master/docs/inch.jpg -------------------------------------------------------------------------------- /docs/t2p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ds26gte/troff2page/master/docs/t2p.png -------------------------------------------------------------------------------- /examples/h.1: -------------------------------------------------------------------------------- 1 | .de gogo 2 | aa 3 | bb 4 | cc 5 | .. 6 | . 7 | .gogo 8 | 9 | -------------------------------------------------------------------------------- /examples/j3.1: -------------------------------------------------------------------------------- 1 | .IX two 2 | . 3 | .de PX 4 | .so \\*[AUXF].ind 5 | .. 6 | .PX 7 | -------------------------------------------------------------------------------- /examples/kk.1: -------------------------------------------------------------------------------- 1 | .RS 4 2 | \h'-04' 3.\h'+-2' oanst 3 | oiaenst 4 | oanst 5 | .RE 6 | -------------------------------------------------------------------------------- /examples/r1.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ds26gte/troff2page/master/examples/r1.1 -------------------------------------------------------------------------------- /examples/r2.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ds26gte/troff2page/master/examples/r2.1 -------------------------------------------------------------------------------- /examples/e2.1: -------------------------------------------------------------------------------- 1 | .de ok 2 | .ig ## 3 | io.write('ieast \\n') 4 | .## 5 | .. 6 | .ok 7 | -------------------------------------------------------------------------------- /examples/es.1: -------------------------------------------------------------------------------- 1 | .mso pca-verb.tmac 2 | .EX 3 | don't expand this escape: \(*t 4 | .EE 5 | -------------------------------------------------------------------------------- /examples/j.1: -------------------------------------------------------------------------------- 1 | .if '1'1' .tm zero 2 | .if '1'1' \{\ 3 | .tm one 4 | .tm two 5 | .\} 6 | -------------------------------------------------------------------------------- /examples/me.1: -------------------------------------------------------------------------------- 1 | .\" last modified 2020-12-07 2 | .tm My process id is \n($$. 3 | . 4 | -------------------------------------------------------------------------------- /examples/ud.1: -------------------------------------------------------------------------------- 1 | .\" last modified 2020-12-05 2 | . 3 | .ND \" undated 4 | .so 1s.1 5 | -------------------------------------------------------------------------------- /examples/am.1: -------------------------------------------------------------------------------- 1 | .de ok 2 | .tm ok 3 | .. 4 | .am ok 5 | .tm \\$1 6 | .. 7 | .ok one two 8 | -------------------------------------------------------------------------------- /examples/cc.1: -------------------------------------------------------------------------------- 1 | .ds AUXF gruen 2 | .de aye 3 | .ds AUXF blau 4 | .. 5 | .aye 6 | \*[AUXF] 7 | -------------------------------------------------------------------------------- /examples/g.1: -------------------------------------------------------------------------------- 1 | .ie \n[.g] .tm running groff 2 | .el .tm running something other than groff 3 | -------------------------------------------------------------------------------- /examples/i.1: -------------------------------------------------------------------------------- 1 | .de gogo 2 | .tm one 3 | .tm two 4 | .return 5 | .tm three 6 | .. 7 | .gogo 8 | -------------------------------------------------------------------------------- /examples/w1.1: -------------------------------------------------------------------------------- 1 | .de BB 2 | \fB\\$*\\fP\c 3 | .. 4 | This is \*[BB very good]. No? 5 | 6 | -------------------------------------------------------------------------------- /examples/sa.1: -------------------------------------------------------------------------------- 1 | .ds c \fC\\$*\fP 2 | 3 | lets see \*[c \en[.troff2page]] how this turns out 4 | -------------------------------------------------------------------------------- /examples/t2.1: -------------------------------------------------------------------------------- 1 | .TS 2 | box, expand; 3 | l c r. 4 | Left side Middle Right side 5 | .TE 6 | 7 | -------------------------------------------------------------------------------- /examples/a2.1: -------------------------------------------------------------------------------- 1 | .de ok 2 | This is \\$1 3 | .. 4 | .am ok 5 | This is \\$2 6 | .. 7 | .ok one two 8 | -------------------------------------------------------------------------------- /examples/bb.1: -------------------------------------------------------------------------------- 1 | .if '\*[AUXF]'' .ds AUXF .grofftmp 2 | auxf is = \*[AUXF] 3 | .tm auxf is \*[AUXF] 4 | -------------------------------------------------------------------------------- /examples/fc.1: -------------------------------------------------------------------------------- 1 | .ds c \fC\\$*\fP 2 | 3 | This is \*[c apropos] nothing about \*[c Common Lisp 2]. 4 | -------------------------------------------------------------------------------- /examples/f.1: -------------------------------------------------------------------------------- 1 | .de gogo 2 | .tm one 3 | .tm two 4 | .return 5 | .tm three 6 | .tm four 7 | .. 8 | .gogo 9 | -------------------------------------------------------------------------------- /examples/im.1: -------------------------------------------------------------------------------- 1 | .mso www.tmac 2 | This is an image 3 | .PP 4 | .PIMG -C "../docs/t2p.png" 5 | .PP 6 | next 7 | -------------------------------------------------------------------------------- /examples/bs.1: -------------------------------------------------------------------------------- 1 | This is \(flu\(ffy 2 | 3 | .I 4 | This is \(flu\(ffy 5 | 6 | .B 7 | This is \(flu\(ffy 8 | 9 | -------------------------------------------------------------------------------- /examples/ce.1: -------------------------------------------------------------------------------- 1 | oanst 2 | .ce 4 3 | a 4 | b 5 | c 6 | .ce 0 7 | oaen 8 | oaen 9 | oineast 10 | onast 11 | -------------------------------------------------------------------------------- /examples/ie.1: -------------------------------------------------------------------------------- 1 | .ie '1'0' \{\ 2 | .tm one 3 | .\} 4 | .el .ie '1'2' \{\ 5 | .tm two 6 | .\} 7 | .el .tm three 8 | -------------------------------------------------------------------------------- /examples/j5.1: -------------------------------------------------------------------------------- 1 | .de ok 2 | .ie '1'1' \{\ 3 | one 4 | .\} 5 | .el \{\ 6 | two 7 | .\} 8 | .. 9 | .ok 10 | -------------------------------------------------------------------------------- /examples/le.1: -------------------------------------------------------------------------------- 1 | .ds xxx abcdefgh 2 | .length yyy \*[xxx] 3 | .tm \n[yyy] 4 | .length y oieanst 5 | .tm \n[y] 6 | -------------------------------------------------------------------------------- /examples/se.1: -------------------------------------------------------------------------------- 1 | .mso pca.tmac 2 | .RT 3 | .ToC 4 | .SH 1 5 | Characters in "section header" 6 | .LP 7 | para 8 | -------------------------------------------------------------------------------- /examples/su.1: -------------------------------------------------------------------------------- 1 | .ds xxx abcdefgh 2 | .substring xxx 1 -4 3 | .tm \*[xxx] 4 | .substring xxx 2 5 | .tm \*[xxx] 6 | -------------------------------------------------------------------------------- /examples/i2.1: -------------------------------------------------------------------------------- 1 | .\"mso www.tmac 2 | This is an image 3 | 4 | .PIMG -C "../../tex2page/t2p.png" 50 5 | 6 | next 7 | -------------------------------------------------------------------------------- /examples/ii.1: -------------------------------------------------------------------------------- 1 | .de gogo 2 | .ecs 3 | .ec @ 4 | .tm auxf is @*[auxf] 5 | .ecr 6 | .. 7 | .ds auxf whatnow 8 | .gogo 9 | -------------------------------------------------------------------------------- /examples/n0.1: -------------------------------------------------------------------------------- 1 | .\" last modified 2020-12-05 2 | . 3 | .tm Uninitialized numreg has value \n[uninitialized_numreg] 4 | -------------------------------------------------------------------------------- /examples/ul.1: -------------------------------------------------------------------------------- 1 | See \*[url http://ds26gte.github.io/troff2page]the troff2page website\& for 2 | further details. 3 | -------------------------------------------------------------------------------- /examples/ft.1: -------------------------------------------------------------------------------- 1 | .nr cm 1c 2 | .nr in 1i 3 | .nr ft \n(in*12 4 | .nr ft_in_cm \n(ft/\n(cm 5 | .tm 1 ft = \n[ft_in_cm] cm 6 | -------------------------------------------------------------------------------- /examples/j2.1: -------------------------------------------------------------------------------- 1 | .ie '1'2' \{\ 2 | .tm one 3 | .\} 4 | .el \{\ 5 | .tm two 6 | .\}xtm what 7 | iaenst 8 | .ok 9 | aisnet 10 | -------------------------------------------------------------------------------- /examples/in.1: -------------------------------------------------------------------------------- 1 | .LP 2 | This is 1\h'1i'inch apart. 3 | .LP 4 | This is 2\h'2i'inches apart. 5 | .LP 6 | This is 3\h'3i'inches apart. 7 | -------------------------------------------------------------------------------- /examples/j6.1: -------------------------------------------------------------------------------- 1 | .ds good good 2 | .de ok 3 | .if '1'1' \{\ 4 | This is \\*[good] 5 | .\} 6 | .. 7 | .ok 8 | .ds good bad 9 | .ok 10 | -------------------------------------------------------------------------------- /examples/k.1: -------------------------------------------------------------------------------- 1 | .ds ok one 2 | .TL 3 | troff2page 4 | .AU 5 | \*[ok] 6 | two 7 | three 8 | .RT 9 | .LP 10 | start start start 11 | . 12 | -------------------------------------------------------------------------------- /examples/nf.1: -------------------------------------------------------------------------------- 1 | oaienstien 2 | aosentas 3 | .nf 4 | one 5 | two 6 | 7 | three 8 | four 9 | .fi 10 | aosent 11 | aonset 12 | aotns 13 | 14 | -------------------------------------------------------------------------------- /examples/sp.1: -------------------------------------------------------------------------------- 1 | dfljadf aldkjf 2 | aldfjk 3 | 4 | lkajdf 5 | lakjdf 6 | .sp 1 7 | alkdjf 8 | alkdjf 9 | .sp 2 10 | alkdjf 11 | alkdjf 12 | -------------------------------------------------------------------------------- /examples/ta.1: -------------------------------------------------------------------------------- 1 | .SH 2 | Box around every cell 3 | .RT 4 | .TS 5 | tab(@), allbox; 6 | l l. 7 | one @ two 8 | buckle @ my show 9 | .TE 10 | -------------------------------------------------------------------------------- /examples/tb.1: -------------------------------------------------------------------------------- 1 | .SH 2 | Box around table, not cells 3 | .RT 4 | .TS 5 | tab(@), box; 6 | l l. 7 | one @ two 8 | buckle @ my show 9 | .TE 10 | -------------------------------------------------------------------------------- /examples/rr.1: -------------------------------------------------------------------------------- 1 | .\" last modified 2020-12-06 2 | .nr a 1 3 | .nr b 2 4 | .tm a is \na 5 | .tm b is \nb 6 | .rr a 7 | .tm a is gone: \na 8 | .tm b is still \nb 9 | -------------------------------------------------------------------------------- /examples/sl.1: -------------------------------------------------------------------------------- 1 | .mso ms.tmac 2 | .mso t2pslides.tmac 3 | 4 | slide one 5 | 6 | .bp 7 | 8 | slide two 9 | 10 | .bp 11 | 12 | slide three 13 | 14 | -------------------------------------------------------------------------------- /examples/ss.1: -------------------------------------------------------------------------------- 1 | .ds ok blueberrypie 2 | .tm \*[ok] 3 | .substring ok 3 5 4 | .tm \*[ok] 5 | .ds tu abcdefgh 6 | .tm \*[tu] 7 | .substring tu 1 -4 8 | .tm \*[tu] 9 | -------------------------------------------------------------------------------- /examples/v3.1: -------------------------------------------------------------------------------- 1 | .mso url.tmac 2 | .RT 3 | page1 4 | .bp 5 | page 2 6 | .TG page2 7 | see nothing 8 | 9 | .bp 10 | page 3 11 | 12 | See page \*[page2] 13 | -------------------------------------------------------------------------------- /examples/b.1: -------------------------------------------------------------------------------- 1 | .if '\*[AUXF]'' .ds AUXF .grofftmp 2 | .ds GOGO .gogool 3 | 4 | \*[AUXF] 5 | 6 | gogo= \*[GOGO] 7 | 8 | .tm \*[AUXF] 9 | .tm gogo= \*[GOGO] 10 | -------------------------------------------------------------------------------- /examples/ff.1: -------------------------------------------------------------------------------- 1 | As can be see\** fon aoien asoinast 2 | . 3 | .FS 4 | oaeisnt oane oianes toeinasto oianest 5 | .FE 6 | . 7 | aoeisnto ioaens toein ioen as 8 | aoeisnt 9 | -------------------------------------------------------------------------------- /examples/gr.1: -------------------------------------------------------------------------------- 1 | .mso pca.tmac 2 | .PP 3 | The golden ratio \[*f] is approximately 4 | .eval 5 | troff:write((1 + math.sqrt(5)) / 2) 6 | troff:write('.\n') 7 | .endeval 8 | -------------------------------------------------------------------------------- /examples/ur.1: -------------------------------------------------------------------------------- 1 | .TAG one 2 | one onen oena oiea soen 3 | asoten 4 | 5 | .bp 6 | 7 | twoo oiea tonew aones toien ast 8 | see 9 | .URL #one 10 | oaenst 11 | on 12 | -------------------------------------------------------------------------------- /examples/w.1: -------------------------------------------------------------------------------- 1 | .blm PP 2 | . 3 | .SH 4 | Section title 5 | 6 | Recognize the blank line above this line as a parsep, so this para is not part of 7 | the section title. 8 | -------------------------------------------------------------------------------- /examples/hx.1: -------------------------------------------------------------------------------- 1 | .blm PP 2 | .HX 0 3 | .LK 4 | 5 | .NH 1 6 | one 7 | 8 | one 9 | 10 | .NH 2 11 | two 12 | 13 | two 14 | 15 | .NH 3 16 | three 17 | 18 | three 19 | -------------------------------------------------------------------------------- /examples/t.1: -------------------------------------------------------------------------------- 1 | .mso ms.tmac 2 | .mso www.tmac 3 | .mso url.tmac 4 | .blm PP 5 | 6 | .TG one 7 | oienast 8 | oianst 9 | 10 | See 11 | \*[one] 12 | for more details. 13 | -------------------------------------------------------------------------------- /examples/ar.1: -------------------------------------------------------------------------------- 1 | .blm PP 2 | .de ok 3 | .ti \\$1 4 | .. 5 | 6 | .ok +2i 7 | oans oasoen 8 | aosent 9 | 10 | .ok +5i 11 | aosnt oan t 12 | aonstoneas 13 | oat 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/hh.1: -------------------------------------------------------------------------------- 1 | .open a a.txt 2 | .de eval 3 | let's sea 4 | .de extra endeval 5 | .. 6 | .de endeval 7 | .tm ocean 8 | .writem a extra 9 | .. 10 | .eval 11 | nix 12 | .endeval 13 | -------------------------------------------------------------------------------- /examples/d.1: -------------------------------------------------------------------------------- 1 | .\"ds AUXF blau 2 | .mso index.tmac 3 | . 4 | .IX one 5 | one one one one 6 | .bp 7 | .IX two 8 | two two two 9 | .bp 10 | .IX three 11 | three three three 12 | .PX 13 | -------------------------------------------------------------------------------- /examples/er.1: -------------------------------------------------------------------------------- 1 | text text 2 | text text 3 | text text 4 | text text 5 | 6 | .als eject pagebreak 7 | 8 | text text 9 | text text 10 | text text 11 | text text 12 | text text 13 | -------------------------------------------------------------------------------- /examples/t1.1: -------------------------------------------------------------------------------- 1 | a surrounding box, but no cell boxes. header in bold 2 | 3 | .TS 4 | box; 5 | cb cb 6 | l l . 7 | Some Head Another 8 | data more data 9 | what the hey? 10 | .TE 11 | -------------------------------------------------------------------------------- /examples/c.1: -------------------------------------------------------------------------------- 1 | .ds AUXF gruen 2 | .de aye 3 | .ds AUXF blau 4 | \\$* 5 | .. 6 | .de bee 7 | .aye \\*[AUXF] 8 | .. 9 | .de cee 10 | .so \\*[AUXF] 11 | .. 12 | .bee 13 | .cee 14 | DONE 15 | -------------------------------------------------------------------------------- /examples/ic.1: -------------------------------------------------------------------------------- 1 | .de bump 2 | .nr j 0 \\$1 3 | .tm \\nj 4 | .tm \\n+j 5 | .tm \\n+j 6 | .tm \\n+j 7 | .tm \\n+j 8 | .tm 9 | .. 10 | 11 | .bump 12 | 13 | .bump 1 14 | 15 | .bump 5 16 | 17 | -------------------------------------------------------------------------------- /examples/t3.1: -------------------------------------------------------------------------------- 1 | a surrounding box, but no cell boxes. header in bold 2 | 3 | .TS 4 | doublebox; 5 | cb cb 6 | l l . 7 | Some Head Another 8 | data more data 9 | what the hey? 10 | .TE 11 | -------------------------------------------------------------------------------- /examples/p1.1: -------------------------------------------------------------------------------- 1 | .SC chapter 2 | .LP 3 | This is 4 | .P1 5 | one 6 | two 7 | three 8 | .P2 9 | back to para 10 | display again 11 | .LD 12 | one 13 | two 14 | three 15 | .DE 16 | back to para 17 | -------------------------------------------------------------------------------- /examples/ve.1: -------------------------------------------------------------------------------- 1 | .tm Major version number is \n(.x 2 | .tm Minor version number is \n(.y 3 | .tm Revision numberis \n(.Y 4 | .tm Page length is \n(.p 5 | .tm troff2page version number is \n[.troff2page] 6 | -------------------------------------------------------------------------------- /examples/pi.1: -------------------------------------------------------------------------------- 1 | The ratio of the circumference of a circle to its diameter is 2 | .eval 3 | -- following prints pi, because cos(pi) = -1 4 | troff:write(math.acos(-1)) 5 | troff:write('.\n') 6 | .endeval 7 | -------------------------------------------------------------------------------- /examples/hd.1: -------------------------------------------------------------------------------- 1 | .RT 2 | .ToC 3 | . 4 | .SH 1 5 | Section header (w/ToC) containing backslash & angle brackets: \\e 6 | .LP 7 | Eaque consequatur illum est ut totam architecto officiis hic. Quas et ab ut et quia. 8 | -------------------------------------------------------------------------------- /examples/a.1: -------------------------------------------------------------------------------- 1 | .ds auxf gruen 2 | .ds boxf \*[auxf] 3 | .ds coxf \\*[auxf] 4 | .ds doxf \\\*[auxf] 5 | auxf is \*[auxf] 6 | boxf is \*[boxf] 7 | coxf is \*[coxf] 8 | doxf is \*[doxf] 9 | yes they are \\ aren't they 10 | -------------------------------------------------------------------------------- /examples/ns.1: -------------------------------------------------------------------------------- 1 | .SH 1 2 | Nested .de's 3 | 4 | .de me 5 | .de me modded 6 | .tm modded me 7 | .modded 8 | .tm original me 9 | .. 10 | 11 | The original me: 12 | 13 | .me 14 | 15 | The modded me: 16 | 17 | .me 18 | -------------------------------------------------------------------------------- /docs/.troff2pagerc.tmac: -------------------------------------------------------------------------------- 1 | .ig 2 | Last modified 2021-11-08. 3 | 4 | This file is here only to prevent $HOME/.troff2pagerc.tmac, if it 5 | exists, from being autoloaded. We have all the macros and css we 6 | need right here. 7 | .. 8 | -------------------------------------------------------------------------------- /examples/ee.1: -------------------------------------------------------------------------------- 1 | .mso pca.tmac 2 | .PP 3 | The ratio of the circumference of a circle to its diameter is 4 | .eval 5 | -- following prints pi, because cos(pi) = -1 6 | troff:write(math.acos(-1)) 7 | troff:write('.\n') 8 | .endeval 9 | -------------------------------------------------------------------------------- /examples/nh.1: -------------------------------------------------------------------------------- 1 | .blm PP 2 | .NH 3 | First section 4 | 5 | oesnt oien oaisent 6 | aoienstoiiean s 7 | aoiesntoenas 8 | toeinast 9 | 10 | .NH 11 | Second aste 12 | 13 | oeianstoien 14 | oaienst 15 | oaienst 16 | y 17 | 18 | -------------------------------------------------------------------------------- /examples/12.1: -------------------------------------------------------------------------------- 1 | .nr num 3 2 | . 3 | .ds nationality French 4 | . 5 | .de pear_tree 6 | List of \\$3 \\$2 \\$1 7 | .. 8 | . 9 | .de partridge 10 | .pear_tree \\$1 \\*[nationality] \\n[num] 11 | .. 12 | . 13 | .partridge hens 14 | -------------------------------------------------------------------------------- /examples/tp.1: -------------------------------------------------------------------------------- 1 | .SH 2 | Long text in cells 3 | .RT 4 | .TS 5 | tab(@), allbox; 6 | l l. 7 | T{ 8 | long 9 | key1 10 | T}@T{ 11 | long 12 | value 13 | T} 14 | T{ 15 | long 16 | key2 17 | T}@T{ 18 | long 19 | value2 20 | T} 21 | .TE 22 | -------------------------------------------------------------------------------- /examples/bl.1: -------------------------------------------------------------------------------- 1 | .de blm-macro 2 | . LP 3 | .. 4 | .blm blm-macro 5 | Home of Groff (GNU Troff). 6 | The USA site also contains older, obsolete versions. 7 | 8 | 9 | The development version is available from a CVS repository, see below. 10 | .nx 11 | -------------------------------------------------------------------------------- /examples/lg.1: -------------------------------------------------------------------------------- 1 | .SH 2 | LarGer and SMaller letters 3 | .LP 4 | This is normal size. 5 | 6 | .LG 7 | Somewhat larger. 8 | 9 | .LG 10 | Larger still. 11 | 12 | .NL 13 | Back to normal. 14 | 15 | .SM 16 | Smaller. 17 | 18 | .SM 19 | Even smaller. 20 | -------------------------------------------------------------------------------- /examples/v2.1: -------------------------------------------------------------------------------- 1 | .nr NR 564 2 | .ds urlh [``\\$1''] 3 | 4 | .open popo temp.ss 5 | 6 | .de A 7 | .write popo .ds \\$1 \\*[urlh \\n(NR] 8 | .. 9 | 10 | .A ok 11 | 12 | .close popo 13 | 14 | .so temp.ss 15 | 16 | para para 17 | 18 | See \*[ok] 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # last modified 2020-12-07 2 | *.ps 3 | *.txt 4 | *temp_* 5 | *~ 6 | .trofftemp* 7 | ?.lisp 8 | ?.ms 9 | [^i]*-Z-* 10 | [^i]*.html 11 | docs/*[^cegls] 12 | examples/*[^1e] 13 | examples/????*.1 14 | lua/*[^a] 15 | man/man1/*[^1] 16 | troffput* 17 | -------------------------------------------------------------------------------- /examples/j7.1: -------------------------------------------------------------------------------- 1 | .mso pca.tmac 2 | .eval 3 | io.write('one') 4 | io.write('\n') 5 | .endeval 6 | .if \n[.troff2page] \{\ 7 | .eval 8 | io.write('eins') 9 | io.write('\n') 10 | .endeval 11 | .\} 12 | .eval 13 | io.write('two') 14 | io.write('\n') 15 | .endeval 16 | .nx 17 | -------------------------------------------------------------------------------- /examples/ac.1: -------------------------------------------------------------------------------- 1 | .AM 2 | yogh and eszett are \*[3] and \*[8]. 3 | Also \[yogh] and \(ss. 4 | 5 | o-ogonek is \*q. 6 | 7 | GS is \n(GS. 8 | 9 | a-acute is a\*'. 10 | 11 | a-umlaut is \[:a]. 12 | 13 | This \*- is an em-dash. 14 | 15 | The temp is 70°F. 16 | 17 | Bye. 18 | -------------------------------------------------------------------------------- /examples/rc.1: -------------------------------------------------------------------------------- 1 | .de makro 2 | This is still double-u: \\$1. 3 | .. 4 | . 5 | .char Z w 6 | .PP 7 | This is double-u: Z (but typed cap-zee). 8 | .PP 9 | .makro Z 10 | .PP 11 | .tm rchar's arg should be cap-zee, not w. 12 | .rchar Z 13 | .PP 14 | This is the real cap-zee: Z. 15 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2003-2021 Dorai Sitaram. 2 | All rights reserved. 3 | 4 | Permission to distribute and use this work for any 5 | purpose is hereby granted provided this copyright 6 | notice is included in the copy. This work is provided 7 | as is, with no warranty of any kind. 8 | -------------------------------------------------------------------------------- /examples/u8.1: -------------------------------------------------------------------------------- 1 | é é 2 | \e[u00E9] \[u00E9] 3 | \e[u0065_0301] \[u0065_0301] 4 | .LP 5 | \e[u00A7] \[u00A7] 6 | \e[u00B6] \[u00B6] 7 | .LP 8 | \e[u005C] \[u005C] 9 | \e[u29F9] \[u29F9] 10 | \e[uFE68] \[uFE68] 11 | .LP 12 | \e[u2621] \[u2621] 13 | \e[u26A0] \[u26A0] 14 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | # last modified 2020-12-07 2 | 3 | src_files = $(wildcard ?.1 ??.1) 4 | 5 | html_files = $(src_files:%.1=%.html) 6 | 7 | all: $(html_files) 8 | 9 | %.html : %.1 10 | troff2page -mpca $< 11 | 12 | again: clean all 13 | 14 | clean: 15 | rm -f *.html *.pdf *.ps *-Z-* 16 | -------------------------------------------------------------------------------- /examples/af.1: -------------------------------------------------------------------------------- 1 | .\" last modified 2020-12-05 2 | . 3 | .nr j 7 4 | .tm \nj 5 | . 6 | .af j 000 7 | .tm \nj 8 | . 9 | .af j I 10 | .tm \nj 11 | . 12 | .af j i 13 | .tm \nj 14 | . 15 | .af j A 16 | .tm \nj 17 | . 18 | .af j a 19 | .tm \nj 20 | . 21 | .af j 1 22 | .tm ...and back to 23 | .tm \nj 24 | -------------------------------------------------------------------------------- /examples/ix.1: -------------------------------------------------------------------------------- 1 | one 2 | .IX one@\fC.one\fP (t r) 3 | .IX one@\fC.one\fP (t r) 4 | 5 | .bp 6 | 7 | two 8 | .IX one@\fC.one\fP (t r) 9 | 10 | .bp 11 | 12 | three 13 | 14 | .IX one@\fC.one\fP (t r) 15 | .IX four 16 | 17 | .bp 18 | 19 | four 20 | .IX four 21 | 22 | .bp 23 | .so \*[AUXF].ind 24 | -------------------------------------------------------------------------------- /examples/Ll.1: -------------------------------------------------------------------------------- 1 | .tm 29827 inches errors in groff, not troff2page 2 | .nr j 29827i 3 | .tm 29826 inches fine 4 | .nr j is largest groff length 5 | .nr j 29826i 6 | .tm j is \nj mpt 7 | .nr j (\nj/1i) 8 | .tm j is \nj in 9 | .nr j (\nj/12) 10 | .tm j is \nj ft 11 | .nr j (\nj/5280) 12 | .tm j is \nj mi 13 | -------------------------------------------------------------------------------- /examples/ev.1: -------------------------------------------------------------------------------- 1 | .mso pca.tmac 2 | .PP 3 | .SH 1 4 | Eval in action 5 | .LP 6 | The ratio of the circumference of a circle to 7 | its radius is \(*t \(~= 8 | .eval 9 | -- following prints tau, because cos(tau/2) = -1 10 | -- 11 | troff:write(2*math.acos(-1), '.\n') 12 | .endeval 13 | .PP 14 | Bye. 15 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = troff2page 2 | 3 | troff2page is a Lua program for making Web 4 | pages and Info documents from troff documents. Consult 5 | 6 | http://ds26gte.github.io/troff2page/index.html 7 | 8 | for its capabilities. 9 | 10 | For installation instructions, please see 11 | link:INSTALL.adoc[]. 12 | -------------------------------------------------------------------------------- /lua/0shebang.lua: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env lua 2 | 3 | Troff2page_version = 20230105 -- last modified 4 | Troff2page_website = 'http://ds26gte.github.io/troff2page' 5 | 6 | Troff2page_copyright_notice = 7 | string.format('Copyright (C) 2003-%s Dorai Sitaram', 8 | string.sub(Troff2page_version, 1, 4)) 9 | -------------------------------------------------------------------------------- /prehistory: -------------------------------------------------------------------------------- 1 | Last change 2017-08-27 2 | 3 | 2017 Aug 18 4 | 5 | Ported to Lua from the Common Lisp version, which is still available in 6 | the 'lisp' branch of this Git repo. See the 'history' file there for history 7 | prior to this date. In this 'master' branch, I'll be documenting subsequent 8 | changes in the Git log. 9 | -------------------------------------------------------------------------------- /examples/sc.1: -------------------------------------------------------------------------------- 1 | .blm PP 2 | .nr bell_localisms 1 3 | SC First section 4 | 5 | oesnt oien oaisent 6 | aoienstoiiean s 7 | .P1 8 | what is #ienst 9 | what is #ienst 10 | what is #ienst 11 | .P2 12 | aoiesntoenas 13 | toeinast 14 | 15 | SC Second aste 16 | 17 | oeianstoien 18 | oaienst 19 | oaienst 20 | y 21 | 22 | -------------------------------------------------------------------------------- /examples/tw.1: -------------------------------------------------------------------------------- 1 | .TL 2 | Table cell widths 3 | .RT 4 | .TS 5 | center allbox tab(@); 6 | blw(15n) lw(75n). 7 | T{ 8 | Note 9 | T}@T{ 10 | \fCmpca\fR’s \fC.TAG\fR overrides a similarly named macro in 11 | the file \fCwww.tmac\fR in the groff distribution, which only allows 12 | backward references. 13 | T} 14 | .TE 15 | 16 | -------------------------------------------------------------------------------- /lua/eval.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-12-03 2 | 3 | function eval_in_lua(tbl) 4 | --print('doing eval_in_lua', table_to_string(tbl)) 5 | local tmpf = os.tmpname() 6 | local o = io.open(tmpf, 'w') 7 | for i=1,#tbl do 8 | o:write(tbl[i], '\n') 9 | end 10 | o:close() 11 | dofile(tmpf) 12 | os.remove(tmpf) 13 | end 14 | -------------------------------------------------------------------------------- /examples/ls.1: -------------------------------------------------------------------------------- 1 | .de lsm-macro 2 | (nix) 3 | .. 4 | .lsm lsm-macro 5 | Home of Groff (GNU Troff). 6 | The USA site also contains older, obsolete versions. 7 | 8 | Home of Groff (GNU Troff). 9 | The USA site also contains older, obsolete versions. 10 | 11 | The development version is available from a CVS repository, see below. 12 | .nx 13 | -------------------------------------------------------------------------------- /examples/as.1: -------------------------------------------------------------------------------- 1 | .ds todayth \n(dy 2 | . 3 | .nr todays_last_digit \n(dy%10 4 | . 5 | .ie \n[todays_last_digit]=1 .as todayth \*{st\*} 6 | .el .ie \n[todays_last_digit]=2 .as todayth \*{nd\*} 7 | .el .ie \n[todays_last_digit]=3 .as todayth \*{rd\*} 8 | .el .as todayth \*{th\*} 9 | . 10 | Today is the \*[todayth]. 11 | -------------------------------------------------------------------------------- /examples/m.1: -------------------------------------------------------------------------------- 1 | .mso url.tmac 2 | .mso pagetag.tmac 3 | . 4 | .TG one 5 | 6 | one one one one one one 7 | see two and three 8 | 9 | .bp 10 | 11 | .TG two 12 | 13 | two two two two two 14 | see one 15 | 16 | .bp 17 | 18 | .TG three 19 | 20 | three three three three 21 | .tm calling string one 22 | see two but one \*[one] 23 | 24 | 25 | -------------------------------------------------------------------------------- /lua/z-neovim.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2019-09-29 2 | 3 | local running_in_neovim = (vim and type(vim) == 'table' and 4 | vim.api and type(vim.api) == 'table' and 5 | vim.api.nvim_eval and type(vim.api.nvim_eval) == 'function') 6 | 7 | if running_in_neovim then 8 | local retobj = {} 9 | retobj.troff2page = troff2page 10 | return retobj 11 | end 12 | -------------------------------------------------------------------------------- /examples/ts.1: -------------------------------------------------------------------------------- 1 | .TS 2 | center,box; 3 | c s s 4 | c s s 5 | c c c 6 | l r r. 7 | Production of Audio Equipment 8 | (units:1000 sets) 9 | _ 10 | Product 1984 1985 11 | _ 12 | General radio 1342314 12323 13 | Clock radio 123 1232 14 | radio/cassette 21323 2323 15 | General radio 1342314 12323 16 | Clock radio 123 1232 17 | radio/cassette 21323 2323 18 | .TE 19 | -------------------------------------------------------------------------------- /examples/al.1: -------------------------------------------------------------------------------- 1 | .de foo 2 | . tm \\$0 3 | .. 4 | .als bar foo 5 | . 6 | .de aaa 7 | . foo 8 | .. 9 | .de bbb 10 | . bar 11 | .. 12 | .de ccc 13 | \\*[foo]\\ 14 | .. 15 | .de ddd 16 | \\*[bar]\\ 17 | .. 18 | . 19 | START 20 | .aaa 21 | .\" error-> foo 22 | .bbb 23 | .\" error-> bar 24 | .ccc 25 | .\" error-> ccc 26 | .ddd 27 | .\" error-> ddd 28 | STOP 29 | -------------------------------------------------------------------------------- /examples/wh.1: -------------------------------------------------------------------------------- 1 | .SH 2 | Whale depletion in southern hemisphere 3 | .LP 4 | .TS 5 | tab(@), box; 6 | cb cb cb cb 7 | l r r r. 8 | type @ original @ remaining @ % killed 9 | humpbacks @ 100,000 @ 3,000 @ 97.0 10 | fin whales @ 400,000 @ 2,000 @ 99.5 11 | seis @ 150,000 @ 1,500 @ 99.0 12 | blue whales @ 180,000 @ 660 @ 99.6 13 | .TE 14 | -------------------------------------------------------------------------------- /examples/t4.1: -------------------------------------------------------------------------------- 1 | .TS 2 | tab(#), center, allbox; 3 | cb cb 4 | l l. 5 | Action # Effect 6 | n, space, mouse click # go to Next slide 7 | p, backspace # go to Previous Slide 8 | t, 0 # Title, or 0pening, slide 9 | \f[I]n\f[P] (integer \(>= 0) # \f[I]n\f[P]th slide 10 | b # toggle current slide with Black screen 11 | w # toggle current with White screen 12 | .TE 13 | 14 | 15 | -------------------------------------------------------------------------------- /bin/neovim-troff2page: -------------------------------------------------------------------------------- 1 | # last modified 2021-11-09 2 | # Dorai Sitaram 3 | 4 | # Use this if you have Neovim but not standalone Lua. 5 | 6 | # Assumes troff2page.lua and troff2page.vim 7 | # are in the lua/ and plugin/ subdirectories respectively 8 | # of a directory in 'runtimepath'. 9 | 10 | if test $# -eq 0; then 11 | echo troff2page needs at least one argument; exit 12 | fi 13 | 14 | echo Troff2page "$@" | nvim -es 15 | -------------------------------------------------------------------------------- /examples/un.1: -------------------------------------------------------------------------------- 1 | .\" length units 2 | 3 | .nr j 1u 4 | .tm 1 u = \nj 5 | 6 | .nr j 1i 7 | .tm 1 inch = \nj 8 | 9 | .nr j 1f 10 | .tm 1 f = \nj 11 | 12 | .nr j 1p 13 | .tm 1 point = \nj 14 | 15 | .nr j 1m 16 | .tm 1 em = \nj 17 | 18 | .nr j 1M 19 | .tm 1 M = \nj 20 | 21 | .nr j 1P 22 | .tm 1 pica = \nj 23 | 24 | .nr j 1c 25 | .tm 1 cm = \nj 26 | 27 | .nr j 1n 28 | .tm 1 en = \nj 29 | 30 | .nr j 1v 31 | .tm 1 v = \nj 32 | -------------------------------------------------------------------------------- /lua/z-luatex.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-11-16 2 | 3 | local running_in_luatex = (tex and tex.print) 4 | 5 | if running_in_luatex then 6 | function luatex_troff2page(s) 7 | s = string.gsub(s, '^%s*(.-)%s*$', '%1') 8 | s = string.gsub(s, '%s%s+', ' ') 9 | return troff2page(table.unpack(split_string(s, ' '))) 10 | end 11 | 12 | local retobj = {} 13 | retobj.troff2page = luatex_troff2page 14 | return retobj 15 | end 16 | -------------------------------------------------------------------------------- /examples/tg.1: -------------------------------------------------------------------------------- 1 | .mso s.tmac 2 | .mso www.tmac 3 | .mso url.tmac 4 | .RT 5 | .blm PP 6 | .TAG one 7 | .TAG two II 8 | 9 | Tag one is actually \*[TAG_one] (expected: 0). 10 | 11 | Tag two is actually \*[TAG_two] (expected: II). 12 | 13 | Referring to tag three 14 | .URL #three 15 | (expected: ). 16 | 17 | Referring to tag one 18 | .URL #one 19 | (expected: <0>). 20 | 21 | Referring to tag two 22 | .URL #two 23 | (expected: ). 24 | 25 | .TAG three III 26 | -------------------------------------------------------------------------------- /examples/kn.1: -------------------------------------------------------------------------------- 1 | .\" troff version of TeX's story.tex 2 | .sp 1i 3 | .ce 1 4 | .B "A SHORT STORY" 5 | .ce 0 6 | .sp 6p 7 | .ce 1 8 | .I "by A. U. Thor" \" !\(r?\(r?! (modified) 9 | .ce 0 10 | .sp .5c 11 | Once upon a time, in a distant 12 | galaxy called \(:O\(:o\(,c, 13 | there lived a computer 14 | named R.\~J. Drofnats. 15 | .PP 16 | Mr.\~Drofnats \(em or \(lqR. J.\(rq, as 17 | he preferred to be called \(em \" error has been fixed! 18 | was happiest when he was at work 19 | typesetting beautiful documents. 20 | .sp 1i 21 | -------------------------------------------------------------------------------- /docs/ebook.ms: -------------------------------------------------------------------------------- 1 | .\" last modified 2021-06-17 2 | .SH 1 3 | 7. Ebooks 4 | .LP 5 | .IX ebook 6 | .IX r t2pebook@-r t2pbook=1, Troff2page command-line option 7 | To have your groff source be converted into an ebook-style HTML, 8 | set the number register \fCt2pebook\fP to non-0 using the 9 | command-line option 10 | .EX 11 | -r t2pebook=1 12 | .EE 13 | This causes Troff2page to generate a single HTML page with no 14 | external CSS 15 | or image dependencies, and which can be sent to an ereader 16 | such as the Amazon Kindle. 17 | -------------------------------------------------------------------------------- /examples/th.1: -------------------------------------------------------------------------------- 1 | Here are the default sizes for \fBpic\fP objects: 2 | .PP 3 | .TS H 4 | center, tab(@), linesize(2); 5 | lb | lb 6 | l | l. 7 | .sp 2p 8 | Object@Default Size 9 | .sp 2p 10 | _ 11 | .sp 2p 12 | .TH 13 | box@0.75" wide by 0.5" high 14 | circle@0.5" diameter 15 | ellipse@0.75" wide by 0.5" high 16 | arc@0.5" radius 17 | line@0.5" long 18 | arrow@0.5" long 19 | .sp 5p 20 | _ 21 | .TE 22 | .PP 23 | The simplest way to think about these defaults is that they make the 24 | other basic objects fit snugly into a default-sized box. 25 | -------------------------------------------------------------------------------- /examples/cm.1: -------------------------------------------------------------------------------- 1 | .de makro1 2 | i arg = \\$1, ii arg = \\$2 3 | .. 4 | .PP 5 | This call sees only one arg, because the dq comment leaves eol 6 | .PP 7 | .makro1 1 \" comment 8 | .PP 9 | This call sees both args, because the sharp comment swallows the 10 | eol 11 | .PP 12 | .makro1 3 \# comment 13 | 4 14 | .PP 15 | .PP 16 | Laborum sint consequatur accusantium sed quia. Quidem sapiente 17 | atque nobis hic quia. Dicta minima cupiditate quidem labore qui 18 | tempore qui. Fugiat ut ducimus enim repellat sed qui est. Veniam 19 | in rerum praesentium incidunt sint asperiores. 20 | -------------------------------------------------------------------------------- /lua/Makefile: -------------------------------------------------------------------------------- 1 | # last modified 2021-11-09 2 | 3 | all: ../bin/troff2page.lua 4 | 5 | 0shebang.lua: [^0]*.lua 6 | test "${USER}" = ds26gte || exit 0; \ 7 | sed -i -e "s/[0-9]\{8\}/$$(date +%Y%m%d)/" 0shebang.lua 8 | 9 | ../bin/troff2page.lua: *.lua 10 | rm -f $@; 11 | for f in *.lua; do \ 12 | if echo $$f | grep -vq '\-Z-'; then \ 13 | cat $$f | grep -v '^-- last modified' >> $@; \ 14 | echo >> $@; \ 15 | fi; \ 16 | done; 17 | echo "troff2page(...)" >> $@; 18 | chmod +x $@ 19 | 20 | again: clean all 21 | 22 | clean: 23 | rm -f ../bin/troff2page.lua 24 | -------------------------------------------------------------------------------- /bin/luatex-troff2page: -------------------------------------------------------------------------------- 1 | # last modified 2021-11-09 2 | # Dorai Sitaram 3 | 4 | # Use this if you have LuaTeX but not standalone Lua. 5 | 6 | # Assumes troff2page.lua has been copied to a 7 | # directory in your TEXINPUTS. 8 | 9 | if test $# -eq 0; then 10 | echo troff2page needs at least one argument; exit 11 | fi 12 | 13 | cat > texput.tex <) 23 | -------------------------------------------------------------------------------- /examples/rm.1: -------------------------------------------------------------------------------- 1 | .\" last modified 2020-12-05 2 | . 3 | .nr Ar 0 4 | .nr Rr 0 5 | .af Rr I 6 | . 7 | .de R 8 | .nr Ar \\$1 9 | .nr Rr \\$1 10 | .tm \\n(Ar is \\n(Rr 11 | .. 12 | . 13 | .R 0 14 | .R 1 15 | .R 2 16 | .R 4 17 | .R 8 18 | .R 16 19 | .R 18 20 | .R 32 21 | .R 36 22 | .R 45 23 | .R 54 24 | .R 64 25 | .R 72 26 | .R 90 27 | .R 108 28 | .R 128 29 | .R 180 30 | .R 256 31 | .R 270 32 | .R 360 33 | .R 512 34 | .R 1024 35 | .R 2048 36 | .R 4096 37 | .R 4999 38 | .R 5000 39 | .R 5280 40 | .R 6080 41 | .R 8192 42 | .R 9999 43 | .R 10000 44 | .R 12000 45 | .R 16384 46 | .R 32768 47 | .R 39999 48 | -------------------------------------------------------------------------------- /examples/ja.1: -------------------------------------------------------------------------------- 1 | .RT 2 | .nr just_did_PP 0 3 | .de BLM 4 | .ie \\n[next_graf_without_indent] \{\ 5 | .nr next_graf_without_indent 0 6 | .LP 7 | .nr just_did_PP 0 8 | .\} 9 | .el \{\ 10 | .PP 11 | .nr just_did_PP 1 12 | .\} 13 | .. 14 | .blm BLM 15 | . 16 | .de LSM 17 | .nr 18 | .ie \\n[just_did_PP] \{\ 19 | .nr just_did_PP 0 20 | .ns 21 | .LP 22 | .\} 23 | .el .br 24 | .nr next_graf_without_indent 1 25 | \h'\\n[lsn]n' 26 | .. 27 | .\"lsm LSM 28 | lkajdflkj 29 | lkajdl lkajdf 30 | 31 | lkjadf 32 | 33 | one 34 | two 35 | three 36 | \& 37 | four 38 | five 39 | 40 | lkjadflkj 41 | adlkfj 42 | -------------------------------------------------------------------------------- /lua/stream.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-11-08 2 | 3 | function troff_open(stream_name, f) 4 | ensure_file_deleted(f) 5 | local h = io.open(f, 'w') 6 | Output_streams[stream_name] = h 7 | end 8 | 9 | function troff_close(stream_name) 10 | --print('doing troff_close') 11 | local h = Output_streams[stream_name] 12 | io.close(h) -- check h is truthy? 13 | Output_streams[stream_name] = nil 14 | end 15 | 16 | function write_troff_macro_to_stream(macro_name, o) 17 | --print('doing write_troff_macro_to_stream', macro_name) 18 | flet({ 19 | Outputting_to = 'troff', 20 | Out = o 21 | }, function() 22 | execute_macro(macro_name) 23 | end) 24 | end 25 | -------------------------------------------------------------------------------- /docs/style.tmac: -------------------------------------------------------------------------------- 1 | .\" last change 2021-02-09 2 | .\" Dorai Sitaram 3 | . 4 | .if \n[.X] \{\ 5 | .mso s \" heirloom troff 6 | .nr .U 1 7 | .\} 8 | . 9 | .mso pca.tmac 10 | . 11 | .so defhsl.tmac 12 | . 13 | .if d @init \{\ 14 | . am @init 15 | . nr FL \\n[LL] 16 | . . 17 | .\} 18 | . 19 | .nr HM .75i 20 | .nr FM 1.25i 21 | .ds CH " 22 | .ds CF \\n[%] 23 | . 24 | .ss 12 0 25 | . 26 | .if !\n[.troff2page] \{\ 27 | .nr GROWPS 2 28 | .nr PSINCR 2p 29 | .nr PI 1.5m 30 | .\} 31 | . 32 | .\"nr FPS \n[PS] 33 | .\"nr FVS \n[VS] 34 | . 35 | .defcolor terracottapink rgb #9b3d3d 36 | . 37 | .am @AU 38 | . ft R 39 | .. 40 | . 41 | .if \n[.X] \{\ 42 | .de DC 43 | \\$1\\$2 44 | .. 45 | .\} 46 | -------------------------------------------------------------------------------- /docs/index.ms: -------------------------------------------------------------------------------- 1 | .so style.tmac 2 | . 3 | .TL 4 | Troff2page 5 | .AU 6 | .ie \n[.troff2page] \{\ 7 | \*[url http://ds26gte.github.io]Dorai Sitaram\& 8 | \*[url https://github.com/ds26gte/troff2page]Download the 9 | \*[troff2page_version_th] version\& 10 | .\} 11 | .el \{\ Dorai Sitaram 12 | \*(DY 13 | .\} 14 | .RT 15 | . 16 | .ToC 17 | . 18 | .so intro.ms 19 | .so commands.ms 20 | .so layout.ms 21 | .so xrefs.ms 22 | .so genindex.ms 23 | .so slideshow.ms 24 | .so ebook.ms 25 | .so eval.ms 26 | .so styling.ms 27 | .so error.ms 28 | .so infodoc.ms 29 | .\"so nvimtex.ms 30 | .LP 31 | .if t \{\ 32 | .SH 1 33 | Index 34 | .LP 35 | .\"rs 36 | .\"if \n(.H .sp .8v 37 | .2C 38 | .\"sp -1v 39 | .so \*[AUXF].ind 40 | .\"1C 41 | .\} 42 | -------------------------------------------------------------------------------- /examples/1s.1: -------------------------------------------------------------------------------- 1 | .TL 2 | One small step for man, one giant leap for mankind 3 | .AU 4 | Neil Armstrong 5 | .RT 6 | . 7 | Harum ut quaerat et itaque aut. In possimus dolor omnis 8 | explicabo. Quibusdam repellendus reiciendis voluptatem ea 9 | repellat recusandae libero et. Aut et similique nihil et. Maiores 10 | modi veritatis excepturi. Est commodi qui cumque. Blanditiis 11 | nostrum tenetur velit rerum. Illum perferendis omnis non esse. 12 | Molestias est nesciunt expedita voluptas architecto consequuntur 13 | accusantium. Perferendis provident libero illo excepturi fuga. 14 | Praesentium a aut adipisci molestiae maxime eius. Voluptatum 15 | velit aut totam in natus. Qui quis in deleniti cupiditate eaque 16 | optio enim deserunt. 17 | -------------------------------------------------------------------------------- /examples/b1.1: -------------------------------------------------------------------------------- 1 | .blm PP 2 | Here is a famous para. 3 | 4 | .B1 5 | .RS 6 | Now is the time for all famous men to come to the aid of the 7 | party 8 | Now is the time for all famous men to come to the aid of the 9 | party 10 | Now is the time for all famous men to come to the aid of the 11 | party 12 | Now is the time for all famous men to come to the aid of the 13 | party 14 | Now is the time for all famous men to come to the aid of the 15 | party 16 | Now is the time for all famous men to come to the aid of the 17 | party 18 | Now is the time for all famous men to come to the aid of the 19 | party 20 | Now is the time for all famous men to come to the aid of the 21 | party 22 | .RE 23 | .B2 24 | 25 | Back to regular programming. 26 | -------------------------------------------------------------------------------- /examples/rd.1: -------------------------------------------------------------------------------- 1 | .PP 2 | Officiis est voluptas est. Debitis consequatur ullam a. Hic ipsum 3 | libero sit ex qui inventore deleniti. Non adipisci non ut eos hic 4 | incidunt est illo. Magni esse vel consectetur hic quo debitis et 5 | excepturi. Nesciunt et voluptas modi. 6 | .PP 7 | .tm Type some prose with \\\\$1 and \\\\$2 interspersed. 8 | .tm End with a blank line. 9 | .tm The output will contain your prose with \\\\$1 substituted 10 | .tm by dog and \\\\$2 substituted by cat. 11 | .tm 12 | .PP 13 | .rd "Start entering" dog cat 14 | .PP 15 | Quis voluptates nihil officiis qui id aperiam quia tenetur. Ullam 16 | molestias voluptatibus placeat rerum quia. Quod dicta voluptatum 17 | itaque suscipit. Qui asperiores qui fuga consequatur ea 18 | reprehenderit fugiat. 19 | -------------------------------------------------------------------------------- /examples/co.1: -------------------------------------------------------------------------------- 1 | .defcolor venetianred_resene rgb #72010f 2 | .defcolor venetianred_resene2 rgb #5b1f22 3 | .defcolor venetianred_hollasch rgb #d41a1f 4 | .defcolor venetianred_fignations rgb #75100b 5 | 6 | \m[venetianred_resene]this is venetian red resene on white.\m[] 7 | 8 | \M[venetianred_resene]this is black on venetian red resene.\M[] 9 | 10 | \m[venetianred_resene2]this is venetian red resene2 on white.\m[] 11 | 12 | \M[venetianred_resene2]this is black on venetian red resene2.\M[] 13 | 14 | \m[venetianred_hollasch]this is venetian red hollasch on white.\m[] 15 | 16 | \M[venetianred_hollasch]this is black on venetian red hollasch.\M[] 17 | 18 | \m[venetianred_fignations]this is venetian red fignations on white.\m[] 19 | 20 | \M[venetianred_fignations]this is black on venetian red fignations.\M[] 21 | 22 | -------------------------------------------------------------------------------- /examples/dv.1: -------------------------------------------------------------------------------- 1 | .TL 2 | Nested diversions 3 | .LP 4 | Qui nihil et aspernatur. Qui sit deserunt voluptas molestiae ut accusamus. Quos 5 | sunt ea ducimus illum dolorem pariatur. Tempore et voluptas voluptate. 6 | .br 7 | .di one 8 | one 9 | .br 10 | .di two 11 | two 12 | .br 13 | .di 14 | one continues 15 | .br 16 | .di 17 | .PP 18 | Cupiditate dolore porro eaque porro eligendi. Est ratione consequuntur a. 19 | Dolorem itaque sunt illo in quae optio voluptatem quasi. 20 | .PP 21 | .one 22 | .PP 23 | Sit ut autem eum maxime quasi. Minus qui et ut veniam. Harum sequi modi velit 24 | rerum qui alias. 25 | .PP 26 | .two 27 | .PP 28 | Impedit nulla quisquam suscipit alias ut perferendis. Qui earum at blanditiis 29 | quia. Sequi autem nostrum sit quia incidunt dicta et. Accusantium voluptas qui 30 | necessitatibus et exercitationem qui. Ad iste natus atque. 31 | -------------------------------------------------------------------------------- /lua/err.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-12-07 2 | 3 | function tlog(...) 4 | Log_stream:write(string.format(...)) 5 | end 6 | 7 | function twarning(...) 8 | tlog('%s:%s: ', Current_source_file, Input_line_no) 9 | tlog(...) 10 | tlog '\n' 11 | end 12 | 13 | function edit_offending_file() 14 | io.write(string.format('Type e to edit file %s at line %s; x to quit.\n', 15 | Current_source_file, Input_line_no)) 16 | io.write '? '; io.flush() 17 | local c = io.read(1) 18 | if c == 'e' then 19 | os.execute(string.format('%s +%s %s', 20 | os.getenv 'EDITOR' or 'vi', 21 | Input_line_no or '', Current_source_file or '')) 22 | end 23 | end 24 | 25 | function terror(...) 26 | twarning(...) 27 | close_all_open_streams() 28 | edit_offending_file() 29 | error 'troff2page fatal error' 30 | end 31 | 32 | function flag_missing_piece(mp) 33 | if not table_member(mp, Missing_pieces) then 34 | table.insert(Missing_pieces, mp) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # last modified 2021-11-07 2 | 3 | src_files = *.ms *.tmac 4 | 5 | define set-up-mpca 6 | @if ! echo $$GROFF_TMAC_PATH | grep -q '\bmpca\b'; then \ 7 | if test ! -f pca.tmac; then \ 8 | echo getting mpca from github; \ 9 | git clone https://github.com/ds26gte/mpca; \ 10 | cp -p mpca/tmac/*.tmac .; \ 11 | rm -fr mpca; \ 12 | fi; \ 13 | fi 14 | endef 15 | 16 | define groff 17 | $(call set-up-mpca) 18 | soelim index.ms | preconv | groff -U -mpca -t > index.ps 19 | endef 20 | 21 | all: index.html 22 | 23 | index.html: index.ms $(src_files) 24 | $(call set-up-mpca) 25 | troff2page.lua index.ms 26 | 27 | index.info: index.html 28 | 29 | index.ps: index.ms $(src_files) .trofftemp.ind 30 | $(call groff) 31 | 32 | .trofftemp.ind: index.ms $(src_files) 33 | $(call groff) 34 | 35 | ps: index.ps 36 | 37 | again: clean all 38 | 39 | clean: 40 | rm -f .troff2page_temp* index*-Z-* index.ps *.html *.info .trofftemp* pca*.tmac 41 | -------------------------------------------------------------------------------- /examples/sh.1: -------------------------------------------------------------------------------- 1 | .tm starting 2 | Iste optio alias explicabo inventore. In sunt dolor nemo. Illo vel provident 3 | quod excepturi nobis aut. Soluta voluptatibus voluptatem suscipit. Et sed 4 | commodi molestias. 5 | .PP 6 | Quas enim aperiam exercitationem ad ratione delectus. Alias quidem in dolorem 7 | aspernatur quo. Enim aut sed illum ipsam sunt. Aut vitae veniam qui. 8 | .PP 9 | .TOC 10 | .PP 11 | .SH 1 12 | Section 1 13 | .PP 14 | Qui non ea commodi excepturi laudantium rerum. Sequi commodi aut nihil. Sint 15 | itaque tempora qui sint temporibus. Error alias dolores molestias corporis 16 | dolore consequuntur. Minima dolorem fugiat impedit. Laborum assumenda autem 17 | laudantium architecto excepturi vel. 18 | .PP 19 | Et facilis quis quam quis. Placeat velit explicabo quo et perferendis. Veniam 20 | et et dignissimos enim. Magni ullam eos eum aliquam nihil. Minima doloremque 21 | aut praesentium libero corporis voluptatum doloremque. 22 | .PP 23 | .SH 1 24 | Section 2 25 | .PP 26 | Eos nemo laudantium sapiente eligendi ut. Omnis ut quia aut qui optio et 27 | ratione. Non omnis provident aut ipsum non. 28 | -------------------------------------------------------------------------------- /lua/footnote.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-06-17 2 | 3 | function emit_footnotes() 4 | if #Footnote_buffer == 0 then return end 5 | --print('emitfootnotes FS calling eep') 6 | emit_end_para() 7 | emit_verbatim '
' 12 | for i = 1, #Footnote_buffer do 13 | emit_para() 14 | local fn = Footnote_buffer[i] 15 | local fntag, fno, fnc = fn.tag, fn.number, fn.text 16 | if fntag then troff2page_line(fntag) 17 | elseif fno then 18 | local node_name = 'TAG:__troff2page_footnote_' .. fno 19 | emit(anchor(node_name)) 20 | emit(link_start(page_node_link(false, 'TAG:__troff2page_call_footnote_' .. fno), true)) 21 | emit_verbatim '' 22 | emit_verbatim(fno) 23 | emit_verbatim '' 24 | emit(link_stop()) 25 | emit_newline() 26 | end 27 | troff2page_chars(fnc) 28 | end 29 | --print('emitfootnotes FE calling eep') 30 | emit_end_para() 31 | emit_verbatim '
\n' 32 | Footnote_buffer = {} 33 | end 34 | -------------------------------------------------------------------------------- /docs/infodoc.ms: -------------------------------------------------------------------------------- 1 | .\" last modified 2021-11-08 2 | .SH 1 3 | 11. GNU Info docs 4 | .LP 5 | .TAG gnuinfo 6 | .IX Info files, generating 7 | .IX troff2page2info@.troff2page2info, Troff2page macro 8 | You can call the macro 9 | .EX 10 | .troff2page2info 11 | .EE 12 | within your document to signal to \fCtroff2page\fP that it should 13 | also create an Info document. 14 | .PP 15 | If the basename of the input groff document is \fCjobname\fP, the 16 | Info file is created in \fCjobname.info\fP, which may be 17 | displayed on any Info viewer. 18 | .PP 19 | .IX troff2pagerc.tmac@.troff2pagerc.tmac, user macro file 20 | .IX t2p@.t2p, user macro file 21 | A good place to set \fC.troff2page2info\fP without modifying the input groff 22 | document is in \fC.troff2pagerc.tmac\fP or \fCjobname.t2p\fP, 23 | described on page \*[TAG:troff2pagerc]. 24 | .PP 25 | .IX TROFF2PAGE2INFO, environment variable 26 | If you’re sure you will always want an Info file for whatever document 27 | you give to \fCtroff2page\fP, then you can set the 28 | environment variable \fCTROFF2PAGE2INFO\fP (the value doesn’t 29 | matter): 30 | .EX 31 | export TROFF2PAGE2INFO=always 32 | .EE 33 | -------------------------------------------------------------------------------- /examples/lb.1: -------------------------------------------------------------------------------- 1 | .mso pca.tmac 2 | .TL 3 | Some constants 4 | .SH 5 | Mathematical 6 | .LP 7 | \[*p] = 8 | .eval 9 | -- following prints pi, because cos(pi) = -1 10 | troff:write(math.acos(-1)) 11 | troff:write('\n') 12 | .endeval 13 | .PP 14 | e = 15 | .eval 16 | troff:write(math.exp(1)) 17 | troff:write('\n') 18 | .endeval 19 | .PP 20 | \[*f] = 21 | .eval 22 | troff:write((math.sqrt(5)+1)/2) 23 | troff:write('\n') 24 | .endeval 25 | .PP 26 | \fIi\fP = 27 | .eval 28 | troff:write('\\[sqrt](\\[mi]1)\n') 29 | .endeval 30 | .SH 31 | Weights & measures 32 | .LP 33 | 1 oz = 34 | .eval 35 | troff:write((1/16) * .45359237 * 1000) 36 | troff:write(' g\n') 37 | .endeval 38 | .PP 39 | 1 gal = 40 | .eval 41 | troff:write(231 * math.pow(2.54, 3) * (1/1000)) 42 | troff:write(' L\n') 43 | .endeval 44 | .PP 45 | 1 nmi = 46 | .eval 47 | troff:write(1852 * 100 * (1/2.54) * (1/12)) 48 | troff:write(' ft\n') 49 | .endeval 50 | .PP 51 | 1 phoot\** = 52 | .eval 53 | troff:write(.299792458 * 100 * (1/2.54) * (1/12)) 54 | troff:write(' foot\n') 55 | .endeval 56 | .FS 57 | A phoot is the distance traveled by a photon in 1 second, i.e., a 58 | light nanosecond. (N. David Mermin) 59 | .FE 60 | -------------------------------------------------------------------------------- /examples/ps.1: -------------------------------------------------------------------------------- 1 | Laborum quia aut qui sapiente facere eaque. Non magnam perferendis aut fugiat 2 | enim. Aperiam et nulla consectetur doloremque. Minima magnam mollitia magnam 3 | modi et. Soluta dolorem enim ut. Ipsa odio modi quas dolorem. 4 | 5 | Nostrum dicta dolor aperiam impedit non ut ut quae. Voluptate occaecati quia 6 | tempora incidunt culpa impedit. Aut aspernatur optio pariatur veritatis quis. 7 | Necessitatibus voluptatem earum doloremque optio est. Pariatur facilis aut 8 | corporis. 9 | 10 | .PSPIC t2p.eps 11 | 12 | Ipsum voluptate pariatur quidem necessitatibus cum eum omnis. Magni veritatis 13 | minima dicta. Ipsam natus quam minus sint. Quis porro dignissimos laborum. 14 | Voluptates quos sint corporis velit. 15 | 16 | Aliquid veritatis sint aut et. Error deleniti adipisci dolorem id nihil. 17 | Ducimus ipsum quas earum porro libero provident ut. Laborum vel aut quibusdam 18 | et cum rem laudantium sunt. Hic facere enim ut voluptates. Eligendi qui 19 | repellendus et ipsam. 20 | 21 | Aut repellendus inventore commodi consequuntur. Aut est aliquam repudiandae. 22 | Dolores eius magni ipsa aliquid doloremque. Repellendus magnam eaque 23 | doloremque. 24 | -------------------------------------------------------------------------------- /examples/s.1: -------------------------------------------------------------------------------- 1 | .blm PP 2 | .IP ienas 3 | oaiesnt aoseitn 4 | aoeisntoei 5 | aostne 6 | oaiesnt aoseitn 7 | aoeisntoei 8 | aostne 9 | oaiesnt aoseitn 10 | aoeisntoei 11 | aostne 12 | oaiesnt aoseitn 13 | aoeisntoei 14 | aostne 15 | oaiesnt aoseitn 16 | aoeisntoei 17 | aostne 18 | oaiesnt aoseitn 19 | aoeisntoei 20 | aostne 21 | oaiesnt aoseitn 22 | aoeisntoei 23 | aostne 24 | oaiesnt aoseitn 25 | aoeisntoei 26 | aostne 27 | 28 | .IP on 29 | aie aooeian o aoeisnt 30 | oeinas oiean stioen ioenastioena 31 | oaiesnt aoseitn 32 | oaiesnt aoseitn 33 | oaiesnt aoseitn 34 | oaiesnt aoseitn 35 | oaiesnt aoseitn 36 | oaiesnt aoseitn 37 | aoeisntoei 38 | aostne 39 | aoeisntoei 40 | aostne 41 | aoeisntoei 42 | aostne 43 | aoeisntoei 44 | aostne 45 | aoeisntoei 46 | aostne 47 | aoeisntoei 48 | aostne 49 | oaiesnt aoseitn 50 | aoeisntoei 51 | aostne 52 | 53 | .IP oi 54 | aoeisntoeian aienst 55 | aoseitnoastn 56 | oeast 57 | 58 | oaeisntone 59 | oaeisntone 60 | oaeisntone 61 | oaeisntone 62 | oaeisntone 63 | oaeisntone 64 | oaeisntonest 65 | oen 66 | oaeisntonest 67 | oen 68 | oaeisntonest 69 | oen 70 | oaeisntonest 71 | oen 72 | oaeisntonest 73 | oen 74 | oaeisntonest 75 | oen 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /lua/init.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-11-08 2 | 3 | function write_aux(...) 4 | Aux_stream:write(...) 5 | Aux_stream:write('\n') 6 | end 7 | 8 | function initialize_all_registers() 9 | initialize_glyphs() 10 | initialize_numregs() 11 | initialize_strings() 12 | initialize_macros() 13 | end 14 | 15 | 16 | function begin_html_document() 17 | 18 | --print('doing begin_html_document') 19 | 20 | 21 | --print('done initns') 22 | 23 | Convert_to_info_p = false 24 | 25 | Last_page_number = -1 26 | 27 | Pso_temp_file = Jobname .. Pso_file_suffix 28 | 29 | Rerun_needed_p = false 30 | 31 | do 32 | local f = Jobname .. Aux_file_suffix 33 | local fc = loadfile(f) 34 | if fc then 35 | --print('loading', f) 36 | fc() 37 | ensure_file_deleted(f) 38 | end 39 | Aux_stream = io.open(f, 'w') 40 | end 41 | 42 | emit_start() 43 | initialize_css_file() 44 | 45 | do 46 | local it = find_macro_file(os.getenv 'TROFF2PAGERC' or '.troff2pagerc.tmac') 47 | if it then troff2page_file(it) end 48 | it = Jobname .. '.t2p' 49 | if probe_file(it) then troff2page_file(it) end 50 | end 51 | 52 | Check_file_write_date=true 53 | end 54 | -------------------------------------------------------------------------------- /examples/ig.1: -------------------------------------------------------------------------------- 1 | 2 | Debitis voluptas magni culpa quae similique. Nobis eaque magni ipsa ducimus 3 | sit. Sint perferendis delectus quis. 4 | 5 | Voluptatem aperiam et qui corrupti voluptatem officia ut tenetur. Possimus 6 | molestiae aliquid et ut sequi provident reiciendis. Placeat ipsam dignissimos 7 | occaecati quia porro quam voluptatem. Labore aliquid exercitationem dolorem 8 | quod porro. 9 | 10 | This should show. 11 | 12 | .ig 13 | This should not show 14 | .. 15 | 16 | This should show. 17 | 18 | Vero provident quo alias quia nobis repellat. Omnis est dolorem itaque 19 | perspiciatis odio id. Consequatur iusto excepturi assumenda. Non aut iure 20 | voluptatem non. 21 | 22 | Nihil error architecto eius quo sit quibusdam. Incidunt cumque velit rerum 23 | labore aut unde. Adipisci velit esse perferendis quas non eaque ea. Voluptas 24 | autem mollitia hic explicabo et. Maxime dolorem officiis iure. Quos 25 | necessitatibus quos non. 26 | 27 | Exercitationem voluptas sequi dolores quasi repellat incidunt eveniet hic. Modi 28 | quis ipsa excepturi soluta eveniet sunt. Magni repellendus ducimus qui. Quo 29 | mollitia quidem iusto eaque. Enim ducimus voluptatem quam veniam voluptate et 30 | aut esse. 31 | -------------------------------------------------------------------------------- /examples/ex.1: -------------------------------------------------------------------------------- 1 | .LP 2 | Let’s use .char to convert the currency sign to a section sign. 3 | .char ¤ § 4 | .PP 5 | Text fenced by .EX/.EE renders as a monospace display only if 6 | troff2page is called with the -man or -mpca options. 7 | Backslash-qua-escape can be used, so backslash can’t be verbatim: 8 | use \ee or a .char kludge. Backslash-qua-escape is useful 9 | especially if UTF-8 characters are used either directly or via 10 | transliteration. It also allows the display to cross page 11 | boundaries. 12 | .EX 13 | Velit fuga maxime qui sunt 14 | \[u00B6] (<- backslash isn't verbatim) 15 | ¶ ❡ 9 o’clock (<- UTF-8 chars render as-is) 16 | ¤ (<- .char is respected) 17 | necessitatibus. Distinctio vitae 18 | perferendis aut et magni 19 | voluptatem. Quo reiciendis nam 20 | reiciendis sed ut atque 21 | laboriosam. 22 | .EE 23 | If you want backslash verbatim, and are willing to forgo UTF-8, 24 | call .EX with some (any) argument. Page boundaries can’t be 25 | crossed, as groff needs backslash-qua-escape at page breaks. 26 | Troff2page, unlike groff, will allow direct UTF-8 (not \e[uxxxx]) 27 | regardless, and page boundary considerations are anyway 28 | irrelevant in HTML. 29 | -------------------------------------------------------------------------------- /examples/tf.1: -------------------------------------------------------------------------------- 1 | .\" \text from testfont.tex 2 | .nr LL 7i 3 | .PP 4 | On November 14, 1885, Senator & Mrs. Leland Stanford called 5 | together at their San Francisco mansion the 24 prominent men who had 6 | been chosen as the first trustees of The Leland Stanford Junior University. 7 | They handed to the board the Founding Grant of the University, which they 8 | had executed three days before. This document — with various amendments, 9 | legislative acts, and court decrees — remains as the University’s charter. 10 | In bold, sweeping language it stipulates that the objectives of the University 11 | are “to qualify students for personal success and direct usefulness in life; 12 | and to promote the publick welfare by exercising an influence in behalf of 13 | humanity and civilization, teaching the blessings of liberty regulated by 14 | law, and inculcating love and reverence for the great principles of 15 | government as derived from the inalienable rights of man to life, liberty, 16 | and the pursuit of happiness.” 17 | .PP 18 | ¿But aren’t Kafka’s Schloß and Æsop’s Œuvres 19 | often naïve vis-à-vis the dæmonic phœnix’s official rôle 20 | in fluffy soufflés? 21 | .PP 22 | (¡THE DAZED BROWN FOX QUICKLY GAVE 12345–67890 JUMPS!) 23 | -------------------------------------------------------------------------------- /lua/do.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-06-17 2 | 3 | function do_afterpar() 4 | local it = Afterpar 5 | if it then 6 | Afterpar = false 7 | it() 8 | end 9 | end 10 | 11 | function do_eject() 12 | if raw_counter_value 't2pslides' ~=0 then 13 | --print('eject for slides') 14 | --print('eject/slides calling eep') 15 | emit_end_para() 16 | emit_verbatim '\n' 17 | emit_verbatim '
\n' 18 | emit_para() 19 | --print('done ejecting for slides') 20 | elseif raw_counter_value 't2pebook' ~=0 then 21 | emit_end_para() 22 | emit_para() 23 | elseif Single_output_page_p then 24 | emit_end_para() 25 | emit_verbatim '
' 26 | emit_para() 27 | else 28 | emit_end_page(); emit_start() 29 | end 30 | end 31 | 32 | function do_tmc(newlinep) 33 | --print('doing do_tmc') 34 | ignore_spaces() 35 | io.write(expand_args(read_troff_line())) 36 | if newlinep then io.write '\n' end 37 | end 38 | 39 | function do_writec(newlinep) 40 | local stream_name = expand_args(read_word()) 41 | local o = Output_streams[stream_name] 42 | o:write(expand_args(read_troff_string_line())) 43 | if newlinep then o:write '\n' end 44 | end 45 | -------------------------------------------------------------------------------- /examples/xp.1: -------------------------------------------------------------------------------- 1 | .\" last modified 2020-12-05 2 | .RT 3 | Voluptas odio enim quia harum. Repellat ea quos ullam enim 4 | repellendus dignissimos quam voluptatum. Nostrum tempora aut 5 | veritatis blanditiis. Est deserunt dicta quae. 6 | .PP 7 | Quo minima reprehenderit soluta. Iste alias distinctio accusamus. 8 | Rerum minima ad nulla hic cumque ab. Ut et eaque quo eum rerum 9 | exercitationem aut quasi. Hic modi ducimus quae impedit et 10 | doloremque. Deleniti ipsa magnam perspiciatis. 11 | .XP 12 | This paragraph hangs: Perferendis itaque delectus quam autem 13 | ipsam facere facilis. Qui aperiam sint nobis aliquam nostrum. 14 | Ullam aut cumque quasi cupiditate eum. Ea sint laudantium vel 15 | quia quasi harum. Esse quae quia iure voluptatem amet labore. 16 | Doloribus rerum omnis ut quis quis repellendus ratione vitae. 17 | Voluptas dolor itaque vitae sed cupiditate magni autem nulla. 18 | .PP 19 | Perferendis itaque delectus quam autem ipsam facere facilis. Qui 20 | aperiam sint nobis aliquam nostrum. Ullam aut cumque quasi 21 | cupiditate eum. Ea sint laudantium vel quia quasi harum. 22 | Esse quae quia iure voluptatem amet labore. Doloribus rerum omnis 23 | ut quis quis repellendus ratione vitae. Voluptas dolor itaque 24 | vitae sed cupiditate magni autem nulla. 25 | -------------------------------------------------------------------------------- /lua/dimen.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-02-09 2 | 3 | Gunit = {} 4 | 5 | function defunit(w, num) 6 | Gunit[w] = num 7 | end 8 | 9 | defunit('u', 1) 10 | defunit('i', 72000) 11 | defunit('f', 2^16) 12 | 13 | defunit('p', Gunit.i / 72) 14 | 15 | defunit('m', Gunit.p * 10) 16 | 17 | defunit('M', Gunit.m * .01) 18 | defunit('P', Gunit.p * 12) 19 | defunit('c', Gunit.i / 2.54) 20 | defunit('n', Gunit.m / 2) 21 | defunit('v', Gunit.p * 16) 22 | 23 | defunit('px', Gunit.i / 96) 24 | 25 | Unit_pattern = '[cfiMmnPpuv]' 26 | 27 | function point_equivalent_of(u) 28 | return Gunit[u]/Gunit.p 29 | end 30 | 31 | function read_length_in_pixels(unit) 32 | ignore_spaces() 33 | local n, unit_already_read_p = read_arith_expr() 34 | --print('\tread_arith_expr retd', n, unit_already_read_p) 35 | if unit_already_read_p then 36 | return n / Gunit.px 37 | end 38 | -- 39 | if unit then 40 | if string.match(unit, Unit_pattern) then 41 | return n*Gunit[unit] / Gunit.px 42 | end 43 | terror('Unknown length indicator %s', unit) 44 | end 45 | -- 46 | --XXX: deadc0de? 47 | local u = snoop_char() 48 | if u and string.match(u, Unit_pattern) then get_char() 49 | return n*Gunit[u] / Gunit.px 50 | end 51 | -- 52 | return math_round(4.5*n) -- XXX 53 | end 54 | -------------------------------------------------------------------------------- /docs/defhsl.tmac: -------------------------------------------------------------------------------- 1 | .\" last change 2020-12-03 2 | .\" Dorai Sitaram 3 | . 4 | .if d defhsl:loaded .nx 5 | .ds defhsl:loaded 1 6 | . 7 | .if !d eval \{\ 8 | .tm defhsl.tmac can't work without the .eval macro 9 | .nx 10 | .\} 11 | . 12 | .eval 13 | -- last modified 2017-08-16 14 | 15 | do 16 | local function between_0_and_1(n) 17 | if n < 0 then 18 | return n + 1 19 | elseif n > 1 then 20 | return n - 1 21 | else 22 | return n 23 | end 24 | end 25 | 26 | local function tc_to_c(tc, p, q) 27 | if tc < 1/6 then 28 | return p + (q - p)*6*tc 29 | elseif 1/6 <= tc and tc < 1/2 then 30 | return q 31 | elseif 1/2 <= tc and tc < 2/3 then 32 | return p + (q - p)*6*(2/3 - tc) 33 | else 34 | return p 35 | end 36 | end 37 | 38 | local function hsl_to_rgb(h, s, l) 39 | h = (h % 360) / 360 40 | local q 41 | if l < 1/2 then 42 | q = l * (s + 1) 43 | else 44 | q = 1 + s - l*s 45 | end 46 | local p = 2*l - q 47 | local tr = between_0_and_1(h + 1/3) 48 | local tg = between_0_and_1(h) 49 | local tb = between_0_and_1(h - 1/3) 50 | return tc_to_c(tr, p, q), 51 | tc_to_c(tg, p, q), 52 | tc_to_c(tb, p, q) 53 | end 54 | 55 | function def_hsl_color(name, h, s, l) 56 | local r, g, b = hsl_to_rgb(h, s, l) 57 | troff:write(string.format('.defcolor %s rgb %s %s %s\n', name, r, g, b)) 58 | end 59 | end 60 | .endeval 61 | -------------------------------------------------------------------------------- /lua/2globals.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-02-27 2 | 3 | Operating_system = 'unix' 4 | if os.getenv 'COMSPEC' then Operating_system = 'windows' end 5 | 6 | Ghostscript = 'gs' 7 | if Operating_system == 'windows' then 8 | for _,f in pairs {'g:\\cygwin\\bin\\gs.exe', 9 | 'g:\\cygwin\\bin\\gs.exe', 10 | 'c:\\aladdin\\gs6.01\\bin\\gswin32c.exe', 11 | 'd:\\aladdin\\gs6.01\\bin\\gswin32c.exe', 12 | 'd:\\gs\\gs8.00\\bin\\gswin32.exe', 13 | 'g:\\gs\\gs8.00\\bin\\gswin32.exe'} do 14 | if probe_file(f) then 15 | Ghostscript = f; break 16 | end 17 | end 18 | end 19 | 20 | Ghostscript_options = ' -q -dBATCH -dNOPAUSE -dNO_PAUSE -sDEVICE=ppmraw' 21 | 22 | Groff_image_options = '-fN -rPS=20 -rVS=24' 23 | 24 | Path_separator = ':' 25 | if Operating_system == 'windows' then Path_separator = ';' end 26 | 27 | Aux_file_suffix = '-Z-A.lua' 28 | Css_file_suffix = '-Z-S.css' 29 | Html_conversion_by = 'HTML conversion by' 30 | Html_page_suffix = '-Z-H-' 31 | Image_file_suffix = '-Z-G-' 32 | Image_format = 'png' 33 | Last_modified = 'Last modified: ' 34 | Log_file_suffix = '-Z-L.log' 35 | Navigation_contents_name = 'contents' 36 | Navigation_first_name = 'first' 37 | Navigation_index_name = 'index' 38 | Navigation_next_name = 'next' 39 | Navigation_page_name = ' page' 40 | Navigation_previous_name = 'previous' 41 | Navigation_sentence_begin = 'Go to ' 42 | Navigation_sentence_end = '' 43 | Output_extension = '.html' 44 | Pso_file_suffix = '-Z-T.1' 45 | 46 | -------------------------------------------------------------------------------- /bin/other-ways-to-call-troff2page.adoc: -------------------------------------------------------------------------------- 1 | = Other ways to call Troff2page 2 | 3 | You can use the built-in Lua of either Neovim or LuaTeX to run 4 | Troff2page. 5 | 6 | == Neovim 7 | 8 | Place `troff2page.vim` in a `plugin/` subdirectory on your 9 | `'runtimepath'`. 10 | 11 | Place `troff2page.lua` in a `lua/` subdirectory on your 12 | `'runtimepath'`. 13 | 14 | Script `neovim-troff2page` (rename to `troff2page` if desired) then 15 | calls Troff2page using Neovim's Lua. The argument syntax is 16 | exactly the same as for `troff2page.lua` as described in the 17 | manual. 18 | 19 | You can also use the Neovim command `:Troff2page` at the Neovim 20 | command line. It takes the same arguments as the shell script, 21 | and `%` stands for the file in the current editor window. In 22 | addition, calling it with no args converts the file in the 23 | current editor window. 24 | 25 | == LuaTeX 26 | 27 | Place `troff2page.lua` in a directory in your `TEXINPUTS`. 28 | 29 | Script `luatex-troff2page` (rename to `troff2page` if desired) then 30 | calls troff2page using LuaTeX's Lua. The argument syntax is 31 | exactly the same as for `troff2page.lua` as described in the 32 | manual. 33 | 34 | It can also be loaded into LuaTeX by 35 | 36 | \directlua{troff2page = require 'troff2page.lua'} 37 | 38 | This defines a Lua function `troff2page.troff2page` than can be 39 | called on troff documents with options as needed, e.g., 40 | 41 | \directlua{ 42 | troff2page.troff2page('-mpca -t doc.ms') 43 | } 44 | -------------------------------------------------------------------------------- /examples/ab.1: -------------------------------------------------------------------------------- 1 | .TL 2 | The Calculus of Conflict Resolution 3 | .AU 4 | Isaac Newton 5 | .AU 6 | Gottfried Wilhelm Leibniz 7 | .AI 8 | The Quadrature Continuum 9 | .AB 10 | Sit similique voluptate id. Ab laboriosam sunt asperiores 11 | voluptatem facilis rerum aliquam optio. Accusantium iste ducimus 12 | est autem nemo. Est quo id alias repellendus earum eveniet. Culpa 13 | alias qui adipisci esse. Non assumenda molestias nam quod 14 | quibusdam minima ratione. Magnam illum voluptatem nihil. Quia 15 | accusamus architecto sed perferendis voluptatem est. Et animi 16 | architecto architecto eveniet vel rem. Magni rerum nihil numquam 17 | quo et. Dolor qui repellendus voluptas laboriosam odio 18 | consectetur. Dolorum praesentium voluptatem ut eveniet. 19 | .AE 20 | .NH 1 21 | Introduction 22 | .LP 23 | Deleniti voluptatem vero voluptatem dicta sunt. Nihil culpa et 24 | voluptas sit deleniti modi aut fuga. Omnis illum distinctio omnis 25 | quae asperiores assumenda. Harum blanditiis eos inventore 26 | reiciendis quidem consequatur. Et vel quo quia delectus explicabo 27 | pariatur. Non iste unde et aut dolores cum asperiores et. 28 | .PP 29 | Hic incidunt atque eos ut possimus voluptatum sunt. Labore porro 30 | eos illum sed asperiores et ad harum. Omnis quaerat voluptas vel 31 | dolorem reprehenderit excepturi. Repudiandae non ut ullam. 32 | .PP 33 | Voluptate consequatur distinctio quo doloribus. Modi quia quod 34 | sed accusantium vero accusantium. Omnis laborum amet quia soluta 35 | laborum. 36 | .PP 37 | ••• 38 | -------------------------------------------------------------------------------- /lua/roman.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-12-07 2 | 3 | do 4 | local roman_quanta = { 10000, 5000, 1000, 500, 100, 50, 10, 5, 1 } 5 | 6 | local roman_digits = { 7 | [10000] = { 'z', 1000 }, 8 | [5000] = { 'w', 1000 }, 9 | [1000] = { 'm', 100 }, 10 | [500] = { 'd', 100 }, 11 | [100] = { 'c', 10 }, 12 | [50] = { 'l', 10 }, 13 | [10] = { 'x', 1 }, 14 | [5] = { 'v', 1 }, 15 | [1] = { 'i', 0 } 16 | } 17 | 18 | function toroman(n, downcasep) 19 | if not (type(n) == 'number' and math.floor(n) == n and n >= 0) then 20 | terror 'toroman: Missing number' 21 | end 22 | 23 | local function approp_case(c) 24 | if downcasep then return c 25 | else return string.upper(c) 26 | end 27 | end 28 | 29 | local n, i, s = n, 1, '' 30 | while true do 31 | if i > #roman_quanta then 32 | if s == '' then s = '0' end 33 | break 34 | end 35 | local val = roman_quanta[i] 36 | local d = roman_digits[val] 37 | local c, nextval = approp_case(d[1]), d[2] 38 | local q, r = math.floor(n / val), n % val 39 | while true do 40 | if q == 0 then 41 | if r >= (val - nextval) then 42 | n = r % nextval 43 | s = s .. approp_case(roman_digits[nextval][1]) .. c 44 | else 45 | n = r 46 | end 47 | i = i+1; break 48 | else 49 | q = q-1; s = s .. c 50 | end 51 | end 52 | end 53 | return s 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /examples/ht.1: -------------------------------------------------------------------------------- 1 | .ig 2 | $Id: htbl_test.ms,v 1.1 2004/05/28 17:24:41 larry Exp $ 3 | $Author: larry $ 4 | .. 5 | .RP no 6 | .TL 7 | A Test of 8 | .I htbl 9 | .AU 10 | Larry Kollar 11 | .AU 12 | Heinz-J\[:u]rgen Oertel 13 | .NH 1 14 | Introduction 15 | .LP 16 | The following table should be turned into HTML: 17 | .TS 18 | box; 19 | cb cb 20 | l l . 21 | Some Head Another 22 | data more data 23 | what the hey? 24 | .TE 25 | the same table with "allbox" 26 | .TS 27 | allbox; 28 | cb cb 29 | l l . 30 | Some Head Another 31 | data more data 32 | what the hey? 33 | .TE 34 | .LP 35 | gabble gabble gabble 36 | .NH 2 37 | Another table showing the "expand" attribute. 38 | .LP 39 | .TS 40 | box, expand; 41 | l c r. 42 | Left side Middle Right side 43 | .TE 44 | .LP 45 | ``Talk to me,'' the mime cried. 46 | .NH 2 47 | Test with another tab character 48 | .LP 49 | .TS 50 | tab(#), allbox, expand; 51 | l c r. 52 | Left side#Middle#Right side 53 | .TE 54 | .LP 55 | Should work, even the tab() attribute is at another place 56 | .LP 57 | .TS 58 | allbox, expand, tab(#); 59 | l c r. 60 | Left side#Middle#Right side 61 | .TE 62 | .NH 2 63 | What happens with ".\\" and "_" ? 64 | .LP 65 | .TS 66 | ; 67 | l l. 68 | first line 69 | second line 70 | _ 71 | fourth line 72 | .\" this is only a comment 73 | 6th line 74 | .TE 75 | .ex 76 | .NH 2 77 | Another example for a horizontal rule in tables 78 | .LP 79 | .TS 80 | tab(#), box, expand; 81 | l c r. 82 | eins#zwei (first line)#1,00 83 | _ 84 | drei#vier#1,00 85 | three#for#1,00 86 | _ 87 | f\[:u]nf#sechs (last line)#1,00 88 | .TE 89 | -------------------------------------------------------------------------------- /lua/nb.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-06-17 2 | 3 | function nb_macro_package(m) 4 | Macro_package = m 5 | if m=='ms' then 6 | local r = get_counter_named('GS') 7 | r.value = 1 8 | end 9 | end 10 | 11 | function nb_last_page_number(n) 12 | Last_page_number = n 13 | end 14 | 15 | function nb_single_output_page() 16 | --print('calling nb_single_output_page') 17 | Single_output_page_p = true 18 | Last_page_number = 0 19 | end 20 | 21 | function nb_node(node, pageno, tag_value) 22 | -- print('doing nb_node') 23 | Node_table[node] = pageno 24 | defstring(node, function() 25 | return link_start(page_node_link(pageno, node), true) .. 26 | verbatim(tag_value) .. link_stop() 27 | end) 28 | end 29 | 30 | function nb_header(s) 31 | table.insert(Html_head, s) 32 | end 33 | 34 | function nb_redirect(f) 35 | Redirected_p = true 36 | nb_header('') 37 | end 38 | 39 | function nb_verbatim_apostrophe() 40 | Verbatim_apostrophe_p = true 41 | end 42 | 43 | function nb_title(title) 44 | Title = title 45 | end 46 | 47 | function nb_stylesheet(css) 48 | table.insert(Stylesheets, css) 49 | end 50 | 51 | function nb_script(jsf) 52 | table.insert(Scripts, jsf) 53 | end 54 | 55 | function nb_last_modification_time(t) 56 | Last_modification_time = t 57 | end 58 | 59 | function nb_preferred_last_modification_time(s) 60 | Preferred_last_modification_time = s 61 | end 62 | 63 | function nb_source_changed_since_last_time_p() 64 | Source_changed_since_last_time_p = true 65 | end 66 | -------------------------------------------------------------------------------- /docs/error.ms: -------------------------------------------------------------------------------- 1 | .\" last modified 2021-06-17 2 | .SH 1 3 | 10. Recovery from errors 4 | .LP 5 | .IX errors 6 | .IX text editor 7 | If Troff2page fails on your document, it will display a message giving its 8 | best guess on what the problem is and where it occurred in the source 9 | document. It also offers to take you there in your text editor so you can fix it immediately. 10 | .EX 11 | \&\f(CIfilename:lineno: error description\fP 12 | Type e to edit file filename at line lineno; x to quit 13 | ? 14 | .EE 15 | In the first line, or the error diagnostic line, 16 | \f(CIfilename\fP is the particular source file (which need not be the 17 | main document file) and \f(CIlineno\fP is the estimated number of the line in 18 | that file that caused the error. (This is a popular error-reporting format 19 | and is exploited by text editors for helping the debugging process.) 20 | .PP 21 | In the second line, Troff2page offers to fire up a text editor with the cursor 22 | approximately close to the 23 | offending line. 24 | .PP 25 | .IX errors!editing location of 26 | If you type \fCe\fP at the \fC?\fP prompt, Troff2page starts the editor specified in your 27 | \fCEDITOR\fP environment variable, or if that is not set, the editor named 28 | \fCvi\fP on your system. Troff2page calls the editor with two arguments: 29 | the first argument is \fC+\fP followed by the line number, and the second 30 | argument is the filename. 31 | (This argument style works for \fIall\fP 32 | vi and emacs clones and I suspect most modern editors take care 33 | to recognize it, so it isn’t as restrictive as it sounds.) 34 | -------------------------------------------------------------------------------- /lua/disp.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-06-17 2 | 3 | function troff_align_to_html(i) 4 | if not i then 5 | i = 'I' 6 | end 7 | if i == 'C' then return 'center' 8 | elseif i == 'B' then return 'block' 9 | elseif i == 'R' then return 'right' 10 | elseif i == 'L' then return 'left' 11 | else return 'indent' 12 | end 13 | end 14 | 15 | function start_display(w) 16 | --print('### doing start_display') 17 | w = troff_align_to_html(w) 18 | local extra_arg = read_args() 19 | emit_para() 20 | emit_verbatim '
' 42 | emit_newline() 43 | ev_push 'display_environment' 44 | unfill_mode() 45 | --print('### start_display finished') 46 | end 47 | 48 | function stop_display() 49 | --print('### calling stop_display') 50 | read_troff_line() 51 | emit(switch_style()) 52 | ev_pop() 53 | emit_newline() 54 | emit_verbatim '
' 55 | emit_newline() 56 | emit_para() 57 | --print('### stop_display finished') 58 | end 59 | -------------------------------------------------------------------------------- /docs/slideshow.ms: -------------------------------------------------------------------------------- 1 | .\" last modified 2021-06-17 2 | .SH 1 3 | 6. Slideshows 4 | .LP 5 | .IX slideshow 6 | .IX Slidy 7 | .IX r t2pslides@-r t2pslides=1, Troff2page command-line option 8 | To have your groff source be converted into slideshow-ready 9 | HTML, set the number register \fCt2pslides\fP to non-0 using the 10 | command-line option 11 | .EX 12 | -r t2pslides=1 13 | .EE 14 | This causes Troff2page to use the style sheet \fCslide.css\fP and JavaScript file 15 | \fCslidy.js\fP from \*[url https://www.w3.org/Talks/Tools/#slidy]Slidy\& to convert 16 | your document into a single 17 | HTML page that can be browsed as a slideshow. Troff2page looks for these files in 18 | the working directory, and if they’re not found there, it links 19 | them from the W3C website. It may be prudent to get these files 20 | beforehand and place them in your working directory, so the 21 | presentation doesn’t rely on WiFi. 22 | .PP 23 | A new slide is started for each 24 | level-1 section, i.e., \fC.SH 1\fP and \fC.NH 1\fP. 25 | (Note of course 26 | that it doesn’t make sense to convert generic groff documents 27 | into presentations. The sections have got to be pretty short!) 28 | .PP 29 | An HTML page meant for presentation uses larger, bolder fonts by 30 | default (but you can add your own CSS). There are no navigation 31 | bars between slides. 32 | .PP 33 | .IX pause@.pause, Troff2page macro 34 | Use the \fC.pause\fP macro to 35 | interrupt display of the rest of the current slide. 36 | .PP 37 | Consult the \*[url https://www.w3.org/Talks/Tools/Slidy2/Overview.html]Slidy documentation\& for the keypresses and clicks you can use 38 | to progress through or dynamically alter the look of your 39 | presentation. 40 | -------------------------------------------------------------------------------- /lua/am.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-12-15 2 | 3 | function accent_marks() 4 | 5 | defstring('`', function() 6 | return verbatim '̀' 7 | end) 8 | 9 | defstring("'", function() 10 | return verbatim '́' 11 | end) 12 | 13 | defstring('^', function() 14 | return verbatim '̂' 15 | end) 16 | 17 | defstring("~", function() 18 | return verbatim '̃' 19 | end) 20 | 21 | defstring("_", function() 22 | return verbatim '̄' 23 | end) 24 | 25 | defstring(":", function() 26 | return verbatim '̈' 27 | end) 28 | 29 | defstring("o", function() 30 | return verbatim '̊' 31 | end) 32 | 33 | defstring("v", function() 34 | return verbatim '̌' 35 | end) 36 | 37 | defstring(".", function() 38 | return verbatim '̣' 39 | end) 40 | 41 | defstring(",", function() 42 | return verbatim '̧' 43 | end) 44 | 45 | -- 46 | 47 | defstring('?', function() 48 | return verbatim '¿' 49 | end) 50 | 51 | defstring('!', function() 52 | return verbatim '¡' 53 | end) 54 | 55 | defstring('8', function() 56 | return verbatim 'ß' 57 | end) 58 | 59 | defstring('3', function() 60 | return verbatim 'ȝ' 61 | end) 62 | 63 | defstring('Th', function() 64 | return verbatim 'Þ' 65 | end) 66 | 67 | defstring('th', function() 68 | return verbatim 'þ' 69 | end) 70 | 71 | defstring('D-', function() 72 | return verbatim 'Ð' 73 | end) 74 | 75 | defstring('d-', function() 76 | return verbatim 'ð' 77 | end) 78 | 79 | defstring('q', function() 80 | return verbatim 'ǫ' 81 | end) 82 | 83 | defstring('ae', function() 84 | return verbatim 'æ' 85 | end) 86 | 87 | defstring('Ae', function() 88 | return verbatim 'Æ' 89 | end) 90 | 91 | defglyph('hooko', verbatim 'ǫ') 92 | 93 | end 94 | -------------------------------------------------------------------------------- /examples/h1.1: -------------------------------------------------------------------------------- 1 | .nr HTML1 1 2 | 3 | Minima cum quod repellat. Eum vitae qui vel. Officiis autem autem 4 | aut in laborum et animi. 5 | 6 | Eveniet assumenda minus officia ipsum. Temporibus exercitationem 7 | unde in deleniti cupiditate labore. Odit accusamus eius fugit 8 | enim nostrum. 9 | 10 | Quod necessitatibus aspernatur et corrupti repudiandae fugiat 11 | dolor cum. Excepturi sed perferendis est nemo. Vel laudantium 12 | repudiandae sequi dolore animi voluptatum similique porro. 13 | 14 | Voluptates tenetur a accusantium exercitationem earum esse 15 | voluptas. Ullam eius sed dolore maiores maxime. Magni porro cum 16 | enim ut explicabo. Necessitatibus autem temporibus consectetur. 17 | Non cum beatae expedita consequatur deleniti consequatur. 18 | Voluptatem est id ab omnis. 19 | 20 | Ipsam in in commodi est officiis corrupti ut. Qui voluptatem et 21 | et et perspiciatis corrupti quis sit. Nulla laudantium est autem. 22 | Dolor quae nostrum libero atque reprehenderit voluptatibus 23 | repudiandae. Molestias nihil omnis totam. 24 | 25 | .bp 26 | 27 | NEXT PAGE NOT RESPECTED AS EXPECTED! 28 | 29 | Ea velit nam soluta error non. Perferendis sequi accusantium 30 | labore. Qui labore aliquam nulla officiis. Aut rerum tempore 31 | suscipit quia dolor autem iste sunt. 32 | 33 | Vel ut commodi quia. Quaerat qui eligendi rem et blanditiis. 34 | Molestiae dolores est debitis sed. Optio vel fugit dolores sed 35 | deleniti nemo. Est vero reprehenderit mollitia sint. 36 | 37 | Voluptatem soluta dicta alias. Aliquam quia numquam officiis eos 38 | voluptatem mollitia. Eaque debitis minus veniam magni ut aut. Et 39 | quis aut animi expedita velit voluptatem saepe. 40 | 41 | Necessitatibus suscipit quo consequatur nam aut at rerum. Eum cum 42 | blanditiis magni est ut quia accusamus veniam. Voluptatum numquam 43 | id voluptatem quia ducimus beatae repellat delectus. Rerum rerum 44 | laudantium consectetur debitis. 45 | -------------------------------------------------------------------------------- /lua/ev.lua: -------------------------------------------------------------------------------- 1 | function ev_copy(lhs, rhs) 2 | lhs.hardlines = rhs.hardlines 3 | lhs.font = rhs.font 4 | lhs.color = rhs.color 5 | lhs.bgcolor = rhs.bgcolor 6 | lhs.prevfont = rhs.prevfont 7 | lhs.prevcolor = rhs.prevcolor 8 | end 9 | 10 | function ev_pop() 11 | if #Ev_stack > 1 then 12 | local ev_curr = table.remove(Ev_stack, 1) 13 | ev_switch(ev_curr, Ev_stack[1]) 14 | end 15 | end 16 | 17 | function ev_push(new_ev_name) 18 | local new_ev = ev_named(new_ev_name) 19 | local curr_ev = Ev_stack[1] 20 | table.insert(Ev_stack, 1, new_ev) 21 | ev_switch(curr_ev, new_ev) 22 | end 23 | 24 | function ev_switch(ev_old, ev_new) 25 | if ev_new ~= ev_old then 26 | local old_font, old_color, old_bgcolor, old_size, 27 | new_font, new_color, new_bgcolor, new_size = 28 | ev_old.font, ev_old.color, ev_old.bgcolor, ev_old.size, 29 | ev_new.font, ev_new.color, ev_new.bgcolor, ev_new.size 30 | if old_font or old_color or old_bgcolor or old_size then 31 | emit_verbatim '' 32 | end 33 | if new_font or new_color or new_bgcolor or new_size then 34 | emit(make_span_open { 35 | font=new_font, color=new_color, bgcolor=new_bgcolor, size=new_size 36 | }) 37 | end 38 | end 39 | end 40 | 41 | function ev_named(s) 42 | local res = Ev_table[s] 43 | if not res then 44 | res = { name = s } 45 | Ev_table[s] = res 46 | end 47 | return res 48 | end 49 | 50 | function fill_mode() 51 | --print('turn fill on') 52 | Ev_stack[1].hardlines = false 53 | end 54 | 55 | function unfill_mode() 56 | --print('turn fill off') 57 | Ev_stack[1].hardlines = true 58 | end 59 | 60 | function fillp() 61 | return not Ev_stack[1].hardlines 62 | end 63 | 64 | function ev_top() 65 | local top = Ev_stack[1] 66 | return { 67 | hardlines = top.hardlines, 68 | font = top.font, 69 | color = top.color, 70 | bgcolor = top.bgcolor, 71 | } 72 | end 73 | -------------------------------------------------------------------------------- /docs/index.t2p: -------------------------------------------------------------------------------- 1 | .\" last modified 2021-06-17 2 | . 3 | .\"nr HTML1 1 4 | . 5 | .de HBP 6 | .bp 7 | .. 8 | . 9 | .nr PI 0 10 | .nr PD 1v 11 | .nr LL 6.5i 12 | . 13 | .nr GROWPS 3 14 | .nr PSINCR 3p 15 | . 16 | .rn @SH @SH_orig 17 | . 18 | .de @SH 19 | .nr style:@SH:arg1 \\$1 20 | .shift 21 | .if '\\n[style:@SH:arg1]'1' .HBP 22 | .@SH_orig \\n[style:@SH:arg1] \\$* 23 | .. 24 | . 25 | .als SH @SH 26 | . 27 | .HX 1 28 | . 29 | .ds troff2page_version_th \n[.troff2page] 30 | . 31 | .nr troff2page_version_last_2_digits \n[.troff2page]%100 32 | .nr troff2page_version_last_digit \n[troff2page_version_last_2_digits]%10 33 | . 34 | .ie \n[troff2page_version_last_2_digits]=11 .as troff2page_version_th \*{th\*} 35 | .el .ie \n[troff2page_version_last_2_digits]=12 .as troff2page_version_th \*{th\*} 36 | .el .ie \n[troff2page_version_last_2_digits]=13 .as troff2page_version_th \*{th\*} 37 | .el .ie \n[troff2page_version_last_digit]=1 .as troff2page_version_th \*{st\*} 38 | .el .ie \n[troff2page_version_last_digit]=2 .as troff2page_version_th \*{nd\*} 39 | .el .ie \n[troff2page_version_last_digit]=3 .as troff2page_version_th \*{rd\*} 40 | .el .as troff2page_version_th \*{th\*} 41 | . 42 | .troff2page2info 43 | . 44 | .ig ## 45 | if raw_counter_value 't2pebook' == 0 then 46 | CSS:write([[ 47 | @media screen { 48 | h1.title { 49 | color: #333333; 50 | padding-bottom: 10px; 51 | border-bottom: 1px solid #dddddf; 52 | } 53 | 54 | h1,h2,h3,h4,h5,h6 { 55 | color: #9b3d3d; /* terracotta pink */ 56 | font-family: sans-serif; 57 | font-weight: normal; 58 | } 59 | 60 | a { 61 | /* color: #dd4814; /* ubuntu orange */ 62 | text-decoration: none; 63 | border-bottom: 1px dotted; 64 | } 65 | 66 | a:hover { 67 | /* color: #333333; */ 68 | background-color: #fdca01; /* ubuntu yellow */ 69 | } 70 | } 71 | 72 | body { 73 | font-family: georgia, serif; 74 | line-height: 1.4; 75 | } 76 | 77 | .dropcap { 78 | font-size: 500%; 79 | } 80 | ]]) 81 | end 82 | .## 83 | -------------------------------------------------------------------------------- /examples/li.1: -------------------------------------------------------------------------------- 1 | .nf 2 | \e(em \(em 3 | \e(hy \(hy 4 | \e- \- 5 | \e(bu \(bu 6 | \e(sq \(sq 7 | \e(ru \(ru 8 | \e(14 \(14 9 | \e(12 \(12 10 | \e(34 \(34 11 | \e(fi \(fi 12 | \e(fl \(fl 13 | \e(ff \(ff 14 | \e(Fi \(Fi 15 | \e(Fl \(Fl 16 | \e(de \(de 17 | \e(dg \(dg 18 | \e(fm \(fm 19 | \e(ct \(ct 20 | \e(rg \(rg 21 | \e(co \(co 22 | 23 | \e(sc \(sc 24 | \e(aa \(aa 25 | \e(ga \(ga 26 | \e(ul \(ul 27 | \e(-> \(-> 28 | \e(<- \(<- 29 | \e(ua \(ua 30 | \e(da \(da 31 | \e(br \(br 32 | \e(dd \(dd 33 | \e(rh \(rh 34 | \e(lh \(lh 35 | \e(ci \(ci 36 | 37 | \e(pl \(pl 38 | \e(mi \(mi 39 | \e(eq \(eq 40 | \e(** \(** 41 | \e(sl \(sl 42 | \e(sr \(sr 43 | \e(rn \(rn 44 | \e(>= \(>= 45 | \e(<= \(<= 46 | \e(== \(== 47 | \e(~= \(~= 48 | \e(ap \(ap 49 | \e(!= \(!= 50 | \e(mu \(mu 51 | \e(di \(di 52 | \e(+- \(+- 53 | \e(cu \(cu 54 | \e(ca \(ca 55 | \e(sb \(sb 56 | \e(sp \(sp 57 | \e(ib \(ib 58 | \e(ip \(ip 59 | \e(if \(if 60 | \e(pd \(pd 61 | \e(gr \(gr 62 | \e(no \(no 63 | \e(is \(is 64 | \e(pt \(pt 65 | \e(es \(es 66 | \e(mo \(mo 67 | \e(or \(or 68 | 69 | \e(lt \(lt 70 | \e(lk \(lk 71 | \e(lb \(lb 72 | \e(rt \(rt 73 | \e(rk \(rk 74 | \e(rb \(rb 75 | \e(lc \(lc 76 | \e(bv \(bv 77 | \e(lf \(lf 78 | \e(rc \(rc 79 | \e(rf \(rf 80 | 81 | \e(*a \(*a 82 | \e(*b \(*b 83 | \e(*g \(*g 84 | \e(*d \(*d 85 | \e(*e \(*e 86 | \e(*z \(*z 87 | \e(*y \(*y 88 | \e(*h \(*h 89 | \e(*i \(*i 90 | \e(*k \(*k 91 | \e(*l \(*l 92 | \e(*m \(*m 93 | \e(*n \(*n 94 | \e(*c \(*c 95 | \e(*o \(*o 96 | \e(*p \(*p 97 | \e(*r \(*r 98 | \e(*s \(*s 99 | \e(ts \(ts 100 | \e(*t \(*t 101 | \e(*u \(*u 102 | \e(*f \(*f 103 | \e(*x \(*x 104 | \e(*q \(*q 105 | \e(*w \(*w 106 | \e(*A \(*A 107 | \e(*B \(*B 108 | \e(*G \(*G 109 | \e(*D \(*D 110 | \e(*E \(*E 111 | \e(*Z \(*Z 112 | \e(*Y \(*Y 113 | \e(*H \(*H 114 | \e(*I \(*I 115 | \e(*K \(*K 116 | \e(*L \(*L 117 | \e(*M \(*M 118 | \e(*N \(*N 119 | \e(*C \(*C 120 | \e(*O \(*O 121 | \e(*P \(*P 122 | \e(*R \(*R 123 | \e(*S \(*S 124 | \e(*T \(*T 125 | \e(*U \(*U 126 | \e(*F \(*F 127 | \e(*X \(*X 128 | \e(*Q \(*Q 129 | \e(*W \(*W 130 | -------------------------------------------------------------------------------- /lua/color.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2017-08-17 2 | 3 | function frac_to_rgb256(n) 4 | n = math_round(n*256) 5 | if n==256 then n=n-1 end 6 | return string.format('%2x', n) 7 | end 8 | 9 | function read_color_number(hashes) 10 | if hashes==1 then return string.format('%s%s', get_char(), get_char()) 11 | elseif hashes==2 then return string.format('%s%s', get_char(), 12 | (function() get_char(); get_char(); return get_char() end)'') 13 | else ignore_spaces() 14 | local n = read_arith_expr(); local c = snoop_char() 15 | if c=='f' then get_char() end 16 | return frac_to_rgb256(n) 17 | end 18 | end 19 | 20 | function cmy_to_rgb(c,m,y) 21 | return { 22 | frac_to_rgb256(1-c), 23 | frac_to_rgb256(1-m), 24 | frac_to_rgb256(1-y) 25 | } 26 | end 27 | 28 | function cmyk_to_rgb(c,m,y,k) 29 | return cmy_to_rgb( 30 | c*(1-k) + k, 31 | m*(1-k) + k, 32 | y*(1-k) + k) 33 | end 34 | 35 | function read_rgb_color() 36 | local scheme = read_word() 37 | local number_hashes = 0 38 | local number_components = 0 39 | local components = {} 40 | if scheme=='rgb' or scheme=='cmy' then number_components=3 41 | elseif scheme=='cmyk' then number_components=4 42 | elseif scheme=='gray' then number_components=1 43 | elseif scheme=='grey' then scheme='gray'; number_components=1 44 | end 45 | ignore_spaces() 46 | if snoop_char() == '#' then get_char() 47 | number_hashes=number_hashes+1 48 | if snoop_char() == '#' then get_char() 49 | number_hashes=number_hashes+1 50 | end 51 | end 52 | table.insert(components, read_color_number(number_hashes)) 53 | if number_components>=3 then 54 | table.insert(components, read_color_number(number_hashes)) 55 | table.insert(components, read_color_number(number_hashes)) 56 | end 57 | if number_components==4 then 58 | table.insert(components, read_color_number(number_hashes)) 59 | end 60 | if scheme~='rgb' then 61 | for i=1,#components do 62 | local n=components[i] 63 | components[i] = tonumber('0x'..n)/256 64 | end 65 | end 66 | if scheme=='cmyk' then components = cmyk_to_rgb(table.unpack(components)) 67 | elseif scheme=='cmy' then components = cmy_to_rgb(table.unpack(components)) 68 | elseif scheme=='gray' then components = cmyk_to_rgb(0,0,0, components[1]) 69 | end 70 | return '#'..table.concat(components) 71 | end 72 | -------------------------------------------------------------------------------- /INSTALL.adoc: -------------------------------------------------------------------------------- 1 | = Installing troff2page 2 | 3 | Get the troff2page distribution from GitHub: 4 | 5 | git clone https://github.com/ds26gte/troff2page 6 | 7 | This creates a directory `troff2page`. `cd` to it. 8 | 9 | Copy the script `bin/troff2page.lua` (`bin/troff2page` is a soft 10 | link) to a directory in your PATH. 11 | 12 | Copy the file `man/man1/troff2page.1` to the `man1` subdirectory of a 13 | directory in your `MANPATH`. 14 | 15 | troff2page can, if it finds them on your system, can make 16 | effective use of the `*.tmac` files from the `mpca` repo. `mpca` 17 | is available from https://github.com/ds26gte/mpca. Getting `mpca` is 18 | optional: You can still use troff2page fruitfully even 19 | if you have no need for the `mpca` features. 20 | 21 | The troff2page documentation (in the `docs` subdirectory) does 22 | rely on `mpca`. However, the `Makefile` in the `docs` directory 23 | will get the needed macro files for one-off use if it doesn't 24 | find them on your system. 25 | 26 | NOTE: If you do decide to download `mpca`, include its `tmac` subdirectory in 27 | your `GROFF_TMAC_PATH`; or add the `pca*.tmac` files in it to 28 | some directory already in your `GROFF_TMAC_PATH`. In a pinch, if 29 | you don't want to mess with `GROFF_TMAC_PATH`, you may simply 30 | copy these `*.tmac` files to your home directory. 31 | 32 | == Man page 33 | 34 | You can now consult the man page `troff2page(1)` 35 | to get started with using troff2page. 36 | 37 | man troff2page 38 | 39 | == System requirements 40 | 41 | `troff2page.lua` has been tested on Lua 5.1.5, 5.2.4 and 42 | 5.3.3; LuaJIT 2.0.4; RaptorJIT 1.0.0; Neovim 0.5.0-dev; and 43 | LuaTeX 1.12.0. 44 | 45 | NOTE: The branch `lisp` in the troff2page git repository contains 46 | an older implementation in Common Lisp. 47 | 48 | == Documentation 49 | 50 | Documentation for troff2page is available online at 51 | http://ds26gte.github.io/troff2page/index.html. 52 | 53 | The troff sources for this document, `index.ms` and subfiles, are 54 | available in the `docs` subdirectory of the distribution. It can 55 | be processed with either groff or troff2page. To convert it into 56 | HTML, you must have installed troff2page, including the macro 57 | files that come with this distribution, as described above. 58 | 59 | If calling groff on `index.ms`, you will need to run groff twice 60 | in order to pick up all the auxiliary file info. (There will be a 61 | message reminding you to do so.) 62 | -------------------------------------------------------------------------------- /lua/links.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-11-18 2 | 3 | function anchor(lbl) 4 | --print('doing anchor', lbl) 5 | return verbatim '' 8 | end 9 | 10 | function link_start(link, internal_node_p) 11 | return verbatim '' 16 | end 17 | 18 | function link_stop() 19 | return verbatim '' 20 | end 21 | 22 | function page_link(pageno) 23 | return page_node_link(pageno, false) 24 | end 25 | 26 | function page_node_link(link_pageno, node) 27 | local curr_pageno = Current_pageno 28 | if not link_pageno then 29 | link_pageno = curr_pageno 30 | end 31 | local res = '' 32 | if link_pageno ~= curr_pageno then 33 | res = Jobname 34 | if link_pageno ~= 0 then 35 | res = res .. Html_page_suffix .. link_pageno 36 | end 37 | res = res .. Output_extension 38 | end 39 | if node then 40 | res = res .. '#' .. node 41 | end 42 | return res 43 | end 44 | 45 | function link_url(url) 46 | if string.sub(url, 1, 1) ~= '#' then 47 | return url, nil 48 | end 49 | url = string.sub(url, 2, -1) 50 | It = Node_table[url] 51 | if It then 52 | return page_node_link(It, url), true 53 | else 54 | return '[???]', false 55 | end 56 | end 57 | 58 | function url_to_html(url, link_text) 59 | --print('doing url_to_html', url, link_text) 60 | local internal_node_p 61 | url, internal_node_p = link_url(url) 62 | local lk = link_start(url, internal_node_p) .. 63 | link_text .. 64 | link_stop() 65 | --print('url_to_html returning', lk) 66 | return lk 67 | end 68 | 69 | function urlh_string_value(url, link_text) 70 | if not link_text then 71 | link_text = '' 72 | local link_text_more, c 73 | while true do 74 | link_text_more = read_till_char('\\', true) 75 | link_text = link_text .. link_text_more 76 | c = snoop_char() 77 | if not c then 78 | link_text = link_text .. '\\'; break 79 | elseif c == '&' then 80 | get_char(); break 81 | else 82 | link_text = link_text .. '\\' 83 | end 84 | end 85 | end 86 | if not url then 87 | url = link_text 88 | end 89 | if link_text == '' then 90 | link_text = url 91 | end 92 | return url_to_html(url, expand_args(link_text)) 93 | end 94 | -------------------------------------------------------------------------------- /lua/counters.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-02-09 2 | 3 | function left_zero_pad(n, reqd_length) 4 | local n = tostring(n) 5 | local length_so_far = #n 6 | if length_so_far >= reqd_length then return n 7 | else 8 | for i = 1, reqd_length - length_so_far do 9 | n = 0 .. n 10 | end 11 | return n 12 | end 13 | end 14 | 15 | function get_counter_named(name) 16 | local r = Numreg_table[name] 17 | if not r then 18 | r = { value = 0, format = '1' } 19 | Numreg_table[name] = r 20 | end 21 | return r 22 | end 23 | 24 | function increment_section_counter(lvl) 25 | if lvl then 26 | local h_lvl = 'H' .. lvl 27 | local c_lvl = get_counter_named(h_lvl) 28 | c_lvl.value = c_lvl.value + 1 29 | while true do 30 | lvl = lvl + 1 31 | c_lvl = Numreg_table['H' .. lvl] 32 | if not c_lvl then break end 33 | c_lvl.value = 0 34 | end 35 | end 36 | end 37 | 38 | function section_counter_value() 39 | local lvl = raw_counter_value('nh*hl') 40 | return lvl>0 and 41 | (function() 42 | local r = formatted_counter_value('H1') 43 | local i = 2 44 | while true do 45 | if i > lvl then break end 46 | r = r .. '.' .. formatted_counter_value('H' .. i) 47 | i = i + 1 48 | end 49 | return r 50 | end)() 51 | end 52 | 53 | function get_counter_value(c) 54 | --print('doing get_counter_value', c) 55 | local v, f, thk = c.value, c.format, c.thunk 56 | if thk then 57 | return tostring(thk()) -- but what if f = 's' 58 | elseif f == 's' then 59 | return v 60 | elseif f == 'A' then 61 | if v == 0 then return '0' 62 | else return string.char(v + string.byte('A') - 1) 63 | end 64 | elseif f == 'a' then 65 | if v == 0 then return '0' 66 | else return string.char(v + string.byte('a') - 1) 67 | end 68 | elseif f == 'I' then 69 | return toroman(v) 70 | elseif f == 'i' then 71 | return toroman(v, 'lowercase') 72 | elseif tonumber(f) and #f > 1 then 73 | return left_zero_pad(v, #f) 74 | else 75 | return tostring(v) 76 | end 77 | end 78 | 79 | function raw_counter_value(str) 80 | return get_counter_named(str).value 81 | end 82 | 83 | function counter_value_in_points(str) 84 | return raw_counter_value(str)/Gunit.p 85 | end 86 | 87 | function counter_value_in_pixels(str) 88 | return raw_counter_value(str)/Gunit.px 89 | end 90 | 91 | function formatted_counter_value(str) 92 | return get_counter_value(get_counter_named(str)) 93 | end 94 | -------------------------------------------------------------------------------- /lua/initnumregs.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-01-29 2 | 3 | function defnumreg(w, ss) 4 | Numreg_table[w] = ss 5 | end 6 | 7 | function initialize_numregs() 8 | defnumreg('.F', {format = 's', thunk = function() return Current_source_file; end}) 9 | defnumreg('.z', {format = 's', thunk = function() return Current_diversion; end}) 10 | 11 | defnumreg('%', {thunk = function() return Current_pageno; end}) 12 | defnumreg('.$', {thunk = function() return #Macro_args - 1; end}) 13 | defnumreg('.c', {thunk = function() return Input_line_no; end}) 14 | defnumreg('c.', {thunk = function() return Input_line_no; end}) 15 | defnumreg('.i', {thunk = function() return Margin_left; end}) 16 | defnumreg('.u', {thunk = function() return bool_to_num(not Ev_stack[1].hardlines); end}) 17 | defnumreg('.ce', {thunk = function() return Lines_to_be_justified; end}) 18 | defnumreg('.rj', {thunk = function() return Lines_to_be_justified; end}) 19 | defnumreg('lsn', {thunk = function() return Leading_spaces_number; end}) 20 | defnumreg('lss', {thunk = function() return Leading_spaces_number * Gunit.p*2.5; end}) 21 | defnumreg('$$', {thunk = function() 22 | local s = io.open '/proc/self/stat' 23 | if s then return s:read '*number' else return 0xbadc0de end 24 | end}) 25 | 26 | defnumreg('.T', {value = 1}) 27 | defnumreg('.U', {value = 1}) 28 | defnumreg('.color', {value = 1}) 29 | defnumreg('.troff2page', {value = Troff2page_version}) 30 | local version_yr = math.floor(Troff2page_version/10000) 31 | local version_wo_yr = Troff2page_version - version_yr*10000 32 | defnumreg('.x', {value = version_yr}) 33 | defnumreg('.y', {value = math.floor(version_wo_yr/100)}) 34 | defnumreg('.Y', {value = version_wo_yr%100}) 35 | defnumreg('www:HX', {value = -1}) 36 | defnumreg('GROWPS', {value = 0}) 37 | defnumreg('PS', {value = 10*Gunit.p}) 38 | defnumreg('PSINCR', {value = Gunit.p}) 39 | defnumreg('PI', {value = 5*Gunit.n}) 40 | defnumreg('PD', {value = .3*Gunit.v}) 41 | defnumreg('DD', {value = .5*Gunit.v}) 42 | 43 | defnumreg('DI', {value = raw_counter_value 'PI'}) 44 | 45 | defnumreg('.SHmag', {value = 1.2}) 46 | 47 | do 48 | local t = os.date '*t' 49 | defnumreg('seconds', {value = t.sec}) 50 | defnumreg('minutes', {value = t.min}) 51 | defnumreg('hours', {value = t.hour}) 52 | defnumreg('dw', {value = t.wday}) 53 | defnumreg('dy', {value = t.day}) 54 | defnumreg('mo', {value = t.month}) 55 | defnumreg('year', {value = t.year}) 56 | defnumreg('yr', {value = t.year - 1900}) 57 | end 58 | 59 | end 60 | -------------------------------------------------------------------------------- /docs/genindex.ms: -------------------------------------------------------------------------------- 1 | .\" last modified 2021-02-09 2 | .SH 1 3 | 5. Making an index 4 | .LP 5 | .IX index 6 | .IX pca-ix.tmac, macro file 7 | .IX MakeIndex 8 | The supplied macro file \fCpca-ix.tmac\fP 9 | creates a sorted 10 | index, with the aid of the external program MakeIndex. 11 | MakeIndex is included with TeX distributions, but you can 12 | also obtain \*[url \ 13 | http://stuff.mit.edu/afs/sipb/project/tex-dev/src/tar/makeindex.tar.gz]just 14 | the MakeIndex distribution\&. 15 | .PP 16 | Note that the indexes created by groff and Troff2page are 17 | necessarily different, because the respective paginations 18 | are different. In addition, the index generated for 19 | Troff2page has the additional feature of hyperlinking to the 20 | appropriate locations in the body text. 21 | .PP 22 | .IX IX@.IX, -mpca macro 23 | The call 24 | .EX 25 | .IX item 26 | .EE 27 | marks the text “item” as an indexable item. The metacharacters \fC@\fP, 28 | \fC!\fP, \fC"\fP, and \fC|\fP can be used to respectively specify (a) 29 | alternate alphabetization, (b) subitems, (c) literal metacharacters, and 30 | (d) encapsulation of the page number. 31 | .PP 32 | E.g., 33 | .EX 34 | .IX m@-m, groff option 35 | .EE 36 | identifies an index entry for “-m, groff option” but alphabetizes 37 | it as though it were “m” rather than something that starts with a 38 | hyphen. 39 | .EX 40 | .IX groff!macro packages 41 | .EE 42 | makes “macro packages” an indented index subentry under “groff”. 43 | Up to two \fC!\fPs may be used. 44 | .EX 45 | .IX groff!macro packages!ms 46 | .EE 47 | produces “ms” as a subsubentry under “macro packages” under 48 | “groff”. 49 | .EX 50 | .IX troff|see groff 51 | .EE 52 | has the index entry for “troff” point to 53 | “groff” rather than have a page number of its own. 54 | .PP 55 | If any of the metacharacters need to 56 | appear in the index entry as themselves, precede them with 57 | \fC"\fP. 58 | .EX 59 | .IX set"!car 60 | .EE 61 | creates an index entry for “set!car” rather than creating a 62 | subentry “car” under “set"”. 63 | .PP 64 | Please see the 65 | MakeIndex 66 | documentation for all the details. Essentially, the syntax for entering 67 | index entries is the same \*[url \ 68 | http://tex.loria.fr/bibdex/makeindex.pdf]as for LaTeX\&, except that in groff we use 69 | “\fC.IX item\fP” where in LaTeX one would use 70 | \%“\fC\eindex{item}\fP”. 71 | .PP 72 | \fCpca-ix.tmac\fP will call MakeIndex to create a 73 | sorted index in the auxiliary file \fC\e*[AUXF].ind\fP, which can be 74 | slurped back into the input document: 75 | .EX 1 76 | .so \*[AUXF].ind 77 | .EE 78 | Adding a section header on top is up to you. 79 | -------------------------------------------------------------------------------- /lua/inputenc.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-02-08 2 | 3 | B_1000_0000 = 0x80 4 | B_1100_0000 = 0xc0 5 | B_1110_0000 = 0xe0 6 | B_1111_0000 = 0xf0 7 | B_1111_1000 = 0xf8 8 | B_0001_1111 = 0x1f 9 | B_0000_1111 = 0x0f 10 | B_0000_0111 = 0x07 11 | B_0011_1111 = 0x3f 12 | 13 | function get_char(dont_translate_p) 14 | --print('doing get_char', dont_translate_p) 15 | local buf = Current_troff_input.buffer 16 | local strm = Current_troff_input.stream 17 | local c 18 | if #buf > 0 then 19 | c = table.remove(buf, 1) 20 | --print('\tbuf nonempty <', c, '>') 21 | elseif not strm then 22 | --print('\tno stream') 23 | return false 24 | else 25 | c = strm:read(1) 26 | if not c then 27 | --print('\tno c') 28 | return false 29 | elseif c == '\r' then 30 | -- if \r return \n. If a real \n follows, discard it 31 | c = '\n' 32 | local c2 = strm:read(1) 33 | if c2 and c2 ~= '\n' then 34 | table.insert(buf, 1, c2) 35 | end 36 | --print('\treturn char') 37 | return c 38 | end 39 | end 40 | -- 41 | -- 42 | local c1byte = string.byte(c) 43 | if c1byte < B_1000_0000 then 44 | -- c1byte = 0xxx_xxxx 45 | local g = false 46 | --FIXME 47 | if Macro_copy_mode_p or dont_translate_p then 48 | --print('\tnot translating', c) 49 | no_op() 50 | else 51 | --print('\ttranslating', c) 52 | g = Unescaped_glyph_table[c] 53 | end 54 | if g then 55 | toss_back_string(g) 56 | return get_char() 57 | else 58 | return c 59 | end 60 | end 61 | -- 62 | local ucode 63 | if c1byte < B_1110_0000 then 64 | -- c1byte = 110x_xxxx 65 | local c2byte = string.byte(strm:read(1)) 66 | --print('c1=', c1byte, 'c2=', c2byte) 67 | ucode = ((c1byte & B_0001_1111) << 6) + 68 | ( c2byte & B_0011_1111) 69 | -- 70 | elseif c1byte < B_1111_0000 then 71 | -- c1byte = 1110_xxxx 72 | local c2byte = string.byte(strm:read(1)) 73 | local c3byte = string.byte(strm:read(1)) 74 | --print('c1=', c1byte, 'c2=', c2byte, 'c3=', c3byte) 75 | ucode = ((c1byte & B_0000_1111) << 12) + 76 | ( (c2byte & B_0011_1111) << 6) + 77 | ( c3byte & B_0011_1111) 78 | -- 79 | elseif c1byte < B_1111_1000 then 80 | -- c1byte = 1111_0xxx 81 | local c2byte = string.byte(strm:read(1)) 82 | local c3byte = string.byte(strm:read(1)) 83 | local c4byte = string.byte(strm:read(1)) 84 | --print('c1=', c1byte, 'c2=', c2byte, 'c3=', c3byte, 'c4=', c4byte) 85 | ucode = ((c1byte & B_0000_0111) << 18) + 86 | ( (c2byte & B_0011_1111) << 12) + 87 | ( (c3byte & B_0011_1111) << 6) + 88 | ( c4byte & B_0011_1111) 89 | -- 90 | else 91 | terror 'get_char' 92 | return false 93 | end 94 | -- 95 | --print(string.format('get_char returned unicode %X\n', ucode)) 96 | toss_back_string(string.format('[u%04X]', ucode)) 97 | return Superescape_char 98 | end 99 | -------------------------------------------------------------------------------- /examples/dc.1: -------------------------------------------------------------------------------- 1 | .CSSS 2 | .dropcap { 3 | color: blue; 4 | } 5 | .CSSE 6 | .TL 7 | Drop-cap color 8 | .LP 9 | .DC T ROFF2PAGE 10 | Default from CSS. If no .dropcap color setting in CSS, black. 11 | Here we've embedded the CSS in the doc, and the color is blue. 12 | Sit officia doloremque aperiam odio. Excepturi sit qui fugiat. 13 | Qui qui fuga nihil est quia aliquid aut. Impedit labore 14 | voluptates occaecati rerum eaque. Ex voluptates voluptatem 15 | dolores. Quidem est accusantium est animi aut nihil. Laudantium 16 | nemo assumenda porro ut asperiores. Sapiente possimus veniam ipsa 17 | sit ullam ut. Nobis nam et quo aut velit tempora. Voluptatem 18 | atque placeat aliquid. Blanditiis voluptatem fugit architecto eos 19 | non labore assumenda. Ipsa hic fugit velit consequatur voluptas 20 | perspiciatis. Odit molestias dolorem fugit. Sunt quaerat nihil 21 | accusamus dicta. Molestiae vero aliquid et ut officiis. Molestiae 22 | ut distinctio sunt totam nobis libero. Ducimus recusandae 23 | perferendis modi officia reiciendis dolorem. Aut a aliquam dicta 24 | maiores est id veniam. Magni qui consequatur dolorum iste dicta 25 | iure in velit. 26 | .LP 27 | .DC T ROFF2PAGE green 28 | From explicit arg green. 29 | Sit officia doloremque aperiam odio. Excepturi sit qui fugiat. 30 | Qui qui fuga nihil est quia aliquid aut. Impedit labore 31 | voluptates occaecati rerum eaque. Ex voluptates voluptatem 32 | dolores. Quidem est accusantium est animi aut nihil. Laudantium 33 | nemo assumenda porro ut asperiores. Sapiente possimus veniam ipsa 34 | sit ullam ut. Nobis nam et quo aut velit tempora. Voluptatem 35 | atque placeat aliquid. Blanditiis voluptatem fugit architecto eos 36 | non labore assumenda. Ipsa hic fugit velit consequatur voluptas 37 | perspiciatis. Odit molestias dolorem fugit. Sunt quaerat nihil 38 | accusamus dicta. Molestiae vero aliquid et ut officiis. Molestiae 39 | ut distinctio sunt totam nobis libero. Ducimus recusandae 40 | perferendis modi officia reiciendis dolorem. Aut a aliquam dicta 41 | maiores est id veniam. Magni qui consequatur dolorum iste dicta 42 | iure in velit. 43 | .LP 44 | .DC T ROFF2PAGE #9b3d3d 45 | From explicit RGB arg (terracotta pink). 46 | Sit officia doloremque aperiam odio. Excepturi sit qui fugiat. 47 | Qui qui fuga nihil est quia aliquid aut. Impedit labore 48 | voluptates occaecati rerum eaque. Ex voluptates voluptatem 49 | dolores. Quidem est accusantium est animi aut nihil. Laudantium 50 | nemo assumenda porro ut asperiores. Sapiente possimus veniam ipsa 51 | sit ullam ut. Nobis nam et quo aut velit tempora. Voluptatem 52 | atque placeat aliquid. Blanditiis voluptatem fugit architecto eos 53 | non labore assumenda. Ipsa hic fugit velit consequatur voluptas 54 | perspiciatis. Odit molestias dolorem fugit. Sunt quaerat nihil 55 | accusamus dicta. Molestiae vero aliquid et ut officiis. Molestiae 56 | ut distinctio sunt totam nobis libero. Ducimus recusandae 57 | perferendis modi officia reiciendis dolorem. Aut a aliquam dicta 58 | maiores est id veniam. Magni qui consequatur dolorum iste dicta 59 | iure in velit. 60 | -------------------------------------------------------------------------------- /lua/initstrings.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-12-07 2 | 3 | function defstring(w, th) 4 | String_table[w] = th 5 | end 6 | 7 | function initialize_strings() 8 | 9 | defstring('-', function() 10 | return verbatim '—' 11 | end) 12 | 13 | defstring('{', function() 14 | return verbatim '' 15 | end) 16 | 17 | defstring('}', function() 18 | return verbatim '' 19 | end) 20 | 21 | defstring('<', function() 22 | return verbatim '' 23 | end) 24 | 25 | defstring('>', function() 26 | return verbatim '' 27 | end) 28 | 29 | defstring('*', function() 30 | This_footnote_is_numbered_p = true 31 | Footnote_count = Footnote_count +1 32 | do 33 | local n = tostring(Footnote_count) 34 | return anchor('TAG:__troff2page_call_footnote_' .. n) .. 35 | link_start(page_node_link(nil, 'TAG:__troff2page_footnote_' .. n), true) .. 36 | verbatim '' .. 37 | verbatim(n) .. 38 | verbatim '' .. 39 | link_stop() 40 | end 41 | end) 42 | 43 | defstring('REFERENCES', function() 44 | return 'References' 45 | end) 46 | 47 | defstring('ABSTRACT', function() 48 | return 'ABSTRACT' 49 | end) 50 | 51 | defstring('TOC', function() 52 | return verbatim 'Table of contents' 53 | end) 54 | 55 | defstring('MONTH1', function() 56 | return 'January' 57 | end) 58 | 59 | defstring('MONTH2', function() 60 | return 'February' 61 | end) 62 | 63 | defstring('MONTH3', function() 64 | return 'March' 65 | end) 66 | 67 | defstring('MONTH4', function() 68 | return 'April' 69 | end) 70 | 71 | defstring('MONTH5', function() 72 | return 'May' 73 | end) 74 | 75 | defstring('MONTH6', function() 76 | return 'June' 77 | end) 78 | 79 | defstring('MONTH7', function() 80 | return 'July' 81 | end) 82 | 83 | defstring('MONTH8', function() 84 | return 'August' 85 | end) 86 | 87 | defstring('MONTH9', function() 88 | return 'September' 89 | end) 90 | 91 | defstring('MONTH10', function() 92 | return 'October' 93 | end) 94 | 95 | defstring('MONTH11', function() 96 | return 'November' 97 | end) 98 | 99 | defstring('MONTH12', function() 100 | return 'December' 101 | end) 102 | 103 | defstring('MO', function() 104 | return String_table['MONTH'..get_counter_named 'mo'.value]() 105 | end) 106 | 107 | defstring('DY', function() 108 | return verbatim(get_counter_named 'dy'.value .. ' ' .. 109 | String_table.MO() .. ' ' .. 110 | get_counter_named 'year'.value) 111 | end) 112 | 113 | defstring('Q', function() 114 | return verbatim '“' 115 | end) 116 | 117 | defstring('U', function() 118 | return verbatim '”' 119 | end) 120 | 121 | defstring('.T', function() 122 | return 'webpage' 123 | end) 124 | 125 | defstring('AUXF', function() 126 | return verbatim('.troff2page_temp_' .. Jobname) 127 | end) 128 | 129 | defstring('pca-eval-lang', function() 130 | return 'lua' 131 | end) 132 | 133 | defstring(':', urlh_string_value) 134 | defstring('url', urlh_string_value) 135 | defstring('urlh', urlh_string_value) 136 | 137 | end 138 | -------------------------------------------------------------------------------- /lua/image.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-06-18 2 | 3 | function next_html_image_file_stem() 4 | Image_file_count = Image_file_count + 1 5 | return Jobname .. Image_file_suffix .. Image_file_count 6 | end 7 | 8 | function call_with_image_stream(p) 9 | local img_file_stem = next_html_image_file_stem() 10 | local aux_file = img_file_stem .. '.troff' 11 | with_open_output_file(aux_file, p) 12 | if Image_format=='ascii' then 13 | source_ascii_file(troff_to_ascii(img_file_stem)) 14 | else 15 | source_image_file(troff_to_image(img_file_stem)) 16 | end 17 | end 18 | 19 | function ps_to_image_png(f) 20 | local png_file = f .. '.png' 21 | os.execute(Ghostscript .. Ghostscript_options .. ' -sOutputFile=' .. f .. '.ppm.1 ' .. f .. '.ps quit.ps') 22 | os.execute('pnmcrop ' .. f .. '.ppm.1 > ' .. f .. '.ppm.tmp') 23 | os.execute('pnmtopng -interlace -transparent "#FFFFFF" < ' .. f .. '.ppm.tmp > ' .. png_file) 24 | for _,e in pairs({'.ppm.1', '.ppm.tmp', '.ppm'}) do 25 | ensure_file_deleted(f .. e) 26 | end 27 | return png_file 28 | end 29 | 30 | -- add ps_to_image for jpeg, gif? netpbm vs imagemagick? 31 | 32 | function ps_to_image(f, fmt) 33 | -- Image_format is png only, for now 34 | if fmt ~= 'png' then terror('only png supported for now') end 35 | return ps_to_image_png(f) 36 | end 37 | 38 | function do_img_src(f) 39 | --print('doing do_img_src', f) 40 | if raw_counter_value 't2pebook' ==0 then 41 | emit_verbatim(f) 42 | else 43 | --local tmpf = Jobname..'-Z-Z.temp' 44 | local tmpf= 'imagefile.temp' 45 | os.execute('echo -n data: > ' .. tmpf) 46 | os.execute('echo -n $(file -bN --mime-type ' .. f .. ') >> ' .. tmpf) 47 | os.execute('echo -n \\;base64, >> ' .. tmpf) 48 | os.execute('base64 -w0 < ' .. f .. ' >> ' .. tmpf) 49 | copy_file_bytes_to_stream(tmpf, Out) 50 | --ensure_file_deleted(tmpf) 51 | end 52 | end 53 | 54 | function source_image_file(img_file) 55 | emit_verbatim '['
 58 |   emit_verbatim(img_file)
 59 |   emit_verbatim ']' 60 | end 61 | 62 | function source_ascii_file(ascii_file) 63 | start_display 'I' 64 | emit(switch_font 'C') 65 | flet({ 66 | Sourcing_ascii_file_p = true, 67 | Turn_off_escape_char_p = true 68 | }, function() 69 | troff2page_file(ascii_file, 'dont_check_date') 70 | end) 71 | stop_display() 72 | end 73 | 74 | function troff_to_image(f) 75 | local img_file = f .. '.' .. Image_format 76 | if not probe_file(img_file) then 77 | os.execute('groff -pte -ms -Tps ' .. Groff_image_options .. ' ' .. 78 | f .. '.troff > ' .. f .. '.ps') 79 | ps_to_image(f, Image_format) 80 | end 81 | return img_file 82 | end 83 | 84 | function troff_to_ascii(f) 85 | local ascii_file = f .. '.ascii' 86 | if not probe_file(ascii_file) then 87 | os.execute('groff -pte -ms -Tascii ' .. f .. '.troff > ' .. ascii_file) 88 | end 89 | return ascii_file 90 | end 91 | 92 | function make_image(env, endenv) 93 | local i = Current_troff_input.stream 94 | call_with_image_stream(function(o) 95 | o:write(env, '\n') 96 | local x, j 97 | while true do 98 | x = i:read '*line' 99 | j = string.find(endenv, x) -- ? 100 | if j == 0 then break end 101 | o:write(x, '\n') 102 | end 103 | o:write(endenv, '\n') 104 | end) 105 | end 106 | 107 | -------------------------------------------------------------------------------- /lua/gen.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-02-08 2 | 3 | function generate_html(percolatable_status_values) 4 | --print('doing generate_html to', Out) 5 | local returned_status_value 6 | flet({ 7 | Exit_status = false 8 | }, function() 9 | --print('doing generate_html2', Exit_status) 10 | while true do 11 | if Exit_status then break end 12 | --print('calling process_line with', Out) 13 | process_line() 14 | end 15 | returned_status_value = Exit_status 16 | end) 17 | if table_member(returned_status_value, percolatable_status_values) then 18 | Exit_status = returned_status_value 19 | end 20 | end 21 | 22 | function process_line() 23 | --print('doing process_line') 24 | local c = snoop_char() 25 | --io.write('process_line starting with ->', c or 'NULL', '<-\n') 26 | --io.write('\tControl_char=', Control_char, '\n') 27 | --io.write('\tMacro_copy_mode_p=', tostring(Macro_copy_mode_p), '\n') 28 | --io.write('\tSourcing_ascii_code_p=', tostring(Sourcing_ascii_code_p), '\n') 29 | --io.write('\n') 30 | flet({ 31 | Keep_newline_p = true 32 | }, function() 33 | local it 34 | if not c then 35 | --print('not c') 36 | Keep_newline_p = false 37 | --print('process_line setting Exit_status = Done') 38 | Exit_status = 'Done' 39 | elseif (c == Control_char or c == No_break_control_char) and 40 | not Macro_copy_mode_p and 41 | not Expanding_args_p and 42 | not Sourcing_ascii_file_p and 43 | (function() it = read_macro_name(); return it end)() then 44 | --print('found control char', c, it) 45 | Keep_newline_p = false 46 | -- if it ~= true ?? 47 | execute_macro(it) 48 | Previous_line_exec_p = true 49 | else 50 | --print('emit exp line') 51 | emit_expanded_line() 52 | Previous_line_exec_p = false 53 | end 54 | -- 55 | if (not fillp() or Lines_to_be_justified > 0) and 56 | not Macro_copy_mode_p and 57 | Outputting_to == 'html' and 58 | Keep_newline_p and 59 | not Previous_line_exec_p then 60 | --print('ctr lines 1') 61 | emit_verbatim '
' 62 | end 63 | if Keep_newline_p and Lines_to_be_justified > 0 then 64 | --print('ctr lines 2') 65 | Lines_to_be_justified = Lines_to_be_justified - 1 66 | if Lines_to_be_justified == 0 then 67 | emit_verbatim '
' 68 | end 69 | end 70 | if Keep_newline_p then 71 | --print('kp nl') 72 | emit_newline() 73 | end 74 | end) 75 | --print('process_line done') 76 | end 77 | 78 | function expand_escape(c) 79 | --print('doing expand_escape', c) 80 | local it 81 | if not c then c = '\n' 82 | else c=get_char() 83 | end 84 | -- 85 | --if Turn_off_escape_char_p then 86 | -- return Superescape_char .. c 87 | --end 88 | -- 89 | local it = Escape_table[c] 90 | --print('it=', it) 91 | --print('copymode=', Macro_copy_mode_p) 92 | if it and 93 | (not Macro_copy_mode_p or 94 | c=='n' or c=='*' or c=='$' or c=='\\' or 95 | c=='"' or c=='#') then 96 | --print('escape action') 97 | return it() 98 | end 99 | -- 100 | if Macro_copy_mode_p then 101 | return Superescape_char..c 102 | end 103 | -- 104 | if it then 105 | return it() 106 | end 107 | -- 108 | it = Glyph_table[c] 109 | if it then 110 | return it 111 | end 112 | return verbatim(c) 113 | end 114 | -------------------------------------------------------------------------------- /lua/t2p.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-12-13 2 | 3 | function find_macro_file(f) 4 | --print('doing find_macro_file', f) 5 | local f_stem = file_stem_name(f) 6 | local f_ext = file_extension(f) 7 | --print('stem=', f_stem, '; ext=', f_ext) 8 | if f_ext == '.tmac' and table_member(f_stem, {'ms', 's', 'www'}) then return false 9 | else 10 | --print('proceeding...') 11 | local function find_in_dir(dir) 12 | local f = dir .. '/' .. f 13 | --print('find_in_dir trying', f) 14 | return probe_file(f) 15 | end 16 | res = some(find_in_dir, Groff_tmac_path) or 17 | find_in_dir '.' or 18 | find_in_dir(os.getenv 'HOME') 19 | --print('find_macro_file found', res) 20 | return res 21 | end 22 | end 23 | 24 | function troff2page_lines(ss) 25 | --print('doing troff2page_lines', #ss) 26 | flet({ 27 | Current_troff_input = make_bstream {} 28 | }, function() 29 | for i = 1, #ss do 30 | toss_back_line(ss[i]) 31 | end 32 | --print('calling generate_html from troff2page_lines with Out=', Out) 33 | generate_html({'ex', 'nx', 'return'}) 34 | end) 35 | end 36 | 37 | function troff2page_chars(cc) 38 | flet({ 39 | Current_troff_input = make_bstream{buffer = cc} 40 | }, function() 41 | --print('calling generate_html from troff2page_chars with Out=', Out) 42 | generate_html{'ex', 'nx', 'return'} 43 | end) 44 | end 45 | 46 | function troff2page_string(s) 47 | flet({ 48 | Current_troff_input = make_bstream{} 49 | }, function() 50 | toss_back_string(s) 51 | --print('calling generate_html from troff2page_string with Out=', Out) 52 | generate_html{'break', 'continue', 'ex', 'nx', 'return'} 53 | end) 54 | end 55 | 56 | function troff2page_line(s) 57 | flet({ 58 | Current_troff_input = make_bstream{} 59 | }, function() 60 | toss_back_line(s) 61 | --print('calling generate_html from troff2page_line with Out=', Out) 62 | generate_html{'ex', 'nx', 'return'} 63 | end) 64 | end 65 | 66 | function aux_file_p(f) 67 | local AUXF = String_table.AUXF() 68 | return (f:sub(1,#AUXF) == AUXF) 69 | end 70 | 71 | function troff2page_stream(istream) 72 | flet({ 73 | Current_troff_input = make_bstream { stream = istream }, 74 | Input_line_no = 0, 75 | }, function() 76 | --print('calling generate_html from troff2page_file with Out=', Out) 77 | generate_html {'ex'} 78 | end) 79 | end 80 | 81 | function troff2page_file(f, dont_check_write_date) 82 | --print('troff2page_file of', f) 83 | if not f or not probe_file(f) then 84 | twarning('can\'t open %s: No such file or directory', f) 85 | flag_missing_piece(f) 86 | else 87 | flet({ 88 | Check_file_write_date = Check_file_write_date and 89 | not dont_check_write_date and 90 | not aux_file_p(f), 91 | Current_source_file = f, 92 | File_postlude = false 93 | }, function() 94 | if Check_file_write_date then 95 | local t = file_write_date(f) 96 | if not Last_modification_time or t>Last_modification_time then 97 | --flag_missing_piece 'source_changed_since_last_time' 98 | Source_changed_since_last_time_p=true 99 | write_aux 'nb_source_changed_since_last_time_p()' 100 | Last_modification_time=t 101 | if not Preferred_last_modification_time and 102 | Colophon_done_p then 103 | --print('lmt from', f) 104 | flag_missing_piece 'last_modification_time' 105 | end 106 | end 107 | end 108 | with_open_input_file(f, troff2page_stream) 109 | if File_postlude then 110 | File_postlude() 111 | end 112 | end) 113 | end 114 | --print('done troff2page_file', f) 115 | end 116 | -------------------------------------------------------------------------------- /docs/xrefs.ms: -------------------------------------------------------------------------------- 1 | .\" last modified 2021-02-09 2 | .SH 1 3 | 4. Cross-references 4 | .LP 5 | .IX cross-references 6 | .IX TAG@.TAG, -mpca macro 7 | .IX pca-tag.tmac, macro file 8 | Troff2page provides a \fC.TAG\fP macro for managing 9 | cross-references. A compatible groff definition is provided in 10 | the supplied macro file \fCpca-tag.tmac\fP. (This overrides the 11 | similarly named macro in groff’s \fCwww.tmac\fP, in order to allow 12 | forward references.) 13 | .EX 14 | .TAG sec_trofflua 15 | .EE 16 | associates the \fItag\fP \fCsec_trofflua\fP with the number of 17 | the current page. The \fIstring\fP \fC\e*[TAG:sec_trofflua]\fP 18 | is defined to typeset as that page number. 19 | Thus, in a hand-crafted table of contents, you could 20 | use 21 | .EX 1 22 | Extending groff using Lua, \*[TAG:sec_trofflua] 23 | .EE 24 | In the HTML output, the string \fC\e*[TAG:sec_trofflua]\fP 25 | furthermore is a link to where \fC.TAG sec_trofflua\fP was 26 | called. 27 | .PP 28 | The \fCpca\fP macros use tags for internal bookkeeping: to avoid 29 | name clashes, don’t start your own tags with two underscores. 30 | .PP 31 | \fC.TAG\fP takes an optional second argument. The tag is 32 | then associated with the text of the second argument instead 33 | of the current page number. 34 | .PP 35 | .SH 2 36 | ToC 37 | .LP 38 | .IX pca-toc.tmac, macro file 39 | .IX table of contents 40 | .IX ToC@.ToC, -mpca macro 41 | The 42 | macro file \fCpca-toc.tmac\fP supplies a \fC.ToC\fP macro 43 | for automatic generation of a table of contents. This can be used 44 | by both groff and Troff2page. 45 | .PP 46 | .IX GROWPS, -ms number register 47 | For both outputs, ToC entries are created for 48 | headers of level \fC\\n[GROWPS]\fP or lower. By default, 49 | \fCGROWPS\fP is set to 0, so you should set it to at least 1 to see 50 | a ToC. 51 | .PP 52 | .IX PSINCR, -ms number register 53 | The original purpose of \fCGROWPS\fP was to govern the font-size 54 | of headers at levels below it, provided it is set to at least 2 55 | and the register \fC\en[PSINCR]\fP is set (which it is, by 56 | default, to 1p). 57 | Troff2page respects this too. If you’d rather use CSS to affect 58 | section-header style, including font-size, but you 59 | must have \fCGROWPS\fP \(>= 2 60 | because your ToC requires it, then conditionally set \fCPSINCR\fP 61 | to 0. 62 | .EX 1 63 | .if \n[.troff2page] .nr PSINCR 0 64 | .EE 65 | \fCpca-toc.tmac\fP doesn’t require you to modify how you use your header 66 | macros (\fC.SH\fP or \fC.NH\fP). It is a solution to the 67 | following statement from the groff manual: 68 | .QS 69 | Altering the ‘NH’ macro to automatically build the table of contents 70 | is perhaps initially more difficult, but would save a great deal of time 71 | in the long run if you use ‘ms’ regularly. 72 | .QE 73 | .IX pca-t2p-man.tmac, macro file 74 | Troff2page autoloads the macro file \fCpca-t2p-man.tmac\fP (if it can 75 | find it in \fCGROFF_TMAC_PATH\fP) 76 | to automatically generate a ToC for man pages, 77 | with a ToC entry for each \fC.SH\fP in the input. 78 | .PP 79 | .SH 2 80 | Bibliography 81 | .LP 82 | The \fC.BIB\fP macro from 83 | the macro file \fCpca-bib.tmac\fP introduces a paragraph that is 84 | a simple bibliographic reference, e.g., 85 | .EX 1 86 | .BIB landes_clock 87 | David S. Landes, \fIRevolutions in Time: Clocks and the 88 | Making of the Modern World\fP, Belknap Press, 1983. 89 | .EE 90 | If it is the \fIn\fPth such reference in the document, it is prefixed 91 | with “[\fIn\fP]” in the output. Furthermore, the label 92 | \fCTAG:landes_clock\fP is 93 | associated with \fIn\fP, using the cross-reference mechanism 94 | described earlier, and can be used to cite the reference. E.g., 95 | .EX 1 96 | For a history of the first portable device that, for better 97 | or worse, completely changed how we live, see 98 | Landes\~[\*[TAG:landes_clock]]. 99 | .EE 100 | -------------------------------------------------------------------------------- /lua/bye.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-06-17 2 | 3 | function clear_per_doc_tables() 4 | Color_table = {} 5 | Diversion_table = {} 6 | Ev_table = {} 7 | Glyph_table = {} 8 | Macro_table = {} 9 | Node_table = {} 10 | Numreg_table = {} 11 | String_table = {} 12 | end 13 | 14 | function close_all_open_streams() 15 | --print('doing close_all_open_streams') 16 | if Aux_stream then Aux_stream:flush(); Aux_stream:close() end 17 | if CSS then CSS:flush(); CSS:close() end 18 | for _,c in pairs(Output_streams) do 19 | --print('strm=', c) 20 | -- c:flush(); 21 | c:close() 22 | end 23 | end 24 | 25 | function do_end_macro() 26 | if End_macro then 27 | local it = Macro_table[End_macro] 28 | if it then troff2page_lines(it) end 29 | end 30 | end 31 | 32 | function load_info_converter() 33 | --print('doing load_info_converter') 34 | if html2info then return end 35 | --print('loading info converter') 36 | local f = find_macro_file('pca-t2p-info-lua.tmac') 37 | if not f then 38 | tlog('File pca-t2p-info-lua.tmac not found.\n') 39 | Convert_to_info_p = false 40 | return 41 | end 42 | troff2page_file(f) 43 | --print('html2info found?', html2info) 44 | if not html2info then 45 | Convert_to_info_p = false 46 | tlog('File pca-t2p-info-lua.tmac corrupted?\n') 47 | end 48 | end 49 | 50 | function do_bye() 51 | --print('doing do_bye') 52 | flet({ Blank_line_macro = false }, function() 53 | emit_blank_line() 54 | end) 55 | Check_file_write_date=false 56 | do_end_macro() 57 | local pageno = Current_pageno 58 | nb_last_page_number(pageno) 59 | --print('pageno=', pageno) 60 | write_aux('nb_last_page_number(', pageno, ')') 61 | emit_end_page() 62 | if raw_counter_value 'HTML1' ~=0 then 63 | write_aux 'nb_single_output_page()' 64 | end 65 | if Verbatim_apostrophe_p then 66 | write_aux 'nb_verbatim_apostrophe()' 67 | end 68 | --print('nb_macro_package=>', Macro_package, '<=') 69 | write_aux('nb_macro_package("', Macro_package, '")') 70 | if Title then 71 | --print('nb_titling', Title) 72 | local escaped_Title = Title 73 | escaped_Title = string.gsub(escaped_Title, '\\', '\\\\') 74 | escaped_Title = string.gsub(escaped_Title, '\n', '\\n') 75 | escaped_Title = string.gsub(escaped_Title, "'", "\\'") 76 | --escaped_Title = string.gsub(escaped_Title, '"', '\\"') 77 | --print('nb_titling ->', escaped_Title) 78 | write_aux('nb_title(\'', escaped_Title, '\')') 79 | end 80 | local SHmag = raw_counter_value '.SHmag' 81 | if SHmag > 0 then 82 | CSS:write(string.format('h1,h2,h3,h4,h5,h6 { font-size: %sem; }\n', SHmag)) 83 | end 84 | if Last_page_number == 0 then 85 | CSS:write('.navigation { display: none; }\n') 86 | end 87 | if Preferred_last_modification_time then 88 | write_aux('nb_preferred_last_modification_time(\'', Preferred_last_modification_time, '\')') 89 | end 90 | if Last_modification_time then 91 | write_aux('nb_last_modification_time(', Last_modification_time, ')') 92 | end 93 | if raw_counter_value 't2pslides' ~=0 then 94 | --print('doing slide setup') 95 | local slidy_css_file = probe_file('slidy.css') or 96 | 'http://www.w3.org/Talks/Tools/Slidy2/styles/slidy.css' 97 | write_aux('nb_stylesheet("', slidy_css_file , '")') 98 | -- 99 | local slidy_js_file = probe_file('slidy.js') or 100 | 'http://www.w3.org/Talks/Tools/Slidy2/scripts/slidy.js' 101 | write_aux('nb_script("', slidy_js_file, '")') 102 | --print('done slide setup') 103 | end 104 | --print('checking Convert_to_info_p', Convert_to_info_p) 105 | if not Convert_to_info_p and os.getenv 'TROFF2PAGE2INFO' then 106 | Convert_to_info_p = true 107 | end 108 | if Convert_to_info_p then 109 | --print('calling load_info_converter') 110 | load_info_converter() 111 | --print('done load_info_converter') 112 | end 113 | clear_per_doc_tables() 114 | if #Missing_pieces > 0 then 115 | Rerun_needed_p = true 116 | tlog('Missing: %s\n', table_to_string(Missing_pieces)) 117 | end 118 | close_all_open_streams() 119 | end 120 | -------------------------------------------------------------------------------- /lua/de.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2020-12-15 2 | 3 | function collect_macro_body(w, ender) 4 | --print('doing collect_macro_body', w, ender) 5 | --print('Turn_off_escape_char_p =', Turn_off_escape_char_p) 6 | if not ender then ender = '.' end 7 | local m = {} 8 | while true do 9 | if not snoop_char() then 10 | Exit_status = 'done' 11 | Macro_spill_over = Control_char .. 'am ' .. w .. ' ' .. ender 12 | break 13 | end 14 | local ln = expand_args(read_troff_line()) 15 | local breakloop 16 | --print('inside collect_macro_body with', ln) 17 | flet({ 18 | Current_troff_input = make_bstream {} 19 | }, function() 20 | toss_back_line(ln) 21 | local c = snoop_char() 22 | if c == Control_char then 23 | get_char() 24 | ignore_spaces() 25 | local w = read_bare_word() 26 | --print('checking ->', w, '<-') 27 | if w == ender then breakloop=true; return end 28 | end 29 | table.insert(m, ln) 30 | end) 31 | if breakloop then break end 32 | end 33 | --print('collect_macro_body returning', table_to_string(m)) 34 | return m 35 | end 36 | 37 | function expand_args(s, not_copy_mode_p) 38 | --print('doing expand_args', s) 39 | if not s then return '' end 40 | local res = with_output_to_string(function (o) 41 | flet({ 42 | Current_troff_input = make_bstream{buffer = string_to_table(s)}, 43 | Macro_copy_mode_p = not not_copy_mode_p, 44 | Expanding_args_p = true, 45 | Outputting_to = 'troff', 46 | Out = o 47 | }, function() 48 | --print('calling generate_html from expand_args') 49 | --print('cti.b =', #(Current_troff_input.buffer)) 50 | generate_html{'break', 'continue', 'ex', 'nx', 'return'} 51 | end) 52 | end) 53 | --print('expand_args retng', res) 54 | return res 55 | end 56 | 57 | function execute_macro(w, noarg) 58 | --print('doing execute_macro', w) 59 | local it 60 | if not w then 61 | return 62 | end 63 | -- 64 | it = Diversion_table[w] 65 | if it then 66 | --print('execing divn') 67 | if not noarg then read_troff_line() end 68 | local divvalue = retrieve_diversion(it) 69 | --print('divvalue =', divvalue) 70 | emit_verbatim(divvalue) 71 | return 72 | end 73 | -- 74 | it = Macro_table[w] 75 | if it then 76 | local args = noarg and {} or {read_args()} 77 | flet({ 78 | Macro_args = args 79 | }, function() 80 | table.insert(Macro_args, 1, w) 81 | execute_macro_body(it) 82 | end) 83 | return 84 | end 85 | -- 86 | it = String_table[w] 87 | if it then 88 | if not noarg then read_troff_line() end 89 | emit_verbatim(it()) 90 | return 91 | end 92 | -- 93 | it = Request_table[w] 94 | if it then 95 | --print('calling request', w) 96 | it() 97 | return 98 | end 99 | -- 100 | if not noarg then read_troff_line() end 101 | end 102 | 103 | function execute_macro_body(ss) 104 | --print('doing execute_macro_body', table_to_string(ss)) 105 | flet({ 106 | Macro_spill_over = false 107 | }, function() 108 | flet({ 109 | Current_troff_input = make_bstream {} 110 | }, function() 111 | local i = #ss 112 | while true do 113 | if i<1 then break end 114 | toss_back_line(ss[i]) 115 | i = i-1 116 | end 117 | --print('calling generate_html from execute_macro_body with Out=', Out) 118 | generate_html {'nx', 'ex'} 119 | end) 120 | if Macro_spill_over then 121 | toss_back_line(Macro_spill_over) 122 | end 123 | end) 124 | end 125 | 126 | function execute_macro_with_args(w, args) 127 | local it 128 | it = Macro_table[w] 129 | if not t then return end 130 | flet({Macro_args = args}, function() 131 | table.insert(Macro_args, 1, w) 132 | execute_macro_body(it) 133 | end) 134 | return 135 | end 136 | 137 | function retrieve_diversion(div) 138 | local value = div.value 139 | if not value then 140 | value = (div.stream):get_output_stream_string() 141 | div.value = value 142 | end 143 | return value 144 | end 145 | -------------------------------------------------------------------------------- /lua/navbar.lua: -------------------------------------------------------------------------------- 1 | -- last modified 2021-06-17 2 | 3 | function emit_navigation_bar(headerp) 4 | if headerp and Last_page_number == -1 then 5 | emit_verbatim '\n' 6 | return 7 | end 8 | if Last_page_number == 0 then return end 9 | -- 10 | local pageno = Current_pageno 11 | local first_page_p = (pageno == 0) 12 | local last_page_p = (pageno == Last_page_number) 13 | local toc_page = Node_table['TAG:__troff2page_toc'] 14 | local toc_page_p = (pageno == toc_page) 15 | local index_page = Node_table['TAG:__troff2page_index'] 16 | local index_page_p = (pageno == index_page) 17 | -- 18 | emit_verbatim '[' 23 | emit(Navigation_sentence_begin) 24 | -- 25 | emit_verbatim '' 28 | if not first_page_p then emit(link_start(page_link(0), true)) end 29 | emit(Navigation_first_name) 30 | if not first_page_p then emit(link_stop()) end 31 | emit_verbatim ', ' 32 | -- 33 | if not first_page_p then emit(link_start(page_link(pageno-1), true)) end 34 | emit(Navigation_previous_name) 35 | if not first_page_p then emit(link_stop()) end 36 | emit_verbatim '' 37 | -- 38 | emit_verbatim '' 41 | if first_page_p then emit_verbatim '' end 42 | emit_verbatim ', ' 43 | if first_page_p then emit_verbatim '' end 44 | if not last_page_p then emit(link_start(page_link(pageno+1), true)) end 45 | emit(Navigation_next_name) 46 | if not last_page_p then emit(link_stop()) end 47 | emit_verbatim '' 48 | -- 49 | emit(Navigation_page_name) 50 | -- 51 | if toc_page or index_page then 52 | emit_verbatim '; ' 58 | emit_nbsp(2) 59 | emit_verbatim '' 60 | -- 61 | if toc_page then 62 | emit_verbatim '' 65 | if not toc_page_p then 66 | emit(link_start(page_node_link(toc_page, 'TAG:__troff2page_toc'), true)) 67 | end 68 | emit(Navigation_contents_name) 69 | if not toc_page_p then emit(link_stop()) end 70 | emit_verbatim '' 71 | end 72 | -- 73 | if index_page then 74 | emit_verbatim '' 77 | emit_verbatim '' 80 | if toc_page then 81 | emit_verbatim '; ' 82 | emit_nbsp(2) 83 | end 84 | emit_verbatim '' 85 | if not index_page_p then 86 | emit(link_start(page_node_link(index_page, 'TAG:__troff2page_index'), true)) 87 | end 88 | emit(Navigation_index_name) 89 | if not index_page_p then emit(link_stop()) end 90 | emit_verbatim '' 91 | end 92 | -- 93 | end 94 | emit(Navigation_sentence_end) 95 | emit_verbatim ']' 96 | emit_verbatim '\n' 97 | -- 98 | end 99 | 100 | function emit_colophon() 101 | --print('colophon calling eep') 102 | emit_end_para() 103 | emit_verbatim '\n' 108 | -- 109 | local it 110 | local timestamp 111 | if Preferred_last_modification_time then 112 | timestamp = Preferred_last_modification_time 113 | elseif Last_modification_time then 114 | timestamp = os.date("%a, %Y-%m-%d", Last_modification_time) 115 | else 116 | it = String_table.DY 117 | if it then it=it() end 118 | if it ~= '' then timestamp = it end 119 | end 120 | if timestamp and timestamp ~= '' then 121 | emit_verbatim '\n' 126 | emit(Last_modified); emit(timestamp) 127 | emit_verbatim '
\n\n' 128 | end 129 | -- 130 | if true then 131 | emit_verbatim '