scn-consultation-api / src /tools /template_utils.py
SS-2005's picture
Initial HF Space deployment
59ec65a
Raw
History Blame Contribute Delete
5.37 kB
from jinja2 import Template
from pygments import highlight
from pygments.lexers import get_lexer_by_name, guess_lexer
from pygments.formatters import HtmlFormatter
from pygments.util import ClassNotFound
import os
import html as html_module
from markupsafe import Markup
def get_pygments_css():
"""Get CSS for syntax highlighting - a more complete and styled version."""
return """
.c { color: #9ca3af; font-style: italic; } /* Comment */
.c1 { color: #9ca3af; font-style: italic; } /* Comment.Single */
.cm { color: #9ca3af; font-style: italic; } /* Comment.Multiline */
.cp { color: #9ca3af; font-style: italic; } /* Comment.Preproc */
.cs { color: #9ca3af; font-style: italic; } /* Comment.Special */
.k { color: #db2777; font-weight: 500; } /* Keyword */
.kc { color: #db2777; font-weight: 500; } /* Keyword.Constant */
.kd { color: #db2777; font-weight: 500; } /* Keyword.Declaration */
.kn { color: #db2777; font-weight: 500; } /* Keyword.Namespace */
.kp { color: #db2777; font-weight: 500; } /* Keyword.Pseudo */
.kr { color: #db2777; font-weight: 500; } /* Keyword.Reserved */
.kt { color: #9333ea; font-weight: 500; } /* Keyword.Type */
.n { color: #1f2937; } /* Name */
.na { color: #4f46e5; } /* Name.Attribute */
.nb { color: #059669; } /* Name.Builtin */
.nc { color: #4f46e5; font-weight: 500; } /* Name.Class */
.nf { color: #4f46e5; font-weight: 500; } /* Name.Function */
.nx { color: #1f2937; } /* Name.Other */
.s { color: #059669; } /* String */
.s1 { color: #059669; } /* String.Single */
.s2 { color: #059669; } /* String.Double */
.p { color: #6b7280; } /* Punctuation */
.m { color: #059669; } /* Number */
.mi { color: #059669; } /* Number.Integer */
.o { color: #db2777; } /* Operator */
.ow { color: #db2777; font-weight: 500; } /* Operator.Word */
.w { color: #d1d5db; } /* Text.Whitespace */
"""
from markupsafe import Markup # pip install markupsafe
def format_code_with_pygments(code_text, language='python'):
"""
Highlights a code snippet using Pygments and wraps each line to preserve
indentation and allow for individual line styling.
"""
try:
lexer = get_lexer_by_name(language, stripall=True)
except ClassNotFound:
lexer = get_lexer_by_name('text') # Fallback to plain text
formatter = HtmlFormatter(nowrap=True)
highlighted_html = highlight(code_text, lexer, formatter)
# Split the original raw code to calculate indentation correctly
raw_lines = code_text.rstrip().split('\n')
# Split the generated HTML, which should correspond to the raw lines
highlighted_lines = highlighted_html.rstrip().split('\n')
# As a safeguard, if the line counts don't match, fall back to a simpler method.
if len(raw_lines) != len(highlighted_lines):
wrapped_html = [f'<span class="code-line">{line}</span>' for line in highlighted_lines]
return Markup('\n'.join(wrapped_html))
wrapped_lines = []
for i, raw_line in enumerate(raw_lines):
# Calculate leading whitespace from the original raw line
leading_spaces = len(raw_line) - len(raw_line.lstrip(' '))
# Create non-breaking spaces for indentation
indentation = '&nbsp;' * leading_spaces
# Use the corresponding line of highlighted HTML for the content
line_content = highlighted_lines[i].lstrip() if raw_line.lstrip() else "&nbsp;"
wrapped_lines.append(f'<span class="code-line">{indentation}{line_content}</span>')
return Markup('\n'.join(wrapped_lines))
def render_template(template_path, data):
"""Render Jinja2 template with data."""
with open(template_path, 'r', encoding='utf-8') as f:
template = Template(f.read())
return template.render(**data)
def extract_code_blocks(content):
"""Extract code blocks from markdown-style content."""
import re
code_blocks = []
pattern = r'```(\w+)?\n(.*?)```'
matches = re.findall(pattern, content, re.DOTALL)
for lang, code in matches:
code_blocks.append({
'language': lang if lang else 'python',
'code': code.strip()
})
return code_blocks
def format_bullet_points(content):
"""
Formats bullet points from content, converting simple markdown (bold, inline code) to HTML.
Code snippets are expected to be handled before this function is called.
"""
import re
lines = content.strip().split('\n')
bullets = []
for line in lines:
stripped_line = line.strip()
if stripped_line.startswith(('-', '*', '•')):
bullet_text = re.sub(r'^[\-\*•]\s*', '', stripped_line)
# Bold markdown: **text** -> <strong>text</strong>
bullet_text = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', bullet_text)
# Inline code markdown: `code` -> <code class="inline-code-span">code</code>
bullet_text = re.sub(r'`([^`]+)`', r'<code class="inline-code-span">\1</code>', bullet_text)
bullets.append(bullet_text)
elif stripped_line: # Append non-empty, non-bullet lines as well
bullets.append(stripped_line)
return {
'bullets': bullets,
'code_snippet': None # This function no longer extracts code.
}