add-feedback-improvements #5

Open
admin wants to merge 10 commits from add-feedback-improvements into main
2 changed files with 35 additions and 79 deletions
Showing only changes of commit fc2f024d60 - Show all commits

View File

@@ -149,11 +149,6 @@ def process_version(
logger.error(f"No man pages were successfully processed for version {version}") logger.error(f"No man pages were successfully processed for version {version}")
return False 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 # Generate web pages
logger.info("Generating web pages...") logger.info("Generating web pages...")
web_gen = WebGenerator(template_dir, config.output_dir) web_gen = WebGenerator(template_dir, config.output_dir)

View File

@@ -73,6 +73,20 @@ class ManPageConverter:
# Clean up HTML # Clean up HTML
html = self._clean_html(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 # Store in ManFile object
man_file.html_content = html man_file.html_content = html
@@ -187,87 +201,34 @@ class ManPageConverter:
return html return html
def link_cross_references(self, man_files: List[ManFile]) -> None: def _generate_redirect_html(self, target_info: dict) -> str:
"""Add hyperlinks to cross-references in SEE ALSO sections. """Generate HTML for a symlink/redirect page.
Goes through all converted HTML files and converts man page references
like pty(4) into working hyperlinks.
Args: 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 name = target_info['name']
lookup = {} section = target_info['section']
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}"
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 # Generate simple redirect HTML with a working hyperlink
for man_file in man_files: 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);">
if not man_file.html_path or not man_file.html_path.exists(): <p style="font-size: 1.2rem; margin-bottom: 1.5rem; color: var(--text-primary);">
continue 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: return html
# Read the HTML
with open(man_file.html_path, 'r', encoding='utf-8') as f:
html = f.read()
# 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: def _get_output_path(self, man_file: ManFile) -> Path:
"""Determine output path for HTML file. """Determine output path for HTML file.