mirror of https://github.com/koreader/koreader
Style tweaks: use css snippets to tweak book styles (#3944)
Adds a new menu "Style tweaks", with a few CSS snippets that can make some things better with some books.pull/3946/head
parent
a9905c5129
commit
5b7664b064
@ -0,0 +1,514 @@
|
||||
local Blitbuffer = require("ffi/blitbuffer")
|
||||
local ButtonTable = require("ui/widget/buttontable")
|
||||
local CenterContainer = require("ui/widget/container/centercontainer")
|
||||
local CssTweaks = require("ui/data/css_tweaks")
|
||||
local DataStorage = require("datastorage")
|
||||
local Device = require("device")
|
||||
local Event = require("ui/event")
|
||||
local Font = require("ui/font")
|
||||
local FrameContainer = require("ui/widget/container/framecontainer")
|
||||
local Geom = require("ui/geometry")
|
||||
local GestureRange = require("ui/gesturerange")
|
||||
local InfoMessage = require("ui/widget/infomessage")
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
local MovableContainer = require("ui/widget/container/movablecontainer")
|
||||
local Size = require("ui/size")
|
||||
local TextBoxWidget = require("ui/widget/textboxwidget")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local VerticalGroup = require("ui/widget/verticalgroup")
|
||||
local VerticalSpan = require("ui/widget/verticalspan")
|
||||
local lfs = require("libs/libkoreader-lfs")
|
||||
local logger = require("logger")
|
||||
local util = require("util")
|
||||
local _ = require("gettext")
|
||||
local Screen = Device.screen
|
||||
local T = require("ffi/util").template
|
||||
|
||||
-- Simple widget for showing tweak info
|
||||
local TweakInfoWidget = InputContainer:new{
|
||||
tweak = nil,
|
||||
is_global_default = nil,
|
||||
toggle_global_default_callback = function() end,
|
||||
modal = true,
|
||||
width = Screen:getWidth()*3/4,
|
||||
}
|
||||
|
||||
function TweakInfoWidget:init()
|
||||
local tweak = self.tweak
|
||||
if Device:isTouchDevice() then
|
||||
self.ges_events.TapClose = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
if Device:hasKeys() then
|
||||
self.key_events = {
|
||||
Close = { {"Back"}, doc = "cancel" }
|
||||
}
|
||||
end
|
||||
|
||||
local content = VerticalGroup:new{
|
||||
TextBoxWidget:new{
|
||||
text = tweak.title,
|
||||
bold = true,
|
||||
face = Font:getFace("infofont"),
|
||||
width = self.width,
|
||||
},
|
||||
VerticalSpan:new{
|
||||
width = Size.padding.large,
|
||||
},
|
||||
}
|
||||
if tweak.description then
|
||||
table.insert(content,
|
||||
TextBoxWidget:new{
|
||||
text = tweak.description,
|
||||
face = Font:getFace("smallinfofont"),
|
||||
width = self.width,
|
||||
}
|
||||
)
|
||||
table.insert(content, VerticalSpan:new{
|
||||
width = Size.padding.large,
|
||||
})
|
||||
end
|
||||
|
||||
-- This css TextBoxWidget may make the widget overflow screen with
|
||||
-- large css text. For now, we don't bother with the complicated
|
||||
-- setup of a scrollable ScrollTextWidget.
|
||||
local css = tweak.css
|
||||
if not css and tweak.css_path then
|
||||
css = ""
|
||||
local f = io.open(tweak.css_path, "r")
|
||||
if f then
|
||||
css = f:read("*all")
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
css = css:gsub("^%s+", ""):gsub("%s+$", "")
|
||||
table.insert(content, FrameContainer:new{
|
||||
bordersize = Size.border.thin,
|
||||
padding = Size.padding.large,
|
||||
TextBoxWidget:new{
|
||||
text = css,
|
||||
face = Font:getFace("infont", 16),
|
||||
width = self.width - 2*Size.padding.large,
|
||||
}
|
||||
})
|
||||
if self.is_global_default then
|
||||
table.insert(content, VerticalSpan:new{
|
||||
width = Size.padding.large,
|
||||
})
|
||||
table.insert(content,
|
||||
TextBoxWidget:new{
|
||||
text = _("This tweak is applied on all books."),
|
||||
face = Font:getFace("smallinfofont"),
|
||||
width = self.width,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
content = FrameContainer:new{
|
||||
bordersize = 0,
|
||||
padding = Size.padding.large,
|
||||
padding_top = Size.padding.default,
|
||||
content,
|
||||
}
|
||||
|
||||
local buttons = {
|
||||
{
|
||||
text = _("Close"),
|
||||
callback = function()
|
||||
UIManager:close(self)
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = self.is_global_default and _("Don't use on all books") or _("Use on all books"),
|
||||
callback = function()
|
||||
self.toggle_global_default_callback()
|
||||
UIManager:close(self)
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
local button_table = ButtonTable:new{
|
||||
width = content:getSize().w,
|
||||
button_font_face = "cfont",
|
||||
button_font_size = 20,
|
||||
buttons = { buttons },
|
||||
zero_sep = true,
|
||||
show_parent = self,
|
||||
}
|
||||
|
||||
self.movable = MovableContainer:new{
|
||||
FrameContainer:new{
|
||||
background = Blitbuffer.COLOR_WHITE,
|
||||
radius = Size.radius.window,
|
||||
margin = Size.margin.default,
|
||||
padding = Size.padding.default,
|
||||
padding_bottom = 0, -- no padding below buttontable
|
||||
VerticalGroup:new{
|
||||
align = "left",
|
||||
content,
|
||||
button_table,
|
||||
}
|
||||
}
|
||||
}
|
||||
self[1] = CenterContainer:new{
|
||||
dimen = Screen:getSize(),
|
||||
self.movable
|
||||
}
|
||||
end
|
||||
|
||||
function TweakInfoWidget:onShow()
|
||||
UIManager:setDirty(self, function()
|
||||
return "ui", self.movable.dimen
|
||||
end)
|
||||
end
|
||||
|
||||
function TweakInfoWidget:onCloseWidget()
|
||||
UIManager:setDirty(nil, function()
|
||||
return "ui", self.movable.dimen
|
||||
end)
|
||||
end
|
||||
|
||||
function TweakInfoWidget:onClose()
|
||||
UIManager:close(self)
|
||||
return true
|
||||
end
|
||||
|
||||
function TweakInfoWidget:onTapClose(arg, ges)
|
||||
if ges.pos:notIntersectWith(self.movable.dimen) then
|
||||
self:onClose()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function TweakInfoWidget:onSelect()
|
||||
if self.selected.x == 1 then
|
||||
self:toggle_global_default_callback()
|
||||
end
|
||||
UIManager:close(self)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Ordering function for tweaks when appened to css_test.
|
||||
-- The order needs to be consistent for crengine's stylesheet change
|
||||
-- detection code to not invalidate cache across loadings.
|
||||
local function tweakOrdering(l, r)
|
||||
if l.priority ~= r.priority then
|
||||
-- lower priority first in the CSS text
|
||||
return l.priority < r.priority
|
||||
end
|
||||
-- same priority: order by ids
|
||||
return l.id < r.id
|
||||
end
|
||||
|
||||
-- Reader component for managing tweaks. The aggregated css_text
|
||||
-- is actually requested from us and applied by ReaderTypeset
|
||||
local ReaderStyleTweak = InputContainer:new{
|
||||
tweaks_by_id = nil,
|
||||
tweaks_table = nil, -- sub-menu items
|
||||
nb_enabled_tweaks = 0, -- for use by main menu item
|
||||
css_text = nil, -- aggregated css text from tweaks individual css snippets
|
||||
enabled = true, -- allows for toggling between selected tweaks / none
|
||||
}
|
||||
|
||||
function ReaderStyleTweak:isTweakEnabled(tweak_id)
|
||||
local g_enabled = false
|
||||
local enabled = false
|
||||
if self.global_tweaks[tweak_id] then
|
||||
enabled = true
|
||||
g_enabled = true
|
||||
end
|
||||
if self.doc_tweaks[tweak_id] == true then
|
||||
enabled = true
|
||||
elseif self.doc_tweaks[tweak_id] == false then
|
||||
enabled = false
|
||||
end
|
||||
return enabled, g_enabled
|
||||
end
|
||||
|
||||
function ReaderStyleTweak:nbTweaksEnabled(sub_item_table)
|
||||
local nb_enabled = 0
|
||||
local nb_found = 0
|
||||
for _, item in ipairs(sub_item_table) do
|
||||
if item.sub_item_table then
|
||||
local sub_nb_enabled, sub_nb_found = self:nbTweaksEnabled(item.sub_item_table)
|
||||
nb_enabled = nb_enabled + sub_nb_enabled
|
||||
nb_found = nb_found + sub_nb_found
|
||||
elseif item.tweak_id then
|
||||
if self:isTweakEnabled(item.tweak_id) then
|
||||
nb_enabled = nb_enabled + 1
|
||||
end
|
||||
nb_found = nb_found + 1
|
||||
end
|
||||
end
|
||||
return nb_enabled, nb_found
|
||||
end
|
||||
|
||||
-- Called by ReaderTypeset, returns the already built string
|
||||
function ReaderStyleTweak:getCssText()
|
||||
return self.css_text
|
||||
end
|
||||
|
||||
-- Build css_text, and request ReaderTypeset to apply it if wanted
|
||||
function ReaderStyleTweak:updateCssText(apply)
|
||||
if self.enabled then
|
||||
local tweaks = {}
|
||||
for id, enabled in pairs(self.global_tweaks) do
|
||||
-- there are only enabled tweaks in global_tweaks, but we don't
|
||||
-- use them if they are disabled in doc_tweaks
|
||||
if self.doc_tweaks[id] ~= false then
|
||||
table.insert(tweaks, self.tweaks_by_id[id])
|
||||
end
|
||||
end
|
||||
for id, enabled in pairs(self.doc_tweaks) do
|
||||
-- there are enabled (true) and disabled (false) tweaks in doc_tweaks
|
||||
if self.doc_tweaks[id] == true then
|
||||
table.insert(tweaks, self.tweaks_by_id[id])
|
||||
end
|
||||
end
|
||||
table.sort(tweaks, tweakOrdering)
|
||||
self.nb_enabled_tweaks = 0
|
||||
local css_snippets = {}
|
||||
for _, tweak in ipairs(tweaks) do
|
||||
self.nb_enabled_tweaks = self.nb_enabled_tweaks + 1
|
||||
local css = tweak.css
|
||||
if not css and tweak.css_path then
|
||||
css = ""
|
||||
local f = io.open(tweak.css_path, "r")
|
||||
if f then
|
||||
css = f:read("*all")
|
||||
f:close()
|
||||
end
|
||||
-- We could store what's been read into tweak.css to avoid
|
||||
-- re-reading it, but this will allow a user to experiment
|
||||
-- wihout having to restart KOReader
|
||||
end
|
||||
css = css:gsub("^%s+", ""):gsub("%s+$", "")
|
||||
table.insert(css_snippets, css)
|
||||
end
|
||||
self.css_text = table.concat(css_snippets, "\n")
|
||||
logger.dbg("made tweak css:\n".. self.css_text .. "[END]")
|
||||
else
|
||||
self.css_text = nil
|
||||
logger.dbg("made no tweak css (Style tweaks disabled)")
|
||||
end
|
||||
if apply then
|
||||
self.ui:handleEvent(Event:new("ApplyStyleSheet"))
|
||||
end
|
||||
end
|
||||
|
||||
function ReaderStyleTweak:onReadSettings(config)
|
||||
self.enabled = not (config:readSetting("style_tweaks_enabled") == false)
|
||||
self.doc_tweaks = config:readSetting("style_tweaks") or {}
|
||||
self.global_tweaks = G_reader_settings:readSetting("style_tweaks") or {}
|
||||
self:updateCssText()
|
||||
end
|
||||
|
||||
function ReaderStyleTweak:onSaveSettings()
|
||||
if self.enabled then
|
||||
self.ui.doc_settings:delSetting("style_tweaks_enabled")
|
||||
else
|
||||
self.ui.doc_settings:saveSetting("style_tweaks_enabled", false)
|
||||
end
|
||||
self.ui.doc_settings:saveSetting("style_tweaks", util.tableSize(self.doc_tweaks) > 0 and self.doc_tweaks or nil)
|
||||
G_reader_settings:saveSetting("style_tweaks", util.tableSize(self.global_tweaks) > 0 and self.global_tweaks or nil)
|
||||
end
|
||||
|
||||
function ReaderStyleTweak:init()
|
||||
self.tweaks_by_id = {}
|
||||
self.tweaks_table = {}
|
||||
|
||||
-- Add first item of sub-menu, that allows toggling between
|
||||
-- enabled tweaks / none (without the need to disable each of
|
||||
-- them)
|
||||
table.insert(self.tweaks_table, {
|
||||
text = _("Enable style tweaks (hold for info)"),
|
||||
checked_func = function() return self.enabled end,
|
||||
callback = function()
|
||||
self.enabled = not self.enabled
|
||||
self:updateCssText(true) -- apply it immediately
|
||||
end,
|
||||
hold_may_update_menu = true, -- just to keep menu opened
|
||||
hold_callback = function()
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _([[
|
||||
Style tweaks allow changing small parts of book styles (including the publisher/embedded styles) to make visual adjustments or disable unwanted publisher layout choices.
|
||||
|
||||
Some tweaks may be useful with some books, while resulting in undesirable effects with others.
|
||||
|
||||
You can enable individual tweaks on this book with a tap, or view more details about a tweak and enable it on all books with hold.]])
|
||||
})
|
||||
end,
|
||||
separator = true,
|
||||
})
|
||||
|
||||
-- Single function for use as enabled_func
|
||||
local is_enabled = function() return self.enabled end
|
||||
|
||||
-- Generic function to recursively build a sub_item_table (as expected
|
||||
-- by TouchMenu) from a table of tweak definitions (like CssTweaks from
|
||||
-- css_tweaks.lua, or like the one we build from user styletweaks
|
||||
-- directory files and sub-directories)
|
||||
local addTweakMenuItem
|
||||
addTweakMenuItem = function(menu, item)
|
||||
if type(item) == "table" and #item > 0 then -- sub-menu
|
||||
local sub_item_table = {}
|
||||
for _, it in ipairs(item) do
|
||||
addTweakMenuItem(sub_item_table, it) -- recurse
|
||||
end
|
||||
table.insert(menu, {
|
||||
text_func = function()
|
||||
local text = item.title or "### undefined submenu title ###"
|
||||
local nb_enabled, nb_found = self:nbTweaksEnabled(sub_item_table) -- luacheck: no unused
|
||||
-- We could add nb_enabled/nb_found, but that makes for
|
||||
-- a busy/ugly menu
|
||||
-- text = string.format("%s (%d/%d)", text, nb_enabled, nb_found)
|
||||
if nb_enabled > 0 then
|
||||
text = string.format("%s (%d)", text, nb_enabled)
|
||||
end
|
||||
return text
|
||||
end,
|
||||
enabled_func = is_enabled,
|
||||
sub_item_table = sub_item_table,
|
||||
})
|
||||
elseif item.id then -- tweak menu item
|
||||
-- Set a default priority of 0 if item doesn't have one
|
||||
if not item.priority then item.priority = 0 end
|
||||
self.tweaks_by_id[item.id] = item
|
||||
table.insert(menu, {
|
||||
tweak_id = item.id,
|
||||
enabled_func = is_enabled,
|
||||
checked_func = function() return self:isTweakEnabled(item.id) end,
|
||||
-- text = item.title or "### undefined tweak title ###",
|
||||
text_func = function()
|
||||
local title = item.title or "### undefined tweak title ###"
|
||||
if self.global_tweaks[item.id] then
|
||||
title = title .. " ★"
|
||||
end
|
||||
return title
|
||||
end,
|
||||
hold_may_update_menu = true,
|
||||
hold_callback = function(refresh_menu_func)
|
||||
UIManager:show(TweakInfoWidget:new{
|
||||
tweak = item,
|
||||
is_global_default = self.global_tweaks[item.id],
|
||||
toggle_global_default_callback = function()
|
||||
if self.global_tweaks[item.id] then
|
||||
self.global_tweaks[item.id] = nil
|
||||
else
|
||||
self.global_tweaks[item.id] = true
|
||||
end
|
||||
refresh_menu_func()
|
||||
self:updateCssText(true) -- apply it immediately
|
||||
end
|
||||
})
|
||||
end,
|
||||
callback = function()
|
||||
-- enable/disable only for this book
|
||||
local enabled, g_enabled = self:isTweakEnabled(item.id)
|
||||
if enabled then
|
||||
if g_enabled then
|
||||
-- if globaly enabled, mark it as disabled
|
||||
-- for this document only
|
||||
self.doc_tweaks[item.id] = false
|
||||
else
|
||||
self.doc_tweaks[item.id] = nil
|
||||
end
|
||||
else
|
||||
self.doc_tweaks[item.id] = true
|
||||
end
|
||||
self:updateCssText(true) -- apply it immediately
|
||||
end,
|
||||
separator = item.separator,
|
||||
})
|
||||
else
|
||||
table.insert(menu, {
|
||||
text = item.if_empty_menu_title or _("This section is empty"),
|
||||
enabled = false,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Add each of CssTweaks' top-level items as a sub-menu
|
||||
for _, item in ipairs(CssTweaks) do
|
||||
addTweakMenuItem(self.tweaks_table, item)
|
||||
end
|
||||
|
||||
-- Users can put their own style tweaks as individual .css files into
|
||||
-- koreader/styletweaks/ directory. These can be organized into
|
||||
-- sub-directories that will show up as sub-menus.
|
||||
local user_styletweaks_dir = DataStorage:getDataDir() .. "/styletweaks"
|
||||
local user_tweaks_table = { title = _("User style tweaks") }
|
||||
|
||||
-- Build a tweak definition table from the content of a directory
|
||||
local process_tweaks_dir
|
||||
process_tweaks_dir = function(dir, item_table, if_empty_menu_title)
|
||||
local file_list = {}
|
||||
local dir_list = {}
|
||||
if lfs.attributes(dir, "mode") == "directory" then
|
||||
for f in lfs.dir(dir) do
|
||||
if f ~= "." and f ~= ".." then
|
||||
local mode = lfs.attributes(dir.."/"..f, "mode")
|
||||
if mode == "directory" then
|
||||
table.insert(dir_list, f)
|
||||
elseif mode == "file" and string.match(f, "%.css$") then
|
||||
table.insert(file_list, f)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(dir_list)
|
||||
table.sort(file_list)
|
||||
for __, subdir in ipairs(dir_list) do
|
||||
local sub_item_table = { title = subdir:gsub("_", " ") }
|
||||
process_tweaks_dir(dir.."/"..subdir, sub_item_table)
|
||||
table.insert(item_table, sub_item_table)
|
||||
end
|
||||
for __, file in ipairs(file_list) do
|
||||
local title = file:gsub("%.css$", ""):gsub("_", " ")
|
||||
local filepath = dir.."/"..file
|
||||
table.insert(item_table, {
|
||||
title = title,
|
||||
id = file, -- keep ".css" in id, to distinguish between koreader/user tweaks
|
||||
description = T(_("User style tweak at %1"), filepath),
|
||||
priority = 10, -- give user tweaks a higher priority
|
||||
css_path = filepath,
|
||||
})
|
||||
end
|
||||
if #item_table == 0 then
|
||||
table.insert(item_table, {
|
||||
if_empty_menu_title = if_empty_menu_title or _("No CSS tweak found in this directory"),
|
||||
})
|
||||
end
|
||||
end
|
||||
local if_empty_menu_title = _("Add your own tweaks in koreader/styletweaks/")
|
||||
process_tweaks_dir(user_styletweaks_dir, user_tweaks_table, if_empty_menu_title)
|
||||
self.tweaks_table[#self.tweaks_table].separator = true
|
||||
addTweakMenuItem(self.tweaks_table, user_tweaks_table)
|
||||
|
||||
self.ui.menu:registerToMainMenu(self)
|
||||
end
|
||||
|
||||
function ReaderStyleTweak:addToMainMenu(menu_items)
|
||||
-- insert table to main reader menu
|
||||
menu_items.style_tweaks = {
|
||||
text_func = function()
|
||||
if self.enabled and self.nb_enabled_tweaks > 0 then
|
||||
return T(_("Style tweaks (%1)"), self.nb_enabled_tweaks)
|
||||
else
|
||||
return _("Style tweaks")
|
||||
end
|
||||
end,
|
||||
sub_item_table = self.tweaks_table,
|
||||
}
|
||||
end
|
||||
|
||||
return ReaderStyleTweak
|
@ -0,0 +1,158 @@
|
||||
--[[--
|
||||
CSS tweaks must have the following attributes:
|
||||
- id: unique ID identifying this tweak, to be stored in settings
|
||||
- title: menu item title (must not be too long)
|
||||
- css: stylesheet text to append to external stylesheet
|
||||
They may have the following optional attributes:
|
||||
- description: text displayed when holding on menu item
|
||||
- priority: higher numbers are appended after lower numbers
|
||||
(if not specified, default to 0)
|
||||
]]
|
||||
|
||||
local _ = require("gettext")
|
||||
|
||||
local CssTweaks = {
|
||||
{
|
||||
title = _("Page"),
|
||||
{
|
||||
id = "margin_body_0";
|
||||
title = _("Ignore publisher page margins"),
|
||||
description = _("Force page margins to be 0, and may allow KOReader's margin settings to work on books where they would not."),
|
||||
css = [[body { margin: 0 !important; }]],
|
||||
},
|
||||
{
|
||||
id = "margin_all_0";
|
||||
title = _("Ignore all publisher margins"),
|
||||
priority = 2,
|
||||
css = [[* { margin: 0 !important; }]],
|
||||
},
|
||||
{
|
||||
id = "titles_page-break-before_avoid ";
|
||||
title = _("Avoid blank page on chapter start"),
|
||||
css = [[h1, h2, h3, .title, .title1, .title2, .title3 { page-break-before: avoid !important; }]],
|
||||
},
|
||||
},
|
||||
{
|
||||
title = _("Text"),
|
||||
{
|
||||
id = "sub_sup_smaller";
|
||||
title = _("Smaller sub- and superscript"),
|
||||
description = _("Prevent sub- and superscript from affecting line-height."),
|
||||
-- https://friendsofepub.github.io/eBookTricks/
|
||||
-- https://github.com/koreader/koreader/issues/3923#issuecomment-386510294
|
||||
css = [[
|
||||
sup { font-size: 50%; vertical-align: super; }
|
||||
sub { font-size: 50%; vertical-align: middle; }
|
||||
]],
|
||||
separator = true,
|
||||
},
|
||||
{
|
||||
id = "lineheight_all_inherit";
|
||||
title = _("Ignore publisher line heights"),
|
||||
description = _("Disable line-height specified in embedded styles, and may allow KOReader's line spacing settings to work on books where they would not."),
|
||||
css = [[* { line-height: inherit !important; }]],
|
||||
},
|
||||
{
|
||||
id = "font_family_all_inherit";
|
||||
title = _("Ignore publisher font families"),
|
||||
description = _("Disable font-family specified in embedded styles."),
|
||||
-- we have to use this trick, font-family handling by crengine is a bit complex
|
||||
css = [[* { font-family: "NoSuchFont" !important; }]],
|
||||
},
|
||||
{
|
||||
id = "font_size_all_inherit";
|
||||
title = _("Ignore publisher font sizes"),
|
||||
description = _("Disable font-size specified in embedded styles."),
|
||||
css = [[* { font-size: inherit !important; }]],
|
||||
separator = true,
|
||||
},
|
||||
{
|
||||
title = _("Links color and weight"),
|
||||
{
|
||||
id = "a_black";
|
||||
title = _("Links always black"),
|
||||
css = [[a { color: black !important; }]],
|
||||
},
|
||||
{
|
||||
id = "a_blue";
|
||||
title = _("Links always blue"),
|
||||
css = [[a { color: blue !important; }]],
|
||||
separator = true,
|
||||
},
|
||||
{
|
||||
id = "a_bold";
|
||||
title = _("Links always bold"),
|
||||
css = [[a { font-weight: bold !important; }]],
|
||||
},
|
||||
{
|
||||
id = "a_not_bold";
|
||||
title = _("Links never bold"),
|
||||
css = [[a { font-weight: normal !important; }]],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title = _("Miscellaneous"),
|
||||
{
|
||||
id = "table_row_odd_even";
|
||||
title = _("Alternate background color of table rows"),
|
||||
css = [[
|
||||
tr:nth-child(odd) { background-color: #EEE !important; }
|
||||
tr:nth-child(even) { background-color: #CCC !important; }
|
||||
]],
|
||||
},
|
||||
{
|
||||
id = "table_force_border";
|
||||
title = _("Show borders on all tables"),
|
||||
css = [[
|
||||
table, tcaption, tr, th, td { border: black solid 1px; border-collapse: collapse; }
|
||||
]],
|
||||
separator = true,
|
||||
},
|
||||
{
|
||||
id = "image_full_width";
|
||||
title = _("Make images full width"),
|
||||
description = _("Useful for books containing only images, when they are smaller than your screen. May stretch images in some cases."),
|
||||
-- This helped me once with a book. Will mess with aspect ratio
|
||||
-- when images have a style="width: NNpx; heigh: NNpx"
|
||||
css = [[
|
||||
img {
|
||||
text-align: center !important;
|
||||
text-indent: 0px !important;
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
]],
|
||||
},
|
||||
},
|
||||
{
|
||||
title = _("Workarounds"),
|
||||
{
|
||||
id = "html_tags_fix";
|
||||
title = _("Fix some HTML elements"),
|
||||
description = _("Make some HTML elements (eg: <cite>) behave as they should (inline/block).\nThis may break past bookmarks and highlights."),
|
||||
css = [[
|
||||
cite { display: inline; font-style: italic; }
|
||||
]],
|
||||
},
|
||||
{
|
||||
id = "list_items_fix";
|
||||
title = _("Fix some list items issues"),
|
||||
description = _("Work around some crengine list items rendering issues."),
|
||||
css = [[
|
||||
li > p:first-child { display: inline !important; }
|
||||
li > div:first-child { display: inline !important; }
|
||||
]],
|
||||
},
|
||||
{
|
||||
id = "border_all_none";
|
||||
title = _("Remove all borders"),
|
||||
description = _("Work around a crengine bug that makes a border drawn when {border: black solid 0px}."),
|
||||
-- css = [[* { border-style: none !important; }]],
|
||||
-- Better to keep the layout implied by width, just draw them in white
|
||||
css = [[* { border-color: white !important; }]],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return CssTweaks
|
Loading…
Reference in New Issue