md2html.lpr 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. program md2html;
  2. {$mode objfpc}{$H+}
  3. uses
  4. {$IFDEF UNIX}
  5. cthreads,
  6. {$ENDIF}
  7. Classes, SysUtils, CustApp, Markdown.Processors, MarkDown.Elements, Markdown.HtmlRender, MarkDown.Parser;
  8. type
  9. { TMD2HTMLApplication }
  10. TMD2HTMLApplication = class(TCustomApplication)
  11. const
  12. ShortOptions = 'hfi:o:H:t:';
  13. LongOptions : Array of String = ('help','full','input:','output:','head:','title:');
  14. private
  15. FHead : TStrings;
  16. FOutput : String;
  17. FInputs : Array of string;
  18. FHTMLTitle : String;
  19. FFull : Boolean;
  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),'.html');
  41. end
  42. else if FOutput<>'' then
  43. Result:=FOutput
  44. else
  45. Result:=ChangeFileExt(aInput,'.html');
  46. Writeln(aInput,' -> ',Result);
  47. end;
  48. procedure TMD2HTMLApplication.ConvertMarkDown(const aInput,aOutput : string);
  49. var
  50. lRenderer : TMarkDownHTMLRenderer;
  51. lParser : TMarkDownParser;
  52. lDoc : TMarkDownDocument;
  53. lMarkDown,lHTML : TStrings;
  54. begin
  55. lParser:=Nil;
  56. lDoc:=Nil;
  57. lMarkDown:=TStringList.Create;
  58. try
  59. lMarkDown.LoadFromFile(aInput);
  60. lParser:=TMarkDownParser.Create(Self);
  61. lDoc:=lParser.Parse(lMarkDown);
  62. lRenderer:=TMarkDownHTMLRenderer.Create(Self);
  63. if FFull then
  64. begin
  65. lRenderer.Options:=[hoEnvelope,hoHead];
  66. lRenderer.Title:=FHTMLTitle;
  67. if assigned(FHead) then
  68. lRenderer.Head:=FHead;
  69. end;
  70. lHTML:=TStringList.Create;
  71. lRenderer.RenderDocument(lDoc,lHTML);
  72. lHTML.SaveToFile(aOutput);
  73. finally
  74. lHTML.Free;
  75. lRenderer.Free;
  76. lDoc.Free;
  77. lParser.Free;
  78. lMarkDown.Free;
  79. end;
  80. end;
  81. procedure TMD2HTMLApplication.DoRun;
  82. var
  83. ErrorMsg: String;
  84. lInPut,lOutput : String;
  85. begin
  86. Terminate;
  87. ErrorMsg:=CheckOptions(ShortOptions,LongOptions);
  88. if (ErrorMsg<>'') or HasOption('h','help') then
  89. begin
  90. Usage(ErrorMsg);
  91. Exit;
  92. end;
  93. if not ProcessOptions then
  94. Exit;
  95. For lInput in FInputs do
  96. begin
  97. lOutput:=CreateOutputFileName(lInput,Length(FInputs)>1);
  98. ConvertMarkDown(lInput,lOutput);
  99. end;
  100. end;
  101. function TMD2HTMLApplication.ProcessOptions: boolean;
  102. var
  103. lFileName : string;
  104. begin
  105. Result:=False;
  106. FInputs:=GetOptionValues('i','input');
  107. if Length(FInputs)=0 then
  108. FInputs:=GetNonOptions(ShortOptions,LongOptions);
  109. FOutput:=GetOptionValue('o','output');
  110. if Length(FInputs)>1 then
  111. If not DirectoryExists(FOutput) then
  112. begin
  113. Usage('Directory does not exist or is not a directory: '+Foutput);
  114. exit;
  115. end;
  116. FFull:=HasOption('f','full');
  117. FHTMLTitle:=GetOptionValue('t','title');
  118. lFileName:=GetOptionValue('H','head');
  119. if (lFilename<>'') then
  120. begin
  121. if not FileExists(lFileName) then
  122. begin
  123. Usage('Head matter file does not exist: '+lFileName);
  124. exit;
  125. end;
  126. FHead:=TStringList.Create;
  127. FHead.LoadFromFile(lFileName);
  128. end;
  129. Result:=True;
  130. end;
  131. constructor TMD2HTMLApplication.Create(aOwner: TComponent);
  132. begin
  133. inherited Create(aOwner);
  134. StopOnException:=True;
  135. end;
  136. destructor TMD2HTMLApplication.Destroy;
  137. begin
  138. FreeAndNil(FHead);
  139. inherited Destroy;
  140. end;
  141. procedure TMD2HTMLApplication.Usage(const ErrMsg : string);
  142. begin
  143. if ErrMsg<>'' then
  144. Writeln('Error: ',ErrMsg);
  145. Writeln('Usage: ', ExeName, ' [options]');
  146. Writeln('Where options is one or more of:');
  147. Writeln('-h --help this message');
  148. Writeln('-i --input=FILE Input markdown file');
  149. Writeln('-o --output=FILE Output HTML file');
  150. Writeln('-f --full Output complete HTML file (html/body/head tags))');
  151. Writeln('-H --head=FILE head tag content file');
  152. ExitCode:=Ord(ErrMsg<>'');
  153. end;
  154. var
  155. Application: TMD2HTMLApplication;
  156. begin
  157. Application:=TMD2HTMLApplication.Create(nil);
  158. Application.Title:='Markdown to HTML converter';
  159. Application.Run;
  160. Application.Free;
  161. end.