dw_markdown.pp 51 KB

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