From: Tom Hughes Date: Wed, 26 Mar 2025 18:23:27 +0000 (+0000) Subject: Merge remote-tracking branch 'upstream/pull/5842' X-Git-Tag: live~144 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/5332913c36c8b3b7a3b53a5edd0aea79f07eaea3?hp=da2535ebe48664d570523e1f8ab3d95c8c0bf603 Merge remote-tracking branch 'upstream/pull/5842' --- diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d8a76bcb1..b60310e79 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -45,6 +45,7 @@ jobs: - name: Populate database run: | sed -f script/normalise-structure db/structure.sql > db/structure.expected + rm -f db/structure.sql bundle exec rails db:migrate sed -f script/normalise-structure db/structure.sql > db/structure.actual diff -uw db/structure.expected db/structure.actual diff --git a/Gemfile b/Gemfile index 7155b1f62..a7801fece 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,8 @@ gem "pg" gem "dartsass-sprockets" # Pin the dependentent sass-embedded to avoid deprecation warnings in bootstrap gem "sass-embedded", "~> 1.64.0" +# Pin uri to avoid errors in dartsass-ruby +gem "uri", "< 1.0.0" # Use Terser as compressor for JavaScript assets gem "terser" @@ -64,7 +66,7 @@ gem "rack-cors" gem "rails-i18n", "~> 8.0.0" gem "rails_param" gem "rinku", ">= 2.0.6", :require => "rails_rinku" -gem "strong_migrations", "< 2.0.0" +gem "strong_migrations" gem "validates_email_format_of", ">= 1.5.1" # Native OSM extensions diff --git a/Gemfile.lock b/Gemfile.lock index 91a24e8c2..925eebe3c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -92,17 +92,18 @@ GEM argon2 (2.3.2) ffi (~> 1.15) ffi-compiler (~> 1.0) - ast (2.4.2) + ast (2.4.3) autoprefixer-rails (10.4.19.0) execjs (~> 2) aws-eventstream (1.3.2) - aws-partitions (1.1068.0) - aws-sdk-core (3.220.1) + aws-partitions (1.1073.0) + aws-sdk-core (3.221.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) base64 jmespath (~> 1, >= 1.6.1) + logger aws-sdk-kms (1.99.0) aws-sdk-core (~> 3, >= 3.216.0) aws-sigv4 (~> 1.5) @@ -406,7 +407,7 @@ GEM net-smtp (0.5.1) net-protocol nio4r (2.7.4) - nokogiri (1.18.5) + nokogiri (1.18.6) mini_portile2 (~> 2.8.2) racc (~> 1.4) oauth (1.1.0) @@ -468,7 +469,7 @@ GEM iniparse (~> 1.4) rexml (>= 3.3.9) parallel (1.26.3) - parser (3.3.7.1) + parser (3.3.7.2) ast (~> 2.4.1) racc pg (1.5.9) @@ -476,6 +477,7 @@ GEM pp (0.6.2) prettyprint prettyprint (0.2.0) + prism (1.4.0) progress (3.6.0) pstore (0.2.0) psych (5.2.3) @@ -548,7 +550,7 @@ GEM rb-inotify (0.11.1) ffi (~> 1.0) rchardet (1.9.0) - rdoc (6.12.0) + rdoc (6.13.0) psych (>= 4.0.0) regexp_parser (2.10.0) reline (0.6.0) @@ -572,8 +574,9 @@ GEM rubocop-ast (>= 1.38.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.39.0) - parser (>= 3.3.1.0) + rubocop-ast (1.43.0) + parser (>= 3.3.7.2) + prism (~> 1.4) rubocop-capybara (2.22.1) lint_roller (~> 1.1) rubocop (~> 1.72, >= 1.72.1) @@ -613,7 +616,7 @@ GEM addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) securerandom (0.4.1) - selenium-webdriver (4.23.0) + selenium-webdriver (4.30.1) base64 (~> 0.2) logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) @@ -641,9 +644,9 @@ GEM actionpack (>= 6.1) activesupport (>= 6.1) sprockets (>= 3.0.0) - stringio (3.1.5) - strong_migrations (1.8.0) - activerecord (>= 5.2) + stringio (3.1.6) + strong_migrations (2.2.1) + activerecord (>= 7) teaspoon (1.4.0) railties (>= 5.0) teaspoon-mocha (2.3.3) @@ -781,12 +784,13 @@ DEPENDENCIES simplecov simplecov-lcov sprockets-exporters_pack - strong_migrations (< 2.0.0) + strong_migrations teaspoon teaspoon-mocha (~> 2.3.3) terser turbo-rails unicode-display_width + uri (< 1.0.0) validates_email_format_of (>= 1.5.1) vendorer webmock diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index 27f2c949e..cd22dc23c 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -118,7 +118,7 @@ class ConfirmationsController < ApplicationController end ## - # display a message about th current status of the gravatar setting + # display a message about the current status of the Gravatar setting def gravatar_status_message(user) if user.image_use_gravatar t "profiles.edit.gravatar.enabled" diff --git a/app/helpers/browse_helper.rb b/app/helpers/browse_helper.rb index 482503e8a..5909706fb 100644 --- a/app/helpers/browse_helper.rb +++ b/app/helpers/browse_helper.rb @@ -79,18 +79,6 @@ module BrowseHelper "nofollow" if object.tags.empty? end - def type_and_paginated_count(type, pages, selected_page = pages.current_page) - if pages.page_count == 1 - t ".#{type.pluralize}", - :count => pages.item_count - else - t ".#{type.pluralize}_paginated", - :x => selected_page.first_item, - :y => selected_page.last_item, - :count => pages.item_count - end - end - def sidebar_classic_pagination(pages, page_param) max_width_for_default_padding = 35 diff --git a/app/views/changesets/_paging_nav.html.erb b/app/views/changesets/_paging_nav.html.erb index 058738222..9fa23f670 100644 --- a/app/views/changesets/_paging_nav.html.erb +++ b/app/views/changesets/_paging_nav.html.erb @@ -1,8 +1,25 @@ -

<%= type_and_paginated_count(type, pages) %>

-<% if pages.page_count > 1 %> +<% if pages.page_count == 1 %> +

+ <%= t ".#{type.pluralize}_title" %> + + <%= pages.item_count %> + +

+<% elsif pages.page_count > 1 %> +

+ <%= t ".#{type.pluralize}_title" %> + + <%= t ".range", :x => pages.current_page.first_item, + :y => pages.current_page.last_item, + :count => pages.item_count %> + +

+ <%= sidebar_classic_pagination(pages, "#{type}_page") do |page| { - :title => type_and_paginated_count(type, pages, page), + :title => t(".#{type.pluralize}_paginated", :x => page.first_item, + :y => page.last_item, + :count => pages.item_count), :data => { :turbo => "true" } } end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 230d9242c..aba37e934 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -522,12 +522,13 @@ en: changesetxml: "Changeset XML" osmchangexml: "osmChange XML" paging_nav: - nodes: "Nodes (%{count})" + nodes_title: "Nodes" nodes_paginated: "Nodes (%{x}-%{y} of %{count})" - ways: "Ways (%{count})" + ways_title: "Ways" ways_paginated: "Ways (%{x}-%{y} of %{count})" - relations: "Relations (%{count})" + relations_title: "Relations" relations_paginated: "Relations (%{x}-%{y} of %{count})" + range: "%{x}-%{y} of %{count}" not_found_message: sorry: "Sorry, changeset #%{id} could not be found." timeout: diff --git a/config/settings.yml b/config/settings.yml index 51f4444c4..b98e77c92 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -136,6 +136,10 @@ overpass_credentials: false graphhopper_url: "https://graphhopper.com/api/1/route" fossgis_osrm_url: "https://routing.openstreetmap.de/" fossgis_valhalla_url: "https://valhalla1.openstreetmap.de/route" +# 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 +linkify_hosts_replacement: "osm.org" # External authentication credentials #google_auth_id: "" #google_auth_secret: "" diff --git a/db/structure.sql b/db/structure.sql index 9d3af4d00..48036fd8e 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -9,6 +9,12 @@ SET xmloption = content; SET client_min_messages = warning; SET row_security = off; +-- +-- Name: public; Type: SCHEMA; Schema: -; Owner: - +-- + +-- *not* creating schema, since initdb creates it + -- -- Name: btree_gist; Type: EXTENSION; Schema: -; Owner: - diff --git a/lib/rich_text.rb b/lib/rich_text.rb index c20f973b1..d9c799611 100644 --- a/lib/rich_text.rb +++ b/lib/rich_text.rb @@ -76,11 +76,13 @@ module RichText end def linkify(text, mode = :urls) - if text.html_safe? - Rinku.auto_link(text, mode, tag_builder.tag_options(:rel => "nofollow noopener noreferrer")).html_safe - else - Rinku.auto_link(text, mode, tag_builder.tag_options(:rel => "nofollow noopener noreferrer")) - end + link_attr = tag_builder.tag_options(:rel => "nofollow noopener noreferrer") + Rinku.auto_link(ERB::Util.html_escape(text), mode, link_attr) do |url| + %r{^https?://([^/]*)(.*)$}.match(url) do |m| + "#{Settings.linkify_hosts_replacement}#{m[2]}" if Settings.linkify_hosts_replacement && + Settings.linkify_hosts&.include?(m[1]) + end || url + end.html_safe end end diff --git a/test/lib/rich_text_test.rb b/test/lib/rich_text_test.rb index 63c70b099..aa9e70085 100644 --- a/test/lib/rich_text_test.rb +++ b/test/lib/rich_text_test.rb @@ -221,19 +221,62 @@ class RichTextTest < ActiveSupport::TestCase assert_equal 50, r.spam_score.round end - def test_text_to_html - r = RichText.new("text", "foo http://example.com/ bar") - assert_html r do - assert_select "a", 1 - assert_select "a[href='http://example.com/']", 1 - assert_select "a[rel='nofollow noopener noreferrer']", 1 + def test_text_to_html_linkify + with_settings(:linkify_hosts => ["replace-me.example.com"], :linkify_hosts_replacement => "repl.example.com") do + r = RichText.new("text", "foo http://example.com/ bar") + assert_html r do + assert_dom "a", :count => 1, :text => "http://example.com/" do + assert_dom "> @href", "http://example.com/" + assert_dom "> @rel", "nofollow noopener noreferrer" + end + end + end + end + + def test_text_to_html_linkify_replace + with_settings(:linkify_hosts => ["replace-me.example.com"], :linkify_hosts_replacement => "repl.example.com") do + r = RichText.new("text", "foo https://replace-me.example.com/some/path?query=te10#result12 bar") + assert_html r do + assert_dom "a", :count => 1, :text => "repl.example.com/some/path?query=te10#result12" do + assert_dom "> @href", "https://replace-me.example.com/some/path?query=te10#result12" + assert_dom "> @rel", "nofollow noopener noreferrer" + end + end end + end + + def test_text_to_html_linkify_replace_other_scheme + with_settings(:linkify_hosts => ["replace-me.example.com"], :linkify_hosts_replacement => "repl.example.com") do + r = RichText.new("text", "foo ftp://replace-me.example.com/some/path?query=te10#result12 bar") + assert_html r do + assert_dom "a", :count => 1, :text => "ftp://replace-me.example.com/some/path?query=te10#result12" do + assert_dom "> @href", "ftp://replace-me.example.com/some/path?query=te10#result12" + assert_dom "> @rel", "nofollow noopener noreferrer" + end + end + end + end + def test_text_to_html_linkify_replace_undefined + with_settings(:linkify_hosts => ["replace-me.example.com"], :linkify_hosts_replacement => nil) do + r = RichText.new("text", "foo https://replace-me.example.com/some/path?query=te10#result12 bar") + assert_html r do + assert_dom "a", :count => 1, :text => "https://replace-me.example.com/some/path?query=te10#result12" do + assert_dom "> @href", "https://replace-me.example.com/some/path?query=te10#result12" + assert_dom "> @rel", "nofollow noopener noreferrer" + end + end + end + end + + def test_text_to_html_email r = RichText.new("text", "foo example@example.com bar") assert_html r do assert_select "a", 0 end + end + def test_text_to_html_escape r = RichText.new("text", "foo < bar & baz > qux") assert_html r do assert_select "p", "foo < bar & baz > qux" diff --git a/yarn.lock b/yarn.lock index ed0a4d796..b5f8e755e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -146,9 +146,9 @@ integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/leaflet@^1.9.0": - version "1.9.16" - resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.9.16.tgz#3e3abc103e106523cde01625057e2294f332ec3b" - integrity sha512-wzZoyySUxkgMZ0ihJ7IaUIblG8Rdc8AbbZKLneyn+QjYsj5q1QU7TEKYqwTr10BGSzY5LI7tJk9Ifo+mEjdFRw== + version "1.9.17" + resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.9.17.tgz#f7f12f9306029df48801cd830f66597d614a2e08" + integrity sha512-IJ4K6t7I3Fh5qXbQ1uwL3CFVbCi6haW9+53oLWgdKlLP7EaS21byWFJxxqOx9y8I0AP0actXSJLVMbyvxhkUTA== dependencies: "@types/geojson" "*"