dw_basehtml.pp 28 KB

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