from awesomeversion import AwesomeVersion
import json
from pyscript import document
import html
def escape_html(text):
"""Escape HTML special characters to prevent XSS attacks."""
return html.escape(str(text), quote=True)
def safe_compare(a, b, operation):
try:
if operation == ">":
return a > b
elif operation == "<":
return a < b
elif operation == "==":
return a == b
elif operation == ">=":
return a >= b
elif operation == "<=":
return a <= b
else:
return None
except Exception as e:
return f"Error: {str(e)}"
def get_version_info(version_str):
try:
if not version_str or version_str.strip() == "":
return {"error": "Empty version string", "valid": False}
version = AwesomeVersion(version_str.strip())
return {
"string": version.string,
"valid": version.valid,
"alpha": version.alpha,
"beta": version.beta,
"dev": version.dev,
"major": version.major,
"micro": version.micro,
"minor": version.minor,
"modifier_type": version.modifier_type,
"modifier": version.modifier,
"patch": version.patch,
"prefix": version.prefix,
"release_candidate": version.release_candidate,
"sections": version.sections,
"simple": version.simple,
"strategy": version.strategy.value if hasattr(version.strategy, 'value') else str(version.strategy),
"year": version.year,
}
except Exception as e:
return {"error": str(e), "valid": False}
def format_version_info(info):
if "error" in info:
return f"❌ Error: {info['error']}"
output = f"✅ Valid: {info['valid']}\n"
output += f"📦 Strategy: {info['strategy']}\n"
output += f"🔢 Version: {info['string']}\n\n"
if info['valid']:
output += "📋 Properties:\n"
output += f" • Major: {info['major']}\n"
output += f" • Minor: {info['minor']}\n"
output += f" • Patch: {info['patch']}\n"
if info['modifier']:
output += f" • Modifier: {info['modifier']} ({info['modifier_type']})\n"
if info['prefix']:
output += f" • Prefix: {info['prefix']}\n"
output += f" • Sections: {info['sections']}\n"
output += f" • Simple: {info['simple']}\n"
# Special version types
if info['alpha']:
output += f" • Alpha: {info['alpha']}\n"
if info['beta']:
output += f" • Beta: {info['beta']}\n"
if info['dev']:
output += f" • Dev: {info['dev']}\n"
if info['release_candidate']:
output += f" • RC: {info['release_candidate']}\n"
if info['year']:
output += f" • Year: {info['year']}\n"
return output
def compare_versions(*args, **kwargs):
try:
version_a_str = document.querySelector("#version-input-a").value.strip()
version_b_str = document.querySelector("#version-input-b").value.strip()
if not version_a_str or not version_b_str:
document.querySelector("#comparison-result").innerHTML = ""
document.querySelector("#properties-output-a").innerText = ""
document.querySelector("#properties-output-b").innerText = ""
document.querySelector("#comparison-details").innerText = ""
document.querySelector("#raw-json-a").innerText = ""
document.querySelector("#raw-json-b").innerText = ""
return
# Get version info
info_a = get_version_info(version_a_str)
info_b = get_version_info(version_b_str)
# Display properties
document.querySelector("#properties-output-a").innerText = format_version_info(info_a)
document.querySelector("#properties-output-b").innerText = format_version_info(info_b)
# Display raw JSON for each version
if "error" not in info_a:
json_output_a = json.dumps(info_a, indent=2, sort_keys=True)
else:
json_output_a = json.dumps(info_a, indent=2)
document.querySelector("#raw-json-a").innerText = json_output_a
if "error" not in info_b:
json_output_b = json.dumps(info_b, indent=2, sort_keys=True)
else:
json_output_b = json.dumps(info_b, indent=2)
document.querySelector("#raw-json-b").innerText = json_output_b
# Compare versions if both are valid
if info_a.get('valid') and info_b.get('valid'):
try:
version_a = AwesomeVersion(version_a_str)
version_b = AwesomeVersion(version_b_str)
comparison_html = ''
comparison_html += f'{escape_html(version_a_str)} > {escape_html(version_b_str)}'
elif version_a < version_b:
comparison_html += 'lesser">'
comparison_html += f'{escape_html(version_a_str)} < {escape_html(version_b_str)}'
else:
comparison_html += 'equal">'
comparison_html += f'{escape_html(version_a_str)} = {escape_html(version_b_str)}'
comparison_html += '
'
document.querySelector("#comparison-result").innerHTML = comparison_html
# Additional comparison details
details = f"🔍 Detailed Comparison:\n"
details += f" • {version_a_str} > {version_b_str}: {safe_compare(version_a, version_b, '>')}\n"
details += f" • {version_a_str} < {version_b_str}: {safe_compare(version_a, version_b, '<')}\n"
details += f" • {version_a_str} == {version_b_str}: {safe_compare(version_a, version_b, '==')}\n"
details += f" • {version_a_str} >= {version_b_str}: {safe_compare(version_a, version_b, '>=')}\n"
details += f" • {version_a_str} <= {version_b_str}: {safe_compare(version_a, version_b, '<=')}\n\n"
details += "🔄 Differences:\n"
details += f" • Major: {info_a['major']} vs {info_b['major']} ({'✓' if info_a['major'] == info_b['major'] else '✗'})\n"
details += f" • Minor: {info_a['minor']} vs {info_b['minor']} ({'✓' if info_a['minor'] == info_b['minor'] else '✗'})\n"
details += f" • Patch: {info_a['patch']} vs {info_b['patch']} ({'✓' if info_a['patch'] == info_b['patch'] else '✗'})\n"
details += f" • Strategy: {info_a['strategy']} vs {info_b['strategy']} ({'✓' if info_a['strategy'] == info_b['strategy'] else '✗'})\n"
document.querySelector("#comparison-details").innerText = details
except Exception as e:
document.querySelector("#comparison-result").innerHTML = f'❌ Comparison Error: {escape_html(str(e))}
'
document.querySelector("#comparison-details").innerText = ""
else:
document.querySelector("#comparison-result").innerHTML = '❌ Cannot compare invalid versions
'
document.querySelector("#comparison-details").innerText = ""
except Exception as e:
document.querySelector("#comparison-result").innerHTML = f'❌ Script Error: {escape_html(str(e))}
'
document.querySelector("#comparison-details").innerText = ""
def load_example(version_a, version_b):
try:
document.querySelector("#version-input-a").value = version_a
document.querySelector("#version-input-b").value = version_b
compare_versions()
except Exception as e:
print(f"Error loading example: {e}")
def analyze_single_version(*args, **kwargs):
try:
version_str = document.querySelector("#single-version-input").value.strip()
if not version_str:
document.querySelector("#single-version-output").innerText = ""
document.querySelector("#single-version-json").innerText = ""
return
info = get_version_info(version_str)
# Display formatted info
document.querySelector("#single-version-output").innerText = format_version_info(info)
# Display raw JSON
if "error" not in info:
json_output = json.dumps(info, indent=2, sort_keys=True)
else:
json_output = json.dumps(info, indent=2)
document.querySelector("#single-version-json").innerText = json_output
except Exception as e:
document.querySelector("#single-version-output").innerText = f"❌ Error: {str(e)}"
document.querySelector("#single-version-json").innerText = f'{{"error": "{str(e)}"}}'
# Make functions available globally for onclick handlers
import js
js.load_example = load_example
js.analyze_single_version = analyze_single_version
js.compare_versions = compare_versions