Skip to content

[clang-doc] Update clang-doc tool to enable mustache templates #138066

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: users/ilovepi/clang-doc-mustache-serializer
Choose a base branch
from

Conversation

ilovepi
Copy link
Contributor

@ilovepi ilovepi commented May 1, 2025

This patch adds a command line option and enables the Mustache template
HTML backend. This allows users to use the new, more flexible templates
over the old and cumbersome HTML output. Split from #133161.

Co-authored-by: Peter Chou peter.chou@mail.utoronto.ca

This patch adds a command line option and enables the Mustache template
HTML backend. This allows users to use the new, more flexible templates
over the old and cumbersome HTML output. Split from #133161.

Co-authored-by: Peter Chou <peter.chou@mail.utoronto.ca>
@llvmbot
Copy link
Member

llvmbot commented May 1, 2025

@llvm/pr-subscribers-clang-tools-extra

Author: Paul Kirth (ilovepi)

Changes

This patch adds a command line option and enables the Mustache template
HTML backend. This allows users to use the new, more flexible templates
over the old and cumbersome HTML output. Split from #133161.

Co-authored-by: Peter Chou <peter.chou@mail.utoronto.ca>


Full diff: https://github.com/llvm/llvm-project/pull/138066.diff

2 Files Affected:

  • (modified) clang-tools-extra/clang-doc/tool/CMakeLists.txt (+7)
  • (modified) clang-tools-extra/clang-doc/tool/ClangDocMain.cpp (+72-20)
diff --git a/clang-tools-extra/clang-doc/tool/CMakeLists.txt b/clang-tools-extra/clang-doc/tool/CMakeLists.txt
index 601a0460d76b3..eccbc99a7ecc4 100644
--- a/clang-tools-extra/clang-doc/tool/CMakeLists.txt
+++ b/clang-tools-extra/clang-doc/tool/CMakeLists.txt
@@ -21,6 +21,13 @@ target_link_libraries(clang-doc
 
 set(assets
   index.js
+  mustache-index.js
+  class-template.mustache
+  comments-template.mustache
+  enum-template.mustache      
+  function-template.mustache
+  namespace-template.mustache      
+  clang-doc-mustache.css
   clang-doc-default-stylesheet.css
 )
 
diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index 8e8f7053a8f87..a9b631f04ec28 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -18,20 +18,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "BitcodeReader.h"
-#include "BitcodeWriter.h"
 #include "ClangDoc.h"
 #include "Generators.h"
 #include "Representation.h"
-#include "clang/AST/AST.h"
-#include "clang/AST/Decl.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchersInternal.h"
-#include "clang/Driver/Options.h"
-#include "clang/Frontend/FrontendActions.h"
 #include "clang/Tooling/AllTUsExecution.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "clang/Tooling/Execution.h"
-#include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
@@ -110,11 +103,7 @@ static llvm::cl::opt<std::string> RepositoryCodeLinePrefix(
     llvm::cl::desc("Prefix of line code for repository."),
     llvm::cl::cat(ClangDocCategory));
 
-enum OutputFormatTy {
-  md,
-  yaml,
-  html,
-};
+enum OutputFormatTy { md, yaml, html, mhtml };
 
 static llvm::cl::opt<OutputFormatTy>
     FormatEnum("format", llvm::cl::desc("Format for outputted docs."),
@@ -123,7 +112,9 @@ static llvm::cl::opt<OutputFormatTy>
                                 clEnumValN(OutputFormatTy::md, "md",
                                            "Documentation in MD format."),
                                 clEnumValN(OutputFormatTy::html, "html",
-                                           "Documentation in HTML format.")),
+                                           "Documentation in HTML format."),
+                                clEnumValN(OutputFormatTy::mhtml, "mhtml",
+                                           "Documentation in mHTML format")),
                llvm::cl::init(OutputFormatTy::yaml),
                llvm::cl::cat(ClangDocCategory));
 
@@ -135,6 +126,8 @@ static std::string getFormatString() {
     return "md";
   case OutputFormatTy::html:
     return "html";
+  case OutputFormatTy::mhtml:
+    return "mhtml";
   }
   llvm_unreachable("Unknown OutputFormatTy");
 }
@@ -168,6 +161,14 @@ static llvm::Error getAssetFiles(clang::doc::ClangDocContext &CDCtx) {
   return llvm::Error::success();
 }
 
+static llvm::SmallString<128> appendPathNative(StringRef Path,
+                                               StringRef Asset) {
+  llvm::SmallString<128> Default;
+  llvm::sys::path::native(Path, Default);
+  llvm::sys::path::append(Default, Asset);
+  return Default;
+}
+
 static llvm::Error getDefaultAssetFiles(const char *Argv0,
                                         clang::doc::ClangDocContext &CDCtx) {
   void *MainAddr = (void *)(intptr_t)getExecutablePath;
@@ -178,13 +179,9 @@ static llvm::Error getDefaultAssetFiles(const char *Argv0,
   llvm::SmallString<128> AssetsPath;
   AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
   llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc");
-  llvm::SmallString<128> DefaultStylesheet;
-  llvm::sys::path::native(AssetsPath, DefaultStylesheet);
-  llvm::sys::path::append(DefaultStylesheet,
-                          "clang-doc-default-stylesheet.css");
-  llvm::SmallString<128> IndexJS;
-  llvm::sys::path::native(AssetsPath, IndexJS);
-  llvm::sys::path::append(IndexJS, "index.js");
+  llvm::SmallString<128> DefaultStylesheet =
+      appendPathNative(AssetsPath, "clang-doc-default-stylesheet.css");
+  llvm::SmallString<128> IndexJS = appendPathNative(AssetsPath, "index.js");
 
   if (!llvm::sys::fs::is_regular_file(IndexJS))
     return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -215,6 +212,54 @@ static llvm::Error getHtmlAssetFiles(const char *Argv0,
   return getDefaultAssetFiles(Argv0, CDCtx);
 }
 
+static llvm::Error getMustacheHtmlFiles(const char *Argv0,
+                                        clang::doc::ClangDocContext &CDCtx) {
+  if (!UserAssetPath.empty() &&
+      !llvm::sys::fs::is_directory(std::string(UserAssetPath)))
+    llvm::outs() << "Asset path supply is not a directory: " << UserAssetPath
+                 << " falling back to default\n";
+  if (llvm::sys::fs::is_directory(std::string(UserAssetPath)))
+    return getAssetFiles(CDCtx);
+
+  void *MainAddr = (void *)(intptr_t)getExecutablePath;
+  std::string ClangDocPath = getExecutablePath(Argv0, MainAddr);
+  llvm::SmallString<128> NativeClangDocPath;
+  llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
+
+  llvm::SmallString<128> AssetsPath;
+  AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
+  llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc");
+
+  llvm::SmallString<128> DefaultStylesheet =
+      appendPathNative(AssetsPath, "clang-doc-mustache.css");
+  llvm::SmallString<128> NamespaceTemplate =
+      appendPathNative(AssetsPath, "namespace-template.mustache");
+  llvm::SmallString<128> ClassTemplate =
+      appendPathNative(AssetsPath, "class-template.mustache");
+  llvm::SmallString<128> EnumTemplate =
+      appendPathNative(AssetsPath, "enum-template.mustache");
+  llvm::SmallString<128> FunctionTemplate =
+      appendPathNative(AssetsPath, "function-template.mustache");
+  llvm::SmallString<128> CommentTemplate =
+      appendPathNative(AssetsPath, "comments-template.mustache");
+  llvm::SmallString<128> IndexJS =
+      appendPathNative(AssetsPath, "mustache-index.js");
+
+  CDCtx.JsScripts.insert(CDCtx.JsScripts.begin(), IndexJS.c_str());
+  CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
+                               std::string(DefaultStylesheet));
+  CDCtx.MustacheTemplates.insert(
+      {"namespace-template", NamespaceTemplate.c_str()});
+  CDCtx.MustacheTemplates.insert({"class-template", ClassTemplate.c_str()});
+  CDCtx.MustacheTemplates.insert({"enum-template", EnumTemplate.c_str()});
+  CDCtx.MustacheTemplates.insert(
+      {"function-template", FunctionTemplate.c_str()});
+  CDCtx.MustacheTemplates.insert(
+      {"comments-template", CommentTemplate.c_str()});
+
+  return llvm::Error::success();
+}
+
 /// Make the output of clang-doc deterministic by sorting the children of
 /// namespaces and records.
 static void
@@ -290,6 +335,13 @@ Example usage for a project using a compile commands database:
     }
   }
 
+  if (Format == "mhtml") {
+    if (auto Err = getMustacheHtmlFiles(argv[0], CDCtx)) {
+      llvm::errs() << toString(std::move(Err)) << "\n";
+      return 1;
+    }
+  }
+
   // Mapping phase
   llvm::outs() << "Mapping decls...\n";
   auto Err =

Copy link
Contributor Author

ilovepi commented May 1, 2025

I'm wondering if this should be earlier in the stack to facilitate better testing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants