diff --git a/packages/core/src/xhtml/builder.ts b/packages/core/src/xhtml/builder.ts
index cedcc0e..e67965e 100644
--- a/packages/core/src/xhtml/builder.ts
+++ b/packages/core/src/xhtml/builder.ts
@@ -6,6 +6,7 @@ import { Item, Style } from '../epub/item';
import { TextCSS, TextXHTML } from '../constant';
import type { XHTMLNode } from './types';
+
import { Fragment } from './render';
const builder = new XMLBuilder({
@@ -65,6 +66,8 @@ export class XHTMLBuilder {
private _body: XHTMLNode[] = [];
+ private _bodyAttrs: Record = {};
+
public constructor(filename: string) {
this._filename = filename;
this._meta.title = path.basename(filename);
@@ -117,6 +120,15 @@ export class XHTMLBuilder {
return this;
}
+ public bodyAttrs(attrs: Record = {}) {
+ const a = Object.entries(attrs).map(([key, value]) => [`@_${key}`, value]);
+ this._bodyAttrs = {
+ ...this._bodyAttrs,
+ ...Object.fromEntries(a)
+ };
+ return this;
+ }
+
public build(): XHTML {
const content = builder.build({
html: {
@@ -128,7 +140,10 @@ export class XHTMLBuilder {
title: this._meta.title,
...list(this._head)
},
- body: list(this._body)
+ body: {
+ ...this._bodyAttrs,
+ ...list(this._body)
+ }
}
});
diff --git a/packages/theme-default/package.json b/packages/theme-default/package.json
index 1f5f866..c8aaf6f 100644
--- a/packages/theme-default/package.json
+++ b/packages/theme-default/package.json
@@ -50,9 +50,9 @@
"node": ">=v18.14.2"
},
"epubook": {
- "pages": [],
"styles": [
- "styles/main.css"
+ "styles/main.css",
+ "styles/cover.css"
],
"images": []
}
diff --git a/packages/theme-default/src/index.ts b/packages/theme-default/src/index.ts
index 15446ab..bb1f232 100644
--- a/packages/theme-default/src/index.ts
+++ b/packages/theme-default/src/index.ts
@@ -10,7 +10,7 @@ import { DefaultThemePageTemplate } from './types';
export * from './types';
export * from './chapter';
-const styles = ['./styles/main.css'];
+const styles = ['./styles/main.css', './styles/cover.css'];
export async function DefaultTheme(): Promise> {
return {
@@ -21,6 +21,7 @@ export async function DefaultTheme(): Promise> {
cover(file, { image, title = '封面' }) {
return new XHTMLBuilder(file)
.title(title)
+ .bodyAttrs({ class: 'cover' })
.body({ tag: 'img', attrs: { src: image.relative(file) } });
},
nav(file, { nav, option }) {
diff --git a/packages/theme-default/styles/cover.css b/packages/theme-default/styles/cover.css
new file mode 100644
index 0000000..acf9e33
--- /dev/null
+++ b/packages/theme-default/styles/cover.css
@@ -0,0 +1,13 @@
+body.cover, body.cover div, body.cover img {
+ margin: 0;
+ padding: 0;
+ text-align: center;
+}
+
+body.cover img {
+ height: 100%;
+ max-width: 100%;
+ border: 0 none;
+ vertical-align: bottom;
+ object-fit: contain;
+}
diff --git a/packages/theme-default/styles/main.css b/packages/theme-default/styles/main.css
index b8d96de..5e24058 100644
--- a/packages/theme-default/styles/main.css
+++ b/packages/theme-default/styles/main.css
@@ -1,74 +1,263 @@
+/* See: https://github.com/spajak/epub3-boilerplate */
+
+@charset "UTF-8";
+
+@page {
+ margin-left: 10pt;
+ margin-right: 10pt;
+ padding: 0;
+}
+
+.hidden, [hidden] {
+ display: none;
+}
+
+/* --- sections --- */
+article,
+aside,
+blockquote,
+figure,
+figcaption,
+footer,
+header,
+main,
+nav,
+section {
+ display: block;
+}
+
body {
- padding: 0%;
- margin-top: 0%;
- margin-bottom: 0%;
- margin-left: 1%;
- margin-right: 1%;
- line-height: 130%;
+ font-size: 100%;
+ font-weight: normal;
text-align: justify;
+ line-height: 1.35;
+ margin: 0;
+ padding: 0;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ widows: 2;
+ orphans: 2;
}
-h1 {
- line-height: 120%;
+section, nav {
+ page-break-before: always;
+ page-break-after: always;
+}
+
+h1, h2, h3, h4, h5, h6 {
text-align: center;
+ line-height: 1.25;
font-weight: bold;
- font-size: 1.65em;
- margin-top: 0.1em;
- margin-bottom: 0.4em;
+ margin: 1.5em 0;
+ -epub-hyphens: none;
+ hyphens: none;
+ page-break-after: avoid;
+ page-break-inside: avoid;
+}
+
+h1 {
+ font-size: 2em;
}
h2 {
- font-size: 1.8em;
- text-align: center;
- line-height: 1.2em;
- text-indent: 0em;
- font-weight: bold;
- margin-top: 0em;
- margin-bottom: 2em;
+ font-size: 1.625em;
+ margin-top: 2.75em;
}
h3 {
- font-size: 1.5em;
- text-align: center;
- line-height: 1.2em;
- text-indent: 0em;
- font-weight: bold;
- margin-top: 1em;
- margin-bottom: 1.5em;
+ font-size: 1.375em;
+ margin-top: 2em;
+ margin-bottom: 1.25em;
}
h4 {
- font-weight: bold;
- font-size: 1.2em;
- text-indent: 0em;
- margin-top: 0em;
- margin-bottom: 0.3em;
- border-bottom: 0.1em solid #000000;
- padding: 0.3em 0 0.2em 0;
+ font-size: 1.125em;
+ margin-bottom: 1em;
}
-h5 {
+h5, h6 {
+ font-size: 1em;
+ margin-top: 1em;
+ margin-bottom: 0.75em;
+}
+
+h6 {
+ font-style: italic;
+}
+
+/* --- Content grouping --- */
+p, blockquote, figure, ol, ul, dl, pre {
+ margin-top: 1em;
+ margin-bottom: 1em;
+ text-indent: 0;
+}
+
+p.classic,
+p.book,
+p.novel {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+p + p.classic,
+p + p.book,
+p + p.novel {
+ text-indent: 1.125em;
+}
+
+p.stanza, p.verses, p.verse, p.poetry {
+ margin-top: 1em;
+ margin-bottom: 1em;
+ text-align: left;
+ text-indent: 0;
+}
+
+blockquote {
+ padding-left: 18pt;
+ padding-right: 18pt;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+blockquote.fancy {
+ padding-left: 10pt;
+ padding-right: 16pt;
+ border-left: 0.875rem solid #9F9F9F;
+}
+
+dt {
font-weight: bold;
- font-size: 1.1em;
- text-indent: 0em;
- margin-top: 0.4em;
- margin-bottom: 0.4em;
- border-left: 3px solid #ff00ff;
- border-bottom: 1px solid #ff00ff;
+ text-align: left;
+ page-break-after: avoid;
+}
+
+dd {
padding: 0;
+ margin-left: 0;
+ margin-right: 0;
+ margin-bottom: 0.25em;
+ padding-left: 22pt;
+ page-break-before: avoid;
}
-div {
- margin: 0px;
- padding: 0px;
- text-align: justify;
- font-family: 'DK-SYMBOL';
+figure {
+ padding: 0;
+ margin-left: 0;
+ margin-right: 0;
+ text-align: center;
+ page-break-inside: avoid;
+}
+
+figcaption {
+ margin: 0.25em auto;
+ line-height: 1.25;
+ font-size: 0.875em;
+ text-align: center;
}
-p {
- text-indent: 2em;
+hr {
+ height: 0;
+ width: auto;
+ padding: 0;
+ border: 0 none;
+ border-top: 0.125rem solid currentColor;
+ margin: 1.5em auto;
+ text-align: center;
+ page-break-after: avoid;
+}
+
+pre {
+ tab-size: 2;
+ text-align: left;
display: block;
- line-height: 1.3em;
- margin-top: 0.4em;
- margin-bottom: 0.4em;
+ white-space: pre-wrap;
+ font-size: 0.8125em;
+ line-height: 1.25;
+}
+
+/* --- List --- */
+ul, ol {
+ text-align: initial;
+ list-style-position: outside;
+ margin-left: 0;
+}
+
+ol {
+ list-style-type: decimal;
+ padding-left: 34pt;
+}
+
+ol.wide {
+ padding-left: 44pt;
+}
+
+ul {
+ list-style-type: disc;
+ padding-left: 24pt;
+}
+
+ul ul {
+ list-style-type: circle;
+}
+
+li ol, li ul {
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-left: 24pt;
+}
+
+li ul {
+ padding-left: 16pt;
+}
+
+/* --- Image --- */
+img {
+ max-width: 100%;
+ max-height: 100%;
+ object-fit: contain;
+ vertical-align: bottom;
+}
+
+/* --- Text --- */
+em, cite, q, i {
+ font-style: italic;
+}
+
+q {
+ quotes: none !important;
+ font-style: italic !important;
+}
+
+dfn {
+ font-style: normal;
+ font-weight: bold;
+}
+
+strong, b {
+ font-weight: bold;
+}
+
+small {
+ font-size: 0.875em;
+}
+
+sub, sup {
+ font-size: 0.675em;
+ line-height: 1.2;
}
+
+sub {
+ vertical-align: sub;
+ vertical-align: -20%;
+}
+
+sup {
+ vertical-align: super;
+ vertical-align: 35%;
+}
+
+code {
+ white-space: pre;
+ text-align: left;
+ font-family: monospace;
+}
\ No newline at end of file