# frozen_string_literal: true
class StatusLengthValidator < ActiveModel::Validator
- MAX_CHARS = 500
+ MAX_CHARS = (ENV['MAX_TOOT_CHARS'] || 500).to_i
+ URL_PATTERN = %r{
+ (?:
+ (#{Twitter::TwitterText::Regex[:valid_url_preceding_chars]})
+ (#{FetchLinkCardService::URL_PATTERN})
+ )
+ }iox
+ URL_PLACEHOLDER = "\1#{'x' * 23}"
def validate(status)
return unless status.local? && !status.reblog?
"@gamestdio/websocket": "^0.3.2",
"@github/webauthn-json": "^0.5.7",
"@rails/ujs": "^6.1.3",
- "array-includes": "^3.1.2",
+ "array-includes": "^3.1.3",
+ "atrament": "0.2.4",
"arrow-key-navigation": "^1.2.0",
"autoprefixer": "^9.8.6",
"axios": "^0.21.1",
expect(status.errors).to_not have_received(:add)
end
+ it 'does not count non-autolinkable URLs as 23 characters flat' do
+ text = ('a' * 476) + "http://#{'b' * 30}.com/example"
+ status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
+
+ subject.validate(status)
+ expect(status.errors).to have_received(:add)
+ end
+
it 'counts only the front part of remote usernames' do
- text = ('a' * 475) + " @alice@#{'b' * 30}.com"
+ username = '@alice'
+ chars = StatusLengthValidator::MAX_CHARS - 1 - username.length
+ text = ('a' * 475) + " #{username}@#{'b' * 30}.com"
status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
subject.validate(status)