CHMProducer.pas 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. unit CHMProducer;
  2. {$I ImagingOptions.inc}
  3. interface
  4. uses
  5. SysUtils, Classes, Helpers, DemoUtils, DOM;
  6. const
  7. sCHMStyleSheet = 'doc2html.xsl';
  8. sCHMTOCStyleSheet = 'toc2hhc.xsl';
  9. sCHMProjectStyleSheet = 'proj2hhp.xsl';
  10. sCHMExt = 'html';
  11. sCHMProjectExt = 'hhp';
  12. sCHMTOCExt = 'hhc';
  13. sCHMDir = 'chm';
  14. sCHMDelim = '/';
  15. sTempFile = 'temp.xml';
  16. sDocTempFile = 'doctemp.xsl';
  17. sXFile = 'file';
  18. type
  19. TCHMProducer = class(TDocProducer)
  20. private
  21. FOutDir: string;
  22. FRootDir: string;
  23. FProject: TDocProject;
  24. FDocTempPath: string;
  25. procedure CreateContents;
  26. procedure CreateProject(Files: TStrings);
  27. procedure ConvertPagesToHTML(Item: TContentItem);
  28. function CreateProducerData(Files: TStrings; Doc: TDOMDocument): TDOMElement;
  29. public
  30. constructor Create;
  31. procedure Process(Project: TDocProject; const OutDir: string); override;
  32. end;
  33. function CreateCHMLinker: TLinkChecker;
  34. implementation
  35. function CheckContext(const S, Context: string): string;
  36. begin
  37. if SameText(Context, sXTOCFile) then
  38. Result := ChangeFileExt(S, '.' + sCHMTOCExt)
  39. else
  40. Result := S;
  41. end;
  42. function CreateCHMLinker: TLinkChecker;
  43. begin
  44. Result := TLinkChecker.Create;
  45. Result.StripDir := True;
  46. Result.Extension := sCHMExt;
  47. Result.NewPathDelim := PathDelim;
  48. Result.CustomConverter := CheckContext;
  49. end;
  50. { TCHMProducer }
  51. constructor TCHMProducer.Create;
  52. begin
  53. inherited Create;
  54. FName := 'HTMLHelp Doc Producer';
  55. end;
  56. function TCHMProducer.CreateProducerData(Files: TStrings; Doc: TDOMDocument): TDOMElement;
  57. var
  58. Elem: TDOMElement;
  59. Text: TDOMText;
  60. I: LongInt;
  61. begin
  62. Result := Doc.CreateElement(sXProducer);
  63. for I := 0 to Files.Count - 1 do
  64. begin
  65. Elem := Doc.CreateElement(sXFile);
  66. Text := Doc.CreateTextNode(Files[I]);
  67. Elem.AppendChild(Text);
  68. Result.AppendChild(Elem);
  69. end;
  70. end;
  71. procedure TCHMProducer.CreateContents;
  72. var
  73. Input, Style, Output: string;
  74. Linker: TLinkChecker;
  75. begin
  76. Msg('Creating HTMLHelp contents file .hhc ...');
  77. Input := FProject.ContentsFile;
  78. Style := FProject.XslDir + PathDelim + sCHMTOCStyleSheet;
  79. Output := FOutDir + PathDelim + sCHMDir + PathDelim +
  80. ExtractFileName(ChangeFileExt(FProject.ContentsFile, '.' + sCHMTOCExt));
  81. Linker := CreateCHMLinker;
  82. Linker.CheckDocument(Input, FProject);
  83. Linker.SaveResult(FOutDir + PathDelim + sTempFile);
  84. TransformDoc(FOutDir + PathDelim + sTempFile, Output, Style);
  85. Linker.DeleteResult;
  86. Linker.Free;
  87. end;
  88. procedure TCHMProducer.CreateProject(Files: TStrings);
  89. var
  90. Input, Style, Output: string;
  91. Linker: TLinkChecker;
  92. begin
  93. Msg('Creating HTMLHelp project file .hhp ...');
  94. Input := FProject.ProjectFile;
  95. Style := FProject.XslDir + PathDelim + sCHMProjectStyleSheet;
  96. Output := FOutDir + PathDelim + sCHMDir + PathDelim +
  97. FProject.OutputFile + '.' + sCHMProjectExt;
  98. Linker := CreateCHMLinker;
  99. Linker.CheckDocument(Input, FProject);
  100. Linker.Doc.DocumentElement.AppendChild(CreateProducerData(Files, Linker.Doc));
  101. Linker.SaveResult(FOutDir + PathDelim + sTempFile);
  102. TransformDoc(FOutDir + PathDelim + sTempFile, Output, Style);
  103. Linker.DeleteResult;
  104. Linker.Free;
  105. end;
  106. procedure TCHMProducer.ConvertPagesToHTML(Item: TContentItem);
  107. var
  108. I: LongInt;
  109. Input, Output: string;
  110. Linker: TLinkChecker;
  111. begin
  112. Input := ExpandFileTo(Item.URL, FRootDir);
  113. Output := FOutDir + PathDelim + sCHMDir + PathDelim +
  114. ChangeFileExt(ExtractFileName(Item.URL), '.' + sCHMExt);
  115. Linker := CreateCHMLinker;
  116. Linker.IntendedOutput := Output;
  117. Linker.CheckDocument(Input, FProject);
  118. Linker.SaveResult(FOutDir + PathDelim + sTempFile);
  119. TransformDoc(FOutDir + PathDelim + sTempFile, Output, FDocTempPath);
  120. Linker.DeleteResult;
  121. Linker.Free;
  122. for I := 0 to Item.ChildCount - 1 do
  123. ConvertPagesToHTML(Item[I]);
  124. end;
  125. procedure TCHMProducer.Process(Project: TDocProject; const OutDir: string);
  126. var
  127. Style, CmdLine: string;
  128. Linker: TXSLLinker;
  129. begin
  130. FOutDir := OutDir;
  131. FProject := Project;
  132. FRootDir := ExtractFileDir(FProject.ProjectFile);
  133. if (not ForceDirectories(FOutDir)) or
  134. (not ForceDirectories(FOutDir + PathDelim + sCHMDir)) then
  135. raise Exception.Create('Cannot create output directories.');
  136. CreateContents;
  137. FDocTempPath := FOutDir + PathDelim + sDocTempFile;
  138. Style := FProject.XslDir + PathDelim + sCHMStyleSheet;
  139. Linker := TXSLLinker.Create;
  140. Linker.IntendedOutput := FOutDir + PathDelim + sCHMDir + PathDelim + 'bla.blo';
  141. Linker.CheckDocument(Style, FProject);
  142. Linker.SaveResult(FDocTempPath);
  143. CreateProject(Linker.References);
  144. Msg('Converting pages to HTML ...');
  145. ConvertPagesToHTML(FProject.Contents);
  146. Linker.DeleteResult;
  147. Linker.Free;
  148. Msg('Compiling HTMLHelp project file .hhp ...');
  149. CmdLine := 'hhc ' + FOutDir + PathDelim + sCHMDir + PathDelim +
  150. FProject.OutputFile + '.' + sCHMProjectExt;
  151. if not RunCmdLine(CmdLine) then
  152. raise Exception.Create('HTMLHelp compiler cannot be executed.');
  153. end;
  154. end.