From 99d464e569d2272d88b5a8576ea5944e8401d94c Mon Sep 17 00:00:00 2001 From: Marwin Hochfelsner <50826859+hlfan@users.noreply.github.com> Date: Tue, 2 Dec 2025 00:14:39 +0100 Subject: [PATCH] Pretty-print URLs in linkify --- config/settings.yml | 9 ++++ lib/rich_text.rb | 5 ++- test/lib/rich_text_test.rb | 90 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) diff --git a/config/settings.yml b/config/settings.yml index bee4027ff..8ff54049a 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -177,6 +177,15 @@ linkify: - "(?[^\"?#<>/\\s]+)=(?[^\"?#<>\\s]+)" path_template: "wiki/Tag:\\k=\\k" host: "https://wiki.openstreetmap.org" + display_rules: + - pattern: "osm\\.org/user/" + replacement: "@" + - pattern: "osm\\.org/(?node|way|relation|changeset|note)/" + replacement: "\\k/" + - pattern: "osm\\.wiki/Key:(?[^\"?#<>/\\s]+)" + replacement: "\\k=*" + - pattern: "osm\\.wiki/Tag:(?[^\"?#<>/\\s]+)(?:=|%3D)(?[^\"?#<>\\s]+)" + replacement: "\\k=\\k" # Main website hosts to match in linkify linkify_hosts: ["www.openstreetmap.org", "www.osm.org", "www.openstreetmap.com", "openstreetmap.org", "osm.org", "openstreetmap.com"] # Shorter host to replace main hosts diff --git a/lib/rich_text.rb b/lib/rich_text.rb index f7be24dd4..50b31b2b0 100644 --- a/lib/rich_text.rb +++ b/lib/rich_text.rb @@ -134,9 +134,12 @@ module RichText def format_link_text(url) url = shorten_host(url, Settings.linkify_hosts, Settings.linkify_hosts_replacement) - shorten_host(url, Settings.linkify_wiki_hosts, Settings.linkify_wiki_hosts_replacement) do |path| + url = shorten_host(url, Settings.linkify_wiki_hosts, Settings.linkify_wiki_hosts_replacement) do |path| path.sub(Regexp.new(Settings.linkify_wiki_optional_path_prefix || ""), "") end + Array.wrap(Settings.linkify&.display_rules) + .select { |rule| rule.pattern && rule.replacement } + .reduce(url) { |url, rule| url.sub(Regexp.new(rule.pattern), rule.replacement) } end def shorten_host(url, hosts, hosts_replacement) diff --git a/test/lib/rich_text_test.rb b/test/lib/rich_text_test.rb index 02ff67c9a..5ac231dbc 100644 --- a/test/lib/rich_text_test.rb +++ b/test/lib/rich_text_test.rb @@ -394,6 +394,96 @@ class RichTextTest < ActiveSupport::TestCase end end + def test_text_to_html_linkify_openstreetmap_links + with_settings(:server_url => "www.openstreetmap.org", :server_protocol => "https") do + cases = { + "https://www.openstreetmap.org/note/4655490" => + ["note/4655490", "https://www.openstreetmap.org/note/4655490"], + + "https://www.openstreetmap.org/changeset/163353772" => + ["changeset/163353772", "https://www.openstreetmap.org/changeset/163353772"], + + "https://www.openstreetmap.org/way/1249366504" => + ["way/1249366504", "https://www.openstreetmap.org/way/1249366504"], + + "https://www.openstreetmap.org/way/1249366504/history" => + ["way/1249366504/history", "https://www.openstreetmap.org/way/1249366504/history"], + + "https://www.openstreetmap.org/way/1249366504/history/2" => + ["way/1249366504/history/2", "https://www.openstreetmap.org/way/1249366504/history/2"], + + "https://www.openstreetmap.org/node/12639964186" => + ["node/12639964186", "https://www.openstreetmap.org/node/12639964186"], + + "https://www.openstreetmap.org/relation/7876483" => + ["relation/7876483", "https://www.openstreetmap.org/relation/7876483"], + + "https://www.openstreetmap.org/user/aharvey" => + ["@aharvey", "https://www.openstreetmap.org/user/aharvey"], + + "https://wiki.openstreetmap.org/wiki/Key:boundary" => + ["boundary=*", "https://wiki.openstreetmap.org/wiki/Key:boundary"], + + "https://wiki.openstreetmap.org/wiki/Tag:boundary=place" => + ["boundary=place", "https://wiki.openstreetmap.org/wiki/Tag:boundary=place"], + + "boundary=*" => + ["boundary=*", "https://wiki.openstreetmap.org/wiki/Key:boundary"], + + "boundary=place" => + ["boundary=place", "https://wiki.openstreetmap.org/wiki/Tag:boundary=place"], + + "node/12639964186" => + ["node/12639964186", "https://www.openstreetmap.org/node/12639964186"], + + "node 12639964186" => + ["node/12639964186", "https://www.openstreetmap.org/node/12639964186"], + + "n12639964186" => + ["node/12639964186", "https://www.openstreetmap.org/node/12639964186"], + + "way/1249366504" => + ["way/1249366504", "https://www.openstreetmap.org/way/1249366504"], + + "way 1249366504" => + ["way/1249366504", "https://www.openstreetmap.org/way/1249366504"], + + "w1249366504" => + ["way/1249366504", "https://www.openstreetmap.org/way/1249366504"], + + "relation/7876483" => + ["relation/7876483", "https://www.openstreetmap.org/relation/7876483"], + + "relation 7876483" => + ["relation/7876483", "https://www.openstreetmap.org/relation/7876483"], + + "r7876483" => + ["relation/7876483", "https://www.openstreetmap.org/relation/7876483"], + + "changeset/163353772" => + ["changeset/163353772", "https://www.openstreetmap.org/changeset/163353772"], + + "changeset 163353772" => + ["changeset/163353772", "https://www.openstreetmap.org/changeset/163353772"], + + "note/4655490" => + ["note/4655490", "https://www.openstreetmap.org/note/4655490"], + + "note 4655490" => + ["note/4655490", "https://www.openstreetmap.org/note/4655490"] + } + + cases.each do |input, (expected_text, expected_href)| + r = RichText.new("text", input) + assert_html r do + assert_dom "a", :count => 1, :text => expected_text do + assert_dom "> @href", expected_href + end + end + end + end + end + def test_text_to_html_linkify_no_year_misinterpretation r = RichText.new("text", "We thought there was no way 2020 could be worse than 2019. We were wrong. Please note 2025 is the first square year since OSM started. In that year, some osmlab repos switched from node 22 to bun 1.3.") assert_html r do -- 2.39.5