dw_markdown.pp 51 KB

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