Spaces:
Runtime error
Runtime error
| 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 = ' ' * leading_spaces | |
| # Use the corresponding line of highlighted HTML for the content | |
| line_content = highlighted_lines[i].lstrip() if raw_line.lstrip() else " " | |
| 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. | |
| } |