Files
mastodon/app/lib/extractor.rb
jcoffey-dev 319ed76dbd
Crowdin / Upload translations / upload-translations (push) Skipped
Historical data migration test / test (14-alpine) (push) Canceled after 0s
Historical data migration test / test (15-alpine) (push) Canceled after 0s
Historical data migration test / test (16-alpine) (push) Canceled after 0s
Historical data migration test / test (17-alpine) (push) Canceled after 0s
Bundler Audit / security (push) Canceled after 0s
Haml Linting / lint (push) Canceled after 0s
JavaScript Linting / lint (push) Canceled after 0s
Ruby Linting / lint (push) Canceled after 0s
JavaScript Testing / test (push) Canceled after 0s
Ruby Testing / build (production) (push) Canceled after 0s
Ruby Testing / test (.ruby-version) (push) Canceled after 0s
Ruby Testing / test (3.3) (push) Canceled after 0s
Ruby Testing / test (3.4) (push) Canceled after 0s
Ruby Testing / End to End testing (.ruby-version) (push) Canceled after 0s
Ruby Testing / End to End testing (3.3) (push) Canceled after 0s
Ruby Testing / End to End testing (3.4) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Canceled after 0s
Check i18n / check-i18n (push) Canceled after 0s
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (javascript) (push) Canceled after 0s
CodeQL / Analyze (ruby) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (3.4, docker.elastic.co/elasticsearch/elasticsearch:7.17.29) (push) Canceled after 0s
Check formatting / lint (push) Canceled after 0s
CSS Linting / lint (push) Canceled after 0s
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.19.2) (push) Canceled after 0s
Chromatic / Check for relevant changes (push) Canceled after 0s
Chromatic / Run Chromatic (push) Canceled after 0s
Import Mastodon v4.7.3
Snapshot of upstream tag v4.7.3 (commit 8ff11c2bb7b9f0714e947b10fa3629c6542c7121) from
https://github.com/mastodon/mastodon, unmodified.
2026-10-05 22:03:13 -07:00

115 lines
3.0 KiB
Ruby
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# frozen_string_literal: true
module Extractor
MAX_DOMAIN_LENGTH = 253
extend Twitter::TwitterText::Extractor
module_function
def extract_entities_with_indices(text, options = {}, &block)
entities = extract_urls_with_indices(text, options) +
extract_hashtags_with_indices(text, check_url_overlap: false) +
extract_mentions_or_lists_with_indices(text) +
extract_extra_uris_with_indices(text)
return [] if entities.empty?
entities = remove_overlapping_entities(entities)
entities.each(&block) if block
entities
end
def extract_mentions_or_lists_with_indices(text)
return [] unless text && Twitter::TwitterText::Regex[:at_signs].match?(text)
possible_entries = []
text.scan(Account::MENTION_RE) do |screen_name, _|
match_data = $LAST_MATCH_INFO
after = ::Regexp.last_match.post_match
unless Twitter::TwitterText::Regex[:end_mention_match].match?(after)
_, domain = screen_name.split('@')
next if domain.present? && domain.length > MAX_DOMAIN_LENGTH
start_position = match_data.char_begin(1) - 1
end_position = match_data.char_end(1)
possible_entries << {
screen_name: screen_name,
indices: [start_position, end_position],
}
end
end
if block_given?
possible_entries.each do |mention|
yield mention[:screen_name], mention[:indices].first, mention[:indices].last
end
end
possible_entries
end
def extract_hashtags_with_indices(text, _options = {})
return [] unless text&.index(/[##]/)
possible_entries = []
text.scan(Tag::HASHTAG_RE) do |hash_text, _|
match_data = $LAST_MATCH_INFO
start_position = match_data.char_begin(1) - 1
end_position = match_data.char_end(1)
after = ::Regexp.last_match.post_match
if after.start_with?('://')
hash_text.match(/(.+)(https?\Z)/) do |matched|
hash_text = matched[1]
end_position -= matched[2].codepoint_length
end
end
possible_entries << {
hashtag: hash_text,
indices: [start_position, end_position],
}
end
if block_given?
possible_entries.each do |tag|
yield tag[:hashtag], tag[:indices].first, tag[:indices].last
end
end
possible_entries
end
def extract_extra_uris_with_indices(text)
return [] unless text&.index(':')
possible_entries = []
text.scan(Twitter::TwitterText::Regex[:valid_extended_uri]) do
valid_uri_match_data = $LAST_MATCH_INFO
start_position = valid_uri_match_data.char_begin(3)
end_position = valid_uri_match_data.char_end(3)
possible_entries << {
url: valid_uri_match_data[3],
indices: [start_position, end_position],
}
end
if block_given?
possible_entries.each do |url|
yield url[:url], url[:indices].first, url[:indices].last
end
end
possible_entries
end
end