dw_basehtml.pp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. {
  2. FPDoc - Free Pascal Documentation Tool
  3. Copyright (C) 2021 by Michael Van Canneyt
  4. * Basic HTML output generator. No assumptions about document/documentation structure
  5. See the file COPYING, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. }
  11. unit dw_basehtml;
  12. {$mode objfpc}{$H+}
  13. interface
  14. uses Classes, DOM, DOM_HTML, dGlobals, PasTree, dWriter;
  15. type
  16. { THTMLWriter }
  17. { TBaseHTMLWriter }
  18. TBaseHTMLWriter = class(TMultiFileDocWriter)
  19. Private
  20. FImageFileList: TStrings;
  21. FContentElement : THTMLELement;
  22. FInsideHeadRow: Boolean;
  23. FOutputNodeStack: TFPList;
  24. FBaseImageURL : String;
  25. FDoc: THTMLDocument;
  26. FCurOutputNode: TDOMNode;
  27. FDoPasHighlighting : Boolean;
  28. FHighlighterFlags: Byte;
  29. Protected
  30. Procedure SetContentElement(aElement : THTMLELement); virtual;
  31. // Description node conversion
  32. Procedure DescrEmitNotesHeader(AContext : TPasElement); override;
  33. Procedure DescrEmitNotesFooter(AContext : TPasElement); override;
  34. procedure DescrWriteText(const AText: DOMString); override;
  35. procedure DescrBeginBold; override;
  36. procedure DescrEndBold; override;
  37. procedure DescrBeginItalic; override;
  38. procedure DescrEndItalic; override;
  39. procedure DescrBeginEmph; override;
  40. procedure DescrEndEmph; override;
  41. procedure DescrBeginUnderline; override;
  42. procedure DescrEndUnderline; override;
  43. procedure DescrWriteImageEl(const AFileName, ACaption, ALinkName : DOMString); override;
  44. procedure DescrWriteFileEl(const AText: DOMString); override;
  45. procedure DescrWriteKeywordEl(const AText: DOMString); override;
  46. procedure DescrWriteVarEl(const AText: DOMString); override;
  47. procedure DescrBeginLink(const AId: DOMString); override;
  48. procedure DescrEndLink; override;
  49. procedure DescrBeginURL(const AURL: DOMString); override;
  50. procedure DescrEndURL; override;
  51. procedure DescrWriteLinebreak; override;
  52. procedure DescrBeginParagraph; override;
  53. procedure DescrEndParagraph; override;
  54. procedure DescrBeginCode(HasBorder: Boolean; const AHighlighterName: String); override;
  55. procedure DescrWriteCodeLine(const ALine: String); override;
  56. procedure DescrEndCode; override;
  57. procedure DescrBeginOrderedList; override;
  58. procedure DescrEndOrderedList; override;
  59. procedure DescrBeginUnorderedList; override;
  60. procedure DescrEndUnorderedList; override;
  61. procedure DescrBeginDefinitionList; override;
  62. procedure DescrEndDefinitionList; override;
  63. procedure DescrBeginListItem; override;
  64. procedure DescrEndListItem; override;
  65. procedure DescrBeginDefinitionTerm; override;
  66. procedure DescrEndDefinitionTerm; override;
  67. procedure DescrBeginDefinitionEntry; override;
  68. procedure DescrEndDefinitionEntry; override;
  69. procedure DescrBeginSectionTitle; override;
  70. procedure DescrBeginSectionBody; override;
  71. procedure DescrEndSection; override;
  72. procedure DescrBeginRemark; override;
  73. procedure DescrEndRemark; override;
  74. procedure DescrBeginTable(ColCount: Integer; HasBorder: Boolean); override;
  75. procedure DescrEndTable; override;
  76. procedure DescrBeginTableCaption; override;
  77. procedure DescrEndTableCaption; override;
  78. procedure DescrBeginTableHeadRow; override;
  79. procedure DescrEndTableHeadRow; override;
  80. procedure DescrBeginTableRow; override;
  81. procedure DescrEndTableRow; override;
  82. procedure DescrBeginTableCell; override;
  83. procedure DescrEndTableCell; override;
  84. // Basic HTML handling
  85. Procedure SetHTMLDocument(aDoc : THTMLDocument); virtual;
  86. procedure PushOutputNode(ANode: TDOMNode); virtual;
  87. procedure PopOutputNode; virtual;
  88. procedure AppendText(Parent: TDOMNode; const AText: AnsiString); virtual;
  89. procedure AppendText(Parent: TDOMNode; const AText: DOMString); virtual;
  90. procedure AppendNbSp(Parent: TDOMNode; ACount: Integer); virtual;
  91. procedure AppendSym(Parent: TDOMNode; const AText: DOMString); virtual;
  92. procedure AppendKw(Parent: TDOMNode; const AText: AnsiString); virtual;
  93. procedure AppendKw(Parent: TDOMNode; const AText: DOMString); virtual;
  94. function AppendPasSHFragment(Parent: TDOMNode; const AText: String; AShFlags: Byte): Byte; virtual;
  95. procedure AppendFragment(aParentNode: TDOMElement; aStream: TStream); virtual;
  96. // FPDoc specifics
  97. procedure AppendSourceRef(aParent: TDOMElement; AElement: TPasElement);
  98. Procedure AppendSeeAlsoSection(AElement: TPasElement; DocNode: TDocNode); virtual;
  99. Procedure AppendExampleSection(AElement : TPasElement;DocNode : TDocNode); virtual;
  100. Procedure AppendShortDescr(Parent: TDOMNode; Element: TPasElement); virtual;
  101. procedure AppendShortDescr(AContext: TPasElement; Parent: TDOMNode; DocNode: TDocNode); virtual;
  102. procedure AppendShortDescrCell(Parent: TDOMNode; Element: TPasElement); virtual;
  103. procedure AppendDescr(AContext: TPasElement; Parent: TDOMNode; DescrNode: TDOMElement; AutoInsertBlock: Boolean); virtual;
  104. procedure AppendDescrSection(AContext: TPasElement; Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: DOMString); virtual;
  105. procedure AppendDescrSection(AContext: TPasElement; Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: AnsiString); virtual;
  106. function AppendHyperlink(Parent: TDOMNode; Element: TPasElement): TDOMElement;
  107. // Helper functions for creating DOM elements
  108. function CreateEl(Parent: TDOMNode; const AName: DOMString): THTMLElement; virtual;
  109. function CreatePara(Parent: TDOMNode): THTMLElement; virtual;
  110. function CreateH1(Parent: TDOMNode): THTMLElement; virtual;
  111. function CreateH2(Parent: TDOMNode): THTMLElement; virtual;
  112. function CreateH3(Parent: TDOMNode): THTMLElement; virtual;
  113. function CreateTable(Parent: TDOMNode; const AClass: DOMString = ''): THTMLElement;virtual;
  114. function CreateContentTable(Parent: TDOMNode): THTMLElement; virtual;
  115. function CreateTR(Parent: TDOMNode): THTMLElement; virtual;
  116. function CreateTD(Parent: TDOMNode): THTMLElement; virtual;
  117. function CreateTD_vtop(Parent: TDOMNode): THTMLElement; virtual;
  118. function CreateLink(Parent: TDOMNode; const AHRef: AnsiString): THTMLElement; virtual;
  119. function CreateLink(Parent: TDOMNode; const AHRef: DOMString): THTMLElement; virtual;
  120. function CreateAnchor(Parent: TDOMNode; const AName: DOMString): THTMLElement; virtual;
  121. function CreateCode(Parent: TDOMNode): THTMLElement; virtual;
  122. function CreateWarning(Parent: TDOMNode): THTMLElement; virtual;
  123. // Some info
  124. Property ContentElement : THTMLELement Read FContentElement Write SetContentElement;
  125. Property OutputNodeStack: TFPList Read FOutputNodeStack;
  126. Property CurOutputNode : TDomNode Read FCurOutputNode;
  127. Property ImageFileList : TStrings Read FImageFileList;
  128. Property Doc: THTMLDocument Read FDoc;
  129. Property InsideHeadRow: Boolean Read FInsideHeadRow;
  130. Property DoPasHighlighting : Boolean Read FDoPasHighlighting;
  131. Property HighlighterFlags : Byte read FHighlighterFlags;
  132. Public
  133. constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
  134. Destructor Destroy; override;
  135. Property BaseImageURL : String Read FBaseImageURL Write FBaseImageURL;
  136. end;
  137. Function FixHTMLpath(const S : String) : STring;
  138. implementation
  139. uses fpdocstrs, xmlread, sysutils, sh_pas;
  140. Function FixHTMLpath(const S : String) : STring;
  141. begin
  142. Result:=StringReplace(S,'\','/',[rfReplaceAll]);
  143. end;
  144. constructor TBaseHTMLWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
  145. begin
  146. Inherited;
  147. FOutputNodeStack := TFPList.Create;
  148. FImageFileList:=TStringList.Create;
  149. end;
  150. destructor TBaseHTMLWriter.Destroy;
  151. begin
  152. FreeAndNil(FOutputNodeStack);
  153. FreeAndNil(FImageFileList);
  154. inherited Destroy;
  155. end;
  156. Procedure TBaseHTMLWriter.SetContentElement(aElement : THTMLELement);
  157. begin
  158. FContentElement:=aElement;
  159. end;
  160. function TBaseHTMLWriter.CreateEl(Parent: TDOMNode;
  161. const AName: DOMString): THTMLElement;
  162. begin
  163. Result := Doc.CreateElement(AName);
  164. Parent.AppendChild(Result);
  165. end;
  166. function TBaseHTMLWriter.CreatePara(Parent: TDOMNode): THTMLElement;
  167. begin
  168. Result := CreateEl(Parent, 'p');
  169. end;
  170. function TBaseHTMLWriter.CreateH1(Parent: TDOMNode): THTMLElement;
  171. begin
  172. Result := CreateEl(Parent, 'h1');
  173. end;
  174. function TBaseHTMLWriter.CreateH2(Parent: TDOMNode): THTMLElement;
  175. begin
  176. Result := CreateEl(Parent, 'h2');
  177. end;
  178. function TBaseHTMLWriter.CreateH3(Parent: TDOMNode): THTMLElement;
  179. begin
  180. Result := CreateEl(Parent, 'h3');
  181. end;
  182. function TBaseHTMLWriter.CreateTable(Parent: TDOMNode; const AClass: DOMString = ''): THTMLElement;
  183. begin
  184. Result := CreateEl(Parent, 'table');
  185. Result['cellspacing'] := '0';
  186. Result['cellpadding'] := '0';
  187. if AClass <> '' then
  188. Result['class'] := AClass;
  189. end;
  190. function TBaseHTMLWriter.CreateContentTable(Parent: TDOMNode): THTMLElement;
  191. begin
  192. Result := CreateEl(Parent, 'table');
  193. end;
  194. function TBaseHTMLWriter.CreateTR(Parent: TDOMNode): THTMLElement;
  195. begin
  196. Result := CreateEl(Parent, 'tr');
  197. end;
  198. function TBaseHTMLWriter.CreateTD(Parent: TDOMNode): THTMLElement;
  199. begin
  200. Result := CreateEl(Parent, 'td');
  201. end;
  202. function TBaseHTMLWriter.CreateTD_vtop(Parent: TDOMNode): THTMLElement;
  203. begin
  204. Result := CreateEl(Parent, 'td');
  205. Result['valign'] := 'top';
  206. end;
  207. function TBaseHTMLWriter.CreateLink(Parent: TDOMNode; const AHRef: AnsiString): THTMLElement;
  208. begin
  209. Result := CreateEl(Parent, 'a');
  210. Result['href'] := UTF8Decode(FixHtmlPath(AHRef));
  211. end;
  212. function TBaseHTMLWriter.CreateLink(Parent: TDOMNode;
  213. const AHRef: DOMString): THTMLElement;
  214. begin
  215. Result:=CreateLink(Parent,UTF8Encode(aHREf));
  216. end;
  217. function TBaseHTMLWriter.CreateAnchor(Parent: TDOMNode;
  218. const AName: DOMString): THTMLElement;
  219. begin
  220. Result := CreateEl(Parent, 'a');
  221. Result['name'] := AName;
  222. end;
  223. function TBaseHTMLWriter.CreateCode(Parent: TDOMNode): THTMLElement;
  224. begin
  225. Result := CreateEl(CreateEl(Parent, 'tt'), 'span');
  226. Result['class'] := 'code';
  227. end;
  228. function TBaseHTMLWriter.CreateWarning(Parent: TDOMNode): THTMLElement;
  229. begin
  230. Result := CreateEl(Parent, 'span');
  231. Result['class'] := 'warning';
  232. end;
  233. procedure TBaseHTMLWriter.DescrEmitNotesHeader(AContext: TPasElement);
  234. begin
  235. AppendText(CreateH2(ContentElement), SDocNotes);
  236. PushOutputNode(ContentElement);
  237. end;
  238. procedure TBaseHTMLWriter.DescrEmitNotesFooter(AContext: TPasElement);
  239. begin
  240. PopOutPutNode;
  241. end;
  242. procedure TBaseHTMLWriter.PushOutputNode(ANode: TDOMNode);
  243. begin
  244. OutputNodeStack.Add(CurOutputNode);
  245. FCurOutputNode := ANode;
  246. end;
  247. procedure TBaseHTMLWriter.PopOutputNode;
  248. begin
  249. FCurOutputNode := TDOMNode(OutputNodeStack[OutputNodeStack.Count - 1]);
  250. OutputNodeStack.Delete(OutputNodeStack.Count - 1);
  251. end;
  252. procedure TBaseHTMLWriter.DescrWriteText(const AText: DOMString);
  253. begin
  254. AppendText(CurOutputNode, AText);
  255. end;
  256. procedure TBaseHTMLWriter.DescrBeginBold;
  257. begin
  258. PushOutputNode(CreateEl(CurOutputNode, 'b'));
  259. end;
  260. procedure TBaseHTMLWriter.DescrEndBold;
  261. begin
  262. PopOutputNode;
  263. end;
  264. procedure TBaseHTMLWriter.DescrBeginItalic;
  265. begin
  266. PushOutputNode(CreateEl(CurOutputNode, 'i'));
  267. end;
  268. procedure TBaseHTMLWriter.DescrEndItalic;
  269. begin
  270. PopOutputNode;
  271. end;
  272. procedure TBaseHTMLWriter.DescrBeginEmph;
  273. begin
  274. PushOutputNode(CreateEl(CurOutputNode, 'em'));
  275. end;
  276. procedure TBaseHTMLWriter.DescrEndEmph;
  277. begin
  278. PopOutputNode;
  279. end;
  280. procedure TBaseHTMLWriter.DescrBeginUnderline;
  281. begin
  282. PushOutputNode(CreateEl(CurOutputNode, 'u'));
  283. end;
  284. procedure TBaseHTMLWriter.DescrEndUnderline;
  285. begin
  286. PopOutputNode;
  287. end;
  288. procedure TBaseHTMLWriter.DescrWriteImageEl(const AFileName, ACaption, ALinkName : DOMString);
  289. Var
  290. Pel,Cel: TDOMNode;
  291. El :TDomElement;
  292. D : String;
  293. L : Integer;
  294. begin
  295. // Determine parent node.
  296. If (ACaption='') then
  297. Pel:=CurOutputNode
  298. else
  299. begin
  300. Cel:=CreateTable(CurOutputNode, 'imagetable');
  301. Pel:=CreateTD(CreateTR(Cel));
  302. Cel:=CreateTD(CreateTR(Cel));
  303. El := CreateEl(Cel, 'span');
  304. El['class'] := 'imagecaption';
  305. Cel := El;
  306. If (ALinkName<>'') then
  307. Cel:=CreateAnchor(Cel,ALinkName);
  308. AppendText(Cel,ACaption);
  309. end;
  310. // Determine URL for image.
  311. If (Module=Nil) then
  312. D:=Allocator.GetRelativePathToTop(Package)
  313. else
  314. D:=Allocator.GetRelativePathToTop(Module);
  315. L:=Length(D);
  316. If (L>0) and (D[L]<>'/') then
  317. D:=D+'/';
  318. // Create image node.
  319. El:=CreateEl(Pel,'img');
  320. EL['src']:=UTF8Decode(D + BaseImageURL) + AFileName;
  321. El['alt']:=ACaption;
  322. //cache image filename, so it can be used later (CHM)
  323. ImageFileList.Add(UTF8Encode(UTF8Decode(BaseImageURL) + AFileName));
  324. end;
  325. procedure TBaseHTMLWriter.DescrWriteFileEl(const AText: DOMString);
  326. var
  327. NewEl: TDOMElement;
  328. begin
  329. NewEl := CreateEl(CurOutputNode, 'span');
  330. NewEl['class'] := 'file';
  331. AppendText(NewEl, AText);
  332. end;
  333. procedure TBaseHTMLWriter.DescrWriteKeywordEl(const AText: DOMString);
  334. var
  335. NewEl: TDOMElement;
  336. begin
  337. NewEl := CreateEl(CurOutputNode, 'span');
  338. NewEl['class'] := 'kw';
  339. AppendText(NewEl, AText);
  340. end;
  341. procedure TBaseHTMLWriter.DescrWriteVarEl(const AText: DOMString);
  342. begin
  343. AppendText(CreateEl(CurOutputNode, 'var'), AText);
  344. end;
  345. procedure TBaseHTMLWriter.DescrBeginLink(const AId: DOMString);
  346. var
  347. a,s,n : String;
  348. begin
  349. a:=UTF8Encode(AId);
  350. s := UTF8Encode(ResolveLinkID(a));
  351. if Length(s) = 0 then
  352. begin
  353. if assigned(module) then
  354. s:=module.name
  355. else
  356. s:='?';
  357. if a='' then a:='<empty>';
  358. if Assigned(CurrentContext) then
  359. N:=CurrentContext.Name
  360. else
  361. N:='?';
  362. DoLog(SErrUnknownLinkID, [s,n,a]);
  363. LinkUnresolvedInc();
  364. PushOutputNode(CreateEl(CurOutputNode, 'b'));
  365. end else
  366. PushOutputNode(CreateLink(CurOutputNode, s));
  367. end;
  368. procedure TBaseHTMLWriter.DescrEndLink;
  369. begin
  370. PopOutputNode;
  371. end;
  372. procedure TBaseHTMLWriter.DescrBeginURL(const AURL: DOMString);
  373. begin
  374. PushOutputNode(CreateLink(CurOutputNode, AURL));
  375. end;
  376. procedure TBaseHTMLWriter.DescrEndURL;
  377. begin
  378. PopOutputNode;
  379. end;
  380. procedure TBaseHTMLWriter.DescrWriteLinebreak;
  381. begin
  382. CreateEl(CurOutputNode, 'br');
  383. end;
  384. procedure TBaseHTMLWriter.DescrBeginParagraph;
  385. begin
  386. PushOutputNode(CreatePara(CurOutputNode));
  387. end;
  388. procedure TBaseHTMLWriter.DescrEndParagraph;
  389. begin
  390. PopOutputNode;
  391. end;
  392. procedure TBaseHTMLWriter.DescrBeginCode(HasBorder: Boolean; const AHighlighterName: String);
  393. var
  394. lNode : THTMLElement;
  395. lClass : string;
  396. begin
  397. FDoPasHighlighting := (AHighlighterName = '') or (AHighlighterName = 'Pascal');
  398. FHighlighterFlags := 0;
  399. lNode:=CreateEl(CurOutputNode, 'pre');
  400. lClass:='code code-';
  401. if AHighlighterName='' then
  402. lClass:=lClass+'pascal'
  403. else
  404. lClass:=lClass+lowercase(AHighlighterName);
  405. lNode['class']:=lClass;
  406. PushOutputNode(lNode);
  407. end;
  408. procedure TBaseHTMLWriter.DescrWriteCodeLine(const ALine: String);
  409. begin
  410. if DoPasHighlighting then
  411. begin
  412. FHighlighterFlags := AppendPasSHFragment(CurOutputNode, ALine,FHighlighterFlags);
  413. AppendText(CurOutputNode, #10);
  414. end else
  415. AppendText(CurOutputNode, ALine + #10);
  416. end;
  417. procedure TBaseHTMLWriter.DescrEndCode;
  418. begin
  419. PopOutputNode;
  420. end;
  421. procedure TBaseHTMLWriter.DescrBeginOrderedList;
  422. begin
  423. PushOutputNode(CreateEl(CurOutputNode, 'ol'));
  424. end;
  425. procedure TBaseHTMLWriter.DescrEndOrderedList;
  426. begin
  427. PopOutputNode;
  428. end;
  429. procedure TBaseHTMLWriter.DescrBeginUnorderedList;
  430. begin
  431. PushOutputNode(CreateEl(CurOutputNode, 'ul'));
  432. end;
  433. procedure TBaseHTMLWriter.DescrEndUnorderedList;
  434. begin
  435. PopOutputNode;
  436. end;
  437. procedure TBaseHTMLWriter.DescrBeginDefinitionList;
  438. begin
  439. PushOutputNode(CreateEl(CurOutputNode, 'dl'));
  440. end;
  441. procedure TBaseHTMLWriter.DescrEndDefinitionList;
  442. begin
  443. PopOutputNode;
  444. end;
  445. procedure TBaseHTMLWriter.DescrBeginListItem;
  446. begin
  447. PushOutputNode(CreateEl(CurOutputNode, 'li'));
  448. end;
  449. procedure TBaseHTMLWriter.DescrEndListItem;
  450. begin
  451. PopOutputNode;
  452. end;
  453. procedure TBaseHTMLWriter.DescrBeginDefinitionTerm;
  454. begin
  455. PushOutputNode(CreateEl(CurOutputNode, 'dt'));
  456. end;
  457. procedure TBaseHTMLWriter.DescrEndDefinitionTerm;
  458. begin
  459. PopOutputNode;
  460. end;
  461. procedure TBaseHTMLWriter.DescrBeginDefinitionEntry;
  462. begin
  463. PushOutputNode(CreateEl(CurOutputNode, 'dd'));
  464. end;
  465. procedure TBaseHTMLWriter.DescrEndDefinitionEntry;
  466. begin
  467. PopOutputNode;
  468. end;
  469. procedure TBaseHTMLWriter.DescrBeginSectionTitle;
  470. begin
  471. PushOutputNode(CreateEl(CurOutputNode, 'h3'));
  472. end;
  473. procedure TBaseHTMLWriter.DescrBeginSectionBody;
  474. begin
  475. PopOutputNode;
  476. end;
  477. procedure TBaseHTMLWriter.DescrEndSection;
  478. begin
  479. end;
  480. procedure TBaseHTMLWriter.DescrBeginRemark;
  481. var
  482. NewEl, TDEl: TDOMElement;
  483. begin
  484. NewEl := CreateEl(CurOutputNode, 'table');
  485. NewEl['width'] := '100%';
  486. NewEl['border'] := '0';
  487. NewEl['CellSpacing'] := '0';
  488. NewEl['class'] := 'remark';
  489. NewEl := CreateTR(NewEl);
  490. TDEl := CreateTD(NewEl);
  491. TDEl['valign'] := 'top';
  492. TDEl['class'] := 'pre';
  493. AppendText(CreateEl(TDEl, 'b'), SDocRemark);
  494. PushOutputNode(CreateTD(NewEl));
  495. end;
  496. procedure TBaseHTMLWriter.DescrEndRemark;
  497. begin
  498. PopOutputNode;
  499. end;
  500. procedure TBaseHTMLWriter.DescrBeginTable(ColCount: Integer; HasBorder: Boolean);
  501. var
  502. Table: TDOMElement;
  503. begin
  504. Table := CreateEl(CurOutputNode, 'table');
  505. Table['border'] := UTF8Decode(IntToStr(Ord(HasBorder)));
  506. PushOutputNode(Table);
  507. end;
  508. procedure TBaseHTMLWriter.DescrEndTable;
  509. begin
  510. PopOutputNode;
  511. end;
  512. procedure TBaseHTMLWriter.DescrBeginTableCaption;
  513. begin
  514. PushOutputNode(CreateEl(CurOutputNode, 'caption'));
  515. end;
  516. procedure TBaseHTMLWriter.DescrEndTableCaption;
  517. begin
  518. PopOutputNode;
  519. end;
  520. procedure TBaseHTMLWriter.DescrBeginTableHeadRow;
  521. begin
  522. PushOutputNode(CreateTr(CurOutputNode));
  523. FInsideHeadRow := True;
  524. end;
  525. procedure TBaseHTMLWriter.DescrEndTableHeadRow;
  526. begin
  527. FInsideHeadRow := False;
  528. PopOutputNode;
  529. end;
  530. procedure TBaseHTMLWriter.DescrBeginTableRow;
  531. begin
  532. PushOutputNode(CreateTR(CurOutputNode));
  533. end;
  534. procedure TBaseHTMLWriter.DescrEndTableRow;
  535. begin
  536. PopOutputNode;
  537. end;
  538. procedure TBaseHTMLWriter.DescrBeginTableCell;
  539. begin
  540. if InsideHeadRow then
  541. PushOutputNode(CreateEl(CurOutputNode, 'th'))
  542. else
  543. PushOutputNode(CreateTD(CurOutputNode));
  544. end;
  545. procedure TBaseHTMLWriter.DescrEndTableCell;
  546. begin
  547. PopOutputNode;
  548. end;
  549. procedure TBaseHTMLWriter.SetHTMLDocument(aDoc: THTMLDocument);
  550. begin
  551. FDoc:=aDoc;
  552. FOutputNodeStack.Clear;
  553. FCurOutputNode:=Nil;
  554. end;
  555. procedure TBaseHTMLWriter.AppendText(Parent: TDOMNode; const AText: AnsiString);
  556. begin
  557. AppendText(Parent,UTF8Decode(aText));
  558. end;
  559. procedure TBaseHTMLWriter.AppendText(Parent: TDOMNode; const AText: DOMString);
  560. begin
  561. Parent.AppendChild(Doc.CreateTextNode(AText));
  562. end;
  563. procedure TBaseHTMLWriter.AppendNbSp(Parent: TDOMNode; ACount: Integer);
  564. begin
  565. while ACount > 0 do
  566. begin
  567. Parent.AppendChild(Doc.CreateEntityReference('nbsp'));
  568. Dec(ACount);
  569. end;
  570. end;
  571. procedure TBaseHTMLWriter.AppendSym(Parent: TDOMNode; const AText: DOMString);
  572. var
  573. El: TDOMElement;
  574. begin
  575. El := CreateEl(Parent, 'span');
  576. El['class'] := 'sym';
  577. AppendText(El, AText);
  578. end;
  579. procedure TBaseHTMLWriter.AppendKw(Parent: TDOMNode; const AText: AnsiString);
  580. begin
  581. AppendKW(Parent,UTF8Decode(aText));
  582. end;
  583. procedure TBaseHTMLWriter.AppendKw(Parent: TDOMNode; const AText: DOMString);
  584. var
  585. El: TDOMElement;
  586. begin
  587. El := CreateEl(Parent, 'span');
  588. El['class'] := 'kw';
  589. AppendText(El, AText);
  590. end;
  591. function TBaseHTMLWriter.AppendPasSHFragment(Parent: TDOMNode;
  592. const AText: String; AShFlags: Byte): Byte;
  593. var
  594. Line, Last, p: PChar;
  595. El: TDOMElement;
  596. Procedure MaybeOutput;
  597. Var
  598. CurParent: TDomNode;
  599. begin
  600. If (Last<>Nil) then
  601. begin
  602. If (el<>Nil) then
  603. CurParent:=El
  604. else
  605. CurParent:=Parent;
  606. AppendText(CurParent,Last);
  607. El:=Nil;
  608. Last:=Nil;
  609. end;
  610. end;
  611. Function NewEl(Const ElType,Attr,AttrVal : DOMString) : TDomElement;
  612. begin
  613. Result:=CreateEl(Parent,ElType);
  614. Result[Attr]:=AttrVal;
  615. end;
  616. Function NewSpan(Const AttrVal : DOMString) : TDomElement;
  617. begin
  618. Result:=CreateEl(Parent,'span');
  619. Result['class']:=AttrVal;
  620. end;
  621. begin
  622. GetMem(Line, Length(AText) * 3 + 4);
  623. Try
  624. DoPascalHighlighting(AShFlags, PChar(AText), Line);
  625. Result := AShFlags;
  626. Last := Nil;
  627. p := Line;
  628. el:=nil;
  629. while p[0] <> #0 do
  630. begin
  631. if p[0] = LF_ESCAPE then
  632. begin
  633. p[0] := #0;
  634. MaybeOutput;
  635. case Ord(p[1]) of
  636. shDefault: El:=Nil;
  637. shInvalid: El:=newel('font','color','red');
  638. shSymbol : El:=newspan('sym');
  639. shKeyword: El:=newspan('kw');
  640. shComment: El:=newspan('cmt');
  641. shDirective: El:=newspan('dir');
  642. shNumbers: El:=newspan('num');
  643. shCharacters: El:=newspan('chr');
  644. shStrings: El:=newspan('str');
  645. shAssembler: El:=newspan('asm');
  646. end;
  647. Inc(P);
  648. end
  649. else If (Last=Nil) then
  650. Last:=P;
  651. Inc(p);
  652. end;
  653. MaybeOutput;
  654. Finally
  655. FreeMem(Line);
  656. end;
  657. end;
  658. procedure TBaseHTMLWriter.AppendSeeAlsoSection ( AElement: TPasElement;
  659. DocNode: TDocNode ) ;
  660. var
  661. Node: TDOMNode;
  662. TableEl, El, TREl, ParaEl, NewEl, DescrEl: TDOMElement;
  663. l,s,n: DOMString;
  664. IsFirstSeeAlso : Boolean;
  665. begin
  666. if Not (Assigned(DocNode) and Assigned(DocNode.SeeAlso)) then
  667. Exit;
  668. IsFirstSeeAlso := True;
  669. Node:=DocNode.SeeAlso.FirstChild;
  670. While Assigned(Node) do
  671. begin
  672. if (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='link') then
  673. begin
  674. if IsFirstSeeAlso then
  675. begin
  676. IsFirstSeeAlso := False;
  677. AppendText(CreateH2(ContentElement), SDocSeeAlso);
  678. TableEl := CreateTable(ContentElement);
  679. end;
  680. El:=TDOMElement(Node);
  681. TREl:=CreateTR(TableEl);
  682. ParaEl:=CreatePara(CreateTD_vtop(TREl));
  683. l:=El['id'];
  684. if Assigned(Engine) and Engine.FalbackSeeAlsoLinks then
  685. s:= ResolveLinkIDUnStrict(UTF8ENcode(l))
  686. else
  687. s:= ResolveLinkID(UTF8ENcode(l));
  688. if Length(s)=0 then
  689. begin
  690. if assigned(module) then
  691. s:=UTF8Decode(module.name)
  692. else
  693. s:='?';
  694. if l='' then l:='<empty>';
  695. if Assigned(AElement) then
  696. N:=UTF8Decode(AElement.PathName)
  697. else
  698. N:='?';
  699. DoLog(SErrUnknownLinkID, [s,N,l]);
  700. LinkUnresolvedInc();
  701. NewEl := CreateEl(ParaEl,'b')
  702. end
  703. else
  704. NewEl := CreateLink(ParaEl,s);
  705. if Not IsDescrNodeEmpty(El) then
  706. begin
  707. PushOutputNode(NewEl);
  708. Try
  709. ConvertBaseShortList(AElement, El, True)
  710. Finally
  711. PopOutputNode;
  712. end;
  713. end
  714. else
  715. AppendText(NewEl,El['id']);
  716. l:=El['id'];
  717. DescrEl := Engine.FindShortDescr(AElement.GetModule,UTF8Encode(L));
  718. if Assigned(DescrEl) then
  719. begin
  720. AppendNbSp(CreatePara(CreateTD(TREl)), 2);
  721. ParaEl := CreatePara(CreateTD(TREl));
  722. ParaEl['class'] := 'cmt';
  723. PushOutputNode(ParaEl);
  724. try
  725. ConvertShort(AElement, DescrEl);
  726. finally
  727. PopOutputNode;
  728. end;
  729. end;
  730. end; // Link node
  731. Node := Node.NextSibling;
  732. end; // While
  733. end;
  734. procedure TBaseHTMLWriter.AppendExampleSection ( AElement: TPasElement; DocNode: TDocNode ) ;
  735. var
  736. Node: TDOMNode;
  737. fn,s: String;
  738. f: Text;
  739. begin
  740. if not (Assigned(DocNode) and Assigned(DocNode.FirstExample)) then
  741. Exit;
  742. Node := DocNode.FirstExample;
  743. while Assigned(Node) do
  744. begin
  745. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'example') then
  746. begin
  747. fn:=Engine.GetExampleFilename(TDOMElement(Node));
  748. If (fn<>'') then
  749. begin
  750. AppendText(CreateH2(ContentElement), SDocExample);
  751. try
  752. Assign(f, FN);
  753. Reset(f);
  754. try
  755. PushOutputNode(ContentElement);
  756. DescrBeginCode(False, UTF8Encode(TDOMElement(Node)['highlighter']));
  757. while not EOF(f) do
  758. begin
  759. ReadLn(f, s);
  760. DescrWriteCodeLine(s);
  761. end;
  762. DescrEndCode;
  763. PopOutputNode;
  764. finally
  765. Close(f);
  766. end;
  767. except
  768. on e: Exception do
  769. begin
  770. e.Message := '[example] ' + e.Message;
  771. raise;
  772. end;
  773. end;
  774. end;
  775. end;
  776. Node := Node.NextSibling;
  777. end;
  778. end;
  779. procedure TBaseHTMLWriter.AppendFragment(aParentNode : TDOMElement; aStream : TStream);
  780. begin
  781. if (aStream<>Nil) then
  782. begin
  783. aStream.Position:=0;
  784. ReadXMLFragment(aParentNode,aStream);
  785. end;
  786. end;
  787. procedure TBaseHTMLWriter.AppendShortDescr ( AContext: TPasElement;
  788. Parent: TDOMNode; DocNode: TDocNode ) ;
  789. Var
  790. N : TDocNode;
  791. begin
  792. if Assigned(DocNode) then
  793. begin
  794. If (DocNode.Link<>'') then
  795. begin
  796. N:=Engine.FindLinkedNode(DocNode);
  797. If (N<>Nil) then
  798. DocNode:=N;
  799. end;
  800. If Assigned(DocNode.ShortDescr) then
  801. begin
  802. PushOutputNode(Parent);
  803. try
  804. if not ConvertShort(AContext,TDomElement(DocNode.ShortDescr)) then
  805. Warning(AContext, SErrInvalidShortDescr)
  806. finally
  807. PopOutputNode;
  808. end;
  809. end;
  810. end;
  811. end;
  812. procedure TBaseHTMLWriter.AppendShortDescr(Parent: TDOMNode; Element: TPasElement);
  813. begin
  814. AppendShortDescr(Element,Parent,Engine.FindDocNode(Element));
  815. end;
  816. procedure TBaseHTMLWriter.AppendShortDescrCell(Parent: TDOMNode; Element: TPasElement);
  817. var
  818. ParaEl: TDOMElement;
  819. begin
  820. if Assigned(Engine.FindShortDescr(Element)) then
  821. begin
  822. AppendNbSp(CreatePara(CreateTD(Parent)), 2);
  823. ParaEl := CreatePara(CreateTD(Parent));
  824. ParaEl['class'] := 'cmt';
  825. AppendShortDescr(ParaEl, Element);
  826. end;
  827. end;
  828. procedure TBaseHTMLWriter.AppendDescr(AContext: TPasElement; Parent: TDOMNode;
  829. DescrNode: TDOMElement; AutoInsertBlock: Boolean);
  830. begin
  831. if Assigned(DescrNode) then
  832. begin
  833. PushOutputNode(Parent);
  834. try
  835. ConvertDescr(AContext, DescrNode, AutoInsertBlock);
  836. finally
  837. PopOutputNode;
  838. end;
  839. end;
  840. end;
  841. procedure TBaseHTMLWriter.AppendDescrSection(AContext: TPasElement; Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: AnsiString);
  842. begin
  843. AppendDescrSection(aContext,Parent,DescrNode,UTF8Decode(aTitle));
  844. end;
  845. procedure TBaseHTMLWriter.AppendDescrSection(AContext: TPasElement;
  846. Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: DOMString);
  847. begin
  848. if not IsDescrNodeEmpty(DescrNode) then
  849. begin
  850. If (ATitle<>'') then // Can be empty for topic.
  851. AppendText(CreateH2(Parent), ATitle);
  852. AppendDescr(AContext, Parent, DescrNode, True);
  853. end;
  854. end;
  855. function TBaseHTMLWriter.AppendHyperlink(Parent: TDOMNode; Element: TPasElement): TDOMElement;
  856. var
  857. s: DOMString;
  858. UnitList: TFPList;
  859. i: Integer;
  860. ThisPackage: TLinkNode;
  861. begin
  862. if Not Assigned(Element) then
  863. begin
  864. Result := nil;
  865. AppendText(CreateWarning(Parent), '<NIL>');
  866. exit;
  867. end
  868. else if Element.InheritsFrom(TPasUnresolvedTypeRef) then
  869. begin
  870. s := ResolveLinkID(Element.Name);
  871. if Length(s) = 0 then
  872. begin
  873. { Try all packages }
  874. ThisPackage := Engine.RootLinkNode.FirstChild;
  875. while Assigned(ThisPackage) do
  876. begin
  877. s := ResolveLinkID(ThisPackage.Name + '.' + Element.Name);
  878. if Length(s) > 0 then
  879. break;
  880. ThisPackage := ThisPackage.NextSibling;
  881. end;
  882. if (Length(s) = 0) and Assigned(Module) then
  883. begin
  884. { Okay, then we have to try all imported units of the current module }
  885. UnitList := Module.InterfaceSection.UsesList;
  886. for i := UnitList.Count - 1 downto 0 do
  887. begin
  888. { Try all packages }
  889. ThisPackage := Engine.RootLinkNode.FirstChild;
  890. while Assigned(ThisPackage) do
  891. begin
  892. s := ResolveLinkID(ThisPackage.Name + '.' +
  893. TPasType(UnitList[i]).Name + '.' + Element.Name);
  894. if Length(s) > 0 then
  895. break;
  896. ThisPackage := ThisPackage.NextSibling;
  897. end;
  898. if length(s)=0 then
  899. s := ResolveLinkID('#rtl.System.' + Element.Name);
  900. if Length(s) > 0 then
  901. break;
  902. end;
  903. end;
  904. end;
  905. end
  906. else if Element is TPasEnumValue then
  907. s := ResolveLinkID(Element.Parent.PathName)
  908. else if Element is TPasAliasType then
  909. begin
  910. s := ResolveLinkID(TPasAliasType(Element).DestType.PathName);
  911. // See if we find a page for the type alias ?
  912. if (S='') then
  913. s := ResolveLinkID(TPasAliasType(Element).Name)
  914. end
  915. else
  916. s := ResolveLinkID(Element.PathName);
  917. if Length(s) > 0 then
  918. begin
  919. Result := CreateLink(Parent, s);
  920. AppendText(Result, Element.Name);
  921. end
  922. else
  923. begin
  924. Result := nil;
  925. if Element is TPasAliasType then
  926. AppendText(Parent, TPasAliasType(Element).DestType.Name)
  927. else
  928. AppendText(Parent, Element.Name); // unresolved items
  929. end;
  930. end;
  931. procedure TBaseHTMLWriter.AppendSourceRef(aParent : TDOMElement; AElement: TPasElement);
  932. begin
  933. AppendText(CreatePara(aParent), Format(SDocSourcePosition,
  934. [ExtractFileName(AElement.SourceFilename), AElement.SourceLinenumber]));
  935. end;
  936. end.