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
8 changes: 6 additions & 2 deletions lib/tickers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
PROTECTED_TAG_RE = re.compile(r"<(/?)(a|code|pre)\b", re.I)
BOLD_TAG_RE = re.compile(r"<(/?)(b|strong)\b", re.I)
URL_RE = re.compile(r'https?://[^\s<>"]+')
RAW_ANCHOR_RE = re.compile(r'<a href="(https?://[^"]+)">\s*https?://[^<]*</a>')
_CITE = r'<a href="[^"]*">\[\d+\]</a>'
CITE_ONLY_RUN_RE = re.compile(rf"\s*\n\s*({_CITE}(?:\s+{_CITE})*)[ \t]*(?=\n|$)") # lines holding only citations
RAW_ANCHOR_RE =re.compile(r'<a href="(https?://[^"]+)">\s*https?://[^<]*</a>')
# "Micron (MU)": up to four capitalised words (or a number) right before a parenthesised ticker.
_WORD = r"[A-Z0-9][\w&'’-]*(?:\.[\w&'’-]+)*"
NAME_TICKER_RE = re.compile(
Expand Down Expand Up @@ -94,7 +96,9 @@ def cite(m: re.Match) -> str:
return f'<a href="{url}">[{n}]</a>{tail}'

text = RAW_ANCHOR_RE.sub(lambda m: m.group(1), text)
return _rewrite(text, lambda seg, bold: URL_RE.sub(cite, seg))
text = _rewrite(text, lambda seg, bold: URL_RE.sub(cite, seg))
# Links the model put on their own lines join the text before them: "volume.[1][2]"
return CITE_ONLY_RUN_RE.sub(lambda m: re.sub(r"(?<=</a>)\s+", "", m.group(1)), text)


def link_tickers(text: str) -> str:
Expand Down
8 changes: 8 additions & 0 deletions tests/test_tickers.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ def test_raw_links_go_behind_citation_numbers():
assert "quote/NVDA" not in out # the ticker inside the URL is not linked


def test_citations_on_their_own_lines_join_the_preceding_text():
a, b = '<a href="https://a.com/1">[1]</a>', '<a href="https://b.com/2">[2]</a>'
assert link_tickers("Thin volume.\n\nhttps://a.com/1\nhttps://b.com/2") == f"Thin volume.{a}{b}"
assert link_tickers("One.\n\nhttps://a.com/1\n\nTwo.\nhttps://b.com/2") == f"One.{a}\n\nTwo.{b}"
assert link_tickers("Said https://a.com/1 then more") == f"Said {a} then more" # inline: untouched
assert link_tickers("Thin.\nhttps://a.com/1 and more") == f"Thin.\n{a} and more" # not a citation-only line


def test_link_labelled_with_its_own_url_is_numbered_but_named_links_and_code_are_not():
assert link_tickers('<a href="https://y.com/p">https://y.com/p…</a> ok') == '<a href="https://y.com/p">[1]</a> ok'
assert link_tickers('<a href="https://y.com/p">Reuters</a>') == '<a href="https://y.com/p">Reuters</a>'
Expand Down
Loading