Style tweaks: handle conflicting/redundant tweaks

Disable redundant or incompatible tweaks when enabling some.
This makes the menu more dynamic to show what's impacted,
save some re-renderings, and may avoid the user trying
combinations that would have no effect.
reviewable/pr9307/r1
poire-z 2 years ago
parent 94b76097aa
commit 6fb266cb71

@ -267,6 +267,82 @@ function ReaderStyleTweak:nbTweaksEnabled(sub_item_table)
return nb_enabled, nb_found return nb_enabled, nb_found
end end
function ReaderStyleTweak:resolveConflictsBeforeEnabling(id, conflicts_with)
-- conflicts_with may be a string, an array or hash table of ids, or a function:
-- make it a function for us here
local conflicts_with_type = type(conflicts_with)
local conflicts_with_func
if conflicts_with_type == "function" then
conflicts_with_func = conflicts_with
elseif conflicts_with_type == "string" then
conflicts_with_func = function(otid) return otid == conflicts_with end
elseif conflicts_with_type == "table" then
conflicts_with_func = function(otid) return conflicts_with[otid] ~= nil or util.arrayContains(conflicts_with, otid) end
else
conflicts_with_func = function(otid) return false end
end
local to_remove = {}
for other_id, other_enabled in pairs(self.doc_tweaks) do
-- We also reset the provided "id" for a complete cleanup,
-- it is expected the called will re-enable it
if other_enabled and (other_id == id or conflicts_with_func(other_id)) then
table.insert(to_remove, other_id)
end
end
for _, other_id in ipairs(to_remove) do
self.doc_tweaks[other_id] = nil
end
-- global_tweaks may also contain some conflicting ids: we need to make them false
-- in doc_tweaks to have them disabled (but we keem them in global_tweaks)
local to_make_false = {}
for other_id, other_enabled in pairs(self.global_tweaks) do
-- (We shouldn't be called if the provided "id" is already enabled
-- in global_tweaks. So we don't check for that here.)
if other_enabled and conflicts_with_func(other_id) then
table.insert(to_make_false, other_id)
end
end
for _, other_id in ipairs(to_make_false) do
self.doc_tweaks[other_id] = false
end
end
function ReaderStyleTweak:resolveConflictsBeforeMakingDefault(id, conflicts_with)
local conflicts_with_type = type(conflicts_with)
local conflicts_with_func
if conflicts_with_type == "function" then
conflicts_with_func = conflicts_with
elseif conflicts_with_type == "string" then
conflicts_with_func = function(otid) return otid == conflicts_with end
elseif conflicts_with_type == "table" then
conflicts_with_func = function(otid) return conflicts_with[otid] ~= nil or util.arrayContains(conflicts_with, otid) end
else
conflicts_with_func = function(otid) return false end
end
local to_remove = {}
for other_id, other_enabled in pairs(self.global_tweaks) do
-- We also reset the provided "id" for a complete cleanup,
-- it is expected the called will re-enable it
if other_id == id or conflicts_with_func(other_id) then
table.insert(to_remove, other_id)
end
end
for _, other_id in ipairs(to_remove) do
self.global_tweaks[other_id] = nil
end
-- Also remove the provided "id" and any conflicting one from doc_tweaks (where
-- they may be false and prevent this new default to apply to current book)
to_remove = {}
for other_id, other_enabled in pairs(self.doc_tweaks) do
if other_id == id or conflicts_with_func(other_id) then
table.insert(to_remove, other_id)
end
end
for _, other_id in ipairs(to_remove) do
self.doc_tweaks[other_id] = nil
end
end
-- Called by ReaderTypeset, returns the already built string -- Called by ReaderTypeset, returns the already built string
function ReaderStyleTweak:getCssText() function ReaderStyleTweak:getCssText()
return self.css_text return self.css_text
@ -432,7 +508,24 @@ You can enable individual tweaks on this book with a tap, or view more details a
toggle_global_default_callback = function() toggle_global_default_callback = function()
if self.global_tweaks[item.id] then if self.global_tweaks[item.id] then
self.global_tweaks[item.id] = nil self.global_tweaks[item.id] = nil
if self.doc_tweaks[item.id] == false then
self.doc_tweaks[item.id] = nil
end
else else
if item.conflicts_with and item.global_conflicts_with ~= false then
-- For hold/makeDefault/global_tweaks, the tweak may provide 'global_conflicts_with':
-- if 'false': no conflict checks
-- if a function: use it instead of item.conflicts_with
-- if nil or 'true', use item.conflicts_with
if type(item.global_conflicts_with) == "function" then
self:resolveConflictsBeforeMakingDefault(item.id, item.global_conflicts_with)
else
self:resolveConflictsBeforeMakingDefault(item.id, item.conflicts_with)
end
-- Remove all references in doc_tweak
self:resolveConflictsBeforeEnabling(item.id, item.conflicts_with)
self.doc_tweaks[item.id] = nil
end
self.global_tweaks[item.id] = true self.global_tweaks[item.id] = true
end end
touchmenu_instance:updateItems() touchmenu_instance:updateItems()
@ -452,6 +545,9 @@ You can enable individual tweaks on this book with a tap, or view more details a
self.doc_tweaks[item.id] = nil self.doc_tweaks[item.id] = nil
end end
else else
if item.conflicts_with then
self:resolveConflictsBeforeEnabling(item.id, item.conflicts_with)
end
self.doc_tweaks[item.id] = true self.doc_tweaks[item.id] = true
end end
self:updateCssText(true) -- apply it immediately self:updateCssText(true) -- apply it immediately
@ -593,10 +689,8 @@ p.someTitleClassName { text-indent: 0; }
DIV.advertisement { display: none !important; } DIV.advertisement { display: none !important; }
.footnoteContainerClassName { .footnoteContainerClassName {
font-size: 0.8rem !important;
text-align: justify !important;
margin: 0 !important;
-cr-hint: footnote-inpage; -cr-hint: footnote-inpage;
margin: 0 !important;
} }
]] ]]

@ -7,8 +7,16 @@ They may have the following optional attributes:
- description: text displayed when holding on menu item - description: text displayed when holding on menu item
- priority: higher numbers are appended after lower numbers - priority: higher numbers are appended after lower numbers
(if not specified, default to 0) (if not specified, default to 0)
- conflicts_with: a string with the id of another tweak that should be
disabled when this tweak is enabled, or an array/table of tweaks ids,
or a function(other_id) return true for ids conflicting.
It is also used with "hold / use on all books", unless the
next property is provided.
- global_conflicts_with: similar to 'conflicts_with', but used with
"hold / use on all books". If 'false', no conflict check is done.
]] ]]
local util = require("util")
local _ = require("gettext") local _ = require("gettext")
local C_ = _.pgettext local C_ = _.pgettext
@ -32,22 +40,26 @@ local CssTweaks = {
title = _("Horizontal margins"), title = _("Horizontal margins"),
{ {
id = "margin_horizontal_all_0", id = "margin_horizontal_all_0",
conflicts_with = "paragraph_no_horizontal_margin",
title = _("Ignore all horizontal margins"), title = _("Ignore all horizontal margins"),
css = [[* { margin-left: 0 !important; margin-right: 0 !important; }]], css = [[* { margin-left: 0 !important; margin-right: 0 !important; }]],
}, },
{ {
id = "padding_horizontal_all_0", id = "padding_horizontal_all_0",
conflicts_with = "paragraph_no_horizontal_padding",
title = _("Ignore all horizontal padding"), title = _("Ignore all horizontal padding"),
css = [[* { padding-left: 0 !important; padding-right: 0 !important; }]], css = [[* { padding-left: 0 !important; padding-right: 0 !important; }]],
separator = true, separator = true,
}, },
{ {
id = "paragraph_no_horizontal_margin", id = "paragraph_no_horizontal_margin",
conflicts_with = "margin_horizontal_all_0",
title = _("Ignore horizontal paragraph margins"), title = _("Ignore horizontal paragraph margins"),
css = [[p, li { margin-left: 0 !important; margin-right: 0 !important; }]], css = [[p, li { margin-left: 0 !important; margin-right: 0 !important; }]],
}, },
{ {
id = "paragraph_no_horizontal_padding", id = "paragraph_no_horizontal_padding",
conflicts_with = "padding_horizontal_all_0",
title = _("Ignore horizontal paragraph padding"), title = _("Ignore horizontal paragraph padding"),
css = [[p, li { padding-left: 0 !important; padding-right: 0 !important; }]], css = [[p, li { padding-left: 0 !important; padding-right: 0 !important; }]],
}, },
@ -56,22 +68,26 @@ local CssTweaks = {
title = _("Vertical margins"), title = _("Vertical margins"),
{ {
id = "margin_vertical_all_0", id = "margin_vertical_all_0",
conflicts_with = "paragraph_no_vertical_margin",
title = _("Ignore all vertical margins"), title = _("Ignore all vertical margins"),
css = [[* { margin-top: 0 !important; margin-bottom: 0 !important; }]], css = [[* { margin-top: 0 !important; margin-bottom: 0 !important; }]],
}, },
{ {
id = "padding_vertical_all_0", id = "padding_vertical_all_0",
conflicts_with = "paragraph_no_vertical_padding",
title = _("Ignore all vertical padding"), title = _("Ignore all vertical padding"),
css = [[* { padding-top: 0 !important; padding-bottom: 0 !important; }]], css = [[* { padding-top: 0 !important; padding-bottom: 0 !important; }]],
separator = true, separator = true,
}, },
{ {
id = "paragraph_no_vertical_margin", id = "paragraph_no_vertical_margin",
conflicts_with = "margin_vertical_all_0",
title = _("Ignore vertical paragraph margins"), title = _("Ignore vertical paragraph margins"),
css = [[p, li { margin-top: 0 !important; margin-bottom: 0 !important; }]], css = [[p, li { margin-top: 0 !important; margin-bottom: 0 !important; }]],
}, },
{ {
id = "paragraph_no_vertical_padding", id = "paragraph_no_vertical_padding",
conflicts_with = "padding_vertical_all_0",
title = _("Ignore vertical paragraph padding"), title = _("Ignore vertical paragraph padding"),
css = [[p, li { padding-top: 0 !important; padding-bottom: 0 !important; }]], css = [[p, li { padding-top: 0 !important; padding-bottom: 0 !important; }]],
}, },
@ -179,6 +195,7 @@ These tweaks allow you to change this behavior, and to override publisher rules.
-- This trick will work with EPUB, but not with single file HTML. -- This trick will work with EPUB, but not with single file HTML.
{ {
id = "widows_orphans_avoid", id = "widows_orphans_avoid",
conflicts_with = "widows_avoid_orphans_allow",
title = _("Avoid widows and orphans"), title = _("Avoid widows and orphans"),
description = _("Avoid widow and orphan lines, allowing for some possible blank space at the bottom of pages."), description = _("Avoid widow and orphan lines, allowing for some possible blank space at the bottom of pages."),
css = [[ css = [[
@ -192,6 +209,7 @@ DocFragment {
}, },
{ {
id = "widows_avoid_orphans_allow", id = "widows_avoid_orphans_allow",
conflicts_with = "widows_orphans_avoid",
title = _("Avoid widows but allow orphans"), title = _("Avoid widows but allow orphans"),
description = _([[ description = _([[
Avoid widow lines, but allow orphan lines, allowing for some possible blank space at the bottom of pages. Avoid widow lines, but allow orphan lines, allowing for some possible blank space at the bottom of pages.
@ -225,6 +243,7 @@ DocFragment {
title = _("Text alignment"), title = _("Text alignment"),
{ {
id = "text_align_most_left", id = "text_align_most_left",
conflicts_with = { "text_align_all_left", "text_align_most_justify" },
title = _("Left align most text"), title = _("Left align most text"),
description = _("Enforce left alignment of text in common text elements."), description = _("Enforce left alignment of text in common text elements."),
css = [[body, p, li { text-align: left !important; }]], css = [[body, p, li { text-align: left !important; }]],
@ -232,6 +251,7 @@ DocFragment {
}, },
{ {
id = "text_align_all_left", id = "text_align_all_left",
conflicts_with = { "text_align_most_left", "text_align_all_justify" },
title = _("Left align all elements"), title = _("Left align all elements"),
description = _("Enforce left alignment of text in all elements."), description = _("Enforce left alignment of text in all elements."),
css = [[* { text-align: left !important; }]], css = [[* { text-align: left !important; }]],
@ -240,6 +260,7 @@ DocFragment {
}, },
{ {
id = "text_align_most_justify", id = "text_align_most_justify",
conflicts_with = { "text_align_most_left", "text_align_all_justify" },
title = _("Justify most text"), title = _("Justify most text"),
description = _("Text justification is the default, but it may be overridden by publisher styles. This will re-enable it for most common text elements."), description = _("Text justification is the default, but it may be overridden by publisher styles. This will re-enable it for most common text elements."),
css = [[ css = [[
@ -253,6 +274,7 @@ pre {
}, },
{ {
id = "text_align_all_justify", id = "text_align_all_justify",
conflicts_with = { "text_align_all_left", "text_align_most_justify" },
title = _("Justify all elements"), title = _("Justify all elements"),
description = _("Text justification is the default, but it may be overridden by publisher styles. This will force justification on all elements, some of which may not be centered as expected."), description = _("Text justification is the default, but it may be overridden by publisher styles. This will force justification on all elements, some of which may not be centered as expected."),
css = [[ css = [[
@ -286,12 +308,14 @@ You may also want to enable, in the top menu → Gear → Taps and gestures →
}, },
{ {
id = "body_direction_rtl", id = "body_direction_rtl",
conflicts_with = "body_direction_ltr",
title = _("Document direction RTL"), title = _("Document direction RTL"),
css = [[body { direction: rtl !important; }]], css = [[body { direction: rtl !important; }]],
priority = 2, -- so it overrides the LTR one below priority = 2, -- so it overrides the LTR one below
}, },
{ {
id = "text_align_most_right", id = "text_align_most_right",
conflicts_with = "text_align_all_right",
title = _("Right align most text"), title = _("Right align most text"),
description = _("Enforce right alignment of text in common text elements."), description = _("Enforce right alignment of text in common text elements."),
-- Includes H1..H6 as this is probably most useful for RTL readers -- Includes H1..H6 as this is probably most useful for RTL readers
@ -300,6 +324,7 @@ You may also want to enable, in the top menu → Gear → Taps and gestures →
}, },
{ {
id = "text_align_all_right", id = "text_align_all_right",
conflicts_with = "text_align_most_right",
title = _("Right align all elements"), title = _("Right align all elements"),
description = _("Enforce right alignment of text in all elements."), description = _("Enforce right alignment of text in all elements."),
css = [[* { text-align: right !important; }]], css = [[* { text-align: right !important; }]],
@ -308,6 +333,7 @@ You may also want to enable, in the top menu → Gear → Taps and gestures →
}, },
{ {
id = "body_direction_ltr", id = "body_direction_ltr",
conflicts_with = "body_direction_rtl",
title = _("Document direction LTR"), title = _("Document direction LTR"),
css = [[body { direction: ltr !important; }]], css = [[body { direction: ltr !important; }]],
}, },
@ -500,6 +526,7 @@ body, h1, h2, h3, h4, h5, h6, div, li, td, th { text-indent: 0 !important; }
title = _("Spacing between paragraphs"), title = _("Spacing between paragraphs"),
{ {
id = "paragraph_whitespace", id = "paragraph_whitespace",
conflicts_with = { "paragraph_whitespace_half", "paragraph_no_whitespace" },
title = _("Spacing between paragraphs"), title = _("Spacing between paragraphs"),
description = _("Add a line of whitespace between paragraphs."), description = _("Add a line of whitespace between paragraphs."),
priority = 5, -- Override "Ignore margins and paddings" above priority = 5, -- Override "Ignore margins and paddings" above
@ -507,6 +534,7 @@ body, h1, h2, h3, h4, h5, h6, div, li, td, th { text-indent: 0 !important; }
}, },
{ {
id = "paragraph_whitespace_half", id = "paragraph_whitespace_half",
conflicts_with = { "paragraph_whitespace", "paragraph_no_whitespace" },
title = _("Spacing between paragraphs (half)"), title = _("Spacing between paragraphs (half)"),
description = _("Add half a line of whitespace between paragraphs."), description = _("Add half a line of whitespace between paragraphs."),
priority = 5, priority = 5,
@ -514,6 +542,7 @@ body, h1, h2, h3, h4, h5, h6, div, li, td, th { text-indent: 0 !important; }
}, },
{ {
id = "paragraph_no_whitespace", id = "paragraph_no_whitespace",
conflicts_with = { "paragraph_whitespace", "paragraph_whitespace_half" },
title = _("No spacing between paragraphs"), title = _("No spacing between paragraphs"),
description = _("No whitespace between paragraphs is the default, but it may be overridden by publisher styles. This will re-enable it for paragraphs and list items."), description = _("No whitespace between paragraphs is the default, but it may be overridden by publisher styles. This will re-enable it for paragraphs and list items."),
priority = 5, priority = 5,
@ -573,45 +602,53 @@ table, tcaption, tr, th, td { border: black solid 1px; border-collapse: collapse
title = _("Links"), title = _("Links"),
{ {
id = "a_black", id = "a_black",
conflicts_with = "a_blue",
title = _("Links always black"), title = _("Links always black"),
css = [[a, a * { color: black !important; }]], css = [[a, a * { color: black !important; }]],
}, },
{ {
id = "a_blue", id = "a_blue",
conflicts_with = "a_black",
title = _("Links always blue"), title = _("Links always blue"),
css = [[a, a * { color: blue !important; }]], css = [[a, a * { color: blue !important; }]],
separator = true, separator = true,
}, },
{ {
id = "a_bold", id = "a_bold",
conflicts_with = "a_not_bold",
title = _("Links always bold"), title = _("Links always bold"),
css = [[a, a * { font-weight: bold !important; }]], css = [[a, a * { font-weight: bold !important; }]],
}, },
{ {
id = "a_not_bold", id = "a_not_bold",
conflicts_with = "a_bold",
title = _("Links never bold"), title = _("Links never bold"),
css = [[a, a * { font-weight: normal !important; }]], css = [[a, a * { font-weight: normal !important; }]],
separator = true, separator = true,
}, },
{ {
id = "a_italic", id = "a_italic",
conflicts_with = "a_not_italic",
title = _("Links always italic"), title = _("Links always italic"),
css = [[a, a * { font-style: italic !important; }]], css = [[a, a * { font-style: italic !important; }]],
}, },
{ {
id = "a_not_italic", id = "a_not_italic",
conflicts_with = "a_italic",
title = _("Links never italic"), title = _("Links never italic"),
css = [[a, a * { font-style: normal !important; }]], css = [[a, a * { font-style: normal !important; }]],
separator = true, separator = true,
}, },
{ {
id = "a_underline", id = "a_underline",
conflicts_with = "a_not_underline",
title = _("Links always underlined"), title = _("Links always underlined"),
css = [[a[href], a[href] * { text-decoration: underline !important; }]], css = [[a[href], a[href] * { text-decoration: underline !important; }]],
-- Have it apply only on real links with a href=, not on anchors -- Have it apply only on real links with a href=, not on anchors
}, },
{ {
id = "a_not_underline", id = "a_not_underline",
conflicts_with = "a_underline",
title = _("Links never underlined"), title = _("Links never underlined"),
css = [[a, a * { text-decoration: none !important; }]], css = [[a, a * { text-decoration: none !important; }]],
}, },
@ -816,6 +853,8 @@ body[name="comments"] > section
}, },
{ {
id = "footnote-inpage_epub", id = "footnote-inpage_epub",
conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_") end,
global_conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_epub") end,
title = _("In-page EPUB footnotes"), title = _("In-page EPUB footnotes"),
description = _([[ description = _([[
Show EPUB footnote text at the bottom of pages that contain links to them. Show EPUB footnote text at the bottom of pages that contain links to them.
@ -839,6 +878,8 @@ This only works with footnotes that have specific attributes set by the publishe
}, },
{ {
id = "footnote-inpage_epub_smaller", id = "footnote-inpage_epub_smaller",
conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_") end,
global_conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_epub") end,
title = _("In-page EPUB footnotes (smaller)"), title = _("In-page EPUB footnotes (smaller)"),
description = _([[ description = _([[
Show EPUB footnote text at the bottom of pages that contain links to them. Show EPUB footnote text at the bottom of pages that contain links to them.
@ -865,6 +906,8 @@ This only works with footnotes that have specific attributes set by the publishe
}, },
{ {
id = "footnote-inpage_wikipedia", id = "footnote-inpage_wikipedia",
conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_") end,
global_conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_wikipedia") end,
title = _("In-page Wikipedia footnotes"), title = _("In-page Wikipedia footnotes"),
description = _([[Show footnotes at the bottom of pages in Wikipedia EPUBs.]]), description = _([[Show footnotes at the bottom of pages in Wikipedia EPUBs.]]),
css = [[ css = [[
@ -880,6 +923,8 @@ ol.references > li > .mw-cite-backlink { display: none; }
}, },
{ {
id = "footnote-inpage_wikipedia_smaller", id = "footnote-inpage_wikipedia_smaller",
conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_") end,
global_conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_wikipedia") end,
title = _("In-page Wikipedia footnotes (smaller)"), title = _("In-page Wikipedia footnotes (smaller)"),
description = _([[Show footnotes at the bottom of pages in Wikipedia EPUBs.]]), description = _([[Show footnotes at the bottom of pages in Wikipedia EPUBs.]]),
css = [[ css = [[
@ -900,6 +945,8 @@ ol.references > li > .mw-cite-backlink { display: none; }
-- usually random across books). -- usually random across books).
{ {
id = "footnote-inpage_classic_classnames", id = "footnote-inpage_classic_classnames",
conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_") end,
global_conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_classic_classnames") end,
title = _("In-page classic classname footnotes"), title = _("In-page classic classname footnotes"),
description = _([[ description = _([[
Show footnotes with classic classnames at the bottom of pages. Show footnotes with classic classnames at the bottom of pages.
@ -918,6 +965,8 @@ This tweak can be duplicated as a user style tweak when books contain footnotes
}, },
{ {
id = "footnote-inpage_classic_classnames_smaller", id = "footnote-inpage_classic_classnames_smaller",
conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_") end,
global_conflicts_with = function(id) return util.stringStartsWith(id, "footnote-inpage_classic_classnames") end,
title = _("In-page classic classname footnotes (smaller)"), title = _("In-page classic classname footnotes (smaller)"),
description = _([[ description = _([[
Show footnotes with classic classnames at the bottom of pages. Show footnotes with classic classnames at the bottom of pages.

Loading…
Cancel
Save