dwriter.pp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296
  1. {
  2. FPDoc - Free Pascal Documentation Tool
  3. Copyright (C) 2000 - 2003 by
  4. Areca Systems GmbH / Sebastian Guenther, [email protected]
  5. 2005-2012 by
  6. various FPC contributors
  7. * Output string definitions
  8. * Basic writer (output generator) class
  9. See the file COPYING, included in this distribution,
  10. for details about the copyright.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. }
  15. unit dWriter;
  16. {$MODE objfpc}
  17. {$H+}
  18. {$WARN 5024 off : Parameter "$1" not used}
  19. interface
  20. uses Classes, DOM, dGlobals, PasTree, SysUtils, fpdocclasstree;
  21. resourcestring
  22. SErrFileWriting = 'An error occurred during writing of file "%s": %s';
  23. SErrInvalidShortDescr = 'Invalid short description';
  24. SErrInvalidDescr = 'Invalid description (illegal XML element: "%s")';
  25. SErrInvalidParaContent = 'Invalid paragraph content';
  26. SErrInvalidElementInList = 'Invalid element in list - only "li" allowed';
  27. SErrInvalidListContent = 'Invalid list content';
  28. SErrInvalidRemarkContent = 'Invalid <remark> content (illegal XML element: "%s")';
  29. SErrListIsEmpty = 'List is empty - need at least one "li" element';
  30. SErrInvalidDefinitionTermContent = 'Invalid content in definition term';
  31. SErrDefinitionEntryMissing = 'Definition entry after definition term is missing';
  32. SErrInvalidBorderValue = 'Invalid "border" value for %s';
  33. SErrInvalidTableContent = 'Invalid table content';
  34. SErrTableRowEmpty = 'Table row is empty (no "td" elements found)';
  35. SErrInvalidContentBeforeSectionTitle = 'Invalid content before section title';
  36. SErrSectionTitleExpected = 'Section title ("title" element) expected';
  37. SErrDescrTagUnknown = 'Warning: Unknown tag "%s" in description';
  38. SErrUnknownEntityReference = 'Warning: Unknown entity reference "&%s;" found';
  39. SErrUnknownLinkID = 'Warning: Target ID of <link> in unit "%s", element "%s", is unknown: "%s"';
  40. SErrUnknownPrintShortID = 'Warning: Target ID of <printshort> is unknown: "%s"';
  41. SErrUnknownLink = 'Could not resolve link to "%s"';
  42. SErralreadyRegistered = 'Class for output format "%s" already registered';
  43. SErrUnknownWriterClass = 'Unknown output format "%s"';
  44. type
  45. // Phony element for pas pages.
  46. TTopicElement = Class(TPaselement)
  47. TopicNode : TDocNode;
  48. Previous,
  49. Next : TPasElement;
  50. Subtopics : TList;
  51. Constructor Create(const AName: String; AParent: TPasElement); override;
  52. Destructor Destroy; override;
  53. end;
  54. TWriterLogEvent = Procedure(Sender : TObject; Const Msg : String) of object;
  55. TWriterNoteEvent = Procedure(Sender : TObject; Note : TDomElement; Var EmitNote : Boolean) of object;
  56. { TFPDocWriter }
  57. TFPDocWriter = class
  58. private
  59. FEmitNotes: Boolean;
  60. FEngine : TFPDocEngine;
  61. FPackage : TPasPackage;
  62. FContext : TPasElement;
  63. FTopics : TList;
  64. FImgExt : String;
  65. FBeforeEmitNote : TWriterNoteEvent;
  66. procedure ConvertURL(AContext: TPasElement; El: TDOMElement);
  67. procedure CreateClassTree;
  68. protected
  69. TreeClass: TClassTreeBuilder; // Global class tree
  70. TreeInterface: TClassTreeBuilder; // Global interface tree
  71. procedure AddElementsFromList(L: TStrings; List: TFPList; UsePathName : Boolean = False);
  72. Procedure DoLog(Const Msg : String);
  73. Procedure DoLog(Const Fmt : String; Args : Array of const);
  74. procedure Warning(AContext: TPasElement; const AMsg: String);
  75. procedure Warning(AContext: TPasElement; const AMsg: String;
  76. const Args: array of const);
  77. // function FindShortDescr(const Name: String): TDOMElement;
  78. // Description conversion
  79. function IsDescrNodeEmpty(Node: TDOMNode): Boolean;
  80. function IsExtShort(Node: TDOMNode): Boolean;
  81. function ConvertShort(AContext: TPasElement; El: TDOMElement): Boolean;
  82. function ConvertNotes(AContext: TPasElement; El: TDOMElement): Boolean; virtual;
  83. function ConvertBaseShort(AContext: TPasElement; Node: TDOMNode): Boolean;
  84. procedure ConvertBaseShortList(AContext: TPasElement; Node: TDOMNode;
  85. MayBeEmpty: Boolean);
  86. procedure ConvertLink(AContext: TPasElement; El: TDOMElement);
  87. function ConvertExtShort(AContext: TPasElement; Node: TDOMNode): Boolean;
  88. procedure ConvertDescr(AContext: TPasElement; El: TDOMElement;
  89. AutoInsertBlock: Boolean);
  90. function ConvertNonSectionBlock(AContext: TPasElement;
  91. Node: TDOMNode): Boolean;
  92. procedure ConvertExtShortOrNonSectionBlocks(AContext: TPasElement;
  93. Node: TDOMNode);
  94. function ConvertSimpleBlock(AContext: TPasElement; Node: TDOMNode): Boolean;
  95. Function FindTopicElement(Node : TDocNode): TTopicElement;
  96. Procedure ConvertImage(El : TDomElement);
  97. Procedure DescrEmitNotesHeader(AContext : TPasElement); virtual;
  98. Procedure DescrEmitNotesFooter(AContext : TPasElement); virtual;
  99. procedure DescrWriteText(const AText: DOMString); virtual; abstract;
  100. procedure DescrBeginBold; virtual; abstract;
  101. procedure DescrEndBold; virtual; abstract;
  102. procedure DescrBeginItalic; virtual; abstract;
  103. procedure DescrEndItalic; virtual; abstract;
  104. procedure DescrBeginUnderline; virtual; abstract;
  105. procedure DescrEndUnderline; virtual; abstract;
  106. procedure DescrBeginEmph; virtual; abstract;
  107. procedure DescrEndEmph; virtual; abstract;
  108. procedure DescrWriteImageEl(const AFileName, ACaption,ALinkName : DOMString); virtual;
  109. procedure DescrWriteFileEl(const AText: DOMString); virtual; abstract;
  110. procedure DescrWriteKeywordEl(const AText: DOMString); virtual; abstract;
  111. procedure DescrWriteVarEl(const AText: DOMString); virtual; abstract;
  112. procedure DescrBeginLink(const AId: DOMString); virtual; abstract;
  113. procedure DescrEndLink; virtual; abstract;
  114. procedure DescrBeginURL(const AURL: DOMString); virtual; abstract;
  115. procedure DescrEndURL; virtual; abstract;
  116. procedure DescrWriteLinebreak; virtual; abstract;
  117. procedure DescrBeginParagraph; virtual; abstract;
  118. procedure DescrEndParagraph; virtual; abstract;
  119. procedure DescrBeginCode(HasBorder: Boolean; const AHighlighterName: String); virtual; abstract;
  120. procedure DescrWriteCodeLine(const ALine: String); virtual; abstract;
  121. procedure DescrEndCode; virtual; abstract;
  122. procedure DescrBeginOrderedList; virtual; abstract;
  123. procedure DescrEndOrderedList; virtual; abstract;
  124. procedure DescrBeginUnorderedList; virtual; abstract;
  125. procedure DescrEndUnorderedList; virtual; abstract;
  126. procedure DescrBeginDefinitionList; virtual; abstract;
  127. procedure DescrEndDefinitionList; virtual; abstract;
  128. procedure DescrBeginListItem; virtual; abstract;
  129. procedure DescrEndListItem; virtual; abstract;
  130. procedure DescrBeginDefinitionTerm; virtual; abstract;
  131. procedure DescrEndDefinitionTerm; virtual; abstract;
  132. procedure DescrBeginDefinitionEntry; virtual; abstract;
  133. procedure DescrEndDefinitionEntry; virtual; abstract;
  134. procedure DescrBeginSectionTitle; virtual; abstract;
  135. procedure DescrBeginSectionBody; virtual; abstract;
  136. procedure DescrEndSection; virtual; abstract;
  137. procedure DescrBeginRemark; virtual; abstract;
  138. procedure DescrEndRemark; virtual; abstract;
  139. procedure DescrBeginTable(ColCount: Integer; HasBorder: Boolean); virtual; abstract;
  140. procedure DescrEndTable; virtual; abstract;
  141. procedure DescrBeginTableCaption; virtual; abstract;
  142. procedure DescrEndTableCaption; virtual; abstract;
  143. procedure DescrBeginTableHeadRow; virtual; abstract;
  144. procedure DescrEndTableHeadRow; virtual; abstract;
  145. procedure DescrBeginTableRow; virtual; abstract;
  146. procedure DescrEndTableRow; virtual; abstract;
  147. procedure DescrBeginTableCell; virtual; abstract;
  148. procedure DescrEndTableCell; virtual; abstract;
  149. Property CurrentContext : TPasElement Read FContext ;
  150. public
  151. Constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); virtual;
  152. destructor Destroy; override;
  153. property Engine : TFPDocEngine read FEngine;
  154. Property Package : TPasPackage read FPackage;
  155. Property Topics : TList Read FTopics;
  156. Property ImageExtension : String Read FImgExt Write FImgExt;
  157. // Should return True if option was succesfully interpreted.
  158. Function InterpretOption(Const Cmd,Arg : String) : Boolean; Virtual;
  159. Class Function FileNameExtension : String; virtual;
  160. Class Procedure Usage(List : TStrings); virtual;
  161. Class procedure SplitImport(var AFilename, ALinkPrefix: String); virtual;
  162. procedure WriteDoc; virtual; Abstract;
  163. Function WriteDescr(Element: TPasElement) : TDocNode;
  164. procedure WriteDescr(Element: TPasElement; DocNode: TDocNode);
  165. procedure WriteDescr(AContext: TPasElement; DescrNode: TDOMElement); virtual;
  166. Procedure FPDocError(Msg : String);
  167. Procedure FPDocError(Fmt : String; Args : Array of Const);
  168. Function ShowMember(M : TPasElement) : boolean;
  169. Procedure GetMethodList(ClassDecl: TPasClassType; List : TStringList);
  170. Property EmitNotes : Boolean Read FEmitNotes Write FEmitNotes;
  171. Property BeforeEmitNote : TWriterNoteEvent Read FBeforeEmitNote Write FBeforeEmitNote;
  172. end;
  173. TFPDocWriterClass = Class of TFPDocWriter;
  174. EFPDocWriterError = Class(Exception);
  175. // Register backend
  176. Procedure RegisterWriter(AClass : TFPDocWriterClass; Const AName,ADescr : String);
  177. // UnRegister backend
  178. Procedure UnRegisterWriter(Const AName : String);
  179. // Return back end class. Exception if not found.
  180. Function GetWriterClass(AName : String) : TFPDocWriterClass;
  181. // Return index of back end class.
  182. Function FindWriterClass(AName : String) : Integer;
  183. // List of backend in name=descr form.
  184. Procedure EnumWriters(List : TStrings);
  185. implementation
  186. { ---------------------------------------------------------------------
  187. Writer registration
  188. ---------------------------------------------------------------------}
  189. Type
  190. { TWriterRecord }
  191. TWriterRecord = Class(TObject)
  192. Private
  193. FClass : TFPDocWriterClass;
  194. FName : String;
  195. FDescription : String;
  196. Public
  197. Constructor Create (AClass : TFPDocWriterClass; Const AName,ADescr : String);
  198. end;
  199. { TWriterRecord }
  200. constructor TWriterRecord.Create(AClass: TFPDocWriterClass; const AName,
  201. ADescr: String);
  202. begin
  203. FClass:=AClass;
  204. FName:=AName;
  205. FDescription:=ADescr;
  206. end;
  207. Var
  208. Writers : TStringList;
  209. Procedure InitWriterList;
  210. begin
  211. Writers:=TStringList.Create;
  212. Writers.Sorted:=True;
  213. end;
  214. Procedure DoneWriterList;
  215. Var
  216. I : Integer;
  217. begin
  218. For I:=Writers.Count-1 downto 0 do
  219. Writers.Objects[i].Free;
  220. FreeAndNil(Writers);
  221. end;
  222. procedure RegisterWriter(AClass : TFPDocWriterClass; Const AName, ADescr : String);
  223. begin
  224. If Writers.IndexOf(AName)<>-1 then
  225. Raise EFPDocWriterError.CreateFmt(SErralreadyRegistered,[ANAme]);
  226. Writers.AddObject(AName,TWriterRecord.Create(AClass,AName,ADescr));
  227. end;
  228. function FindWriterClass(AName : String) : Integer;
  229. begin
  230. Result:=Writers.IndexOf(AName);
  231. end;
  232. function GetWriterClass(AName : String) : TFPDocWriterClass;
  233. Var
  234. Index : Integer;
  235. begin
  236. Index:=FindWriterClass(AName);
  237. If Index=-1 then
  238. Raise EFPDocWriterError.CreateFmt(SErrUnknownWriterClass,[ANAme]);
  239. Result:=(Writers.Objects[Index] as TWriterRecord).FClass;
  240. end;
  241. // UnRegister backend
  242. Procedure UnRegisterWriter(Const AName : String);
  243. Var
  244. Index : Integer;
  245. begin
  246. Index:=Writers.IndexOf(AName);
  247. If Index=-1 then
  248. Raise EFPDocWriterError.CreateFmt(SErrUnknownWriterClass,[ANAme]);
  249. Writers.Objects[Index].Free;
  250. Writers.Delete(Index);
  251. end;
  252. Procedure EnumWriters(List : TStrings);
  253. Var
  254. I : Integer;
  255. begin
  256. List.Clear;
  257. For I:=0 to Writers.Count-1 do
  258. With (Writers.Objects[I] as TWriterRecord) do
  259. List.Add(FName+'='+FDescription);
  260. end;
  261. function IsWhitespaceNode(Node: TDOMText): Boolean;
  262. var
  263. I,L: Integer;
  264. S: DOMString;
  265. P : PWideChar;
  266. begin
  267. S := Node.Data;
  268. Result := True;
  269. I:=0;
  270. L:=Length(S);
  271. P:=PWideChar(S);
  272. While Result and (I<L) do
  273. begin
  274. Result:=P^ in [#32,#10,#9,#13];
  275. Inc(P);
  276. Inc(I);
  277. end;
  278. end;
  279. { ---------------------------------------------------------------------
  280. TFPDocWriter
  281. ---------------------------------------------------------------------}
  282. {
  283. fmtIPF:
  284. begin
  285. if Length(Engine.Output) = 0 then
  286. WriteLn(SCmdLineOutputOptionMissing)
  287. else
  288. CreateIPFDocForPackage(Engine.Package, Engine);
  289. end;
  290. }
  291. constructor TFPDocWriter.Create ( APackage: TPasPackage; AEngine: TFPDocEngine
  292. ) ;
  293. begin
  294. inherited Create;
  295. FEngine := AEngine;
  296. FPackage := APackage;
  297. FTopics:=Tlist.Create;
  298. FImgExt:='.png';
  299. TreeClass:= TClassTreeBuilder.Create(FEngine, FPackage, okClass);
  300. TreeInterface:= TClassTreeBuilder.Create(FEngine, FPackage, okInterface);
  301. CreateClassTree;
  302. end;
  303. destructor TFPDocWriter.Destroy;
  304. Var
  305. i : integer;
  306. begin
  307. For I:=0 to FTopics.Count-1 do
  308. TTopicElement(FTopics[i]).Free;
  309. FTopics.Free;
  310. TreeClass.free;
  311. TreeInterface.Free;
  312. Inherited;
  313. end;
  314. function TFPDocWriter.InterpretOption(const Cmd, Arg: String): Boolean;
  315. begin
  316. Result:=False;
  317. end;
  318. class function TFPDocWriter.FileNameExtension: String;
  319. begin
  320. //Override in linear writers with the expected extension.
  321. Result := ''; //Output must not contain an extension.
  322. end;
  323. class procedure TFPDocWriter.Usage(List: TStrings);
  324. begin
  325. // Do nothing.
  326. end;
  327. class procedure TFPDocWriter.SplitImport(var AFilename, ALinkPrefix: String);
  328. var
  329. i: integer;
  330. begin
  331. //override in HTML and CHM writer
  332. i := Pos(',', AFilename);
  333. if i > 0 then
  334. begin //split CSV into filename and prefix
  335. ALinkPrefix := Copy(AFilename,i+1,Length(AFilename));
  336. SetLength(AFilename, i-1);
  337. end;
  338. end;
  339. function TFPDocWriter.FindTopicElement ( Node: TDocNode ) : TTopicElement;
  340. Var
  341. I : Integer;
  342. begin
  343. Result:=Nil;
  344. I:=FTopics.Count-1;
  345. While (I>=0) and (Result=Nil) do
  346. begin
  347. If (TTopicElement(FTopics[i]).TopicNode=Node) Then
  348. Result:=TTopicElement(FTopics[i]);
  349. Dec(I);
  350. end;
  351. end;
  352. procedure TFPDocWriter.DescrWriteImageEl(const AFileName, ACaption,
  353. ALinkName: DOMString);
  354. begin
  355. DoLog('%s : No support for images yet: %s (caption: "%s")',[ClassName,AFileName,ACaption]);
  356. end;
  357. { ---------------------------------------------------------------------
  358. Generic documentation node conversion
  359. ---------------------------------------------------------------------}
  360. function IsContentNodeType(Node: TDOMNode): Boolean;
  361. begin
  362. Result := (Node.NodeType = ELEMENT_NODE) or
  363. ((Node.NodeType = TEXT_NODE) and not IsWhitespaceNode(TDOMText(Node))) or
  364. (Node.NodeType = ENTITY_REFERENCE_NODE);
  365. end;
  366. procedure TFPDocWriter.Warning(AContext: TPasElement; const AMsg: String);
  367. begin
  368. if (AContext<>nil) then
  369. DoLog('[%s] %s',[AContext.PathName,AMsg])
  370. else
  371. DoLog('[<no context>] %s', [AMsg]);
  372. end;
  373. procedure TFPDocWriter.Warning(AContext: TPasElement; const AMsg: String;
  374. const Args: array of const);
  375. begin
  376. Warning(AContext, Format(AMsg, Args));
  377. end;
  378. function TFPDocWriter.IsDescrNodeEmpty(Node: TDOMNode): Boolean;
  379. var
  380. Child: TDOMNode;
  381. begin
  382. if (not Assigned(Node)) or (not Assigned(Node.FirstChild)) then
  383. Result := True
  384. else
  385. begin
  386. Child := Node.FirstChild;
  387. while Assigned(Child) do
  388. begin
  389. if (Child.NodeType = ELEMENT_NODE) or (Child.NodeType = TEXT_NODE) or
  390. (Child.NodeType = ENTITY_REFERENCE_NODE) then
  391. begin
  392. Result := False;
  393. exit;
  394. end;
  395. Child := Child.NextSibling;
  396. end;
  397. end;
  398. Result := True;
  399. end;
  400. { Check wether the nodes starting with the node given as argument make up an
  401. 'extshort' production. }
  402. function TFPDocWriter.IsExtShort(Node: TDOMNode): Boolean;
  403. begin
  404. while Assigned(Node) do
  405. begin
  406. if Node.NodeType = ELEMENT_NODE then
  407. if (Node.NodeName <> 'br') and
  408. (Node.NodeName <> 'link') and
  409. (Node.NodeName <> 'url') and
  410. (Node.NodeName <> 'b') and
  411. (Node.NodeName <> 'file') and
  412. (Node.NodeName <> 'i') and
  413. (Node.NodeName <> 'kw') and
  414. (Node.NodeName <> 'printshort') and
  415. (Node.NodeName <> 'var') then
  416. begin
  417. Result := False;
  418. exit;
  419. end;
  420. Node := Node.NextSibling;
  421. end;
  422. Result := True;
  423. end;
  424. function TFPDocWriter.ConvertShort(AContext: TPasElement;
  425. El: TDOMElement): Boolean;
  426. var
  427. Node: TDOMNode;
  428. begin
  429. Result := False;
  430. if not Assigned(El) then
  431. exit;
  432. FContext:=AContext;
  433. try
  434. Node := El.FirstChild;
  435. while Assigned(Node) do
  436. begin
  437. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'link') then
  438. ConvertLink(AContext, TDOMElement(Node))
  439. else if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'url') then
  440. ConvertURL(AContext, TDOMElement(Node))
  441. else
  442. if not ConvertBaseShort(AContext, Node) then
  443. exit;
  444. Node := Node.NextSibling;
  445. end;
  446. Result := True;
  447. finally
  448. FContext:=Nil;
  449. end;
  450. end;
  451. function TFPDocWriter.ConvertNotes(AContext: TPasElement; El: TDOMElement
  452. ): Boolean;
  453. Var
  454. L : TFPList;
  455. N : TDomNode;
  456. I : Integer;
  457. B : Boolean;
  458. begin
  459. Result:=Assigned(El) and EmitNotes;
  460. If Not Result then
  461. exit;
  462. L:=TFPList.Create;
  463. try
  464. N:=El.FirstChild;
  465. While Assigned(N) do
  466. begin
  467. If (N.NodeType=ELEMENT_NODE) and (N.NodeName='note') then
  468. begin
  469. B:=True;
  470. if Assigned(FBeforeEmitNote) then
  471. FBeforeEmitNote(Self,TDomElement(N),B);
  472. If B then
  473. L.Add(N);
  474. end;
  475. N:=N.NextSibling;
  476. end;
  477. Result:=L.Count>0;
  478. If Not Result then
  479. exit;
  480. DescrEmitNotesHeader(AContext);
  481. DescrBeginUnorderedList;
  482. For i:=0 to L.Count-1 do
  483. begin
  484. DescrBeginListItem;
  485. ConvertExtShortOrNonSectionBlocks(AContext, TDOMNode(L[i]).FirstChild);
  486. DescrEndListItem;
  487. end;
  488. DescrEndUnorderedList;
  489. DescrEmitNotesFooter(AContext);
  490. finally
  491. L.Free;
  492. end;
  493. end;
  494. function TFPDocWriter.ConvertBaseShort(AContext: TPasElement;
  495. Node: TDOMNode): Boolean;
  496. function ConvertText: DOMString;
  497. var
  498. s: DOMString;
  499. i: Integer;
  500. begin
  501. if Node.NodeType = TEXT_NODE then
  502. begin
  503. s := Node.NodeValue;
  504. i := 1;
  505. Result:='';
  506. while i <= Length(s) do
  507. if s[i] = #13 then
  508. begin
  509. Result := Result + ' ';
  510. Inc(i);
  511. if s[i] = #10 then
  512. Inc(i);
  513. end else if s[i] = #10 then
  514. begin
  515. Result := Result + ' ';
  516. Inc(i);
  517. end else
  518. begin
  519. Result := Result + s[i];
  520. Inc(i);
  521. end;
  522. end else if Node.NodeType = ENTITY_REFERENCE_NODE then
  523. if Node.NodeName = 'fpc' then
  524. Result := 'Free Pascal'
  525. else if Node.NodeName = 'delphi' then
  526. Result := 'Delphi'
  527. else
  528. begin
  529. Warning(AContext, Format(SErrUnknownEntityReference, [Node.NodeName]));
  530. Result := Node.NodeName;
  531. end
  532. else if Node.NodeType = ELEMENT_NODE then
  533. SetLength(Result, 0);
  534. end;
  535. function ConvertTextContent: DOMString;
  536. begin
  537. Result:='';
  538. Node := Node.FirstChild;
  539. while Assigned(Node) do
  540. begin
  541. Result := Result + ConvertText;
  542. Node := Node.NextSibling;
  543. end;
  544. end;
  545. var
  546. El, DescrEl: TDOMElement;
  547. hlp : TPasElement;
  548. begin
  549. Result := True;
  550. if Node.NodeType = ELEMENT_NODE then
  551. if Node.NodeName = 'b' then
  552. begin
  553. DescrBeginBold;
  554. ConvertBaseShortList(AContext, Node, False);
  555. DescrEndBold;
  556. end else
  557. if Node.NodeName = 'i' then
  558. begin
  559. DescrBeginItalic;
  560. ConvertBaseShortList(AContext, Node, False);
  561. DescrEndItalic;
  562. end else
  563. if Node.NodeName = 'em' then
  564. begin
  565. DescrBeginEmph;
  566. ConvertBaseShortList(AContext, Node, False);
  567. DescrEndEmph;
  568. end else
  569. if Node.NodeName = 'u' then
  570. begin
  571. DescrBeginUnderline;
  572. ConvertBaseShortList(AContext, Node, False);
  573. DescrEndUnderline;
  574. end else
  575. if Node.NodeName = 'file' then
  576. DescrWriteFileEl(ConvertTextContent)
  577. else if Node.NodeName = 'kw' then
  578. DescrWriteKeywordEl(ConvertTextContent)
  579. else if Node.NodeName = 'printshort' then
  580. begin
  581. El := TDOMElement(Node);
  582. hlp:=AContext;
  583. while assigned(hlp) and not (hlp is TPasModule) do
  584. hlp:=hlp.parent;
  585. if not (hlp is TPasModule) then
  586. hlp:=nil;
  587. DescrEl := Engine.FindShortDescr(TPasModule(hlp), UTF8Encode(El['id']));
  588. if Assigned(DescrEl) then
  589. ConvertShort(AContext, DescrEl)
  590. else
  591. begin
  592. Warning(AContext, Format(SErrUnknownPrintShortID, [El['id']]));
  593. DescrBeginBold;
  594. DescrWriteText('#ShortDescr:' + El['id']);
  595. DescrEndBold;
  596. end;
  597. end else if Node.NodeName = 'var' then
  598. DescrWriteVarEl(ConvertTextContent)
  599. else
  600. Result := False
  601. else
  602. DescrWriteText(ConvertText);
  603. end;
  604. procedure TFPDocWriter.ConvertBaseShortList(AContext: TPasElement;
  605. Node: TDOMNode; MayBeEmpty: Boolean);
  606. var
  607. Child: TDOMNode;
  608. begin
  609. Child := Node.FirstChild;
  610. while Assigned(Child) do
  611. begin
  612. if not ConvertBaseShort(AContext, Child) then
  613. Warning(AContext, SErrInvalidShortDescr)
  614. else
  615. MayBeEmpty := True;
  616. Child := Child.NextSibling;
  617. end;
  618. if not MayBeEmpty then
  619. Warning(AContext, SErrInvalidShortDescr)
  620. end;
  621. procedure TFPDocWriter.ConvertLink(AContext: TPasElement; El: TDOMElement);
  622. begin
  623. DescrBeginLink(El['id']);
  624. if not IsDescrNodeEmpty(El) then
  625. ConvertBaseShortList(AContext, El, True)
  626. else
  627. DescrWriteText(El['id']);
  628. DescrEndLink;
  629. end;
  630. procedure TFPDocWriter.ConvertURL(AContext: TPasElement; El: TDOMElement);
  631. begin
  632. DescrBeginURL(El['href']);
  633. if not IsDescrNodeEmpty(El) then
  634. ConvertBaseShortList(AContext, El, True)
  635. else
  636. DescrWriteText(El['href']);
  637. DescrEndURL;
  638. end;
  639. procedure TFPDocWriter.AddElementsFromList ( L: TStrings; List: TFPList;
  640. UsePathName: Boolean ) ;
  641. Var
  642. I : Integer;
  643. El : TPasElement;
  644. N : TDocNode;
  645. begin
  646. For I:=0 to List.Count-1 do
  647. begin
  648. El:=TPasElement(List[I]);
  649. N:=Engine.FindDocNode(El);
  650. if (N=Nil) or (not N.IsSkipped) then
  651. begin
  652. if UsePathName then
  653. L.AddObject(El.PathName,El)
  654. else
  655. L.AddObject(El.Name,El);
  656. If el is TPasEnumType then
  657. AddElementsFromList(L,TPasEnumType(el).Values);
  658. end;
  659. end;
  660. end;
  661. procedure TFPDocWriter.CreateClassTree;
  662. var
  663. L: TStringList;
  664. M: TPasModule;
  665. I:Integer;
  666. begin
  667. L:=TStringList.Create;
  668. try
  669. For I:=0 to Package.Modules.Count-1 do
  670. begin
  671. M:=TPasModule(Package.Modules[i]);
  672. if Not (M is TPasExternalModule) and assigned(M.InterfaceSection) then
  673. Self.AddElementsFromList(L,M.InterfaceSection.Classes,True)
  674. end;
  675. TreeClass.BuildTree(L);
  676. TreeInterface.BuildTree(L);
  677. {$IFDEF TREE_TEST}
  678. TreeClass.SaveToXml('TreeClass.xml');
  679. TreeInterface.SaveToXml('TreeInterface.xml');
  680. {$ENDIF}
  681. Finally
  682. L.Free;
  683. end;
  684. end;
  685. procedure TFPDocWriter.DoLog(const Msg: String);
  686. begin
  687. If Assigned(FEngine.OnLog) then
  688. FEngine.OnLog(Self,Msg);
  689. end;
  690. procedure TFPDocWriter.DoLog(const Fmt: String; Args: array of const);
  691. begin
  692. DoLog(Format(Fmt,Args));
  693. end;
  694. function TFPDocWriter.ConvertExtShort(AContext: TPasElement;
  695. Node: TDOMNode): Boolean;
  696. begin
  697. Result := False;
  698. while Assigned(Node) do
  699. begin
  700. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'link') then
  701. ConvertLink(AContext, TDOMElement(Node))
  702. else if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'url') then
  703. ConvertURL(AContext, TDOMElement(Node))
  704. else if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'br') then
  705. DescrWriteLinebreak
  706. else
  707. if not ConvertBaseShort(AContext, Node) then
  708. exit;
  709. Node := Node.NextSibling;
  710. end;
  711. Result := True;
  712. end;
  713. procedure TFPDocWriter.ConvertDescr(AContext: TPasElement; El: TDOMElement;
  714. AutoInsertBlock: Boolean);
  715. var
  716. Node, Child: TDOMNode;
  717. ParaCreated: Boolean;
  718. begin
  719. FContext:=AContext;
  720. try
  721. if AutoInsertBlock then
  722. if IsExtShort(El.FirstChild) then
  723. DescrBeginParagraph
  724. else
  725. AutoInsertBlock := False;
  726. Node := El.FirstChild;
  727. if not ConvertExtShort(AContext, Node) then
  728. begin
  729. while Assigned(Node) do
  730. begin
  731. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'section') then
  732. begin
  733. DescrBeginSectionTitle;
  734. Child := Node.FirstChild;
  735. while Assigned(Child) and (Child.NodeType <> ELEMENT_NODE) do
  736. begin
  737. if not IsDescrNodeEmpty(Child) then
  738. Warning(AContext, SErrInvalidContentBeforeSectionTitle);
  739. Child := Child.NextSibling;
  740. end;
  741. if not Assigned(Child) or (Child.NodeName <> 'title') then
  742. Warning(AContext, SErrSectionTitleExpected)
  743. else
  744. ConvertShort(AContext, TDOMElement(Child));
  745. DescrBeginSectionBody;
  746. if IsExtShort(Child) then
  747. begin
  748. DescrBeginParagraph;
  749. ParaCreated := True;
  750. end else
  751. ParaCreated := False;
  752. ConvertExtShortOrNonSectionBlocks(AContext, Child.NextSibling);
  753. if ParaCreated then
  754. DescrEndParagraph;
  755. DescrEndSection;
  756. end else if not ConvertNonSectionBlock(AContext, Node) then
  757. Warning(AContext, SErrInvalidDescr, [Node.NodeName]);
  758. Node := Node.NextSibling;
  759. end;
  760. end else
  761. if AutoInsertBlock then
  762. DescrEndParagraph;
  763. finally
  764. FContext:=Nil;
  765. end;
  766. end;
  767. procedure TFPDocWriter.ConvertExtShortOrNonSectionBlocks(AContext: TPasElement;
  768. Node: TDOMNode);
  769. begin
  770. if not ConvertExtShort(AContext, Node) then
  771. while Assigned(Node) do
  772. begin
  773. if not ConvertNonSectionBlock(AContext, Node) then
  774. Warning(AContext, SErrInvalidDescr, [Node.NodeName]);
  775. Node := Node.NextSibling;
  776. end;
  777. end;
  778. function TFPDocWriter.ConvertNonSectionBlock(AContext: TPasElement;
  779. Node: TDOMNode): Boolean;
  780. procedure ConvertCells(Node: TDOMNode);
  781. var
  782. Child: TDOMNode;
  783. IsEmpty: Boolean;
  784. begin
  785. Node := Node.FirstChild;
  786. IsEmpty := True;
  787. while Assigned(Node) do
  788. begin
  789. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'td') then
  790. begin
  791. DescrBeginTableCell;
  792. Child := Node.FirstChild;
  793. if not ConvertExtShort(AContext, Child) then
  794. while Assigned(Child) do
  795. begin
  796. if not ConvertSimpleBlock(AContext, Child) then
  797. Warning(AContext, SErrInvalidTableContent);
  798. Child := Child.NextSibling;
  799. end;
  800. DescrEndTableCell;
  801. IsEmpty := False;
  802. end else
  803. if IsContentNodeType(Node) then
  804. Warning(AContext, SErrInvalidTableContent);
  805. Node := Node.NextSibling;
  806. end;
  807. if IsEmpty then
  808. Warning(AContext, SErrTableRowEmpty);
  809. end;
  810. procedure ConvertTable;
  811. function GetColCount(Node: TDOMNode): Integer;
  812. begin
  813. Result := 0;
  814. Node := Node.FirstChild;
  815. while Assigned(Node) do
  816. begin
  817. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'td') then
  818. Inc(Result);
  819. Node := Node.NextSibling;
  820. end;
  821. end;
  822. var
  823. s: DOMString;
  824. HasBorder, CaptionPossible, HeadRowPossible: Boolean;
  825. ColCount, ThisRowColCount: Integer;
  826. Subnode: TDOMNode;
  827. begin
  828. s := TDOMElement(Node)['border'];
  829. if s = '1' then
  830. HasBorder := True
  831. else
  832. begin
  833. HasBorder := False;
  834. if (Length(s) <> 0) and (s <> '0') then
  835. Warning(AContext, SErrInvalidBorderValue, ['<table>']);
  836. end;
  837. // Determine the number of columns
  838. ColCount := 0;
  839. Subnode := Node.FirstChild;
  840. while Assigned(Subnode) do
  841. begin
  842. if Subnode.NodeType = ELEMENT_NODE then
  843. if (Subnode.NodeName = 'caption') or (Subnode.NodeName = 'th') or
  844. (Subnode.NodeName = 'tr') then
  845. begin
  846. ThisRowColCount := GetColCount(Subnode);
  847. if ThisRowColCount > ColCount then
  848. ColCount := ThisRowColCount;
  849. end;
  850. Subnode := Subnode.NextSibling;
  851. end;
  852. DescrBeginTable(ColCount, HasBorder);
  853. Node := Node.FirstChild;
  854. CaptionPossible := True;
  855. HeadRowPossible := True;
  856. while Assigned(Node) do
  857. begin
  858. if Node.NodeType = ELEMENT_NODE then
  859. if CaptionPossible and (Node.NodeName = 'caption') then
  860. begin
  861. DescrBeginTableCaption;
  862. if not ConvertExtShort(AContext, Node.FirstChild) then
  863. Warning(AContext, SErrInvalidTableContent);
  864. DescrEndTableCaption;
  865. CaptionPossible := False;
  866. end else if HeadRowPossible and (Node.NodeName = 'th') then
  867. begin
  868. DescrBeginTableHeadRow;
  869. ConvertCells(Node);
  870. DescrEndTableHeadRow;
  871. CaptionPossible := False;
  872. HeadRowPossible := False;
  873. end else if Node.NodeName = 'tr' then
  874. begin
  875. DescrBeginTableRow;
  876. ConvertCells(Node);
  877. DescrEndTableRow;
  878. end else
  879. Warning(AContext, SErrInvalidTableContent)
  880. else if IsContentNodeType(Node) then
  881. Warning(AContext, SErrInvalidTableContent);
  882. Node := Node.NextSibling;
  883. end;
  884. DescrEndTable;
  885. end;
  886. begin
  887. if Node.NodeType <> ELEMENT_NODE then
  888. begin
  889. if Node.NodeType = TEXT_NODE then
  890. Result := IsWhitespaceNode(TDOMText(Node))
  891. else
  892. Result := Node.NodeType = COMMENT_NODE;
  893. exit;
  894. end;
  895. if Node.NodeName = 'remark' then
  896. begin
  897. DescrBeginRemark;
  898. Node := Node.FirstChild;
  899. if not ConvertExtShort(AContext, Node) then
  900. while Assigned(Node) do
  901. begin
  902. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'table') then
  903. ConvertTable
  904. else
  905. if not ConvertSimpleBlock(AContext, Node) then
  906. Warning(AContext, SErrInvalidRemarkContent, [Node.NodeName]);
  907. Node := Node.NextSibling;
  908. end;
  909. DescrEndRemark;
  910. Result := True;
  911. end else if Node.NodeName = 'table' then
  912. begin
  913. ConvertTable;
  914. Result := True;
  915. end else
  916. Result := ConvertSimpleBlock(AContext, Node);
  917. end;
  918. function TFPDocWriter.ConvertSimpleBlock(AContext: TPasElement;
  919. Node: TDOMNode): Boolean;
  920. procedure ConvertListItems;
  921. var
  922. Empty: Boolean;
  923. begin
  924. Node := Node.FirstChild;
  925. Empty := True;
  926. while Assigned(Node) do
  927. begin
  928. if ((Node.NodeType = TEXT_NODE) and not IsWhitespaceNode(TDOMText(Node))) or (Node.NodeType = ENTITY_REFERENCE_NODE)
  929. then
  930. Warning(AContext, SErrInvalidListContent)
  931. else if Node.NodeType = ELEMENT_NODE then
  932. if Node.NodeName = 'li' then
  933. begin
  934. DescrBeginListItem;
  935. ConvertExtShortOrNonSectionBlocks(AContext, Node.FirstChild);
  936. DescrEndListItem;
  937. Empty := False;
  938. end else
  939. Warning(AContext, SErrInvalidElementInList);
  940. Node := Node.NextSibling;
  941. end;
  942. if Empty then
  943. Warning(AContext, SErrListIsEmpty);
  944. end;
  945. procedure ConvertDefinitionList;
  946. var
  947. Empty, ExpectDTNext: Boolean;
  948. begin
  949. Node := Node.FirstChild;
  950. Empty := True;
  951. ExpectDTNext := True;
  952. while Assigned(Node) do
  953. begin
  954. if ((Node.NodeType = TEXT_NODE) and not IsWhitespaceNode(TDOMText(Node))) or (Node.NodeType = ENTITY_REFERENCE_NODE)
  955. then
  956. Warning(AContext, SErrInvalidListContent)
  957. else if Node.NodeType = ELEMENT_NODE then
  958. if ExpectDTNext and (Node.NodeName = 'dt') then
  959. begin
  960. DescrBeginDefinitionTerm;
  961. if not ConvertShort(AContext, TDOMElement(Node)) then
  962. Warning(AContext, SErrInvalidDefinitionTermContent);
  963. DescrEndDefinitionTerm;
  964. Empty := False;
  965. ExpectDTNext := False;
  966. end else if not ExpectDTNext and (Node.NodeName = 'dd') then
  967. begin
  968. DescrBeginDefinitionEntry;
  969. ConvertExtShortOrNonSectionBlocks(AContext, Node.FirstChild);
  970. DescrEndDefinitionEntry;
  971. ExpectDTNext := True;
  972. end else
  973. Warning(AContext, SErrInvalidElementInList);
  974. Node := Node.NextSibling;
  975. end;
  976. if Empty then
  977. Warning(AContext, SErrListIsEmpty)
  978. else if not ExpectDTNext then
  979. Warning(AContext, SErrDefinitionEntryMissing);
  980. end;
  981. procedure ProcessCodeBody(Node: TDOMNode);
  982. var
  983. s: String;
  984. i, j: Integer;
  985. begin
  986. Node := Node.FirstChild;
  987. S:='';
  988. while Assigned(Node) do
  989. begin
  990. if Node.NodeType = TEXT_NODE then
  991. begin
  992. s := s + UTF8Encode(Node.NodeValue);
  993. j := 1;
  994. for i := 1 to Length(s) do
  995. // In XML, linefeeds are normalized to #10 by the parser!
  996. if s[i] = #10 then
  997. begin
  998. DescrWriteCodeLine(Copy(s, j, i - j));
  999. j := i + 1;
  1000. end;
  1001. if j > 1 then
  1002. s := Copy(s, j, Length(s));
  1003. end;
  1004. Node := Node.NextSibling;
  1005. end;
  1006. if Length(s) > 0 then
  1007. DescrWriteCodeLine(s);
  1008. end;
  1009. var
  1010. s: DOMString;
  1011. HasBorder: Boolean;
  1012. begin
  1013. if Node.NodeType <> ELEMENT_NODE then
  1014. begin
  1015. Result := (Node.NodeType = TEXT_NODE) and IsWhitespaceNode(TDOMText(Node));
  1016. exit;
  1017. end;
  1018. if Node.NodeName = 'p' then
  1019. begin
  1020. DescrBeginParagraph;
  1021. if not ConvertExtShort(AContext, Node.FirstChild) then
  1022. Warning(AContext, SErrInvalidParaContent);
  1023. DescrEndParagraph;
  1024. Result := True;
  1025. end else if Node.NodeName = 'code' then
  1026. begin
  1027. s := TDOMElement(Node)['border'];
  1028. if s = '1' then
  1029. HasBorder := True
  1030. else
  1031. begin
  1032. if (Length(s) > 0) and (s <> '0') then
  1033. Warning(AContext, SErrInvalidBorderValue, ['<code>']);
  1034. end;
  1035. DescrBeginCode(HasBorder, UTF8Encode(TDOMElement(Node)['highlighter']));
  1036. ProcessCodeBody(Node);
  1037. DescrEndCode;
  1038. Result := True;
  1039. end else if Node.NodeName = 'pre' then
  1040. begin
  1041. DescrBeginCode(False, 'none');
  1042. ProcessCodeBody(Node);
  1043. DescrEndCode;
  1044. Result := True;
  1045. end else if Node.NodeName = 'ul' then
  1046. begin
  1047. DescrBeginUnorderedList;
  1048. ConvertListItems;
  1049. DescrEndUnorderedList;
  1050. Result := True;
  1051. end else if Node.NodeName = 'ol' then
  1052. begin
  1053. DescrBeginOrderedList;
  1054. ConvertListItems;
  1055. DescrEndOrderedList;
  1056. Result := True;
  1057. end else if Node.NodeName = 'dl' then
  1058. begin
  1059. DescrBeginDefinitionList;
  1060. ConvertDefinitionList;
  1061. DescrEndDefinitionList;
  1062. Result := True;
  1063. end else if Node.NodeName = 'img' then
  1064. begin
  1065. begin
  1066. ConvertImage(Node as TDomElement);
  1067. Result:=True;
  1068. end;
  1069. end else
  1070. Result := False;
  1071. end;
  1072. procedure TFPDocWriter.ConvertImage ( El: TDomElement ) ;
  1073. Var
  1074. FN,Cap,LinkName : DOMString;
  1075. begin
  1076. FN:=El['file'];
  1077. Cap:=El['caption'];
  1078. LinkName:=El['name'];
  1079. FN:=UTF8decode(ChangeFileExt(UTF8Encode(FN),ImageExtension));
  1080. DescrWriteImageEl(FN,Cap,LinkName);
  1081. end;
  1082. procedure TFPDocWriter.DescrEmitNotesHeader(AContext: TPasElement);
  1083. begin
  1084. DescrWriteLinebreak;
  1085. DescrBeginBold;
  1086. DescrWriteText(UTF8Decode(SDocNotes));
  1087. DescrEndBold;
  1088. DescrWriteLinebreak;
  1089. end;
  1090. procedure TFPDocWriter.DescrEmitNotesFooter(AContext: TPasElement);
  1091. begin
  1092. DescrWriteLinebreak;
  1093. end;
  1094. Constructor TTopicElement.Create(const AName: String; AParent: TPasElement);
  1095. begin
  1096. Inherited Create(AName,AParent);
  1097. SubTopics:=TList.Create;
  1098. end;
  1099. Destructor TTopicElement.Destroy;
  1100. begin
  1101. // Actual subtopics are freed by TFPDocWriter Topics list.
  1102. SubTopics.Free;
  1103. Inherited;
  1104. end;
  1105. function TFPDocWriter.WriteDescr ( Element: TPasElement ) : TDocNode;
  1106. begin
  1107. Result:=Engine.FindDocNode(Element);
  1108. WriteDescr(ELement,Result);
  1109. end;
  1110. procedure TFPDocWriter.WriteDescr(Element: TPasElement; DocNode: TDocNode);
  1111. begin
  1112. if Assigned(DocNode) then
  1113. begin
  1114. if not IsDescrNodeEmpty(DocNode.Descr) then
  1115. WriteDescr(Element, DocNode.Descr)
  1116. else if not IsDescrNodeEmpty(DocNode.ShortDescr) then
  1117. WriteDescr(Element, DocNode.ShortDescr);
  1118. end;
  1119. end;
  1120. procedure TFPDocWriter.WriteDescr(AContext: TPasElement; DescrNode: TDOMElement);
  1121. begin
  1122. if Assigned(DescrNode) then
  1123. ConvertDescr(AContext, DescrNode, False);
  1124. end;
  1125. procedure TFPDocWriter.FPDocError(Msg: String);
  1126. begin
  1127. Raise EFPDocWriterError.Create(Msg);
  1128. end;
  1129. procedure TFPDocWriter.FPDocError(Fmt: String; Args: array of const);
  1130. begin
  1131. FPDocError(Format(Fmt,Args));
  1132. end;
  1133. function TFPDocWriter.ShowMember(M: TPasElement): boolean;
  1134. begin
  1135. Result:=not ((M.Visibility=visPrivate) and Engine.HidePrivate);
  1136. If Result then
  1137. Result:=Not ((M.Visibility=visProtected) and Engine.HideProtected)
  1138. end;
  1139. procedure TFPDocWriter.GetMethodList ( ClassDecl: TPasClassType;
  1140. List: TStringList ) ;
  1141. Var
  1142. I : Integer;
  1143. M : TPasElement;
  1144. begin
  1145. List.Clear;
  1146. List.Sorted:=False;
  1147. for i := 0 to ClassDecl.Members.Count - 1 do
  1148. begin
  1149. M:=TPasElement(ClassDecl.Members[i]);
  1150. if M.InheritsFrom(TPasProcedureBase) and ShowMember(M) then
  1151. List.AddObject(M.Name,M);
  1152. end;
  1153. List.Sorted:=False;
  1154. end;
  1155. initialization
  1156. InitWriterList;
  1157. finalization
  1158. DoneWriterList;
  1159. end.