add-feedback-improvements #5
@@ -149,11 +149,6 @@ def process_version(
|
||||
logger.error(f"No man pages were successfully processed for version {version}")
|
||||
return False
|
||||
|
||||
# Link cross-references between man pages
|
||||
logger.info("Linking cross-references...")
|
||||
converter = ManPageConverter(version_output_dir)
|
||||
converter.link_cross_references(all_man_files)
|
||||
|
||||
# Generate web pages
|
||||
logger.info("Generating web pages...")
|
||||
web_gen = WebGenerator(template_dir, config.output_dir)
|
||||
|
||||
@@ -73,6 +73,20 @@ class ManPageConverter:
|
||||
# Clean up HTML
|
||||
html = self._clean_html(html)
|
||||
|
||||
# Check if mandoc output indicates this is a symlink/redirect
|
||||
# Pattern: <div class="manual-text">/usr/share/man/man8/target.8.gz</div>
|
||||
# or: <div class="manual-text">See the file /usr/share/man/man8/target.8.</div>
|
||||
symlink_match = re.search(r'<div class="manual-text">(?:See the file )?(/usr/share/man/man\d+[a-z]*/([^/]+)\.(\d+[a-z]*)(?:\.gz)?)\.</div>', html)
|
||||
if not symlink_match:
|
||||
# Try simpler pattern without "See the file" or period
|
||||
symlink_match = re.search(r'<div class="manual-text">(/usr/share/man/man\d+[a-z]*/([^/<]+)\.(\d+[a-z]*)(?:\.gz)?)</div>', html)
|
||||
|
||||
if symlink_match:
|
||||
name = symlink_match.group(2)
|
||||
section = symlink_match.group(3)
|
||||
logger.info(f"{man_file.display_name} detected as symlink to {name}({section})")
|
||||
html = self._generate_redirect_html({'name': name, 'section': section})
|
||||
|
||||
# Store in ManFile object
|
||||
man_file.html_content = html
|
||||
|
||||
@@ -187,87 +201,34 @@ class ManPageConverter:
|
||||
|
||||
return html
|
||||
|
||||
def link_cross_references(self, man_files: List[ManFile]) -> None:
|
||||
"""Add hyperlinks to cross-references in SEE ALSO sections.
|
||||
|
||||
Goes through all converted HTML files and converts man page references
|
||||
like pty(4) into working hyperlinks.
|
||||
def _generate_redirect_html(self, target_info: dict) -> str:
|
||||
"""Generate HTML for a symlink/redirect page.
|
||||
|
||||
Args:
|
||||
man_files: List of all converted ManFile objects
|
||||
target_info: Dict with 'name' and 'section' of target man page
|
||||
|
||||
Returns:
|
||||
HTML fragment for redirect page
|
||||
"""
|
||||
# Build lookup index: (name, section) -> relative_path
|
||||
lookup = {}
|
||||
for mf in man_files:
|
||||
key = (mf.name.lower(), str(mf.section))
|
||||
if key not in lookup:
|
||||
# Store the relative path from the version root
|
||||
lookup[key] = f"{mf.package_name}/man{mf.section}/{mf.html_filename}"
|
||||
name = target_info['name']
|
||||
section = target_info['section']
|
||||
|
||||
logger.info(f"Linking cross-references across {len(man_files)} man pages...")
|
||||
# Generate the relative path to the target man page
|
||||
# Symlinks are in the same package, just different file names
|
||||
target_filename = f"{name}.{section}.html"
|
||||
|
||||
# Process each man page HTML file
|
||||
for man_file in man_files:
|
||||
if not man_file.html_path or not man_file.html_path.exists():
|
||||
continue
|
||||
# Generate simple redirect HTML with a working hyperlink
|
||||
html = f'''<div class="symlink-notice" style="padding: 2rem; text-align: center; background-color: var(--bg-tertiary); border-radius: 8px; border: 1px solid var(--border-color);">
|
||||
<p style="font-size: 1.2rem; margin-bottom: 1.5rem; color: var(--text-primary);">
|
||||
This is an alias for <b>{name}</b>({section}).
|
||||
</p>
|
||||
<p style="font-size: 1.1rem;">
|
||||
<a href="{target_filename}" style="color: var(--accent-primary); text-decoration: none; font-weight: 500;">View the manual page</a>
|
||||
</p>
|
||||
</div>'''
|
||||
|
||||
try:
|
||||
# Read the HTML
|
||||
with open(man_file.html_path, 'r', encoding='utf-8') as f:
|
||||
html = f.read()
|
||||
return html
|
||||
|
||||
# Find and replace man page references
|
||||
# Mandoc outputs references as: <b>name</b>(section)
|
||||
# Pattern matches both <b>name</b>(section) and plain name(section)
|
||||
pattern = r'<b>([\w\-_.]+)</b>\((\d+[a-z]*)\)|\b([\w\-_.]+)\((\d+[a-z]*)\)'
|
||||
|
||||
def replace_reference(match):
|
||||
full_match = match.group(0)
|
||||
|
||||
# Check if this match is already inside an <a> tag
|
||||
# Look back up to 500 chars for context
|
||||
before_text = html[max(0, match.start()-500):match.start()]
|
||||
|
||||
# Find the last <a and last </a> before this match
|
||||
last_open = before_text.rfind('<a ')
|
||||
last_close = before_text.rfind('</a>')
|
||||
|
||||
# If the last <a> is after the last </a>, we're inside a link
|
||||
if last_open > last_close:
|
||||
return full_match
|
||||
|
||||
if match.group(1): # <b>name</b>(section) format
|
||||
name = match.group(1).lower()
|
||||
section = match.group(2)
|
||||
else: # plain name(section) format
|
||||
name = match.group(3).lower()
|
||||
section = match.group(4)
|
||||
|
||||
# Look up the referenced man page
|
||||
key = (name, section)
|
||||
if key in lookup:
|
||||
# Calculate relative path from current file to target
|
||||
target_path = lookup[key]
|
||||
# File structure: output_dir/version/package_name/manN/file.html
|
||||
# Need to go up 3 levels to reach version root
|
||||
# Current: package_name/manN/file.html
|
||||
# Target: other_package/manM/file.html
|
||||
rel_path = f"../../../{target_path}"
|
||||
return f'<a href="{rel_path}">{full_match}</a>'
|
||||
|
||||
return full_match
|
||||
|
||||
updated_html = re.sub(pattern, replace_reference, html)
|
||||
|
||||
# Only write if something changed
|
||||
if updated_html != html:
|
||||
with open(man_file.html_path, 'w', encoding='utf-8') as f:
|
||||
f.write(updated_html)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Error linking references in {man_file.display_name}: {e}")
|
||||
|
||||
logger.info("Cross-reference linking complete")
|
||||
|
||||
def _get_output_path(self, man_file: ManFile) -> Path:
|
||||
"""Determine output path for HTML file.
|
||||
|
||||
Reference in New Issue
Block a user