fpc/utils/fpdoc/dw_html.pp
2005-05-27 17:43:19 +00:00

2897 lines
82 KiB
ObjectPascal

{
FPDoc - Free Pascal Documentation Tool
Copyright (C) 2000 - 2003 by
Areca Systems GmbH / Sebastian Guenther, sg@freepascal.org
* HTML/XHTML output generator
See the file COPYING, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}
{$mode objfpc}
{$H+}
unit dw_HTML;
interface
uses Classes, DOM, DOM_HTML, dGlobals, PasTree, dWriter;
const
// Subpage indices for modules
ResstrSubindex = 1;
ConstsSubindex = 2;
TypesSubindex = 3;
ClassesSubindex = 4;
ProcsSubindex = 5;
VarsSubindex = 6;
// Maybe needed later for topic overview ??
TopicsSubIndex = 7;
// Subpage indices for classes
PropertiesByInheritanceSubindex = 1;
PropertiesByNameSubindex = 2;
MethodsByInheritanceSubindex = 3;
MethodsByNameSubindex = 4;
EventsByInheritanceSubindex = 5;
EventsByNameSubindex = 6;
type
TFileAllocator = class
public
procedure AllocFilename(AElement: TPasElement; ASubindex: Integer); virtual;
function GetFilename(AElement: TPasElement;
ASubindex: Integer): String; virtual; abstract;
function GetRelativePathToTop(AElement: TPasElement): String; virtual;
function GetCSSFilename(ARelativeTo: TPasElement): DOMString; virtual;
end;
TShortNameFileAllocator = class(TFileAllocator)
private
FExtension: String;
public
constructor Create(const AExtension: String);
procedure AllocFilename(AElement: TPasElement; ASubindex: Integer); override;
property Extension: String read FExtension;
end;
TLongNameFileAllocator = class(TFileAllocator)
private
FExtension: String;
public
constructor Create(const AExtension: String);
function GetFilename(AElement: TPasElement;
ASubindex: Integer): String; override;
function GetRelativePathToTop(AElement: TPasElement): String; override;
property Extension: String read FExtension;
end;
TPageInfo = class
Element: TPasElement;
SubpageIndex: Integer;
end;
{ THTMLWriter }
THTMLWriter = class(TFPDocWriter)
private
FOnTest: TNotifyEvent;
FPackage: TPasPackage;
function GetPageCount: Integer;
procedure SetOnTest(const AValue: TNotifyEvent);
protected
FAllocator: TFileAllocator;
Procedure CreateAllocator; virtual;
CurDirectory: String; // relative to curdir of process
BaseDirectory: String; // relative path to package base directory
PageInfos: TObjectList; // list of TPageInfo objects
Doc: THTMLDocument;
BodyElement, TitleElement: TDOMElement;
Module: TPasModule;
OutputNodeStack: TList;
CurOutputNode: TDOMNode;
InsideHeadRow, DoPasHighlighting: Boolean;
HighlighterFlags: Byte;
FooterFile: string;
function ResolveLinkID(const Name: String): DOMString;
function ResolveLinkWithinPackage(AElement: TPasElement;
ASubpageIndex: Integer): String;
// Helper functions for creating DOM elements
function CreateEl(Parent: TDOMNode; const AName: DOMString): THTMLElement;
function CreatePara(Parent: TDOMNode): THTMLElement;
function CreateH1(Parent: TDOMNode): THTMLElement;
function CreateH2(Parent: TDOMNode): THTMLElement;
function CreateH3(Parent: TDOMNode): THTMLElement;
function CreateTable(Parent: TDOMNode): THTMLElement;
function CreateContentTable(Parent: TDOMNode): THTMLElement;
function CreateTR(Parent: TDOMNode): THTMLElement;
function CreateTD(Parent: TDOMNode): THTMLElement;
function CreateTD_vtop(Parent: TDOMNode): THTMLElement;
function CreateLink(Parent: TDOMNode; const AHRef: DOMString): THTMLElement;
function CreateAnchor(Parent: TDOMNode; const AName: DOMString): THTMLElement;
function CreateCode(Parent: TDOMNode): THTMLElement;
function CreateWarning(Parent: TDOMNode): THTMLElement;
// Description node conversion
procedure PushOutputNode(ANode: TDOMNode);
procedure PopOutputNode;
procedure DescrWriteText(const AText: DOMString); override;
procedure DescrBeginBold; override;
procedure DescrEndBold; override;
procedure DescrBeginItalic; override;
procedure DescrEndItalic; override;
procedure DescrBeginEmph; override;
procedure DescrEndEmph; override;
procedure DescrWriteFileEl(const AText: DOMString); override;
procedure DescrWriteKeywordEl(const AText: DOMString); override;
procedure DescrWriteVarEl(const AText: DOMString); override;
procedure DescrBeginLink(const AId: DOMString); override;
procedure DescrEndLink; override;
procedure DescrWriteLinebreak; override;
procedure DescrBeginParagraph; override;
procedure DescrEndParagraph; override;
procedure DescrBeginCode(HasBorder: Boolean; const AHighlighterName: String); override;
procedure DescrWriteCodeLine(const ALine: String); override;
procedure DescrEndCode; override;
procedure DescrBeginOrderedList; override;
procedure DescrEndOrderedList; override;
procedure DescrBeginUnorderedList; override;
procedure DescrEndUnorderedList; override;
procedure DescrBeginDefinitionList; override;
procedure DescrEndDefinitionList; override;
procedure DescrBeginListItem; override;
procedure DescrEndListItem; override;
procedure DescrBeginDefinitionTerm; override;
procedure DescrEndDefinitionTerm; override;
procedure DescrBeginDefinitionEntry; override;
procedure DescrEndDefinitionEntry; override;
procedure DescrBeginSectionTitle; override;
procedure DescrBeginSectionBody; override;
procedure DescrEndSection; override;
procedure DescrBeginRemark; override;
procedure DescrEndRemark; override;
procedure DescrBeginTable(ColCount: Integer; HasBorder: Boolean); override;
procedure DescrEndTable; override;
procedure DescrBeginTableCaption; override;
procedure DescrEndTableCaption; override;
procedure DescrBeginTableHeadRow; override;
procedure DescrEndTableHeadRow; override;
procedure DescrBeginTableRow; override;
procedure DescrEndTableRow; override;
procedure DescrBeginTableCell; override;
procedure DescrEndTableCell; override;
procedure AppendText(Parent: TDOMNode; const AText: DOMString);
procedure AppendNbSp(Parent: TDOMNode; ACount: Integer);
procedure AppendSym(Parent: TDOMNode; const AText: DOMString);
procedure AppendKw(Parent: TDOMNode; const AText: DOMString);
function AppendPasSHFragment(Parent: TDOMNode; const AText: String;
AShFlags: Byte): Byte;
Procedure AppendShortDescr(AContext : TPasElement;Parent: TDOMNode; DocNode : TDocNode);
procedure AppendShortDescr(Parent: TDOMNode; Element: TPasElement);
procedure AppendDescr(AContext: TPasElement; Parent: TDOMNode;
DescrNode: TDOMElement; AutoInsertBlock: Boolean);
procedure AppendDescrSection(AContext: TPasElement; Parent: TDOMNode;
DescrNode: TDOMElement; const ATitle: DOMString);
procedure AppendShortDescrCell(Parent: TDOMNode; Element: TPasElement);
function AppendHyperlink(Parent: TDOMNode; Element: TPasElement): TDOMElement;
function AppendType(CodeEl, TableEl: TDOMElement;
Element: TPasType; Expanded: Boolean): TDOMElement;
function AppendProcType(CodeEl, TableEl: TDOMElement;
Element: TPasProcedureType; Indent: Integer): TDOMElement;
procedure AppendProcExt(CodeEl: TDOMElement; Element: TPasProcedure);
procedure AppendProcDecl(CodeEl, TableEl: TDOMElement;
Element: TPasProcedureBase);
procedure AppendProcArgsSection(Parent: TDOMNode;
Element: TPasProcedureType);
procedure AppendTitle(const AText: DOMString);
procedure AppendMenuBar(ASubpageIndex: Integer);
procedure AppendTopicMenuBar(Topic : TTopicElement);
procedure AppendSourceRef(AElement: TPasElement);
procedure FinishElementPage(AElement: TPasElement);
Procedure AppendSeeAlsoSection(AElement : TPasElement;DocNode : TDocNode);
Procedure AppendExampleSection(AElement : TPasElement;DocNode : TDocNode);
procedure AppendFooter;
procedure CreatePageBody(AElement: TPasElement; ASubpageIndex: Integer); virtual;
procedure CreatePackagePageBody;
Procedure CreateTopicPageBody(AElement : TTopicElement);
procedure CreateModulePageBody(AModule: TPasModule; ASubpageIndex: Integer);
procedure CreateConstPageBody(AConst: TPasConst);
procedure CreateTypePageBody(AType: TPasType);
procedure CreateClassPageBody(AClass: TPasClassType; ASubpageIndex: Integer);
procedure CreateClassMemberPageBody(AElement: TPasElement);
procedure CreateVarPageBody(AVar: TPasVariable);
procedure CreateProcPageBody(AProc: TPasProcedureBase);
Procedure CreateTopicLinks(Node : TDocNode; PasElement : TPasElement);
public
constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
destructor Destroy; override;
// Single-page generation
function CreateHTMLPage(AElement: TPasElement;
ASubpageIndex: Integer): TXMLDocument;
function CreateXHTMLPage(AElement: TPasElement;
ASubpageIndex: Integer): TXMLDocument;
// For producing complete package documentation
procedure WriteHTMLPages;
procedure WriteXHTMLPages;
SearchPage: String;
property Allocator: TFileAllocator read FAllocator;
property Package: TPasPackage read FPackage;
property PageCount: Integer read GetPageCount;
property OnTest: TNotifyEvent read FOnTest write SetOnTest;
Function InterPretOption(Const Cmd,Arg : String) : boolean; override;
Procedure WriteDoc; override;
class procedure Usage(List: TStrings); override;
end;
THTMWriter = class(THTMLWriter)
Protected
Procedure CreateAllocator; override;
end;
implementation
uses SysUtils, XHTML, XMLRead, XMLWrite, HTMWrite, sh_pas;
Function FixHTMLpath(S : String) : STring;
begin
Result:=StringReplace(S,'\','/',[rfReplaceAll]);
end;
procedure TFileAllocator.AllocFilename(AElement: TPasElement;
ASubindex: Integer);
begin
end;
function TFileAllocator.GetRelativePathToTop(AElement: TPasElement): String;
begin
SetLength(Result, 0);
end;
function TFileAllocator.GetCSSFilename(ARelativeTo: TPasElement): DOMString;
begin
Result := GetRelativePathToTop(ARelativeTo) + 'fpdoc.css';
end;
constructor TShortNameFileAllocator.Create(const AExtension: String);
begin
inherited Create;
FExtension := AExtension;
end;
procedure TShortNameFileAllocator.AllocFilename(AElement: TPasElement;
ASubindex: Integer);
begin
// !!!: Add element to file list
end;
constructor TLongNameFileAllocator.Create(const AExtension: String);
begin
inherited Create;
FExtension := AExtension;
end;
function TLongNameFileAllocator.GetFilename(AElement: TPasElement;
ASubindex: Integer): String;
var
i: Integer;
begin
if AElement.ClassType = TPasPackage then
Result := 'index'
else if AElement.ClassType = TPasModule then
Result := LowerCase(AElement.Name) + PathDelim + 'index'
else
begin
Result := LowerCase(AElement.PathName);
i := 1;
if (Length(Result)>0) and (Result[1]='#') then
begin
while Result[i] <> '.' do
Inc(i);
Result:=Copy(Result,i+1,Length(Result));
end;
i := 1;
while (I<=Length(Result)) and (Result[i]<>'.') do
Inc(i);
If (I<=Length(Result)) and (I>0) then
Result[i]:= PathDelim;
end;
if ASubindex > 0 then
Result := Result + '-' + IntToStr(ASubindex);
Result := Result + Extension;
end;
function TLongNameFileAllocator.GetRelativePathToTop(AElement: TPasElement): String;
begin
if (AElement.ClassType=TPasPackage) then
Result := ''
else if (AElement.ClassType=TTopicElement) then
begin
If (AElement.Parent.ClassType=TTopicElement) then
Result:='../'+GetRelativePathToTop(AElement.Parent)
else if (AElement.Parent.ClassType=TPasPackage) then
Result:=''
else if (AElement.Parent.ClassType=TPasModule) then
Result:='../';
end
else
Result := '../';
end;
constructor THTMLWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
procedure AddPage(AElement: TPasElement; ASubpageIndex: Integer);
var
PageInfo: TPageInfo;
begin
PageInfo := TPageInfo.Create;
PageInfo.Element := AElement;
PageInfo.SubpageIndex := ASubpageIndex;
PageInfos.Add(PageInfo);
Allocator.AllocFilename(AElement, ASubpageIndex);
if ASubpageIndex = 0 then
Engine.AddLink(AElement.PathName,
Allocator.GetFilename(AElement, ASubpageIndex));
end;
procedure AddTopicPages(AElement: TPasElement);
var
PreviousTopic,
TopicElement : TTopicElement;
PageInfo : TPageInfo;
DocNode,
TopicNode : TDocNode;
begin
DocNode:=Engine.FindDocNode(AElement);
If not Assigned(DocNode) then
exit;
TopicNode:=DocNode.FirstChild;
PreviousTopic:=Nil;
While Assigned(TopicNode) do
begin
If TopicNode.TopicNode then
begin
TopicElement:=TTopicElement.Create(TopicNode.Name,AElement);
Topics.Add(TopicElement);
TopicElement.TopicNode:=TopicNode;
TopicElement.Previous:=PreviousTopic;
If Assigned(PreviousTopic) then
PreviousTopic.Next:=TopicElement;
PreviousTopic:=TopicElement;
if AElement is TTopicElement then
TTopicElement(AElement).SubTopics.Add(TopicElement);
PageInfo := TPageInfo.Create;
PageInfo.Element := TopicElement;
PageInfo.SubpageIndex := 0;
PageInfos.Add(PageInfo);
Allocator.AllocFilename(TopicElement,0);
Engine.AddLink(TopicElement.PathName, Allocator.GetFilename(TopicElement,0));
if AElement is TTopicElement then
TTopicElement(AElement).SubTopics.Add(TopicElement)
else // Only one level of recursion.
AddTopicPages(TopicElement);
end;
TopicNode:=TopicNode.NextSibling;
end;
end;
procedure AddPages(AElement: TPasElement; ASubpageIndex: Integer;
AList: TList);
var
i: Integer;
begin
if AList.Count > 0 then
begin
AddPage(AElement, ASubpageIndex);
for i := 0 to AList.Count - 1 do
AddPage(TPasElement(AList[i]), 0);
end;
end;
procedure ScanModule(AModule: TPasModule);
var
i, j, k: Integer;
s: String;
ClassEl: TPasClassType;
FPEl, AncestorMemberEl: TPasElement;
DocNode: TDocNode;
DidAutolink: Boolean;
begin
AddPage(AModule, 0);
AddTopicPages(AModule);
with AModule do
begin
if InterfaceSection.ResStrings.Count > 0 then
begin
AddPage(AModule, ResstrSubindex);
s := Allocator.GetFilename(AModule, ResstrSubindex);
for i := 0 to InterfaceSection.ResStrings.Count - 1 do
with TPasResString(InterfaceSection.ResStrings[i]) do
Engine.AddLink(PathName, s + '#' + LowerCase(Name));
end;
AddPages(AModule, ConstsSubindex, InterfaceSection.Consts);
AddPages(AModule, TypesSubindex, InterfaceSection.Types);
if InterfaceSection.Classes.Count > 0 then
begin
AddPage(AModule, ClassesSubindex);
for i := 0 to InterfaceSection.Classes.Count - 1 do
begin
ClassEl := TPasClassType(InterfaceSection.Classes[i]);
AddPage(ClassEl, 0);
// !!!: Only add when there are items
AddPage(ClassEl, PropertiesByInheritanceSubindex);
AddPage(ClassEl, PropertiesByNameSubindex);
AddPage(ClassEl, MethodsByInheritanceSubindex);
AddPage(ClassEl, MethodsByNameSubindex);
AddPage(ClassEl, EventsByInheritanceSubindex);
AddPage(ClassEl, EventsByNameSubindex);
for j := 0 to ClassEl.Members.Count - 1 do
begin
FPEl := TPasElement(ClassEl.Members[j]);
if ((FPEl.Visibility = visPrivate) and Engine.HidePrivate) or
((FPEl.Visibility = visProtected) and Engine.HideProtected) then
continue;
DocNode := Engine.FindDocNode(FPEl);
if not Assigned(DocNode) then
begin
DidAutolink := False;
if Assigned(ClassEl.AncestorType) and
(ClassEl.AncestorType.ClassType = TPasClassType) then
begin
for k := 0 to TPasClassType(ClassEl.AncestorType).Members.Count - 1 do
begin
AncestorMemberEl :=
TPasElement(TPasClassType(ClassEl.AncestorType).Members[k]);
if AncestorMemberEl.Name = FPEl.Name then
begin
DocNode := Engine.FindDocNode(AncestorMemberEl);
if Assigned(DocNode) then
begin
DidAutolink := True;
Engine.AddLink(FPEl.PathName,
Engine.FindAbsoluteLink(AncestorMemberEl.PathName));
break;
end;
end;
end;
end;
if not DidAutolink then
AddPage(FPEl, 0);
end else
AddPage(FPEl, 0);
end;
end;
end;
AddPages(AModule, ProcsSubindex, InterfaceSection.Functions);
AddPages(AModule, VarsSubindex, InterfaceSection.Variables);
end;
end;
var
i: Integer;
begin
inherited ;
CreateAllocator;
FPackage := APackage;
OutputNodeStack := TList.Create;
PageInfos := TObjectList.Create;
// Allocate page for the package itself, if a name is given (i.e. <> '#')
if Length(Package.Name) > 1 then
begin
AddPage(Package, 0);
AddTopicPages(Package);
end;
for i := 0 to Package.Modules.Count - 1 do
ScanModule(TPasModule(Package.Modules[i]));
end;
destructor THTMLWriter.Destroy;
begin
PageInfos.Free;
OutputNodeStack.Free;
inherited Destroy;
end;
function THTMLWriter.CreateHTMLPage(AElement: TPasElement;
ASubpageIndex: Integer): TXMLDocument;
var
HTMLEl: THTMLHtmlElement;
HeadEl: THTMLHeadElement;
El: TDOMElement;
begin
Doc := THTMLDocument.Create;
Result := Doc;
Doc.AppendChild(Doc.CreateProcessingInstruction(
'DOCTYPE', 'HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"'));
HTMLEl := Doc.CreateHtmlElement;
Doc.AppendChild(HTMLEl);
HeadEl := Doc.CreateHeadElement;
HTMLEl.AppendChild(HeadEl);
El := Doc.CreateElement('meta');
HeadEl.AppendChild(El);
El['http-equiv'] := 'Content-Type';
El['content'] := 'text/html; charset=iso-8859-1';
TitleElement := Doc.CreateElement('title');
HeadEl.AppendChild(TitleElement);
El := Doc.CreateElement('link');
BodyElement := Doc.CreateElement('body');
HTMLEl.AppendChild(BodyElement);
CreatePageBody(AElement, ASubpageIndex);
AppendFooter;
HeadEl.AppendChild(El);
El['rel'] := 'stylesheet';
El['type'] := 'text/css';
El['href'] := FixHtmlPath(Allocator.GetCSSFilename(AElement));
end;
function THTMLWriter.CreateXHTMLPage(AElement: TPasElement;
ASubpageIndex: Integer): TXMLDocument;
begin
Result := nil;
end;
procedure CreatePath(const AFilename: String);
var
EndIndex: Integer;
Path: String;
begin
EndIndex := Length(AFilename);
if EndIndex = 0 then
exit;
while not (AFilename[EndIndex] in DirSeparators) do
begin
Dec(EndIndex);
if EndIndex = 0 then
exit;
end;
Path := Copy(AFilename, 1, EndIndex - 1);
if not FileExists(Path) then
begin
CreatePath(Path);
MkDir(Path);
end;
end;
procedure THTMLWriter.WriteHTMLPages;
var
i: Integer;
PageDoc: TXMLDocument;
Filename: String;
begin
if Engine.Output <> '' then
Engine.Output := IncludeTrailingBackSlash(Engine.Output);
for i := 0 to PageInfos.Count - 1 do
with TPageInfo(PageInfos[i]) do
begin
PageDoc := CreateHTMLPage(Element, SubpageIndex);
try
Filename := Engine.Output + Allocator.GetFilename(Element, SubpageIndex);
CreatePath(Filename);
WriteHTMLFile(PageDoc, Filename);
finally
PageDoc.Free;
end;
end;
end;
procedure THTMLWriter.WriteXHTMLPages;
begin
end;
{procedure THTMLWriter.CreateDoc(const ATitle: DOMString;
AElement: TPasElement; const AFilename: String);
var
El: TDOMElement;
DocInfo: TDocInfo;
CSSName: String;
begin
Doc := TXHTMLDocument.Create;
with TXHTMLDocument(Doc) do
begin
Encoding := 'ISO8859-1';
CSSName := 'fpdoc.css';
if Assigned(Module) then
CSSName := '../' + CSSName;
$IFNDEF ver1_0
StylesheetType := 'text/css';
StylesheetHRef := CSSName;
$ENDIF
CreateRoot(xhtmlStrict);
with RequestHeadElement do
begin
AppendText(RequestTitleElement, ATitle);
El := CreateElement('link');
AppendChild(El);
El['rel'] := 'stylesheet';
El['type'] := 'text/css';
El['href'] := FixHtmlPath(CSSName);
end;
Self.BodyElement := RequestBodyElement('en');
end;
if Length(AFilename) > 0 then
begin
DocInfo := TDocInfo.Create;
DocInfos.Add(DocInfo);
DocInfo.Element := AElement;
DocInfo.Filename := AFilename;
end;
end;
}
{ Used for:
- <link> elements in descriptions
- "see also" entries
- AppendHyperlink (for unresolved parse tree element links)
}
function THTMLWriter.ResolveLinkID(const Name: String): DOMString;
var
i: Integer;
ThisPackage: TLinkNode;
begin
if Length(Name) = 0 then
begin
SetLength(Result, 0);
exit;
end;
if Name[1] = '#' then
Result := Engine.FindAbsoluteLink(Name)
else
begin
SetLength(Result, 0);
{ Try all packages }
ThisPackage := Engine.RootLinkNode.FirstChild;
while Assigned(ThisPackage) do
begin
Result := Engine.FindAbsoluteLink(ThisPackage.Name + '.' + Name);
if Length(Result) = 0 then
begin
if Assigned(Module) then
Result := Engine.FindAbsoluteLink(Module.PathName + '.' + Name);
// WriteLn('Searching for ', Module.PathName + '.' + Name, ' => ', Result);
if Length(Result) = 0 then
for i := Length(Name) downto 1 do
if Name[i] = '.' then
begin
Result := ResolveLinkID(Copy(Name, 1, i - 1));
exit;
end;
end;
ThisPackage := ThisPackage.NextSibling;
end;
end;
if Length(Result) > 0 then
if Copy(Result, 1, Length(CurDirectory) + 1) = CurDirectory + '/' then
Result := Copy(Result, Length(CurDirectory) + 2, Length(Result))
else
Result := BaseDirectory + Result;
end;
function THTMLWriter.ResolveLinkWithinPackage(AElement: TPasElement;
ASubpageIndex: Integer): String;
var
ParentEl: TPasElement;
begin
ParentEl := AElement;
while Assigned(ParentEl) and not (ParentEl.ClassType = TPasPackage) do
ParentEl := ParentEl.Parent;
if Assigned(ParentEl) and (TPasPackage(ParentEl) = Engine.Package) then
begin
Result := Allocator.GetFilename(AElement, ASubpageIndex);
if Copy(Result, 1, Length(CurDirectory) + 1) = CurDirectory + '/' then
Result := Copy(Result, Length(CurDirectory) + 2, Length(Result))
else
Result := BaseDirectory + Result;
end else
SetLength(Result, 0);
end;
function THTMLWriter.CreateEl(Parent: TDOMNode;
const AName: DOMString): THTMLElement;
begin
Result := Doc.CreateElement(AName);
Parent.AppendChild(Result);
end;
function THTMLWriter.CreatePara(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'p');
end;
function THTMLWriter.CreateH1(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'h1');
end;
function THTMLWriter.CreateH2(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'h2');
end;
function THTMLWriter.CreateH3(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'h3');
end;
function THTMLWriter.CreateTable(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'table');
Result['cellspacing'] := '0';
Result['cellpadding'] := '0';
end;
function THTMLWriter.CreateContentTable(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'table');
end;
function THTMLWriter.CreateTR(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'tr');
end;
function THTMLWriter.CreateTD(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'td');
end;
function THTMLWriter.CreateTD_vtop(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'td');
Result['valign'] := 'top';
end;
function THTMLWriter.CreateLink(Parent: TDOMNode;
const AHRef: DOMString): THTMLElement;
begin
Result := CreateEl(Parent, 'a');
Result['href'] := FixHtmlPath(AHRef);
end;
function THTMLWriter.CreateAnchor(Parent: TDOMNode;
const AName: DOMString): THTMLElement;
begin
Result := CreateEl(Parent, 'a');
Result['name'] := AName;
end;
function THTMLWriter.CreateCode(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(CreateEl(Parent, 'tt'), 'span');
Result['class'] := 'code';
end;
function THTMLWriter.CreateWarning(Parent: TDOMNode): THTMLElement;
begin
Result := CreateEl(Parent, 'span');
Result['class'] := 'warning';
end;
procedure THTMLWriter.PushOutputNode(ANode: TDOMNode);
begin
OutputNodeStack.Add(CurOutputNode);
CurOutputNode := ANode;
end;
procedure THTMLWriter.PopOutputNode;
begin
CurOutputNode := TDOMNode(OutputNodeStack[OutputNodeStack.Count - 1]);
OutputNodeStack.Delete(OutputNodeStack.Count - 1);
end;
procedure THTMLWriter.DescrWriteText(const AText: DOMString);
begin
AppendText(CurOutputNode, AText);
end;
procedure THTMLWriter.DescrBeginBold;
begin
PushOutputNode(CreateEl(CurOutputNode, 'b'));
end;
procedure THTMLWriter.DescrEndBold;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginItalic;
begin
PushOutputNode(CreateEl(CurOutputNode, 'i'));
end;
procedure THTMLWriter.DescrEndItalic;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginEmph;
begin
PushOutputNode(CreateEl(CurOutputNode, 'em'));
end;
procedure THTMLWriter.DescrEndEmph;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrWriteFileEl(const AText: DOMString);
var
NewEl: TDOMElement;
begin
NewEl := CreateEl(CurOutputNode, 'span');
NewEl['class'] := 'file';
AppendText(NewEl, AText);
end;
procedure THTMLWriter.DescrWriteKeywordEl(const AText: DOMString);
var
NewEl: TDOMElement;
begin
NewEl := CreateEl(CurOutputNode, 'span');
NewEl['class'] := 'kw';
AppendText(NewEl, AText);
end;
procedure THTMLWriter.DescrWriteVarEl(const AText: DOMString);
begin
AppendText(CreateEl(CurOutputNode, 'var'), AText);
end;
procedure THTMLWriter.DescrBeginLink(const AId: DOMString);
var
a,s: String;
begin
a:=AId;
s := ResolveLinkID(a);
if Length(s) = 0 then
begin
WriteLn(Format(SErrUnknownLinkID, [a]));
PushOutputNode(CreateEl(CurOutputNode, 'b'));
end else
PushOutputNode(CreateLink(CurOutputNode, s));
end;
procedure THTMLWriter.DescrEndLink;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrWriteLinebreak;
begin
CreateEl(CurOutputNode, 'br');
end;
procedure THTMLWriter.DescrBeginParagraph;
begin
PushOutputNode(CreatePara(CurOutputNode));
end;
procedure THTMLWriter.DescrEndParagraph;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginCode(HasBorder: Boolean; const AHighlighterName: String);
begin
DoPasHighlighting := (AHighlighterName = '') or (AHighlighterName = 'Pascal');
HighlighterFlags := 0;
PushOutputNode(CreateEl(CurOutputNode, 'pre'));
end;
procedure THTMLWriter.DescrWriteCodeLine(const ALine: String);
begin
if DoPasHighlighting then
begin
HighlighterFlags := AppendPasSHFragment(CurOutputNode, ALine,
HighlighterFlags);
AppendText(CurOutputNode, #10);
end else
AppendText(CurOutputNode, ALine + #10);
end;
procedure THTMLWriter.DescrEndCode;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginOrderedList;
begin
PushOutputNode(CreateEl(CurOutputNode, 'ol'));
end;
procedure THTMLWriter.DescrEndOrderedList;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginUnorderedList;
begin
PushOutputNode(CreateEl(CurOutputNode, 'ul'));
end;
procedure THTMLWriter.DescrEndUnorderedList;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginDefinitionList;
begin
PushOutputNode(CreateEl(CurOutputNode, 'dl'));
end;
procedure THTMLWriter.DescrEndDefinitionList;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginListItem;
begin
PushOutputNode(CreateEl(CurOutputNode, 'li'));
end;
procedure THTMLWriter.DescrEndListItem;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginDefinitionTerm;
begin
PushOutputNode(CreateEl(CurOutputNode, 'dt'));
end;
procedure THTMLWriter.DescrEndDefinitionTerm;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginDefinitionEntry;
begin
PushOutputNode(CreateEl(CurOutputNode, 'dd'));
end;
procedure THTMLWriter.DescrEndDefinitionEntry;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginSectionTitle;
begin
PushOutputNode(CreateEl(CurOutputNode, 'h3'));
end;
procedure THTMLWriter.DescrBeginSectionBody;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrEndSection;
begin
end;
procedure THTMLWriter.DescrBeginRemark;
var
NewEl, TDEl: TDOMElement;
begin
NewEl := CreateEl(CurOutputNode, 'table');
NewEl['width'] := '100%';
NewEl['border'] := '0';
NewEl['CellSpacing'] := '0';
NewEl['class'] := 'remark';
NewEl := CreateTR(NewEl);
TDEl := CreateTD(NewEl);
TDEl['valign'] := 'top';
TDEl['class'] := 'pre';
AppendText(CreateEl(TDEl, 'b'), SDocRemark);
PushOutputNode(CreateTD(NewEl));
end;
procedure THTMLWriter.DescrEndRemark;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginTable(ColCount: Integer; HasBorder: Boolean);
var
Table: TDOMElement;
begin
Table := CreateEl(CurOutputNode, 'table');
Table['border'] := IntToStr(Ord(HasBorder));
PushOutputNode(Table);
end;
procedure THTMLWriter.DescrEndTable;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginTableCaption;
begin
PushOutputNode(CreateEl(CurOutputNode, 'caption'));
end;
procedure THTMLWriter.DescrEndTableCaption;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginTableHeadRow;
begin
PushOutputNode(CreateTr(CurOutputNode));
InsideHeadRow := True;
end;
procedure THTMLWriter.DescrEndTableHeadRow;
begin
InsideHeadRow := False;
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginTableRow;
begin
PushOutputNode(CreateTR(CurOutputNode));
end;
procedure THTMLWriter.DescrEndTableRow;
begin
PopOutputNode;
end;
procedure THTMLWriter.DescrBeginTableCell;
begin
if InsideHeadRow then
PushOutputNode(CreateEl(CurOutputNode, 'th'))
else
PushOutputNode(CreateTD(CurOutputNode));
end;
procedure THTMLWriter.DescrEndTableCell;
begin
PopOutputNode;
end;
procedure THTMLWriter.AppendText(Parent: TDOMNode; const AText: DOMString);
begin
Parent.AppendChild(Doc.CreateTextNode(AText));
end;
procedure THTMLWriter.AppendNbSp(Parent: TDOMNode; ACount: Integer);
begin
while ACount > 0 do
begin
Parent.AppendChild(Doc.CreateEntityReference('nbsp'));
Dec(ACount);
end;
end;
procedure THTMLWriter.AppendSym(Parent: TDOMNode; const AText: DOMString);
var
El: TDOMElement;
begin
El := CreateEl(Parent, 'span');
El['class'] := 'sym';
AppendText(El, AText);
end;
procedure THTMLWriter.AppendKw(Parent: TDOMNode; const AText: DOMString);
var
El: TDOMElement;
begin
El := CreateEl(Parent, 'span');
El['class'] := 'kw';
AppendText(El, AText);
end;
function THTMLWriter.AppendPasSHFragment(Parent: TDOMNode;
const AText: String; AShFlags: Byte): Byte;
var
CurParent: TDOMNode;
Line, Last, p: PChar;
IsInSpecial: Boolean;
El: TDOMElement;
begin
GetMem(Line, Length(AText) * 3 + 4);
DoPascalHighlighting(AShFlags, PChar(AText), Line);
Result := AShFlags;
CurParent := Parent;
IsInSpecial := False;
Last := Line;
p := Line;
while p[0] <> #0 do
begin
if p[0] = LF_ESCAPE then
begin
p[0] := #0;
AppendText(CurParent, Last);
if IsInSpecial then
CurParent := Parent;
case Ord(p[1]) of
shDefault:
IsInSpecial := False;
shInvalid:
begin
El := CreateEl(CurParent, 'font');
El['color'] := 'red';
CurParent := El;
IsInSpecial := True;
end;
shSymbol:
begin
El := CreateEl(CurParent, 'span');
El['class'] := 'sym';
CurParent := El;
IsInSpecial := True;
end;
shKeyword:
begin
El := CreateEl(CurParent, 'span');
El['class'] := 'kw';
CurParent := El;
IsInSpecial := True;
end;
shComment:
begin
El := CreateEl(CurParent, 'span');
El['class'] := 'cmt';
CurParent := El;
IsInSpecial := True;
end;
shDirective:
begin
El := CreateEl(CurParent, 'span');
El['class'] := 'dir';
CurParent := El;
IsInSpecial := True;
end;
shNumbers:
begin
El := CreateEl(CurParent, 'span');
El['class'] := 'num';
CurParent := El;
IsInSpecial := True;
end;
shCharacters:
begin
El := CreateEl(CurParent, 'span');
El['class'] := 'chr';
CurParent := El;
IsInSpecial := True;
end;
shStrings:
begin
El := CreateEl(CurParent, 'span');
El['class'] := 'str';
CurParent := El;
IsInSpecial := True;
end;
shAssembler:
begin
El := CreateEl(CurParent, 'span');
El['class'] := 'asm';
CurParent := El;
IsInSpecial := True;
end;
end;
Last := p + 2;
end;
Inc(p);
end;
if Last <> p then
AppendText(CurParent, Last);
FreeMem(Line);
end;
Procedure THTMLWriter.AppendShortDescr(AContext: TPasElement; Parent: TDOMNode; DocNode : TDocNode);
begin
if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
begin
PushOutputNode(Parent);
try
if not ConvertShort(AContext,TDomElement(DocNode.ShortDescr)) then
WriteLn(SErrInvalidShortDescr);
finally
PopOutputNode;
end;
end;
end;
procedure THTMLWriter.AppendShortDescr(Parent: TDOMNode; Element: TPasElement);
begin
AppendShortDescr(Element,Parent,Engine.FindDocNode(Element));
end;
procedure THTMLWriter.AppendDescr(AContext: TPasElement; Parent: TDOMNode;
DescrNode: TDOMElement; AutoInsertBlock: Boolean);
begin
if Assigned(DescrNode) then
begin
PushOutputNode(Parent);
try
ConvertDescr(AContext, DescrNode, AutoInsertBlock);
finally
PopOutputNode;
end;
end;
end;
procedure THTMLWriter.AppendDescrSection(AContext: TPasElement;
Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: DOMString);
begin
if not IsDescrNodeEmpty(DescrNode) then
begin
If (ATitle<>'') then // Can be empty for topic.
AppendText(CreateH2(Parent), ATitle);
AppendDescr(AContext, Parent, DescrNode, True);
end;
end;
procedure THTMLWriter.AppendShortDescrCell(Parent: TDOMNode;
Element: TPasElement);
var
ParaEl: TDOMElement;
begin
if Assigned(Engine.FindShortDescr(Element)) then
begin
AppendNbSp(CreatePara(CreateTD(Parent)), 2);
ParaEl := CreatePara(CreateTD(Parent));
ParaEl['class'] := 'cmt';
AppendShortDescr(ParaEl, Element);
end;
end;
function THTMLWriter.AppendHyperlink(Parent: TDOMNode;
Element: TPasElement): TDOMElement;
var
s: String;
UnitList: TList;
i: Integer;
ThisPackage: TLinkNode;
begin
if Assigned(Element) then
begin
if Element.InheritsFrom(TPasUnresolvedTypeRef) then
begin
s := ResolveLinkID(Element.Name);
if Length(s) = 0 then
begin
{ Try all packages }
ThisPackage := Engine.RootLinkNode.FirstChild;
while Assigned(ThisPackage) do
begin
s := ResolveLinkID(ThisPackage.Name + '.' + Element.Name);
if Length(s) > 0 then
break;
ThisPackage := ThisPackage.NextSibling;
end;
if Length(s) = 0 then
begin
{ Okay, then we have to try all imported units of the current module }
UnitList := Module.InterfaceSection.UsesList;
for i := UnitList.Count - 1 downto 0 do
begin
{ Try all packages }
ThisPackage := Engine.RootLinkNode.FirstChild;
while Assigned(ThisPackage) do
begin
s := ResolveLinkID(ThisPackage.Name + '.' +
TPasType(UnitList[i]).Name + '.' + Element.Name);
if Length(s) > 0 then
break;
ThisPackage := ThisPackage.NextSibling;
end;
if Length(s) > 0 then
break;
end;
end;
end;
end else
s := ResolveLinkID(Element.PathName);
if Length(s) > 0 then
begin
Result := CreateLink(Parent, s);
AppendText(Result, Element.Name);
end else
begin
Result := nil;
AppendText(Parent, Element.Name);
end;
end else
begin
Result := nil;
AppendText(CreateWarning(Parent), '<NIL>');
end;
end;
{ Returns the new CodeEl, which will be the old CodeEl in most cases }
function THTMLWriter.AppendType(CodeEl, TableEl: TDOMElement;
Element: TPasType; Expanded: Boolean): TDOMElement;
begin
Result := CodeEl;
if not Assigned(Element) then
AppendText(CreateWarning(CodeEl), '<NIL>')
else if (not Expanded) and (Length(Element.Name) > 0) then
AppendHyperlink(CodeEl, Element)
else
// Array
if Element.ClassType = TPasArrayType then
begin
AppendPasSHFragment(CodeEl,
'array [' + TPasArrayType(Element).IndexRange + '] of ', 0);
Result := AppendType(CodeEl, TableEl, TPasArrayType(Element).ElType, False);
end else
// Procedure or funtion type
if Element.InheritsFrom(TPasProcedureType) then
begin
AppendKw(CodeEl, TPasProcedureType(Element).TypeName);
Result := AppendProcType(CodeEl, TableEl, TPasProcedureType(Element), 0)
end else
// Range type
if Element.InheritsFrom(TPasRangeType) then
AppendPasSHFragment(CodeEl, TPasRangeType(Element).RangeStart + '..' +
TPasRangeType(Element).RangeEnd, 0)
else
// Other types
AppendHyperlink(CodeEl, Element);
end;
function THTMLWriter.AppendProcType(CodeEl, TableEl: TDOMElement;
Element: TPasProcedureType; Indent: Integer): TDOMElement;
function CreateIndentedCodeEl(Indent: Integer): TDOMElement;
begin
Result := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
AppendNbSp(Result, Indent);
end;
var
i: Integer;
Arg: TPasArgument;
begin
if Element.Args.Count > 0 then
begin
AppendSym(CodeEl, '(');
for i := 0 to Element.Args.Count - 1 do
begin
Arg := TPasArgument(Element.Args[i]);
CodeEl := CreateIndentedCodeEl(Indent + 2);
case Arg.Access of
argConst: AppendKw(CodeEl, 'const ');
argVar: AppendKw(CodeEl, 'var ');
argOut: AppendKw(CodeEl, 'out ');
end;
AppendText(CodeEl, Arg.Name);
if Assigned(Arg.ArgType) then
begin
AppendSym(CodeEl, ': ');
CodeEl := AppendType(CodeEl, TableEl, Arg.ArgType, False);
end;
if Length(Arg.Value) > 0 then
AppendPasSHFragment(CodeEl, ' = ' + Arg.Value, 0);
if i < Element.Args.Count - 1 then
AppendSym(CodeEl, ';');
end;
if Element.InheritsFrom(TPasFunctionType) or Element.IsOfObject then
begin
CodeEl := CreateIndentedCodeEl(Indent);
if Element.InheritsFrom(TPasFunctionType) then
begin
AppendSym(CodeEl, '):');
AppendHyperlink(CodeEl, TPasFunctionType(Element).ResultEl.ResultType);
end else
AppendSym(CodeEl, ')');
if Element.IsOfObject then
begin
AppendText(CodeEl, ' '); // Don't remove
AppendKw(CodeEl, 'of object');
end;
end else
if Indent > 0 then
AppendSym(CodeEl, ')')
else
begin
CodeEl := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
AppendSym(CodeEl, ')');
end;
end else
begin
{ Procedure or function without arguments }
if Element.InheritsFrom(TPasFunctionType) then
begin
AppendSym(CodeEl, ': ');
AppendHyperlink(CodeEl, TPasFunctionType(Element).ResultEl.ResultType);
end;
if Element.IsOfObject then
AppendKw(CodeEl, ' of object');
end;
Result := CodeEl;
end;
procedure THTMLWriter.AppendProcExt(CodeEl: TDOMElement;
Element: TPasProcedure);
procedure AppendExt(const Ext: String);
begin
AppendKw(CodeEl, ' ' + Ext);
AppendSym(CodeEl, ';');
end;
begin
if Element.IsVirtual then
AppendExt('virtual');
if Element.IsDynamic then
AppendExt('dynamic');
if Element.IsAbstract then
AppendExt('abstract');
if Element.IsOverride then
AppendExt('override');
if Element.IsOverload then
AppendExt('overload');
if Element.IsMessage then
AppendExt('message');
end;
{ Used in two places:
- Page for the method of a class
- Page for a tandalone procedure or function. }
procedure THTMLWriter.AppendProcDecl(CodeEl, TableEl: TDOMElement;
Element: TPasProcedureBase);
procedure WriteVariant(AProc: TPasProcedure);
begin
AppendProcArgsSection(TableEl.ParentNode, AProc.ProcType);
AppendKw(CodeEl, AProc.TypeName);
if Element.Parent.ClassType = TPasClassType then
begin
AppendText(CodeEl, ' ');
AppendHyperlink(CodeEl, Element.Parent);
AppendSym(CodeEl, '.');
AppendText(CodeEl, AProc.Name);
end else
AppendText(CodeEl, ' ' + AProc.FullName);
CodeEl := AppendProcType(CodeEl, TableEl, AProc.ProcType, 0);
AppendSym(CodeEl, ';');
AppendProcExt(CodeEl, AProc);
end;
var
i: Integer;
begin
if Element.ClassType = TPasOverloadedProc then
for i := 0 to TPasOverloadedProc(Element).Overloads.Count - 1 do
begin
if i > 0 then
begin
CreateEl(CodeEl, 'br');
CreateEl(CodeEl, 'br');
end;
WriteVariant(TPasProcedure(TPasOverloadedProc(Element).Overloads[i]));
end
else
WriteVariant(TPasProcedure(Element));
end;
procedure THTMLWriter.AppendProcArgsSection(Parent: TDOMNode;
Element: TPasProcedureType);
var
HasFullDescr, IsFirst: Boolean;
ResultEl: TPasResultElement;
ArgTableEl, TREl: TDOMElement;
DocNode: TDocNode;
i: Integer;
Arg: TPasArgument;
begin
IsFirst := True;
for i := 0 to Element.Args.Count - 1 do
begin
Arg := TPasArgument(Element.Args[i]);
if IsDescrNodeEmpty(Engine.FindShortDescr(Arg)) then
continue;
if IsFirst then
begin
IsFirst := False;
AppendText(CreateH2(Parent), SDocArguments);
ArgTableEl := CreateTable(Parent);
end;
TREl := CreateTR(ArgTableEl);
AppendText(CreateCode(CreatePara(CreateTD_vtop(TREl))), Arg.Name);
AppendShortDescrCell(TREl, Arg);
end;
if Element.ClassType = TPasFunctionType then
begin
ResultEl := TPasFunctionType(Element).ResultEl;
DocNode := Engine.FindDocNode(ResultEl);
HasFullDescr := Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.Descr);
if HasFullDescr or
(Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.ShortDescr)) then
begin
AppendText(CreateH2(Parent), SDocFunctionResult);
if HasFullDescr then
AppendDescr(ResultEl, Parent, DocNode.Descr, True)
else
AppendDescr(ResultEl, CreatePara(Parent), DocNode.ShortDescr, False);
end;
end;
end;
procedure THTMLWriter.AppendTitle(const AText: DOMString);
begin
AppendText(TitleElement, AText);
AppendText(CreateH1(BodyElement), AText);
end;
procedure THTMLWriter.AppendTopicMenuBar(Topic : TTopicElement);
var
TableEl, TREl, ParaEl, TitleEl: TDOMElement;
procedure AddLink(El : TPasElement; const AName: String);
begin
AppendText(ParaEl, '[');
AppendText(CreateLink(ParaEl, ResolveLinkWithinPackage(El,0)),AName);
AppendText(ParaEl, ']');
end;
begin
TableEl := CreateEl(BodyElement, 'table');
TableEl['cellpadding'] := '4';
TableEl['cellspacing'] := '0';
TableEl['border'] := '0';
TableEl['width'] := '100%';
TableEl['class'] := 'bar';
TREl := CreateTR(TableEl);
ParaEl := CreateEl(CreateTD(TREl), 'b');
If Assigned(Topic.Previous) then
AddLink(Topic.Previous,SDocPrevious);
If Assigned(Topic.Parent) then
AddLink(Topic.Parent,SDocUp);
if Assigned(Topic.Next) then
AddLink(Topic.Next,SDocNext);
if Length(SearchPage) > 0 then
begin
AppendText(ParaEl, '[');
AppendText(CreateLink(ParaEl, SearchPage), SDocSearch);
AppendText(ParaEl, ']');
end;
ParaEl := CreateTD(TREl);
ParaEl['align'] := 'right';
TitleEl := CreateEl(ParaEl, 'span');
TitleEl['class'] := 'bartitle';
if Assigned(Module) then
AppendText(TitleEl, Format(SDocUnitTitle, [Module.Name]));
if Assigned(Package) then
begin
AppendText(TitleEl, ' (');
AppendHyperlink(TitleEl, Package);
AppendText(TitleEl, ')');
end;
end;
procedure THTMLWriter.AppendMenuBar(ASubpageIndex: Integer);
var
TableEl, TREl, ParaEl, TitleEl: TDOMElement;
procedure AddLink(ALinkSubpageIndex: Integer; const AName: String);
begin
AppendText(ParaEl, '[');
if ALinkSubpageIndex = ASubpageIndex then
AppendText(ParaEl, AName)
else
AppendText(
CreateLink(ParaEl, ResolveLinkWithinPackage(Module, ALinkSubpageIndex)),
AName);
AppendText(ParaEl, ']');
end;
begin
TableEl := CreateEl(BodyElement, 'table');
TableEl['cellpadding'] := '4';
TableEl['cellspacing'] := '0';
TableEl['border'] := '0';
TableEl['width'] := '100%';
TableEl['class'] := 'bar';
TREl := CreateTR(TableEl);
ParaEl := CreateEl(CreateTD(TREl), 'b');
if Assigned(Module) then
begin
AddLink(0, SDocOverview);
if Module.InterfaceSection.ResStrings.Count > 0 then
AddLink(ResstrSubindex, SDocResStrings);
if Module.InterfaceSection.Consts.Count > 0 then
AddLink(ConstsSubindex, SDocConstants);
if Module.InterfaceSection.Types.Count > 0 then
AddLink(TypesSubindex, SDocTypes);
if Module.InterfaceSection.Classes.Count > 0 then
AddLink(ClassesSubindex, SDocClasses);
if Module.InterfaceSection.Functions.Count > 0 then
AddLink(ProcsSubindex, SDocProceduresAndFunctions);
if Module.InterfaceSection.Variables.Count > 0 then
AddLink(VarsSubindex, SDocVariables);
end;
if Length(SearchPage) > 0 then
begin
AppendText(ParaEl, '[');
AppendText(CreateLink(ParaEl, SearchPage), SDocSearch);
AppendText(ParaEl, ']');
end;
ParaEl := CreateTD(TREl);
ParaEl['align'] := 'right';
TitleEl := CreateEl(ParaEl, 'span');
TitleEl['class'] := 'bartitle';
if Assigned(Module) then
AppendText(TitleEl, Format(SDocUnitTitle, [Module.Name]));
if Assigned(Package) then
begin
AppendText(TitleEl, ' (');
AppendHyperlink(TitleEl, Package);
AppendText(TitleEl, ')');
end;
end;
procedure THTMLWriter.AppendSourceRef(AElement: TPasElement);
begin
AppendText(CreatePara(BodyElement), Format(SDocSourcePosition,
[ExtractFileName(AElement.SourceFilename), AElement.SourceLinenumber]));
end;
Procedure THTMLWriter.AppendSeeAlsoSection(AElement : TPasElement;DocNode : TDocNode);
var
Node: TDOMNode;
TableEl, El, TREl, TDEl, ParaEl, NewEl, DescrEl: TDOMElement;
l,s: String;
f: Text;
IsFirstSeeAlso : Boolean;
begin
if Not (Assigned(DocNode) and Assigned(DocNode.SeeAlso)) then
Exit;
IsFirstSeeAlso := True;
Node:=DocNode.SeeAlso.FirstChild;
While Assigned(Node) do
begin
if (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='link') then
begin
if IsFirstSeeAlso then
begin
IsFirstSeeAlso := False;
AppendText(CreateH2(BodyElement), SDocSeeAlso);
TableEl := CreateTable(BodyElement);
end;
El:=TDOMElement(Node);
TREl:=CreateTR(TableEl);
ParaEl:=CreatePara(CreateTD_vtop(TREl));
l:=El['id'];
s:= ResolveLinkID(l);
if Length(s)=0 then
begin
WriteLn(Format(SErrUnknownLinkID, [l]));
NewEl := CreateEl(ParaEl,'b')
end
else
NewEl := CreateLink(ParaEl,s);
AppendText(NewEl,El['id']);
l:=El['id'];
DescrEl := Engine.FindShortDescr(AElement.GetModule,L);
if Assigned(DescrEl) then
begin
AppendNbSp(CreatePara(CreateTD(TREl)), 2);
ParaEl := CreatePara(CreateTD(TREl));
ParaEl['class'] := 'cmt';
PushOutputNode(ParaEl);
try
ConvertShort(AElement, DescrEl);
finally
PopOutputNode;
end;
end;
end; // Link node
Node := Node.NextSibling;
end; // While
end;
Procedure THTMLWriter.AppendExampleSection(AElement : TPasElement;DocNode : TDocNode);
var
Node: TDOMNode;
// TableEl, El, TREl, TDEl, ParaEl, NewEl, DescrEl: TDOMElement;
s: String;
f: Text;
begin
if not (Assigned(DocNode) and Assigned(DocNode.FirstExample)) then
Exit;
Node := DocNode.FirstExample;
while Assigned(Node) do
begin
if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'example') then
begin
AppendText(CreateH2(BodyElement), SDocExample);
try
Assign(f, Engine.GetExampleFilename(TDOMElement(Node)));
Reset(f);
try
PushOutputNode(BodyElement);
DescrBeginCode(False, TDOMElement(Node)['highlighter']);
while not EOF(f) do
begin
ReadLn(f, s);
DescrWriteCodeLine(s);
end;
DescrEndCode;
PopOutputNode;
finally
Close(f);
end;
except
on e: Exception do
begin
e.Message := '[example] ' + e.Message;
raise;
end;
end;
end;
Node := Node.NextSibling;
end;
end;
procedure THTMLWriter.AppendFooter;
begin
if FooterFile<>'' then
ReadXMLFragment(BodyElement, FooterFile);
end;
procedure THTMLWriter.FinishElementPage(AElement: TPasElement);
var
DocNode: TDocNode;
begin
DocNode := Engine.FindDocNode(AElement);
If Assigned(DocNode) then
begin
// Description
if Assigned(DocNode.Descr) then
AppendDescrSection(AElement, BodyElement, DocNode.Descr, SDocDescription);
// Append "Errors" section
if Assigned(DocNode.ErrorsDoc) then
AppendDescrSection(AElement, BodyElement, DocNode.ErrorsDoc, SDocErrors);
// Append "See also" section
AppendSeeAlsoSection(AElement,DocNode);
// Append examples, if present
AppendExampleSection(AElement,DocNode);
end;
end;
Procedure THTMLWriter.CreateTopicPageBody(AElement : TTopicElement);
var
DocNode: TDocNode;
TableEl, TREl: TDOMElement;
I : Integer;
S : String;
begin
AppendTopicMenuBar(AElement);
DocNode:=AElement.TopicNode;
if Assigned(DocNode) then // should always be true, but we're being careful.
begin
AppendShortDescr(AElement,TitleElement, DocNode);
AppendShortDescr(AElement,CreateH2(BodyElement), DocNode);
if Assigned(DocNode.Descr) then
AppendDescrSection(AElement, BodyElement, DocNode.Descr, '');
AppendSeeAlsoSection(AElement,DocNode);
CreateTopicLinks(DocNode,AElement);
AppendExampleSection(AElement,DocNode);
end;
end;
procedure THTMLWriter.CreatePageBody(AElement: TPasElement;
ASubpageIndex: Integer);
var
i: Integer;
Element: TPasElement;
begin
CurDirectory := Allocator.GetFilename(AElement, ASubpageIndex);
i := Length(CurDirectory);
while (i > 0) and not (CurDirectory[i] in DirSeparators) do
Dec(i);
CurDirectory := Copy(CurDirectory, 1, i);
BaseDirectory := Allocator.GetRelativePathToTop(AElement);
if AElement.ClassType = TPasPackage then
CreatePackagePageBody
else
begin
Element := AElement;
while (Element<>Nil) and (Element.ClassType<>TPasModule) do
Element := Element.Parent;
Module := TPasModule(Element);
if AElement.ClassType = TPasModule then
CreateModulePageBody(TPasModule(AElement), ASubpageIndex)
else if AElement.Parent.InheritsFrom(TPasClassType) then
CreateClassMemberPageBody(AElement)
else if AElement.ClassType = TPasConst then
CreateConstPageBody(TPasConst(AElement))
else if AElement.InheritsFrom(TPasClassType) then
CreateClassPageBody(TPasClassType(AElement), ASubpageIndex)
else if AElement.InheritsFrom(TPasType) then
CreateTypePageBody(TPasType(AElement))
else if AElement.ClassType = TPasVariable then
CreateVarPageBody(TPasVariable(AElement))
else if AElement.InheritsFrom(TPasProcedureBase) then
CreateProcPageBody(TPasProcedure(AElement))
else if AElement.ClassType = TTopicELement then
CreateTopicPageBody(TTopicElement(AElement))
end;
end;
procedure THTMLWriter.CreatePackagePageBody;
var
DocNode: TDocNode;
TableEl, TREl: TDOMElement;
i: Integer;
ThisModule: TPasModule;
L : TStringList;
begin
AppendMenuBar(0);
AppendTitle(Format(SDocPackageTitle, [Copy(Package.Name, 2, 256)]));
AppendShortDescr(CreatePara(BodyElement), Package);
AppendText(CreateH2(BodyElement), SDocUnits);
TableEl := CreateTable(BodyElement);
L:=TStringList.Create;
Try
L.Sorted:=True;
// Sort modules.
For I:=0 to Package.Modules.Count-1 do
L.AddObject(TPasModule(Package.Modules[i]).Name,TPasModule(Package.Modules[i]));
// Now create table.
for i:=0 to L.Count - 1 do
begin
ThisModule := TPasModule(L.Objects[i]);
TREl := CreateTR(TableEl);
AppendHyperlink(CreateCode(CreatePara(CreateTD_vtop(TREl))), ThisModule);
AppendShortDescrCell(TREl, ThisModule);
end;
Finally
L.Free;
end;
DocNode := Engine.FindDocNode(Package);
if Assigned(DocNode) then
begin
if Assigned(DocNode.Descr) then
AppendDescrSection(nil, BodyElement, DocNode.Descr, SDocDescription);
CreateTopicLinks(DocNode,Package);
end;
end;
Procedure THTMLWriter.CreateTopicLinks(Node : TDocNode; PasElement : TPasElement);
var
DocNode: TDocNode;
TableEl, TREl: TDOMElement;
First : Boolean;
ThisTopic: TPasElement;
begin
DocNode:=Node.FirstChild;
First:=True;
While Assigned(DocNode) do
begin
If DocNode.TopicNode then
begin
if first then
begin
First:=False;
AppendText(CreateH2(BodyElement), SDocRelatedTopics);
TableEl := CreateTable(BodyElement);
end;
TREl := CreateTR(TableEl);
ThisTopic:=FindTopicElement(DocNode);
if Assigned(ThisTopic) then
AppendHyperlink(CreateCode(CreatePara(CreateTD_vtop(TREl))), ThisTopic);
AppendShortDescrCell(TREl, ThisTopic);
end;
DocNode:=DocNode.NextSibling;
end;
end;
procedure THTMLWriter.CreateModulePageBody(AModule: TPasModule;
ASubpageIndex: Integer);
procedure CreateMainPage;
var
TableEl, TREl, TDEl, CodeEl: TDOMElement;
i: Integer;
UnitRef: TPasType;
DocNode: TDocNode;
begin
AppendMenuBar(0);
AppendTitle(Format(SDocUnitTitle, [AModule.Name]));
AppendShortDescr(CreatePara(BodyElement), AModule);
if AModule.InterfaceSection.UsesList.Count > 0 then
begin
TableEl := CreateTable(BodyElement);
AppendKw(CreateCode(CreatePara(CreateTD(CreateTR(TableEl)))), 'uses');
for i := 0 to AModule.InterfaceSection.UsesList.Count - 1 do
begin
UnitRef := TPasType(AModule.InterfaceSection.UsesList[i]);
DocNode := Engine.FindDocNode(UnitRef);
if Assigned(DocNode) and DocNode.IsSkipped then
continue;
TREl := CreateTR(TableEl);
TDEl := CreateTD_vtop(TREl);
CodeEl := CreateCode(CreatePara(TDEl));
AppendNbSp(CodeEl, 2);
AppendHyperlink(CodeEl, UnitRef);
if i < AModule.InterfaceSection.UsesList.Count - 1 then
AppendSym(CodeEl, ',')
else
AppendSym(CodeEl, ';');
AppendText(CodeEl, ' '); // Space for descriptions
AppendShortDescrCell(TREl, UnitRef);
end;
end;
DocNode := Engine.FindDocNode(AModule);
if Assigned(DocNode) then
begin
if Assigned(DocNode.Descr) then
AppendDescrSection(AModule, BodyElement, DocNode.Descr, SDocOverview);
CreateTopicLinks(DocNode,AModule);
end;
end;
procedure CreateSimpleSubpage(const ATitle: DOMString; AList: TList);
var
TableEl, TREl, TDEl, CodeEl: TDOMElement;
i, j: Integer;
Decl: TPasElement;
SortedList: TList;
DocNode: TDocNode;
S : String;
begin
AppendMenuBar(ASubpageIndex);
S:=ATitle;
AppendTitle(Format(SDocUnitTitle + ': %s', [AModule.Name, S]));
SortedList := TList.Create;
try
for i := 0 to AList.Count - 1 do
begin
Decl := TPasElement(AList[i]);
DocNode := Engine.FindDocNode(Decl);
if (not Assigned(DocNode)) or (not DocNode.IsSkipped) then
begin
j := 0;
while (j < SortedList.Count) and (CompareText(
TPasElement(SortedList[j]).PathName, Decl.PathName) < 0) do
Inc(j);
SortedList.Insert(j, Decl);
end;
end;
TableEl := CreateTable(BodyElement);
for i := 0 to SortedList.Count - 1 do
begin
Decl := TPasElement(SortedList[i]);
TREl := CreateTR(TableEl);
CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
AppendHyperlink(CodeEl, Decl);
AppendShortDescrCell(TREl, Decl);
end;
finally
SortedList.Free;
end;
end;
procedure CreateResStringsPage;
var
ParaEl: TDOMElement;
i, j: Integer;
Decl: TPasResString;
DocNode: TDocNode;
begin
AppendMenuBar(ResstrSubindex);
AppendTitle(Format(SDocUnitTitle + ': %s', [AModule.Name, SDocResStrings]));
for i := 0 to AModule.InterfaceSection.ResStrings.Count - 1 do
begin
Decl := TPasResString(AModule.InterfaceSection.ResStrings[i]);
CreateEl(BodyElement, 'a')['name'] := LowerCase(Decl.Name);
ParaEl := CreatePara(BodyElement);
AppendText(CreateCode(ParaEl), Decl.Name);
CreateEl(ParaEl, 'br');
AppendText(ParaEl, Decl.Value);
end;
end;
begin
case ASubpageIndex of
0:
CreateMainPage;
ResstrSubindex:
CreateResStringsPage;
ConstsSubindex:
CreateSimpleSubpage(SDocConstants, AModule.InterfaceSection.Consts);
TypesSubindex:
CreateSimpleSubpage(SDocTypes, AModule.InterfaceSection.Types);
ClassesSubindex:
CreateSimpleSubpage(SDocClasses, AModule.InterfaceSection.Classes);
ProcsSubindex:
CreateSimpleSubpage(SDocProceduresAndFunctions, AModule.InterfaceSection.Functions);
VarsSubindex:
CreateSimpleSubpage(SDocVariables, AModule.InterfaceSection.Variables);
end;
end;
procedure THTMLWriter.CreateConstPageBody(AConst: TPasConst);
var
TableEl, CodeEl: TDOMElement;
begin
AppendMenuBar(-1);
AppendTitle(AConst.Name);
AppendShortDescr(CreatePara(BodyElement), AConst);
AppendText(CreateH2(BodyElement), SDocDeclaration);
AppendSourceRef(AConst);
TableEl := CreateTable(BodyElement);
CodeEl := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
AppendKw(CodeEl, 'const');
AppendText(CodeEl, ' ' + AConst.Name);
if Assigned(AConst.VarType) then
begin
AppendSym(CodeEl, ': ');
AppendType(CodeEl, TableEl, AConst.VarType, False);
end;
AppendPasSHFragment(CodeEl, ' = ' + AConst.Value + ';', 0);
FinishElementPage(AConst);
end;
procedure THTMLWriter.CreateTypePageBody(AType: TPasType);
var
TableEl, TREl, TDEl, CodeEl: TDOMElement;
DocNode: TDocNode;
i: Integer;
s: String;
EnumType: TPasEnumType;
EnumValue: TPasEnumValue;
Variable: TPasVariable;
begin
AppendMenuBar(-1);
AppendTitle(AType.Name);
AppendShortDescr(CreatePara(BodyElement), AType);
AppendText(CreateH2(BodyElement), SDocDeclaration);
AppendSourceRef(AType);
TableEl := CreateTable(BodyElement);
TREl := CreateTR(TableEl);
TDEl := CreateTD(TREl);
CodeEl := CreateCode(CreatePara(TDEl));
DocNode := Engine.FindDocNode(AType);
AppendKw(CodeEl, 'type ');
AppendText(CodeEl, AType.Name);
AppendSym(CodeEl, ' = ');
If Assigned(DocNode) and
Assigned(DocNode.Node) and
(Docnode.Node['opaque']='1') then
AppendText(CodeEl,SDocOpaque)
else
begin
// Alias
if AType.ClassType = TPasAliasType then
begin
if Assigned(TPasAliasType(AType).DestType) then
AppendHyperlink(CodeEl, TPasAliasType(AType).DestType)
else
AppendText(CreateWarning(CodeEl), '<Destination type is NIL>');
AppendSym(CodeEl, ';');
end else
// Class of
if AType.ClassType = TPasClassOfType then
begin
AppendKw(CodeEl, 'class of ');
AppendHyperlink(CodeEl, TPasClassOfType(AType).DestType);
AppendSym(CodeEl, ';');
end else
// Enumeration
if AType.ClassType = TPasEnumType then
begin
AppendSym(CodeEl, '(');
for i := 0 to TPasEnumType(AType).Values.Count - 1 do
begin
EnumValue := TPasEnumValue(TPasEnumType(AType).Values[i]);
TREl := CreateTR(TableEl);
CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
AppendShortDescrCell(TREl, EnumValue);
AppendNbSp(CodeEl, 2);
s := EnumValue.Name;
if EnumValue.IsValueUsed then
s := s + ' = ' + IntToStr(EnumValue.Value);
if i < TPasEnumType(AType).Values.Count - 1 then
s := s + ',';
AppendPasSHFragment(CodeEl, s, 0);
end;
AppendSym(CreateCode(CreatePara(CreateTD(CreateTR(TableEl)))), ');');
end else
// Pointer type
if AType.ClassType = TPasPointerType then
begin
AppendSym(CodeEl, '^');
if Assigned(TPasPointerType(AType).DestType) then
AppendHyperlink(CodeEl, TPasPointerType(AType).DestType)
else
AppendText(CreateWarning(CodeEl), '<Destination type is NIL>');
AppendSym(CodeEl, ';');
end else
if AType.InheritsFrom(TPasProcedureType) then
begin
AppendSym(AppendType(CodeEl, TableEl, TPasType(AType), True), ';');
AppendProcArgsSection(BodyElement, TPasProcedureType(AType));
end else
// Record
if AType.ClassType = TPasRecordType then
begin
if TPasRecordType(AType).IsPacked then
AppendKw(CodeEl, 'packed record')
else
AppendKw(CodeEl, 'record');
for i := 0 to TPasRecordType(AType).Members.Count - 1 do
begin
Variable := TPasVariable(TPasRecordType(AType).Members[i]);
TREl := CreateTR(TableEl);
CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
AppendShortDescrCell(TREl, Variable);
AppendNbSp(CodeEl, 2);
AppendText(CodeEl, Variable.Name);
AppendSym(CodeEl, ': ');
AppendType(CodeEl, TableEl, Variable.VarType, False);
AppendSym(CodeEl, ';');
end;
CodeEl := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
AppendText(CodeEl, ' '); // !!!: Dirty trick, necessary for current XML writer
AppendKw(CodeEl, 'end');
AppendSym(CodeEl, ';');
end else
// Set
if AType.ClassType = TPasSetType then
begin
AppendKw(CodeEl, 'set of ');
if TPasSetType(AType).EnumType.ClassType = TPasEnumType then
begin
AppendSym(CodeEl, '(');
EnumType := TPasEnumType(TPasSetType(AType).EnumType);
for i := 0 to EnumType.Values.Count - 1 do
begin
EnumValue := TPasEnumValue(EnumType.Values[i]);
TREl := CreateTR(TableEl);
CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
AppendShortDescrCell(TREl, EnumValue);
AppendNbSp(CodeEl, 2);
s := EnumValue.Name;
if EnumValue.IsValueUsed then
s := s + ' = ' + IntToStr(EnumValue.Value);
if i < EnumType.Values.Count - 1 then
s := s + ',';
AppendPasSHFragment(CodeEl, s, 0);
end;
AppendSym(CreateCode(CreatePara(CreateTD(CreateTR(TableEl)))), ');');
end else
begin
AppendHyperlink(CodeEl, TPasSetType(AType).EnumType);
AppendSym(CodeEl, ';');
end;
end else
// Type alias
if AType.ClassType = TPasTypeAliasType then
begin
AppendKw(CodeEl, 'type ');
AppendHyperlink(CodeEl, TPasTypeAliasType(AType).DestType);
AppendSym(CodeEl, ';');
end else
// Probably one of the simple types, which allowed in other places as wel...
AppendSym(AppendType(CodeEl, TableEl, TPasType(AType), True), ';');
end;
FinishElementPage(AType);
end;
function PropertyFilter(AMember: TPasElement): Boolean;
begin
Result := (AMember.ClassType = TPasProperty) and
(Copy(AMember.Name, 1, 2) <> 'On');
end;
function MethodFilter(AMember: TPasElement): Boolean;
begin
Result := AMember.InheritsFrom(TPasProcedureBase);
end;
function EventFilter(AMember: TPasElement): Boolean;
begin
Result := (AMember.ClassType = TPasProperty) and
(Copy(AMember.Name, 1, 2) = 'On');
end;
procedure THTMLWriter.CreateClassPageBody(AClass: TPasClassType;
ASubpageIndex: Integer);
type
TMemberFilter = function(AMember: TPasElement): Boolean;
var
ParaEl: TDOMElement;
procedure AppendMemberListLink(AListSubpageIndex: Integer;
const AText: DOMString);
var
LinkEl: TDOMElement;
begin
AppendText(ParaEl, '[');
LinkEl := CreateEl(ParaEl, 'a');
LinkEl['href'] :=
FixHtmlPath(ResolveLinkWithinPackage(AClass, AListSubpageIndex));
LinkEl['onClick'] := 'window.open(''' + LinkEl['href'] + ''', ''list'', ' +
'''dependent=yes,resizable=yes,scrollbars=yes,height=400,width=300''); return false;';
AppendText(LinkEl, AText);
AppendText(ParaEl, ' (');
LinkEl := CreateEl(ParaEl, 'a');
LinkEl['href'] :=
FixHtmlPath(ResolveLinkWithinPackage(AClass, AListSubpageIndex + 1));
LinkEl['onClick'] := 'window.open(''' + LinkEl['href'] + ''', ''list'', ' +
'''dependent=yes,resizable=yes,scrollbars=yes,height=400,width=300''); return false;';
AppendText(LinkEl, SDocByName);
AppendText(ParaEl, ')');
AppendText(ParaEl, '] ');
end;
procedure CreateMainPage;
var
TableEl, TREl, TDEl, CodeEl: TDOMElement;
DocNode: TDocNode;
Member: TPasElement;
CurVisibility: TPasMemberVisibility;
i: Integer;
s: String;
ThisClass: TPasClassType;
HaveSeenTObject: Boolean;
begin
AppendMenuBar(-1);
AppendTitle(AClass.Name);
ParaEl := CreatePara(BodyElement);
AppendMemberListLink(PropertiesByInheritanceSubindex, SDocProperties);
AppendMemberListLink(MethodsByInheritanceSubindex, SDocMethods);
AppendMemberListLink(EventsByInheritanceSubindex, SDocEvents);
AppendShortDescr(CreatePara(BodyElement), AClass);
AppendText(CreateH2(BodyElement), SDocDeclaration);
AppendSourceRef(AClass);
TableEl := CreateTable(BodyElement);
TREl := CreateTR(TableEl);
TDEl := CreateTD(TREl);
CodeEl := CreateCode(CreatePara(TDEl));
AppendKw(CodeEl, 'type');
AppendText(CodeEl, ' ' + AClass.Name + ' ');
AppendSym(CodeEl, '=');
AppendText(CodeEl, ' ');
AppendKw(CodeEl, ObjKindNames[AClass.ObjKind]);
if Assigned(AClass.AncestorType) then
begin
AppendSym(CodeEl, '(');
AppendHyperlink(CodeEl, AClass.AncestorType);
AppendSym(CodeEl, ')');
end;
if AClass.Members.Count > 0 then
begin
CurVisibility := visDefault;
for i := 0 to AClass.Members.Count - 1 do
begin
Member := TPasElement(AClass.Members[i]);
if CurVisibility <> Member.Visibility then
begin
CurVisibility := Member.Visibility;
if ((CurVisibility = visPrivate) and Engine.HidePrivate) or
((CurVisibility = visProtected) and Engine.HideProtected) then
continue;
case CurVisibility of
visPrivate: s := 'private';
visProtected: s := 'protected';
visPublic: s := 'public';
visPublished: s := 'published';
visAutomated: s := 'automated';
end;
AppendKw(CreateCode(CreatePara(CreateTD(CreateTR(TableEl)))), s);
end else
if ((CurVisibility = visPrivate) and Engine.HidePrivate) or
((CurVisibility = visProtected) and Engine.HideProtected) then
continue;
TREl := CreateTR(TableEl);
CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
AppendNbSp(CodeEl, 2);
AppendShortDescrCell(TREl, Member);
if Member.InheritsFrom(TPasProcedureBase) then
begin
AppendKw(CodeEl, TPasProcedureBase(Member).TypeName + ' ');
AppendHyperlink(CodeEl, Member);
if (Member.ClassType = TPasOverloadedProc) or
(TPasProcedure(Member).ProcType.Args.Count > 0) then
AppendSym(CodeEl, '();')
else
AppendSym(CodeEl, ';');
if Member.ClassType <> TPasOverloadedProc then
AppendProcExt(CodeEl, TPasProcedure(Member));
end else
if Member.ClassType = TPasVariable then
begin
AppendHyperlink(CodeEl, Member);
AppendSym(CodeEl, ': ');
AppendHyperlink(CodeEl, TPasVariable(Member).VarType);
AppendSym(CodeEl, ';');
end else
if Member.ClassType = TPasProperty then
begin
AppendKw(CodeEl, 'property ');
AppendHyperlink(CodeEl, Member);
if Assigned(TPasProperty(Member).VarType) then
begin
AppendSym(CodeEl, ': ');
AppendHyperlink(CodeEl, TPasProperty(Member).VarType);
end;
AppendSym(CodeEl, ';');
if TPasProperty(Member).IsDefault then
begin
AppendKw(CodeEl, ' default');
AppendSym(CodeEl, ';');
end;
SetLength(s, 0);
if Length(TPasProperty(Member).ReadAccessorName) > 0 then
s := s + 'r';
if Length(TPasProperty(Member).WriteAccessorName) > 0 then
s := s + 'w';
if Length(TPasProperty(Member).StoredAccessorName) > 0 then
s := s + 's';
if Length(s) > 0 then
AppendText(CodeEl, ' [' + s + ']');
end else
AppendText(CreateWarning(CodeEl), '<' + Member.ClassName + '>');
end;
CodeEl := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
end;
AppendText(CodeEl, ' '); // !!!: Dirty trick, necessary for current XML writer
AppendKw(CodeEl, 'end');
AppendSym(CodeEl, ';');
AppendText(CreateH2(BodyElement), SDocInheritance);
TableEl := CreateTable(BodyElement);
HaveSeenTObject := AClass.ObjKind <> okClass;
ThisClass := AClass;
while True do
begin
TREl := CreateTR(TableEl);
TDEl := CreateTD_vtop(TREl);
TDEl['align'] := 'center';
CodeEl := CreateCode(CreatePara(TDEl));
AppendHyperlink(CodeEl, ThisClass);
AppendShortDescrCell(TREl, ThisClass);
if HaveSeenTObject or (CompareText(ThisClass.Name, 'TObject') = 0) then
HaveSeenTObject := True
else
begin
TDEl := CreateTD(CreateTR(TableEl));
TDEl['align'] := 'center';
AppendText(TDEl, '|');
end;
if Assigned(ThisClass.AncestorType) then
begin
if ThisClass.AncestorType.InheritsFrom(TPasClassType) then
ThisClass := TPasClassType(ThisClass.AncestorType)
else
begin
TDEl := CreateTD(CreateTR(TableEl));
TDEl['align'] := 'center';
AppendText(CreateCode(CreatePara(TDEl)), ThisClass.AncestorType.Name);
if CompareText(ThisClass.AncestorType.Name, 'TObject') = 0 then
HaveSeenTObject := True
else
begin
TDEl := CreateTD(CreateTR(TableEl));
TDEl['align'] := 'center';
AppendText(TDEl, '?');
end;
break;
end
end else
break;
end;
if not HaveSeenTObject then
begin
TDEl := CreateTD(CreateTR(TableEl));
TDEl['align'] := 'center';
AppendText(CreateCode(CreatePara(TDEl)), 'TObject');
end;
FinishElementPage(AClass);
end;
procedure CreateInheritanceSubpage(AFilter: TMemberFilter);
var
ThisClass: TPasClassType;
i: Integer;
Member: TPasElement;
TableEl, TREl, TDEl, ParaEl, LinkEl: TDOMElement;
begin
TableEl := CreateTable(BodyElement);
ThisClass := AClass;
while True do
begin
TREl := CreateTR(TableEl);
TDEl := CreateTD(TREl);
TDEl['colspan'] := '3';
CreateTD(TREl);
LinkEl := AppendHyperlink(CreateEl(CreateCode(CreatePara(TDEl)), 'b'), ThisClass);
if Assigned(LinkEl) then
LinkEl['onClick'] := 'opener.location.href = ''' + LinkEl['href'] +
'''; return false;';
for i := 0 to ThisClass.Members.Count - 1 do
begin
Member := TPasElement(ThisClass.Members[i]);
if ((Member.Visibility = visPrivate) and Engine.HidePrivate) or
((Member.Visibility = visProtected) and Engine.HideProtected) or
not AFilter(Member) then
continue;
TREl := CreateTR(TableEl);
ParaEl := CreatePara(CreateTD(TREl));
case Member.Visibility of
visPrivate:
AppendText(ParaEl, 'pv');
visProtected:
AppendText(ParaEl, 'pt');
visPublished:
AppendText(ParaEl, 'pl');
end;
AppendNbSp(ParaEl, 1);
ParaEl := CreateTD(TREl);
if (Member.ClassType = TPasProperty) and
(Length(TPasProperty(Member).WriteAccessorName) = 0) then
begin
AppendText(ParaEl, 'ro');
AppendNbSp(ParaEl, 1);
end;
LinkEl := AppendHyperlink(CreatePara(CreateTD(TREl)), Member);
if Assigned(LinkEl) then
LinkEl['onClick'] := 'opener.location.href = ''' + LinkEl['href'] +
'''; return false;';
end;
if (not Assigned(ThisClass.AncestorType)) or
(not (ThisClass.AncestorType.ClassType = TPasClassType)) then
break;
ThisClass := TPasClassType(ThisClass.AncestorType);
AppendNbSp(CreatePara(CreateTD(CreateTR(TableEl))), 1);
end;
end;
procedure CreateSortedSubpage(AFilter: TMemberFilter);
var
List: TList;
ThisClass: TPasClassType;
i, j: Integer;
Member: TPasElement;
TableEl, TREl, TDEl, ParaEl, LinkEl: TDOMElement;
begin
List := TList.Create;
try
ThisClass := AClass;
while True do
begin
for i := 0 to ThisClass.Members.Count - 1 do
begin
Member := TPasElement(ThisClass.Members[i]);
if (not (((Member.Visibility = visPrivate) and Engine.HidePrivate) or
((Member.Visibility = visProtected) and Engine.HideProtected))) and
AFilter(Member) then
begin
j := 0;
while (j < List.Count) and
(CompareText(TPasElement(List[j]).Name, Member.Name) < 0) do
Inc(j);
List.Insert(j, Member);
end;
end;
if (not Assigned(ThisClass.AncestorType)) or
(not (ThisClass.AncestorType.ClassType = TPasClassType)) then
break;
ThisClass := TPasClassType(ThisClass.AncestorType);
end;
TableEl := CreateTable(BodyElement);
for i := 0 to List.Count - 1 do
begin
Member := TPasElement(List[i]);
TREl := CreateTR(TableEl);
ParaEl := CreatePara(CreateTD(TREl));
case Member.Visibility of
visPrivate:
AppendText(ParaEl, 'pv');
visProtected:
AppendText(ParaEl, 'pt');
visPublished:
AppendText(ParaEl, 'pl');
end;
AppendNbSp(ParaEl, 1);
ParaEl := CreatePara(CreateTD(TREl));
if (Member.ClassType = TPasProperty) and
(Length(TPasProperty(Member).WriteAccessorName) = 0) then
begin
AppendText(ParaEl, 'ro');
AppendNbSp(ParaEl, 1);
end;
TDEl := CreateTD(TREl);
TDEl['nowrap'] := 'nowrap';
ParaEl := CreatePara(TDEl);
LinkEl := AppendHyperlink(ParaEl, Member);
if Assigned(LinkEl) then
LinkEl['onClick'] := 'opener.location.href = ''' + LinkEl['href'] +
'''; return false;';
AppendText(ParaEl, ' (');
LinkEl := AppendHyperlink(ParaEl, Member.Parent);
if Assigned(LinkEl) then
LinkEl['onClick'] := 'opener.location.href = ''' + LinkEl['href'] +
'''; return false;';
AppendText(ParaEl, ')');
end;
finally
List.Free;
end;
end;
begin
case ASubpageIndex of
0:
CreateMainPage;
PropertiesByInheritanceSubindex:
CreateInheritanceSubpage(@PropertyFilter);
PropertiesByNameSubindex:
CreateSortedSubpage(@PropertyFilter);
MethodsByInheritanceSubindex:
CreateInheritanceSubpage(@MethodFilter);
MethodsByNameSubindex:
CreateSortedSubpage(@MethodFilter);
EventsByInheritanceSubindex:
CreateInheritanceSubpage(@EventFilter);
EventsByNameSubindex:
CreateSortedSubpage(@EventFilter);
end;
end;
procedure THTMLWriter.CreateClassMemberPageBody(AElement: TPasElement);
var
TableEl, TREl, CodeEl: TDOMElement;
procedure CreateVarPage(Element: TPasVariable);
begin
AppendHyperlink(CodeEl, Element.Parent);
AppendSym(CodeEl, '.');
AppendText(CodeEl, Element.Name);
if Assigned(Element.VarType) then
begin
AppendSym(CodeEl, ': ');
AppendSym(AppendType(CodeEl, TableEl, Element.VarType, False), ';');
end;
end;
procedure CreatePropertyPage(Element: TPasProperty);
var
NeedBreak: Boolean;
begin
AppendKw(CodeEl, 'property ');
AppendHyperlink(CodeEl, Element.Parent);
AppendSym(CodeEl, '.');
AppendText(CodeEl, Element.Name);
if Assigned(Element.VarType) then
begin
AppendSym(CodeEl, ': ');
AppendType(CodeEl, TableEl, Element.VarType, False);
end;
NeedBreak := False;
if Length(TPasProperty(Element).IndexValue) <> 0 then
begin
CreateEl(CodeEl, 'br');
AppendNbsp(CodeEl, 2);
AppendKw(CodeEl, 'index ');
AppendPasSHFragment(CodeEl, TPasProperty(Element).IndexValue, 0);
NeedBreak := True;
end;
if Length(TPasProperty(Element).ReadAccessorName) <> 0 then
begin
CreateEl(CodeEl, 'br');
AppendNbsp(CodeEl, 2);
AppendKw(CodeEl, 'read ');
AppendText(CodeEl, TPasProperty(Element).ReadAccessorName);
NeedBreak := True;
end;
if Length(TPasProperty(Element).WriteAccessorName) <> 0 then
begin
CreateEl(CodeEl, 'br');
AppendNbsp(CodeEl, 2);
AppendKw(CodeEl, 'write ');
AppendText(CodeEl, TPasProperty(Element).WriteAccessorName);
NeedBreak := True;
end;
if Length(TPasProperty(Element).StoredAccessorName) <> 0 then
begin
CreateEl(CodeEl, 'br');
AppendNbsp(CodeEl, 2);
AppendKw(CodeEl, 'stored ');
AppendText(CodeEl, TPasProperty(Element).StoredAccessorName);
NeedBreak := True;
end;
if Length(TPasProperty(Element).DefaultValue) <> 0 then
begin
CreateEl(CodeEl, 'br');
AppendNbsp(CodeEl, 2);
AppendKw(CodeEl, 'default ');
AppendPasSHFragment(CodeEl, TPasProperty(Element).DefaultValue, 0);
NeedBreak := True;
end;
AppendSym(CodeEl, ';');
if TPasProperty(Element).IsDefault or TPasProperty(Element).IsNodefault then
begin
if NeedBreak then
begin
CreateEl(CodeEl, 'br');
AppendNbsp(CodeEl, 2);
end;
if TPasProperty(Element).IsDefault then
AppendKw(CodeEl, 'default')
else
AppendKw(CodeEl, 'nodefault');
AppendSym(CodeEl, ';');
end;
end;
var
s: String;
DocNode: TDocNode;
begin
AppendMenuBar(-1);
AppendTitle(AElement.FullName);
AppendShortDescr(CreatePara(BodyElement), AElement);
AppendText(CreateH2(BodyElement), SDocDeclaration);
AppendSourceRef(AElement);
TableEl := CreateTable(BodyElement);
TREl := CreateTR(TableEl);
CodeEl := CreateCode(CreatePara(CreateTD(TREl)));
AppendText(CodeEl, ' '); // !!!: Workaround for current HTML writer
case AElement.Visibility of
visPrivate: s := 'private';
visProtected: s := 'protected';
visPublic: s := 'public';
visPublished: s := 'published';
visAutomated: s := 'automated';
else s := '';
end;
if Length(s) > 0 then
AppendKw(CodeEl, s);
AppendText(CodeEl, ' ');
if AElement.ClassType = TPasVariable then
CreateVarPage(TPasVariable(AElement))
else if AElement.InheritsFrom(TPasProcedureBase) then
AppendProcDecl(CodeEl, TableEl, TPasProcedureBase(AElement))
else if AElement.ClassType = TPasProperty then
CreatePropertyPage(TPasProperty(AElement))
else
AppendText(CreateWarning(BodyElement), '<' + AElement.ClassName + '>');
FinishElementPage(AElement);
end;
procedure THTMLWriter.CreateVarPageBody(AVar: TPasVariable);
var
TableEl, TREl, TDEl, CodeEl, El: TDOMElement;
DocNode: TDocNode;
begin
AppendMenuBar(-1);
AppendTitle(AVar.FullName);
AppendShortDescr(CreatePara(BodyElement), AVar);
AppendText(CreateH2(BodyElement), SDocDeclaration);
AppendSourceRef(AVar);
TableEl := CreateTable(BodyElement);
TREl := CreateTR(TableEl);
TDEl := CreateTD(TREl);
CodeEl := CreateCode(CreatePara(TDEl));
AppendKw(CodeEl, 'var');
AppendText(CodeEl, ' ' + AVar.Name);
if Assigned(AVar.VarType) then
begin
AppendSym(CodeEl, ': ');
El := AppendType(CodeEl, TableEl, AVar.VarType, False);
end else
El := CodeEl;
if Length(AVar.Value) > 0 then
AppendPasSHFragment(El, ' = ' + AVar.Value + ';', 0)
else
AppendSym(El, ';');
FinishElementPage(AVar);
end;
procedure THTMLWriter.CreateProcPageBody(AProc: TPasProcedureBase);
var
TableEl, TREl, TDEl, CodeEl: TDOMElement;
begin
AppendMenuBar(-1);
AppendTitle(AProc.Name);
AppendShortDescr(CreatePara(BodyElement), AProc);
AppendText(CreateH2(BodyElement), SDocDeclaration);
AppendSourceRef(AProc);
TableEl := CreateTable(BodyElement);
TREl := CreateTR(TableEl);
TDEl := CreateTD(TREl);
CodeEl := CreateCode(CreatePara(TDEl));
AppendProcDecl(CodeEl, TableEl, AProc);
FinishElementPage(AProc);
end;
Function THTMLWriter.InterPretOption(Const Cmd,Arg : String) : boolean;
begin
Result:=True;
if Cmd = '--html-search' then
SearchPage := Arg
else if Cmd = '--footer' then
FooterFile := Arg
else
Result:=False;
end;
procedure THTMLWriter.WriteDoc;
begin
WriteLn(Format(SWritingPages, [PageCount]));
WriteHTMLPages;
end;
procedure THTMLWriter.Usage(List: TStrings);
begin
List.add('--footer');
List.Add(SHTMLUsageFooter);
end;
// private methods
function THTMLWriter.GetPageCount: Integer;
begin
Result := PageInfos.Count;
end;
procedure THTMLWriter.SetOnTest(const AValue: TNotifyEvent);
begin
if FOnTest=AValue then exit;
FOnTest:=AValue;
end;
procedure THTMLWriter.CreateAllocator;
begin
FAllocator:=TLongNameFileAllocator.Create('.html');
end;
procedure THTMWriter.CreateAllocator;
begin
FAllocator:=TShortNameFileAllocator.Create('.htm');
end;
initialization
// Do not localize.
RegisterWriter(THTMLWriter,'html','HTML output using fpdoc.css stylesheet.');
RegisterWriter(THTMWriter,'htm','HTM (8.3 filenames) output using fpdoc.css stylesheet.');
finalization
UnRegisterWriter('html');
UnRegisterWriter('htm');
end.