This commit is contained in:
pika 2025-03-31 10:08:58 +02:00
parent 7ce4914ea1
commit 94ededdf69
9 changed files with 2894 additions and 44 deletions

View file

@ -37,8 +37,12 @@ def create_app(config_name="development"):
# Register template filters
from app.core.template_filters import bp as filters_bp
from app.core.template_filters import markdown_filter
app.register_blueprint(filters_bp)
# Register the markdown filter directly
app.jinja_env.filters['markdown'] = markdown_filter
# Create database tables without seeding any data
with app.app_context():

View file

@ -7,35 +7,75 @@ bp = Blueprint("filters", __name__)
def github_style_admonition(text):
"""Transform GitHub-style alerts (> [!NOTE], etc.) to custom HTML"""
patterns = {
r"> \[!NOTE\](.*?)(?:\n\n|\Z)": '<div class="markdown-alert markdown-alert-note"><p class="markdown-alert-title">Note</p>\\1</div>',
r"> \[!TIP\](.*?)(?:\n\n|\Z)": '<div class="markdown-alert markdown-alert-tip"><p class="markdown-alert-title">Tip</p>\\1</div>',
r"> \[!IMPORTANT\](.*?)(?:\n\n|\Z)": '<div class="markdown-alert markdown-alert-important"><p class="markdown-alert-title">Important</p>\\1</div>',
r"> \[!WARNING\](.*?)(?:\n\n|\Z)": '<div class="markdown-alert markdown-alert-warning"><p class="markdown-alert-title">Warning</p>\\1</div>',
r"> \[!CAUTION\](.*?)(?:\n\n|\Z)": '<div class="markdown-alert markdown-alert-caution"><p class="markdown-alert-title">Caution</p>\\1</div>',
}
for pattern, replacement in patterns.items():
text = re.sub(pattern, replacement, text, flags=re.DOTALL)
return text
"""Transform GitHub-style alerts (> [!NOTE], etc.) to custom HTML with GitHub styling"""
# Process the text line by line for better control
lines = text.split('\n')
result_lines = []
i = 0
while i < len(lines):
line = lines[i]
# Check if this line starts a GitHub-style alert
alert_match = re.match(r'>\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*(.*)', line)
if alert_match:
# Found an alert start
alert_type = alert_match.group(1).lower()
first_line_content = alert_match.group(2).strip()
# Collect all continuation lines (those starting with >)
alert_content = [first_line_content] if first_line_content else []
j = i + 1
while j < len(lines) and lines[j].strip().startswith('>'):
# Remove the > and one optional space after it
content = re.sub(r'^>\s?', '', lines[j].strip())
alert_content.append(content)
j += 1
# Create the HTML for the alert with proper styling
alert_html = f'<div class="markdown-alert markdown-alert-{alert_type}">\n'
alert_html += f'<p class="markdown-alert-title">{alert_type.capitalize()}</p>\n'
# Join the content with line breaks
if alert_content:
alert_html += '\n'.join(alert_content)
alert_html += '\n</div>'
# Add the processed alert HTML
result_lines.append(alert_html)
# Move past all the lines we've processed
i = j
else:
# Not an alert line, add it unchanged
result_lines.append(line)
i += 1
return '\n'.join(result_lines)
@bp.app_template_filter("markdown")
def markdown_filter(text):
"""Convert markdown text to HTML with support for GitHub-style features"""
if text:
# Pre-process GitHub-style alerts
text = github_style_admonition(text)
# Convert to HTML with regular markdown
html = md_package.markdown(
text, extensions=["tables", "fenced_code", "codehilite", "nl2br"]
)
return html
return ""
"""Convert markdown text to HTML with proper GitHub styling for all elements"""
if not text:
return ""
# First process GitHub-style alerts
processed_text = github_style_admonition(text)
# Convert to HTML with standard markdown
html = md_package.markdown(
processed_text,
extensions=["tables", "fenced_code", "codehilite", "nl2br", "sane_lists", "smarty"]
)
# Wrap in GitHub's markdown reading view class for consistent styling
html = f'<div class="markdown-reading-view">{html}</div>'
return html
@bp.app_template_filter("ip_network")

View file

@ -173,4 +173,299 @@
[data-bs-theme="light"] .documentation-wrapper {
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
/* Markdown admonition styling */
.markdown-content .admonition {
padding: 1rem;
margin: 1.5rem 0;
border-radius: 0.375rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.markdown-content .admonition-title {
font-weight: 600;
margin: -1rem -1rem 0.8rem -1rem;
padding: 0.5rem 1rem;
border-top-left-radius: 0.375rem;
border-top-right-radius: 0.375rem;
display: flex;
align-items: center;
}
.markdown-content .admonition-title::before {
margin-right: 0.5rem;
font-family: "tabler-icons";
font-weight: normal;
}
/* Note styling */
.markdown-content .admonition.note {
background-color: rgba(66, 153, 225, 0.1);
border-left: 4px solid #4299e1;
}
.markdown-content .admonition.note .admonition-title {
background-color: rgba(66, 153, 225, 0.15);
color: #2b6cb0;
}
.markdown-content .admonition.note .admonition-title::before {
content: "\ea67";
/* ti-info-circle */
}
/* Tip styling */
.markdown-content .admonition.tip {
background-color: rgba(72, 187, 120, 0.1);
border-left: 4px solid #48bb78;
}
.markdown-content .admonition.tip .admonition-title {
background-color: rgba(72, 187, 120, 0.15);
color: #2f855a;
}
.markdown-content .admonition.tip .admonition-title::before {
content: "\ea4a";
/* ti-bulb */
}
/* Important styling */
.markdown-content .admonition.important {
background-color: rgba(118, 106, 240, 0.1);
border-left: 4px solid #766af0;
}
.markdown-content .admonition.important .admonition-title {
background-color: rgba(118, 106, 240, 0.15);
color: #5046e4;
}
.markdown-content .admonition.important .admonition-title::before {
content: "\eaca";
/* ti-star */
}
/* Warning styling */
.markdown-content .admonition.warning {
background-color: rgba(246, 173, 85, 0.1);
border-left: 4px solid #f6ad55;
}
.markdown-content .admonition.warning .admonition-title {
background-color: rgba(246, 173, 85, 0.15);
color: #c05621;
}
.markdown-content .admonition.warning .admonition-title::before {
content: "\eb4f";
/* ti-alert-triangle */
}
/* Danger/Caution styling */
.markdown-content .admonition.danger {
background-color: rgba(245, 101, 101, 0.1);
border-left: 4px solid #f56565;
}
.markdown-content .admonition.danger .admonition-title {
background-color: rgba(245, 101, 101, 0.15);
color: #c53030;
}
.markdown-content .admonition.danger .admonition-title::before {
content: "\eb50";
/* ti-alert-octagon */
}
/* Dark mode adjustments */
[data-bs-theme="dark"] .markdown-content .admonition.note {
background-color: rgba(56, 127, 187, 0.15);
}
[data-bs-theme="dark"] .markdown-content .admonition.tip {
background-color: rgba(56, 161, 105, 0.15);
}
[data-bs-theme="dark"] .markdown-content .admonition.important {
background-color: rgba(102, 92, 209, 0.15);
}
[data-bs-theme="dark"] .markdown-content .admonition.warning {
background-color: rgba(221, 155, 76, 0.15);
}
[data-bs-theme="dark"] .markdown-content .admonition.danger {
background-color: rgba(224, 92, 92, 0.15);
}
/* Make sure the markdown content text color is visible */
.markdown-content {
color: var(--tblr-body-color);
}
[data-bs-theme="dark"] .markdown-content {
color: #e1e3e6;
}
/* Fix the app name in the expanded accordion */
.app-card-header .app-link {
font-weight: 600;
text-decoration: none;
}
/* GitHub-style markdown alerts */
.markdown-alert {
padding: 0.85rem 1rem;
margin: 1rem 0;
border-radius: 0.375rem;
border-left-width: 4px;
border-left-style: solid;
color: inherit;
}
.markdown-alert-title {
font-weight: 600;
margin-top: 0;
margin-bottom: 0.5rem;
font-size: 1rem;
display: flex;
align-items: center;
}
.markdown-alert-title::before {
margin-right: 0.5rem;
font-family: "tabler-icons";
font-weight: normal;
}
/* Individual alert types */
/* Note styling */
.markdown-alert-note {
background-color: rgba(66, 153, 225, 0.1);
border-left-color: #4299e1;
}
.markdown-alert-note .markdown-alert-title {
color: #2b6cb0;
}
.markdown-alert-note .markdown-alert-title::before {
content: "\ea67";
/* ti-info-circle */
}
/* Tip styling */
.markdown-alert-tip {
background-color: rgba(72, 187, 120, 0.1);
border-left-color: #48bb78;
}
.markdown-alert-tip .markdown-alert-title {
color: #2f855a;
}
.markdown-alert-tip .markdown-alert-title::before {
content: "\ea4a";
/* ti-bulb */
}
/* Important styling */
.markdown-alert-important {
background-color: rgba(118, 106, 240, 0.1);
border-left-color: #766af0;
}
.markdown-alert-important .markdown-alert-title {
color: #5046e4;
}
.markdown-alert-important .markdown-alert-title::before {
content: "\eaca";
/* ti-star */
}
/* Warning styling */
.markdown-alert-warning {
background-color: rgba(246, 173, 85, 0.1);
border-left-color: #f6ad55;
}
.markdown-alert-warning .markdown-alert-title {
color: #c05621;
}
.markdown-alert-warning .markdown-alert-title::before {
content: "\eb4f";
/* ti-alert-triangle */
}
/* Caution styling */
.markdown-alert-caution {
background-color: rgba(245, 101, 101, 0.1);
border-left-color: #f56565;
}
.markdown-alert-caution .markdown-alert-title {
color: #c53030;
}
.markdown-alert-caution .markdown-alert-title::before {
content: "\eb50";
/* ti-alert-octagon */
}
/* Dark mode adjustments */
[data-bs-theme="dark"] .markdown-alert-note {
background-color: rgba(56, 127, 187, 0.15);
}
[data-bs-theme="dark"] .markdown-alert-tip {
background-color: rgba(56, 161, 105, 0.15);
}
[data-bs-theme="dark"] .markdown-alert-important {
background-color: rgba(102, 92, 209, 0.15);
}
[data-bs-theme="dark"] .markdown-alert-warning {
background-color: rgba(221, 155, 76, 0.15);
}
[data-bs-theme="dark"] .markdown-alert-caution {
background-color: rgba(224, 92, 92, 0.15);
}
/* Fix content inside alerts */
.markdown-alert p {
margin-bottom: 0.5rem;
}
.markdown-alert p:last-child {
margin-bottom: 0;
}
/* Ensure proper spacing for code in alerts */
.markdown-alert code {
background-color: rgba(0, 0, 0, 0.07);
border-radius: 3px;
padding: 0.2em 0.4em;
font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
}
[data-bs-theme="dark"] .markdown-alert code {
background-color: rgba(255, 255, 255, 0.1);
}
/* Fix port display in accordion headers */
.accordion-button .badge {
font-size: 0.7rem;
padding: 0.25em 0.5em;
margin-right: 0.25rem;
}
/* Add compatibility classes for GitHub markdown */
.markdown-content .markdown-reading-view {
width: 100%;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,14 +0,0 @@
/* GitHub Markdown CSS (simplified version) */
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 1000px;
margin: 0 auto;
padding: 45px;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}

View file

@ -145,8 +145,15 @@
placeholder="Enter documentation in Markdown format">{{ app.documentation if app else '' }}</textarea>
<small class="form-hint">
Use <a href="https://www.markdownguide.org/basic-syntax/" target="_blank">Markdown syntax</a>
to format your documentation. The content will be rendered when viewing the application.
to format your documentation. You can use GitHub-style alerts:
</small>
<div class="mt-2 d-flex gap-2 flex-wrap">
<code>> [!NOTE] This is a note</code>
<code>> [!TIP] This is a tip</code>
<code>> [!IMPORTANT] Important info</code>
<code>> [!WARNING] Warning message</code>
<code>> [!CAUTION] Critical caution</code>
</div>
</div>
<div class="form-footer">

View file

@ -138,7 +138,8 @@
aria-controls="app-collapse-{{ app.id }}">
<span class="me-2">{{ app.name }}</span>
{% for port in app.ports %}
<span class="badge bg-primary mx-1">{{ port.number }}/{{ port.protocol }}</span>
<span class="badge bg-primary">{% if port.port_number %}{{ port.port_number }}{% elif port.number %}{{
port.number }}{% endif %}/{{ port.protocol }}</span>
{% endfor %}
</button>
</h2>
@ -171,7 +172,7 @@
<!-- Documentation section with improved styling -->
<div class="documentation-wrapper p-3">
<div class="markdown-content theme-styled">
<div class="markdown-content">
{% if app.documentation %}
{{ app.documentation|markdown|safe }}
{% else %}

View file

@ -20,7 +20,8 @@
<link rel="stylesheet" href="{{ url_for('static', filename='libs/tabler-icons/tabler-icons.min.css') }}"
onerror="this.onerror=null;this.href='https://cdn.jsdelivr.net/npm/@tabler/icons@latest/iconfont/tabler-icons.min.css';">
<link rel="stylesheet" href="{{ url_for('static', filename='css/custom.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/markdown.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/github-markdown-reading-view.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/github-markdown-source-view.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/theme.css') }}">
<!-- Favicon -->
<link rel="icon" type="image/png" href="{{ url_for('static', filename='img/favicon.png') }}">
@ -604,4 +605,4 @@
{% block scripts %}{% endblock %}
</body>
</html>
</html>