dw_markdown.pp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973
  1. {
  2. FPDoc - Free Pascal Documentation Tool
  3. Copyright (C) 2021 by Michael Van Canneyt
  4. * Markdown generator, multi-file
  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. {$mode objfpc}
  12. {$H+}
  13. unit dw_markdown;
  14. {$WARN 5024 off : Parameter "$1" not used}
  15. interface
  16. uses Classes, dGlobals, PasTree, dWriter, dw_basemd, DOM;
  17. type
  18. TMemberListOption = (mloAppendParent,mloAppendType,mloCheckVisibility);
  19. TMemberListOptions = Set of TMemberListOption;
  20. TNavigationMode = (nmUnitTree,nmUnitSubTree);
  21. { TMarkdownWriter }
  22. TMarkdownWriter = class(TBaseMarkdownWriter)
  23. private
  24. FBaseImageURL: String;
  25. FImageFileList: TStrings;
  26. FIndexColCount: Integer;
  27. FAdditionalConfig : TStrings;
  28. FFooterMarkDown : TStrings;
  29. FHeaderMarkDown : TStrings;
  30. FNavigationMode: TNavigationMode;
  31. FOnTest: TNotifyEvent;
  32. FNavigation : TStrings;
  33. FUnitSubTreeStarted : Boolean;
  34. function GetAdditionalConfig: TStrings;
  35. function GetClassDeclaration(aEl: TPasClassType): String;
  36. function GetClassDeclarationFirstLine(aEl: TPasClassType): String;
  37. function GetDeclaration(aEl: TPasElement): String;
  38. function GetFooterMarkDown: TStrings;
  39. function GetHeaderMarkDown: TStrings;
  40. function GetPageCount: Integer;
  41. procedure SetOnTest(const AValue: TNotifyEvent);
  42. protected
  43. function GetFileBaseDir(aOutput: String): String; override;
  44. // MkDocs
  45. procedure WriteMkdocsYaml; virtual;
  46. procedure CreateMkdocsYaml(mkDocs: TStrings); virtual;
  47. procedure AddToNavigation(const aFileName: String; aElement: TPasElement; aSubPageIndex: Integer);
  48. // Some raw markdown functions
  49. procedure AppendPageFooter; virtual;
  50. procedure WriteMetadata; virtual;
  51. procedure AppendPageHeader; virtual;
  52. Procedure AppendText(Const S : String);
  53. Procedure AppendTitle(Const S : String);
  54. Procedure AppendTitle(Const Fmt : String; Const Args : Array of const);
  55. // Description
  56. Procedure AppendShortDescr(AContext : TPasElement; DocNode : TDocNode); virtual;
  57. procedure AppendShortDescr(Element: TPasElement); virtual;
  58. procedure AppendShortDescrCell(Element: TPasElement); virtual;
  59. procedure AppendDescr(AContext: TPasElement; DescrNode: TDOMElement; AutoInsertBlock: Boolean); virtual;
  60. procedure AppendDescrSection(AContext: TPasElement; DescrNode: TDOMElement; const ATitle: String); virtual;
  61. procedure AppendDescrSection(AContext: TPasElement; DescrNode: TDOMElement; const ATitle: DOMString); virtual;
  62. Procedure AppendHyperlink(Element: TPasElement);
  63. Function CreateHyperlink(Element: TPasElement) : string;
  64. // Reusable routines
  65. procedure CollectDeclarationTypes(aList: TStringList; aElement: TPasElement );
  66. procedure CollectSeeAlsoNodes(aList: TStringList; aSeeAlso: TDomNode);
  67. procedure AddModuleIdentifiers(AModule : TPasModule; L : TStrings);
  68. procedure AppendSourceRef(AElement: TPasElement); virtual;
  69. procedure AppendDeclaration(aEl: TPasElement; aKind: string; PrependVisibility: Boolean); virtual;
  70. procedure FinishElementPage(AElement: TPasElement; SkipDescription: Boolean=false); virtual;
  71. Procedure AppendSeeAlsoSection(AElement : TPasElement;DocNode : TDocNode); virtual;
  72. Procedure AppendExampleSection(AElement : TPasElement;DocNode : TDocNode); virtual;
  73. procedure AppendProcArgsSection(Element: TPasProcedureBase); virtual;
  74. procedure CreateMemberDeclarations(AParent: TPasElement; Members: TFPList; Options : TMemberListOptions); virtual;
  75. Procedure CreateTopicLinks(Node : TDocNode; PasElement : TPasElement); virtual;
  76. procedure CreateIndexPage(L : TStringList); virtual;
  77. procedure CreateSimpleSubpage(aModule: TPasModule; const ATitle, aItem: String; AList: TFPList); virtual;
  78. // Various kind of pages.
  79. // Main entry
  80. procedure CreatePageBody(AElement: TPasElement; ASubpageIndex: Integer); virtual;
  81. // Package
  82. procedure CreatePackagePageBody; virtual;
  83. procedure CreatePackageIndex; virtual;
  84. procedure CreatePackageClassHierarchy; virtual;
  85. procedure CreateClassHierarchyPage(AddUnit : Boolean); virtual;
  86. // Module
  87. procedure CreateModuleIndexPage(AModule: TPasModule); virtual;
  88. procedure CreateModuleMainPageBody(AModule: TPasModule); virtual;
  89. procedure CreateModulePageBody(AModule: TPasModule; ASubpageIndex: Integer); virtual;
  90. // Per simple type
  91. procedure CreateResStringsPage(aModule: TPasModule); virtual;
  92. Procedure CreateTopicPageBody(AElement : TTopicElement); virtual;
  93. procedure CreateConstPageBody(AConst: TPasConst); virtual;
  94. procedure CreateTypePageBody(AType: TPasType); virtual;
  95. procedure CreateVarPageBody(AVar: TPasVariable); virtual;
  96. procedure CreateProcPageBody(AProc: TPasProcedureBase); virtual;
  97. // Class/Record
  98. procedure CreateClassMainPage(aClass: TPasClassType); virtual;
  99. procedure CreateClassPageBody(AClass: TPasClassType; ASubpageIndex: Integer); virtual;
  100. procedure CreateClassMemberPageBody(AElement: TPasElement); virtual;
  101. procedure CreateInheritanceSubpage(aClass: TPasClassType; aTitle : string; AFilter: TMemberFilter); virtual;
  102. procedure CreateSortedSubpage(ACLass: TPasClassType; aTitle : string; AFilter: TMemberFilter ); virtual;
  103. // Here we write the documentation
  104. Procedure DoWriteDocumentation; override;
  105. public
  106. constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
  107. destructor Destroy; override;
  108. // Single-page generation
  109. procedure WriteDocPage(const aFileName: String; aElement: TPasElement; aSubPageIndex: Integer); override;
  110. // Start producing html complete package documentation
  111. Function InterPretOption(Const Cmd,Arg : String) : boolean; override;
  112. Class Function FileNameExtension : String; override;
  113. class procedure Usage(List: TStrings); override;
  114. Class procedure SplitImport(var AFilename, ALinkPrefix: String); override;
  115. property OnTest: TNotifyEvent read FOnTest write SetOnTest;
  116. Property IndexColCount : Integer Read FIndexColCount write FIndexColCount;
  117. Property BaseImageURL : String Read FBaseImageURL Write FBaseImageURL;
  118. Property HeaderMarkDown : TStrings Read GetHeaderMarkDown;
  119. Property FooterMarkDown : TStrings Read GetFooterMarkDown;
  120. property AdditionalConfig : TStrings Read GetAdditionalConfig;
  121. property NavigationMode: TNavigationMode Read FNavigationMode;
  122. end;
  123. implementation
  124. uses fpdocstrs, SysUtils, fpdocclasstree;
  125. Function FixHTMLpath(S : String) : STring;
  126. begin
  127. Result:=StringReplace(S,'\','/',[rfReplaceAll]);
  128. end;
  129. constructor TMarkdownWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
  130. begin
  131. inherited Create(APackage, AEngine);
  132. IndexColCount:=3;
  133. FImageFileList := TStringList.Create;
  134. FNavigation:=TStringList.Create;
  135. end;
  136. destructor TMarkdownWriter.Destroy;
  137. begin
  138. FreeAndNil(FImageFileList);
  139. FreeAndNil(FAdditionalConfig);
  140. FreeAndNil(FFooterMarkDown);
  141. FreeAndNil(FHeaderMarkDown);
  142. FreeAndNil(FNavigation);
  143. inherited Destroy;
  144. end;
  145. procedure TMarkdownWriter.AddToNavigation(const aFileName: String; aElement: TPasElement; aSubPageIndex: Integer);
  146. Procedure AddToNav(aLevel : Integer; aName,aFile : String);
  147. begin
  148. if aName<>'' then
  149. aName:=''''+aName+''':';
  150. if aFile<>'' then
  151. aFile:=' '''+aFile+'''';
  152. FNavigation.Add(StringOfChar(' ',aLevel*4)+'- '+aName+aFile);
  153. end;
  154. Var
  155. Offs : Integer;
  156. begin
  157. if aElement is TPasPackage then
  158. begin
  159. case aSubPageIndex of
  160. IdentifierIndex:
  161. begin
  162. AddToNav(1,SDocPackageLinkTitle,'');
  163. AddToNav(2,SDocOverview,aFileName);
  164. end;
  165. IndexSubIndex : AddToNav(2,SDocIdentifierIndex,aFileName);
  166. ClassHierarchySubIndex : AddToNav(2,SDocPackageClassHierarchy,aFileName);
  167. end
  168. end
  169. else if (aElement is TPasModule) then
  170. begin
  171. offS:=Ord (NavigationMode=nmUnitSubTree);
  172. if Offs=1 then
  173. if Not FUnitSubTreeStarted then
  174. begin
  175. FUnitSubTreeStarted:=True;
  176. AddToNav(1,SDocUnits,'');
  177. end;;
  178. case aSubPageIndex of
  179. IdentifierIndex :
  180. begin
  181. if Offs=0 then
  182. AddToNav(1+Offs,Format(StringReplace(SDocUnitMenuTitle,'''','',[rfReplaceALl]),[aElement.Name]),'')
  183. else
  184. AddToNav(1+Offs,aElement.Name,'');
  185. AddToNav(2+offs,SDocOverview,aFileName);
  186. end;
  187. ResstrSubindex: AddToNav(2+Offs,SDocResStrings,aFileName);
  188. ConstsSubindex: AddToNav(2+Offs,SDocConstants,aFileName);
  189. TypesSubindex: AddToNav(2+Offs,SDocTypes,aFileName);
  190. ClassesSubindex: AddToNav(2+Offs,SDocClasses,aFileName);
  191. ProcsSubindex: AddToNav(2+Offs,SDocProceduresAndFunctions,aFileName);
  192. VarsSubindex: AddToNav(2+Offs,SDocVariables,aFileName);
  193. end;
  194. end
  195. end;
  196. procedure TMarkdownWriter.WriteDocPage(const aFileName: String; aElement: TPasElement; aSubPageIndex: Integer);
  197. begin
  198. if MarkDownEngine=meMkDocs then
  199. AddToNavigation(aFileName,aElement,aSubPageIndex);
  200. ClearMarkDown;
  201. WriteMetaData;
  202. AppendPageHeader;
  203. CreatePageBody(AElement, ASubpageIndex);
  204. AppendPageFooter;
  205. SaveToFile(GetFileBaseDir(Engine.Output)+aFileName);
  206. end;
  207. procedure TMarkdownWriter.WriteMetadata;
  208. begin
  209. end;
  210. procedure TMarkdownWriter.AppendPageHeader;
  211. Var
  212. S : String;
  213. begin
  214. if Assigned(FHeaderMarkDown) then
  215. begin
  216. EnsureEmptyLine;
  217. For S in FHeaderMarkDown do
  218. AppendToLine(S,False)
  219. end;
  220. end;
  221. procedure TMarkdownWriter.WriteMkdocsYaml;
  222. Var
  223. mkDocs : TStrings;
  224. begin
  225. mkDocs:=TStringList.Create;
  226. try
  227. CreatemkDocsYaml(mkDocs);
  228. mkDocs.SaveToFile(Engine.Output+PathDelim+'mkdocs.yml');
  229. finally
  230. Mkdocs.Free;
  231. end;
  232. end;
  233. procedure TMarkdownWriter.CreateMkdocsYaml(mkDocs: TStrings);
  234. begin
  235. With MKDocs do
  236. begin
  237. add('site_name: '+SDocPackageTitle,[Package.Name]);
  238. add('');
  239. add('docs_dir: docs');
  240. add('');
  241. add('site_dir: site');
  242. add('');
  243. add('markdown_extensions:');
  244. add(' - def_list');
  245. add(' - codehilite');
  246. add(' - admonition');
  247. add('');
  248. add('theme: '+Theme);
  249. If Assigned(FAdditionalConfig) then
  250. begin
  251. add('');
  252. AddStrings(FAdditionalConfig);
  253. end;
  254. add('');
  255. add('nav:');
  256. AddStrings(FNavigation);
  257. end;
  258. end;
  259. procedure TMarkdownWriter.DoWriteDocumentation;
  260. begin
  261. Inherited;
  262. If MarkDownEngine=memkDocs then
  263. WriteMkdocsYaml;
  264. end;
  265. function TMarkdownWriter.GetFooterMarkDown: TStrings;
  266. begin
  267. If FFooterMarkDown=Nil then
  268. FFooterMarkDown:=TStringList.Create;
  269. Result:=FFooterMarkDown;
  270. end;
  271. function TMarkdownWriter.GetHeaderMarkDown: TStrings;
  272. begin
  273. If FHeaderMarkDown=Nil then
  274. FHeaderMarkDown:=TStringList.Create;
  275. Result:=FHeaderMarkDown;
  276. end;
  277. procedure TMarkdownWriter.AppendShortDescr(AContext: TPasElement; DocNode: TDocNode) ;
  278. Var
  279. N : TDocNode;
  280. begin
  281. if Not Assigned(DocNode) then
  282. exit;
  283. N:=Nil;
  284. If (DocNode.Link<>'') then
  285. N:=Engine.FindLinkedNode(DocNode);
  286. If (N=Nil) then
  287. N:=DocNode;
  288. If Assigned(N.ShortDescr) then
  289. if not ConvertShort(AContext,N.ShortDescr) then
  290. Warning(AContext, SErrInvalidShortDescr)
  291. end;
  292. procedure TMarkdownWriter.AppendShortDescr(Element: TPasElement);
  293. begin
  294. AppendShortDescr(Element,Engine.FindDocNode(Element));
  295. end;
  296. procedure TMarkdownWriter.AppendShortDescrCell(Element: TPasElement);
  297. begin
  298. if Not Assigned(Engine.FindShortDescr(Element)) then
  299. exit;
  300. DescrBeginTableCell;
  301. AppendShortDescr(Element);
  302. DescrEndTableCell;
  303. end;
  304. procedure TMarkdownWriter.AppendDescr(AContext: TPasElement; DescrNode: TDOMElement; AutoInsertBlock: Boolean);
  305. begin
  306. if Not Assigned(DescrNode) then
  307. exit;
  308. EnsureEmptyLine;
  309. ConvertDescr(AContext, DescrNode, AutoInsertBlock);
  310. end;
  311. procedure TMarkdownWriter.AppendDescrSection(AContext: TPasElement; DescrNode: TDOMElement; const ATitle: String);
  312. begin
  313. if IsDescrNodeEmpty(DescrNode) then
  314. exit;
  315. If (ATitle<>'') then // Can be empty for topic.
  316. AppendHeader(2,ATitle);
  317. AppendDescr(AContext, DescrNode, True);
  318. end;
  319. procedure TMarkdownWriter.AppendDescrSection(AContext: TPasElement; DescrNode: TDOMElement; const ATitle: DOMString);
  320. begin
  321. AppendDescrSection(aContext,DescrNode,UTF8Encode(aTitle));
  322. end;
  323. procedure TMarkdownWriter.AppendHyperlink(Element: TPasElement);
  324. begin
  325. if Not Assigned(Element) then
  326. begin
  327. AppendText('<NIL>');
  328. exit;
  329. end;
  330. AppendToLine(CreateHyperLink(Element),False)
  331. end;
  332. function TMarkdownWriter.CreateHyperlink(Element: TPasElement): string;
  333. var
  334. s: DOMString;
  335. UnitList: TFPList;
  336. i: Integer;
  337. ThisPackage: TLinkNode;
  338. begin
  339. if Not Assigned(Element) then
  340. Exit('\<NIL\>');
  341. if Not Element.InheritsFrom(TPasUnresolvedTypeRef) then
  342. begin
  343. if Element is TPasEnumValue then
  344. s := ResolveLinkID(Element.Parent.PathName)
  345. else
  346. s := ResolveLinkID(Element.PathName);
  347. end
  348. else
  349. begin
  350. s := ResolveLinkID(Element.Name);
  351. if Length(s) = 0 then
  352. begin
  353. { Try all packages }
  354. ThisPackage := Engine.RootLinkNode.FirstChild;
  355. while Assigned(ThisPackage) do
  356. begin
  357. s := ResolveLinkID(ThisPackage.Name + '.' + Element.Name);
  358. if Length(s) > 0 then
  359. break;
  360. ThisPackage := ThisPackage.NextSibling;
  361. end;
  362. if (Length(s) = 0) and Assigned(Module) then
  363. begin
  364. { Okay, then we have to try all imported units of the current module }
  365. UnitList := Module.InterfaceSection.UsesList;
  366. for i := UnitList.Count - 1 downto 0 do
  367. begin
  368. { Try all packages }
  369. ThisPackage := Engine.RootLinkNode.FirstChild;
  370. while Assigned(ThisPackage) do
  371. begin
  372. s := ResolveLinkID(ThisPackage.Name + '.' +
  373. TPasType(UnitList[i]).Name + '.' + Element.Name);
  374. if Length(s) > 0 then
  375. break;
  376. ThisPackage := ThisPackage.NextSibling;
  377. end;
  378. if length(s)=0 then
  379. s := ResolveLinkID('#rtl.System.' + Element.Name);
  380. if Length(s) > 0 then
  381. break;
  382. end;
  383. end;
  384. end;
  385. end;
  386. if Length(s) > 0 then
  387. Result:=CreateLink(Element.Name,UTF8Encode(S))
  388. else
  389. Result:=Element.Name;
  390. end;
  391. procedure TMarkdownWriter.AppendProcArgsSection(Element: TPasProcedureBase);
  392. var
  393. HasFullDescr, IsFirstType: Boolean;
  394. ResultEl: TPasResultElement;
  395. DocNode: TDocNode;
  396. aList : TStringList;
  397. Procedure CollectVariant(AProc: TPasProcedure);
  398. var
  399. i: Integer;
  400. Arg: TPasArgument;
  401. aType : TPasProcedureType;
  402. begin
  403. aType:=aProc.ProcType;
  404. for I:=0 to aType.Args.Count-1 do
  405. begin
  406. Arg:=TPasArgument(aType.Args[i]);
  407. if IsDescrNodeEmpty(Engine.FindShortDescr(Arg)) then
  408. Continue;
  409. aList.AddObject(Arg.Name,Arg);
  410. end;
  411. if (aType is TPasFunctionType) and (ResultEl=Nil) then
  412. ResultEl:=TPasFunctionType(aType).ResultEl;
  413. end;
  414. Procedure WriteType(aProc : TPasProcedure; aName: string);
  415. var
  416. i: Integer;
  417. Arg: TPasArgument;
  418. aType : TPasProcedureType;
  419. begin
  420. aType:=aProc.ProcType;
  421. for I:=0 to aType.Args.Count-1 do
  422. begin
  423. Arg:=TPasArgument(aType.Args[i]);
  424. if SameText(Arg.Name,aName) then
  425. begin
  426. if not IsFirstType then
  427. AppendText(', ');
  428. AppendHyperlink(Arg.ArgType);
  429. end;
  430. if IsDescrNodeEmpty(Engine.FindShortDescr(Arg)) then
  431. Continue;
  432. aList.AddObject(Arg.Name,Arg);
  433. end;
  434. end;
  435. Procedure WriteTypes(aName: string);
  436. Var
  437. I : Integer;
  438. begin
  439. IsFirstType:=True;
  440. if Element.ClassType <> TPasOverloadedProc then
  441. WriteType(TPasProcedure(Element),aName)
  442. else for i := 0 to TPasOverloadedProc(Element).Overloads.Count - 1 do
  443. WriteType(TPasProcedure(TPasOverloadedProc(Element).Overloads[i]),AName);
  444. end;
  445. Var
  446. I: Integer;
  447. begin
  448. ResultEl:=Nil;
  449. aList:=TStringList.Create;
  450. try
  451. AList.Duplicates:=DupIgnore;
  452. if Element.ClassType <> TPasOverloadedProc then
  453. CollectVariant(TPasProcedure(Element))
  454. else for i := 0 to TPasOverloadedProc(Element).Overloads.Count - 1 do
  455. CollectVariant(TPasProcedure(TPasOverloadedProc(Element).Overloads[i]));
  456. If AList.Count<>0 then
  457. begin
  458. AppendHeader(2,SDocArguments);
  459. AppendTableHeader([SDocName,SDocTypes,SDocDescription]);
  460. for I:=0 to aList.Count-1 do
  461. begin
  462. DescrBeginTableRow;
  463. DescrBeginTableCell;
  464. AppendText(aList[i]);
  465. DescrEndTableCell;
  466. DescrBeginTableCell;
  467. WriteTypes(aList[i]);
  468. DescrEndTableCell;
  469. AppendShortDescrCell(TPasArgument(aList.Objects[i]));
  470. DescrEndTableRow;
  471. end;
  472. DescrEndTable;
  473. end;
  474. finally
  475. aList.Free;
  476. end;
  477. if Not Assigned(ResultEl) then
  478. Exit;
  479. DocNode := Engine.FindDocNode(ResultEl);
  480. HasFullDescr := Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.Descr);
  481. if HasFullDescr or
  482. (Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.ShortDescr)) then
  483. begin
  484. AppendHeader(2, SDocFunctionResult);
  485. if HasFullDescr then
  486. AppendDescr(ResultEl,DocNode.Descr, True)
  487. else
  488. AppendDescr(ResultEl,DocNode.ShortDescr, False);
  489. end;
  490. end;
  491. procedure TMarkdownWriter.AppendSourceRef(AElement: TPasElement);
  492. begin
  493. EnsureEmptyLine;
  494. AppendToLine(Format(SDocSourcePosition,
  495. [ExtractFileName(AElement.SourceFilename), AElement.SourceLinenumber]));
  496. EnsureEmptyLine;
  497. end;
  498. procedure TMarkdownWriter.CollectSeeAlsoNodes(aList : TStringList; aSeeAlso: TDomNode);
  499. Var
  500. Node : TDOMNode;
  501. L : String;
  502. El : TDOMElement;
  503. begin
  504. Node:=aSeeAlso.FirstChild;
  505. While Assigned(Node) do
  506. begin
  507. if (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='link') then
  508. begin
  509. El:=TDOMElement(Node);
  510. l:=UTF8encode(El['id']);
  511. aList.AddObject(L,El);
  512. end;
  513. Node:=Node.NextSibling;
  514. end;
  515. end;
  516. procedure TMarkdownWriter.CollectDeclarationTypes(aList : TStringList; aElement : TPasElement);
  517. Procedure MaybeAdd(aType : TPasType);
  518. Var
  519. N : TDocNode;
  520. begin
  521. if aType is TPasPointerType then
  522. aType:=TPasPointerType(aType).DestType;
  523. if (aType=Nil) or (aType.Name='') then
  524. exit;
  525. N:=Engine.FindDocNode(aType);
  526. if N<>Nil then
  527. aList.AddObject(aType.Name,aType);
  528. end;
  529. Var
  530. I : integer;
  531. begin
  532. if aElement is TPasVariable then
  533. MaybeAdd(TPasVariable(aElement).VarType)
  534. else if aElement is TPasMembersType then
  535. begin
  536. for I:=0 to TPasMembersType(aElement).Members.Count-1 do
  537. if TObject(TPasMembersType(aElement).Members[i]) is TPasVariable then
  538. MaybeAdd(TPasVariable(TPasMembersType(aElement).Members[i]).VarType);
  539. end;
  540. end;
  541. procedure TMarkdownWriter.AppendSeeAlsoSection(AElement: TPasElement; DocNode: TDocNode) ;
  542. Procedure AppendSeeALso(aID : String; El: TDomElement);
  543. Var
  544. S,N : DOMString;
  545. doBold : Boolean;
  546. begin
  547. s:= ResolveLinkID(aID);
  548. doBold:=Length(S)=0;
  549. if DoBold then
  550. begin
  551. if assigned(module) then
  552. s:=UTF8Decode(module.name)
  553. else
  554. s:='?';
  555. if aID='' then aID:='<empty>';
  556. if Assigned(AElement) then
  557. N:=UTF8Decode(AElement.Name)
  558. else
  559. N:='?';
  560. DoLog(SErrUnknownLinkID, [s,N,aID]);
  561. LinkUnresolvedInc();
  562. end ;
  563. if doBold then
  564. DescrBeginBold
  565. else
  566. DescrBeginURL(S);
  567. if Not IsDescrNodeEmpty(El) then
  568. ConvertBaseShortList(AElement, El, True)
  569. else
  570. AppendText(aID);
  571. if doBold then
  572. DescrEndBold
  573. else
  574. DescrEndURL();
  575. end;
  576. Procedure AppendTypeRef(aName : String; El: TPasType);
  577. begin
  578. AppendHyperLink(El);
  579. end;
  580. var
  581. I : Integer;
  582. aList : TStringList;
  583. DescrEl : TDomElement;
  584. begin
  585. if Not (Assigned(DocNode) and Assigned(DocNode.SeeAlso)) then
  586. Exit;
  587. AList:=TStringList.Create;
  588. Try
  589. aList.Duplicates:=dupIgnore;
  590. // AList will have a TDomElement (seealso) or a TPasType element as object
  591. CollectSeeAlsoNodes(aList,DocNode.SeeAlso);
  592. CollectDeclarationTypes(aList,aElement);
  593. if aList.Count = 0 then
  594. exit;
  595. aList.Sort;
  596. AppendHeader(2,SDocSeeAlso);
  597. AppendTableHeader([SDocName,SDocDescription]);
  598. For I:=0 to aList.Count-1 do
  599. begin
  600. DescrEl:=Nil;
  601. DescrBeginTableRow;
  602. DescrBeginTableCell;
  603. if aList.Objects[I] is TDomElement then
  604. AppendSeeAlso(aList[i],TDomElement(aList.Objects[i]))
  605. else if aList.Objects[i] is TPasType then
  606. AppendTypeRef(aList[i],TPasType(aList.Objects[i]));
  607. DescrEndTableCell;
  608. DescrBeginTableCell;
  609. DescrEl:=Engine.FindShortDescr(AElement.GetModule(),UTF8Encode(aList[i]));
  610. if Assigned(DescrEl) then
  611. ConvertShort(AElement, DescrEl)
  612. else
  613. AppendToLine(' ',False);
  614. DescrEndTableCell;
  615. DescrEndTableRow;
  616. end;
  617. DescrEndTable;
  618. Finally
  619. aList.Free;
  620. end;
  621. end;
  622. procedure TMarkdownWriter.AppendExampleSection ( AElement: TPasElement;
  623. DocNode: TDocNode ) ;
  624. var
  625. Node: TDOMNode;
  626. fn,s: String;
  627. f: Text;
  628. begin
  629. if not (Assigned(DocNode) and Assigned(DocNode.FirstExample)) then
  630. Exit;
  631. Node := DocNode.FirstExample;
  632. while Assigned(Node) do
  633. begin
  634. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'example') then
  635. begin
  636. fn:=Engine.GetExampleFilename(TDOMElement(Node));
  637. If (fn<>'') then
  638. begin
  639. AppendHeader(2, SDocExample);
  640. try
  641. Assign(f, FN);
  642. Reset(f);
  643. try
  644. DescrBeginCode(False, UTF8Encode(TDOMElement(Node)['highlighter']));
  645. while not EOF(f) do
  646. begin
  647. ReadLn(f, s);
  648. DescrWriteCodeLine(s);
  649. end;
  650. finally
  651. Close(f);
  652. DescrEndCode;
  653. end;
  654. except
  655. on e: Exception do
  656. begin
  657. e.Message := '[example] ' + e.Message;
  658. raise;
  659. end;
  660. end;
  661. end;
  662. end;
  663. Node := Node.NextSibling;
  664. end;
  665. end;
  666. procedure TMarkdownWriter.AppendPageFooter;
  667. Var
  668. S : String;
  669. begin
  670. if Assigned(FFooterMarkDown) then
  671. begin
  672. EnsureEmptyLine;
  673. For S in FFooterMarkDown do
  674. AppendToLine(S,False)
  675. end;
  676. end;
  677. procedure TMarkdownWriter.FinishElementPage(AElement: TPasElement; SkipDescription : Boolean = false);
  678. var
  679. DocNode: TDocNode;
  680. begin
  681. DocNode := Engine.FindDocNode(AElement);
  682. If Not Assigned(DocNode) then
  683. exit;
  684. // Description
  685. if Assigned(DocNode.Descr) and not SkipDescription then
  686. AppendDescrSection(AElement, DocNode.Descr, UTF8Encode(SDocDescription));
  687. // Append "Errors" section
  688. if Assigned(DocNode.ErrorsDoc) then
  689. AppendDescrSection(AElement, DocNode.ErrorsDoc, UTF8Encode(SDocErrors));
  690. // Append Version info
  691. if Assigned(DocNode.Version) then
  692. AppendDescrSection(AElement, DocNode.Version, UTF8Encode(SDocVersion));
  693. // Append "See also" section
  694. AppendSeeAlsoSection(AElement,DocNode);
  695. // Append examples, if present
  696. AppendExampleSection(AElement,DocNode);
  697. // Append notes, if present
  698. ConvertNotes(AElement,DocNode.Notes);
  699. end;
  700. procedure TMarkdownWriter.CreateTopicPageBody(AElement: TTopicElement);
  701. var
  702. DocNode: TDocNode;
  703. begin
  704. DocNode:=AElement.TopicNode;
  705. AppendTitle(AElement.Name);
  706. if not Assigned(DocNode) then // should always be true, but we're being careful.
  707. exit;
  708. AppendShortDescr(AElement, DocNode);
  709. if Assigned(DocNode.Descr) then
  710. AppendDescrSection(AElement, DocNode.Descr, '');
  711. AppendSeeAlsoSection(AElement,DocNode);
  712. CreateTopicLinks(DocNode,AElement);
  713. AppendExampleSection(AElement,DocNode);
  714. ConvertNotes(AElement,DocNode.Notes);
  715. end;
  716. procedure TMarkdownWriter.CreateClassHierarchyPage(AddUnit : Boolean);
  717. type
  718. TypeEN = (NPackage, NModule, NName);
  719. Procedure AddClassList;
  720. begin
  721. DescrBeginUnorderedList;
  722. end;
  723. Procedure EndClassList;
  724. begin
  725. DescrEndUnorderedList;
  726. end;
  727. function ExtractName(APathName: String; Tp: TypeEN):String;
  728. var
  729. l:TStringList;
  730. begin
  731. Result:= Trim(APathName);
  732. if Result = '' then exit;
  733. l:=TStringList.Create;
  734. try
  735. l.AddDelimitedText(Result, '.', True);
  736. if l.Count=3 then
  737. Result:= l.Strings[Integer(Tp)]
  738. else
  739. Result:='';
  740. finally
  741. l.free;
  742. end;
  743. end;
  744. Procedure AppendClass(EN : TPasElementNode);
  745. Var
  746. PE,PM : TPasElement;
  747. I : Integer;
  748. begin
  749. if not Assigned(EN) then exit;
  750. PE:=EN.Element;
  751. DescrBeginListItem;
  752. AppendHyperLink(PE);
  753. PM:=PE.GetModule();
  754. if (PM<>Nil) then
  755. begin
  756. AppendText(' (');
  757. AppendHyperLink(PM);
  758. AppendText(')');
  759. end
  760. else
  761. AppendText(EN.Element.Name);
  762. if EN.ChildCount>0 then
  763. begin
  764. AddClassList;
  765. For I:=0 to EN.ChildCount-1 do
  766. AppendClass(EN.Children[i] as TPasElementNode);
  767. EndClassList;
  768. end;
  769. DescrEndListItem;
  770. end;
  771. begin
  772. AddClassList;
  773. AppendClass(TreeClass.RootNode);
  774. EndClassList;
  775. end;
  776. procedure TMarkdownWriter.CreatePackageClassHierarchy;
  777. Var
  778. S : String;
  779. begin
  780. S:=Package.Name;
  781. If Length(S)>0 then
  782. Delete(S,1,1);
  783. AppendTitle(SDocPackageClassHierarchy, [S]);
  784. CreateClassHierarchyPage(True);
  785. end;
  786. procedure TMarkdownWriter.CreatePageBody(AElement: TPasElement; ASubpageIndex: Integer);
  787. var
  788. i: Integer;
  789. Element: TPasElement;
  790. begin
  791. CurDirectory := Allocator.GetFilename(AElement, ASubpageIndex);
  792. i := Length(CurDirectory);
  793. while (i > 0) and not (CurDirectory[i] in AllowDirectorySeparators) do
  794. Dec(i);
  795. CurDirectory := Copy(CurDirectory, 1, i);
  796. BaseDirectory := Allocator.GetRelativePathToTop(AElement);
  797. if AElement.ClassType = TPasPackage then
  798. begin
  799. Module:=Nil;
  800. If (ASubPageIndex=0) then
  801. CreatePackagePageBody
  802. else if ASubPageIndex=IndexSubIndex then
  803. CreatePackageIndex
  804. else if ASubPageIndex=ClassHierarchySubIndex then
  805. CreatePackageClassHierarchy
  806. end
  807. else
  808. begin
  809. Element := AElement;
  810. while (Element<>Nil) and (not (Element.ClassType.inheritsfrom(TPasModule))) do
  811. Element := Element.Parent;
  812. Module := TPasModule(Element);
  813. if AElement.ClassType.inheritsfrom(TPasModule) then
  814. CreateModulePageBody(TPasModule(AElement), ASubpageIndex)
  815. else if AElement.Parent.InheritsFrom(TPasClassType) then
  816. CreateClassMemberPageBody(AElement)
  817. else if AElement.ClassType = TPasConst then
  818. CreateConstPageBody(TPasConst(AElement))
  819. else if AElement.InheritsFrom(TPasClassType) then
  820. CreateClassPageBody(TPasClassType(AElement), ASubpageIndex)
  821. else if AElement.InheritsFrom(TPasType) then
  822. CreateTypePageBody(TPasType(AElement))
  823. else if AElement.ClassType = TPasVariable then
  824. CreateVarPageBody(TPasVariable(AElement))
  825. else if AElement.InheritsFrom(TPasProcedureBase) then
  826. CreateProcPageBody(TPasProcedureBase(AElement))
  827. else if AElement.ClassType = TTopicELement then
  828. CreateTopicPageBody(TTopicElement(AElement))
  829. else if AElement.ClassType = TPasProperty then
  830. CreateClassMemberPageBody(TPasProperty(AElement))
  831. else
  832. writeln('Unknown classtype: ',AElement.classtype.classname);
  833. end;
  834. end;
  835. procedure TMarkdownWriter.CreateIndexPage(L : TStringList);
  836. Var
  837. Lists : Array['A'..'Z'] of TStringList;
  838. CL : TStringList;
  839. E : TPasElement;
  840. CCount,I,Rows,J,Index : Integer;
  841. S : String;
  842. C : Char;
  843. begin
  844. For C:='A' to 'Z' do
  845. Lists[C]:=Nil;
  846. L.Sort;
  847. Cl:=Nil;
  848. // Divide over alphabet
  849. For I:=0 to L.Count-1 do
  850. begin
  851. S:=L[i];
  852. E:=TPasElement(L.Objects[i]);
  853. If not (E is TPasUnresolvedTypeRef) then
  854. begin
  855. If (S<>'') then
  856. begin
  857. C:=Upcase(S[1]);
  858. If C='_' then
  859. C:='A';
  860. If (C in ['A'..'Z']) and (Lists[C]=Nil) then
  861. begin
  862. CL:=TStringList.Create;
  863. Lists[C]:=CL;
  864. end;
  865. end;
  866. if assigned(cl) then
  867. CL.AddObject(S,E);
  868. end;
  869. end;
  870. Try
  871. // Create a quick jump table to all available letters.
  872. CCount:=0;
  873. for C:='A' to 'Z' do
  874. If (Lists[C]<>Nil) then
  875. Inc(CCount);
  876. DescrBeginTable(CCount,False);
  877. DescrBeginTableHeadRow;
  878. for C:='A' to 'Z' do
  879. If (Lists[C]<>Nil) then
  880. begin
  881. DescrBeginTableCell;
  882. AppendLink(C,'#'+LowerCase(C));
  883. DescrendTableCell;
  884. end;
  885. DescrEndTableHeadRow;
  886. // Now emit all identifiers.
  887. For C:='A' to 'Z' do
  888. begin
  889. CL:=Lists[C];
  890. If CL<>Nil then
  891. begin
  892. AppendHeader(3,C);
  893. DescrBeginTable(IndexColCount,False);
  894. DescrBeginTableHeadRow;
  895. For I:=1 to IndexColCount do
  896. begin
  897. DescrBeginTableCell;
  898. AppendToLine('&nbsp; ',False);
  899. DescrEndTableCell;
  900. end;
  901. DescrEndTableHeadRow;
  902. // Determine number of rows needed
  903. Rows:=(CL.Count div IndexColCount);
  904. If ((CL.Count Mod IndexColCount)<>0) then
  905. Inc(Rows);
  906. // Fill rows
  907. For I:=0 to Rows-1 do
  908. begin
  909. DescrBeginTableRow;
  910. For J:=0 to IndexColCount-1 do
  911. begin
  912. DescrBeginTableCell;
  913. Index:=(J*Rows)+I;
  914. If (Index<CL.Count) then
  915. begin
  916. S:=CL[Index];
  917. E:=TPasElement(CL.Objects[Index]);
  918. AppendHyperlink(E);
  919. end;
  920. end;
  921. DescrEndTableRow;
  922. end;
  923. end; // have List
  924. end; // For C:=
  925. Finally
  926. for C:='A' to 'Z' do
  927. FreeAndNil(Lists[C]);
  928. end;
  929. end;
  930. procedure TMarkdownWriter.AddModuleIdentifiers(AModule : TPasModule; L : TStrings);
  931. begin
  932. if assigned(AModule.InterfaceSection) Then
  933. begin
  934. AddElementsFromList(L,AModule.InterfaceSection.Consts);
  935. AddElementsFromList(L,AModule.InterfaceSection.Types);
  936. AddElementsFromList(L,AModule.InterfaceSection.Functions);
  937. AddElementsFromList(L,AModule.InterfaceSection.Classes);
  938. AddElementsFromList(L,AModule.InterfaceSection.Variables);
  939. AddElementsFromList(L,AModule.InterfaceSection.ResStrings);
  940. end;
  941. end;
  942. procedure TMarkdownWriter.CreatePackageIndex;
  943. Var
  944. L : TStringList;
  945. I : Integer;
  946. M : TPasModule;
  947. S : String;
  948. begin
  949. L:=TStringList.Create;
  950. try
  951. L.Capacity:=PageInfos.Count; // Too much, but that doesn't hurt.
  952. For I:=0 to Package.Modules.Count-1 do
  953. begin
  954. M:=TPasModule(Package.Modules[i]);
  955. L.AddObject(M.Name,M);
  956. AddModuleIdentifiers(M,L);
  957. end;
  958. S:=Package.Name;
  959. If Length(S)>0 then
  960. Delete(S,1,1);
  961. AppendTitle(SDocPackageIndex, [S]);
  962. CreateIndexPage(L);
  963. Finally
  964. L.Free;
  965. end;
  966. end;
  967. procedure TMarkdownWriter.CreatePackagePageBody;
  968. var
  969. DocNode: TDocNode;
  970. i: Integer;
  971. ThisModule: TPasModule;
  972. L : TStringList;
  973. begin
  974. AppendTitle(SDocPackageTitle, [Copy(Package.Name, 2, 256)]);
  975. AppendShortDescr(Package);
  976. AppendHeader(2,SDocUnits);
  977. L:=TStringList.Create;
  978. Try
  979. L.Sorted:=True;
  980. // Sort modules.
  981. For I:=0 to Package.Modules.Count-1 do
  982. L.AddObject(TPasModule(Package.Modules[i]).Name,TPasModule(Package.Modules[i]));
  983. AppendTableHeader([SDocUnits,SDocDescription]);
  984. // Now create table.
  985. for i:=0 to L.Count - 1 do
  986. begin
  987. ThisModule := TPasModule(L.Objects[i]);
  988. DescrBeginTableRow;
  989. DescrBeginTableCell;
  990. AppendHyperlink(ThisModule);
  991. DescrEndTableCell;
  992. AppendShortDescrCell(ThisModule);
  993. DescrEndTableRow;
  994. end;
  995. DescrEndTable;
  996. Finally
  997. L.Free;
  998. end;
  999. DocNode := Engine.FindDocNode(Package);
  1000. if Assigned(DocNode) then
  1001. begin
  1002. if Assigned(DocNode.Descr) then
  1003. AppendDescrSection(nil, DocNode.Descr, UTF8Decode(SDocDescription));
  1004. CreateTopicLinks(DocNode,Package);
  1005. end;
  1006. end;
  1007. procedure TMarkdownWriter.CreateTopicLinks ( Node: TDocNode; PasElement: TPasElement ) ;
  1008. var
  1009. DocNode: TDocNode;
  1010. First : Boolean;
  1011. ThisTopic: TPasElement;
  1012. begin
  1013. DocNode:=Node.FirstChild;
  1014. First:=True;
  1015. While Assigned(DocNode) do
  1016. begin
  1017. If DocNode.TopicNode then
  1018. begin
  1019. if first then
  1020. begin
  1021. First:=False;
  1022. AppendHeader(2,SDocRelatedTopics);
  1023. AppendTableHeader([SDocTopic,SDocDescription]);
  1024. end;
  1025. ThisTopic:=FindTopicElement(DocNode);
  1026. if Assigned(ThisTopic) then
  1027. begin
  1028. DescrBeginTableRow;
  1029. DescrBeginTableCell;
  1030. AppendHyperlink(ThisTopic);
  1031. DescrEndTableCell;
  1032. AppendShortDescrCell(ThisTopic);
  1033. DescrEndTableRow;
  1034. end;
  1035. end;
  1036. DocNode:=DocNode.NextSibling;
  1037. end;
  1038. if not First then
  1039. DescrEndTable;
  1040. end;
  1041. function TMarkdownWriter.GetFileBaseDir(aOutput: String): String;
  1042. begin
  1043. Result:=inherited GetFileBaseDir(aOutput)+'docs'+pathdelim;
  1044. end;
  1045. procedure TMarkdownWriter.CreateModuleIndexPage(AModule: TPasModule);
  1046. Var
  1047. L : TStringList;
  1048. begin
  1049. L:=TStringList.Create;
  1050. try
  1051. AddModuleIdentifiers(AModule,L);
  1052. AppendTitle(SDocModuleIndex, [AModule.Name]);
  1053. CreateIndexPage(L);
  1054. Finally
  1055. L.Free;
  1056. end;
  1057. end;
  1058. procedure TMarkdownWriter.CreateModuleMainPageBody(AModule: TPasModule);
  1059. var
  1060. i: Integer;
  1061. UnitRef: TPasType;
  1062. DocNode: TDocNode;
  1063. begin
  1064. AppendTitle(SDocUnitTitle, [AModule.Name]);
  1065. AppendShortDescr(AModule);
  1066. if AModule.InterfaceSection.UsesList.Count > 0 then
  1067. begin
  1068. AppendTableHeader(['Uses unit',SDocDescription]);
  1069. for i := 0 to AModule.InterfaceSection.UsesList.Count - 1 do
  1070. begin
  1071. UnitRef := TPasType(AModule.InterfaceSection.UsesList[i]);
  1072. DocNode := Engine.FindDocNode(UnitRef);
  1073. if Assigned(DocNode) and DocNode.IsSkipped then
  1074. continue;
  1075. DescrBeginTableRow;
  1076. DescrBeginTableCell;
  1077. AppendHyperlink(UnitRef);
  1078. DescrEndTableCell;
  1079. AppendShortDescrCell(UnitRef);
  1080. end;
  1081. DescrEndTable;
  1082. end;
  1083. DocNode := Engine.FindDocNode(AModule);
  1084. if Assigned(DocNode) then
  1085. begin
  1086. if Assigned(DocNode.Descr) then
  1087. AppendDescrSection(AModule, DocNode.Descr, UTF8Decode(SDocOverview));
  1088. ConvertNotes(AModule,DocNode.Notes);
  1089. CreateTopicLinks(DocNode,AModule);
  1090. end;
  1091. end;
  1092. procedure TMarkdownWriter.CreateSimpleSubpage(aModule : TPasModule; const ATitle,aItem: String; AList: TFPList);
  1093. var
  1094. i: Integer;
  1095. Decl: TPasElement;
  1096. SortedList: TFPList;
  1097. DocNode: TDocNode;
  1098. begin
  1099. AppendTitle(SDocUnitTitle + ': %s', [AModule.Name, aTitle]);
  1100. SortedList := TFPList.Create;
  1101. try
  1102. for i := 0 to AList.Count - 1 do
  1103. begin
  1104. Decl := TPasElement(AList[i]);
  1105. DocNode := Engine.FindDocNode(Decl);
  1106. if not (Assigned(DocNode) and DocNode.IsSkipped) then
  1107. SortedList.Add(Decl);
  1108. end;
  1109. SortedList.Sort(@SortPasElements);
  1110. AppendTableHeader([aItem,SDocDescription]);
  1111. for i := 0 to SortedList.Count - 1 do
  1112. begin
  1113. Decl:=TPasElement(SortedList[i]);
  1114. DescrBeginTableRow;
  1115. DescrBeginTableCell;
  1116. AppendHyperlink(Decl);
  1117. DescrEndTableCell;
  1118. AppendShortDescrCell(Decl);
  1119. DescrEndTableRow;
  1120. end;
  1121. DescrEndTable;
  1122. finally
  1123. SortedList.Free;
  1124. end;
  1125. end;
  1126. procedure TMarkdownWriter.CreateResStringsPage(aModule : TPasModule);
  1127. var
  1128. i: Integer;
  1129. Decl: TPasResString;
  1130. begin
  1131. AppendTitle(SDocUnitTitle + ': %s', [AModule.Name, SDocResStrings]);
  1132. If AModule.InterfaceSection.ResStrings.Count = 0 then
  1133. exit;
  1134. for i := 0 to AModule.InterfaceSection.ResStrings.Count - 1 do
  1135. begin
  1136. Decl := TPasResString(AModule.InterfaceSection.ResStrings[i]);
  1137. AppendToLine('<a name="%s"> %s',[LowerCase(Decl.Name),Decl.Name]);
  1138. Indent;
  1139. UTF8Decode(Decl.Expr.getDeclaration(true));
  1140. undent;
  1141. end;
  1142. end;
  1143. procedure TMarkdownWriter.CreateModulePageBody(AModule: TPasModule;
  1144. ASubpageIndex: Integer);
  1145. begin
  1146. case ASubpageIndex of
  1147. 0:
  1148. CreateModuleMainPageBody(aModule);
  1149. ResstrSubindex:
  1150. CreateResStringsPage(aModule);
  1151. ConstsSubindex:
  1152. CreateSimpleSubpage(aModule,SDocConstants, SDocConstant, AModule.InterfaceSection.Consts);
  1153. TypesSubindex:
  1154. CreateSimpleSubpage(aModule,SDocTypes, SDocType, AModule.InterfaceSection.Types);
  1155. ClassesSubindex:
  1156. CreateSimpleSubpage(aModule,SDocClasses, SDocClass, AModule.InterfaceSection.Classes);
  1157. ProcsSubindex:
  1158. CreateSimpleSubpage(aModule,SDocProceduresAndFunctions, SDocProcedureOrFunction, AModule.InterfaceSection.Functions);
  1159. VarsSubindex:
  1160. CreateSimpleSubpage(aModule,SDocVariables, SDocVariable, AModule.InterfaceSection.Variables);
  1161. IndexSubIndex:
  1162. CreateModuleIndexPage(AModule);
  1163. end;
  1164. end;
  1165. procedure TMarkdownWriter.CreateConstPageBody(AConst: TPasConst);
  1166. begin
  1167. AppendTitle(AConst.Name);
  1168. AppendShortDescr(AConst);
  1169. AppendHeader(2,SDocDeclaration);
  1170. AppendSourceRef(AConst);
  1171. DescrBeginCode(False,'Pascal');
  1172. EmitLine('const');
  1173. EmitLine(aConst.GetDeclaration(True));
  1174. DescrEndCode;
  1175. FinishElementPage(AConst);
  1176. end;
  1177. procedure TMarkdownWriter.CreateTypePageBody(AType: TPasType);
  1178. begin
  1179. AppendTitle(AType.Name);
  1180. AppendShortDescr(AType);
  1181. AppendHeader(2,SDocDeclaration);
  1182. AppendSourceRef(AType);
  1183. DescrBeginCode(False,'Pascal');
  1184. EmitLine('Type');
  1185. EmitLine(aType.GetDeclaration(True));
  1186. DescrEndCode;
  1187. FinishElementPage(AType);
  1188. end;
  1189. procedure TMarkdownWriter.CreateMemberDeclarations(AParent: TPasElement; Members: TFPList; Options: TMemberListOptions);
  1190. function GetMemberType(aMember : TPasElement) : string;
  1191. begin
  1192. if aMember is TPasProcedure then
  1193. Result:=SDocMethod
  1194. else if aMember is TPasProperty then
  1195. Result:=SDocProperty
  1196. else if aMember is TPasConst then
  1197. Result:=SDocConstant
  1198. else if aMember is TPasType then
  1199. Result:=SDocType
  1200. else
  1201. Result:=SDocField;
  1202. end;
  1203. var
  1204. Member: TPasElement;
  1205. MVisibility : TPasMemberVisibility;
  1206. i,aCount: Integer;
  1207. // isRecord,
  1208. isOverLoad : Boolean;
  1209. begin
  1210. // isRecord:=AParent is TPasRecordType;
  1211. if Members.Count = 0 then
  1212. begin
  1213. AppendText(SDocNoneAVailable);
  1214. Exit;
  1215. end;
  1216. if mloAppendType in Options then
  1217. AppendTableHeader([SDocMember,SDocType,SDocVisibility,SDocDescription])
  1218. else
  1219. AppendTableHeader([SDocMember,SDocVisibility,SDocDescription]);
  1220. aCount:=0;
  1221. Members.Sort(@SortPasElements);
  1222. for i := 0 to Members.Count - 1 do
  1223. begin
  1224. Member := TPasElement(Members[i]);
  1225. MVisibility:=Member.Visibility;
  1226. if mloCheckVisibility in Options then
  1227. if not Engine.ShowElement(Member) then
  1228. Continue;
  1229. isOverLoad:=(Member is TPasOverloadedProc);
  1230. if isOverload then
  1231. Member:=TPasElement((Member as TPasOverloadedProc).Overloads[0]);
  1232. Inc(aCount);
  1233. DescrBeginTableRow;
  1234. DescrBeginTableCell;
  1235. AppendHyperlink(Member);
  1236. if mloAppendParent in options then
  1237. begin
  1238. AppendText('(');
  1239. AppendHyperLink(Member.Parent);
  1240. AppendText(')');
  1241. end;
  1242. DescrEndTableCell;
  1243. if mloAppendType in Options then
  1244. begin
  1245. DescrBeginTableCell;
  1246. AppendText(GetMemberType(Member));
  1247. DescrEndTableCell;
  1248. end;
  1249. DescrBeginTableCell;
  1250. AppendText(VisibilityNames[MVisibility]);
  1251. DescrEndTableCell;
  1252. AppendShortDescrCell(member);
  1253. DescrEndTableRow;
  1254. end;
  1255. DescrEndTable;
  1256. if ACount=0 then
  1257. AppendText(SDocNoneAVailable)
  1258. end;
  1259. procedure TMarkdownWriter.AppendTitle(const S: String);
  1260. begin
  1261. AddMetaData('title',S);
  1262. AppendHeader(1,S);
  1263. EnsureEmptyLine;
  1264. end;
  1265. procedure TMarkdownWriter.AppendTitle(const Fmt: String;
  1266. const Args: array of const);
  1267. begin
  1268. AppendTitle(Format(Fmt,Args));
  1269. end;
  1270. function TMarkdownWriter.GetClassDeclarationFirstLine(aEl: TPasClassType): String;
  1271. Var
  1272. aLine : string;
  1273. I : Integer;
  1274. begin
  1275. aLine:=aEL.Name;
  1276. if aEl.GenericTemplateTypes.Count>0 then
  1277. begin
  1278. aLine:='generic '+aLine+'<';
  1279. For I:=0 to aEl.GenericTemplateTypes.Count-1 do
  1280. begin
  1281. if I>0 then
  1282. aLine:=aLine+', ';
  1283. aLine:=aLine+TPasGenericTemplateType(aEl.GenericTemplateTypes[i]).Name;
  1284. end;
  1285. aLine:=aLine+'>';
  1286. end;
  1287. aLine:=aLine+' = '+aEl.ElementTypeName;
  1288. if aEl.HelperForType<>Nil then
  1289. aLine:=aLine+' for '+aEl.HelperForType.Name;
  1290. if aEL.ExternalName<>'' then
  1291. aLine:=aLine+' external name '''+ael.ExternalName+'''';
  1292. if Assigned(aEL.AncestorType) then
  1293. if (aEL.AncestorType is TPasSpecializeType) then
  1294. begin
  1295. aLine:=aLine+'(specialize ';
  1296. aLine:=aLine+ TPasSpecializeType(aEL.AncestorType).DestType.Name;
  1297. aLine:=aLine+ '<,>)';
  1298. end
  1299. else
  1300. begin
  1301. aLine:=aLine+' ('+ael.AncestorType.Name;
  1302. if Assigned(ael.Interfaces) and (aEl.Interfaces.Count>0) then
  1303. For I:=0 to aEl.Interfaces.Count-1 do
  1304. aLine:=aLine+', '+TPasElement(aEl.Interfaces[i]).Name;
  1305. aLine:=aLine+')';
  1306. end;
  1307. if Assigned(aEl.GUIDExpr) then
  1308. aLine:=aLine+' ['+aEl.GUIDExpr.GetDeclaration(True)+']';
  1309. Result:=aLine;
  1310. end;
  1311. function TMarkdownWriter.GetClassDeclaration(aEl: TPasClassType): String;
  1312. Var
  1313. S,T : TStrings;
  1314. I,J : Integer;
  1315. LastVis : TPasMemberVisibility;
  1316. aMember : TPasElement;
  1317. begin
  1318. T:=Nil;
  1319. lastVis:=VisDefault;
  1320. S:=TStringList.Create;
  1321. try
  1322. T:=TStringList.Create;
  1323. S.Add(GetClassDeclarationFirstLine(aEl));
  1324. for I:=0 to aEl.Members.Count-1 do
  1325. begin
  1326. aMember:=TPasElement(aEl.Members[i]);
  1327. if aMember.Visibility<>LastVis then
  1328. begin
  1329. LastVis:=aMember.Visibility;
  1330. S.Add(VisibilityNames[LastVis]);
  1331. end;
  1332. T.Text:=GetDeclaration(aMember);
  1333. for J:=0 to T.count-1 do
  1334. S.Add(' '+T[J]);
  1335. end;
  1336. if not aEl.IsShortDefinition then
  1337. S.Add('end');
  1338. Result:=S.Text;
  1339. finally
  1340. S.Free;
  1341. T.Free;
  1342. end;
  1343. end;
  1344. function TMarkdownWriter.GetDeclaration(aEl: TPasElement): String;
  1345. Var
  1346. I : Integer;
  1347. Ovl : TPasOverloadedProc;
  1348. S : String;
  1349. begin
  1350. if (aEl is TPasClassType) then
  1351. exit(GetClassDeclaration(TPasClassType(aEl))+';');
  1352. if Not (aEl is TPasOverloadedProc) then
  1353. Exit(aEl.GetDeclaration(True)+';');
  1354. ovl:=aEl as TPasOverloadedProc;
  1355. S:='';
  1356. for I:=0 to ovl.Overloads.Count-1 do
  1357. begin
  1358. if s<>'' then
  1359. S:=S+sLineBreak;
  1360. S:=S+TPasElement(Ovl.Overloads[i]).GetDeclaration(True)+';';
  1361. end;
  1362. Result:=S;
  1363. end;
  1364. procedure TMarkdownWriter.AppendDeclaration(aEl : TPasElement; aKind : string; PrependVisibility : Boolean);
  1365. Var
  1366. S : String;
  1367. begin
  1368. DescrBeginCode(False,'Pascal');
  1369. if PrependVisibility then
  1370. S:=VisibilityNames[aEL.Visibility]+' '
  1371. else
  1372. S:='';
  1373. S:=S+aKind;
  1374. EmitLine(S);
  1375. S:=GetDeclaration(aEl);
  1376. EmitCode(S,2);
  1377. DescrEndCode;
  1378. end;
  1379. procedure TMarkdownWriter.CreateClassMainPage(aClass : TPasClassType);
  1380. procedure AppendMemberListLink(AListSubpageIndex: Integer; const AText: String);
  1381. begin
  1382. AppendToLine('\[',False);
  1383. AppendLink(aText,FixHtmlPath(ResolveLinkWithinPackage(AClass, AListSubpageIndex)));
  1384. AppendText(' (');
  1385. AppendLink(SDocByName,FixHtmlPath(ResolveLinkWithinPackage(AClass, AListSubpageIndex+1)));
  1386. AppendToLine(')\]',False);
  1387. end;
  1388. var
  1389. i: Integer;
  1390. ThisInterface,
  1391. ThisClass: TPasType;
  1392. ThisTreeNode: TPasElementNode;
  1393. DocNode: TDocNode;
  1394. begin
  1395. DocNode := Engine.FindDocNode(aClass);
  1396. //WriteLn('@ClassPageBody.CreateMainPage Class=', AClass.Name);
  1397. AppendTitle(AClass.Name);
  1398. AppendMemberListLink(PropertiesByInheritanceSubindex,SDocProperties);
  1399. AppendMemberListLink(MethodsByInheritanceSubindex, SDocMethods);
  1400. AppendMemberListLink(EventsByInheritanceSubindex, SDocEvents);
  1401. EnsureEmptyLine;
  1402. AppendShortDescr(AClass);
  1403. AppendHeader(2,SDocDeclaration);
  1404. AppendSourceRef(AClass);
  1405. AppendDeclaration(aClass,'Type',False);
  1406. // Description
  1407. if Assigned(DocNode) and Assigned(DocNode.Descr) then
  1408. AppendDescrSection(aClass, DocNode.Descr, SDocDescription);
  1409. AppendHeader(2,SDocMembers);
  1410. CreateMemberDeclarations(aClass, AClass.Members,[mloAppendType]);
  1411. AppendHeader(2,SDocInheritance);
  1412. EnsureEmptyLine;
  1413. AppendTableHeader([SDocClass,SDocDescription]);
  1414. ThisClass := AClass;
  1415. ThisTreeNode := Nil;
  1416. if AClass.ObjKind = okInterface then
  1417. ThisTreeNode := TreeInterface.GetPasElNode(AClass)
  1418. else
  1419. ThisTreeNode := TreeClass.GetPasElNode(AClass);
  1420. while True do
  1421. begin
  1422. DescrBeginTableRow;
  1423. DescrBeginTableCell;
  1424. // Show class item
  1425. if Assigned(ThisClass) Then
  1426. AppendHyperlink(ThisClass);
  1427. if Assigned(ThisClass) and (AClass.Interfaces.count>0) then
  1428. begin
  1429. AppendText('(');
  1430. for i:=0 to AClass.interfaces.count-1 do
  1431. begin
  1432. ThisInterface:= TPasType(AClass.Interfaces[i]);
  1433. if I>0 then
  1434. AppendText(', ');
  1435. AppendHyperlink( ThisInterface);
  1436. end;
  1437. AppendText(')');
  1438. end;
  1439. DescrEndTableCell;
  1440. AppendShortDescrCell(ThisClass);
  1441. DescrEndTableRow;
  1442. if Not Assigned(ThisTreeNode) then
  1443. Break
  1444. else if not Assigned(ThisTreeNode.ParentNode) then
  1445. begin
  1446. ThisClass := nil;
  1447. ThisTreeNode:= nil;
  1448. break;
  1449. end
  1450. else
  1451. begin
  1452. DescrBeginTableRow;
  1453. DescrBeginTableCell;
  1454. AppendText('|');
  1455. DescrEndTableCell;
  1456. DescrBeginTableCell;
  1457. DescrEndTableCell;
  1458. ThisClass := ThisTreeNode.ParentNode.Element;
  1459. ThisTreeNode := ThisTreeNode.ParentNode;
  1460. end;
  1461. end;
  1462. DescrEndTable;
  1463. FinishElementPage(AClass,True);
  1464. end;
  1465. procedure TMarkdownWriter.CreateInheritanceSubpage(aClass: TPasClassType; aTitle: string; AFilter: TMemberFilter);
  1466. var
  1467. ThisClass: TPasClassType;
  1468. i,aCount: Integer;
  1469. Member: TPasElement;
  1470. aList : TFPList;
  1471. begin
  1472. aTitle:=aClass.Name+' : '+aTitle+ ' '+SDocByInheritance;
  1473. AppendTitle(aTitle);
  1474. ThisClass := AClass;
  1475. aCount:=0;
  1476. aList:=TFPList.Create;
  1477. try
  1478. while assigned(ThisClass) do
  1479. begin
  1480. aList.Clear;
  1481. for i := 0 to ThisClass.Members.Count - 1 do
  1482. begin
  1483. Member := TPasElement(ThisClass.Members[i]);
  1484. if (Engine.ShowElement(Member) and AFilter(Member)) then
  1485. aList.Add(Member);
  1486. end;
  1487. aCount:=aCount+aList.Count;
  1488. if AList.Count>0 then
  1489. begin
  1490. AppendHeader(2,CreateHyperLink(ThisClass),False);
  1491. CreateMemberDeclarations(aClass, aList, []);
  1492. end;
  1493. if ThisClass.AncestorType is TPasClassType then
  1494. ThisClass := TPasClassType(ThisClass.AncestorType)
  1495. else
  1496. ThisClass:=Nil;
  1497. end;
  1498. if aCount=0 then
  1499. AppendText(SDocNoneAVailable);
  1500. finally
  1501. aList.Free;
  1502. end;
  1503. end;
  1504. procedure TMarkdownWriter.CreateSortedSubpage(ACLass: TPasClassType; aTitle: string; AFilter: TMemberFilter);
  1505. var
  1506. List: TFPList;
  1507. ThisClass: TPasClassType;
  1508. i : Integer;
  1509. Member: TPasElement;
  1510. begin
  1511. aTitle:=aClass.Name+' : '+aTitle+' '+SDocByName;
  1512. AppendTitle(aTitle);
  1513. List := TFPList.Create;
  1514. try
  1515. ThisClass := AClass;
  1516. while Assigned(ThisClass) do
  1517. begin
  1518. for i := 0 to ThisClass.Members.Count - 1 do
  1519. begin
  1520. Member := TPasElement(ThisClass.Members[i]);
  1521. if Engine.ShowElement(Member) and AFilter(Member) then
  1522. List.Add(Member)
  1523. end;
  1524. if (ThisClass.AncestorType is TPasClassType) then
  1525. ThisClass := TPasClassType(ThisClass.AncestorType)
  1526. else
  1527. ThisClass := Nil;
  1528. end;
  1529. CreateMemberDeclarations(aClass, List, [mloAppendParent]);
  1530. finally
  1531. List.Free;
  1532. end;
  1533. end;
  1534. function TMarkdownWriter.GetAdditionalConfig: TStrings;
  1535. begin
  1536. if FAdditionalConfig=Nil then
  1537. FAdditionalConfig:=TstringList.Create;
  1538. Result:=FAdditionalConfig;
  1539. end;
  1540. procedure TMarkdownWriter.CreateClassPageBody(AClass: TPasClassType;
  1541. ASubpageIndex: Integer);
  1542. begin
  1543. case ASubpageIndex of
  1544. 0:
  1545. CreateClassMainPage(aClass);
  1546. PropertiesByInheritanceSubindex:
  1547. CreateInheritanceSubpage(aClass,SDocPropertyOverview,@PropertyFilter);
  1548. PropertiesByNameSubindex:
  1549. CreateSortedSubpage(aClass,SDocPropertyOverview, @PropertyFilter);
  1550. MethodsByInheritanceSubindex:
  1551. CreateInheritanceSubpage(aClass,SDocMethodOverview,@MethodFilter);
  1552. MethodsByNameSubindex:
  1553. CreateSortedSubpage(aClass,SDocMethodOverview,@MethodFilter);
  1554. EventsByInheritanceSubindex:
  1555. CreateInheritanceSubpage(aClass,SDocEventOverview,@EventFilter);
  1556. EventsByNameSubindex:
  1557. CreateSortedSubpage(aClass,SDocEventOverview, @EventFilter);
  1558. end;
  1559. end;
  1560. procedure TMarkdownWriter.CreateClassMemberPageBody(AElement: TPasElement);
  1561. procedure CreateVarPage(Element: TPasVariable);
  1562. begin
  1563. AppendDeclaration(Element,'Var',True);
  1564. end;
  1565. procedure CreateTypePage(Element: TPasType);
  1566. begin
  1567. AppendDeclaration(Element,'Type',True);
  1568. end;
  1569. procedure CreateConstPage(Element: TPasConst);
  1570. begin
  1571. AppendDeclaration(Element,'Const',True);
  1572. end;
  1573. procedure CreatePropertyPage(Element: TPasProperty);
  1574. begin
  1575. AppendDeclaration(Element,'Property',True);
  1576. end;
  1577. var
  1578. s: String;
  1579. begin
  1580. AppendTitle(aElement.FullName);
  1581. AppendShortDescr(AElement);
  1582. AppendHeader(2, SDocDeclaration);
  1583. AppendSourceRef(AElement);
  1584. if AElement is TPasProperty then
  1585. S:='Property'
  1586. else if AElement is TPasConst then
  1587. S:='Const'
  1588. else if (AElement is TPasVariable) then
  1589. S:='var'
  1590. else if AElement is TPasProcedureBase then
  1591. s:=''
  1592. else if AElement is TPasType then
  1593. S:='Type'
  1594. else
  1595. AppendText('<' + AElement.ClassName + '>');
  1596. AppendDeclaration(aElement,S,True);
  1597. FinishElementPage(AElement);
  1598. end;
  1599. procedure TMarkdownWriter.CreateVarPageBody(AVar: TPasVariable);
  1600. begin
  1601. AppendTitle(AVar.FullName);
  1602. AppendShortDescr(AVar);
  1603. AppendHeader(2, SDocDeclaration);
  1604. AppendSourceRef(AVar);
  1605. AppendDeclaration(aVar,'var',false);
  1606. FinishElementPage(AVar);
  1607. end;
  1608. procedure TMarkdownWriter.CreateProcPageBody(AProc: TPasProcedureBase);
  1609. begin
  1610. AppendTitle(AProc.Name);
  1611. AppendShortDescr(AProc);
  1612. AppendHeader(2,SDocDeclaration);
  1613. AppendSourceRef(AProc);
  1614. AppendDeclaration(AProc,'',False);
  1615. FinishElementPage(AProc);
  1616. end;
  1617. function TMarkdownWriter.InterPretOption ( const Cmd, Arg: String ) : boolean;
  1618. procedure ReadFile(aStrings : TStrings; aFileName : string);
  1619. begin
  1620. aFileName:= SetDirSeparators(aFileName);
  1621. if copy(aFileName,1,1)<>'@' then
  1622. aStrings.text:=aFileName
  1623. else
  1624. begin
  1625. Delete(aFileName,1,1);
  1626. aStrings.LoadFromFile(aFileName);
  1627. end;
  1628. end;
  1629. begin
  1630. Result:=True;
  1631. if Cmd = '--footer' then
  1632. ReadFile(FooterMarkDown,Arg)
  1633. else if Cmd = '--header' then
  1634. ReadFile(HeaderMarkDown,Arg)
  1635. else if Cmd = '--index-colcount' then
  1636. IndexColCount := StrToIntDef(Arg,IndexColCount)
  1637. else if Cmd = '--image-url' then
  1638. FBaseImageURL := Arg
  1639. else if Cmd = '--theme' then
  1640. begin
  1641. if arg='-' then
  1642. Theme:=''
  1643. else
  1644. Theme := Arg
  1645. end
  1646. else if Cmd='--navigation' then
  1647. begin
  1648. if SameText(Arg,'UnitSubTree') then
  1649. FNavigationMode:=nmUnitSubTree
  1650. else if SameText(Arg,'UnitTree') then
  1651. FNavigationMode:=nmUnitTree;
  1652. end
  1653. else
  1654. Result:=inherited InterPretOption(Cmd, Arg);
  1655. end;
  1656. class procedure TMarkdownWriter.Usage(List: TStrings);
  1657. begin
  1658. inherited Usage(List);
  1659. List.add('--header=file');
  1660. List.Add(SMDUsageHeader);
  1661. List.add('--footer=file');
  1662. List.Add(SMDUsageFooter);
  1663. List.Add('--index-colcount=N');
  1664. List.Add(SMDIndexColcount);
  1665. List.Add('--image-url=url');
  1666. List.Add(SMDImageUrl);
  1667. List.Add('--theme=name');
  1668. List.Add(SMDTheme);
  1669. List.Add('--navigation=scheme');
  1670. List.Add(SMDNavigation);
  1671. // we have to write even count of params into list either we will have a exception
  1672. List.Add('');
  1673. List.Add(SMDNavSubtree);
  1674. List.Add('');
  1675. List.Add(SMDNavTree);
  1676. end;
  1677. class procedure TMarkdownWriter.SplitImport(var AFilename, ALinkPrefix: String);
  1678. var
  1679. i: integer;
  1680. begin
  1681. i := Pos(',', AFilename);
  1682. if i > 0 then
  1683. begin //split into filename and prefix
  1684. ALinkPrefix := Copy(AFilename,i+1,Length(AFilename));
  1685. SetLength(AFilename, i-1);
  1686. end
  1687. else if ALinkPrefix = '' then
  1688. begin //synthesize outdir\pgk.xct, ..\pkg
  1689. ALinkPrefix := '../' + ChangeFileExt(ExtractFileName(AFilename), '');
  1690. AFilename := ChangeFileExt(AFilename, '.xct');
  1691. end;
  1692. end;
  1693. class function TMarkdownWriter.FileNameExtension: String;
  1694. begin
  1695. result:='md';
  1696. end;
  1697. // private methods
  1698. function TMarkdownWriter.GetPageCount: Integer;
  1699. begin
  1700. Result := PageInfos.Count;
  1701. end;
  1702. procedure TMarkdownWriter.SetOnTest(const AValue: TNotifyEvent);
  1703. begin
  1704. if FOnTest=AValue then exit;
  1705. FOnTest:=AValue;
  1706. end;
  1707. procedure TMarkdownWriter.AppendText(const S: String);
  1708. begin
  1709. AppendToLine(S,True);
  1710. end;
  1711. initialization
  1712. // Do not localize.
  1713. RegisterWriter(TMarkdownWriter,'md','Markdown output.');
  1714. finalization
  1715. UnRegisterWriter('md');
  1716. end.