Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions scripts/portal_generator/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from .discovery import discover_apis, calculate_stats
from .builders.tree_builder import build_operation_tree
from .assets import get_css, get_js, get_jsonpath_js
from .template_env import create_env
from .template_env import create_env, _skill_title
from .mulesoft_chrome import fetch_mulesoft_chrome


Expand Down Expand Up @@ -313,7 +313,7 @@ def _generate_skill_pages(self):
template = self.env.get_template('skill_page.html')

for skill in self.all_skills:
skill_name = skill.get('name', skill['slug']).replace('-', ' ').title()
skill_name = _skill_title(skill.get('name', skill['slug']))
api_refs = skill.get('api_refs', [])

# Build op_lookup scoped to APIs this skill references
Expand Down
21 changes: 21 additions & 0 deletions scripts/portal_generator/template_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,26 @@ def _resolve_skill_inputs(inputs_dict, step_details):
return result


_UPPERCASE_WORDS = {'api', 'apis', 'mcp', 'ip', 'id', 'url', 'http', 'https', 'sdk', 'cli', 'jtbd'}


def _skill_title(value):
"""Convert a slug like 'apply-policy-to-api-instance' to 'Apply Policy to API Instance'.

Preserves known acronyms in uppercase and keeps short words lowercase."""
if not value:
return ''
words = str(value).replace('-', ' ').split()
result = []
for word in words:
lower = word.lower()
if lower in _UPPERCASE_WORDS:
result.append(lower.upper())
else:
result.append(word.capitalize())
return ' '.join(result)


def _truncate_text(text, max_length=25):
"""Truncate text to max_length characters, adding ellipsis if truncated."""
if not text or len(text) <= max_length:
Expand Down Expand Up @@ -239,6 +259,7 @@ def create_env() -> Environment:
env.filters['titleize_operation'] = _titleize_operation
env.filters['slugify'] = _slugify
env.filters['resolve_skill_inputs'] = _resolve_skill_inputs
env.filters['skill_title'] = _skill_title
env.filters['truncate_text'] = _truncate_text
env.filters['should_collapse_description'] = _should_collapse_description

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% set skill_name = skill.name|replace('-', ' ')|title %}
{% set skill_name = skill.name|skill_title %}
<a href="skills/{{ skill.slug }}.html" class="catalog-card-link" data-name="{{ skill_name|lower }}" data-type="skill">
<article class="catalog-card">
<div class="catalog-card-header">
Expand Down
2 changes: 1 addition & 1 deletion scripts/portal_generator/templates/partials/sidebar.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
{% if api.skills %}
<div id="skills-panel" class="sidebar-panel" role="tabpanel" aria-labelledby="skills-tab" style="display: none;">
{% for skill in api.skills %}
{% set skill_name = skill.name|replace('-', ' ')|title %}
{% set skill_name = skill.name|skill_title %}
{% set step_count = skill.step_details|length %}
<li>
<a href="../skills/{{ skill.slug }}.html" class="nav-link nav-operation-flat">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% set skill_name = skill.name|replace('-', ' ')|title %}
{% set skill_name = skill.name|skill_title %}
{% set slug = skill.slug %}
{% set step_details = skill.step_details|default([]) %}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% from "skills/step_unified.html" import render_step_unified %}

{% macro render_skill(skill, private_api_slugs=[], api_link_prefix='', op_lookup={}) %}
{% set skill_name = skill.name|replace('-', ' ')|title %}
{% set skill_name = skill.name|skill_title %}
{% set slug = skill.slug %}
{% set step_details = skill.step_details|default([]) %}

Expand Down
29 changes: 28 additions & 1 deletion scripts/tests/test_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from portal_generator.utils import get_category, CATEGORY_MAPPING
from portal_generator.builders.tree_builder import build_operation_tree, count_tree_operations
from portal_generator.template_env import _nl2br, _nl2br_html, _render_markdown, _tojson_raw
from portal_generator.template_env import _nl2br, _nl2br_html, _render_markdown, _tojson_raw, _skill_title
from portal_generator.generator import _build_api_meta, _get_example_body, PortalGenerator
from portal_generator.parsers.skill_parser import (
_extract_yaml_blocks,
Expand Down Expand Up @@ -227,6 +227,33 @@ def test_custom_indent(self):
assert ' "a"' in str(result)


# ============================================================================
# _skill_title
# ============================================================================

class TestSkillTitle:
def test_api_uppercase(self):
assert _skill_title('apply-policy-to-api-instance') == 'Apply Policy To API Instance'

def test_mcp_uppercase(self):
assert _skill_title('protect-mcp-server-with-policies') == 'Protect MCP Server With Policies'

def test_multiple_acronyms(self):
assert _skill_title('setup-api-with-oauth') == 'Setup API With Oauth'

def test_no_acronyms(self):
assert _skill_title('run-agent-scan-and-view-results') == 'Run Agent Scan And View Results'

def test_empty_string(self):
assert _skill_title('') == ''

def test_single_word(self):
assert _skill_title('api') == 'API'

def test_already_spaced(self):
assert _skill_title('protect api with policies') == 'Protect API With Policies'


# ============================================================================
# generator helpers
# ============================================================================
Expand Down
Loading