md2fpdoc.lpr 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. program md2fpdoc;
  2. {$mode objfpc}{$H+}
  3. uses
  4. {$IFDEF UNIX}
  5. cthreads,
  6. {$ENDIF}
  7. Classes, SysUtils, CustApp, Markdown.Processors, MarkDown.Elements, Markdown.FPDocRender, MarkDown.Parser;
  8. type
  9. { TMD2HTMLApplication }
  10. TMD2HTMLApplication = class(TCustomApplication)
  11. const
  12. ShortOptions = 'hi:o:p:q';
  13. LongOptions : Array of String = ('help','input:','output:','package:','quiet');
  14. private
  15. FQuiet : Boolean;
  16. FOutput : String;
  17. FInputs : Array of string;
  18. FPackage : String;
  19. procedure DoLog(EventType: TEventType; const Msg: String); override;
  20. procedure ConvertMarkDown(const aInput, aOutput: string);
  21. function CreateOutputFileName(const aInput: string; isMulti: boolean): string;
  22. protected
  23. procedure DoRun; override;
  24. function ProcessOptions : boolean; virtual;
  25. procedure Usage(const ErrMsg: string); virtual;
  26. public
  27. constructor Create(aOwner: TComponent); override;
  28. destructor Destroy; override;
  29. end;
  30. { TMD2HTMLApplication }
  31. function TMD2HTMLApplication.CreateOutputFileName(const aInput : string; isMulti : boolean) : string;
  32. var
  33. lDir : string;
  34. begin
  35. if isMulti then
  36. begin
  37. lDir:=Foutput;
  38. if lDir<>'' then
  39. lDir:=IncludeTrailingPathDelimiter(lDir);
  40. Result:=lDir+ChangeFileExt(ExtractFileName(aInput),'.xml');
  41. end
  42. else if FOutput<>'' then
  43. Result:=FOutput
  44. else
  45. Result:=ChangeFileExt(aInput,'.xml');
  46. end;
  47. procedure TMD2HTMLApplication.DoLog(EventType: TEventType; const Msg: String);
  48. begin
  49. if FQuiet then
  50. exit;
  51. Writeln(StdErr,'[',EventType,'] ',Msg);
  52. end;
  53. procedure TMD2HTMLApplication.ConvertMarkDown(const aInput,aOutput : string);
  54. var
  55. lRenderer : TMarkDownFPDocRenderer;
  56. lParser : TMarkDownParser;
  57. lDoc : TMarkDownDocument;
  58. lMarkDown,lHTML : TStrings;
  59. begin
  60. Log(etInfo,'Converting %s to %s',[aInput,aOutput]);
  61. try
  62. lParser:=Nil;
  63. lDoc:=Nil;
  64. lMarkDown:=TStringList.Create;
  65. try
  66. lMarkDown.LoadFromFile(aInput);
  67. lParser:=TMarkDownParser.Create(Self);
  68. lDoc:=lParser.Parse(lMarkDown);
  69. lRenderer:=TMarkDownFPDocRenderer.Create(Self);
  70. lRenderer.PackageName:=FPackage;
  71. lHTML:=TStringList.Create;
  72. lRenderer.RenderDocument(lDoc,lHTML);
  73. lHTML.SaveToFile(aOutput);
  74. finally
  75. lHTML.Free;
  76. lRenderer.Free;
  77. lDoc.Free;
  78. lParser.Free;
  79. lMarkDown.Free;
  80. end;
  81. except
  82. on E : Exception do
  83. Log(etError,'Error %s while onverting %s to %s : %s',[E.ClassName,aInput,aOutput,E.Message]);
  84. end;
  85. end;
  86. procedure TMD2HTMLApplication.DoRun;
  87. var
  88. ErrorMsg: String;
  89. lInPut,lOutput : String;
  90. begin
  91. Terminate;
  92. ErrorMsg:=CheckOptions(ShortOptions,LongOptions);
  93. if (ErrorMsg<>'') or HasOption('h','help') then
  94. begin
  95. Usage(ErrorMsg);
  96. Exit;
  97. end;
  98. if not ProcessOptions then
  99. Exit;
  100. For lInput in FInputs do
  101. begin
  102. lOutput:=CreateOutputFileName(lInput,Length(FInputs)>1);
  103. ConvertMarkDown(lInput,lOutput);
  104. end;
  105. end;
  106. function TMD2HTMLApplication.ProcessOptions: boolean;
  107. begin
  108. Result:=False;
  109. FQuiet:=HasOption('q','quiet');
  110. FInputs:=GetOptionValues('i','input');
  111. if Length(FInputs)=0 then
  112. FInputs:=GetNonOptions(ShortOptions,LongOptions);
  113. FOutput:=GetOptionValue('o','output');
  114. if Length(FInputs)>1 then
  115. If not DirectoryExists(FOutput) then
  116. begin
  117. Usage('Directory does not exist or is not a directory: '+Foutput);
  118. exit;
  119. end;
  120. FPackage:=GetOptionValue('p','package');
  121. if FPackage='' then
  122. begin
  123. Usage('A package name is required');
  124. exit;
  125. end;
  126. Result:=True;
  127. end;
  128. constructor TMD2HTMLApplication.Create(aOwner: TComponent);
  129. begin
  130. inherited Create(aOwner);
  131. StopOnException:=True;
  132. end;
  133. destructor TMD2HTMLApplication.Destroy;
  134. begin
  135. inherited Destroy;
  136. end;
  137. procedure TMD2HTMLApplication.Usage(const ErrMsg : string);
  138. begin
  139. if ErrMsg<>'' then
  140. begin
  141. Writeln(StdErr,'Error: ',ErrMsg);
  142. Flush(StdErr);
  143. end;
  144. Writeln('Usage: ', ExeName, ' [options]');
  145. Writeln('Where options is one or more of:');
  146. Writeln('-h --help this message.');
  147. Writeln('-i --input=FILE Input markdown file.');
  148. Writeln('-o --output=FILE Output HTML file.');
  149. Writeln('-p --package=NAME Set package name.');
  150. Writeln('-q --quiet Less messages.');
  151. ExitCode:=Ord(ErrMsg<>'');
  152. end;
  153. var
  154. Application: TMD2HTMLApplication;
  155. begin
  156. Application:=TMD2HTMLApplication.Create(nil);
  157. Application.Title:='Markdown to FPDoc converter';
  158. Application.Run;
  159. Application.Free;
  160. end.