杰瑞科技汇

Python脚本如何生成CHM帮助文件?

Of course! Creating a CHM (Compiled HTML Help) file from a Python script is a common need for documenting libraries, tools, or applications. The process involves two main steps:

Python脚本如何生成CHM帮助文件?-图1
(图片来源网络,侵删)
  1. Create the HTML source files: This includes your documentation content, images, and a table of contents (TOC).
  2. Compile those files into a .chm file: This is the step a Python script can automate.

Here’s a complete guide, from manual setup to a fully automated Python script.


Step 1: The Manual Way (Understanding the Process)

Before we automate it, it's crucial to understand how CHM files are created. The standard tool for this on Windows is the HTML Help Workshop from Microsoft.

  1. Install HTML Help Workshop:

    • Download it from the Microsoft Download Center.
    • Install it. Make sure to note the installation path (e.g., C:\Program Files (x86)\HTML Help Workshop).
  2. Create Your HTML Content:

    Python脚本如何生成CHM帮助文件?-图2
    (图片来源网络,侵删)
    • Create a folder for your project, for example, my_docs.
    • Inside my_docs, create your HTML files. A good structure is:
      my_docs/
      ├── index.html          # The main entry page
      ├── getting_started.html
      ├── advanced_topics.html
      └── images/
          └── logo.png
  3. Create the Table of Contents (.hhc file):

    • This is the most important file for navigation. It's a simple HTML-like file that defines the tree structure of your help file.
    • You can create it manually or use a tool like VimHelpCompiler or Pothos Help Compiler.
    • Example my_toc.hhc:
      <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
      <HTML>
      <HEAD>
      <meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1">
      <!-- Sitemap 1.0 -->
      </HEAD><BODY>
      <OBJECT type="text/site properties">
        <param name="Window Styles" value="0x800227">
        <param name="ImageType" value="Folder">
      </OBJECT>
      <UL>
        <LI> <OBJECT type="text/sitemap">
          <param name="Name" value="My Awesome Project">
          <param name="Local" value="index.html">
        </OBJECT>
        <UL>
          <LI> <OBJECT type="text/sitemap">
            <param name="Name" value="Getting Started">
            <param name="Local" value="getting_started.html">
          </OBJECT>
          <LI> <OBJECT type="text/sitemap">
            <param name="Name" value="Advanced Topics">
            <param name="Local" value="advanced_topics.html">
          </OBJECT>
        </UL>
      </UL>
      </BODY></HTML>
  4. Create a Project File (.hhp file):

    • This file tells the HTML Help Compiler which files to include and what to name the output.

    • Create a file named my_project.hhp in the my_docs folder.

      Python脚本如何生成CHM帮助文件?-图3
      (图片来源网络,侵删)
    • Example my_project.hhp:

      [OPTIONS]
      Compatibility=1.1
      Compiled file=my_project.chm
      Contents file=my_toc.hhc
      Default topic=index.html
      Display compile progress=Yes
      Full-text search=Yes
      Title=My Awesome Project Documentation
      [FILES]
      index.html
      getting_started.html
      advanced_topics.html
      images/logo.png
  5. Compile the CHM:

    • Open the HTML Help Workshop.
    • Go to File -> Compile....
    • Select your my_project.hpp file.
    • Click Compile. It will generate my_project.chm.

Step 2: The Automated Python Script

Now, let's automate this process. The script will:

  1. Read your documentation source (e.g., from Markdown files).
  2. Generate the necessary HTML files.
  3. Generate the .hhc (Table of Contents) file.
  4. Generate the .hhp (Project) file.
  5. Call the hhc.exe compiler to create the final .chm file.

Prerequisites

  1. HTML Help Workshop: Must be installed (see Step 1).

  2. Python Libraries:

    • markdown: To convert Markdown to HTML.
    • Jinja2: For powerful and clean HTML templating.

    Install them via pip:

    pip install markdown Jinja2

The Python Script (create_chm.py)

This script is designed to be flexible. You define your documentation structure in a dictionary, and it builds everything for you.

import os
import subprocess
import markdown
from jinja2 import Environment, FileSystemLoader
# --- Configuration ---
# IMPORTANT: Set the path to your HTML Help Workshop hhc.exe
# This is often the default installation path.
HHC_COMPILER_PATH = r"C:\Program Files (x86)\HTML Help Workshop\hhc.exe"
# Define your documentation structure
# 'file' is the source markdown file is the title for the TOC and page
# 'children' is a list of child pages (for nested structure)
DOCS_STRUCTURE = {: "My Awesome Project",
    "file": "index.md",
    "children": [
        {
            "title": "Introduction",
            "file": "intro.md",
            "children": [
                {"title": "Getting Started", "file": "getting_started.md"},
                {"title": "Installation", "file": "installation.md"},
            ]
        },
        {
            "title": "Advanced Topics",
            "file": "advanced.md",
            "children": [
                {"title": "API Reference", "file": "api.md"},
                {"title": "Contributing", "file": "contributing.md"},
            ]
        }
    ]
}
# --- Script Logic ---
def render_template(template_name, **context):
    """Renders a Jinja2 template from the 'templates' directory."""
    env = Environment(loader=FileSystemLoader('templates'))
    template = env.get_template(template_name)
    return template.render(**context)
def generate_html(structure, output_dir="build", base_path=""):
    """Recursively generates HTML files from the documentation structure."""
    html_content = ""
    toc_data = []
    # Convert the current markdown file to HTML
    md_file = os.path.join(base_path, structure['file'])
    if os.path.exists(md_file):
        with open(md_file, 'r', encoding='utf-8') as f:
            md_content = f.read()
        html_content = markdown.markdown(md_content, extensions=['fenced_code', 'tables'])
    else:
        html_content = f"<h1>{structure['title']}</h1>\n<p><em>Source file {md_file} not found.</em></p>"
    # Render the full HTML page using a template
    full_html = render_template(
        "page.html",
        title=structure['title'],
        content=html_content
    )
    # Define the output HTML file path
    html_filename = os.path.splitext(structure['file'])[0] + ".html"
    output_html_path = os.path.join(output_dir, html_filename)
    # Write the HTML file
    with open(output_html_path, 'w', encoding='utf-8') as f:
        f.write(full_html)
    # Add to TOC data
    toc_entry = {
        "Name": structure['title'],
        "Local": html_filename,
        "Children": []
    }
    toc_data.append(toc_entry)
    # Recursively process children
    if 'children' in structure:
        for child in structure['children']:
            child_html, child_toc = generate_html(child, output_dir, base_path)
            toc_entry["Children"].extend(child_toc)
    return html_content, toc_data
def generate_hhc(toc_data, output_path):
    """Generates the HTML Help Contents (.hhc) file."""
    hhc_content = render_template(
        "toc.hhc",
        toc_data=toc_data
    )
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(hhc_content)
def generate_hpp(hhp_path, hhc_path, chm_filename, title):
    """Generates the HTML Help Project (.hhp) file."""
    hhp_content = render_template(
        "project.hhp",
        hhc_file=os.path.basename(hhc_path),
        chm_file=chm_filename,
        title=title
    )
    with open(hhp_path, 'w', encoding='utf-8') as f:
        f.write(hhp_content)
def compile_chm(hhp_path):
    """Compiles the .hhp file into a .chm file using hhc.exe."""
    if not os.path.exists(HHC_COMPILER_PATH):
        print(f"ERROR: hhc.exe not found at {HHC_COMPILER_PATH}")
        print("Please install HTML Help Workshop and update the HHC_COMPILER_PATH variable.")
        return False
    print(f"Compiling {hhp_path}...")
    try:
        # hhc.exe returns 0 on success, 1 on failure.
        # It prints to stdout/stderr, so we capture it.
        result = subprocess.run(
            [HHC_COMPILER_PATH, hhp_path],
            capture_output=True,
            text=True,
            check=False  # We'll check the return code manually
        )
        if result.returncode == 0:
            print("Successfully compiled CHM file!")
            return True
        else:
            print("Compilation failed.")
            print("STDOUT:", result.stdout)
            print("STDERR:", result.stderr)
            return False
    except Exception as e:
        print(f"An error occurred during compilation: {e}")
        return False
def main():
    """Main function to orchestrate the CHM creation process."""
    print("Starting CHM generation process...")
    # Define directories and file paths
    source_dir = "source"  # Where your .md files are
    build_dir = "build"    # Where temporary files will be created
    hhc_file = os.path.join(build_dir, "toc.hhc")
    hhp_file = os.path.join(build_dir, "project.hhp")
    chm_file = os.path.join(build_dir, "MyAwesomeProject.chm")
    # Create build directory if it doesn't exist
    os.makedirs(build_dir, exist_ok=True)
    # 1. Generate HTML files and Table of Contents data
    print("Generating HTML files and TOC data...")
    _, toc_data = generate_html(DOCS_STRUCTURE, build_dir, source_dir)
    # 2. Generate the .hhc file
    print(f"Generating {hhc_file}...")
    generate_hhc(toc_data, hhc_file)
    # 3. Generate the .hhp file
    print(f"Generating {hp_file}...")
    generate_hpp(hhp_file, hhc_file, os.path.basename(chm_file), DOCS_STRUCTURE['title'])
    # 4. Compile the CHM file
    if compile_chm(hhp_file):
        print(f"\nProcess complete. CHM file created at: {chm_file}")
    else:
        print("\nProcess failed. Check the errors above.")
if __name__ == "__main__":
    main()

Template Files

You need to create a templates directory in the same location as your script and place the following files inside it.

templates/page.html This is the master template for each documentation page.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">{{ title }}</title>
    <style>
        body { font-family: sans-serif; line-height: 1.6; margin: 2em; }
        h1, h2, h3 { color: #333; }
        pre { background-color: #f4f4f4; padding: 1em; border-radius: 5px; }
        code { background-color: #f4f4f4; padding: 0.2em 0.4em; border-radius: 3px; }
    </style>
</head>
<body>
    <h1>{{ title }}</h1>
    {{ content | safe }}
</body>
</html>

templates/toc.hhc This template generates the Table of Contents file.

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1">
<!-- Sitemap 1.0 -->
</HEAD><BODY>
<OBJECT type="text/site properties">
  <param name="Window Styles" value="0x800227">
  <param name="ImageType" value="Folder">
</OBJECT>
<UL>
{% for item in toc_data %}
  <LI> <OBJECT type="text/sitemap">
    <param name="Name" value="{{ item.Name }}">
    <param name="Local" value="{{ item.Local }}">
  </OBJECT>
  {% if item.Children %}
  <UL>
  {% for child in item.Children %}
    <LI> <OBJECT type="text/sitemap">
      <param name="Name" value="{{ child.Name }}">
      <param name="Local" value="{{ child.Local }}">
    </OBJECT>
    {% if child.Children %}
    <UL>
    {% for grandchild in child.Children %}
      <LI> <OBJECT type="text/sitemap">
        <param name="Name" value="{{ grandchild.Name }}">
        <param name="Local" value="{{ grandchild.Local }}">
      </OBJECT>
    {% endfor %}
    </UL>
    {% endif %}
    </LI>
  {% endfor %}
  </UL>
  {% endif %}
  </LI>
{% endfor %}
</UL>
</BODY></HTML>

templates/project.hhp This template generates the Project file.

[OPTIONS]
Compatibility=1.1
Compiled file={{ chm_file }}
Contents file={{ hhc_file }}
Default topic=index.html
Display compile progress=Yes
Full-text search=Yes{{ title }}
[FILES]
# Note: The [FILES] section needs to be populated with all generated HTML files.
# A more advanced script would list them here automatically.
# For this example, we'll assume the script adds them or you add them manually.
index.html
intro.html
getting_started.html
installation.html
advanced.html
api.html
contributing.html

How to Run Everything

  1. Project Structure: Create the following folder structure:

    my_chm_project/
    ├── create_chm.py
    ├── templates/
    │   ├── page.html
    │   ├── toc.hhc
    │   └── project.hhp
    └── source/
        ├── index.md
        ├── intro.md
        ├── getting_started.md
        ├── installation.md
        ├── advanced.md
        ├── api.md
        └── contributing.md
  2. Fill in the Markdown Files: Write your documentation in the .md files inside the source/ directory. For example, source/index.md:

    # Welcome to My Awesome Project!
    This is the main documentation for our fantastic project.
    ## Features
    *   Easy to use
    *   Powerful
    *   Well-documented (you're reading it now!)
  3. Run the Script: Open a command prompt or terminal, navigate to the my_chm_project directory, and run:

    python create_chm.py
  4. Result: The script will create a build directory containing your final MyAwesomeProject.chm file, along with the intermediate .hhc and .hhp files. You can now double-click the .chm file to view your beautifully compiled documentation

分享:
扫描分享到社交APP
上一篇
下一篇