1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-01 17:38:37 +00:00

feat(ui): add user setting to control target="_blank" on links

Rationale: Opening links in the current tab is the default browser behavior.

Using `target="_blank"` on external links can lead to accessibility issues and override user preferences. It may also interfere with assistive technologies and expected browser behavior.

To maintain backward compatibility, this option is enabled by default (`true`), which adds `target="_blank"` to links.
This commit is contained in:
Frédéric Guillot 2025-06-08 20:47:57 -07:00
parent 699deea72c
commit c718eb039b
39 changed files with 345 additions and 259 deletions

View file

@ -48,11 +48,12 @@ type SettingsForm struct {
CategoriesSortingOrder string
MarkReadOnView bool
// MarkReadBehavior is a string representation of the MarkReadOnView and MarkReadOnMediaPlayerCompletion fields together
MarkReadBehavior MarkReadBehavior
MediaPlaybackRate float64
BlockFilterEntryRules string
KeepFilterEntryRules string
AlwaysOpenExternalLinks bool
MarkReadBehavior MarkReadBehavior
MediaPlaybackRate float64
BlockFilterEntryRules string
KeepFilterEntryRules string
AlwaysOpenExternalLinks bool
OpenExternalLinksInNewTab bool
}
// MarkAsReadBehavior returns the MarkReadBehavior from the given MarkReadOnView and MarkReadOnMediaPlayerCompletion values.
@ -116,6 +117,7 @@ func (s *SettingsForm) Merge(user *model.User) *model.User {
user.BlockFilterEntryRules = s.BlockFilterEntryRules
user.KeepFilterEntryRules = s.KeepFilterEntryRules
user.AlwaysOpenExternalLinks = s.AlwaysOpenExternalLinks
user.OpenExternalLinksInNewTab = s.OpenExternalLinksInNewTab
MarkReadOnView, MarkReadOnMediaPlayerCompletion := ExtractMarkAsReadBehavior(s.MarkReadBehavior)
user.MarkReadOnView = MarkReadOnView
@ -181,32 +183,33 @@ func NewSettingsForm(r *http.Request) *SettingsForm {
mediaPlaybackRate = 1
}
return &SettingsForm{
Username: r.FormValue("username"),
Password: r.FormValue("password"),
Confirmation: r.FormValue("confirmation"),
Theme: r.FormValue("theme"),
Language: r.FormValue("language"),
Timezone: r.FormValue("timezone"),
EntryDirection: r.FormValue("entry_direction"),
EntryOrder: r.FormValue("entry_order"),
EntriesPerPage: int(entriesPerPage),
KeyboardShortcuts: r.FormValue("keyboard_shortcuts") == "1",
ShowReadingTime: r.FormValue("show_reading_time") == "1",
CustomCSS: r.FormValue("custom_css"),
CustomJS: r.FormValue("custom_js"),
ExternalFontHosts: r.FormValue("external_font_hosts"),
EntrySwipe: r.FormValue("entry_swipe") == "1",
GestureNav: r.FormValue("gesture_nav"),
DisplayMode: r.FormValue("display_mode"),
DefaultReadingSpeed: int(defaultReadingSpeed),
CJKReadingSpeed: int(cjkReadingSpeed),
DefaultHomePage: r.FormValue("default_home_page"),
CategoriesSortingOrder: r.FormValue("categories_sorting_order"),
MarkReadOnView: r.FormValue("mark_read_on_view") == "1",
MarkReadBehavior: MarkReadBehavior(r.FormValue("mark_read_behavior")),
MediaPlaybackRate: mediaPlaybackRate,
BlockFilterEntryRules: r.FormValue("block_filter_entry_rules"),
KeepFilterEntryRules: r.FormValue("keep_filter_entry_rules"),
AlwaysOpenExternalLinks: r.FormValue("always_open_external_links") == "1",
Username: r.FormValue("username"),
Password: r.FormValue("password"),
Confirmation: r.FormValue("confirmation"),
Theme: r.FormValue("theme"),
Language: r.FormValue("language"),
Timezone: r.FormValue("timezone"),
EntryDirection: r.FormValue("entry_direction"),
EntryOrder: r.FormValue("entry_order"),
EntriesPerPage: int(entriesPerPage),
KeyboardShortcuts: r.FormValue("keyboard_shortcuts") == "1",
ShowReadingTime: r.FormValue("show_reading_time") == "1",
CustomCSS: r.FormValue("custom_css"),
CustomJS: r.FormValue("custom_js"),
ExternalFontHosts: r.FormValue("external_font_hosts"),
EntrySwipe: r.FormValue("entry_swipe") == "1",
GestureNav: r.FormValue("gesture_nav"),
DisplayMode: r.FormValue("display_mode"),
DefaultReadingSpeed: int(defaultReadingSpeed),
CJKReadingSpeed: int(cjkReadingSpeed),
DefaultHomePage: r.FormValue("default_home_page"),
CategoriesSortingOrder: r.FormValue("categories_sorting_order"),
MarkReadOnView: r.FormValue("mark_read_on_view") == "1",
MarkReadBehavior: MarkReadBehavior(r.FormValue("mark_read_behavior")),
MediaPlaybackRate: mediaPlaybackRate,
BlockFilterEntryRules: r.FormValue("block_filter_entry_rules"),
KeepFilterEntryRules: r.FormValue("keep_filter_entry_rules"),
AlwaysOpenExternalLinks: r.FormValue("always_open_external_links") == "1",
OpenExternalLinksInNewTab: r.FormValue("open_external_links_in_new_tab") == "1",
}
}