@ca-plant-list/ca-plant-list 0.4.33 → 0.4.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/glossary/peduncle.md +1 -1
- package/data/inatobsphotos.csv +499 -75
- package/data/inattaxonphotos.csv +728 -242
- package/data/synonyms.csv +86 -0
- package/data/taxa.csv +1985 -1905
- package/data/text/Allium-obtusum-var-obtusum.md +1 -0
- package/data/text/Allium-validum.md +1 -0
- package/data/text/Amelanchier-alnifolia-var-pumila.md +1 -0
- package/data/text/Amelanchier-utahensis.md +1 -0
- package/data/text/Angelica-breweri.md +1 -0
- package/data/text/Angelica-capitellata.md +1 -0
- package/data/text/Castilleja-applegatei-subsp-pallida.md +1 -0
- package/data/text/Castilleja-miniata-subsp-miniata.md +1 -0
- package/data/text/Ceanothus-cordulatus.md +1 -0
- package/data/text/Ceanothus-velutinus.md +1 -0
- package/data/text/Collinsia-parviflora.md +1 -0
- package/data/text/Collinsia-torreyi.md +1 -0
- package/data/text/Ericameria-nauseosa-var-speciosa.md +1 -0
- package/data/text/Ericameria-nauseosa.md +1 -0
- package/data/text/Erigeron-algidus.md +1 -0
- package/data/text/Erigeron-coulteri.md +1 -0
- package/data/text/Hackelia-micrantha.md +1 -0
- package/data/text/Hieracium-albiflorum.md +1 -0
- package/data/text/Hieracium-horridum.md +1 -0
- package/data/text/Hieracium-triste.md +1 -0
- package/data/text/Linanthus-pungens-subsp-pulchriflorus.md +1 -0
- package/data/text/Lupinus-argenteus-var-meionanthus.md +1 -0
- package/data/text/Lupinus-latifolius-var-latifolius.md +1 -1
- package/data/text/Lupinus-lepidus-var-lobbii.md +1 -0
- package/data/text/Lupinus-polyphyllus-var-burkei.md +1 -0
- package/data/text/Pedicularis-attollens.md +1 -0
- package/data/text/Pedicularis-groenlandica.md +1 -0
- package/data/text/Penstemon-deustus-var-deustus.md +1 -0
- package/data/text/Penstemon-deustus-var-pedicellatus.md +1 -0
- package/data/text/Penstemon-heterodoxus-var-heterodoxus.md +1 -0
- package/data/text/Penstemon-rydbergii-var-oreocharis.md +1 -0
- package/data/text/Phlox-diffusa.md +1 -0
- package/data/text/Potentilla-flabellifolia.md +1 -0
- package/data/text/Potentilla-gracilis-var-fastigiata.md +1 -0
- package/data/text/Primula-jeffreyi.md +1 -1
- package/data/text/Primula-tetrandra.md +1 -1
- package/data/text/Pseudognaphalium-beneolens.md +1 -0
- package/data/text/Pseudognaphalium-californicum.md +1 -0
- package/data/text/Pseudognaphalium-ramosissimum.md +1 -0
- package/data/text/Pyrola-asarifolia-subsp-asarifolia.md +1 -0
- package/data/text/Pyrola-dentata.md +1 -0
- package/data/text/Pyrola-picta.md +1 -0
- package/data/text/Salix-lemmonii.md +1 -0
- package/data/text/Salix-scouleriana.md +1 -0
- package/data/text/Senecio-integerrimus-var-exaltatus.md +1 -0
- package/data/text/Senecio-integerrimus-var-major.md +1 -0
- package/data/text/Senecio-triangularis.md +1 -0
- package/data/text/Sorbus-californica.md +1 -0
- package/data/text/Sorbus-scopulina.md +1 -0
- package/ebook/css/main.css +20 -13
- package/lib/csv.js +0 -2
- package/lib/ebook/ebook.js +178 -178
- package/lib/ebook/pages/taxonpage.js +19 -9
- package/lib/ebook/plantbook.js +17 -3
- package/lib/externalsites.js +12 -0
- package/lib/htmltaxon.js +13 -2
- package/lib/index.d.ts +3 -0
- package/lib/markdown.js +1 -1
- package/lib/program.js +0 -26
- package/lib/sitegenerator.js +4 -4
- package/lib/taxonomy/taxa.js +26 -5
- package/lib/taxonomy/taxon.js +12 -2
- package/lib/tools/calflora.js +0 -2
- package/lib/tools/calipc.js +111 -0
- package/lib/tools/taxacsv.js +5 -4
- package/lib/utils/eleventyGenerator.js +2 -0
- package/lib/utils/inat-tools.js +8 -4
- package/lib/web/pageTaxon.js +1 -0
- package/package.json +6 -6
- package/scripts/build-ebook.js +21 -6
- package/scripts/build-site.js +1 -1
- package/scripts/cpl-photos.js +1 -1
- package/scripts/cpl-tools.js +15 -1
- package/scripts/inattaxonphotos.js +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Nearly prostrate.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Stamens protruding beyond petals.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Upper leaf without hairs. Flower with 5 [styles](./g/style.html).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Upper leaf with hairs. Flower with 2 to 4 [styles](./g/style.html).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Umbels hairless or sparsely hairy. Secondary umbels open, not spherical.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Umbels covered with hairs. Secondary umbels spherical.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
In dry areas. Leaf usually with 3 lobes. Generally shorther than _C. miniata_.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
In wet areas. Usually 50 cm or taller. Leaves not toothed or lobed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Twigs grayish, stiff and thorn-like.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Twigs green or brown, flexible and not thorny.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Inflorescence hairless or sparsely glandular.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Inflorescence densely glandular.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Generally in dry areas. Disc flowers only. Phyllaries with keels.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Disc flowers only. Phyllaries with keels.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves on stem sparse and narrow. Phyllaries and stem hairy.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves on stem usually clasping the stem. Ray flowers narrow (narrower than _E. glacialis_).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[Calyx](./g/calyx.html) shorter than 3mm. Corolla tube does not extend much beyond calyx. Flowers usually 5-8mm in diameter.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
In forested areas.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
In rocky areas. Leaves densely hairy.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Usually in moist or forested areas. [Phyllaries](./g/phyllary.html) with black hairs.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Flowers funnel shaped. Leaves spine-tipped.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
In dry areas. Silvery leaves. Yellow patch on banner petals.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Fruit densely hairy. Upper keel margin hairy from base to middle, not hairy from middle to tip
|
|
1
|
+
In moist areas or open forest. Fruit densely hairy. Upper keel margin hairy from base to middle, not hairy from middle to tip. Stem not hollow. Often more than 1 meter tall.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves hairy. Plant mostly prostrate; inflorescence low.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
In wet areas. Leaves and keel margins generally not hairy. Stem hollow.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Inflorescence hairy. Beak 3-5 mm (shorter than _P. groenlandica_).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Inflorescence not hairy. Beak 6-13 mm (longer than _P. attolens_).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves generally wider (8-18 mm) than var. pedicellatus. Upper lip white.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves generally narrower (<= 8 mm) than var. deustus. Upper lip brown.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Usually on dry mountain slopes. Inflorescence with glandular hairs. Similar to _P. rydbergii_.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Generally in high elevation wet habitats. Usually not hairy. Similar to _P. heterodoxus_.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Flowers not funnel shaped (base rounded). Leaves not spine-tipped.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Petals with small notch at tips.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves palmate, with 5-7 toothed leaflets.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Stem hairy and glandular.
|
|
1
|
+
Stem hairy and glandular. Intergrades with _P. tetrandra_.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Stem not hairy.
|
|
1
|
+
Stem not hairy. Intergrades with _P. jeffreyi_.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves gray. Scented.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves green. Scented.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves green. Scented.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaf blades round, with petioles.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Flower bract not longer than [pedicel](./g/pedicel.html).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves with wide white veins. Flower bract not longer than [pedicel](./g/pedicel.html).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves generally pointed at both ends. Older leaves usually hairless; younger leaves often somewhat hairy.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Leaves wider at end than at base; base generally wedge-shaped.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Usually around 13 ray flowers. Leaves not triangular, larger and more numerous towards base. Phyllary tips black.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Usually around 13 ray flowers. Leaves not triangular, larger and more numerous towards base. Phyllary tips green.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Usually 8 ray flowers. Leaves triangular and toothed; evenly distributed along stem.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Hairs reddish brown and sparse. Intergrades with [_S. scopulina_](./Sorbus-scopulina.html).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Hairs whitish.
|
package/ebook/css/main.css
CHANGED
|
@@ -1,40 +1,47 @@
|
|
|
1
1
|
* {
|
|
2
|
-
|
|
2
|
+
font-family: Georgia, 'Times New Roman', Times, serif;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
div.flr {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
background-color: lightgray;
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
div.hdr {
|
|
12
|
+
display: flex;
|
|
13
|
+
column-gap: 2rem;
|
|
14
|
+
row-gap: .5rem;
|
|
15
|
+
flex-flow: row wrap;
|
|
16
|
+
justify-content: space-between;
|
|
9
17
|
}
|
|
10
18
|
|
|
11
19
|
div.section {
|
|
12
|
-
|
|
20
|
+
margin-bottom: .5rem;
|
|
13
21
|
}
|
|
14
22
|
|
|
15
23
|
div.photos {
|
|
16
|
-
|
|
24
|
+
display: flex;
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
figure {
|
|
20
|
-
|
|
28
|
+
margin: auto;
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
img.flr-color {
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
padding-right: .25rem;
|
|
33
|
+
width: 1rem;
|
|
26
34
|
}
|
|
27
35
|
|
|
28
36
|
span.flr-time,
|
|
29
37
|
span.lc {
|
|
30
|
-
|
|
38
|
+
font-weight: bold;
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
span.lcs {
|
|
34
|
-
|
|
42
|
+
margin-right: 1rem;
|
|
35
43
|
}
|
|
36
44
|
|
|
37
|
-
/* Glossary */
|
|
38
45
|
div.glossary img {
|
|
39
|
-
|
|
46
|
+
width: 100%
|
|
40
47
|
}
|
package/lib/csv.js
CHANGED
|
@@ -134,7 +134,6 @@ export class CSV {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
|
-
*
|
|
138
137
|
* @param {string} fileName
|
|
139
138
|
* @param {string[][]} data
|
|
140
139
|
* @param {string[]} [headerData]
|
|
@@ -146,7 +145,6 @@ export class CSV {
|
|
|
146
145
|
}
|
|
147
146
|
|
|
148
147
|
/**
|
|
149
|
-
*
|
|
150
148
|
* @param {string} fileName
|
|
151
149
|
* @param {Object<string,any>[]} data
|
|
152
150
|
* @param {string[]} headerData
|
package/lib/ebook/ebook.js
CHANGED
|
@@ -4,193 +4,193 @@ import { XHTML } from "./xhtml.js";
|
|
|
4
4
|
import { Config } from "../config.js";
|
|
5
5
|
|
|
6
6
|
const MEDIA_TYPES = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
SVG: "image/svg+xml",
|
|
8
|
+
JPG: "image/jpeg",
|
|
9
|
+
XHTML: "application/xhtml+xml",
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @type {Object<string,string>}
|
|
14
14
|
*/
|
|
15
15
|
const EXT_MEDIA_MAP = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
jpeg: MEDIA_TYPES.JPG,
|
|
17
|
+
jpg: MEDIA_TYPES.JPG,
|
|
18
|
+
svg: MEDIA_TYPES.SVG,
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
class EBook {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
22
|
+
#outputDir;
|
|
23
|
+
#filename;
|
|
24
|
+
#pub_id;
|
|
25
|
+
#title;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} outputDir
|
|
29
|
+
* @param {string} filename
|
|
30
|
+
* @param {string} pub_id
|
|
31
|
+
* @param {string} title
|
|
32
|
+
*/
|
|
33
|
+
constructor(outputDir, filename, pub_id, title) {
|
|
34
|
+
this.#outputDir = outputDir;
|
|
35
|
+
this.#filename = filename;
|
|
36
|
+
this.#pub_id = pub_id;
|
|
37
|
+
this.#title = title;
|
|
38
|
+
|
|
39
|
+
// Initialize output directory.
|
|
40
|
+
fs.rmSync(this.#outputDir, { force: true, recursive: true });
|
|
41
|
+
fs.mkdirSync(this.getContentDir(), { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async create() {
|
|
45
|
+
const contentDir = this.getContentDir();
|
|
46
|
+
|
|
47
|
+
this.#createContainerFile();
|
|
48
|
+
await this.createPages();
|
|
49
|
+
this.#createPackageFile();
|
|
50
|
+
|
|
51
|
+
// Copy assets
|
|
52
|
+
fs.cpSync(Config.getPackageDir() + "/ebook", contentDir, {
|
|
53
|
+
recursive: true,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
this.createZip();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
#createContainerFile() {
|
|
60
|
+
const metaDir = this.#getMetaDir();
|
|
61
|
+
|
|
62
|
+
fs.mkdirSync(metaDir, { recursive: true });
|
|
63
|
+
|
|
64
|
+
let xml =
|
|
65
|
+
'<?xml version="1.0"?>' +
|
|
66
|
+
'<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">';
|
|
67
|
+
|
|
68
|
+
xml +=
|
|
69
|
+
'<rootfiles><rootfile full-path="epub/package.opf" media-type="application/oebps-package+xml" /></rootfiles>';
|
|
70
|
+
xml += "</container>";
|
|
71
|
+
|
|
72
|
+
fs.writeFileSync(metaDir + "/container.xml", xml);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
#createPackageFile() {
|
|
76
|
+
const dir = this.getContentDir();
|
|
77
|
+
|
|
78
|
+
let xml =
|
|
79
|
+
'<?xml version="1.0"?>\n' +
|
|
80
|
+
'<package version="3.0" xml:lang="en" xmlns="http://www.idpf.org/2007/opf" unique-identifier="pub-id">';
|
|
81
|
+
|
|
82
|
+
xml += this.#renderMetadata();
|
|
83
|
+
xml += this.#renderManifest();
|
|
84
|
+
xml += this.#renderSpine();
|
|
85
|
+
|
|
86
|
+
xml += "</package>";
|
|
87
|
+
|
|
88
|
+
fs.writeFileSync(dir + "/package.opf", xml);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async createPages() {
|
|
92
|
+
throw new Error("must be implemented by subclass");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
createZip() {
|
|
96
|
+
// Create zip.
|
|
97
|
+
const filename = this.#outputDir + "/" + this.#filename + ".epub";
|
|
98
|
+
const output = fs.createWriteStream(filename);
|
|
99
|
+
const archive = archiver("zip", {
|
|
100
|
+
zlib: { level: 9 }, // Sets the compression level.
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
archive.pipe(output);
|
|
104
|
+
|
|
105
|
+
archive.append("application/epub+zip", {
|
|
106
|
+
name: "mimetype",
|
|
107
|
+
store: true,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
archive.directory(this.#getMetaDir(), "META-INF");
|
|
111
|
+
archive.directory(this.getContentDir(), "epub");
|
|
112
|
+
|
|
113
|
+
archive.finalize();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
getContentDir() {
|
|
117
|
+
return this.#outputDir + "/epub";
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {string} id
|
|
122
|
+
* @param {string} href
|
|
123
|
+
* @param {string} mediaType
|
|
124
|
+
*/
|
|
125
|
+
static getManifestEntry(id, href, mediaType = MEDIA_TYPES.XHTML) {
|
|
126
|
+
return (
|
|
127
|
+
'<item id="' +
|
|
128
|
+
id +
|
|
129
|
+
'" href="' +
|
|
130
|
+
href +
|
|
131
|
+
'" media-type="' +
|
|
132
|
+
mediaType +
|
|
133
|
+
'" />'
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @param {string} ext
|
|
139
|
+
*/
|
|
140
|
+
static getMediaTypeForExt(ext) {
|
|
141
|
+
return EXT_MEDIA_MAP[ext];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @param {string} id
|
|
146
|
+
*/
|
|
147
|
+
static getSpineEntry(id) {
|
|
148
|
+
return '<itemref idref="' + id + '"/>';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#getMetaDir() {
|
|
152
|
+
return this.#outputDir + "/META-INF";
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
#renderManifest() {
|
|
156
|
+
let xml = "<manifest>";
|
|
157
|
+
xml += '<item id="c0" href="css/main.css" media-type="text/css" />';
|
|
158
|
+
xml += this.renderManifestEntries();
|
|
159
|
+
xml +=
|
|
160
|
+
'<item id="toc" href="toc.xhtml" media-type="application/xhtml+xml" properties="nav" />';
|
|
161
|
+
return xml + "</manifest>";
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
renderManifestEntries() {
|
|
165
|
+
throw new Error("must be implemented by subclass");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
#renderMetadata() {
|
|
169
|
+
let xml = '<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">';
|
|
170
|
+
xml += XHTML.textElement("dc:identifier", this.#pub_id, {
|
|
171
|
+
id: "pub-id",
|
|
172
|
+
});
|
|
173
|
+
xml += "<dc:language>en-US</dc:language>";
|
|
174
|
+
xml += XHTML.textElement("dc:title", this.#title);
|
|
175
|
+
const d = new Date();
|
|
176
|
+
d.setUTCMilliseconds(0);
|
|
177
|
+
xml +=
|
|
178
|
+
'<meta property="dcterms:modified">' +
|
|
179
|
+
d.toISOString().replace(".000", "") +
|
|
180
|
+
"</meta>";
|
|
181
|
+
return xml + "</metadata>";
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
#renderSpine() {
|
|
185
|
+
let xml = "<spine>";
|
|
186
|
+
xml += '<itemref idref="toc"/>';
|
|
187
|
+
xml += this.renderSpineElements();
|
|
188
|
+
return xml + "</spine>";
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
renderSpineElements() {
|
|
192
|
+
throw new Error("must be implemented by subclass");
|
|
193
|
+
}
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
export { EBook };
|