HTMLDocGenerator.st
changeset 2016 1084cacd75ac
parent 2002 43ff7ad28fb5
child 2017 bc6393e8c430
equal deleted inserted replaced
2015:8633780e0347 2016:1084cacd75ac
    12 "{ Package: 'stx:libbasic3' }"
    12 "{ Package: 'stx:libbasic3' }"
    13 
    13 
    14 Object subclass:#HTMLDocGenerator
    14 Object subclass:#HTMLDocGenerator
    15 	instanceVariableNames:'outStream pathToTopOfDocumentation
    15 	instanceVariableNames:'outStream pathToTopOfDocumentation
    16 		pathToLanguageTopOfDocumentation httpRequestOrNil
    16 		pathToLanguageTopOfDocumentation httpRequestOrNil
    17 		generateBodyOnly backRef backCmd imagePath'
    17 		generateBodyOnly backRef backCmd imagePath refLines demoLines
       
    18 		warnLines hintLines authorLines classProtocolCategories
       
    19 		instanceProtocolCategories'
    18 	classVariableNames:''
    20 	classVariableNames:''
    19 	poolDictionaries:''
    21 	poolDictionaries:''
    20 	category:'System-Documentation'
    22 	category:'System-Documentation'
    21 !
    23 !
    22 
    24 
   294 
   296 
   295     pathToTopOfDocumentation := something.
   297     pathToTopOfDocumentation := something.
   296 ! !
   298 ! !
   297 
   299 
   298 !HTMLDocGenerator methodsFor:'document generation'!
   300 !HTMLDocGenerator methodsFor:'document generation'!
       
   301 
       
   302 generateClassInfoForClass:aClass
       
   303     |owner|
       
   304 
       
   305     owner := aClass owningClass.
       
   306 
       
   307     outStream nextPutLine:'<dl>'.
       
   308     outStream nextPutLine:'<dt><a name="PACKAGE"><b>Package:</b></A>'.
       
   309     outStream nextPutLine:'<dd><b>', aClass package , '</b>'.
       
   310     outStream nextPutLine:'</dl>'.
       
   311 
       
   312 
       
   313     aClass category notNil ifTrue:[
       
   314         outStream nextPutLine:'<dl>'.
       
   315         outStream nextPutLine:'<dt><a name="CATEGORY"><b>Category:</b></A>'.
       
   316         outStream nextPutLine:'<dd><b>', aClass category , '</b>'.
       
   317         outStream nextPutLine:'</dl>'.
       
   318     ].
       
   319 
       
   320     owner notNil ifTrue:[
       
   321         outStream nextPutLine:'<dl>'.
       
   322         outStream nextPutLine:'<dt><a name="OWNER"><b>Owner:</b></A>'.
       
   323         outStream nextPutAll:'<dd><b>'. 
       
   324         self generateClassDocReferenceFor:owner name.
       
   325         outStream cr.
       
   326 "/        outStream nextPutLine:(self 
       
   327 "/                    anchorForHTMLDocAction:
       
   328 "/                        ('htmlDocOf:', owner name )
       
   329 "/                    info:
       
   330 "/                        ( 'Show documentation of ' , owner nameWithoutPrefix )
       
   331 "/                    text:
       
   332 "/                        owner nameWithoutPrefix).
       
   333         outStream nextPutLine:'</b>'.
       
   334     ] ifFalse:[
       
   335         self htmlRevisionDocOf:aClass to:outStream.
       
   336     ].
       
   337     outStream nextPutLine:'</dl>'.
       
   338 
       
   339     authorLines notNil ifTrue:[
       
   340         outStream nextPutLine:'<dl><dt><a name="AUTHOR"><b>Author:</b></A>'.
       
   341         authorLines do:[:l|
       
   342             outStream nextPutLine:'<dd><b>', l , '</b>'.
       
   343         ].
       
   344         outStream nextPutLine:'</dl>'.
       
   345     ].
       
   346 !
       
   347 
       
   348 generateClassProtocolDocumentationForClass:aClass
       
   349     |metaClass shortMetaName|
       
   350 
       
   351     classProtocolCategories notEmpty ifTrue:[
       
   352         metaClass := aClass class.
       
   353         shortMetaName := metaClass nameWithoutPrefix.
       
   354 
       
   355         outStream nextPutLine:'<li><a href="#CLASSPROTOCOL" name="I_CLASSPROTOCOL">Class protocol</a>'.
       
   356         outStream nextPutLine:'<ul>'.
       
   357         classProtocolCategories do:[:cat |
       
   358             outStream nextPutLine:'<li><a name="I_' , shortMetaName , '_category_' , cat , '"' ,
       
   359                                      ' href="#' , shortMetaName , '_category_' , cat ,
       
   360                                      '">' , cat , '</a> '.
       
   361         ].
       
   362         outStream nextPutLine:'</ul>'.
       
   363     ].
       
   364 !
       
   365 
       
   366 generateDemo
       
   367     outStream nextPutLine:'<h2><a name="DEMOSTARTUP" href="#I_DEMOSTARTUP">Demonstration:</A></h2>'.
       
   368     demoLines do:[:l |
       
   369         outStream nextPutLine:'<a INFO="demonstration" type="example">'.
       
   370         outStream nextPutLine:'<pre><code>'.
       
   371         outStream nextPutLine:'    ' , l withoutSeparators.
       
   372         outStream nextPutLine:'</code></pre>'.
       
   373         outStream nextPutLine:'</a>'.
       
   374         outStream nextPutLine:'<br>'.
       
   375     ].
       
   376 !
       
   377 
       
   378 generateDescription:docu
       
   379     docu notNil ifTrue:[
       
   380         outStream nextPutLine:'<h2><a name="DESCRIPTION" href="#I_DESCRIPTION">Description:</A></h2>'.
       
   381         outStream nextPutLine:'<BR>'.
       
   382 
       
   383         outStream nextPutLine:'<pre>'.
       
   384         outStream nextPutLine:docu.
       
   385         outStream nextPutLine:'</pre>'.
       
   386         self generateHorizontalLine.
       
   387     ].
       
   388 !
   299 
   389 
   300 generateExampleEnd
   390 generateExampleEnd
   301     outStream nextPutLine:'</code></pre>'.
   391     outStream nextPutLine:'</code></pre>'.
   302     self generatingForSTXBrowser ifTrue:[
   392     self generatingForSTXBrowser ifTrue:[
   303         outStream nextPutLine:'</a>'.
   393         outStream nextPutLine:'</a>'.
   342         self generateExampleEnd.
   432         self generateExampleEnd.
   343     ].
   433     ].
   344     self generateHorizontalLine.
   434     self generateHorizontalLine.
   345 !
   435 !
   346 
   436 
   347 generatePrivateClassInfoFor:aClass with:privateClasses on:aStream
   437 generateInheritanceTreeForClass:aClass
   348     |s|
   438     |indent first supers subs|
   349 
   439 
   350     s := aStream.
   440     supers := aClass allSuperclasses.
   351 
   441     (aClass == Autoload or:[aClass == Object]) ifTrue:[
   352         s nextPutLine:'<pre>'.
   442         subs := #()
   353         privateClasses do:[:cls |
   443     ] ifFalse:[
   354             |nm fullName|
   444         subs := self shownSubclassesOf:aClass. 
   355 
   445     ].
   356             nm := cls nameWithoutPrefix.
   446 
   357             fullName := cls name.
   447     outStream nextPutLine:'<h2><a name="INHERITANCE" href="#I_INHERITANCE">Inheritance:</A></h2>'.
   358             s nextPutAll:'    '.
   448     outStream nextPutLine:'<pre>'.
   359             (cls owningClass isLoaded not
   449     indent := 3.
   360             or:[cls owningClass wasAutoloaded]) ifTrue:[
   450     first := true.
   361                 self
   451     (supers size > 0) ifTrue:[
   362                     generateClassDocReferenceFor:fullName 
   452         supers reverseDo:[:cls |
   363                     text:nm 
   453             |className|
   364                     autoloading:(cls owningClass name)
   454 
   365             ] ifFalse:[
   455             className := cls name.    
   366                 self 
   456             first ifFalse:[
   367                     generateClassDocReferenceFor:fullName 
   457                 outStream spaces:indent; nextPutLine:'|'.
   368                     text:nm.
   458                 outStream spaces:indent; nextPutAll:'+--'.
       
   459                 indent := indent + 3.
       
   460             ] ifTrue:[
       
   461                 outStream spaces:indent
   369             ].
   462             ].
   370             s cr.
   463             first := false.
   371         ].
   464 
   372         s nextPutLine:'</pre>'.
   465             self generateClassDocReferenceFor:className.
   373 !
   466             outStream cr.
   374 
   467         ].
   375 generateRefLineFor:ref forClass:aClass on:aStream
   468         outStream spaces:indent; nextPutLine:'|'.
       
   469         outStream spaces:indent. 
       
   470         outStream nextPutAll:'+--<B>'; nextPutAll:aClass name; nextPutLine:'</B>'.
       
   471         indent := indent + 3.
       
   472     ] ifFalse:[
       
   473         outStream spaces:indent; nextPutLine:'nil'.
       
   474         outStream spaces:indent; nextPutLine:'|'.
       
   475         outStream spaces:indent; nextPutAll:'+--<B>'; nextPutAll:aClass name; nextPutLine:'</B>'.
       
   476         aClass ~~ Object ifTrue:[
       
   477             outStream cr.
       
   478             outStream nextPutLine:'  <B>This class inherits NOTHING - most messages will lead into doesNotUnderstand:</B>'
       
   479         ].
       
   480         indent := indent + 3.
       
   481     ].
       
   482 
       
   483     subs notEmpty ifTrue:[
       
   484         subs do:[:aSubclass |
       
   485             |className|
       
   486 
       
   487             className := aSubclass name.    
       
   488             outStream spaces:indent; nextPutLine:'|'.
       
   489             outStream spaces:indent; nextPutAll:'+--'.
       
   490             self generateClassDocReferenceFor:className.
       
   491             outStream cr.
       
   492         ]
       
   493     ] ifFalse:[
       
   494         aClass == Object ifTrue:[
       
   495             outStream spaces:indent; nextPutLine:'|'.
       
   496             outStream spaces:indent; nextPutLine:'+-- ... almost every other class ...'
       
   497         ]
       
   498     ].
       
   499 
       
   500     outStream nextPutLine:'</pre>'.
       
   501 !
       
   502 
       
   503 generateInstanceProtocolDocumentationForClass:aClass
       
   504     |shortName|
       
   505 
       
   506     shortName := aClass nameWithoutPrefix.
       
   507     instanceProtocolCategories notEmpty ifTrue:[
       
   508         outStream nextPutLine:'<li><a href="#INSTANCEPROTOCOL" name="I_INSTANCEPROTOCOL">Instance protocol</a>'.
       
   509         outStream nextPutLine:'<ul>'.
       
   510         instanceProtocolCategories do:[:cat |
       
   511             outStream nextPutLine:'<li><a name="I_' , shortName , '_category_' , cat , '"' ,
       
   512                                      ' href="#' , shortName , '_category_' , cat ,
       
   513                                      '">' , cat , '</a> '.
       
   514         ].
       
   515         outStream nextPutLine:'</ul>'.
       
   516     ].
       
   517 !
       
   518 
       
   519 generatePrivateClassInfoForClass:aClass withPrivateClasses:privateClasses
       
   520     outStream nextPutLine:'<pre>'.
       
   521     privateClasses do:[:cls |
       
   522         |nm fullName|
       
   523 
       
   524         nm := cls nameWithoutPrefix.
       
   525         fullName := cls name.
       
   526         outStream nextPutAll:'    '.
       
   527         (cls owningClass isLoaded not
       
   528         or:[cls owningClass wasAutoloaded]) ifTrue:[
       
   529             self
       
   530                 generateClassDocReferenceFor:fullName 
       
   531                 text:nm 
       
   532                 autoloading:(cls owningClass name)
       
   533         ] ifFalse:[
       
   534             self 
       
   535                 generateClassDocReferenceFor:fullName 
       
   536                 text:nm.
       
   537         ].
       
   538         outStream cr.
       
   539     ].
       
   540     outStream nextPutLine:'</pre>'.
       
   541 !
       
   542 
       
   543 generateRefLineFor:ref forClass:aClass
   376     |idx1 idx2 realRef ns nm href|
   544     |idx1 idx2 realRef ns nm href|
   377 
   545 
   378     aStream nextPutAll:'    '.
   546     outStream nextPutAll:'    '.
   379 
   547 
   380     idx1 := ref indexOf:$:.
   548     idx1 := ref indexOf:$:.
   381     idx2 := ref indexOf:$: startingAt:idx1+1.
   549     idx2 := ref indexOf:$: startingAt:idx1+1.
   382 
   550 
   383     (idx1 == 0 or:[idx2 == (idx1+1)]) ifTrue:[
   551     (idx1 == 0 or:[idx2 == (idx1+1)]) ifTrue:[
   384         (ref includesMatchCharacters) ifTrue:[
   552         (ref includesMatchCharacters) ifTrue:[
   385             aStream nextPutAll:(self 
   553             outStream nextPutAll:(self 
   386                         anchorForHTMLDocAction:
   554                         anchorForHTMLDocAction:
   387                             ('htmlClassesMatching:''' , ref , ''' backTo:nil')
   555                             ('htmlClassesMatching:''' , ref , ''' backTo:nil')
   388                         info:
   556                         info:
   389                             ( 'Show documentation of ' , ref )
   557                             ( 'Show documentation of ' , ref )
   390                         text:
   558                         text:
   403         self generateClassDocReferenceFor:realRef text:ref.
   571         self generateClassDocReferenceFor:realRef text:ref.
   404         ^ self
   572         ^ self
   405     ].
   573     ].
   406 
   574 
   407     (ref startsWith:'http:') ifTrue:[
   575     (ref startsWith:'http:') ifTrue:[
   408         aStream nextPutAll:'<a href="' , ref , '"><I>' , ref , '</I></a>'.
   576         outStream nextPutAll:'<a href="' , ref , '"><I>' , ref , '</I></a>'.
   409         ^ self.
   577         ^ self.
   410     ].
   578     ].
   411 
   579 
   412     nm := (ref copyFrom:2 to:idx1-1) withoutSpaces.
   580     nm := (ref copyFrom:2 to:idx1-1) withoutSpaces.
   413     href := (ref copyFrom:(ref indexOf:$:)+1 to:(ref size - 1)) withoutSpaces.
   581     href := (ref copyFrom:(ref indexOf:$:)+1 to:(ref size - 1)) withoutSpaces.
   414     (href startsWith:'man:') ifTrue:[
   582     (href startsWith:'man:') ifTrue:[
   415         href := (href copyFrom:5) withoutSpaces.
   583         href := (href copyFrom:5) withoutSpaces.
   416         aStream nextPutAll:'<a INFO="Show manual page" href="' , self pathToTopOfDocumentation , '/misc/onlyInSTX2.html" action="html:' , self class name , ' manPageFor:''' , href , '''">[<I>' , nm , '</I>]</A>'.
   584         outStream nextPutAll:'<a INFO="Show manual page" href="' , self pathToTopOfDocumentation , '/misc/onlyInSTX2.html" action="html:' , self class name , ' manPageFor:''' , href , '''">[<I>' , nm , '</I>]</A>'.
   417         ^ self.
   585         ^ self.
   418     ].
   586     ].
   419     (href startsWith:'http:') ifTrue:[
   587     (href startsWith:'http:') ifTrue:[
   420         aStream nextPutAll:'<a href="' , href , '">[<I>' , nm , '</I>]</a>'.
   588         outStream nextPutAll:'<a href="' , href , '">[<I>' , nm , '</I>]</a>'.
   421         ^ self
   589         ^ self
   422     ].
   590     ].
   423     (href startsWith:'html:') ifTrue:[
   591     (href startsWith:'html:') ifTrue:[
   424         href := (href copyFrom:6) withoutSpaces.
   592         href := (href copyFrom:6) withoutSpaces.
   425     ].                                             
   593     ].                                             
   426     aStream nextPutAll:'<a href="' , (self pathToDocumentationFile:href) , '">[<I>' , nm , '</I>]</a>'.
   594     outStream nextPutAll:'<a href="' , (self pathToDocumentationFile:href) , '">[<I>' , nm , '</I>]</a>'.
   427 !
   595 !
   428 
   596 
   429 generateRefLines:refLines forClass:aClass on:aStream
   597 generateRefLines:refLines forClass:aClass
   430     aStream nextPutLine:'<pre>'.
   598     outStream nextPutLine:'<pre>'.
   431     refLines do:[:l |
   599     refLines do:[:l |
   432         l isString ifTrue:[
   600         l isString ifTrue:[
   433             self generateRefLineFor:l forClass:aClass on:aStream.
   601             self generateRefLineFor:l forClass:aClass.
   434             aStream cr.
   602             outStream cr.
   435         ] ifFalse:[
   603         ] ifFalse:[
   436             l do:[:ref |
   604             l do:[:ref |
   437                 self generateRefLineFor:ref forClass:aClass on:aStream.
   605                 self generateRefLineFor:ref forClass:aClass.
   438                 aStream cr.
   606                 outStream cr.
   439             ].
   607             ].
   440         ].
   608         ].
   441     ].
   609     ].
   442     aStream nextPutLine:'</pre>'.
   610     outStream nextPutLine:'</pre>'.
   443 !
   611 !
   444 
   612 
   445 generateSubclassInfoFor:aClass on:aStream
   613 generateSubclassInfoForClass:aClass
   446     |s subs|
   614     |subs|
   447 
       
   448     s := aStream.
       
   449 
   615 
   450     subs := self shownSubclassesOf:aClass. 
   616     subs := self shownSubclassesOf:aClass. 
   451 
   617 
   452     s nextPutLine:'<pre>'.
   618     outStream nextPutLine:'<pre>'.
   453     subs do:[:cls |
   619     subs do:[:cls |
   454         |nm|
   620         |nm|
   455 
   621 
   456         nm := cls name.
   622         nm := cls name.
   457         s nextPutAll:'    '.
   623         outStream nextPutAll:'    '.
   458         cls isLoaded ifFalse:[
   624         cls isLoaded ifFalse:[
   459             self 
   625             self 
   460                 generateClassDocReferenceFor:nm
   626                 generateClassDocReferenceFor:nm
   461                 text:nm
   627                 text:nm
   462                 autoloading:nm
   628                 autoloading:nm
   463         ] ifTrue:[
   629         ] ifTrue:[
   464             self generateClassDocReferenceFor:nm.
   630             self generateClassDocReferenceFor:nm.
   465         ].
   631         ].
   466         s cr.
   632         outStream cr.
   467     ].
   633     ].
   468     s nextPutLine:'</pre>'.
   634     outStream nextPutLine:'</pre>'.
   469 
   635 
   470     "Modified: / 05-11-2007 / 17:22:43 / cg"
   636     "Modified: / 05-11-2007 / 17:22:43 / cg"
   471 !
   637 !
       
   638 
       
   639 htmlDocOf:aClass
       
   640     "generate an HTML document string which contains a classes documentation"
       
   641 
       
   642     ^ self htmlDocOf:aClass back:nil backRef:nil
       
   643 
       
   644     "
       
   645      self htmlDocOf:PostscriptPrinterStream
       
   646     "
       
   647 
       
   648     "Modified: / 30.10.1997 / 13:22:19 / cg"
       
   649 !
       
   650 
       
   651 htmlDocOf:aClass back:backCmd
       
   652     "generate an HTML document string which contains a classes documentation"
       
   653 
       
   654     ^ self htmlDocOf:aClass back:backCmd backRef:nil
       
   655 
       
   656     "Modified: / 30.10.1997 / 13:22:27 / cg"
       
   657 !
       
   658 
       
   659 htmlDocOf:aClass back:backCmd backRef:backRef
       
   660     "generate a nice HTML page from a class, with a back-reference
       
   661      to a command or document.
       
   662 
       
   663      Extract sections from the classes documentation method,
       
   664      where the following lines start a special subsection:
       
   665         [see also:]   - references to other classes and/or documents
       
   666         [start with:] - one-liners to start a demonstration
       
   667         [author:]     - author(s) of this class
       
   668         [warning:]    - usage warnings if any
       
   669         [hints:]      - usage hints if any
       
   670      Each section ends with an empty line - however, for formatting,
       
   671      a line consisting of a single backslash character will be converted
       
   672      to an empty line.
       
   673 
       
   674      Also extract examples from the classes example method,
       
   675      where executable examples are made from sections enclosed in:
       
   676         [exBegin]
       
   677         ...
       
   678         [exEnd]
       
   679      these parts are displayed in courier and will be made executable.
       
   680      everything else is plain documentation text.
       
   681     "
       
   682 
       
   683     ^ self
       
   684         htmlDocOf:aClass 
       
   685         back:backCmd 
       
   686         backRef:backRef 
       
   687         imagePath:(self pathToTopOfDocumentation , '/icons')
       
   688 !
       
   689 
       
   690 htmlDocOf:aClass back:backCmdArg backRef:backRefArg imagePath:imagePathArg
       
   691     "generate a nice HTML page from a class, with a back-reference
       
   692      to a command or document.
       
   693 
       
   694      Extract sections from the classes documentation method,
       
   695      where the following lines start a special subsection:
       
   696         [see also:]   - references to other classes and/or documents
       
   697         [start with:] - one-liners to start a demonstration
       
   698         [author:]     - author(s) of this class
       
   699         [warning:]    - usage warnings if any
       
   700         [hints:]      - usage hints if any
       
   701      Each section ends with an empty line - however, for formatting,
       
   702      a line consisting of a single backslash character will be converted
       
   703      to an empty line.
       
   704 
       
   705      Also extract examples from the classes example method,
       
   706      where executable examples are made from sections enclosed in:
       
   707         [exBegin]
       
   708         ...
       
   709         [exEnd]
       
   710      these parts are displayed in courier and will be made executable.
       
   711      everything else is plain documentation text.
       
   712     "
       
   713         
       
   714     |docu examples wasLoaded didLoadBin
       
   715      privateClasses owner shortName |
       
   716 
       
   717     backRef := backRefArg.
       
   718     backCmd := backCmdArg.
       
   719     imagePath := imagePathArg.
       
   720 
       
   721     aClass isNil ifTrue:[
       
   722         ^ ''  "/ just in case ...
       
   723     ].
       
   724 
       
   725     outStream := '' writeStream.
       
   726     shortName := aClass nameWithoutPrefix.
       
   727 
       
   728     self generateHTMLHeadWithTitle:('Class: ' , aClass name).
       
   729     self generateBODYStart.
       
   730     self generateBackButton.
       
   731 
       
   732     (aClass isRealNameSpace) ifTrue:[
       
   733         outStream 
       
   734             nextPutLine:'<h1>';
       
   735             nextPutAll:'NameSpace: ';
       
   736             nextPutLine:(shortName);
       
   737             nextPutLine:'</h1>'.
       
   738         self generateBODYandHTMLEnd.
       
   739         ^ outStream contents.
       
   740     ].
       
   741 
       
   742     (wasLoaded := aClass isLoaded) ifFalse:[
       
   743         "/ load it - but not a binary
       
   744         didLoadBin := Smalltalk loadBinaries.
       
   745         Smalltalk loadBinaries:false.
       
   746         [
       
   747             Autoload autoloadFailedSignal handle:[:ex |
       
   748                 ^ 'Autoload of ' , aClass name , ' failed - no documentation available.'
       
   749             ] do:[
       
   750                 aClass autoload.
       
   751             ].
       
   752         ] ensure:[
       
   753             didLoadBin ifTrue:[Smalltalk loadBinaries:true].
       
   754         ].
       
   755     ].
       
   756 
       
   757     owner := aClass owningClass.
       
   758     privateClasses := aClass privateClassesSorted.
       
   759 
       
   760     docu := self extractDocumentationFromClass:aClass.
       
   761     "/ refLines, demoLines etc. are generated as a side effect.
       
   762 
       
   763     examples := self extractExamplesFromClass:aClass.
       
   764 
       
   765     self extractProtocolCategoriesFrom:aClass.
       
   766 
       
   767     outStream nextPutLine:'<h1>'.
       
   768     outStream nextPutAll:'Class: '.
       
   769 
       
   770     self generatingForSTXBrowser ifTrue:[
       
   771         outStream 
       
   772             nextPutAll:'<a INFO="Open a Browser on ' , shortName , '" type="example" action="Smalltalk browseInClass:' , aClass name , '">';
       
   773             nextPutAll:shortName; nextPutLine:'</a>'.
       
   774     ] ifFalse:[
       
   775         outStream nextPutAll:shortName.
       
   776     ].
       
   777     owner notNil ifTrue:[
       
   778         outStream nextPutAll:' (private in '.
       
   779         self generatingForSTXBrowser ifTrue:[
       
   780             outStream 
       
   781                 nextPutAll:'<a INFO="Open a Browser on ' , owner nameWithoutPrefix , '" type="example" action="Smalltalk browseInClass:' , owner name , '">';
       
   782                 nextPutAll:(owner nameWithoutPrefix); nextPutLine:'</a>)'.
       
   783         ] ifFalse:[
       
   784             outStream nextPutAll:owner nameWithoutPrefix.
       
   785         ].
       
   786     ] ifFalse:[
       
   787         aClass nameSpace ~~ Smalltalk ifTrue:[
       
   788             outStream nextPutAll:' (in ' , aClass nameSpace name , ')'
       
   789         ]
       
   790     ].
       
   791     outStream nextPutLine:'</h1>'.
       
   792 
       
   793     owner notNil ifTrue:[
       
   794         outStream nextPutLine:'This class is only visible from within'.
       
   795         outStream nextPutAll:owner nameWithoutPrefix.
       
   796         owner owningClass notNil ifTrue:[
       
   797             outStream nextPutAll:' (which is itself a private class of '.
       
   798             outStream nextPutAll:owner owningClass nameWithoutPrefix.
       
   799             outStream nextPutAll:')'
       
   800         ].
       
   801         outStream nextPutLine:'.'
       
   802     ].
       
   803 
       
   804     "/
       
   805     "/ index
       
   806     "/
       
   807 "/    s nextPutAll:'Index:'; cr.
       
   808     outStream nextPutLine:'<ul>'.
       
   809     outStream nextPutLine:'<li><a href="#INHERITANCE" name="I_INHERITANCE">Inheritance</a>'.
       
   810 
       
   811     docu notNil ifTrue:[
       
   812         outStream nextPutLine:'<li><a href="#DESCRIPTION" name="I_DESCRIPTION">Description</a>'.
       
   813     ].
       
   814     warnLines notEmptyOrNil ifTrue:[
       
   815         outStream nextPutLine:'<li><a href="#WARNING" name="I_WARNING">Warning</a>'.
       
   816     ].
       
   817     hintLines notEmptyOrNil ifTrue:[
       
   818         outStream nextPutLine:'<li><a href="#HINTS" name="I_HINTS">Hints</a>'.
       
   819     ].
       
   820     refLines notNil ifTrue:[
       
   821         outStream nextPutLine:'<li><a href="#SEEALSO" name="I_SEEALSO">Related information</a>'.
       
   822     ].
       
   823 
       
   824 "/    s nextPutLine:'<li><a href="#INSTANCEVARIABLES" name="I_INSTANCEVARIABLES">Instance variables</a>'.
       
   825 "/    s nextPutLine:'<li><a href="#CLASSVARIABLES" name="I_CLASSVARIABLES">Class variables</a>'.
       
   826 
       
   827     self generateClassProtocolDocumentationForClass:aClass.
       
   828     self generateInstanceProtocolDocumentationForClass:aClass.
       
   829 
       
   830     privateClasses notEmptyOrNil ifTrue:[
       
   831         privateClasses := privateClasses asOrderedCollection sort:[:a :b | a nameWithoutPrefix < b nameWithoutPrefix].
       
   832         outStream nextPutLine:'<li><a href="#PRIVATECLASSES" name="I_PRIVATECLASSES">Private classes</a>'.
       
   833     ].
       
   834 
       
   835     (aClass == Object or:[aClass == Autoload]) ifTrue:[
       
   836         outStream nextPutLine:'<li><a href="#SUBCLASSES" name="I_SUBCLASSES">Subclasses</a>'.
       
   837     ].
       
   838     demoLines notNil ifTrue:[
       
   839         outStream nextPutLine:'<li><a href="#DEMOSTARTUP" name="I_DEMOSTARTUP">Demonstration</a>'.
       
   840     ].
       
   841     examples notNil ifTrue:[
       
   842         outStream nextPutLine:'<li><a href="#EXAMPLES" name="I_EXAMPLES">Examples</a>'.
       
   843     ].
       
   844     outStream nextPutLine:'</ul>'.
       
   845     self generateHorizontalLine.
       
   846 
       
   847     "/
       
   848     "/ hierarchy
       
   849     "/
       
   850     self generateInheritanceTreeForClass:aClass.
       
   851     self generateHorizontalLine.
       
   852 
       
   853     "/
       
   854     "/ category, version & package
       
   855     "/
       
   856     self generateClassInfoForClass:aClass.
       
   857     self generateHorizontalLine.
       
   858 
       
   859     self generateDescription:docu.
       
   860 
       
   861     warnLines notNil ifTrue:[
       
   862         outStream nextPutLine:'<h2><a name="WARNING" href="#I_WARNING">Warning:</A></h2>'.
       
   863         outStream nextPutLine:'<BR>'.
       
   864 
       
   865         outStream nextPutLine:'<pre>'.
       
   866 
       
   867         warnLines := self undentedToFirstLinesIndent:warnLines.
       
   868         warnLines do:[:aLine |
       
   869             outStream nextPutLine:aLine
       
   870         ].
       
   871         outStream nextPutLine:'</pre>'.
       
   872         self generateHorizontalLine.
       
   873     ].
       
   874 
       
   875     hintLines notNil ifTrue:[
       
   876         outStream nextPutLine:'<h2><a name="HINTS" href="#I_HINTS">Hints:</A></h2>'.
       
   877         outStream nextPutLine:'<BR>'.
       
   878 
       
   879         outStream nextPutLine:'<pre>'.
       
   880         hintLines := self undentedToFirstLinesIndent:hintLines.
       
   881 
       
   882         hintLines do:[:aLine |
       
   883             outStream nextPutLine:aLine
       
   884         ].
       
   885         outStream nextPutLine:'</pre>'.
       
   886         self generateHorizontalLine.
       
   887     ].
       
   888 
       
   889     "/
       
   890     "/ see also
       
   891     "/
       
   892     refLines notNil ifTrue:[
       
   893         outStream nextPutLine:'<h2><a name="SEEALSO" href="#I_SEEALSO">Related information:</A></h2>'.
       
   894         self generateRefLines:refLines forClass:aClass.        
       
   895         self generateHorizontalLine.
       
   896     ].
       
   897 
       
   898 
       
   899     "/
       
   900     "/ inst & classVars
       
   901     "/ to be added
       
   902 
       
   903 
       
   904     "/
       
   905     "/ protocol
       
   906     "/
       
   907     self printOutHTMLProtocolOf:aClass on:outStream.
       
   908 
       
   909     "/
       
   910     "/ subclasses (only for Object and Autoload)
       
   911     "/
       
   912     (aClass == Object or:[aClass == Autoload]) ifTrue:[
       
   913         outStream nextPutLine:'<h2><a name="SUBCLASSES" href="#I_SUBCLASSES">Subclasses (direct subclasses only):</A></h2>'.
       
   914         self generateSubclassInfoForClass:aClass.
       
   915         self generateHorizontalLine.
       
   916     ].
       
   917 
       
   918     "/
       
   919     "/ private classes
       
   920     "/
       
   921     privateClasses notEmptyOrNil ifTrue:[
       
   922         outStream nextPutLine:'<h2><a name="PRIVATECLASSES" href="#I_PRIVATECLASSES">Private classes:</A></h2>'.
       
   923         self generatePrivateClassInfoForClass:aClass withPrivateClasses:privateClasses.
       
   924         self generateHorizontalLine.
       
   925     ].
       
   926 
       
   927     "/ demonstration, if there are any
       
   928     demoLines notNil ifTrue:[
       
   929         self generateDemo.
       
   930         self generateHorizontalLine.
       
   931     ].
       
   932 
       
   933     "/ examples, if there are any
       
   934     examples notNil ifTrue:[
       
   935         self generateExamples:examples.
       
   936     ].
       
   937 
       
   938     self generateBODYandHTMLEnd.
       
   939 
       
   940     wasLoaded ifFalse:[
       
   941         aClass unload
       
   942     ].
       
   943 
       
   944     ^ outStream contents
       
   945 
       
   946     "
       
   947      self htmlDocOf:Object
       
   948      self htmlDocOf:Array
       
   949      self htmlDocOf:Filename
       
   950      self htmlDocOf:Block
       
   951     "
       
   952 
       
   953     "Created: / 24-04-1996 / 15:01:59 / cg"
       
   954     "Modified: / 05-11-2007 / 17:22:54 / cg"
       
   955 !
       
   956 
       
   957 htmlDocOf:aClass backRef:backRef
       
   958     "generate an HTML document string which contains a classes documentation"
       
   959 
       
   960     ^ self htmlDocOf:aClass back:nil backRef:backRef
       
   961 
       
   962     "Created: / 24.4.1996 / 15:03:25 / cg"
       
   963     "Modified: / 30.10.1997 / 13:23:12 / cg"
       
   964 !
       
   965 
       
   966 htmlDocOfImplementorsOf:selector
       
   967     "generate an HTML document string which contains HREFS
       
   968      to all implementors of a particular selector"
       
   969 
       
   970     |sel s classes|
       
   971 
       
   972     sel := self withSpecialHTMLCharactersEscaped:selector.
       
   973 
       
   974     outStream := s := '' writeStream.
       
   975 
       
   976     self generateHTMLHeadWithTitle:('Implementations of: ' , sel).
       
   977     self generateBODYStart.
       
   978 
       
   979     self generateUpArrowButtonForTop.
       
   980     self generateHorizontalLine.
       
   981     self generateH1:sel.
       
   982 
       
   983     s nextPutLine:'<dl>'.
       
   984 
       
   985     classes := IdentitySet new.
       
   986 
       
   987     sel := selector asSymbol.
       
   988     Smalltalk allClassesAndMetaclassesDo:[:cls |
       
   989         cls isPrivate ifFalse:[
       
   990             (cls includesSelector:sel) ifTrue:[
       
   991                 classes add:cls
       
   992             ]
       
   993         ]
       
   994     ].
       
   995 
       
   996     (classes asOrderedCollection sort:[:a :b | a name < b name]) 
       
   997         do:[:cls |
       
   998             self 
       
   999                 printOutHTMLMethodProtocol:(cls compiledMethodAt:sel) 
       
  1000                 on:s 
       
  1001                 showClassName:true 
       
  1002                 classRef:true.
       
  1003             s nextPutLine:'<p>'.
       
  1004         ].
       
  1005 
       
  1006     s nextPutLine:'</dl>'.
       
  1007     self generateBODYandHTMLEnd.
       
  1008 
       
  1009     ^ s contents
       
  1010 
       
  1011     "Created: / 22.4.1996 / 20:03:31 / cg"
       
  1012     "Modified: / 30.10.1998 / 22:15:30 / cg"
       
  1013 !
       
  1014 
       
  1015 htmlDocOfImplementorsOfAnyMatching:selectorPattern
       
  1016     "generate an HTML document string which contains HREFS
       
  1017      to all implementors of a particular selector"
       
  1018 
       
  1019     |s sel classes|
       
  1020 
       
  1021     outStream := s := '' writeStream.
       
  1022 
       
  1023     sel := self withSpecialHTMLCharactersEscaped:selectorPattern.
       
  1024     self generateHTMLHeadWithTitle:('Implementations of: ' , sel).
       
  1025     self generateBODYStart.
       
  1026 
       
  1027     self generateUpArrowButtonForTop.
       
  1028     self generateHorizontalLine.
       
  1029 
       
  1030     self generateH1:sel.
       
  1031 
       
  1032     s nextPutLine:'<dl>'.
       
  1033 
       
  1034     classes := IdentitySet new.
       
  1035 
       
  1036     Smalltalk allClassesAndMetaclassesDo:[:cls |
       
  1037         cls isPrivate ifFalse:[
       
  1038             (cls methodDictionary keys contains:[:sel | selectorPattern match:sel]) ifTrue:[
       
  1039                 classes add:cls
       
  1040             ]
       
  1041         ]
       
  1042     ].
       
  1043 
       
  1044     (classes asOrderedCollection sort:[:a :b | a name < b name]) 
       
  1045         do:[:cls |
       
  1046             cls methodDictionary keys do:[:eachSel |
       
  1047                 (selectorPattern match:eachSel) ifTrue:[
       
  1048                     self 
       
  1049                         printOutHTMLMethodProtocol:(cls compiledMethodAt:eachSel) 
       
  1050                         on:s 
       
  1051                         showClassName:true 
       
  1052                         classRef:true.
       
  1053                     s nextPutLine:'<p>'.
       
  1054                 ].
       
  1055             ].
       
  1056         ].
       
  1057 
       
  1058     s nextPutLine:'</dl>'.
       
  1059     self generateBODYandHTMLEnd.
       
  1060 
       
  1061     ^ s contents
       
  1062 ! !
       
  1063 
       
  1064 !HTMLDocGenerator methodsFor:'document generation-helpers'!
       
  1065 
       
  1066 extractAndRemoveSpecial:pattern from:docu
       
  1067     "given a collection of docu lines (from documentation methods comment),
       
  1068      extract things like [see also:], [author:] etc.
       
  1069      If found, remove the lines from the string collection,
       
  1070      and return the extracted ones. Otherwise return nil.
       
  1071      Attention: docu is sideeffectively changed (lines removed)"
       
  1072 
       
  1073     |srchIdx idx lines l|
       
  1074 
       
  1075     srchIdx := docu findFirst:[:l | l asLowercase withoutSeparators = pattern].
       
  1076     srchIdx ~~ 0 ifTrue:[
       
  1077         lines := OrderedCollection new.
       
  1078 
       
  1079         idx := srchIdx+1.
       
  1080         [idx <= docu size] whileTrue:[
       
  1081             l := docu at:idx.
       
  1082             (l isNil or:[l withoutSeparators size == 0]) ifTrue:[
       
  1083                 idx := docu size + 1.
       
  1084             ] ifFalse:[
       
  1085                 l withoutSeparators = '\' ifTrue:[
       
  1086                     l := ''
       
  1087                 ].
       
  1088                 lines add:l
       
  1089             ].
       
  1090             idx := idx + 1.
       
  1091         ].
       
  1092 
       
  1093         docu removeFromIndex:srchIdx toIndex:srchIdx+lines size
       
  1094     ].
       
  1095     ^ lines
       
  1096 
       
  1097     "Created: 25.4.1996 / 14:16:01 / cg"
       
  1098     "Modified: 11.1.1997 / 13:03:38 / cg"
       
  1099 !
       
  1100 
       
  1101 extractAndRemoveSpecialLinesFromDocumentation:docu
       
  1102     "Extract things like [see also:], [author:] etc. from docu
       
  1103      If found, remove the lines from the string collection,
       
  1104      and leave them in corresponding instVars.
       
  1105      Attention: docu is sideeffectively changed (lines removed)"
       
  1106 
       
  1107     "/
       
  1108     "/ search for a [see also:] section
       
  1109     "/
       
  1110     refLines := self extractAndRemoveSpecial:'[see also:]' from:docu.
       
  1111     refLines notNil ifTrue:[
       
  1112         "/ care for the special tuple format
       
  1113         refLines := refLines collect:[:l | 
       
  1114                         |t|
       
  1115 
       
  1116                         ((t := l withoutSeparators) startsWith:'(') ifTrue:[
       
  1117                             t
       
  1118                         ] ifFalse:[
       
  1119                             t := l asCollectionOfWords.
       
  1120                             (t size == 1
       
  1121                             and:[ (t first includes:$:) not ]) ifTrue:[
       
  1122                                 t first
       
  1123                             ] ifFalse:[
       
  1124                                 t
       
  1125                             ]
       
  1126                         ]
       
  1127                     ].
       
  1128     ].
       
  1129 
       
  1130 
       
  1131     "/
       
  1132     "/ search for a [start with:] section
       
  1133     "/
       
  1134     demoLines := self extractAndRemoveSpecial:'[start with:]' from:docu.
       
  1135 
       
  1136     "/
       
  1137     "/ search for a [author:] section
       
  1138     "/
       
  1139     authorLines := self extractAndRemoveSpecial:'[author:]' from:docu.
       
  1140     authorLines isNil ifTrue:[
       
  1141         authorLines := self extractAndRemoveSpecial:'[authors:]' from:docu.
       
  1142     ].
       
  1143 
       
  1144     "/
       
  1145     "/ search for a [warning:] section
       
  1146     "/
       
  1147     warnLines := self extractAndRemoveSpecial:'[warning:]' from:docu.
       
  1148     warnLines notNil ifTrue:[
       
  1149         warnLines := warnLines asStringCollection.
       
  1150     ].
       
  1151 
       
  1152     "/
       
  1153     "/ search for a [hints:] section
       
  1154     "/
       
  1155     hintLines := self extractAndRemoveSpecial:'[hints:]' from:docu.
       
  1156     hintLines isNil ifTrue:[
       
  1157         hintLines := self extractAndRemoveSpecial:'[hint:]' from:docu.
       
  1158     ].
       
  1159     hintLines notNil ifTrue:[
       
  1160         hintLines := hintLines asStringCollection.
       
  1161     ].
       
  1162 !
       
  1163 
       
  1164 extractDocumentationFromClass:aClass
       
  1165     |documentationMethod docu|
       
  1166 
       
  1167     documentationMethod := aClass theMetaclass compiledMethodAt:#documentation.
       
  1168     documentationMethod notNil ifTrue:[
       
  1169         docu := documentationMethod comment.
       
  1170     ] ifFalse:[
       
  1171         "try comment"
       
  1172         docu := aClass theNonMetaclass comment.
       
  1173     ].
       
  1174     docu isEmptyOrNil ifTrue:[ ^ nil ].
       
  1175 
       
  1176     docu := self withSpecialHTMLCharactersEscaped:docu.
       
  1177     docu := docu asStringCollection.
       
  1178 
       
  1179     self extractAndRemoveSpecialLinesFromDocumentation:docu.
       
  1180 
       
  1181     docu notEmpty ifTrue:[
       
  1182         "/
       
  1183         "/ strip off empty lines
       
  1184         "/
       
  1185         [docu notEmpty and:[ docu first size == 0]] whileTrue:[
       
  1186             docu removeFirst
       
  1187         ].
       
  1188         [docu notEmpty and:[ docu last size == 0]] whileTrue:[
       
  1189             docu removeLast
       
  1190         ].
       
  1191     ].
       
  1192 
       
  1193     docu notEmpty ifTrue:[
       
  1194         docu := self undentedToFirstLinesIndent:docu.
       
  1195     ].
       
  1196     docu := docu asString.
       
  1197     ^ docu
       
  1198 !
       
  1199 
       
  1200 extractExamplesFromClass:aClass
       
  1201     |m examples|
       
  1202 
       
  1203     m := aClass theMetaclass compiledMethodAt:#examples.
       
  1204     m isNil ifTrue:[ ^ nil].
       
  1205 
       
  1206     examples := m comment.
       
  1207     examples isEmptyOrNil ifTrue:[ ^ nil].
       
  1208 
       
  1209     examples := self withSpecialHTMLCharactersEscaped:examples.
       
  1210     examples := examples asStringCollection.
       
  1211 
       
  1212     "/
       
  1213     "/ strip off empty lines
       
  1214     "/
       
  1215     [examples first size == 0] whileTrue:[
       
  1216         examples removeIndex:1
       
  1217     ].
       
  1218     [examples last size == 0] whileTrue:[
       
  1219         examples removeIndex:(examples size)
       
  1220     ].
       
  1221 
       
  1222     examples isEmpty ifTrue:[ ^ nil].
       
  1223 
       
  1224     examples := self undentedToFirstLinesIndent:examples.
       
  1225     ^ examples
       
  1226 !
       
  1227 
       
  1228 extractProtocolCategoriesFrom:aClass
       
  1229     classProtocolCategories := aClass theMetaclass categories asSortedCollection.
       
  1230     classProtocolCategories notEmpty ifTrue:[
       
  1231         classProtocolCategories := classProtocolCategories asSortedCollection.
       
  1232         classProtocolCategories remove:'documentation' ifAbsent:nil.
       
  1233     ].
       
  1234     instanceProtocolCategories := aClass theNonMetaclass categories asSortedCollection.
       
  1235     instanceProtocolCategories notEmpty ifTrue:[
       
  1236         instanceProtocolCategories := instanceProtocolCategories asSortedCollection.
       
  1237     ].
       
  1238 !
       
  1239 
       
  1240 htmlForMethod:aMethod
       
  1241     |who sel partStream args argStream methodSpecLine|
       
  1242 
       
  1243     who := aMethod who.
       
  1244     sel := who methodSelector.
       
  1245 
       
  1246     partStream := sel keywords readStream.
       
  1247 
       
  1248     (args := aMethod methodArgNames) notNil ifTrue:[
       
  1249         argStream := args readStream.
       
  1250 
       
  1251         methodSpecLine := ''. 
       
  1252         1 to:sel numArgs do:[:index |
       
  1253             methodSpecLine size > 0 ifTrue:[
       
  1254                 methodSpecLine := methodSpecLine , ' '
       
  1255             ].
       
  1256             methodSpecLine := methodSpecLine , '<B>' , partStream next , '</B>'.
       
  1257             methodSpecLine := methodSpecLine , ' <I>' , argStream next , '</I>'.
       
  1258         ].
       
  1259     ] ifFalse:[
       
  1260         methodSpecLine := '<B>' , partStream next , '</B>'
       
  1261     ].
       
  1262     ^ methodSpecLine
       
  1263 
       
  1264     "Created: / 05-11-2007 / 16:13:39 / cg"
       
  1265 !
       
  1266 
       
  1267 htmlRevisionDocOf:aClass to:s
       
  1268     "extract a classes versionInfo and return an HTML document string
       
  1269      for that."
       
  1270 
       
  1271     |revInfo pckgInfo text path|
       
  1272 
       
  1273     revInfo := aClass revisionInfo.
       
  1274     pckgInfo := aClass packageSourceCodeInfo.
       
  1275 
       
  1276     s nextPutLine:'<dl><dt><a name="VERSION"><b>Version:</b></A>'.
       
  1277 
       
  1278     (revInfo isNil and:[pckgInfo isNil]) ifTrue:[
       
  1279         s nextPutLine:'<dd>no revision info'.
       
  1280     ] ifFalse:[
       
  1281 
       
  1282         revInfo isNil ifTrue:[revInfo := IdentityDictionary new].
       
  1283         pckgInfo isNil ifTrue:[pckgInfo := IdentityDictionary new].
       
  1284 
       
  1285         s nextPutLine:'<dd>rev: <b>'.
       
  1286 
       
  1287         "/ fetch the revision-info; prefer revisionInfo
       
  1288         text := revInfo at:#revision ifAbsent:(pckgInfo at:#revision ifAbsent:'?').
       
  1289         s nextPutLine:text.
       
  1290 
       
  1291         "/ fetch the date & time; prefer revisionInfo
       
  1292         text := revInfo at:#date ifAbsent:(pckgInfo at:#date ifAbsent:'?').
       
  1293         s nextPutAll:'</b> date: <b>' ,  text.
       
  1294         text := revInfo at:#time ifAbsent:(pckgInfo at:#time ifAbsent:'?').
       
  1295         s nextPutLine:' ', text , '</b>'.
       
  1296 
       
  1297         text := revInfo at:#user ifAbsent:(pckgInfo at:#user ifAbsent:'?').
       
  1298         s nextPutLine:'<dd>user: <b>' , text , '</b>'.
       
  1299 
       
  1300         text := revInfo at:#fileName ifAbsent:(pckgInfo at:#fileNamer ifAbsent:'?').
       
  1301         s nextPutAll:'<dd>file: <b>' , text.
       
  1302 
       
  1303         text := revInfo at:#directory ifAbsent:(pckgInfo at:#directory ifAbsent:nil).
       
  1304         text isNil ifTrue:[
       
  1305             path := revInfo at:#repositoryPathName ifAbsent:(pckgInfo at:#repositoryPathName ifAbsent:nil).
       
  1306             path notNil ifTrue:[
       
  1307                 SourceCodeManager notNil ifTrue:[
       
  1308                     text := SourceCodeManager directoryFromContainerPath:path forClass:aClass.
       
  1309                 ].
       
  1310                 text isNil ifTrue:[text := '?'].
       
  1311             ] ifFalse:[
       
  1312                 text := '?'
       
  1313             ]
       
  1314         ].
       
  1315         s nextPutLine:'</b> directory: <b>' , text , '</b>'.
       
  1316 
       
  1317         text := revInfo at:#module ifAbsent:(pckgInfo at:#module ifAbsent:nil).
       
  1318         text isNil ifTrue:[
       
  1319             path := revInfo at:#repositoryPathName ifAbsent:(pckgInfo at:#repositoryPathName ifAbsent:nil).
       
  1320             path notNil ifTrue:[
       
  1321                 SourceCodeManager notNil ifTrue:[
       
  1322                     text := SourceCodeManager moduleFromContainerPath:path forClass:aClass.
       
  1323                 ].
       
  1324                 text isNil ifTrue:[text := '?'].
       
  1325             ] ifFalse:[
       
  1326                 text := '?'
       
  1327             ]
       
  1328         ].
       
  1329         s nextPutAll:'<dd>module: <b>' , text.
       
  1330 
       
  1331         text := revInfo at:#library ifAbsent:(pckgInfo at:#library ifAbsent:'*none*').
       
  1332         s nextPutLine:'</b> stc-classLibrary: <b>' ,  text , '</b>'.
       
  1333     ].
       
  1334 
       
  1335     "Created: / 8.1.1997 / 13:43:28 / cg"
       
  1336     "Modified: / 30.10.1997 / 13:24:39 / cg"
       
  1337 !
       
  1338 
       
  1339 printOutHTMLCategoryProtocol:aCategory of:aClass on:aStream
       
  1340     "append documentation on each method in a particular methodCategory
       
  1341      of the given class in HTML onto aStream."
       
  1342 
       
  1343     |any dict selectors methods shortName|
       
  1344 
       
  1345     shortName := aClass nameWithoutPrefix.
       
  1346 
       
  1347     dict := aClass methodDictionary.
       
  1348 
       
  1349     dict notNil ifTrue:[
       
  1350         any := false.
       
  1351         dict do:[:aMethod |
       
  1352             (aCategory = aMethod category) ifTrue:[
       
  1353                 any := true
       
  1354             ]
       
  1355         ].
       
  1356 
       
  1357         any ifTrue:[
       
  1358             aStream nextPutLine:'<a name="' , shortName , '_category_' , aCategory ,
       
  1359                                      '" href="#I_' , shortName , '_category_' , aCategory ,
       
  1360                                      '"><b>' , aCategory , '</b></A>'.
       
  1361             aStream nextPutLine:'<dl>'.
       
  1362 
       
  1363             selectors := dict keys asArray.
       
  1364             methods := dict values.
       
  1365             selectors sortWith:methods.
       
  1366             methods do:[:aMethod |
       
  1367                 (aCategory = aMethod category) ifTrue:[
       
  1368                     Error catch:[
       
  1369                         self printOutHTMLMethodProtocol:aMethod on:aStream.
       
  1370                     ].
       
  1371                     aStream nextPutLine:'<p>'.
       
  1372                 ]
       
  1373             ].
       
  1374             aStream nextPutLine:'</dl>'.
       
  1375         ]
       
  1376     ]
       
  1377 
       
  1378     "
       
  1379       self printOutHTMLProtocolOf:Float on:Stdout 
       
  1380     "
       
  1381 
       
  1382     "Created: / 22.4.1996 / 20:03:30 / cg"
       
  1383     "Modified: / 5.6.1996 / 13:41:27 / stefan"
       
  1384     "Modified: / 30.10.1997 / 13:27:58 / cg"
       
  1385 !
       
  1386 
       
  1387 printOutHTMLMethodProtocol:aMethod on:aStream
       
  1388     "given the source in aString, print the methods message specification
       
  1389      and any method comments - without source; used to generate documentation
       
  1390      pages"
       
  1391 
       
  1392     ^ self 
       
  1393         printOutHTMLMethodProtocol:aMethod 
       
  1394         on:aStream 
       
  1395         showClassName:false 
       
  1396         classRef:false
       
  1397 
       
  1398     "Modified: 22.4.1996 / 18:01:56 / cg"
       
  1399     "Created: 22.4.1996 / 20:03:30 / cg"
       
  1400 !
       
  1401 
       
  1402 printOutHTMLMethodProtocol:aMethod on:aStream showClassName:showClassName classRef:withClassRef
       
  1403     "given the source in aString, print the methods message specification
       
  1404      and any method comments - without source; used to generate documentation
       
  1405      pages"
       
  1406 
       
  1407     |p|
       
  1408 
       
  1409 "/    p := imagePath.
       
  1410 "/    p isNil ifTrue:[
       
  1411 "/        p := self pathToTopOfDocumentation , '/icons' 
       
  1412 "/    ].
       
  1413     p := self pathToTopOfDocumentation , '/pictures'.
       
  1414     ^ self
       
  1415         printOutHTMLMethodProtocol:aMethod 
       
  1416         on:aStream 
       
  1417         showClassName:showClassName 
       
  1418         classRef:withClassRef 
       
  1419         picturePath:p
       
  1420 !
       
  1421 
       
  1422 printOutHTMLMethodProtocol:aMethod on:aStream showClassName:showClassName classRef:withClassRef picturePath:picturePath
       
  1423     "given the source in aString, print the methods message specification
       
  1424      and any method comments - without source; used to generate documentation
       
  1425      pages"
       
  1426 
       
  1427     |comment cls sel who methodSpecLine 
       
  1428      firstIndent firstNonEmpty isSubres isObsolete smallOrEmpty
       
  1429      ballColor anchorName parseTree expr obsoleteInfo|
       
  1430 
       
  1431     who := aMethod who.
       
  1432     cls := who methodClass.
       
  1433     sel := who methodSelector.
       
  1434 
       
  1435     methodSpecLine := self htmlForMethod:aMethod.
       
  1436 
       
  1437     "/ use string-asSymbol (instead of the obvious symbol itself)
       
  1438     "/ in the checks below, to avoid tricking myself,
       
  1439     "/ when the documentation on this method is generated
       
  1440     "/ (otherwise, I'll say that this method is both
       
  1441     "/  a subres and and obsolete method ...)
       
  1442 
       
  1443     isSubres := (aMethod sends:#'subclassResponsibility').
       
  1444 
       
  1445     isObsolete := aMethod isObsolete.
       
  1446     "/ the above checks for the obsolete-resource flag;
       
  1447     "/ there is still achance for obsoleteMethodWarning to be sent, without the resource flag being present.
       
  1448     isObsolete ifFalse:[
       
  1449         ((aMethod sends:'obsoleteMethodWarning' asSymbol)
       
  1450         or:[(aMethod sends:'obsoleteMethodWarning:' asSymbol)
       
  1451         or:[(aMethod sends:'obsoleteMethodWarning:from:' asSymbol)]]) ifTrue:[
       
  1452             (sel startsWith:'obsoleteMethodWarning') ifFalse:[
       
  1453                 true "cls ~~ Object" ifTrue:[
       
  1454                     isObsolete := true.
       
  1455                     ParseTreeSearcher notNil ifTrue:[
       
  1456                         parseTree := cls parseTreeFor:sel.
       
  1457                         parseTree notNil ifTrue: [
       
  1458                             expr := ParseTreeSearcher treeMatching:'`@e1 obsoleteMethodWarning:`@e2' in: parseTree.
       
  1459                             expr isNil ifTrue:[
       
  1460                                 expr := ParseTreeSearcher treeMatching:'`@e1 obsoleteMethodWarning:`@e2 from:`@e3' in: parseTree.
       
  1461                             ].
       
  1462                             expr notNil ifTrue:[
       
  1463                                 |arg1|
       
  1464 
       
  1465                                 arg1 := expr arguments first.
       
  1466                                 arg1 isLiteral ifTrue:[
       
  1467                                     arg1 value isString ifTrue:[
       
  1468                                         obsoleteInfo := arg1 value.
       
  1469                                     ].
       
  1470                                 ].
       
  1471                             ].
       
  1472                         ].
       
  1473                     ].
       
  1474                 ].
       
  1475             ]
       
  1476         ].
       
  1477     ].
       
  1478 
       
  1479     smallOrEmpty := ''.
       
  1480     aMethod isPrivate ifTrue:[
       
  1481         methodSpecLine :=  '<i>private</i> ' , methodSpecLine.
       
  1482 "/        smallOrEmpty := '-small'.
       
  1483     ] ifFalse:[
       
  1484         aMethod isProtected ifTrue:[
       
  1485             methodSpecLine := '<i>protected</i> ' , methodSpecLine.
       
  1486 "/            smallOrEmpty := '-small'.
       
  1487         ] ifFalse:[
       
  1488             aMethod isIgnored ifTrue:[
       
  1489                 methodSpecLine := '[ ' , methodSpecLine , ' ] (<i>invisible</i>)'.
       
  1490 "/                smallOrEmpty := '-small'.
       
  1491             ]
       
  1492         ]
       
  1493     ].
       
  1494 
       
  1495     aStream nextPutLine:'<DT>'.
       
  1496 
       
  1497 
       
  1498     cls isMeta ifTrue:[
       
  1499         ballColor := 'yellow'
       
  1500     ] ifFalse:[
       
  1501         ballColor := 'red'
       
  1502     ].
       
  1503 
       
  1504     aStream nextPutLine:'<IMG src="' , picturePath , '/' , ballColor , '-ball' , smallOrEmpty , '.gif" alt="o " width=6 height=6>'.
       
  1505     aStream nextPutAll:'&nbsp;'.
       
  1506 
       
  1507     sel := self withSpecialHTMLCharactersEscaped:sel.
       
  1508     anchorName := cls name , '_' , sel.
       
  1509 
       
  1510     withClassRef ifTrue:[
       
  1511         aStream nextPutAll:(self 
       
  1512                             anchorForHTMLDocAction:
       
  1513                                 ('htmlDocOf:', cls theNonMetaclass name )
       
  1514                             info:
       
  1515                                 ('Show documentation of ' , cls theNonMetaclass name )
       
  1516                             text:
       
  1517                                 cls name
       
  1518                             name:anchorName).
       
  1519         aStream nextPutLine:'&nbsp;' , methodSpecLine.
       
  1520     ] ifFalse:[
       
  1521         showClassName ifTrue:[
       
  1522             methodSpecLine := cls name , ' ' , methodSpecLine
       
  1523         ].
       
  1524 
       
  1525         aStream nextPutLine:'<a name="' , anchorName , '" ' ,
       
  1526 "/                                 'href="' , cls name , '_' , sel , '"' ,
       
  1527                                  '>' , methodSpecLine , '</a>'.
       
  1528     ].
       
  1529     aStream nextPutLine:'<DD>'.
       
  1530 
       
  1531     (comment := self methodCommentOf:aMethod) notNil ifTrue:[
       
  1532         comment := self withSpecialHTMLCharactersEscaped:comment.
       
  1533 
       
  1534         comment notEmpty ifTrue:[
       
  1535             comment := comment asStringCollection.
       
  1536             firstIndent := comment first leftIndent.
       
  1537             firstIndent > 0 ifTrue:[
       
  1538                 comment := comment collect:[:line |
       
  1539                                         line leftIndent >= firstIndent ifTrue:[
       
  1540                                             line copyFrom:firstIndent.
       
  1541                                         ] ifFalse:[
       
  1542                                             line
       
  1543                                         ]
       
  1544                                      ].
       
  1545             ].
       
  1546             firstNonEmpty := comment findFirst:[:line | line notEmpty].
       
  1547             firstNonEmpty > 1 ifTrue:[
       
  1548                 comment := comment copyFrom:firstNonEmpty
       
  1549             ].
       
  1550             comment := comment asString.
       
  1551         ].
       
  1552 
       
  1553         comment asStringCollection do:[:line |
       
  1554             aStream 
       
  1555                 "/ nextPutAll:'<I>'; 
       
  1556                 nextPutAll:line; 
       
  1557                 "/ nextPutAll:'</I>'; 
       
  1558                 nextPutLine:'<BR>'.
       
  1559         ].
       
  1560     ].
       
  1561 
       
  1562     isSubres ifTrue:[
       
  1563         aStream nextPutLine:'<BR>'.
       
  1564         aStream nextPutLine:'<I>** This method raises an error - it must be redefined in concrete classes **</I>'.
       
  1565     ].
       
  1566     isObsolete ifTrue:[
       
  1567         aStream nextPutLine:'<BR>'.
       
  1568         aStream nextPutLine:'<I>** This is an obsolete interface - do not use it (it may vanish in future versions) **</I>'.
       
  1569         obsoleteInfo notNil ifTrue:[
       
  1570             aStream nextPutLine:'<BR>'.
       
  1571             aStream nextPutLine:'<I>** ' , obsoleteInfo , ' **</I>'.
       
  1572         ].
       
  1573     ].
       
  1574 
       
  1575     "Created: / 22-04-1996 / 20:03:30 / cg"
       
  1576     "Modified: / 05-11-2007 / 16:13:46 / cg"
       
  1577 !
       
  1578 
       
  1579 printOutHTMLProtocolOf:aClass on:aStream 
       
  1580     "append documentation  of the given class in HTML onto aStream."
       
  1581 
       
  1582     |collectionOfCategories any|
       
  1583 
       
  1584 "/    self printOutDefinitionOn:aPrintStream.
       
  1585 
       
  1586     collectionOfCategories := aClass class categories asSortedCollection.
       
  1587     any := false.
       
  1588 
       
  1589     collectionOfCategories size > 0 ifTrue:[
       
  1590         collectionOfCategories := collectionOfCategories asOrderedCollection.
       
  1591         collectionOfCategories remove:'documentation' ifAbsent:[].
       
  1592         collectionOfCategories size > 0 ifTrue:[
       
  1593             collectionOfCategories sort.
       
  1594             aStream nextPutLine:'<h2><a name="CLASSPROTOCOL" href="#I_CLASSPROTOCOL">Class protocol:</a></h2>'.
       
  1595             collectionOfCategories do:[:aCategory |
       
  1596                 self printOutHTMLCategoryProtocol:aCategory of:aClass class on:aStream.
       
  1597                 any := true.
       
  1598             ].
       
  1599 "/        any ifFalse:[
       
  1600 "/            aStream nextPutAll:'no new protocol'
       
  1601 "/        ].
       
  1602             self generateHorizontalLine.
       
  1603         ]
       
  1604     ].
       
  1605 
       
  1606 
       
  1607     collectionOfCategories := aClass categories asSortedCollection.
       
  1608     any := false.
       
  1609     collectionOfCategories size > 0 ifTrue:[
       
  1610         collectionOfCategories := collectionOfCategories asOrderedCollection sort.
       
  1611         aStream nextPutLine:'<h2><a name="INSTANCEPROTOCOL" href="#I_INSTANCEPROTOCOL">Instance protocol:</A></h2>'.
       
  1612         collectionOfCategories do:[:aCategory |
       
  1613             self printOutHTMLCategoryProtocol:aCategory of:aClass on:aStream
       
  1614         ].
       
  1615 "/        any ifFalse:[
       
  1616 "/            aStream nextPutAll:'no new protocol'
       
  1617 "/        ].
       
  1618         self generateHorizontalLine.
       
  1619     ]
       
  1620 
       
  1621     "
       
  1622       self printOutHTMLProtocolOf:Float on:Stdout 
       
  1623     "
       
  1624 
       
  1625     "Created: / 22.4.1996 / 20:03:30 / cg"
       
  1626     "Modified: / 25.11.1998 / 12:40:59 / cg"
       
  1627 !
       
  1628 
       
  1629 undentedToFirstLinesIndent:someText
       
  1630     |undentedText firstIndent firstNonEmpty|
       
  1631 
       
  1632     firstIndent := someText first withTabsExpanded leftIndent.
       
  1633     firstIndent > 0 ifTrue:[
       
  1634         undentedText := someText collect:[:line |
       
  1635                                 |l|
       
  1636 
       
  1637                                 l := line withTabsExpanded.
       
  1638                                 l leftIndent >= firstIndent ifTrue:[
       
  1639                                     l copyFrom:firstIndent + 1.
       
  1640                                 ] ifFalse:[
       
  1641                                     l
       
  1642                                 ]
       
  1643                              ].
       
  1644     ] ifFalse:[
       
  1645         undentedText := someText
       
  1646     ].
       
  1647 
       
  1648     firstNonEmpty := undentedText findFirst:[:line | line notEmpty].
       
  1649     firstNonEmpty > 1 ifTrue:[
       
  1650         undentedText := undentedText copyFrom:firstNonEmpty
       
  1651     ].
       
  1652     ^ undentedText
       
  1653 ! !
       
  1654 
       
  1655 !HTMLDocGenerator methodsFor:'document generation-lists'!
   472 
  1656 
   473 htmlClassCategoryList
  1657 htmlClassCategoryList
   474     "generate a formatted list of all available class categories as
  1658     "generate a formatted list of all available class categories as
   475      an HTML string. Each category will be a hyperlink to another
  1659      an HTML string. Each category will be a hyperlink to another
   476      autogenerated page, containing the classes per category.
  1660      autogenerated page, containing the classes per category.
   767     "
  1951     "
   768 
  1952 
   769     "Modified: / 10-11-2006 / 17:11:30 / cg"
  1953     "Modified: / 10-11-2006 / 17:11:30 / cg"
   770 !
  1954 !
   771 
  1955 
   772 htmlDocOf:aClass
       
   773     "generate an HTML document string which contains a classes documentation"
       
   774 
       
   775     ^ self htmlDocOf:aClass back:nil backRef:nil
       
   776 
       
   777     "
       
   778      self htmlDocOf:PostscriptPrinterStream
       
   779     "
       
   780 
       
   781     "Modified: / 30.10.1997 / 13:22:19 / cg"
       
   782 !
       
   783 
       
   784 htmlDocOf:aClass back:backCmd
       
   785     "generate an HTML document string which contains a classes documentation"
       
   786 
       
   787     ^ self htmlDocOf:aClass back:backCmd backRef:nil
       
   788 
       
   789     "Modified: / 30.10.1997 / 13:22:27 / cg"
       
   790 !
       
   791 
       
   792 htmlDocOf:aClass back:backCmd backRef:backRef
       
   793     "generate a nice HTML page from a class, with a back-reference
       
   794      to a command or document.
       
   795 
       
   796      Extract sections from the classes documentation method,
       
   797      where the following lines start a special subsection:
       
   798         [see also:]   - references to other classes and/or documents
       
   799         [start with:] - one-liners to start a demonstration
       
   800         [author:]     - author(s) of this class
       
   801         [warning:]    - usage warnings if any
       
   802         [hints:]      - usage hints if any
       
   803      Each section ends with an empty line - however, for formatting,
       
   804      a line consisting of a single backslash character will be converted
       
   805      to an empty line.
       
   806 
       
   807      Also extract examples from the classes example method,
       
   808      where executable examples are made from sections enclosed in:
       
   809         [exBegin]
       
   810         ...
       
   811         [exEnd]
       
   812      these parts are displayed in courier and will be made executable.
       
   813      everything else is plain documentation text.
       
   814     "
       
   815 
       
   816     ^ self
       
   817         htmlDocOf:aClass 
       
   818         back:backCmd 
       
   819         backRef:backRef 
       
   820         imagePath:(self pathToTopOfDocumentation , '/icons')
       
   821 !
       
   822 
       
   823 htmlDocOf:aClass back:backCmdArg backRef:backRefArg imagePath:imagePathArg
       
   824     "generate a nice HTML page from a class, with a back-reference
       
   825      to a command or document.
       
   826 
       
   827      Extract sections from the classes documentation method,
       
   828      where the following lines start a special subsection:
       
   829         [see also:]   - references to other classes and/or documents
       
   830         [start with:] - one-liners to start a demonstration
       
   831         [author:]     - author(s) of this class
       
   832         [warning:]    - usage warnings if any
       
   833         [hints:]      - usage hints if any
       
   834      Each section ends with an empty line - however, for formatting,
       
   835      a line consisting of a single backslash character will be converted
       
   836      to an empty line.
       
   837 
       
   838      Also extract examples from the classes example method,
       
   839      where executable examples are made from sections enclosed in:
       
   840         [exBegin]
       
   841         ...
       
   842         [exEnd]
       
   843      these parts are displayed in courier and will be made executable.
       
   844      everything else is plain documentation text.
       
   845     "
       
   846         
       
   847     |supers s indent m docu examples firstIndent firstNonEmpty
       
   848      collectionOfCategories collectionOfClassCategories subs refLines demoLines warnLines hintLines authorLines first wasLoaded didLoadBin
       
   849      privateClasses owner className metaClass shortName shortMetaName|
       
   850 
       
   851     backRef := backRefArg.
       
   852     backCmd := backCmdArg.
       
   853     imagePath := imagePathArg.
       
   854 
       
   855     aClass isNil ifTrue:[
       
   856         ^ ''  "/ just in case ...
       
   857     ].
       
   858 
       
   859     outStream := s := '' writeStream.
       
   860     className := aClass name.
       
   861     shortName := aClass nameWithoutPrefix.
       
   862     metaClass := aClass class.
       
   863     shortMetaName := metaClass nameWithoutPrefix.
       
   864 
       
   865     self generateHTMLHeadWithTitle:('Class: ' , className).
       
   866     self generateBODYStart.
       
   867     self generateBackButton.
       
   868 
       
   869     (aClass isRealNameSpace) ifTrue:[
       
   870         s nextPutLine:'<h1>'.
       
   871         s nextPutAll:'NameSpace: ';
       
   872           nextPutLine:(shortName).
       
   873         s nextPutLine:'</h1>'.
       
   874         self generateBODYandHTMLEnd.
       
   875         ^ s contents.
       
   876     ].
       
   877 
       
   878     (wasLoaded := aClass isLoaded) ifFalse:[
       
   879         "/ load it - but not a binary
       
   880         didLoadBin := Smalltalk loadBinaries.
       
   881         Smalltalk loadBinaries:false.
       
   882         [
       
   883             Autoload autoloadFailedSignal handle:[:ex |
       
   884                 ^ 'Autoload of ' , aClass name , ' failed - no documentation available.'
       
   885             ] do:[
       
   886                 aClass autoload.
       
   887             ].
       
   888         ] ensure:[
       
   889             didLoadBin ifTrue:[Smalltalk loadBinaries:true].
       
   890         ].
       
   891     ].
       
   892 
       
   893     owner := aClass owningClass.
       
   894     privateClasses := aClass privateClassesSorted.
       
   895 
       
   896     "/
       
   897     "/ extract documentation or comment, if there is any
       
   898     "/
       
   899     m := metaClass compiledMethodAt:#documentation.
       
   900     m notNil ifTrue:[
       
   901         docu := m comment.
       
   902     ] ifFalse:[
       
   903         "try comment"
       
   904         docu := aClass comment.
       
   905     ].
       
   906 
       
   907     (docu notNil and:[docu isEmpty]) ifTrue:[
       
   908         docu := nil
       
   909     ].
       
   910     docu notNil ifTrue:[
       
   911         docu := self withSpecialHTMLCharactersEscaped:docu.
       
   912         docu := docu asStringCollection.
       
   913 
       
   914         "/
       
   915         "/ search for a [see also:] section
       
   916         "/
       
   917         refLines := self extractSpecial:'[see also:]' from:docu.
       
   918 
       
   919         "/
       
   920         "/ search for a [start with:] section
       
   921         "/
       
   922         demoLines := self extractSpecial:'[start with:]' from:docu.
       
   923 
       
   924         "/
       
   925         "/ search for a [author:] section
       
   926         "/
       
   927         authorLines := self extractSpecial:'[author:]' from:docu.
       
   928         authorLines isNil ifTrue:[
       
   929             authorLines := self extractSpecial:'[authors:]' from:docu.
       
   930         ].
       
   931 
       
   932         "/
       
   933         "/ search for a [warning:] section
       
   934         "/
       
   935         warnLines := self extractSpecial:'[warning:]' from:docu.
       
   936 
       
   937         "/
       
   938         "/ search for a [hints:] section
       
   939         "/
       
   940         hintLines := self extractSpecial:'[hints:]' from:docu.
       
   941         hintLines isNil ifTrue:[
       
   942             hintLines := self extractSpecial:'[hint:]' from:docu.
       
   943         ].
       
   944 
       
   945         docu notEmpty ifTrue:[
       
   946             "/
       
   947             "/ strip off empty lines
       
   948             "/
       
   949             [docu notEmpty and:[(docu at:1) size == 0]] whileTrue:[
       
   950                 docu removeIndex:1
       
   951             ].
       
   952             [docu notEmpty and:[(docu at:docu size) size == 0]] whileTrue:[
       
   953                 docu removeIndex:(docu size)
       
   954             ].
       
   955         ].
       
   956 
       
   957         docu notEmpty ifTrue:[
       
   958             firstIndent := docu first leftIndent.
       
   959             firstIndent > 0 ifTrue:[
       
   960                 docu := docu collect:[:line |
       
   961                                         line leftIndent >= firstIndent ifTrue:[
       
   962                                             line copyFrom:firstIndent + 1.
       
   963                                         ] ifFalse:[
       
   964                                             line
       
   965                                         ]
       
   966                                      ].
       
   967             ].
       
   968             firstNonEmpty := docu findFirst:[:line | line notEmpty].
       
   969             firstNonEmpty > 1 ifTrue:[
       
   970                 docu := docu copyFrom:firstNonEmpty
       
   971             ]
       
   972         ].
       
   973         docu := docu asString.
       
   974     ].
       
   975 
       
   976     refLines notNil ifTrue:[
       
   977         refLines := refLines collect:[:l | 
       
   978                         |t|
       
   979 
       
   980                         ((t := l withoutSeparators) startsWith:'(') ifTrue:[
       
   981                             t
       
   982                         ] ifFalse:[
       
   983                             t := l asCollectionOfWords.
       
   984                             (t size == 1
       
   985                             and:[ (t first includes:$:) not ]) ifTrue:[
       
   986                                 t first
       
   987                             ] ifFalse:[
       
   988                                 t
       
   989                             ]
       
   990                         ]
       
   991                     ].
       
   992     ].
       
   993 
       
   994     "/
       
   995     "/ extract examples if there are any
       
   996     "/
       
   997     m := metaClass compiledMethodAt:#examples.
       
   998     m notNil ifTrue:[
       
   999         examples := m comment.
       
  1000         examples notNil ifTrue:[
       
  1001             examples isEmpty ifTrue:[
       
  1002                 examples := nil
       
  1003             ].
       
  1004         ].
       
  1005         examples notNil ifTrue:[
       
  1006             examples := self withSpecialHTMLCharactersEscaped:examples.
       
  1007             examples := examples asStringCollection.
       
  1008 
       
  1009             "/
       
  1010             "/ strip off empty lines
       
  1011             "/
       
  1012             [examples first size == 0] whileTrue:[
       
  1013                 examples removeIndex:1
       
  1014             ].
       
  1015             [examples last size == 0] whileTrue:[
       
  1016                 examples removeIndex:(examples size)
       
  1017             ].
       
  1018 
       
  1019             examples notEmpty ifTrue:[
       
  1020                 firstIndent := examples first withTabsExpanded leftIndent.
       
  1021                 firstIndent > 0 ifTrue:[
       
  1022                     examples := examples collect:[:line |
       
  1023                                             |l|
       
  1024 
       
  1025                                             l := line withTabsExpanded.
       
  1026                                             l leftIndent >= firstIndent ifTrue:[
       
  1027                                                 l copyFrom:firstIndent.
       
  1028                                             ] ifFalse:[
       
  1029                                                 l
       
  1030                                             ]
       
  1031                                          ].
       
  1032                 ].
       
  1033                 firstNonEmpty := examples findFirst:[:line | line notEmpty].
       
  1034                 firstNonEmpty > 1 ifTrue:[
       
  1035                     examples := examples copyFrom:firstNonEmpty
       
  1036                 ]
       
  1037             ].
       
  1038         ]
       
  1039     ].
       
  1040 
       
  1041     collectionOfClassCategories := metaClass categories asSortedCollection.
       
  1042     collectionOfClassCategories size > 0 ifTrue:[
       
  1043         collectionOfClassCategories := collectionOfClassCategories asOrderedCollection.
       
  1044         collectionOfClassCategories remove:'documentation' ifAbsent:nil.
       
  1045     ].
       
  1046     collectionOfCategories := aClass categories asSortedCollection.
       
  1047     collectionOfCategories size > 0 ifTrue:[
       
  1048         collectionOfCategories := collectionOfCategories asOrderedCollection.
       
  1049     ].
       
  1050 
       
  1051     (aClass == Autoload or:[aClass == Object]) ifTrue:[
       
  1052         subs := #()
       
  1053     ] ifFalse:[
       
  1054         subs := self shownSubclassesOf:aClass. 
       
  1055     ].
       
  1056 
       
  1057     s nextPutLine:'<h1>'.
       
  1058     s nextPutAll:'Class: '.
       
  1059 
       
  1060     self generatingForSTXBrowser ifTrue:[
       
  1061         s nextPutAll:'<a INFO="Open a Browser on ' , shortName , '" type="example" action="Smalltalk browseInClass:' , className , '">';
       
  1062           nextPutAll:shortName; nextPutLine:'</a>'.
       
  1063     ] ifFalse:[
       
  1064         s nextPutAll:shortName.
       
  1065     ].
       
  1066     owner notNil ifTrue:[
       
  1067         s nextPutAll:' (private in '.
       
  1068         self generatingForSTXBrowser ifTrue:[
       
  1069           s nextPutAll:'<a INFO="Open a Browser on ' , owner nameWithoutPrefix , '" type="example" action="Smalltalk browseInClass:' , owner name , '">';
       
  1070             nextPutAll:(owner nameWithoutPrefix); nextPutLine:'</a>)'.
       
  1071         ] ifFalse:[
       
  1072             s nextPutAll:owner nameWithoutPrefix.
       
  1073         ].
       
  1074     ] ifFalse:[
       
  1075         aClass nameSpace ~~ Smalltalk ifTrue:[
       
  1076             s nextPutAll:' (in ' , aClass nameSpace name , ')'
       
  1077         ]
       
  1078     ].
       
  1079     s nextPutLine:'</h1>'.
       
  1080 
       
  1081     owner notNil ifTrue:[
       
  1082         s nextPutLine:'This class is only visible from within'.
       
  1083         s nextPutAll:owner nameWithoutPrefix.
       
  1084         owner owningClass notNil ifTrue:[
       
  1085             s nextPutAll:' (which is itself a private class of '.
       
  1086             s nextPutAll:owner owningClass nameWithoutPrefix.
       
  1087             s nextPutAll:')'
       
  1088         ].
       
  1089         s nextPutLine:'.'
       
  1090     ].
       
  1091 
       
  1092     "/
       
  1093     "/ index
       
  1094     "/
       
  1095 "/    s nextPutAll:'Index:'; cr.
       
  1096     s nextPutLine:'<ul>'.
       
  1097     s nextPutLine:'<li><a href="#INHERITANCE" name="I_INHERITANCE">Inheritance</a>'.
       
  1098 
       
  1099     docu notNil ifTrue:[
       
  1100         s nextPutLine:'<li><a href="#DESCRIPTION" name="I_DESCRIPTION">Description</a>'.
       
  1101     ].
       
  1102     warnLines notNil ifTrue:[
       
  1103         warnLines := warnLines asStringCollection.
       
  1104         s nextPutLine:'<li><a href="#WARNING" name="I_WARNING">Warning</a>'.
       
  1105     ].
       
  1106     hintLines notNil ifTrue:[
       
  1107         hintLines := hintLines asStringCollection.
       
  1108         s nextPutLine:'<li><a href="#HINTS" name="I_HINTS">Hints</a>'.
       
  1109     ].
       
  1110 
       
  1111     refLines notNil ifTrue:[
       
  1112         s nextPutLine:'<li><a href="#SEEALSO" name="I_SEEALSO">Related information</a>'.
       
  1113     ].
       
  1114 
       
  1115 "/    s nextPutLine:'<li><a href="#INSTANCEVARIABLES" name="I_INSTANCEVARIABLES">Instance variables</a>'.
       
  1116 "/    s nextPutLine:'<li><a href="#CLASSVARIABLES" name="I_CLASSVARIABLES">Class variables</a>'.
       
  1117 
       
  1118     collectionOfClassCategories size > 0 ifTrue:[
       
  1119         s nextPutLine:'<li><a href="#CLASSPROTOCOL" name="I_CLASSPROTOCOL">Class protocol</a>'.
       
  1120         s nextPutLine:'<ul>'.
       
  1121         collectionOfClassCategories sort do:[:cat |
       
  1122             s nextPutLine:'<li><a name="I_' , shortMetaName , '_category_' , cat , '"' ,
       
  1123                                      ' href="#' , shortMetaName , '_category_' , cat ,
       
  1124                                      '">' , cat , '</a> '.
       
  1125         ].
       
  1126         s nextPutLine:'</ul>'.
       
  1127     ].
       
  1128     collectionOfCategories size > 0 ifTrue:[
       
  1129         s nextPutLine:'<li><a href="#INSTANCEPROTOCOL" name="I_INSTANCEPROTOCOL">Instance protocol</a>'.
       
  1130         s nextPutLine:'<ul>'.
       
  1131         collectionOfCategories sort do:[:cat |
       
  1132             s nextPutLine:'<li><a name="I_' , shortName , '_category_' , cat , '"' ,
       
  1133                                      ' href="#' , shortName , '_category_' , cat ,
       
  1134                                      '">' , cat , '</a> '.
       
  1135         ].
       
  1136         s nextPutLine:'</ul>'.
       
  1137     ].
       
  1138 
       
  1139     privateClasses size > 0 ifTrue:[
       
  1140         privateClasses := privateClasses asOrderedCollection sort:[:a :b | a nameWithoutPrefix < b nameWithoutPrefix].
       
  1141         s nextPutLine:'<li><a href="#PRIVATECLASSES" name="I_PRIVATECLASSES">Private classes</a>'.
       
  1142     ].
       
  1143 
       
  1144     (aClass == Object or:[aClass == Autoload]) ifTrue:[
       
  1145         s nextPutLine:'<li><a href="#SUBCLASSES" name="I_SUBCLASSES">Subclasses</a>'.
       
  1146     ].
       
  1147     demoLines notNil ifTrue:[
       
  1148         s nextPutLine:'<li><a href="#DEMOSTARTUP" name="I_DEMOSTARTUP">Demonstration</a>'.
       
  1149     ].
       
  1150     examples notNil ifTrue:[
       
  1151         s nextPutLine:'<li><a href="#EXAMPLES" name="I_EXAMPLES">Examples</a>'.
       
  1152     ].
       
  1153     s nextPutLine:'</ul>'.
       
  1154     self generateHorizontalLine.
       
  1155 
       
  1156     "/
       
  1157     "/ hierarchy
       
  1158     "/
       
  1159     s nextPutLine:'<h2><a name="INHERITANCE" href="#I_INHERITANCE">Inheritance:</A></h2>'.
       
  1160     s nextPutLine:'<pre>'.
       
  1161     indent := 3.
       
  1162     first := true.
       
  1163     supers := aClass allSuperclasses.
       
  1164     (supers size > 0) ifTrue:[
       
  1165         supers reverseDo:[:cls |
       
  1166             |className|
       
  1167 
       
  1168             className := cls name.    
       
  1169             first ifFalse:[
       
  1170                 s spaces:indent; nextPutLine:'|'.
       
  1171                 s spaces:indent; nextPutAll:'+--'.
       
  1172                 indent := indent + 3.
       
  1173             ] ifTrue:[
       
  1174                 s spaces:indent
       
  1175             ].
       
  1176             first := false.
       
  1177 
       
  1178             self generateClassDocReferenceFor:className.
       
  1179             s cr.
       
  1180         ].
       
  1181         s spaces:indent; nextPutLine:'|'.
       
  1182         s spaces:indent. 
       
  1183         s nextPutAll:'+--<B>'; nextPutAll:className; nextPutLine:'</B>'.
       
  1184         indent := indent + 3.
       
  1185     ] ifFalse:[
       
  1186         s spaces:indent; nextPutLine:'nil'.
       
  1187         s spaces:indent; nextPutLine:'|'.
       
  1188         s spaces:indent; nextPutAll:'+--<B>'; nextPutAll:className; nextPutLine:'</B>'.
       
  1189         aClass ~~ Object ifTrue:[
       
  1190             s cr.
       
  1191             s nextPutLine:'  <B>This class inherits NOTHING - most messages will lead into doesNotUnderstand:</B>'
       
  1192         ].
       
  1193         indent := indent + 3.
       
  1194     ].
       
  1195 
       
  1196     subs notEmpty ifTrue:[
       
  1197         subs do:[:aSubclass |
       
  1198             |className|
       
  1199 
       
  1200             className := aSubclass name.    
       
  1201             s spaces:indent; nextPutLine:'|'.
       
  1202             s spaces:indent; nextPutAll:'+--'.
       
  1203             self generateClassDocReferenceFor:className.
       
  1204             s cr.
       
  1205         ]
       
  1206     ] ifFalse:[
       
  1207         aClass == Object ifTrue:[
       
  1208             s spaces:indent; nextPutLine:'|'.
       
  1209             s spaces:indent; nextPutLine:'+-- ... almost every other class ...'
       
  1210         ]
       
  1211     ].
       
  1212 
       
  1213 
       
  1214     s nextPutLine:'</pre>'.
       
  1215     self generateHorizontalLine.
       
  1216 
       
  1217     "/
       
  1218     "/ category, version & package
       
  1219     "/
       
  1220     aClass category notNil ifTrue:[
       
  1221         s nextPutLine:'<dl>'.
       
  1222         s nextPutLine:'<dt><a name="CATEGORY"><b>Category:</b></A>'.
       
  1223         s nextPutLine:'<dd><b>', aClass category , '</b>'.
       
  1224         s nextPutLine:'</dl>'.
       
  1225     ].
       
  1226 
       
  1227     owner notNil ifTrue:[
       
  1228         s nextPutLine:'<dl>'.
       
  1229         s nextPutLine:'<dt><a name="OWNER"><b>Owner:</b></A>'.
       
  1230         s nextPutAll:'<dd><b>'. 
       
  1231         self generateClassDocReferenceFor:owner name.
       
  1232         s cr.
       
  1233 "/        s nextPutLine:(self 
       
  1234 "/                    anchorForHTMLDocAction:
       
  1235 "/                        ('htmlDocOf:', owner name )
       
  1236 "/                    info:
       
  1237 "/                        ( 'Show documentation of ' , owner nameWithoutPrefix )
       
  1238 "/                    text:
       
  1239 "/                        owner nameWithoutPrefix).
       
  1240         s nextPutLine:'</b>'.
       
  1241     ] ifFalse:[
       
  1242         self htmlRevisionDocOf:aClass to:s.
       
  1243     ].
       
  1244     s nextPutLine:'</dl>'.
       
  1245 
       
  1246     authorLines notNil ifTrue:[
       
  1247         s nextPutLine:'<dl><dt><a name="AUTHOR"><b>Author:</b></A>'.
       
  1248         authorLines do:[:l|
       
  1249             s nextPutLine:'<dd><b>', l , '</b>'.
       
  1250         ].
       
  1251         s nextPutLine:'</dl>'.
       
  1252     ].
       
  1253 
       
  1254     self generateHorizontalLine.
       
  1255 
       
  1256     docu notNil ifTrue:[
       
  1257         s nextPutLine:'<h2><a name="DESCRIPTION" href="#I_DESCRIPTION">Description:</A></h2>'.
       
  1258         s nextPutLine:'<BR>'.
       
  1259 
       
  1260         s nextPutLine:'<pre>'.
       
  1261         s nextPutLine:docu.
       
  1262         s nextPutLine:'</pre>'.
       
  1263         self generateHorizontalLine.
       
  1264     ].
       
  1265 
       
  1266     warnLines notNil ifTrue:[
       
  1267         s nextPutLine:'<h2><a name="WARNING" href="#I_WARNING">Warning:</A></h2>'.
       
  1268         s nextPutLine:'<BR>'.
       
  1269 
       
  1270         s nextPutLine:'<pre>'.
       
  1271         firstIndent := warnLines first leftIndent.
       
  1272 
       
  1273         warnLines do:[:aLine |
       
  1274             aLine leftIndent >= firstIndent ifTrue:[
       
  1275                 s nextPutLine:(aLine copyFrom:firstIndent+1)
       
  1276             ] ifFalse:[
       
  1277                 s nextPutLine:aLine
       
  1278             ].
       
  1279         ].
       
  1280         s nextPutLine:'</pre>'.
       
  1281         self generateHorizontalLine.
       
  1282     ].
       
  1283 
       
  1284     hintLines notNil ifTrue:[
       
  1285         s nextPutLine:'<h2><a name="HINTS" href="#I_HINTS">Hints:</A></h2>'.
       
  1286         s nextPutLine:'<BR>'.
       
  1287 
       
  1288         s nextPutLine:'<pre>'.
       
  1289         firstIndent := hintLines first leftIndent.
       
  1290 
       
  1291         hintLines do:[:aLine |
       
  1292             aLine leftIndent >= firstIndent ifTrue:[
       
  1293                 s nextPutLine:(aLine copyFrom:firstIndent+1)
       
  1294             ] ifFalse:[
       
  1295                 s nextPutLine:aLine
       
  1296             ].
       
  1297         ].
       
  1298         s nextPutLine:'</pre>'.
       
  1299         self generateHorizontalLine.
       
  1300     ].
       
  1301 
       
  1302     "/
       
  1303     "/ see also
       
  1304     "/
       
  1305     refLines notNil ifTrue:[
       
  1306         s nextPutLine:'<h2><a name="SEEALSO" href="#I_SEEALSO">Related information:</A></h2>'.
       
  1307         self generateRefLines:refLines forClass:aClass on:s.        
       
  1308         self generateHorizontalLine.
       
  1309     ].
       
  1310 
       
  1311 
       
  1312     "/
       
  1313     "/ inst & classVars
       
  1314     "/ to be added
       
  1315 
       
  1316 
       
  1317     "/
       
  1318     "/ protocol
       
  1319     "/
       
  1320     self printOutHTMLProtocolOf:aClass on:s.
       
  1321 
       
  1322     "/
       
  1323     "/ subclasses (only for Object and Autoload)
       
  1324     "/
       
  1325     (aClass == Object or:[aClass == Autoload]) ifTrue:[
       
  1326         s nextPutLine:'<h2><a name="SUBCLASSES" href="#I_SUBCLASSES">Subclasses (direct subclasses only):</A></h2>'.
       
  1327         self generateSubclassInfoFor:aClass on:s.
       
  1328         self generateHorizontalLine.
       
  1329     ].
       
  1330 
       
  1331     "/
       
  1332     "/ private classes
       
  1333     "/
       
  1334     privateClasses size > 0 ifTrue:[
       
  1335         s nextPutLine:'<h2><a name="PRIVATECLASSES" href="#I_PRIVATECLASSES">Private classes:</A></h2>'.
       
  1336         self generatePrivateClassInfoFor:aClass with:privateClasses on:s.
       
  1337         self generateHorizontalLine.
       
  1338     ].
       
  1339 
       
  1340     "/
       
  1341     "/ demonstration
       
  1342     "/
       
  1343     demoLines notNil ifTrue:[
       
  1344         s nextPutLine:'<h2><a name="DEMOSTARTUP" href="#I_DEMOSTARTUP">Demonstration:</A></h2>'.
       
  1345         demoLines do:[:l |
       
  1346             s nextPutLine:'<a INFO="demonstration" type="example">'.
       
  1347             s nextPutLine:'<pre><code>'.
       
  1348             s nextPutLine:'    ' , l withoutSeparators.
       
  1349             s nextPutLine:'</code></pre>'.
       
  1350             s nextPutLine:'</a>'.
       
  1351             s nextPutLine:'<br>'.
       
  1352         ].
       
  1353         self generateHorizontalLine.
       
  1354     ].
       
  1355 
       
  1356     "/
       
  1357     "/ add examples if there are any
       
  1358     "/
       
  1359     examples notNil ifTrue:[
       
  1360         self generateExamples:examples.
       
  1361     ].
       
  1362 
       
  1363     self generateBODYandHTMLEnd.
       
  1364 
       
  1365     wasLoaded ifFalse:[
       
  1366         aClass unload
       
  1367     ].
       
  1368 
       
  1369     ^ s contents
       
  1370 
       
  1371     "
       
  1372      self htmlDocOf:Object
       
  1373      self htmlDocOf:Array
       
  1374      self htmlDocOf:Filename
       
  1375      self htmlDocOf:Block
       
  1376     "
       
  1377 
       
  1378     "Created: / 24-04-1996 / 15:01:59 / cg"
       
  1379     "Modified: / 05-11-2007 / 17:22:54 / cg"
       
  1380 !
       
  1381 
       
  1382 htmlDocOf:aClass backRef:backRef
       
  1383     "generate an HTML document string which contains a classes documentation"
       
  1384 
       
  1385     ^ self htmlDocOf:aClass back:nil backRef:backRef
       
  1386 
       
  1387     "Created: / 24.4.1996 / 15:03:25 / cg"
       
  1388     "Modified: / 30.10.1997 / 13:23:12 / cg"
       
  1389 !
       
  1390 
       
  1391 htmlDocOfImplementorsOf:selector
       
  1392     "generate an HTML document string which contains HREFS
       
  1393      to all implementors of a particular selector"
       
  1394 
       
  1395     |sel s classes|
       
  1396 
       
  1397     sel := self withSpecialHTMLCharactersEscaped:selector.
       
  1398 
       
  1399     outStream := s := '' writeStream.
       
  1400 
       
  1401     self generateHTMLHeadWithTitle:('Implementations of: ' , sel).
       
  1402     self generateBODYStart.
       
  1403 
       
  1404     self generateUpArrowButtonForTop.
       
  1405     self generateHorizontalLine.
       
  1406     self generateH1:sel.
       
  1407 
       
  1408     s nextPutLine:'<dl>'.
       
  1409 
       
  1410     classes := IdentitySet new.
       
  1411 
       
  1412     sel := selector asSymbol.
       
  1413     Smalltalk allClassesAndMetaclassesDo:[:cls |
       
  1414         cls isPrivate ifFalse:[
       
  1415             (cls includesSelector:sel) ifTrue:[
       
  1416                 classes add:cls
       
  1417             ]
       
  1418         ]
       
  1419     ].
       
  1420 
       
  1421     (classes asOrderedCollection sort:[:a :b | a name < b name]) 
       
  1422         do:[:cls |
       
  1423             self 
       
  1424                 printOutHTMLMethodProtocol:(cls compiledMethodAt:sel) 
       
  1425                 on:s 
       
  1426                 showClassName:true 
       
  1427                 classRef:true.
       
  1428             s nextPutLine:'<p>'.
       
  1429         ].
       
  1430 
       
  1431     s nextPutLine:'</dl>'.
       
  1432     self generateBODYandHTMLEnd.
       
  1433 
       
  1434     ^ s contents
       
  1435 
       
  1436     "Created: / 22.4.1996 / 20:03:31 / cg"
       
  1437     "Modified: / 30.10.1998 / 22:15:30 / cg"
       
  1438 !
       
  1439 
       
  1440 htmlDocOfImplementorsOfAnyMatching:selectorPattern
       
  1441     "generate an HTML document string which contains HREFS
       
  1442      to all implementors of a particular selector"
       
  1443 
       
  1444     |s sel classes|
       
  1445 
       
  1446     outStream := s := '' writeStream.
       
  1447 
       
  1448     sel := self withSpecialHTMLCharactersEscaped:selectorPattern.
       
  1449     self generateHTMLHeadWithTitle:('Implementations of: ' , sel).
       
  1450     self generateBODYStart.
       
  1451 
       
  1452     self generateUpArrowButtonForTop.
       
  1453     self generateHorizontalLine.
       
  1454 
       
  1455     self generateH1:sel.
       
  1456 
       
  1457     s nextPutLine:'<dl>'.
       
  1458 
       
  1459     classes := IdentitySet new.
       
  1460 
       
  1461     Smalltalk allClassesAndMetaclassesDo:[:cls |
       
  1462         cls isPrivate ifFalse:[
       
  1463             (cls methodDictionary keys contains:[:sel | selectorPattern match:sel]) ifTrue:[
       
  1464                 classes add:cls
       
  1465             ]
       
  1466         ]
       
  1467     ].
       
  1468 
       
  1469     (classes asOrderedCollection sort:[:a :b | a name < b name]) 
       
  1470         do:[:cls |
       
  1471             cls methodDictionary keys do:[:eachSel |
       
  1472                 (selectorPattern match:eachSel) ifTrue:[
       
  1473                     self 
       
  1474                         printOutHTMLMethodProtocol:(cls compiledMethodAt:eachSel) 
       
  1475                         on:s 
       
  1476                         showClassName:true 
       
  1477                         classRef:true.
       
  1478                     s nextPutLine:'<p>'.
       
  1479                 ].
       
  1480             ].
       
  1481         ].
       
  1482 
       
  1483     s nextPutLine:'</dl>'.
       
  1484     self generateBODYandHTMLEnd.
       
  1485 
       
  1486     ^ s contents
       
  1487 !
       
  1488 
       
  1489 htmlSelectorList
  1956 htmlSelectorList
  1490     "generate an HTML string for all selectors (for which methods exist)
  1957     "generate an HTML string for all selectors (for which methods exist)
  1491      in the system"
  1958      in the system"
  1492 
  1959 
  1493     |selectors|
  1960     |selectors|
  1603 
  2070 
  1604     ^ s contents
  2071     ^ s contents
  1605 
  2072 
  1606     "Created: / 22.4.1996 / 20:03:31 / cg"
  2073     "Created: / 22.4.1996 / 20:03:31 / cg"
  1607     "Modified: / 30.10.1997 / 13:26:34 / cg"
  2074     "Modified: / 30.10.1997 / 13:26:34 / cg"
  1608 ! !
       
  1609 
       
  1610 !HTMLDocGenerator methodsFor:'document generation-helpers'!
       
  1611 
       
  1612 htmlForMethod:aMethod
       
  1613     |who sel partStream args argStream methodSpecLine|
       
  1614 
       
  1615     who := aMethod who.
       
  1616     sel := who methodSelector.
       
  1617 
       
  1618     partStream := sel keywords readStream.
       
  1619 
       
  1620     (args := aMethod methodArgNames) notNil ifTrue:[
       
  1621         argStream := args readStream.
       
  1622 
       
  1623         methodSpecLine := ''. 
       
  1624         1 to:sel numArgs do:[:index |
       
  1625             methodSpecLine size > 0 ifTrue:[
       
  1626                 methodSpecLine := methodSpecLine , ' '
       
  1627             ].
       
  1628             methodSpecLine := methodSpecLine , '<B>' , partStream next , '</B>'.
       
  1629             methodSpecLine := methodSpecLine , ' <I>' , argStream next , '</I>'.
       
  1630         ].
       
  1631     ] ifFalse:[
       
  1632         methodSpecLine := '<B>' , partStream next , '</B>'
       
  1633     ].
       
  1634     ^ methodSpecLine
       
  1635 
       
  1636     "Created: / 05-11-2007 / 16:13:39 / cg"
       
  1637 !
       
  1638 
       
  1639 htmlRevisionDocOf:aClass to:s
       
  1640     "extract a classes versionInfo and return an HTML document string
       
  1641      for that."
       
  1642 
       
  1643     |revInfo pckgInfo text path|
       
  1644 
       
  1645     revInfo := aClass revisionInfo.
       
  1646     pckgInfo := aClass packageSourceCodeInfo.
       
  1647 
       
  1648     s nextPutLine:'<dl><dt><a name="VERSION"><b>Version:</b></A>'.
       
  1649 
       
  1650     (revInfo isNil and:[pckgInfo isNil]) ifTrue:[
       
  1651         s nextPutLine:'<dd>no revision info'.
       
  1652     ] ifFalse:[
       
  1653 
       
  1654         revInfo isNil ifTrue:[revInfo := IdentityDictionary new].
       
  1655         pckgInfo isNil ifTrue:[pckgInfo := IdentityDictionary new].
       
  1656 
       
  1657         s nextPutLine:'<dd>rev: <b>'.
       
  1658 
       
  1659         "/ fetch the revision-info; prefer revisionInfo
       
  1660         text := revInfo at:#revision ifAbsent:(pckgInfo at:#revision ifAbsent:'?').
       
  1661         s nextPutLine:text.
       
  1662 
       
  1663         "/ fetch the date & time; prefer revisionInfo
       
  1664         text := revInfo at:#date ifAbsent:(pckgInfo at:#date ifAbsent:'?').
       
  1665         s nextPutAll:'</b> date: <b>' ,  text.
       
  1666         text := revInfo at:#time ifAbsent:(pckgInfo at:#time ifAbsent:'?').
       
  1667         s nextPutLine:' ', text , '</b>'.
       
  1668 
       
  1669         text := revInfo at:#user ifAbsent:(pckgInfo at:#user ifAbsent:'?').
       
  1670         s nextPutLine:'<dd>user: <b>' , text , '</b>'.
       
  1671 
       
  1672         text := revInfo at:#fileName ifAbsent:(pckgInfo at:#fileNamer ifAbsent:'?').
       
  1673         s nextPutAll:'<dd>file: <b>' , text.
       
  1674 
       
  1675         text := revInfo at:#directory ifAbsent:(pckgInfo at:#directory ifAbsent:nil).
       
  1676         text isNil ifTrue:[
       
  1677             path := revInfo at:#repositoryPathName ifAbsent:(pckgInfo at:#repositoryPathName ifAbsent:nil).
       
  1678             path notNil ifTrue:[
       
  1679                 SourceCodeManager notNil ifTrue:[
       
  1680                     text := SourceCodeManager directoryFromContainerPath:path forClass:aClass.
       
  1681                 ].
       
  1682                 text isNil ifTrue:[text := '?'].
       
  1683             ] ifFalse:[
       
  1684                 text := '?'
       
  1685             ]
       
  1686         ].
       
  1687         s nextPutLine:'</b> directory: <b>' , text , '</b>'.
       
  1688 
       
  1689         text := revInfo at:#module ifAbsent:(pckgInfo at:#module ifAbsent:nil).
       
  1690         text isNil ifTrue:[
       
  1691             path := revInfo at:#repositoryPathName ifAbsent:(pckgInfo at:#repositoryPathName ifAbsent:nil).
       
  1692             path notNil ifTrue:[
       
  1693                 SourceCodeManager notNil ifTrue:[
       
  1694                     text := SourceCodeManager moduleFromContainerPath:path forClass:aClass.
       
  1695                 ].
       
  1696                 text isNil ifTrue:[text := '?'].
       
  1697             ] ifFalse:[
       
  1698                 text := '?'
       
  1699             ]
       
  1700         ].
       
  1701         s nextPutAll:'<dd>module: <b>' , text.
       
  1702 
       
  1703         text := revInfo at:#library ifAbsent:(pckgInfo at:#library ifAbsent:'*none*').
       
  1704         s nextPutLine:'</b> stc-classLibrary: <b>' ,  text , '</b>'.
       
  1705     ].
       
  1706 
       
  1707     "Created: / 8.1.1997 / 13:43:28 / cg"
       
  1708     "Modified: / 30.10.1997 / 13:24:39 / cg"
       
  1709 !
       
  1710 
       
  1711 printOutHTMLCategoryProtocol:aCategory of:aClass on:aStream
       
  1712     "append documentation on each method in a particular methodCategory
       
  1713      of the given class in HTML onto aStream."
       
  1714 
       
  1715     |any dict selectors methods shortName|
       
  1716 
       
  1717     shortName := aClass nameWithoutPrefix.
       
  1718 
       
  1719     dict := aClass methodDictionary.
       
  1720 
       
  1721     dict notNil ifTrue:[
       
  1722         any := false.
       
  1723         dict do:[:aMethod |
       
  1724             (aCategory = aMethod category) ifTrue:[
       
  1725                 any := true
       
  1726             ]
       
  1727         ].
       
  1728 
       
  1729         any ifTrue:[
       
  1730             aStream nextPutLine:'<a name="' , shortName , '_category_' , aCategory ,
       
  1731                                      '" href="#I_' , shortName , '_category_' , aCategory ,
       
  1732                                      '"><b>' , aCategory , '</b></A>'.
       
  1733             aStream nextPutLine:'<dl>'.
       
  1734 
       
  1735             selectors := dict keys asArray.
       
  1736             methods := dict values.
       
  1737             selectors sortWith:methods.
       
  1738             methods do:[:aMethod |
       
  1739                 (aCategory = aMethod category) ifTrue:[
       
  1740                     Error catch:[
       
  1741                         self printOutHTMLMethodProtocol:aMethod on:aStream.
       
  1742                     ].
       
  1743                     aStream nextPutLine:'<p>'.
       
  1744                 ]
       
  1745             ].
       
  1746             aStream nextPutLine:'</dl>'.
       
  1747         ]
       
  1748     ]
       
  1749 
       
  1750     "
       
  1751       self printOutHTMLProtocolOf:Float on:Stdout 
       
  1752     "
       
  1753 
       
  1754     "Created: / 22.4.1996 / 20:03:30 / cg"
       
  1755     "Modified: / 5.6.1996 / 13:41:27 / stefan"
       
  1756     "Modified: / 30.10.1997 / 13:27:58 / cg"
       
  1757 !
       
  1758 
       
  1759 printOutHTMLMethodProtocol:aMethod on:aStream
       
  1760     "given the source in aString, print the methods message specification
       
  1761      and any method comments - without source; used to generate documentation
       
  1762      pages"
       
  1763 
       
  1764     ^ self 
       
  1765         printOutHTMLMethodProtocol:aMethod 
       
  1766         on:aStream 
       
  1767         showClassName:false 
       
  1768         classRef:false
       
  1769 
       
  1770     "Modified: 22.4.1996 / 18:01:56 / cg"
       
  1771     "Created: 22.4.1996 / 20:03:30 / cg"
       
  1772 !
       
  1773 
       
  1774 printOutHTMLMethodProtocol:aMethod on:aStream showClassName:showClassName classRef:withClassRef
       
  1775     "given the source in aString, print the methods message specification
       
  1776      and any method comments - without source; used to generate documentation
       
  1777      pages"
       
  1778 
       
  1779     |p|
       
  1780 
       
  1781 "/    p := imagePath.
       
  1782 "/    p isNil ifTrue:[
       
  1783 "/        p := self pathToTopOfDocumentation , '/icons' 
       
  1784 "/    ].
       
  1785     p := self pathToTopOfDocumentation , '/pictures'.
       
  1786     ^ self
       
  1787         printOutHTMLMethodProtocol:aMethod 
       
  1788         on:aStream 
       
  1789         showClassName:showClassName 
       
  1790         classRef:withClassRef 
       
  1791         picturePath:p
       
  1792 !
       
  1793 
       
  1794 printOutHTMLMethodProtocol:aMethod on:aStream showClassName:showClassName classRef:withClassRef picturePath:picturePath
       
  1795     "given the source in aString, print the methods message specification
       
  1796      and any method comments - without source; used to generate documentation
       
  1797      pages"
       
  1798 
       
  1799     |comment cls sel who methodSpecLine 
       
  1800      firstIndent firstNonEmpty isSubres isObsolete smallOrEmpty
       
  1801      ballColor anchorName parseTree expr obsoleteInfo|
       
  1802 
       
  1803     who := aMethod who.
       
  1804     cls := who methodClass.
       
  1805     sel := who methodSelector.
       
  1806 
       
  1807     methodSpecLine := self htmlForMethod:aMethod.
       
  1808 
       
  1809     "/ use string-asSymbol (instead of the obvious symbol itself)
       
  1810     "/ in the checks below, to avoid tricking myself,
       
  1811     "/ when the documentation on this method is generated
       
  1812     "/ (otherwise, I'll say that this method is both
       
  1813     "/  a subres and and obsolete method ...)
       
  1814 
       
  1815     isSubres := (aMethod sends:#'subclassResponsibility').
       
  1816 
       
  1817     isObsolete := aMethod isObsolete.
       
  1818     "/ the above checks for the obsolete-resource flag;
       
  1819     "/ there is still achance for obsoleteMethodWarning to be sent, without the resource flag being present.
       
  1820     isObsolete ifFalse:[
       
  1821         ((aMethod sends:'obsoleteMethodWarning' asSymbol)
       
  1822         or:[(aMethod sends:'obsoleteMethodWarning:' asSymbol)
       
  1823         or:[(aMethod sends:'obsoleteMethodWarning:from:' asSymbol)]]) ifTrue:[
       
  1824             (sel startsWith:'obsoleteMethodWarning') ifFalse:[
       
  1825                 true "cls ~~ Object" ifTrue:[
       
  1826                     isObsolete := true.
       
  1827                     ParseTreeSearcher notNil ifTrue:[
       
  1828                         parseTree := cls parseTreeFor:sel.
       
  1829                         parseTree notNil ifTrue: [
       
  1830                             expr := ParseTreeSearcher treeMatching:'`@e1 obsoleteMethodWarning:`@e2' in: parseTree.
       
  1831                             expr isNil ifTrue:[
       
  1832                                 expr := ParseTreeSearcher treeMatching:'`@e1 obsoleteMethodWarning:`@e2 from:`@e3' in: parseTree.
       
  1833                             ].
       
  1834                             expr notNil ifTrue:[
       
  1835                                 |arg1|
       
  1836 
       
  1837                                 arg1 := expr arguments first.
       
  1838                                 arg1 isLiteral ifTrue:[
       
  1839                                     arg1 value isString ifTrue:[
       
  1840                                         obsoleteInfo := arg1 value.
       
  1841                                     ].
       
  1842                                 ].
       
  1843                             ].
       
  1844                         ].
       
  1845                     ].
       
  1846                 ].
       
  1847             ]
       
  1848         ].
       
  1849     ].
       
  1850 
       
  1851     smallOrEmpty := ''.
       
  1852     aMethod isPrivate ifTrue:[
       
  1853         methodSpecLine :=  '<i>private</i> ' , methodSpecLine.
       
  1854 "/        smallOrEmpty := '-small'.
       
  1855     ] ifFalse:[
       
  1856         aMethod isProtected ifTrue:[
       
  1857             methodSpecLine := '<i>protected</i> ' , methodSpecLine.
       
  1858 "/            smallOrEmpty := '-small'.
       
  1859         ] ifFalse:[
       
  1860             aMethod isIgnored ifTrue:[
       
  1861                 methodSpecLine := '[ ' , methodSpecLine , ' ] (<i>invisible</i>)'.
       
  1862 "/                smallOrEmpty := '-small'.
       
  1863             ]
       
  1864         ]
       
  1865     ].
       
  1866 
       
  1867     aStream nextPutLine:'<DT>'.
       
  1868 
       
  1869 
       
  1870     cls isMeta ifTrue:[
       
  1871         ballColor := 'yellow'
       
  1872     ] ifFalse:[
       
  1873         ballColor := 'red'
       
  1874     ].
       
  1875 
       
  1876     aStream nextPutLine:'<IMG src="' , picturePath , '/' , ballColor , '-ball' , smallOrEmpty , '.gif" alt="o " width=6 height=6>'.
       
  1877     aStream nextPutAll:'&nbsp;'.
       
  1878 
       
  1879     sel := self withSpecialHTMLCharactersEscaped:sel.
       
  1880     anchorName := cls name , '_' , sel.
       
  1881 
       
  1882     withClassRef ifTrue:[
       
  1883         aStream nextPutAll:(self 
       
  1884                             anchorForHTMLDocAction:
       
  1885                                 ('htmlDocOf:', cls theNonMetaclass name )
       
  1886                             info:
       
  1887                                 ('Show documentation of ' , cls theNonMetaclass name )
       
  1888                             text:
       
  1889                                 cls name
       
  1890                             name:anchorName).
       
  1891         aStream nextPutLine:'&nbsp;' , methodSpecLine.
       
  1892     ] ifFalse:[
       
  1893         showClassName ifTrue:[
       
  1894             methodSpecLine := cls name , ' ' , methodSpecLine
       
  1895         ].
       
  1896 
       
  1897         aStream nextPutLine:'<a name="' , anchorName , '" ' ,
       
  1898 "/                                 'href="' , cls name , '_' , sel , '"' ,
       
  1899                                  '>' , methodSpecLine , '</a>'.
       
  1900     ].
       
  1901     aStream nextPutLine:'<DD>'.
       
  1902 
       
  1903     (comment := self methodCommentOf:aMethod) notNil ifTrue:[
       
  1904         comment := self withSpecialHTMLCharactersEscaped:comment.
       
  1905 
       
  1906         comment notEmpty ifTrue:[
       
  1907             comment := comment asStringCollection.
       
  1908             firstIndent := comment first leftIndent.
       
  1909             firstIndent > 0 ifTrue:[
       
  1910                 comment := comment collect:[:line |
       
  1911                                         line leftIndent >= firstIndent ifTrue:[
       
  1912                                             line copyFrom:firstIndent.
       
  1913                                         ] ifFalse:[
       
  1914                                             line
       
  1915                                         ]
       
  1916                                      ].
       
  1917             ].
       
  1918             firstNonEmpty := comment findFirst:[:line | line notEmpty].
       
  1919             firstNonEmpty > 1 ifTrue:[
       
  1920                 comment := comment copyFrom:firstNonEmpty
       
  1921             ].
       
  1922             comment := comment asString.
       
  1923         ].
       
  1924 
       
  1925         comment asStringCollection do:[:line |
       
  1926             aStream 
       
  1927                 "/ nextPutAll:'<I>'; 
       
  1928                 nextPutAll:line; 
       
  1929                 "/ nextPutAll:'</I>'; 
       
  1930                 nextPutLine:'<BR>'.
       
  1931         ].
       
  1932     ].
       
  1933 
       
  1934     isSubres ifTrue:[
       
  1935         aStream nextPutLine:'<BR>'.
       
  1936         aStream nextPutLine:'<I>** This method raises an error - it must be redefined in concrete classes **</I>'.
       
  1937     ].
       
  1938     isObsolete ifTrue:[
       
  1939         aStream nextPutLine:'<BR>'.
       
  1940         aStream nextPutLine:'<I>** This is an obsolete interface - do not use it (it may vanish in future versions) **</I>'.
       
  1941         obsoleteInfo notNil ifTrue:[
       
  1942             aStream nextPutLine:'<BR>'.
       
  1943             aStream nextPutLine:'<I>** ' , obsoleteInfo , ' **</I>'.
       
  1944         ].
       
  1945     ].
       
  1946 
       
  1947     "Created: / 22-04-1996 / 20:03:30 / cg"
       
  1948     "Modified: / 05-11-2007 / 16:13:46 / cg"
       
  1949 !
       
  1950 
       
  1951 printOutHTMLProtocolOf:aClass on:aStream 
       
  1952     "append documentation  of the given class in HTML onto aStream."
       
  1953 
       
  1954     |collectionOfCategories any|
       
  1955 
       
  1956 "/    self printOutDefinitionOn:aPrintStream.
       
  1957 
       
  1958     collectionOfCategories := aClass class categories asSortedCollection.
       
  1959     any := false.
       
  1960 
       
  1961     collectionOfCategories size > 0 ifTrue:[
       
  1962         collectionOfCategories := collectionOfCategories asOrderedCollection.
       
  1963         collectionOfCategories remove:'documentation' ifAbsent:[].
       
  1964         collectionOfCategories size > 0 ifTrue:[
       
  1965             collectionOfCategories sort.
       
  1966             aStream nextPutLine:'<h2><a name="CLASSPROTOCOL" href="#I_CLASSPROTOCOL">Class protocol:</a></h2>'.
       
  1967             collectionOfCategories do:[:aCategory |
       
  1968                 self printOutHTMLCategoryProtocol:aCategory of:aClass class on:aStream.
       
  1969                 any := true.
       
  1970             ].
       
  1971 "/        any ifFalse:[
       
  1972 "/            aStream nextPutAll:'no new protocol'
       
  1973 "/        ].
       
  1974             self generateHorizontalLine.
       
  1975         ]
       
  1976     ].
       
  1977 
       
  1978 
       
  1979     collectionOfCategories := aClass categories asSortedCollection.
       
  1980     any := false.
       
  1981     collectionOfCategories size > 0 ifTrue:[
       
  1982         collectionOfCategories := collectionOfCategories asOrderedCollection sort.
       
  1983         aStream nextPutLine:'<h2><a name="INSTANCEPROTOCOL" href="#I_INSTANCEPROTOCOL">Instance protocol:</A></h2>'.
       
  1984         collectionOfCategories do:[:aCategory |
       
  1985             self printOutHTMLCategoryProtocol:aCategory of:aClass on:aStream
       
  1986         ].
       
  1987 "/        any ifFalse:[
       
  1988 "/            aStream nextPutAll:'no new protocol'
       
  1989 "/        ].
       
  1990         self generateHorizontalLine.
       
  1991     ]
       
  1992 
       
  1993     "
       
  1994       self printOutHTMLProtocolOf:Float on:Stdout 
       
  1995     "
       
  1996 
       
  1997     "Created: / 22.4.1996 / 20:03:30 / cg"
       
  1998     "Modified: / 25.11.1998 / 12:40:59 / cg"
       
  1999 ! !
  2075 ! !
  2000 
  2076 
  2001 !HTMLDocGenerator methodsFor:'format conversion-man pages'!
  2077 !HTMLDocGenerator methodsFor:'format conversion-man pages'!
  2002 
  2078 
  2003 manPageFor:aCommand
  2079 manPageFor:aCommand
  2238     "
  2314     "
  2239      self new anchorForHTMLDocAction:'foo' text:'text'
  2315      self new anchorForHTMLDocAction:'foo' text:'text'
  2240     "
  2316     "
  2241 !
  2317 !
  2242 
  2318 
  2243 extractSpecial:pattern from:docu
       
  2244     "given a collection of docu lines (from documentation methods comment),
       
  2245      extract things like [see also:], [author:] etc.
       
  2246      If found, remove the lines from the string collection,
       
  2247      and return the extracted ones. Otherwise return nil."
       
  2248 
       
  2249     |srchIdx idx lines l|
       
  2250 
       
  2251     srchIdx := docu findFirst:[:l | l asLowercase withoutSeparators = pattern].
       
  2252     srchIdx ~~ 0 ifTrue:[
       
  2253         lines := OrderedCollection new.
       
  2254 
       
  2255         idx := srchIdx+1.
       
  2256         [idx <= docu size] whileTrue:[
       
  2257             l := docu at:idx.
       
  2258             (l isNil or:[l withoutSeparators size == 0]) ifTrue:[
       
  2259                 idx := docu size + 1.
       
  2260             ] ifFalse:[
       
  2261                 l withoutSeparators = '\' ifTrue:[
       
  2262                     l := ''
       
  2263                 ].
       
  2264                 lines add:l
       
  2265             ].
       
  2266             idx := idx + 1.
       
  2267         ].
       
  2268 
       
  2269         docu removeFromIndex:srchIdx toIndex:srchIdx+lines size
       
  2270     ].
       
  2271     ^ lines
       
  2272 
       
  2273     "Created: 25.4.1996 / 14:16:01 / cg"
       
  2274     "Modified: 11.1.1997 / 13:03:38 / cg"
       
  2275 !
       
  2276 
       
  2277 generateBODYEnd
  2319 generateBODYEnd
  2278     generateBodyOnly == true ifFalse:[
  2320     generateBodyOnly == true ifFalse:[
  2279         outStream nextPutLine:'</body>'.
  2321         outStream nextPutLine:'</body>'.
  2280     ]
  2322     ]
  2281 !
  2323 !
  2550 ! !
  2592 ! !
  2551 
  2593 
  2552 !HTMLDocGenerator class methodsFor:'documentation'!
  2594 !HTMLDocGenerator class methodsFor:'documentation'!
  2553 
  2595 
  2554 version
  2596 version
  2555     ^ '$Header: /cvs/stx/stx/libbasic3/HTMLDocGenerator.st,v 1.84 2008-07-11 09:44:46 sr Exp $'
  2597     ^ '$Header: /cvs/stx/stx/libbasic3/HTMLDocGenerator.st,v 1.85 2008-10-19 11:21:33 cg Exp $'
  2556 ! !
  2598 ! !