forked from akai/readest
213 lines
7.8 KiB
TypeScript
213 lines
7.8 KiB
TypeScript
import { MONOSPACE_FONTS, SANS_SERIF_FONTS, SERIF_FONTS } from '@/services/constants';
|
|
import { ViewSettings } from '@/types/book';
|
|
|
|
import fontfacesCSS from '!!raw-loader!../styles/fonts.css';
|
|
|
|
const getFontStyles = (
|
|
serif: string,
|
|
sansSerif: string,
|
|
monospace: string,
|
|
defaultFont: string,
|
|
fontSize: number,
|
|
overrideFont: boolean,
|
|
) => {
|
|
const serifFonts = [serif, ...SERIF_FONTS.filter((font) => font !== serif)];
|
|
const sansSerifFonts = [sansSerif, ...SANS_SERIF_FONTS.filter((font) => font !== sansSerif)];
|
|
const monospaceFonts = [monospace, ...MONOSPACE_FONTS.filter((font) => font !== monospace)];
|
|
const fontStyles = `
|
|
html {
|
|
--serif: ${serifFonts.map((font) => `"${font}"`).join(', ')}, serif;
|
|
--sans-serif: ${sansSerifFonts.map((font) => `"${font}"`).join(', ')}, sans-serif;
|
|
--monospace: ${monospaceFonts.map((font) => `"${font}"`).join(', ')}, monospace;
|
|
}
|
|
body {
|
|
font-family: var(${defaultFont.toLowerCase() === 'serif' ? '--serif' : '--sans-serif'}) ${overrideFont ? '!important' : ''};
|
|
font-size: ${fontSize}px ${overrideFont ? '!important' : ''};
|
|
}
|
|
body * {
|
|
font-family: revert ${overrideFont ? '!important' : ''};
|
|
font-family: inherit;
|
|
}
|
|
`;
|
|
return fontStyles;
|
|
};
|
|
|
|
const getAdditionalFontFaces = () => `
|
|
@font-face {
|
|
font-family: "FangSong";
|
|
font-display: swap;
|
|
src: local("Fang Song"), local("FangSong"), local("Noto Serif CJK"), url("https://db.onlinewebfonts.com/t/2ecbfe1d9bfc191c6f15c0ccc23cbd43.eot");
|
|
src: url("https://db.onlinewebfonts.com/t/2ecbfe1d9bfc191c6f15c0ccc23cbd43.eot?#iefix") format("embedded-opentype"),
|
|
url("https://db.onlinewebfonts.com/t/2ecbfe1d9bfc191c6f15c0ccc23cbd43.woff2") format("woff2"),
|
|
url("https://db.onlinewebfonts.com/t/2ecbfe1d9bfc191c6f15c0ccc23cbd43.woff") format("woff"),
|
|
url("https://db.onlinewebfonts.com/t/2ecbfe1d9bfc191c6f15c0ccc23cbd43.ttf") format("truetype"),
|
|
url("https://db.onlinewebfonts.com/t/2ecbfe1d9bfc191c6f15c0ccc23cbd43.svg#FangSong") format("svg");
|
|
}
|
|
@font-face {
|
|
font-family: "Kaiti";
|
|
font-display: swap;
|
|
src: local("Kai"), local("KaiTi"), local("AR PL UKai"), url("https://db.onlinewebfonts.com/t/1ee9941f1b8c128110ca4307dda59917.eot");
|
|
src: url("https://db.onlinewebfonts.com/t/1ee9941f1b8c128110ca4307dda59917.eot?#iefix")format("embedded-opentype"),
|
|
url("https://db.onlinewebfonts.com/t/1ee9941f1b8c128110ca4307dda59917.woff2")format("woff2"),
|
|
url("https://db.onlinewebfonts.com/t/1ee9941f1b8c128110ca4307dda59917.woff")format("woff"),
|
|
url("https://db.onlinewebfonts.com/t/1ee9941f1b8c128110ca4307dda59917.ttf")format("truetype"),
|
|
url("https://db.onlinewebfonts.com/t/1ee9941f1b8c128110ca4307dda59917.svg#STKaiti")format("svg");
|
|
}
|
|
@font-face {
|
|
font-family: "Heiti";
|
|
font-display: swap;
|
|
src: local("Hei"), local("SimHei"), local("WenQuanYi Zen Hei"), url("https://db.onlinewebfonts.com/t/a4948b9d43a91468825a5251df1ec58d.eot");
|
|
src: url("https://db.onlinewebfonts.com/t/a4948b9d43a91468825a5251df1ec58d.eot?#iefix")format("embedded-opentype"),
|
|
url("https://db.onlinewebfonts.com/t/a4948b9d43a91468825a5251df1ec58d.woff2")format("woff2"),
|
|
url("https://db.onlinewebfonts.com/t/a4948b9d43a91468825a5251df1ec58d.woff")format("woff"),
|
|
url("https://db.onlinewebfonts.com/t/a4948b9d43a91468825a5251df1ec58d.ttf")format("truetype"),
|
|
url("https://db.onlinewebfonts.com/t/a4948b9d43a91468825a5251df1ec58d.svg#WenQuanYi Micro Hei")format("svg");
|
|
}
|
|
@font-face {
|
|
font-family: "XiHeiti";
|
|
font-display: swap;
|
|
src: local("PingFang SC"), local("Microsoft YaHei"), local("WenQuanYi Micro Hei"), url("https://db.onlinewebfonts.com/t/4f0b783ba4a1b381fc7e7af81ecab481.eot");
|
|
src: url("https://db.onlinewebfonts.com/t/4f0b783ba4a1b381fc7e7af81ecab481.eot?#iefix")format("embedded-opentype"),
|
|
url("https://db.onlinewebfonts.com/t/4f0b783ba4a1b381fc7e7af81ecab481.woff2")format("woff2"),
|
|
url("https://db.onlinewebfonts.com/t/4f0b783ba4a1b381fc7e7af81ecab481.woff")format("woff"),
|
|
url("https://db.onlinewebfonts.com/t/4f0b783ba4a1b381fc7e7af81ecab481.ttf")format("truetype"),
|
|
url("https://db.onlinewebfonts.com/t/4f0b783ba4a1b381fc7e7af81ecab481.svg#STHeiti J Light")format("svg");
|
|
}
|
|
`;
|
|
|
|
const getLayoutStyles = (
|
|
spacing: number,
|
|
justify: boolean,
|
|
hyphenate: boolean,
|
|
zoomLevel: number,
|
|
writingMode: string,
|
|
bg: string,
|
|
fg: string,
|
|
primary: string,
|
|
) => `
|
|
@namespace epub "http://www.idpf.org/2007/ops";
|
|
html {
|
|
color-scheme: light dark;
|
|
color: ${fg};
|
|
}
|
|
a:any-link {
|
|
color: ${primary} ${bg === '#ffffff' ? '' : '!important'};
|
|
}
|
|
aside[epub|type~="footnote"] {
|
|
display: none;
|
|
}
|
|
/* https://github.com/whatwg/html/issues/5426 */
|
|
@media (prefers-color-scheme: dark) {
|
|
a:link {
|
|
color: lightblue;
|
|
}
|
|
}
|
|
|
|
html {
|
|
--theme-bg-color: ${bg};
|
|
--default-text-align: ${justify ? 'justify' : 'start'};
|
|
hanging-punctuation: allow-end last;
|
|
orphans: 2;
|
|
widows: 2;
|
|
}
|
|
[align="left"] { text-align: left; }
|
|
[align="right"] { text-align: right; }
|
|
[align="center"] { text-align: center; }
|
|
[align="justify"] { text-align: justify; }
|
|
:is(hgroup, header) p {
|
|
text-align: unset;
|
|
hyphens: unset;
|
|
}
|
|
pre {
|
|
white-space: pre-wrap !important;
|
|
tab-size: 2;
|
|
}
|
|
html[has-background], body[has-background] {
|
|
--background-set: var(--theme-bg-color);
|
|
}
|
|
html, body {
|
|
color: ${fg};
|
|
${writingMode === 'auto' ? '' : `writing-mode: ${writingMode};`}
|
|
text-align: var(--default-text-align);
|
|
background-color: var(--theme-bg-color, transparent);
|
|
background: var(--background-set, none);
|
|
}
|
|
body *:not(a):not(#b1):not(#b1 *):not(#b2):not(#b2 *):not(.bg):not(.bg *):not(.vol):not(.vol *):not(.background):not(.background *) {
|
|
border-color: currentColor !important;
|
|
${bg === '#ffffff' ? '' : `color: inherit;`}
|
|
${bg === '#ffffff' ? '' : `background-color: ${bg} !important;`}
|
|
}
|
|
body * {
|
|
zoom: ${zoomLevel};
|
|
}
|
|
svg, img {
|
|
background-color: transparent !important;
|
|
}
|
|
p, li, blockquote, dd {
|
|
line-height: ${spacing} !important;
|
|
text-align: inherit;
|
|
-webkit-hyphens: ${hyphenate ? 'auto' : 'manual'};
|
|
hyphens: ${hyphenate ? 'auto' : 'manual'};
|
|
-webkit-hyphenate-limit-before: 3;
|
|
-webkit-hyphenate-limit-after: 2;
|
|
-webkit-hyphenate-limit-lines: 2;
|
|
hanging-punctuation: allow-end last;
|
|
widows: 2;
|
|
}
|
|
/* prevent the above from overriding the align attribute */
|
|
[align="left"] { text-align: left; }
|
|
[align="right"] { text-align: right; }
|
|
[align="center"] { text-align: center; }
|
|
[align="justify"] { text-align: justify; }
|
|
|
|
pre {
|
|
white-space: pre-wrap !important;
|
|
}
|
|
aside[epub|type~="endnote"],
|
|
aside[epub|type~="footnote"],
|
|
aside[epub|type~="note"],
|
|
aside[epub|type~="rearnote"] {
|
|
display: none;
|
|
}
|
|
|
|
.duokan-footnote-content,
|
|
.duokan-footnote-item {
|
|
display: none;
|
|
}
|
|
`;
|
|
|
|
export interface ThemeCode {
|
|
bg: string;
|
|
fg: string;
|
|
primary: string;
|
|
}
|
|
|
|
export const getStyles = (viewSettings: ViewSettings, themeCode: ThemeCode) => {
|
|
const layoutStyles = getLayoutStyles(
|
|
viewSettings.lineHeight!,
|
|
viewSettings.fullJustification!,
|
|
viewSettings.hyphenation!,
|
|
viewSettings.zoomLevel! / 100.0,
|
|
viewSettings.writingMode!,
|
|
themeCode.bg,
|
|
themeCode.fg,
|
|
themeCode.primary,
|
|
);
|
|
const fontStyles = getFontStyles(
|
|
viewSettings.serifFont!,
|
|
viewSettings.sansSerifFont!,
|
|
viewSettings.monospaceFont!,
|
|
viewSettings.defaultFont!,
|
|
viewSettings.defaultFontSize!,
|
|
viewSettings.overrideFont!,
|
|
);
|
|
const userStylesheet = viewSettings.userStylesheet!;
|
|
return `${layoutStyles}\n${fontStyles}\n${fontfacesCSS}\n${userStylesheet}`;
|
|
};
|
|
|
|
export const mountAdditionalFonts = (document: Document) => {
|
|
const style = document.createElement('style');
|
|
style.textContent = getAdditionalFontFaces();
|
|
document.head.appendChild(style);
|
|
};
|