forked from akai/readest
@@ -13,7 +13,12 @@ import { usePagination } from '../hooks/usePagination';
|
||||
import { useFoliateEvents } from '../hooks/useFoliateEvents';
|
||||
import { useProgressSync } from '../hooks/useProgressSync';
|
||||
import { useProgressAutoSave } from '../hooks/useProgressAutoSave';
|
||||
import { applyTranslationStyles, getStyles, transformStylesheet } from '@/utils/style';
|
||||
import {
|
||||
applyImageStyle,
|
||||
applyTranslationStyle,
|
||||
getStyles,
|
||||
transformStylesheet,
|
||||
} from '@/utils/style';
|
||||
import { mountAdditionalFonts } from '@/utils/font';
|
||||
import { getBookDirFromLanguage, getBookDirFromWritingMode } from '@/utils/book';
|
||||
import { useUICSS } from '@/hooks/useUICSS';
|
||||
@@ -129,6 +134,8 @@ const FoliateViewer: React.FC<{
|
||||
|
||||
mountAdditionalFonts(detail.doc, isCJKLang(bookData.book?.primaryLanguage));
|
||||
|
||||
applyImageStyle(detail.doc);
|
||||
|
||||
// Inline scripts in tauri platforms are not executed by default
|
||||
if (viewSettings.allowScript && isTauriAppPlatform()) {
|
||||
evalInlineScripts(detail.doc);
|
||||
@@ -242,7 +249,7 @@ const FoliateViewer: React.FC<{
|
||||
const height = viewHeight - insets.top - insets.bottom;
|
||||
book.transformTarget?.addEventListener('data', getDocTransformHandler({ width, height }));
|
||||
view.renderer.setStyles?.(getStyles(viewSettings));
|
||||
applyTranslationStyles(viewSettings);
|
||||
applyTranslationStyle(viewSettings);
|
||||
|
||||
const animated = viewSettings.animated!;
|
||||
const maxColumnCount = viewSettings.maxColumnCount!;
|
||||
|
||||
@@ -84,7 +84,24 @@ export const getPosition = (
|
||||
const [sx, , , sy] = match?.[1]?.split(/\s*,\s*/)?.map((x) => parseFloat(x)) ?? [];
|
||||
|
||||
const frame = frameElement?.getBoundingClientRect() ?? { top: 0, left: 0 };
|
||||
const rects = Array.from(target.getClientRects());
|
||||
let padding = { top: 0, right: 0, bottom: 0, left: 0 };
|
||||
if ('nodeType' in target && target.nodeType === 1) {
|
||||
const computedStyle = window.getComputedStyle(target);
|
||||
padding = {
|
||||
top: parseInt(computedStyle.paddingTop, 10) || 0,
|
||||
right: parseInt(computedStyle.paddingRight, 10) || 0,
|
||||
bottom: parseInt(computedStyle.paddingBottom, 10) || 0,
|
||||
left: parseInt(computedStyle.paddingLeft, 10) || 0,
|
||||
};
|
||||
}
|
||||
const rects = Array.from(target.getClientRects()).map((rect) => {
|
||||
return {
|
||||
top: rect.top + padding.top,
|
||||
right: rect.right - padding.right,
|
||||
bottom: rect.bottom - padding.bottom,
|
||||
left: rect.left + padding.left,
|
||||
};
|
||||
});
|
||||
const first = frameRect(frame, rects[0], sx, sy);
|
||||
const last = frameRect(frame, rects.at(-1), sx, sy);
|
||||
|
||||
|
||||
@@ -211,6 +211,11 @@ const getLayoutStyles = (
|
||||
width: auto;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
/* enlarge the clickable area of links */
|
||||
a {
|
||||
padding: 10px;
|
||||
margin: -10px;
|
||||
}
|
||||
p, blockquote, dd, div:not(:has(*:not(b, a, em, i, strong, u, span))) {
|
||||
line-height: ${lineSpacing} ${overrideLayout ? '!important' : ''};
|
||||
word-spacing: ${wordSpacing}px ${overrideLayout ? '!important' : ''};
|
||||
@@ -286,13 +291,12 @@ const getLayoutStyles = (
|
||||
}
|
||||
|
||||
/* inline images without dimension */
|
||||
p > img, span > img, sup img {
|
||||
sup img {
|
||||
height: 1em;
|
||||
}
|
||||
p:has(> img:only-child) img, span:has(> img:only-child) img,
|
||||
p:has(> a:first-child + img:last-child) img,
|
||||
span:has(> a:first-child + img:last-child) img {
|
||||
height: auto;
|
||||
img.has-text-siblings {
|
||||
height: 1em;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
.ie6 img {
|
||||
width: auto;
|
||||
@@ -328,6 +332,8 @@ export const getFootnoteStyles = () => `
|
||||
|
||||
a:any-link {
|
||||
text-decoration: none;
|
||||
padding: unset;
|
||||
margin: unset;
|
||||
}
|
||||
|
||||
ol {
|
||||
@@ -446,8 +452,8 @@ export const getStyles = (viewSettings: ViewSettings, themeCode?: ThemeCode) =>
|
||||
return `${layoutStyles}\n${fontStyles}\n${colorStyles}\n${translationStyles}\n${userStylesheet}`;
|
||||
};
|
||||
|
||||
export const applyTranslationStyles = (viewSettings: ViewSettings) => {
|
||||
const styleId = 'translation-styles';
|
||||
export const applyTranslationStyle = (viewSettings: ViewSettings) => {
|
||||
const styleId = 'translation-style';
|
||||
|
||||
const existingStyle = document.getElementById(styleId);
|
||||
if (existingStyle) {
|
||||
@@ -509,3 +515,16 @@ export const transformStylesheet = (vw: number, vh: number, css: string) => {
|
||||
.replace(/[\s;]color\s*:\s*rgb\(0,\s*0,\s*0\)/gi, 'color: var(--theme-fg-color)');
|
||||
return css;
|
||||
};
|
||||
|
||||
export const applyImageStyle = (document: Document) => {
|
||||
document.querySelectorAll('img').forEach((img) => {
|
||||
const parent = img.parentNode;
|
||||
if (!parent || parent.nodeType !== Node.ELEMENT_NODE) return;
|
||||
const hasTextSiblings = Array.from(parent.childNodes).some(
|
||||
(node) => node.nodeType === Node.TEXT_NODE && node.textContent?.trim(),
|
||||
);
|
||||
if (hasTextSiblings) {
|
||||
img.classList.add('has-text-siblings');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user