dw_basehtml.pp 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070
  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);
  86. procedure PushOutputNode(ANode: TDOMNode);
  87. procedure PopOutputNode;
  88. procedure AppendText(Parent: TDOMNode; const AText: String);
  89. procedure AppendText(Parent: TDOMNode; const AText: DOMString);
  90. procedure AppendNbSp(Parent: TDOMNode; ACount: Integer);
  91. procedure AppendSym(Parent: TDOMNode; const AText: DOMString);
  92. procedure AppendKw(Parent: TDOMNode; const AText: String);
  93. procedure AppendKw(Parent: TDOMNode; const AText: DOMString);
  94. function AppendPasSHFragment(Parent: TDOMNode; const AText: String; AShFlags: Byte): Byte;
  95. procedure AppendFragment(aParentNode: TDOMElement; aStream: TStream);
  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);
  101. procedure AppendShortDescr(AContext: TPasElement; Parent: TDOMNode; DocNode: TDocNode);
  102. procedure AppendShortDescrCell(Parent: TDOMNode; Element: TPasElement);
  103. procedure AppendDescr(AContext: TPasElement; Parent: TDOMNode; DescrNode: TDOMElement; AutoInsertBlock: Boolean);
  104. procedure AppendDescrSection(AContext: TPasElement; Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: DOMString);
  105. procedure AppendDescrSection(AContext: TPasElement; Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: String);
  106. function AppendHyperlink(Parent: TDOMNode; Element: TPasElement): TDOMElement;
  107. // Helper functions for creating DOM elements
  108. function CreateEl(Parent: TDOMNode; const AName: DOMString): THTMLElement;
  109. function CreatePara(Parent: TDOMNode): THTMLElement;
  110. function CreateH1(Parent: TDOMNode): THTMLElement;
  111. function CreateH2(Parent: TDOMNode): THTMLElement;
  112. function CreateH3(Parent: TDOMNode): THTMLElement;
  113. function CreateTable(Parent: TDOMNode; const AClass: DOMString = ''): THTMLElement;
  114. function CreateContentTable(Parent: TDOMNode): THTMLElement;
  115. function CreateTR(Parent: TDOMNode): THTMLElement;
  116. function CreateTD(Parent: TDOMNode): THTMLElement;
  117. function CreateTD_vtop(Parent: TDOMNode): THTMLElement;
  118. function CreateLink(Parent: TDOMNode; const AHRef: String): THTMLElement;
  119. function CreateLink(Parent: TDOMNode; const AHRef: DOMString): THTMLElement;
  120. function CreateAnchor(Parent: TDOMNode; const AName: DOMString): THTMLElement;
  121. function CreateCode(Parent: TDOMNode): THTMLElement;
  122. function CreateWarning(Parent: TDOMNode): THTMLElement;
  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(S : String) : STring;
  138. implementation
  139. uses fpdocstrs, xmlread, sysutils, sh_pas;
  140. Function FixHTMLpath(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: String): 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. begin
  394. FDoPasHighlighting := (AHighlighterName = '') or (AHighlighterName = 'Pascal');
  395. FHighlighterFlags := 0;
  396. PushOutputNode(CreateEl(CurOutputNode, 'pre'));
  397. end;
  398. procedure TBaseHTMLWriter.DescrWriteCodeLine(const ALine: String);
  399. begin
  400. if DoPasHighlighting then
  401. begin
  402. FHighlighterFlags := AppendPasSHFragment(CurOutputNode, ALine,FHighlighterFlags);
  403. AppendText(CurOutputNode, #10);
  404. end else
  405. AppendText(CurOutputNode, ALine + #10);
  406. end;
  407. procedure TBaseHTMLWriter.DescrEndCode;
  408. begin
  409. PopOutputNode;
  410. end;
  411. procedure TBaseHTMLWriter.DescrBeginOrderedList;
  412. begin
  413. PushOutputNode(CreateEl(CurOutputNode, 'ol'));
  414. end;
  415. procedure TBaseHTMLWriter.DescrEndOrderedList;
  416. begin
  417. PopOutputNode;
  418. end;
  419. procedure TBaseHTMLWriter.DescrBeginUnorderedList;
  420. begin
  421. PushOutputNode(CreateEl(CurOutputNode, 'ul'));
  422. end;
  423. procedure TBaseHTMLWriter.DescrEndUnorderedList;
  424. begin
  425. PopOutputNode;
  426. end;
  427. procedure TBaseHTMLWriter.DescrBeginDefinitionList;
  428. begin
  429. PushOutputNode(CreateEl(CurOutputNode, 'dl'));
  430. end;
  431. procedure TBaseHTMLWriter.DescrEndDefinitionList;
  432. begin
  433. PopOutputNode;
  434. end;
  435. procedure TBaseHTMLWriter.DescrBeginListItem;
  436. begin
  437. PushOutputNode(CreateEl(CurOutputNode, 'li'));
  438. end;
  439. procedure TBaseHTMLWriter.DescrEndListItem;
  440. begin
  441. PopOutputNode;
  442. end;
  443. procedure TBaseHTMLWriter.DescrBeginDefinitionTerm;
  444. begin
  445. PushOutputNode(CreateEl(CurOutputNode, 'dt'));
  446. end;
  447. procedure TBaseHTMLWriter.DescrEndDefinitionTerm;
  448. begin
  449. PopOutputNode;
  450. end;
  451. procedure TBaseHTMLWriter.DescrBeginDefinitionEntry;
  452. begin
  453. PushOutputNode(CreateEl(CurOutputNode, 'dd'));
  454. end;
  455. procedure TBaseHTMLWriter.DescrEndDefinitionEntry;
  456. begin
  457. PopOutputNode;
  458. end;
  459. procedure TBaseHTMLWriter.DescrBeginSectionTitle;
  460. begin
  461. PushOutputNode(CreateEl(CurOutputNode, 'h3'));
  462. end;
  463. procedure TBaseHTMLWriter.DescrBeginSectionBody;
  464. begin
  465. PopOutputNode;
  466. end;
  467. procedure TBaseHTMLWriter.DescrEndSection;
  468. begin
  469. end;
  470. procedure TBaseHTMLWriter.DescrBeginRemark;
  471. var
  472. NewEl, TDEl: TDOMElement;
  473. begin
  474. NewEl := CreateEl(CurOutputNode, 'table');
  475. NewEl['width'] := '100%';
  476. NewEl['border'] := '0';
  477. NewEl['CellSpacing'] := '0';
  478. NewEl['class'] := 'remark';
  479. NewEl := CreateTR(NewEl);
  480. TDEl := CreateTD(NewEl);
  481. TDEl['valign'] := 'top';
  482. TDEl['class'] := 'pre';
  483. AppendText(CreateEl(TDEl, 'b'), SDocRemark);
  484. PushOutputNode(CreateTD(NewEl));
  485. end;
  486. procedure TBaseHTMLWriter.DescrEndRemark;
  487. begin
  488. PopOutputNode;
  489. end;
  490. procedure TBaseHTMLWriter.DescrBeginTable(ColCount: Integer; HasBorder: Boolean);
  491. var
  492. Table: TDOMElement;
  493. begin
  494. Table := CreateEl(CurOutputNode, 'table');
  495. Table['border'] := UTF8Decode(IntToStr(Ord(HasBorder)));
  496. PushOutputNode(Table);
  497. end;
  498. procedure TBaseHTMLWriter.DescrEndTable;
  499. begin
  500. PopOutputNode;
  501. end;
  502. procedure TBaseHTMLWriter.DescrBeginTableCaption;
  503. begin
  504. PushOutputNode(CreateEl(CurOutputNode, 'caption'));
  505. end;
  506. procedure TBaseHTMLWriter.DescrEndTableCaption;
  507. begin
  508. PopOutputNode;
  509. end;
  510. procedure TBaseHTMLWriter.DescrBeginTableHeadRow;
  511. begin
  512. PushOutputNode(CreateTr(CurOutputNode));
  513. FInsideHeadRow := True;
  514. end;
  515. procedure TBaseHTMLWriter.DescrEndTableHeadRow;
  516. begin
  517. FInsideHeadRow := False;
  518. PopOutputNode;
  519. end;
  520. procedure TBaseHTMLWriter.DescrBeginTableRow;
  521. begin
  522. PushOutputNode(CreateTR(CurOutputNode));
  523. end;
  524. procedure TBaseHTMLWriter.DescrEndTableRow;
  525. begin
  526. PopOutputNode;
  527. end;
  528. procedure TBaseHTMLWriter.DescrBeginTableCell;
  529. begin
  530. if InsideHeadRow then
  531. PushOutputNode(CreateEl(CurOutputNode, 'th'))
  532. else
  533. PushOutputNode(CreateTD(CurOutputNode));
  534. end;
  535. procedure TBaseHTMLWriter.DescrEndTableCell;
  536. begin
  537. PopOutputNode;
  538. end;
  539. procedure TBaseHTMLWriter.SetHTMLDocument(aDoc: THTMLDocument);
  540. begin
  541. FDoc:=aDoc;
  542. FOutputNodeStack.Clear;
  543. FCurOutputNode:=Nil;
  544. end;
  545. procedure TBaseHTMLWriter.AppendText(Parent: TDOMNode; const AText: String);
  546. begin
  547. AppendText(Parent,UTF8Decode(aText));
  548. end;
  549. procedure TBaseHTMLWriter.AppendText(Parent: TDOMNode; const AText: DOMString);
  550. begin
  551. Parent.AppendChild(Doc.CreateTextNode(AText));
  552. end;
  553. procedure TBaseHTMLWriter.AppendNbSp(Parent: TDOMNode; ACount: Integer);
  554. begin
  555. while ACount > 0 do
  556. begin
  557. Parent.AppendChild(Doc.CreateEntityReference('nbsp'));
  558. Dec(ACount);
  559. end;
  560. end;
  561. procedure TBaseHTMLWriter.AppendSym(Parent: TDOMNode; const AText: DOMString);
  562. var
  563. El: TDOMElement;
  564. begin
  565. El := CreateEl(Parent, 'span');
  566. El['class'] := 'sym';
  567. AppendText(El, AText);
  568. end;
  569. procedure TBaseHTMLWriter.AppendKw(Parent: TDOMNode; const AText: String);
  570. begin
  571. AppendKW(Parent,UTF8Decode(aText));
  572. end;
  573. procedure TBaseHTMLWriter.AppendKw(Parent: TDOMNode; const AText: DOMString);
  574. var
  575. El: TDOMElement;
  576. begin
  577. El := CreateEl(Parent, 'span');
  578. El['class'] := 'kw';
  579. AppendText(El, AText);
  580. end;
  581. function TBaseHTMLWriter.AppendPasSHFragment(Parent: TDOMNode;
  582. const AText: String; AShFlags: Byte): Byte;
  583. var
  584. Line, Last, p: PChar;
  585. El: TDOMElement;
  586. Procedure MaybeOutput;
  587. Var
  588. CurParent: TDomNode;
  589. begin
  590. If (Last<>Nil) then
  591. begin
  592. If (el<>Nil) then
  593. CurParent:=El
  594. else
  595. CurParent:=Parent;
  596. AppendText(CurParent,Last);
  597. El:=Nil;
  598. Last:=Nil;
  599. end;
  600. end;
  601. Function NewEl(Const ElType,Attr,AttrVal : DOMString) : TDomElement;
  602. begin
  603. Result:=CreateEl(Parent,ElType);
  604. Result[Attr]:=AttrVal;
  605. end;
  606. Function NewSpan(Const AttrVal : DOMString) : TDomElement;
  607. begin
  608. Result:=CreateEl(Parent,'span');
  609. Result['class']:=AttrVal;
  610. end;
  611. begin
  612. GetMem(Line, Length(AText) * 3 + 4);
  613. Try
  614. DoPascalHighlighting(AShFlags, PChar(AText), Line);
  615. Result := AShFlags;
  616. Last := Nil;
  617. p := Line;
  618. el:=nil;
  619. while p[0] <> #0 do
  620. begin
  621. if p[0] = LF_ESCAPE then
  622. begin
  623. p[0] := #0;
  624. MaybeOutput;
  625. case Ord(p[1]) of
  626. shDefault: El:=Nil;
  627. shInvalid: El:=newel('font','color','red');
  628. shSymbol : El:=newspan('sym');
  629. shKeyword: El:=newspan('kw');
  630. shComment: El:=newspan('cmt');
  631. shDirective: El:=newspan('dir');
  632. shNumbers: El:=newspan('num');
  633. shCharacters: El:=newspan('chr');
  634. shStrings: El:=newspan('str');
  635. shAssembler: El:=newspan('asm');
  636. end;
  637. Inc(P);
  638. end
  639. else If (Last=Nil) then
  640. Last:=P;
  641. Inc(p);
  642. end;
  643. MaybeOutput;
  644. Finally
  645. FreeMem(Line);
  646. end;
  647. end;
  648. procedure TBaseHTMLWriter.AppendSeeAlsoSection ( AElement: TPasElement;
  649. DocNode: TDocNode ) ;
  650. var
  651. Node: TDOMNode;
  652. TableEl, El, TREl, ParaEl, NewEl, DescrEl: TDOMElement;
  653. l,s,n: DOMString;
  654. IsFirstSeeAlso : Boolean;
  655. begin
  656. if Not (Assigned(DocNode) and Assigned(DocNode.SeeAlso)) then
  657. Exit;
  658. IsFirstSeeAlso := True;
  659. Node:=DocNode.SeeAlso.FirstChild;
  660. While Assigned(Node) do
  661. begin
  662. if (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='link') then
  663. begin
  664. if IsFirstSeeAlso then
  665. begin
  666. IsFirstSeeAlso := False;
  667. AppendText(CreateH2(ContentElement), SDocSeeAlso);
  668. TableEl := CreateTable(ContentElement);
  669. end;
  670. El:=TDOMElement(Node);
  671. TREl:=CreateTR(TableEl);
  672. ParaEl:=CreatePara(CreateTD_vtop(TREl));
  673. l:=El['id'];
  674. if Assigned(Engine) and Engine.FalbackSeeAlsoLinks then
  675. s:= ResolveLinkIDUnStrict(UTF8ENcode(l))
  676. else
  677. s:= ResolveLinkID(UTF8ENcode(l));
  678. if Length(s)=0 then
  679. begin
  680. if assigned(module) then
  681. s:=UTF8Decode(module.name)
  682. else
  683. s:='?';
  684. if l='' then l:='<empty>';
  685. if Assigned(AElement) then
  686. N:=UTF8Decode(AElement.PathName)
  687. else
  688. N:='?';
  689. DoLog(SErrUnknownLinkID, [s,N,l]);
  690. LinkUnresolvedInc();
  691. NewEl := CreateEl(ParaEl,'b')
  692. end
  693. else
  694. NewEl := CreateLink(ParaEl,s);
  695. if Not IsDescrNodeEmpty(El) then
  696. begin
  697. PushOutputNode(NewEl);
  698. Try
  699. ConvertBaseShortList(AElement, El, True)
  700. Finally
  701. PopOutputNode;
  702. end;
  703. end
  704. else
  705. AppendText(NewEl,El['id']);
  706. l:=El['id'];
  707. DescrEl := Engine.FindShortDescr(AElement.GetModule,UTF8Encode(L));
  708. if Assigned(DescrEl) then
  709. begin
  710. AppendNbSp(CreatePara(CreateTD(TREl)), 2);
  711. ParaEl := CreatePara(CreateTD(TREl));
  712. ParaEl['class'] := 'cmt';
  713. PushOutputNode(ParaEl);
  714. try
  715. ConvertShort(AElement, DescrEl);
  716. finally
  717. PopOutputNode;
  718. end;
  719. end;
  720. end; // Link node
  721. Node := Node.NextSibling;
  722. end; // While
  723. end;
  724. procedure TBaseHTMLWriter.AppendExampleSection ( AElement: TPasElement; DocNode: TDocNode ) ;
  725. var
  726. Node: TDOMNode;
  727. fn,s: String;
  728. f: Text;
  729. begin
  730. if not (Assigned(DocNode) and Assigned(DocNode.FirstExample)) then
  731. Exit;
  732. Node := DocNode.FirstExample;
  733. while Assigned(Node) do
  734. begin
  735. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'example') then
  736. begin
  737. fn:=Engine.GetExampleFilename(TDOMElement(Node));
  738. If (fn<>'') then
  739. begin
  740. AppendText(CreateH2(ContentElement), SDocExample);
  741. try
  742. Assign(f, FN);
  743. Reset(f);
  744. try
  745. PushOutputNode(ContentElement);
  746. DescrBeginCode(False, UTF8Encode(TDOMElement(Node)['highlighter']));
  747. while not EOF(f) do
  748. begin
  749. ReadLn(f, s);
  750. DescrWriteCodeLine(s);
  751. end;
  752. DescrEndCode;
  753. PopOutputNode;
  754. finally
  755. Close(f);
  756. end;
  757. except
  758. on e: Exception do
  759. begin
  760. e.Message := '[example] ' + e.Message;
  761. raise;
  762. end;
  763. end;
  764. end;
  765. end;
  766. Node := Node.NextSibling;
  767. end;
  768. end;
  769. procedure TBaseHTMLWriter.AppendFragment(aParentNode : TDOMElement; aStream : TStream);
  770. begin
  771. if (aStream<>Nil) then
  772. begin
  773. aStream.Position:=0;
  774. ReadXMLFragment(aParentNode,aStream);
  775. end;
  776. end;
  777. procedure TBaseHTMLWriter.AppendShortDescr ( AContext: TPasElement;
  778. Parent: TDOMNode; DocNode: TDocNode ) ;
  779. Var
  780. N : TDocNode;
  781. begin
  782. if Assigned(DocNode) then
  783. begin
  784. If (DocNode.Link<>'') then
  785. begin
  786. N:=Engine.FindLinkedNode(DocNode);
  787. If (N<>Nil) then
  788. DocNode:=N;
  789. end;
  790. If Assigned(DocNode.ShortDescr) then
  791. begin
  792. PushOutputNode(Parent);
  793. try
  794. if not ConvertShort(AContext,TDomElement(DocNode.ShortDescr)) then
  795. Warning(AContext, SErrInvalidShortDescr)
  796. finally
  797. PopOutputNode;
  798. end;
  799. end;
  800. end;
  801. end;
  802. procedure TBaseHTMLWriter.AppendShortDescr(Parent: TDOMNode; Element: TPasElement);
  803. begin
  804. AppendShortDescr(Element,Parent,Engine.FindDocNode(Element));
  805. end;
  806. procedure TBaseHTMLWriter.AppendShortDescrCell(Parent: TDOMNode; Element: TPasElement);
  807. var
  808. ParaEl: TDOMElement;
  809. begin
  810. if Assigned(Engine.FindShortDescr(Element)) then
  811. begin
  812. AppendNbSp(CreatePara(CreateTD(Parent)), 2);
  813. ParaEl := CreatePara(CreateTD(Parent));
  814. ParaEl['class'] := 'cmt';
  815. AppendShortDescr(ParaEl, Element);
  816. end;
  817. end;
  818. procedure TBaseHTMLWriter.AppendDescr(AContext: TPasElement; Parent: TDOMNode;
  819. DescrNode: TDOMElement; AutoInsertBlock: Boolean);
  820. begin
  821. if Assigned(DescrNode) then
  822. begin
  823. PushOutputNode(Parent);
  824. try
  825. ConvertDescr(AContext, DescrNode, AutoInsertBlock);
  826. finally
  827. PopOutputNode;
  828. end;
  829. end;
  830. end;
  831. procedure TBaseHTMLWriter.AppendDescrSection(AContext: TPasElement; Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: String);
  832. begin
  833. AppendDescrSection(aContext,Parent,DescrNode,UTF8Decode(aTitle));
  834. end;
  835. procedure TBaseHTMLWriter.AppendDescrSection(AContext: TPasElement;
  836. Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: DOMString);
  837. begin
  838. if not IsDescrNodeEmpty(DescrNode) then
  839. begin
  840. If (ATitle<>'') then // Can be empty for topic.
  841. AppendText(CreateH2(Parent), ATitle);
  842. AppendDescr(AContext, Parent, DescrNode, True);
  843. end;
  844. end;
  845. function TBaseHTMLWriter.AppendHyperlink(Parent: TDOMNode; Element: TPasElement): TDOMElement;
  846. var
  847. s: DOMString;
  848. UnitList: TFPList;
  849. i: Integer;
  850. ThisPackage: TLinkNode;
  851. begin
  852. if Not Assigned(Element) then
  853. begin
  854. Result := nil;
  855. AppendText(CreateWarning(Parent), '<NIL>');
  856. end;
  857. if Element.InheritsFrom(TPasUnresolvedTypeRef) then
  858. begin
  859. s := ResolveLinkID(Element.Name);
  860. if Length(s) = 0 then
  861. begin
  862. { Try all packages }
  863. ThisPackage := Engine.RootLinkNode.FirstChild;
  864. while Assigned(ThisPackage) do
  865. begin
  866. s := ResolveLinkID(ThisPackage.Name + '.' + Element.Name);
  867. if Length(s) > 0 then
  868. break;
  869. ThisPackage := ThisPackage.NextSibling;
  870. end;
  871. if (Length(s) = 0) and Assigned(Module) then
  872. begin
  873. { Okay, then we have to try all imported units of the current module }
  874. UnitList := Module.InterfaceSection.UsesList;
  875. for i := UnitList.Count - 1 downto 0 do
  876. begin
  877. { Try all packages }
  878. ThisPackage := Engine.RootLinkNode.FirstChild;
  879. while Assigned(ThisPackage) do
  880. begin
  881. s := ResolveLinkID(ThisPackage.Name + '.' +
  882. TPasType(UnitList[i]).Name + '.' + Element.Name);
  883. if Length(s) > 0 then
  884. break;
  885. ThisPackage := ThisPackage.NextSibling;
  886. end;
  887. if length(s)=0 then
  888. s := ResolveLinkID('#rtl.System.' + Element.Name);
  889. if Length(s) > 0 then
  890. break;
  891. end;
  892. end;
  893. end;
  894. end
  895. else if Element is TPasEnumValue then
  896. s := ResolveLinkID(Element.Parent.PathName)
  897. else if Element is TPasAliasType then
  898. s := ResolveLinkID(TPasAliasType(Element).DestType.PathName)
  899. else
  900. s := ResolveLinkID(Element.PathName);
  901. if Length(s) > 0 then
  902. begin
  903. Result := CreateLink(Parent, s);
  904. AppendText(Result, Element.Name);
  905. end
  906. else
  907. begin
  908. Result := nil;
  909. if Element is TPasAliasType then
  910. AppendText(Parent, TPasAliasType(Element).DestType.Name)
  911. else
  912. AppendText(Parent, Element.Name); // unresolved items
  913. end;
  914. end;
  915. procedure TBaseHTMLWriter.AppendSourceRef(aParent : TDOMElement; AElement: TPasElement);
  916. begin
  917. AppendText(CreatePara(aParent), Format(SDocSourcePosition,
  918. [ExtractFileName(AElement.SourceFilename), AElement.SourceLinenumber]));
  919. end;
  920. end.