dw_markdown.pp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974
  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 ModuleForElement(AnElement:TPasElement):TPasModule;
  110. Function InterPretOption(Const Cmd,Arg : String) : boolean; override;
  111. Procedure WriteDoc; 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 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.WriteDoc;
  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. function TMarkdownWriter.ModuleForElement(AnElement:TPasElement):TPasModule;
  278. begin
  279. result:=TPasModule(AnElement);
  280. while assigned(result) and not (result is TPasModule) do
  281. result:=TPasModule(result.parent);
  282. if not (result is TPasModule) then
  283. result:=nil;
  284. end;
  285. procedure TMarkdownWriter.AppendShortDescr(AContext: TPasElement; DocNode: TDocNode) ;
  286. Var
  287. N : TDocNode;
  288. begin
  289. if Not Assigned(DocNode) then
  290. exit;
  291. N:=Nil;
  292. If (DocNode.Link<>'') then
  293. N:=Engine.FindLinkedNode(DocNode);
  294. If (N=Nil) then
  295. N:=DocNode;
  296. If Assigned(N.ShortDescr) then
  297. if not ConvertShort(AContext,N.ShortDescr) then
  298. Warning(AContext, SErrInvalidShortDescr)
  299. end;
  300. procedure TMarkdownWriter.AppendShortDescr(Element: TPasElement);
  301. begin
  302. AppendShortDescr(Element,Engine.FindDocNode(Element));
  303. end;
  304. procedure TMarkdownWriter.AppendShortDescrCell(Element: TPasElement);
  305. begin
  306. if Not Assigned(Engine.FindShortDescr(Element)) then
  307. exit;
  308. DescrBeginTableCell;
  309. AppendShortDescr(Element);
  310. DescrEndTableCell;
  311. end;
  312. procedure TMarkdownWriter.AppendDescr(AContext: TPasElement; DescrNode: TDOMElement; AutoInsertBlock: Boolean);
  313. begin
  314. if Not Assigned(DescrNode) then
  315. exit;
  316. EnsureEmptyLine;
  317. ConvertDescr(AContext, DescrNode, AutoInsertBlock);
  318. end;
  319. procedure TMarkdownWriter.AppendDescrSection(AContext: TPasElement; DescrNode: TDOMElement; const ATitle: String);
  320. begin
  321. if IsDescrNodeEmpty(DescrNode) then
  322. exit;
  323. If (ATitle<>'') then // Can be empty for topic.
  324. AppendHeader(2,ATitle);
  325. AppendDescr(AContext, DescrNode, True);
  326. end;
  327. procedure TMarkdownWriter.AppendDescrSection(AContext: TPasElement; DescrNode: TDOMElement; const ATitle: DOMString);
  328. begin
  329. AppendDescrSection(aContext,DescrNode,UTF8Encode(aTitle));
  330. end;
  331. procedure TMarkdownWriter.AppendHyperlink(Element: TPasElement);
  332. begin
  333. if Not Assigned(Element) then
  334. begin
  335. AppendText('<NIL>');
  336. exit;
  337. end;
  338. AppendToLine(CreateHyperLink(Element),False)
  339. end;
  340. function TMarkdownWriter.CreateHyperlink(Element: TPasElement): string;
  341. var
  342. s: DOMString;
  343. UnitList: TFPList;
  344. i: Integer;
  345. ThisPackage: TLinkNode;
  346. begin
  347. if Not Assigned(Element) then
  348. Exit('\<NIL\>');
  349. if Not Element.InheritsFrom(TPasUnresolvedTypeRef) then
  350. begin
  351. if Element is TPasEnumValue then
  352. s := ResolveLinkID(Element.Parent.PathName)
  353. else
  354. s := ResolveLinkID(Element.PathName);
  355. end
  356. else
  357. begin
  358. s := ResolveLinkID(Element.Name);
  359. if Length(s) = 0 then
  360. begin
  361. { Try all packages }
  362. ThisPackage := Engine.RootLinkNode.FirstChild;
  363. while Assigned(ThisPackage) do
  364. begin
  365. s := ResolveLinkID(ThisPackage.Name + '.' + Element.Name);
  366. if Length(s) > 0 then
  367. break;
  368. ThisPackage := ThisPackage.NextSibling;
  369. end;
  370. if Length(s) = 0 then
  371. begin
  372. { Okay, then we have to try all imported units of the current module }
  373. UnitList := Module.InterfaceSection.UsesList;
  374. for i := UnitList.Count - 1 downto 0 do
  375. begin
  376. { Try all packages }
  377. ThisPackage := Engine.RootLinkNode.FirstChild;
  378. while Assigned(ThisPackage) do
  379. begin
  380. s := ResolveLinkID(ThisPackage.Name + '.' +
  381. TPasType(UnitList[i]).Name + '.' + Element.Name);
  382. if Length(s) > 0 then
  383. break;
  384. ThisPackage := ThisPackage.NextSibling;
  385. end;
  386. if length(s)=0 then
  387. s := ResolveLinkID('#rtl.System.' + Element.Name);
  388. if Length(s) > 0 then
  389. break;
  390. end;
  391. end;
  392. end;
  393. end;
  394. if Length(s) > 0 then
  395. Result:=CreateLink(Element.Name,UTF8Encode(S))
  396. else
  397. Result:=Element.Name;
  398. end;
  399. procedure TMarkdownWriter.AppendProcArgsSection(Element: TPasProcedureBase);
  400. var
  401. HasFullDescr, IsFirstType: Boolean;
  402. ResultEl: TPasResultElement;
  403. DocNode: TDocNode;
  404. aList : TStringList;
  405. Procedure CollectVariant(AProc: TPasProcedure);
  406. var
  407. i: Integer;
  408. Arg: TPasArgument;
  409. aType : TPasProcedureType;
  410. begin
  411. aType:=aProc.ProcType;
  412. for I:=0 to aType.Args.Count-1 do
  413. begin
  414. Arg:=TPasArgument(aType.Args[i]);
  415. if IsDescrNodeEmpty(Engine.FindShortDescr(Arg)) then
  416. Continue;
  417. aList.AddObject(Arg.Name,Arg);
  418. end;
  419. if (aType is TPasFunctionType) and (ResultEl=Nil) then
  420. ResultEl:=TPasFunctionType(aType).ResultEl;
  421. end;
  422. Procedure WriteType(aProc : TPasProcedure; aName: string);
  423. var
  424. i: Integer;
  425. Arg: TPasArgument;
  426. aType : TPasProcedureType;
  427. begin
  428. aType:=aProc.ProcType;
  429. for I:=0 to aType.Args.Count-1 do
  430. begin
  431. Arg:=TPasArgument(aType.Args[i]);
  432. if SameText(Arg.Name,aName) then
  433. begin
  434. if not IsFirstType then
  435. AppendText(', ');
  436. AppendHyperlink(Arg.ArgType);
  437. end;
  438. if IsDescrNodeEmpty(Engine.FindShortDescr(Arg)) then
  439. Continue;
  440. aList.AddObject(Arg.Name,Arg);
  441. end;
  442. end;
  443. Procedure WriteTypes(aName: string);
  444. Var
  445. I : Integer;
  446. begin
  447. IsFirstType:=True;
  448. if Element.ClassType <> TPasOverloadedProc then
  449. WriteType(TPasProcedure(Element),aName)
  450. else for i := 0 to TPasOverloadedProc(Element).Overloads.Count - 1 do
  451. WriteType(TPasProcedure(TPasOverloadedProc(Element).Overloads[i]),AName);
  452. end;
  453. Var
  454. I: Integer;
  455. begin
  456. ResultEl:=Nil;
  457. aList:=TStringList.Create;
  458. try
  459. AList.Duplicates:=DupIgnore;
  460. if Element.ClassType <> TPasOverloadedProc then
  461. CollectVariant(TPasProcedure(Element))
  462. else for i := 0 to TPasOverloadedProc(Element).Overloads.Count - 1 do
  463. CollectVariant(TPasProcedure(TPasOverloadedProc(Element).Overloads[i]));
  464. If AList.Count<>0 then
  465. begin
  466. AppendHeader(2,SDocArguments);
  467. AppendTableHeader([SDocName,SDocTypes,SDocDescription]);
  468. for I:=0 to aList.Count-1 do
  469. begin
  470. DescrBeginTableRow;
  471. DescrBeginTableCell;
  472. AppendText(aList[i]);
  473. DescrEndTableCell;
  474. DescrBeginTableCell;
  475. WriteTypes(aList[i]);
  476. DescrEndTableCell;
  477. AppendShortDescrCell(TPasArgument(aList.Objects[i]));
  478. DescrEndTableRow;
  479. end;
  480. DescrEndTable;
  481. end;
  482. finally
  483. aList.Free;
  484. end;
  485. if Not Assigned(ResultEl) then
  486. Exit;
  487. DocNode := Engine.FindDocNode(ResultEl);
  488. HasFullDescr := Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.Descr);
  489. if HasFullDescr or
  490. (Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.ShortDescr)) then
  491. begin
  492. AppendHeader(2, SDocFunctionResult);
  493. if HasFullDescr then
  494. AppendDescr(ResultEl,DocNode.Descr, True)
  495. else
  496. AppendDescr(ResultEl,DocNode.ShortDescr, False);
  497. end;
  498. end;
  499. procedure TMarkdownWriter.AppendSourceRef(AElement: TPasElement);
  500. begin
  501. EnsureEmptyLine;
  502. AppendToLine(Format(SDocSourcePosition,
  503. [ExtractFileName(AElement.SourceFilename), AElement.SourceLinenumber]));
  504. EnsureEmptyLine;
  505. end;
  506. procedure TMarkdownWriter.CollectSeeAlsoNodes(aList : TStringList; aSeeAlso: TDomNode);
  507. Var
  508. Node : TDOMNode;
  509. L : String;
  510. El : TDOMElement;
  511. begin
  512. Node:=aSeeAlso.FirstChild;
  513. While Assigned(Node) do
  514. begin
  515. if (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='link') then
  516. begin
  517. El:=TDOMElement(Node);
  518. l:=UTF8encode(El['id']);
  519. aList.AddObject(L,El);
  520. end;
  521. Node:=Node.NextSibling;
  522. end;
  523. end;
  524. procedure TMarkdownWriter.CollectDeclarationTypes(aList : TStringList; aElement : TPasElement);
  525. Procedure MaybeAdd(aType : TPasType);
  526. Var
  527. N : TDocNode;
  528. begin
  529. if aType is TPasPointerType then
  530. aType:=TPasPointerType(aType).DestType;
  531. if (aType=Nil) or (aType.Name='') then
  532. exit;
  533. N:=Engine.FindDocNode(aType);
  534. if N<>Nil then
  535. aList.AddObject(aType.Name,aType);
  536. end;
  537. Var
  538. I : integer;
  539. begin
  540. if aElement is TPasVariable then
  541. MaybeAdd(TPasVariable(aElement).VarType)
  542. else if aElement is TPasMembersType then
  543. begin
  544. for I:=0 to TPasMembersType(aElement).Members.Count-1 do
  545. if TObject(TPasMembersType(aElement).Members[i]) is TPasVariable then
  546. MaybeAdd(TPasVariable(TPasMembersType(aElement).Members[i]).VarType);
  547. end;
  548. end;
  549. procedure TMarkdownWriter.AppendSeeAlsoSection(AElement: TPasElement; DocNode: TDocNode) ;
  550. Procedure AppendSeeALso(aID : String; El: TDomElement);
  551. Var
  552. S,N : DOMString;
  553. doBold : Boolean;
  554. begin
  555. s:= ResolveLinkID(aID);
  556. doBold:=Length(S)=0;
  557. if DoBold then
  558. begin
  559. if assigned(module) then
  560. s:=UTF8Decode(module.name)
  561. else
  562. s:='?';
  563. if aID='' then aID:='<empty>';
  564. if Assigned(AElement) then
  565. N:=UTF8Decode(AElement.Name)
  566. else
  567. N:='?';
  568. DoLog(SErrUnknownLinkID, [s,N,aID]);
  569. end ;
  570. if doBold then
  571. DescrBeginBold
  572. else
  573. DescrBeginURL(S);
  574. if Not IsDescrNodeEmpty(El) then
  575. ConvertBaseShortList(AElement, El, True)
  576. else
  577. AppendText(aID);
  578. if doBold then
  579. DescrEndBold
  580. else
  581. DescrEndURL();
  582. end;
  583. Procedure AppendTypeRef(aName : String; El: TPasType);
  584. begin
  585. AppendHyperLink(El);
  586. end;
  587. var
  588. I : Integer;
  589. aList : TStringList;
  590. DescrEl : TDomElement;
  591. begin
  592. if Not (Assigned(DocNode) and Assigned(DocNode.SeeAlso)) then
  593. Exit;
  594. AList:=TStringList.Create;
  595. Try
  596. aList.Duplicates:=dupIgnore;
  597. // AList will have a TDomElement (seealso) or a TPasType element as object
  598. CollectSeeAlsoNodes(aList,DocNode.SeeAlso);
  599. CollectDeclarationTypes(aList,aElement);
  600. if aList.Count = 0 then
  601. exit;
  602. aList.Sort;
  603. AppendHeader(2,SDocSeeAlso);
  604. AppendTableHeader([SDocName,SDocDescription]);
  605. For I:=0 to aList.Count-1 do
  606. begin
  607. DescrEl:=Nil;
  608. DescrBeginTableRow;
  609. DescrBeginTableCell;
  610. if aList.Objects[I] is TDomElement then
  611. AppendSeeAlso(aList[i],TDomElement(aList.Objects[i]))
  612. else if aList.Objects[i] is TPasType then
  613. AppendTypeRef(aList[i],TPasType(aList.Objects[i]));
  614. DescrEndTableCell;
  615. DescrBeginTableCell;
  616. DescrEl:=Engine.FindShortDescr(ModuleForElement(AElement),UTF8Encode(aList[i]));
  617. if Assigned(DescrEl) then
  618. ConvertShort(AElement, DescrEl)
  619. else
  620. AppendToLine(' ',False);
  621. DescrEndTableCell;
  622. DescrEndTableRow;
  623. end;
  624. DescrEndTable;
  625. Finally
  626. aList.Free;
  627. end;
  628. end;
  629. procedure TMarkdownWriter.AppendExampleSection ( AElement: TPasElement;
  630. DocNode: TDocNode ) ;
  631. var
  632. Node: TDOMNode;
  633. fn,s: String;
  634. f: Text;
  635. begin
  636. if not (Assigned(DocNode) and Assigned(DocNode.FirstExample)) then
  637. Exit;
  638. Node := DocNode.FirstExample;
  639. while Assigned(Node) do
  640. begin
  641. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'example') then
  642. begin
  643. fn:=Engine.GetExampleFilename(TDOMElement(Node));
  644. If (fn<>'') then
  645. begin
  646. AppendHeader(2, SDocExample);
  647. try
  648. Assign(f, FN);
  649. Reset(f);
  650. try
  651. DescrBeginCode(False, UTF8Encode(TDOMElement(Node)['highlighter']));
  652. while not EOF(f) do
  653. begin
  654. ReadLn(f, s);
  655. DescrWriteCodeLine(s);
  656. end;
  657. finally
  658. Close(f);
  659. DescrEndCode;
  660. end;
  661. except
  662. on e: Exception do
  663. begin
  664. e.Message := '[example] ' + e.Message;
  665. raise;
  666. end;
  667. end;
  668. end;
  669. end;
  670. Node := Node.NextSibling;
  671. end;
  672. end;
  673. procedure TMarkdownWriter.AppendPageFooter;
  674. Var
  675. S : String;
  676. begin
  677. if Assigned(FFooterMarkDown) then
  678. begin
  679. EnsureEmptyLine;
  680. For S in FFooterMarkDown do
  681. AppendToLine(S,False)
  682. end;
  683. end;
  684. procedure TMarkdownWriter.FinishElementPage(AElement: TPasElement; SkipDescription : Boolean = false);
  685. var
  686. DocNode: TDocNode;
  687. begin
  688. DocNode := Engine.FindDocNode(AElement);
  689. If Not Assigned(DocNode) then
  690. exit;
  691. // Description
  692. if Assigned(DocNode.Descr) and not SkipDescription then
  693. AppendDescrSection(AElement, DocNode.Descr, UTF8Encode(SDocDescription));
  694. // Append "Errors" section
  695. if Assigned(DocNode.ErrorsDoc) then
  696. AppendDescrSection(AElement, DocNode.ErrorsDoc, UTF8Encode(SDocErrors));
  697. // Append Version info
  698. if Assigned(DocNode.Version) then
  699. AppendDescrSection(AElement, DocNode.Version, UTF8Encode(SDocVersion));
  700. // Append "See also" section
  701. AppendSeeAlsoSection(AElement,DocNode);
  702. // Append examples, if present
  703. AppendExampleSection(AElement,DocNode);
  704. // Append notes, if present
  705. ConvertNotes(AElement,DocNode.Notes);
  706. end;
  707. procedure TMarkdownWriter.CreateTopicPageBody(AElement: TTopicElement);
  708. var
  709. DocNode: TDocNode;
  710. begin
  711. DocNode:=AElement.TopicNode;
  712. AppendTitle(AElement.Name);
  713. if not Assigned(DocNode) then // should always be true, but we're being careful.
  714. exit;
  715. AppendShortDescr(AElement, DocNode);
  716. if Assigned(DocNode.Descr) then
  717. AppendDescrSection(AElement, DocNode.Descr, '');
  718. AppendSeeAlsoSection(AElement,DocNode);
  719. CreateTopicLinks(DocNode,AElement);
  720. AppendExampleSection(AElement,DocNode);
  721. ConvertNotes(AElement,DocNode.Notes);
  722. end;
  723. procedure TMarkdownWriter.CreateClassHierarchyPage(AddUnit : Boolean);
  724. type
  725. TypeEN = (NPackage, NModule, NName);
  726. Procedure AddClassList;
  727. begin
  728. DescrBeginUnorderedList;
  729. end;
  730. Procedure EndClassList;
  731. begin
  732. DescrEndUnorderedList;
  733. end;
  734. function ExtractName(APathName: String; Tp: TypeEN):String;
  735. var
  736. l:TStringList;
  737. begin
  738. Result:= Trim(APathName);
  739. if Result = '' then exit;
  740. l:=TStringList.Create;
  741. try
  742. l.AddDelimitedText(Result, '.', True);
  743. if l.Count=3 then
  744. Result:= l.Strings[Integer(Tp)]
  745. else
  746. Result:='';
  747. finally
  748. l.free;
  749. end;
  750. end;
  751. Procedure AppendClass(EN : TPasElementNode);
  752. Var
  753. PE,PM : TPasElement;
  754. I : Integer;
  755. begin
  756. if not Assigned(EN) then exit;
  757. PE:=EN.Element;
  758. DescrBeginListItem;
  759. AppendHyperLink(PE);
  760. PM:=ModuleForElement(PE);
  761. if (PM<>Nil) then
  762. begin
  763. AppendText(' (');
  764. AppendHyperLink(PM);
  765. AppendText(')');
  766. end
  767. else
  768. AppendText(EN.Element.Name);
  769. if EN.ChildCount>0 then
  770. begin
  771. AddClassList;
  772. For I:=0 to EN.ChildCount-1 do
  773. AppendClass(EN.Children[i] as TPasElementNode);
  774. EndClassList;
  775. end;
  776. DescrEndListItem;
  777. end;
  778. begin
  779. AddClassList;
  780. AppendClass(TreeClass.RootNode);
  781. EndClassList;
  782. end;
  783. procedure TMarkdownWriter.CreatePackageClassHierarchy;
  784. Var
  785. S : String;
  786. begin
  787. S:=Package.Name;
  788. If Length(S)>0 then
  789. Delete(S,1,1);
  790. AppendTitle(SDocPackageClassHierarchy, [S]);
  791. CreateClassHierarchyPage(True);
  792. end;
  793. procedure TMarkdownWriter.CreatePageBody(AElement: TPasElement; ASubpageIndex: Integer);
  794. var
  795. i: Integer;
  796. Element: TPasElement;
  797. begin
  798. CurDirectory := Allocator.GetFilename(AElement, ASubpageIndex);
  799. i := Length(CurDirectory);
  800. while (i > 0) and not (CurDirectory[i] in AllowDirectorySeparators) do
  801. Dec(i);
  802. CurDirectory := Copy(CurDirectory, 1, i);
  803. BaseDirectory := Allocator.GetRelativePathToTop(AElement);
  804. if AElement.ClassType = TPasPackage then
  805. begin
  806. Module:=Nil;
  807. If (ASubPageIndex=0) then
  808. CreatePackagePageBody
  809. else if ASubPageIndex=IndexSubIndex then
  810. CreatePackageIndex
  811. else if ASubPageIndex=ClassHierarchySubIndex then
  812. CreatePackageClassHierarchy
  813. end
  814. else
  815. begin
  816. Element := AElement;
  817. while (Element<>Nil) and (not (Element.ClassType.inheritsfrom(TPasModule))) do
  818. Element := Element.Parent;
  819. Module := TPasModule(Element);
  820. if AElement.ClassType.inheritsfrom(TPasModule) then
  821. CreateModulePageBody(TPasModule(AElement), ASubpageIndex)
  822. else if AElement.Parent.InheritsFrom(TPasClassType) then
  823. CreateClassMemberPageBody(AElement)
  824. else if AElement.ClassType = TPasConst then
  825. CreateConstPageBody(TPasConst(AElement))
  826. else if AElement.InheritsFrom(TPasClassType) then
  827. CreateClassPageBody(TPasClassType(AElement), ASubpageIndex)
  828. else if AElement.InheritsFrom(TPasType) then
  829. CreateTypePageBody(TPasType(AElement))
  830. else if AElement.ClassType = TPasVariable then
  831. CreateVarPageBody(TPasVariable(AElement))
  832. else if AElement.InheritsFrom(TPasProcedureBase) then
  833. CreateProcPageBody(TPasProcedureBase(AElement))
  834. else if AElement.ClassType = TTopicELement then
  835. CreateTopicPageBody(TTopicElement(AElement))
  836. else if AElement.ClassType = TPasProperty then
  837. CreateClassMemberPageBody(TPasProperty(AElement))
  838. else
  839. writeln('Unknown classtype: ',AElement.classtype.classname);
  840. end;
  841. end;
  842. procedure TMarkdownWriter.CreateIndexPage(L : TStringList);
  843. Var
  844. Lists : Array['A'..'Z'] of TStringList;
  845. CL : TStringList;
  846. E : TPasElement;
  847. CCount,I,Rows,J,Index : Integer;
  848. S : String;
  849. C : Char;
  850. begin
  851. For C:='A' to 'Z' do
  852. Lists[C]:=Nil;
  853. L.Sort;
  854. Cl:=Nil;
  855. // Divide over alphabet
  856. For I:=0 to L.Count-1 do
  857. begin
  858. S:=L[i];
  859. E:=TPasElement(L.Objects[i]);
  860. If not (E is TPasUnresolvedTypeRef) then
  861. begin
  862. If (S<>'') then
  863. begin
  864. C:=Upcase(S[1]);
  865. If C='_' then
  866. C:='A';
  867. If (C in ['A'..'Z']) and (Lists[C]=Nil) then
  868. begin
  869. CL:=TStringList.Create;
  870. Lists[C]:=CL;
  871. end;
  872. end;
  873. if assigned(cl) then
  874. CL.AddObject(S,E);
  875. end;
  876. end;
  877. Try
  878. // Create a quick jump table to all available letters.
  879. CCount:=0;
  880. for C:='A' to 'Z' do
  881. If (Lists[C]<>Nil) then
  882. Inc(CCount);
  883. DescrBeginTable(CCount,False);
  884. DescrBeginTableHeadRow;
  885. for C:='A' to 'Z' do
  886. If (Lists[C]<>Nil) then
  887. begin
  888. DescrBeginTableCell;
  889. AppendLink(C,'#'+LowerCase(C));
  890. DescrendTableCell;
  891. end;
  892. DescrEndTableHeadRow;
  893. // Now emit all identifiers.
  894. For C:='A' to 'Z' do
  895. begin
  896. CL:=Lists[C];
  897. If CL<>Nil then
  898. begin
  899. AppendHeader(3,C);
  900. DescrBeginTable(IndexColCount,False);
  901. DescrBeginTableHeadRow;
  902. For I:=1 to IndexColCount do
  903. begin
  904. DescrBeginTableCell;
  905. AppendToLine('&nbsp; ',False);
  906. DescrEndTableCell;
  907. end;
  908. DescrEndTableHeadRow;
  909. // Determine number of rows needed
  910. Rows:=(CL.Count div IndexColCount);
  911. If ((CL.Count Mod IndexColCount)<>0) then
  912. Inc(Rows);
  913. // Fill rows
  914. For I:=0 to Rows-1 do
  915. begin
  916. DescrBeginTableRow;
  917. For J:=0 to IndexColCount-1 do
  918. begin
  919. DescrBeginTableCell;
  920. Index:=(J*Rows)+I;
  921. If (Index<CL.Count) then
  922. begin
  923. S:=CL[Index];
  924. E:=TPasElement(CL.Objects[Index]);
  925. AppendHyperlink(E);
  926. end;
  927. end;
  928. DescrEndTableRow;
  929. end;
  930. end; // have List
  931. end; // For C:=
  932. Finally
  933. for C:='A' to 'Z' do
  934. FreeAndNil(Lists[C]);
  935. end;
  936. end;
  937. procedure TMarkdownWriter.AddModuleIdentifiers(AModule : TPasModule; L : TStrings);
  938. begin
  939. if assigned(AModule.InterfaceSection) Then
  940. begin
  941. AddElementsFromList(L,AModule.InterfaceSection.Consts);
  942. AddElementsFromList(L,AModule.InterfaceSection.Types);
  943. AddElementsFromList(L,AModule.InterfaceSection.Functions);
  944. AddElementsFromList(L,AModule.InterfaceSection.Classes);
  945. AddElementsFromList(L,AModule.InterfaceSection.Variables);
  946. AddElementsFromList(L,AModule.InterfaceSection.ResStrings);
  947. end;
  948. end;
  949. procedure TMarkdownWriter.CreatePackageIndex;
  950. Var
  951. L : TStringList;
  952. I : Integer;
  953. M : TPasModule;
  954. S : String;
  955. begin
  956. L:=TStringList.Create;
  957. try
  958. L.Capacity:=PageInfos.Count; // Too much, but that doesn't hurt.
  959. For I:=0 to Package.Modules.Count-1 do
  960. begin
  961. M:=TPasModule(Package.Modules[i]);
  962. L.AddObject(M.Name,M);
  963. AddModuleIdentifiers(M,L);
  964. end;
  965. S:=Package.Name;
  966. If Length(S)>0 then
  967. Delete(S,1,1);
  968. AppendTitle(SDocPackageIndex, [S]);
  969. CreateIndexPage(L);
  970. Finally
  971. L.Free;
  972. end;
  973. end;
  974. procedure TMarkdownWriter.CreatePackagePageBody;
  975. var
  976. DocNode: TDocNode;
  977. i: Integer;
  978. ThisModule: TPasModule;
  979. L : TStringList;
  980. begin
  981. AppendTitle(SDocPackageTitle, [Copy(Package.Name, 2, 256)]);
  982. AppendShortDescr(Package);
  983. AppendHeader(2,SDocUnits);
  984. L:=TStringList.Create;
  985. Try
  986. L.Sorted:=True;
  987. // Sort modules.
  988. For I:=0 to Package.Modules.Count-1 do
  989. L.AddObject(TPasModule(Package.Modules[i]).Name,TPasModule(Package.Modules[i]));
  990. AppendTableHeader([SDocUnits,SDocDescription]);
  991. // Now create table.
  992. for i:=0 to L.Count - 1 do
  993. begin
  994. ThisModule := TPasModule(L.Objects[i]);
  995. DescrBeginTableRow;
  996. DescrBeginTableCell;
  997. AppendHyperlink(ThisModule);
  998. DescrEndTableCell;
  999. AppendShortDescrCell(ThisModule);
  1000. DescrEndTableRow;
  1001. end;
  1002. DescrEndTable;
  1003. Finally
  1004. L.Free;
  1005. end;
  1006. DocNode := Engine.FindDocNode(Package);
  1007. if Assigned(DocNode) then
  1008. begin
  1009. if Assigned(DocNode.Descr) then
  1010. AppendDescrSection(nil, DocNode.Descr, UTF8Decode(SDocDescription));
  1011. CreateTopicLinks(DocNode,Package);
  1012. end;
  1013. end;
  1014. procedure TMarkdownWriter.CreateTopicLinks ( Node: TDocNode; PasElement: TPasElement ) ;
  1015. var
  1016. DocNode: TDocNode;
  1017. First : Boolean;
  1018. ThisTopic: TPasElement;
  1019. begin
  1020. DocNode:=Node.FirstChild;
  1021. First:=True;
  1022. While Assigned(DocNode) do
  1023. begin
  1024. If DocNode.TopicNode then
  1025. begin
  1026. if first then
  1027. begin
  1028. First:=False;
  1029. AppendHeader(2,SDocRelatedTopics);
  1030. AppendTableHeader([SDocTopic,SDocDescription]);
  1031. end;
  1032. ThisTopic:=FindTopicElement(DocNode);
  1033. if Assigned(ThisTopic) then
  1034. begin
  1035. DescrBeginTableRow;
  1036. DescrBeginTableCell;
  1037. AppendHyperlink(ThisTopic);
  1038. DescrEndTableCell;
  1039. AppendShortDescrCell(ThisTopic);
  1040. DescrEndTableRow;
  1041. end;
  1042. end;
  1043. DocNode:=DocNode.NextSibling;
  1044. end;
  1045. if not First then
  1046. DescrEndTable;
  1047. end;
  1048. function TMarkdownWriter.GetFileBaseDir(aOutput: String): String;
  1049. begin
  1050. Result:=inherited GetFileBaseDir(aOutput)+'docs'+pathdelim;
  1051. end;
  1052. procedure TMarkdownWriter.CreateModuleIndexPage(AModule: TPasModule);
  1053. Var
  1054. L : TStringList;
  1055. begin
  1056. L:=TStringList.Create;
  1057. try
  1058. AddModuleIdentifiers(AModule,L);
  1059. AppendTitle(SDocModuleIndex, [AModule.Name]);
  1060. CreateIndexPage(L);
  1061. Finally
  1062. L.Free;
  1063. end;
  1064. end;
  1065. procedure TMarkdownWriter.CreateModuleMainPageBody(AModule: TPasModule);
  1066. var
  1067. i: Integer;
  1068. UnitRef: TPasType;
  1069. DocNode: TDocNode;
  1070. begin
  1071. AppendTitle(SDocUnitTitle, [AModule.Name]);
  1072. AppendShortDescr(AModule);
  1073. if AModule.InterfaceSection.UsesList.Count > 0 then
  1074. begin
  1075. AppendTableHeader(['Uses unit',SDocDescription]);
  1076. for i := 0 to AModule.InterfaceSection.UsesList.Count - 1 do
  1077. begin
  1078. UnitRef := TPasType(AModule.InterfaceSection.UsesList[i]);
  1079. DocNode := Engine.FindDocNode(UnitRef);
  1080. if Assigned(DocNode) and DocNode.IsSkipped then
  1081. continue;
  1082. DescrBeginTableRow;
  1083. DescrBeginTableCell;
  1084. AppendHyperlink(UnitRef);
  1085. DescrEndTableCell;
  1086. AppendShortDescrCell(UnitRef);
  1087. end;
  1088. DescrEndTable;
  1089. end;
  1090. DocNode := Engine.FindDocNode(AModule);
  1091. if Assigned(DocNode) then
  1092. begin
  1093. if Assigned(DocNode.Descr) then
  1094. AppendDescrSection(AModule, DocNode.Descr, UTF8Decode(SDocOverview));
  1095. ConvertNotes(AModule,DocNode.Notes);
  1096. CreateTopicLinks(DocNode,AModule);
  1097. end;
  1098. end;
  1099. procedure TMarkdownWriter.CreateSimpleSubpage(aModule : TPasModule; const ATitle,aItem: String; AList: TFPList);
  1100. var
  1101. i: Integer;
  1102. Decl: TPasElement;
  1103. SortedList: TFPList;
  1104. DocNode: TDocNode;
  1105. begin
  1106. AppendTitle(SDocUnitTitle + ': %s', [AModule.Name, aTitle]);
  1107. SortedList := TFPList.Create;
  1108. try
  1109. for i := 0 to AList.Count - 1 do
  1110. begin
  1111. Decl := TPasElement(AList[i]);
  1112. DocNode := Engine.FindDocNode(Decl);
  1113. if not (Assigned(DocNode) and DocNode.IsSkipped) then
  1114. SortedList.Add(Decl);
  1115. end;
  1116. SortedList.Sort(@SortPasElements);
  1117. AppendTableHeader([aItem,SDocDescription]);
  1118. for i := 0 to SortedList.Count - 1 do
  1119. begin
  1120. Decl:=TPasElement(SortedList[i]);
  1121. DescrBeginTableRow;
  1122. DescrBeginTableCell;
  1123. AppendHyperlink(Decl);
  1124. DescrEndTableCell;
  1125. AppendShortDescrCell(Decl);
  1126. DescrEndTableRow;
  1127. end;
  1128. DescrEndTable;
  1129. finally
  1130. SortedList.Free;
  1131. end;
  1132. end;
  1133. procedure TMarkdownWriter.CreateResStringsPage(aModule : TPasModule);
  1134. var
  1135. i: Integer;
  1136. Decl: TPasResString;
  1137. begin
  1138. AppendTitle(SDocUnitTitle + ': %s', [AModule.Name, SDocResStrings]);
  1139. If AModule.InterfaceSection.ResStrings.Count = 0 then
  1140. exit;
  1141. for i := 0 to AModule.InterfaceSection.ResStrings.Count - 1 do
  1142. begin
  1143. Decl := TPasResString(AModule.InterfaceSection.ResStrings[i]);
  1144. AppendToLine('<a name="%s"> %s',[LowerCase(Decl.Name),Decl.Name]);
  1145. Indent;
  1146. UTF8Decode(Decl.Expr.getDeclaration(true));
  1147. undent;
  1148. end;
  1149. end;
  1150. procedure TMarkdownWriter.CreateModulePageBody(AModule: TPasModule;
  1151. ASubpageIndex: Integer);
  1152. begin
  1153. case ASubpageIndex of
  1154. 0:
  1155. CreateModuleMainPageBody(aModule);
  1156. ResstrSubindex:
  1157. CreateResStringsPage(aModule);
  1158. ConstsSubindex:
  1159. CreateSimpleSubpage(aModule,SDocConstants, SDocConstant, AModule.InterfaceSection.Consts);
  1160. TypesSubindex:
  1161. CreateSimpleSubpage(aModule,SDocTypes, SDocType, AModule.InterfaceSection.Types);
  1162. ClassesSubindex:
  1163. CreateSimpleSubpage(aModule,SDocClasses, SDocClass, AModule.InterfaceSection.Classes);
  1164. ProcsSubindex:
  1165. CreateSimpleSubpage(aModule,SDocProceduresAndFunctions, SDocProcedureOrFunction, AModule.InterfaceSection.Functions);
  1166. VarsSubindex:
  1167. CreateSimpleSubpage(aModule,SDocVariables, SDocVariable, AModule.InterfaceSection.Variables);
  1168. IndexSubIndex:
  1169. CreateModuleIndexPage(AModule);
  1170. end;
  1171. end;
  1172. procedure TMarkdownWriter.CreateConstPageBody(AConst: TPasConst);
  1173. begin
  1174. AppendTitle(AConst.Name);
  1175. AppendShortDescr(AConst);
  1176. AppendHeader(2,SDocDeclaration);
  1177. AppendSourceRef(AConst);
  1178. DescrBeginCode(False,'Pascal');
  1179. EmitLine('const');
  1180. EmitLine(aConst.GetDeclaration(True));
  1181. DescrEndCode;
  1182. FinishElementPage(AConst);
  1183. end;
  1184. procedure TMarkdownWriter.CreateTypePageBody(AType: TPasType);
  1185. begin
  1186. AppendTitle(AType.Name);
  1187. AppendShortDescr(AType);
  1188. AppendHeader(2,SDocDeclaration);
  1189. AppendSourceRef(AType);
  1190. DescrBeginCode(False,'Pascal');
  1191. EmitLine('Type');
  1192. EmitLine(aType.GetDeclaration(True));
  1193. DescrEndCode;
  1194. FinishElementPage(AType);
  1195. end;
  1196. procedure TMarkdownWriter.CreateMemberDeclarations(AParent: TPasElement; Members: TFPList; Options: TMemberListOptions);
  1197. function GetMemberType(aMember : TPasElement) : string;
  1198. begin
  1199. if aMember is TPasProcedure then
  1200. Result:=SDocMethod
  1201. else if aMember is TPasProperty then
  1202. Result:=SDocProperty
  1203. else if aMember is TPasConst then
  1204. Result:=SDocConstant
  1205. else if aMember is TPasType then
  1206. Result:=SDocType
  1207. else
  1208. Result:=SDocField;
  1209. end;
  1210. var
  1211. Member: TPasElement;
  1212. MVisibility : TPasMemberVisibility;
  1213. i,aCount: Integer;
  1214. // isRecord,
  1215. isOverLoad : Boolean;
  1216. begin
  1217. // isRecord:=AParent is TPasRecordType;
  1218. if Members.Count = 0 then
  1219. begin
  1220. AppendText(SDocNoneAVailable);
  1221. Exit;
  1222. end;
  1223. if mloAppendType in Options then
  1224. AppendTableHeader([SDocMember,SDocType,SDocVisibility,SDocDescription])
  1225. else
  1226. AppendTableHeader([SDocMember,SDocVisibility,SDocDescription]);
  1227. aCount:=0;
  1228. Members.Sort(@SortPasElements);
  1229. for i := 0 to Members.Count - 1 do
  1230. begin
  1231. Member := TPasElement(Members[i]);
  1232. MVisibility:=Member.Visibility;
  1233. if mloCheckVisibility in Options then
  1234. if not Engine.ShowElement(Member) then
  1235. Continue;
  1236. isOverLoad:=(Member is TPasOverloadedProc);
  1237. if isOverload then
  1238. Member:=TPasElement((Member as TPasOverloadedProc).Overloads[0]);
  1239. Inc(aCount);
  1240. DescrBeginTableRow;
  1241. DescrBeginTableCell;
  1242. AppendHyperlink(Member);
  1243. if mloAppendParent in options then
  1244. begin
  1245. AppendText('(');
  1246. AppendHyperLink(Member.Parent);
  1247. AppendText(')');
  1248. end;
  1249. DescrEndTableCell;
  1250. if mloAppendType in Options then
  1251. begin
  1252. DescrBeginTableCell;
  1253. AppendText(GetMemberType(Member));
  1254. DescrEndTableCell;
  1255. end;
  1256. DescrBeginTableCell;
  1257. AppendText(VisibilityNames[MVisibility]);
  1258. DescrEndTableCell;
  1259. AppendShortDescrCell(member);
  1260. DescrEndTableRow;
  1261. end;
  1262. DescrEndTable;
  1263. if ACount=0 then
  1264. AppendText(SDocNoneAVailable)
  1265. end;
  1266. procedure TMarkdownWriter.AppendTitle(const S: String);
  1267. begin
  1268. AddMetaData('title',S);
  1269. AppendHeader(1,S);
  1270. EnsureEmptyLine;
  1271. end;
  1272. procedure TMarkdownWriter.AppendTitle(const Fmt: String;
  1273. const Args: array of const);
  1274. begin
  1275. AppendTitle(Format(Fmt,Args));
  1276. end;
  1277. function TMarkdownWriter.GetClassDeclarationFirstLine(aEl: TPasClassType): String;
  1278. Var
  1279. aLine : string;
  1280. I : Integer;
  1281. begin
  1282. aLine:=aEL.Name;
  1283. if aEl.GenericTemplateTypes.Count>0 then
  1284. begin
  1285. aLine:='generic '+aLine+'<';
  1286. For I:=0 to aEl.GenericTemplateTypes.Count-1 do
  1287. begin
  1288. if I>0 then
  1289. aLine:=aLine+', ';
  1290. aLine:=aLine+TPasGenericTemplateType(aEl.GenericTemplateTypes[i]).Name;
  1291. end;
  1292. aLine:=aLine+'>';
  1293. end;
  1294. aLine:=aLine+' = '+aEl.ElementTypeName;
  1295. if aEl.HelperForType<>Nil then
  1296. aLine:=aLine+' for '+aEl.HelperForType.Name;
  1297. if aEL.ExternalName<>'' then
  1298. aLine:=aLine+' external name '''+ael.ExternalName+'''';
  1299. if Assigned(aEL.AncestorType) then
  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: TPasClassType;
  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 (ThisClass.Interfaces.count>0) then
  1428. begin
  1429. AppendText('(');
  1430. for i:=0 to ThisClass.interfaces.count-1 do
  1431. begin
  1432. ThisInterface:=TPasClassType(ThisClass.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. end;
  1654. class procedure TMarkdownWriter.Usage(List: TStrings);
  1655. begin
  1656. List.add('--header=file');
  1657. List.Add(SMDUsageHeader);
  1658. List.add('--footer=file');
  1659. List.Add(SMDUsageFooter);
  1660. List.Add('--index-colcount=N');
  1661. List.Add(SMDIndexColcount);
  1662. List.Add('--image-url=url');
  1663. List.Add(SMDImageUrl);
  1664. List.Add('--theme=name');
  1665. List.Add(SMDTheme);
  1666. List.Add('--navigation=scheme');
  1667. List.Add(SMDNavigation);
  1668. List.Add(SMDNavSubtree);
  1669. List.Add(SMDNavTree);
  1670. end;
  1671. class procedure TMarkdownWriter.SplitImport(var AFilename, ALinkPrefix: String);
  1672. var
  1673. i: integer;
  1674. begin
  1675. i := Pos(',', AFilename);
  1676. if i > 0 then
  1677. begin //split into filename and prefix
  1678. ALinkPrefix := Copy(AFilename,i+1,Length(AFilename));
  1679. SetLength(AFilename, i-1);
  1680. end
  1681. else if ALinkPrefix = '' then
  1682. begin //synthesize outdir\pgk.xct, ..\pkg
  1683. ALinkPrefix := '../' + ChangeFileExt(ExtractFileName(AFilename), '');
  1684. AFilename := ChangeFileExt(AFilename, '.xct');
  1685. end;
  1686. end;
  1687. class function TMarkdownWriter.FileNameExtension: String;
  1688. begin
  1689. result:='md';
  1690. end;
  1691. // private methods
  1692. function TMarkdownWriter.GetPageCount: Integer;
  1693. begin
  1694. Result := PageInfos.Count;
  1695. end;
  1696. procedure TMarkdownWriter.SetOnTest(const AValue: TNotifyEvent);
  1697. begin
  1698. if FOnTest=AValue then exit;
  1699. FOnTest:=AValue;
  1700. end;
  1701. procedure TMarkdownWriter.AppendText(const S: String);
  1702. begin
  1703. AppendToLine(S,True);
  1704. end;
  1705. initialization
  1706. // Do not localize.
  1707. RegisterWriter(TMarkdownWriter,'md','Markdown output.');
  1708. finalization
  1709. UnRegisterWriter('md');
  1710. end.