Posted By

reboltutorial on 03/02/10


Tagged

html generator documentation REBOL


Versions (?)

Makedoc2


 / Published in: CSS
 

URL: http://www.rebol.net/docs/makedoc.html

  1. ;; =================================================
  2. ;; Script: makedoc2.r
  3. ;; downloaded from: www.REBOL.org
  4. ;; on: 21-Aug-2008
  5. ;; at: 12:46:20 UTC
  6. ;; owner: carl [script library member who can update
  7. ;; this script]
  8. ;; =================================================
  9. REBOL [
  10. Title: "MakeDoc 2 - The REBOL Standard Document Formatter"
  11. Version: 2.5.7
  12. Copyright: "REBOL Technologies 1999-2005"
  13. Author: "Carl Sassenrath"
  14. File: %makedoc2.r
  15. Date: 10-Mar-2007 ;10-Jan-2005
  16. Purpose: {
  17. This is the official MakeDoc document formatter that is used by
  18. REBOL Technologies for all documentation. It is the fastest and
  19. easiest way to create good looking documentation using any text
  20. editor (even ones that do not auto-wrap text). It creates titles,
  21. headings, contents, bullets, numbered lists, indented examples,
  22. note blocks, and more. For documentation, notes, and other info
  23. visit http://www.rebol.net/docs/makedoc.html
  24. }
  25. Usage: {
  26. Create a text document in any editor. Separate each paragraph
  27. with a blank line. Run this script and provide your text file.
  28. The output file will be the same name with .html following it.
  29. If you use REBOL/View the output file will be displayed in
  30. your web browser as well.
  31.  
  32. You can also call this script from other scripts (e.g. CGI).
  33. These are supported:
  34.  
  35. do %makedoc2.r
  36.  
  37. do/args %makedoc2.r %document.txt
  38.  
  39. do/args %makedoc2.r 'load-only
  40. doc: scan-doc read %file.txt
  41. set [title out] gen-html/options doc [(options)]
  42. write %out.html out
  43. }
  44. Library: [
  45. level: 'intermediate
  46. platform: 'all
  47. type: [tool]
  48. domain: [html cgi markup]
  49. tested-under: none
  50. support: none
  51. license: 'BSD
  52. see-also: none
  53. ]
  54. ]
  55.  
  56. ; Below you can specify an HTML output template to use for all your docs.
  57. ; See the default-template example below as a starting suggestion.
  58. template-file: %template.html ; Example: %template.html
  59.  
  60. ; There are three parts to this script:
  61. ; 1. The document input scanner.
  62. ; 2. The document output formatter (for HTML).
  63. ; 3. The code that deals with input and output files.
  64.  
  65. *scanner*: context [
  66.  
  67. ;-- Debugging:
  68. verbose: off
  69. debug: func [data] [if verbose [print data]]
  70.  
  71. ;-- Module Variables:
  72. text: none
  73. para: none
  74. code: none
  75. title: none
  76. left-flag: off
  77. opts: [] ;[no-toc no-nums]
  78. out: [] ; The output block (static, reused)
  79. option: none
  80.  
  81. ;--- Parser rules for the Makedoc text language (top-down):
  82.  
  83. rules: [some commands]
  84. commands: [
  85. newline
  86. here: (debug ["---PARSE:" copy/part here find here newline])
  87.  
  88. ;-- Document sections:
  89. | ["===" | "-1-"] text-line (emit-section 1)
  90. | ["---" | "-2-"] text-line (emit-section 2)
  91. | ["+++" | "-3-"] text-line (emit-section 3)
  92. | ["..." | "-4-"] text-line (emit-section 4)
  93. | "###" to end (emit end none) ; allows notes, comments to follow
  94.  
  95. ;-- Common commands:
  96. | #"*" [
  97. [">>" | "**"] text-block (emit bullet3 para)
  98. | [">" | "*" ] text-block (emit bullet2 para)
  99. | text-block (emit bullet para)
  100. ]
  101. | #"#" [
  102. ">>" text-block (emit enum3 para)
  103. | ">" text-block (emit enum2 para)
  104. | text-block (emit enum para)
  105. ]
  106. | #":" define opt newline (emit define reduce [text para])
  107.  
  108. ; ">>" reserved
  109. ; "<<" reserved
  110.  
  111. ;-- Enter a special section:
  112. | #"\" [
  113. "in" (emit indent-in none)
  114. | "note" text-line (emit note-in text)
  115. | "table" text-line (emit table-in text)
  116. | "group" (emit group-in none)
  117. | "center" (emit center-in none)
  118. | "column" (emit column-in none)
  119. ]
  120.  
  121. ;-- Exit a special section:
  122. | #"/" [
  123. "in" (emit indent-out none)
  124. | "note" (emit note-out none)
  125. | "table" (emit table-out none)
  126. | "group" (emit group-out none)
  127. | "center" (emit center-out none)
  128. | "column" (emit column-out none)
  129. ]
  130.  
  131. ;-- Extended commands (all begin with "="):
  132. | #";" text-block ; comments and hidden paragraphs
  133. | #"=" [
  134. #"=" output (emit output trim/auto code)
  135. | "image" image
  136. | "row" (emit table-row none)
  137. | "column" (emit column none) ; (for doc, not tables)
  138. | "options" [
  139. any [
  140. spaces copy option [
  141. "toc"
  142. | "nums"
  143. | "indent"
  144. | "no-indent"
  145. | "no-toc"
  146. | "no-nums"
  147. | "no-template"
  148. | "no-title"
  149. | "old-tags"
  150. | "root-images"
  151. ] (append opts to-word option)
  152. ]
  153. ]
  154. | "template" some-chars (repend opts ['template as-file text])
  155. ]
  156.  
  157. ;-- Primary implied paragraph types:
  158. | example (emit code trim/auto detab code)
  159. | paragraph (
  160. either title [emit para para][emit title title: para]
  161. )
  162. | skip (debug "???WARN: Unrecognized")
  163. ]
  164. space: charset " ^-"
  165. nochar: charset " ^-^/"
  166. chars: complement nochar
  167. spaces: [any space]
  168. some-chars: [some space copy text some chars]
  169. text-line: [any space copy text thru newline]
  170. text-block: [any space paragraph opt newline] ; ignore leading space, extra NL !???
  171. paragraph: [copy para some [chars thru newline]]
  172. example: [copy code some [indented | some newline indented]]
  173. indented: [some space chars thru newline]
  174. output: [
  175. some space copy code thru newline
  176. any ["==" ["^-" | " "] copy text thru newline (append code text)]
  177. ]
  178. define: [copy text to " -" 2 skip text-block]
  179. image: [
  180. left? any space copy text some chars (
  181. if text/1 = #"%" [remove text] ; remove %file
  182. text: as-file text
  183. emit image reduce [text pick [left center] left-flag]
  184. )
  185. ]
  186. left?: [some space "left" (left-flag: on) | none (left-flag: off)]
  187.  
  188. as-file: func [str] [to-file trim str]
  189.  
  190. ;-- Output emitters:
  191.  
  192. emit: func ['word data] [
  193. debug ["===EMIT: " word]
  194. if block? word [word: do word] ;????
  195. if string? data [trim/tail data]
  196. repend out [word data]
  197. ]
  198.  
  199. emit-section: func [num] [
  200. emit [to-word join "sect" num] text
  201. title: true
  202. ]
  203.  
  204. ;-- Export function to scan doc. Returns format block.
  205. set 'scan-doc func [str /options block] [
  206. clear out
  207. title: none
  208.  
  209. if options [
  210. if find block 'no-title [title: true]
  211. ]
  212. emit options opts
  213. str: join str "^/^/###" ; makes the parse easier
  214. parse/all detab str rules
  215. if verbose [
  216. n: 1
  217. foreach [word data] out [
  218. print [word data]
  219. if (n: n + 1) > 5 [break]
  220. ]
  221. ]
  222. copy out
  223. ]
  224. ]
  225.  
  226. ;-- HTML Output Generator ----------------------------------------------------
  227.  
  228. *html*: context [
  229.  
  230. ;-- HTML foprmat global option variables:
  231. no-nums: ; Do not use numbered sections
  232. no-toc: ; Do not generate table of contents
  233. no-title: ; Do not generate a title or boilerplate
  234. no-indent: ; Do not indent each section
  235. no-template: ; Do not use a template HTML page
  236. old-tags: ; Allow old markup convention (slower)
  237. root-images: ; Images should be located relative to /
  238. none
  239.  
  240. toc-levels: 2 ; Levels shown in table of contents
  241. image-path: "" ; Path to images
  242.  
  243. set 'gen-html func [
  244. doc [block!]
  245. /options opts [block!]
  246. /local title template tmp
  247. ][
  248. clear out ; (reused)
  249. group-count: 0
  250.  
  251. ; Options still need work!!!
  252. no-nums:
  253. no-toc:
  254. no-title:
  255. no-indent:
  256. no-template:
  257. old-tags:
  258. root-images:
  259. none
  260.  
  261. set-options opts: any [opts []]
  262. set-options select doc 'options
  263. if root-images [image-path: %/]
  264.  
  265. ; Template can be provided in =template or in
  266. ; options block following 'template. If options
  267. ; has 'no-template, then do not use a template.
  268. if not no-template [
  269. template: any [select opts 'template select doc 'template template-file]
  270. if file? template [template: attempt [read template]]
  271. if not template [template: trim/auto default-template]
  272. ]
  273.  
  274. ; Emit title and boilerplate:
  275. if not no-title [title: emit-boiler doc]
  276.  
  277. ; Emit table of contents:
  278. clear-sects
  279. if not no-toc [
  280. emit-toc doc
  281. clear-sects
  282. ]
  283.  
  284. prior-cmd: none
  285. forskip doc 2 [
  286. ; If in a table, emit a cell each time.
  287. if all [
  288. in-table
  289. zero? group-count ; do not emit cell if in group
  290. not find [table-out table-row] doc/1
  291. not find [table-in table-row] prior-cmd
  292. ][
  293. emit-table-cell
  294. ]
  295. switch prior-cmd: doc/1 [
  296. para [emit-para doc/2]
  297. sect1 [emit-sect 1 doc/2]
  298. sect2 [emit-sect 2 doc/2]
  299. sect3 [emit-sect 3 doc/2]
  300. sect4 [emit-sect 4 doc/2]
  301. bullet [emit-item doc doc/1]
  302. bullet2 [emit-item doc doc/1]
  303. bullet3 [emit-item doc doc/1]
  304. enum [emit-item doc doc/1]
  305. enum2 [emit-item doc doc/1]
  306. enum3 [emit-item doc doc/1]
  307. code [doc: emit-code doc]
  308. output [doc: emit-code doc]
  309. define [emit-def doc]
  310. image [emit-image doc/2]
  311. table-in [emit-table doc/2]
  312. table-out [emit-table-end]
  313. table-row [emit-table-row]
  314. center-in [emit <center>]
  315. center-out [emit </center>]
  316. note-in [emit-note doc/2]
  317. note-out [emit-note-end]
  318. group-in [group-count: group-count + 1]
  319. group-out [group-count: max 0 group-count - 1]
  320. indent-in [emit <blockquote>]
  321. indent-out [emit </blockquote>]
  322. column-in [emit {<table border=0 cellpadding=4 width=100%><tr><td valign=top>}]
  323. column-out [emit {</td></tr></table>}]
  324. column [emit {</td><td valign=top>}]
  325. ]
  326. ]
  327. doc: head doc
  328. emit </blockquote>
  329.  
  330. if template [
  331. ; Template variables all begin with $
  332. tmp: copy template ; in case it gets reused
  333. replace/all tmp "$title" title
  334. replace/all tmp "$date" now/date
  335. replace tmp "$content" out
  336. out: tmp
  337. ]
  338. reduce [title out]
  339. ]
  340.  
  341. set-options: func [options] [
  342. if none? options [exit]
  343. foreach opt [
  344. no-nums
  345. no-toc
  346. no-indent
  347. no-template
  348. no-title
  349. old-tags
  350. root-images
  351. ][if find options opt [set opt true]]
  352. foreach [opt word] [
  353. nums no-nums
  354. toc no-toc
  355. indent no-indent
  356. ][if find options opt [set word false]]
  357. ]
  358.  
  359. ;-- Default HTML Template:
  360.  
  361. default-template: {
  362. <html>
  363. <!--Page generated by REBOL-->
  364. <head>
  365. <title>$title</title>
  366. <style type="text/css">
  367. html, body, p, td, li {font-family: arial, sans-serif, helvetica; font-size: 10pt;}
  368. h1 {font-size: 16pt; Font-Weight: bold;}
  369. h2 {font-size: 14pt; color: #2030a0; Font-Weight: bold; width: 100%;
  370. border-bottom: 1px solid #c09060;}
  371. h3 {font-size: 12pt; color: #2030a0; Font-Weight: bold;}
  372. h4 {font-size: 10pt; color: #2030a0; Font-Weight: bold;}
  373. h5 {font-size: 10pt; Font-Weight: bold;}
  374. tt {font-family: "courier new", monospace, courier; color: darkgreen;}
  375. pre {font: bold 10pt "courier new", monospace, console;
  376. background-color: #e0e0e0; padding: 16px; border: solid #a0a0a0 1px;}
  377. .toc1 {margin-left: 1cm; font-size: 12pt; font-weight: bold;}
  378. .toc2 {margin-left: 2cm; font-size: 10pt; Font-Weight: bold; text-decoration: none;}
  379. .toc3 {margin-left: 3cm; font-size: 10pt; text-decoration: none;}
  380. .toc4 {margin-left: 4cm; font-size: 10pt; color: grey; text-decoration: none;}
  381. .output {color: #000080; font-weight: normal;}
  382. .note {background-color: #f0e090; width: 100%; padding: 16px; border: solid #a0a0a0 1px;}
  383. .tail {color: gray; font-size: 8pt;}
  384. </style>
  385. </head>
  386. <body bgcolor="white">
  387. <table width="660" cellpadding="4" cellspacing="0" border="0">
  388. <tr>
  389. <td><!-- header --></td>
  390. </tr>
  391. <tr height="10"><td></td></tr>
  392. <tr><td>$content</td></tr><tr>
  393. <tr><td><!-- footer --></td></tr>
  394. <td align="center">
  395. <span class="tail"><a href="http://www.rebol.com">Generated on </a>$date</span>
  396. </td></tr></table>
  397. </body></html>
  398. }
  399.  
  400. ;-- HTML Emit Utility Functions:
  401.  
  402. out: make string! 10000
  403.  
  404. emit: func [data /line] [
  405. ; Primary emit function:
  406. insert insert tail out reduce data newline
  407. ]
  408.  
  409. wsp: charset " ^-^/" ; whitespace: sp, tab, return
  410.  
  411. emit-end-tag: func [tag] [
  412. ; Emit an end tag from a tag.
  413. tag: copy/part tag any [find tag wsp tail tag]
  414. insert tag #"/"
  415. emit tag
  416. ]
  417.  
  418. emit-tag: func [text tag start end] [
  419. ; Used to emit special one-sided tags:
  420. while [text: find text tag] [
  421. remove/part text length? tag
  422. text: insert text start
  423. text: insert any [find text end-char tail text] end
  424. ]
  425. ]
  426. end-char: charset [" " ")" "]" "." "," "^/"]
  427.  
  428. escape-html: func [text][
  429. ; Convert to avoid special HTML chars:
  430. foreach [from to] html-codes [replace/all text from to]
  431. text
  432. ]
  433. html-codes: ["&" "&amp;" "<" "&lt;" ">" "&gt;"]
  434.  
  435. emit-lines: func [text] [
  436. ; Emit separate lines in normal font:
  437. replace/all text newline <br>
  438. emit text
  439. ]
  440.  
  441. ;-- HTML Document Formatting Functions:
  442.  
  443. fix-tags: func [text] [
  444. if old-tags [
  445. emit-tag text "<c>" "<tt>" "</tt>"
  446. emit-tag text "<w>" "<b><tt>" "</tt></b>"
  447. emit-tag text "<s>" "<b><i>" "</i></b>"
  448. ]
  449. text
  450. ]
  451.  
  452. emit-para: func [text] [
  453. ; Emit standard text paragraph:
  454. emit [<p> fix-tags text </p>]
  455. ]
  456.  
  457. emit-code: func [doc] [
  458. emit <pre>
  459. while [
  460. switch doc/1 [
  461. code [emit [escape-html doc/2]]
  462. output [emit [<span class="output"> escape-html doc/2 </span>]]
  463. ]
  464. ][doc: skip doc 2]
  465. emit </pre>
  466. doc: skip doc -2
  467. ]
  468.  
  469. emit-image: func [spec /local tag] [
  470. ; Emit image. Spec = 'center or default is 'left.
  471. emit [
  472. either spec/2 = 'center [<p align="center">][<p>]
  473. join {<img src="} [(join image-path spec/1) {">}]
  474. </p>
  475. ]
  476. ]
  477.  
  478. buls: [bullet bullet2 bullet3]
  479. enums: [enum enum2 enum3]
  480.  
  481. bul-stack: []
  482.  
  483. push-bul: func [bul][
  484. if any [empty? bul-stack bul <> last bul-stack][
  485. ;print ['push bul mold bul-stack]
  486. append bul-stack bul
  487. emit pick [<ul><ol>] found? find buls bul
  488. ]
  489. ]
  490.  
  491. pop-bul: func [bul /local here][
  492. here: any [find buls bul find enums bul]
  493. while [
  494. all [
  495. not empty? bul-stack
  496. bul <> last bul-stack
  497. any [
  498. not here ; not bullet or enum
  499. find next here last bul-stack
  500. all [here: find bul-stack bul not tail? here]
  501. ]
  502. ]
  503. ][
  504. ;print ['pop bul mold bul-stack]
  505. emit pick [</ul></ol>] found? find buls last bul-stack
  506. remove back tail bul-stack
  507. ]
  508. ]
  509.  
  510. emit-item: func [doc item /local tag][
  511. push-bul item
  512. emit [<li> fix-tags doc/2 </li>]
  513. pop-bul doc/3
  514. ]
  515.  
  516. emit-def: func [doc] [
  517. ; Emit indented definitions table. Start and end it as necessary.
  518. if doc/-2 <> 'define [
  519. emit {<table cellspacing="6" border="0" width="95%">}
  520. ]
  521. emit [
  522. <tr><td width="20"> "&nbsp;" </td>
  523. <td valign="top" width="80">
  524. <b> any [doc/2/1 "&nbsp;"] </b></td>
  525. <td valign="top"> fix-tags any [doc/2/2 " "] </td>
  526. </tr>
  527. ]
  528. if doc/3 <> 'define [emit {</table>}]
  529. ]
  530.  
  531. emit-note: func [text] [
  532. ; Start a note sidebar, centered on page:
  533. emit [<p><fieldset class="fset"><legend> fix-tags text </legend>]
  534. ]
  535.  
  536. emit-note-end: does [
  537. ; End a note sidebar.
  538. emit </fieldset></p>
  539. ]
  540.  
  541. in-table: in-header: false
  542.  
  543. emit-table: does [
  544. in-table: true
  545. in-header: true
  546. emit {<table border="0" cellspacing="1" cellpadding="4" bgcolor="#505050">
  547. <tr bgcolor="silver"><td><b>}
  548. ]
  549.  
  550. emit-table-end: does [
  551. in-table: false
  552. emit "</td></tr></table>"
  553. ]
  554.  
  555. emit-table-cell: does [
  556. emit pick [{</b></td><td><b>} {</td><td valign="top" bgcolor="white">}] in-header
  557. ]
  558.  
  559. emit-table-row: does [
  560. in-header: false
  561. emit {</td></tr><tr><td valign="top" bgcolor="white">}
  562. ]
  563.  
  564. ;-- Section handling:
  565.  
  566. clear-sects: does [sects: 0.0.0.0]
  567.  
  568. next-section: func [level /local bump mask] [
  569. ; Return next section number. Clear sub numbers.
  570. set [bump mask] pick [
  571. [1.0.0.0 1.0.0.0]
  572. [0.1.0.0 1.1.0.0]
  573. [0.0.1.0 1.1.1.0]
  574. [0.0.0.1 1.1.1.1]
  575. ] level
  576. level: form sects: sects + bump * mask
  577. clear find level ".0"
  578. level
  579. ]
  580.  
  581. make-heading: func [level num str /toc /local lnk][
  582. ; Make a proper heading link or TOC target.
  583. ; Determine link target str. Search for [target] in front of heading.
  584. either parse str [
  585. "[" copy lnk to "]"
  586. s: to end
  587. ][
  588. str: next s ; remove link target
  589. ][
  590. lnk: join "section-" num
  591. ]
  592. if not no-nums [str: rejoin [num pick [". " " "] level = 1 str]]
  593. rejoin either toc [
  594. [{<a class="toc} level {" href="#} lnk {">} str </a>]
  595. ][
  596. [{<h} level + 1 { id="} lnk {">} str {</h} level + 1 {>}]
  597. ]
  598. ]
  599.  
  600. emit-sect: func [level str /local sn] [
  601. ; Unindent prior level:
  602. if all [not no-indent level <= 2 sects/1 > 0] [emit </blockquote>]
  603. sn: next-section level
  604. emit make-heading level sn str
  605. if all [not no-indent level <= 2] [emit <blockquote>]
  606. ]
  607.  
  608. emit-toc: func [doc /local w sn] [
  609. ; Output table of contents:
  610. emit [<h2> "Contents:" </h2>]
  611. foreach [word str] doc [
  612. if w: find [sect1 sect2 sect3 sect4] word [
  613. w: index? w
  614. if w <= toc-levels [
  615. sn: next-section w
  616. emit [make-heading/toc w sn str <br>]
  617. ]
  618. ]
  619. ]
  620. ]
  621.  
  622. emit-boiler: func [doc /local title info temp] [
  623. ; Output top boiler plate:
  624. title: any [
  625. select doc 'title
  626. select doc 'sect1
  627. "Untitled"
  628. ]
  629. emit [<h1> title </h1>]
  630. foreach [word val] doc [
  631. if word = 'code [
  632. emit {<blockquote><b>}
  633. emit-lines val
  634. emit {</b></blockquote>}
  635. remove/part find doc 'code 2
  636. break
  637. ]
  638. if not find [title template options] word [break]
  639. ]
  640. title
  641. ]
  642.  
  643. ]
  644.  
  645. do-makedoc: has [in-view? file msg doc] [
  646.  
  647. in-view?: all [value? 'view? view?] ; Are we using View?
  648.  
  649. ; Get the file name from the script argument:
  650. file: system/script/args
  651. if any-string? file [file: to-file file] ; makes copy too
  652.  
  653. ; If no file provided, should we do the last file again?
  654. if all [
  655. not file
  656. exists? %last-file.tmp
  657. ][
  658. file: load %last-file.tmp
  659. either confirm reform ["Reprocess" file "?"] [
  660. system/script/args: none
  661. ][
  662. file: none
  663. ]
  664. ]
  665.  
  666. ; If no file still, then ask the user for the file name:
  667. if not file [
  668. either in-view? [
  669. file: request-file/only
  670. ][
  671. file: ask "Filename? "
  672. file: all [not empty? trim file to-file file]
  673. ]
  674. ]
  675.  
  676. ; No file provided:
  677. if not file [exit]
  678.  
  679. ; File must exist:
  680. if not exists? file [
  681. msg: reform ["Error:" file "does not exist"]
  682. either in-view? [alert msg] [ask msg]
  683. exit
  684. ]
  685.  
  686. ; Save this as the last file processed:
  687. save %last-file.tmp file
  688.  
  689. ; Process the file. Returns [title doc]
  690. doc: second gen-html scan-doc read file
  691.  
  692. ; Create output file name:
  693. append clear find/last file #"." ".html"
  694. write file doc
  695.  
  696. if all [in-view? not system/script/args] [browse file]
  697. file ; return new file (entire path)
  698. ]
  699.  
  700. ; Start process (but caller may request it only be loaded):
  701. if system/script/args <> 'load-only [do-makedoc]

Report this snippet  

You need to login to post a comment.