aboutsummaryrefslogtreecommitdiff
path: root/components/news.py
diff options
context:
space:
mode:
Diffstat (limited to 'components/news.py')
-rw-r--r--components/news.py11
1 files changed, 8 insertions, 3 deletions
diff --git a/components/news.py b/components/news.py
index 522826c..cb43ea8 100644
--- a/components/news.py
+++ b/components/news.py
@@ -3,6 +3,7 @@ import streamlit as st
from datetime import datetime
from services.news_service import get_company_news, get_news_sentiment
from services.fmp_service import get_company_news as get_fmp_news
+from utils.security import escape_html, validate_outbound_url
def _sentiment_badge(sentiment: str) -> str:
@@ -69,9 +70,10 @@ def render_news(ticker: str):
for article in articles:
headline = article.get("headline") or article.get("title", "No title")
source = article.get("source") or article.get("site", "")
- url = article.get("url") or article.get("newsURL") or article.get("url", "")
+ url = validate_outbound_url(article.get("url") or article.get("newsURL"))
timestamp = article.get("datetime") or article.get("publishedDate", "")
summary = article.get("summary") or article.get("text") or ""
+ headline_html = escape_html(headline)
sentiment = _classify_sentiment(article)
badge = _sentiment_badge(sentiment)
@@ -81,9 +83,12 @@ def render_news(ticker: str):
col1, col2 = st.columns([5, 1])
with col1:
if url:
- st.markdown(f"**[{headline}]({url})**")
+ st.markdown(
+ f'<strong><a href="{escape_html(url)}" target="_blank" rel="noopener noreferrer">{headline_html}</a></strong>',
+ unsafe_allow_html=True,
+ )
else:
- st.markdown(f"**{headline}**")
+ st.markdown(f"<strong>{headline_html}</strong>", unsafe_allow_html=True)
meta = " ยท ".join(filter(None, [source, time_str]))
if meta:
st.caption(meta)