@ca-plant-list/ca-plant-list 0.4.33 → 0.4.35
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/inatobsphotos.csv +439 -66
- package/data/inattaxonphotos.csv +518 -134
- package/data/synonyms.csv +80 -0
- package/data/taxa.csv +1976 -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/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-polyphyllus-var-burkei.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/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 +8 -0
- 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 +4 -0
- package/lib/index.d.ts +2 -0
- 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 +1 -1
- package/scripts/build-ebook.js +20 -5
- package/scripts/cpl-tools.js +15 -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
|
+
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
|
+
In wet areas. Leaves and keel margins generally not hairy. Stem hollow.
|
@@ -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
|
+
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 narrow and pointed at both ends.
|
@@ -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
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 };
|
@@ -8,16 +8,19 @@ import { Images } from "../images.js";
|
|
8
8
|
import imageSize from "image-size";
|
9
9
|
|
10
10
|
class TaxonPage extends EBookPage {
|
11
|
+
#config;
|
11
12
|
#taxon;
|
12
13
|
#images;
|
13
14
|
|
14
15
|
/**
|
15
16
|
* @param {string} outputDir
|
17
|
+
* @param {Config} config
|
16
18
|
* @param {import("../../taxonomy/taxon.js").Taxon} taxon
|
17
19
|
* @param {Images} images
|
18
20
|
*/
|
19
|
-
constructor(outputDir, taxon, images) {
|
21
|
+
constructor(outputDir, config, taxon, images) {
|
20
22
|
super(outputDir + "/" + taxon.getFileName(), taxon.getName());
|
23
|
+
this.#config = config;
|
21
24
|
this.#taxon = taxon;
|
22
25
|
this.#images = images;
|
23
26
|
}
|
@@ -40,19 +43,26 @@ class TaxonPage extends EBookPage {
|
|
40
43
|
const name = this.#taxon.getName();
|
41
44
|
let html = XHTML.textElement("h1", name);
|
42
45
|
|
46
|
+
// Show header with common name, native status, and family.
|
47
|
+
let header = "";
|
48
|
+
|
49
|
+
const cn = this.#taxon.getCommonNames();
|
50
|
+
if (cn && cn.length > 0) {
|
51
|
+
header += XHTML.textElement("div", cn.join(", "));
|
52
|
+
}
|
53
|
+
|
43
54
|
const family = this.#taxon.getFamily();
|
44
|
-
|
55
|
+
header += XHTML.wrap(
|
45
56
|
"div",
|
46
57
|
XHTML.getLink(family.getFileName(), family.getName()),
|
47
|
-
{ class: "section" },
|
48
58
|
);
|
49
59
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
60
|
+
header += XHTML.textElement(
|
61
|
+
"div",
|
62
|
+
this.#taxon.getStatusDescription(this.#config),
|
63
|
+
);
|
64
|
+
|
65
|
+
html += XHTML.wrap("div", header, "section hdr");
|
56
66
|
|
57
67
|
html += HTMLTaxon.getFlowerInfo(this.#taxon, "section flr");
|
58
68
|
|
package/lib/ebook/plantbook.js
CHANGED
@@ -11,16 +11,19 @@ import { TaxonPage } from "./pages/taxonpage.js";
|
|
11
11
|
import { TOCPage } from "./pages/tocpage.js";
|
12
12
|
|
13
13
|
class PlantBook extends EBook {
|
14
|
+
#config;
|
14
15
|
#taxa;
|
15
16
|
#glossary;
|
16
17
|
#images;
|
18
|
+
#maxTaxa;
|
17
19
|
|
18
20
|
/**
|
19
21
|
* @param {string} outputDir
|
20
22
|
* @param {import("../config.js").Config} config
|
21
23
|
* @param {import("../types.js").Taxa} taxa
|
24
|
+
* @param {number|undefined} maxTaxa
|
22
25
|
*/
|
23
|
-
constructor(outputDir, config, taxa) {
|
26
|
+
constructor(outputDir, config, taxa, maxTaxa) {
|
24
27
|
super(
|
25
28
|
outputDir,
|
26
29
|
getRequiredConfigValue(config, "filename"),
|
@@ -28,16 +31,21 @@ class PlantBook extends EBook {
|
|
28
31
|
getRequiredConfigValue(config, "title"),
|
29
32
|
);
|
30
33
|
|
34
|
+
this.#config = config;
|
31
35
|
this.#taxa = taxa;
|
32
36
|
const generator = new EBookSiteGenerator(config, this.getContentDir());
|
33
37
|
this.#glossary = new GlossaryPages(generator);
|
34
38
|
this.#images = new Images(generator, this.getContentDir(), taxa);
|
39
|
+
this.#maxTaxa = maxTaxa;
|
35
40
|
}
|
36
41
|
|
37
42
|
async createPages() {
|
38
43
|
const contentDir = this.getContentDir();
|
39
44
|
|
40
|
-
const
|
45
|
+
const allTaxa = this.#taxa.getTaxonList();
|
46
|
+
const taxonList = this.#maxTaxa
|
47
|
+
? allTaxa.slice(0, this.#maxTaxa)
|
48
|
+
: allTaxa;
|
41
49
|
|
42
50
|
await this.#images.createImages(taxonList);
|
43
51
|
|
@@ -45,9 +53,15 @@ class PlantBook extends EBook {
|
|
45
53
|
"creating taxon pages",
|
46
54
|
taxonList.length,
|
47
55
|
);
|
56
|
+
|
48
57
|
for (let index = 0; index < taxonList.length; index++) {
|
49
58
|
const taxon = taxonList[index];
|
50
|
-
new TaxonPage(
|
59
|
+
new TaxonPage(
|
60
|
+
contentDir,
|
61
|
+
this.#config,
|
62
|
+
taxon,
|
63
|
+
this.#images,
|
64
|
+
).create();
|
51
65
|
meter.update(index + 1);
|
52
66
|
}
|
53
67
|
meter.stop();
|