dw_markdown.pp 50 KB

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