@ca-plant-list/ca-plant-list 0.3.7 → 0.4.1
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/.vscode/settings.json +7 -1
- package/data/synonyms.csv +95 -2
- package/data/taxa.csv +53 -22
- package/data/text/Antennaria-media.md +1 -0
- package/data/text/Antennaria-rosea-subsp-rosea.md +1 -0
- package/data/text/Camassia-leichtlinii-subsp-suksdorfii.md +1 -0
- package/data/text/Camassia-quamash-subsp-breviflora.md +1 -0
- package/data/text/Delphinium-glaucum.md +1 -0
- package/data/text/Delphinium-nuttallianum.md +1 -0
- package/data/text/Drymocallis-glandulosa-var-glandulosa.md +1 -0
- package/data/text/Drymocallis-lactea-var-austiniae.md +1 -0
- package/data/text/Erigeron-compositus.md +1 -0
- package/data/text/Erigeron-glacialis-var-glacialis.md +1 -0
- package/data/text/Eriogonum-incanum.md +1 -0
- package/data/text/Eriogonum-lobbii.md +1 -0
- package/data/text/Eriogonum-ovalifolium-var-nivale.md +1 -0
- package/data/text/Erythranthe-breweri.md +1 -0
- package/data/text/Erythranthe-erubescens.md +1 -0
- package/data/text/Navarretia-leptalea-subsp-bicolor.md +1 -0
- package/data/text/Navarretia-leptalea-subsp-leptalea.md +1 -0
- package/data/text/Polemonium-californicum.md +1 -0
- package/data/text/Polemonium-pulcherrimum-var-pulcherrimum.md +1 -0
- package/data/text/Primula-jeffreyi.md +1 -0
- package/data/text/Primula-tetrandra.md +1 -0
- package/data/text/Silene-douglasii-var-douglasii.md +1 -0
- package/data/text/Silene-lemmonii.md +1 -0
- package/data/text/Silene-sargentii.md +1 -0
- package/lib/basepagerenderer.js +3 -4
- package/lib/config.js +42 -19
- package/lib/csv.js +54 -36
- package/lib/ebook/ebook.js +84 -57
- package/lib/ebook/ebookpage.js +22 -11
- package/lib/ebook/ebooksitegenerator.js +36 -14
- package/lib/ebook/glossarypages.js +20 -17
- package/lib/ebook/images.js +13 -5
- package/lib/ebook/pages/page_list_families.js +0 -2
- package/lib/ebook/pages/page_list_flower_color.js +14 -9
- package/lib/ebook/pages/page_list_flowers.js +59 -41
- package/lib/ebook/pages/taxonpage.js +1 -1
- package/lib/ebook/pages/tocpage.js +26 -20
- package/lib/ebook/plantbook.js +6 -13
- package/lib/ebook/{image.js → taxonimage.js} +2 -2
- package/lib/exceptions.js +42 -26
- package/lib/externalsites.js +11 -4
- package/lib/families.js +10 -8
- package/lib/flowercolor.js +42 -0
- package/lib/genera.js +13 -21
- package/lib/genericpage.js +12 -0
- package/lib/html.js +11 -23
- package/lib/htmltaxon.js +89 -6
- package/lib/index.d.ts +54 -0
- package/lib/index.js +2 -30
- package/lib/jekyll.js +49 -21
- package/lib/jepson.js +7 -8
- package/lib/markdown.js +6 -0
- package/lib/pagerenderer.js +43 -8
- package/lib/plants/glossary.js +5 -0
- package/lib/program.js +47 -0
- package/lib/rareplants.js +44 -30
- package/lib/sitegenerator.js +41 -24
- package/lib/taxa.js +20 -134
- package/lib/taxon.js +1 -1
- package/lib/web/glossarypages.js +6 -0
- package/lib/web/pagetaxon.js +1 -5
- package/package.json +8 -7
- package/schemas/exceptions.schema.json +57 -0
- package/scripts/build-ebook.js +38 -47
- package/scripts/build-site.js +25 -14
- package/types/classes.d.ts +136 -8
- package/lib/commandandtaxaprocessor.js +0 -25
- package/lib/commandprocessor.js +0 -108
- package/lib/generictaxaloader.js +0 -48
- package/lib/taxaloader.js +0 -50
- package/lib/taxaprocessor.js +0 -34
- /package/data/text/{Calyptridium-ubellatum.md → Calyptridium-umbellatum.md} +0 -0
@@ -2,33 +2,55 @@ import { Files } from "../files.js";
|
|
2
2
|
import { SiteGenerator } from "../sitegenerator.js";
|
3
3
|
|
4
4
|
class EBookSiteGenerator extends SiteGenerator {
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
/**
|
6
|
+
* @param {string} baseDir
|
7
|
+
*/
|
8
|
+
constructor(baseDir) {
|
9
|
+
super(baseDir);
|
8
10
|
}
|
9
11
|
|
10
12
|
#pageEnd() {
|
11
13
|
return "</body></html>";
|
12
14
|
}
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
/**
|
17
|
+
* @param {number} depth
|
18
|
+
* @param {{title:string}} attributes
|
19
|
+
*/
|
20
|
+
#pageStart(depth, attributes) {
|
21
|
+
let html = '<?xml version="1.0" encoding="utf-8"?>\n';
|
22
|
+
html +=
|
23
|
+
'<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">';
|
17
24
|
html += "<head><title>" + attributes.title + "</title>";
|
18
|
-
html +=
|
25
|
+
html +=
|
26
|
+
'<link href="' +
|
27
|
+
"../".repeat(depth) +
|
28
|
+
'css/main.css" rel="stylesheet" />';
|
19
29
|
html += "</head><body>";
|
20
30
|
return html;
|
21
31
|
}
|
22
32
|
|
23
|
-
|
24
|
-
|
33
|
+
/**
|
34
|
+
* @param {number} depth
|
35
|
+
* @param {string} content
|
36
|
+
* @param {{title:string}} attributes
|
37
|
+
*/
|
38
|
+
#wrap(depth, content, attributes) {
|
39
|
+
return this.#pageStart(depth, attributes) + content + this.#pageEnd();
|
25
40
|
}
|
26
41
|
|
27
|
-
|
28
|
-
|
29
|
-
|
42
|
+
/**
|
43
|
+
* @param {string} content
|
44
|
+
* @param {{title:string}} attributes
|
45
|
+
* @param {string} filename
|
46
|
+
*/
|
47
|
+
writeTemplate(content, attributes, filename) {
|
48
|
+
const depth = (filename.match(/\//g) || []).length;
|
49
|
+
Files.write(
|
50
|
+
Files.join(this.getBaseDir(), filename),
|
51
|
+
this.#wrap(depth, content, attributes)
|
52
|
+
);
|
30
53
|
}
|
31
|
-
|
32
54
|
}
|
33
55
|
|
34
|
-
export { EBookSiteGenerator };
|
56
|
+
export { EBookSiteGenerator };
|
@@ -2,39 +2,42 @@ import { GlossaryPages as BaseGlossaryPages } from "../web/glossarypages.js";
|
|
2
2
|
import { EBook } from "./ebook.js";
|
3
3
|
|
4
4
|
class GlossaryPages extends BaseGlossaryPages {
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
/**
|
6
|
+
* @param {SiteGenerator} siteGenerator
|
7
|
+
*/
|
8
|
+
constructor(siteGenerator) {
|
9
|
+
super(siteGenerator);
|
8
10
|
}
|
9
11
|
|
10
12
|
getManifestEntries() {
|
11
|
-
|
12
13
|
const glossaryEntries = this.getGlossary().getEntries();
|
13
14
|
const manifestEntries = [];
|
14
15
|
|
15
|
-
manifestEntries.push(
|
16
|
-
for (
|
17
|
-
const entry = glossaryEntries[
|
18
|
-
manifestEntries.push(
|
16
|
+
manifestEntries.push(EBook.getManifestEntry("g", "glossary.html"));
|
17
|
+
for (let index = 0; index < glossaryEntries.length; index++) {
|
18
|
+
const entry = glossaryEntries[index];
|
19
|
+
manifestEntries.push(
|
20
|
+
EBook.getManifestEntry(
|
21
|
+
"g" + index,
|
22
|
+
"g/" + entry.getHTMLFileName()
|
23
|
+
)
|
24
|
+
);
|
19
25
|
}
|
20
26
|
|
21
|
-
return manifestEntries.join(
|
27
|
+
return manifestEntries.join("");
|
22
28
|
}
|
23
29
|
|
24
30
|
getSpineEntries() {
|
25
|
-
|
26
31
|
const glossaryEntries = this.getGlossary().getEntries();
|
27
32
|
const spineEntries = [];
|
28
33
|
|
29
|
-
spineEntries.push(
|
30
|
-
for (
|
31
|
-
spineEntries.push(
|
34
|
+
spineEntries.push(EBook.getSpineEntry("g"));
|
35
|
+
for (let index = 0; index < glossaryEntries.length; index++) {
|
36
|
+
spineEntries.push(EBook.getSpineEntry("g" + index));
|
32
37
|
}
|
33
38
|
|
34
|
-
return spineEntries.join(
|
35
|
-
|
39
|
+
return spineEntries.join("");
|
36
40
|
}
|
37
|
-
|
38
41
|
}
|
39
42
|
|
40
|
-
export { GlossaryPages };
|
43
|
+
export { GlossaryPages };
|
package/lib/ebook/images.js
CHANGED
@@ -3,19 +3,24 @@ import path from "node:path";
|
|
3
3
|
|
4
4
|
import sharp from "sharp";
|
5
5
|
|
6
|
-
import { Image } from "./image.js";
|
7
6
|
import { EBook } from "./ebook.js";
|
8
|
-
import { Taxa } from "../taxa.js";
|
9
7
|
import { Config } from "../config.js";
|
10
8
|
import { CSV } from "../csv.js";
|
11
9
|
import { Files } from "../files.js";
|
10
|
+
import { TaxonImage } from "./taxonimage.js";
|
12
11
|
|
13
12
|
class Images {
|
14
13
|
#siteGenerator;
|
15
14
|
#contentDir;
|
16
15
|
#taxa;
|
16
|
+
/** @type {Object<string,TaxonImage[]>} */
|
17
17
|
#images = {};
|
18
18
|
|
19
|
+
/**
|
20
|
+
* @param {SiteGenerator} siteGenerator
|
21
|
+
* @param {string} contentDir
|
22
|
+
* @param {Taxa} taxa
|
23
|
+
*/
|
19
24
|
constructor(siteGenerator, contentDir, taxa) {
|
20
25
|
this.#siteGenerator = siteGenerator;
|
21
26
|
this.#contentDir = contentDir;
|
@@ -59,17 +64,17 @@ class Images {
|
|
59
64
|
await Files.fetch(src, srcFileName);
|
60
65
|
}
|
61
66
|
|
62
|
-
await
|
67
|
+
await sharp(srcFileName)
|
63
68
|
.resize({ width: 300 })
|
64
69
|
.jpeg({ quality: 40 })
|
65
70
|
.toFile(targetFileName);
|
66
71
|
|
67
72
|
imageList.push(
|
68
|
-
new
|
73
|
+
new TaxonImage(imagePrefix + "/" + filename, row["credit"])
|
69
74
|
);
|
70
75
|
}
|
71
76
|
|
72
|
-
this.#siteGenerator.copyIllustrations(
|
77
|
+
this.#siteGenerator.copyIllustrations(this.#taxa.getFlowerColors());
|
73
78
|
}
|
74
79
|
|
75
80
|
getManifestEntries() {
|
@@ -91,6 +96,9 @@ class Images {
|
|
91
96
|
return entries.join("");
|
92
97
|
}
|
93
98
|
|
99
|
+
/**
|
100
|
+
* @param {string} name
|
101
|
+
*/
|
94
102
|
getTaxonImages(name) {
|
95
103
|
return this.#images[name];
|
96
104
|
}
|
@@ -2,25 +2,30 @@ import { EBookPage } from "../ebookpage.js";
|
|
2
2
|
import { XHTML } from "../xhtml.js";
|
3
3
|
|
4
4
|
class PageListFlowerColor extends EBookPage {
|
5
|
-
|
6
5
|
#color;
|
7
6
|
|
8
|
-
|
9
|
-
|
7
|
+
/**
|
8
|
+
* @param {string} outputDir
|
9
|
+
* @param {FlowerColor} color
|
10
|
+
*/
|
11
|
+
constructor(outputDir, color) {
|
12
|
+
super(
|
13
|
+
outputDir + "/" + color.getFileName(),
|
14
|
+
color.getColorName(true) + " Flowers"
|
15
|
+
);
|
10
16
|
this.#color = color;
|
11
17
|
}
|
12
18
|
|
13
19
|
renderPageBody() {
|
14
|
-
|
15
|
-
const html = XHTML.textElement( "h1", this.getTitle() );
|
20
|
+
const html = XHTML.textElement("h1", this.getTitle());
|
16
21
|
|
17
22
|
const links = [];
|
18
|
-
for (
|
19
|
-
links.push(
|
23
|
+
for (const taxon of this.#color.getTaxa()) {
|
24
|
+
links.push(XHTML.getLink(taxon.getFileName(), taxon.getName()));
|
20
25
|
}
|
21
26
|
|
22
|
-
return html + XHTML.wrap(
|
27
|
+
return html + XHTML.wrap("ol", XHTML.arrayToLI(links));
|
23
28
|
}
|
24
29
|
}
|
25
30
|
|
26
|
-
export { PageListFlowerColor };
|
31
|
+
export { PageListFlowerColor };
|
@@ -6,104 +6,122 @@ import { EBook } from "../ebook.js";
|
|
6
6
|
const FN_FLOWER_TIME_INDEX = "fm.html";
|
7
7
|
|
8
8
|
class PageListFlowers {
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
/**
|
10
|
+
* @param {string} contentDir
|
11
|
+
* @param {Taxa} taxa
|
12
|
+
*/
|
13
|
+
static createPages(contentDir, taxa) {
|
14
|
+
new PageListFlowerTimeIndex(contentDir).create();
|
15
|
+
for (let m1 = 1; m1 < 13; m1++) {
|
16
|
+
new PageListFlowerTime(contentDir, taxa, m1).create();
|
14
17
|
}
|
15
18
|
}
|
16
19
|
|
17
20
|
static getManifestEntries() {
|
18
|
-
|
19
21
|
const manifestEntries = [];
|
20
22
|
|
21
|
-
manifestEntries.push(
|
22
|
-
|
23
|
-
|
23
|
+
manifestEntries.push(
|
24
|
+
EBook.getManifestEntry("fm0", FN_FLOWER_TIME_INDEX)
|
25
|
+
);
|
26
|
+
for (let m1 = 1; m1 < 13; m1++) {
|
27
|
+
manifestEntries.push(
|
28
|
+
EBook.getManifestEntry(
|
29
|
+
"fm" + m1,
|
30
|
+
PageListFlowerTime.getFileNameBloomTime(m1)
|
31
|
+
)
|
32
|
+
);
|
24
33
|
}
|
25
34
|
|
26
|
-
return manifestEntries.join(
|
35
|
+
return manifestEntries.join("");
|
27
36
|
}
|
28
37
|
|
29
38
|
static getSpineEntries() {
|
30
|
-
|
31
39
|
const spineEntries = [];
|
32
40
|
|
33
|
-
spineEntries.push(
|
34
|
-
for (
|
35
|
-
spineEntries.push(
|
41
|
+
spineEntries.push(EBook.getSpineEntry("fm0"));
|
42
|
+
for (let m1 = 1; m1 < 13; m1++) {
|
43
|
+
spineEntries.push(EBook.getSpineEntry("fm" + m1));
|
36
44
|
}
|
37
45
|
|
38
|
-
return spineEntries.join(
|
39
|
-
|
46
|
+
return spineEntries.join("");
|
40
47
|
}
|
41
48
|
|
42
49
|
static renderMonthLinks() {
|
43
50
|
const links = [];
|
44
|
-
for (
|
51
|
+
for (let m1 = 1; m1 < 13; m1++) {
|
45
52
|
links.push(
|
46
53
|
XHTML.getLink(
|
47
|
-
PageListFlowerTime.getFileNameBloomTime(
|
48
|
-
DateUtils.getMonthName(
|
54
|
+
PageListFlowerTime.getFileNameBloomTime(m1),
|
55
|
+
DateUtils.getMonthName(m1) +
|
56
|
+
" - " +
|
57
|
+
DateUtils.getMonthName((m1 % 12) + 1)
|
49
58
|
)
|
50
59
|
);
|
51
60
|
}
|
52
|
-
return XHTML.wrap(
|
61
|
+
return XHTML.wrap("ol", XHTML.arrayToLI(links));
|
53
62
|
}
|
54
|
-
|
55
63
|
}
|
56
64
|
|
57
65
|
class PageListFlowerTimeIndex extends EBookPage {
|
58
|
-
|
59
|
-
|
60
|
-
|
66
|
+
/**
|
67
|
+
* @param {string} outputDir
|
68
|
+
*/
|
69
|
+
constructor(outputDir) {
|
70
|
+
super(outputDir + "/" + FN_FLOWER_TIME_INDEX, "Flowering Times");
|
61
71
|
}
|
62
72
|
|
63
73
|
renderPageBody() {
|
64
|
-
const html = XHTML.textElement(
|
74
|
+
const html = XHTML.textElement("h1", this.getTitle());
|
65
75
|
return html + PageListFlowers.renderMonthLinks();
|
66
76
|
}
|
67
|
-
|
68
77
|
}
|
69
78
|
|
70
79
|
class PageListFlowerTime extends EBookPage {
|
71
|
-
|
72
80
|
#taxa;
|
73
81
|
#m1;
|
74
82
|
#m2;
|
75
83
|
|
76
|
-
|
84
|
+
/**
|
85
|
+
* @param {string} outputDir
|
86
|
+
* @param {Taxa} taxa
|
87
|
+
* @param {number} month
|
88
|
+
*/
|
89
|
+
constructor(outputDir, taxa, month) {
|
77
90
|
super(
|
78
|
-
outputDir + "/" + PageListFlowerTime.getFileNameBloomTime(
|
79
|
-
"Flowering in " +
|
91
|
+
outputDir + "/" + PageListFlowerTime.getFileNameBloomTime(month),
|
92
|
+
"Flowering in " +
|
93
|
+
DateUtils.getMonthName(month) +
|
94
|
+
" - " +
|
95
|
+
DateUtils.getMonthName((month % 12) + 1)
|
80
96
|
);
|
81
97
|
this.#taxa = taxa;
|
82
98
|
this.#m1 = month;
|
83
|
-
this.#m2 = month % 12 + 1;
|
99
|
+
this.#m2 = (month % 12) + 1;
|
84
100
|
}
|
85
101
|
|
86
|
-
|
102
|
+
/**
|
103
|
+
* @param {number} m1
|
104
|
+
*/
|
105
|
+
static getFileNameBloomTime(m1) {
|
87
106
|
return "list_fm_" + m1 + ".html";
|
88
107
|
}
|
89
108
|
|
90
109
|
renderPageBody() {
|
110
|
+
const html = XHTML.textElement("h1", this.getTitle());
|
91
111
|
|
92
|
-
|
93
|
-
|
94
|
-
const range = [ this.#m1, this.#m2 ];
|
112
|
+
/** @type {[number,number]} */
|
113
|
+
const range = [this.#m1, this.#m2];
|
95
114
|
const links = [];
|
96
|
-
for (
|
115
|
+
for (const taxon of this.#taxa.getTaxonList()) {
|
97
116
|
const m1 = taxon.getBloomStart();
|
98
117
|
const m2 = taxon.getBloomEnd();
|
99
|
-
if (
|
100
|
-
links.push(
|
118
|
+
if (m1 && m2 && DateUtils.monthRangesOverlap(range, [m1, m2])) {
|
119
|
+
links.push(XHTML.getLink(taxon.getFileName(), taxon.getName()));
|
101
120
|
}
|
102
121
|
}
|
103
122
|
|
104
|
-
return html + XHTML.wrap(
|
123
|
+
return html + XHTML.wrap("ol", XHTML.arrayToLI(links));
|
105
124
|
}
|
106
|
-
|
107
125
|
}
|
108
126
|
|
109
|
-
export { PageListFlowers, PageListFlowerTime };
|
127
|
+
export { PageListFlowers, PageListFlowerTime };
|
@@ -14,7 +14,7 @@ class TaxonPage extends EBookPage {
|
|
14
14
|
/**
|
15
15
|
* @param {string} outputDir
|
16
16
|
* @param {Taxon} taxon
|
17
|
-
* @param {
|
17
|
+
* @param {TaxonImage[]} photos
|
18
18
|
*/
|
19
19
|
constructor(outputDir, taxon, photos) {
|
20
20
|
super(outputDir + "/" + taxon.getFileName(), taxon.getName());
|
@@ -1,26 +1,30 @@
|
|
1
|
-
import { Taxa } from "../../taxa.js";
|
2
1
|
import { EBookPage } from "../ebookpage.js";
|
3
2
|
import { XHTML } from "../xhtml.js";
|
4
3
|
import { PageListFlowers } from "./page_list_flowers.js";
|
5
4
|
|
6
5
|
class TOCPage extends EBookPage {
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
#taxa;
|
7
|
+
|
8
|
+
/**
|
9
|
+
* @param {string} outputDir
|
10
|
+
* @param {Taxa} taxa
|
11
|
+
*/
|
12
|
+
constructor(outputDir, taxa) {
|
13
|
+
super(outputDir + "/toc.xhtml", "Table of Contents");
|
14
|
+
this.#taxa = taxa;
|
10
15
|
}
|
11
16
|
|
12
17
|
renderPageBody() {
|
13
|
-
|
14
|
-
|
15
|
-
html += "<h1 epub:type=\"title\">Table of Contents</h1>";
|
18
|
+
let html = '<nav id="toc" role="doc-toc" epub:type="toc">';
|
19
|
+
html += '<h1 epub:type="title">Table of Contents</h1>';
|
16
20
|
|
17
21
|
const mainLinks = [];
|
18
|
-
mainLinks.push(
|
19
|
-
mainLinks.push(
|
20
|
-
mainLinks.push(
|
21
|
-
mainLinks.push(
|
22
|
-
mainLinks.push(
|
23
|
-
html += XHTML.wrap(
|
22
|
+
mainLinks.push(this.#getFlowerColorLinks());
|
23
|
+
mainLinks.push(this.#getFlowerTimeLinks());
|
24
|
+
mainLinks.push(XHTML.getLink("./list_families.html", "All Families"));
|
25
|
+
mainLinks.push(XHTML.getLink("./list_species.html", "All Species"));
|
26
|
+
mainLinks.push(XHTML.getLink("./glossary.html", "Glossary"));
|
27
|
+
html += XHTML.wrap("ol", XHTML.arrayToLI(mainLinks));
|
24
28
|
|
25
29
|
html += "</nav>";
|
26
30
|
|
@@ -28,19 +32,21 @@ class TOCPage extends EBookPage {
|
|
28
32
|
}
|
29
33
|
|
30
34
|
#getFlowerColorLinks() {
|
31
|
-
const html = XHTML.textElement(
|
35
|
+
const html = XHTML.textElement("span", "Flower Color");
|
32
36
|
const links = [];
|
33
|
-
for (
|
34
|
-
|
37
|
+
for (const color of this.#taxa.getFlowerColors()) {
|
38
|
+
const colorName = color.getColorName();
|
39
|
+
links.push(
|
40
|
+
XHTML.getLink("list_fc_" + colorName + ".html", colorName)
|
41
|
+
);
|
35
42
|
}
|
36
|
-
return html + XHTML.wrap(
|
43
|
+
return html + XHTML.wrap("ol", XHTML.arrayToLI(links));
|
37
44
|
}
|
38
45
|
|
39
46
|
#getFlowerTimeLinks() {
|
40
|
-
const html = XHTML.getLink(
|
47
|
+
const html = XHTML.getLink("fm.html", "Flowering Times");
|
41
48
|
return html + PageListFlowers.renderMonthLinks();
|
42
49
|
}
|
43
|
-
|
44
50
|
}
|
45
51
|
|
46
|
-
export { TOCPage };
|
52
|
+
export { TOCPage };
|
package/lib/ebook/plantbook.js
CHANGED
@@ -8,7 +8,6 @@ import { PageListFlowers } from "./pages/page_list_flowers.js";
|
|
8
8
|
import { PageListSpecies } from "./pages/page_list_species.js";
|
9
9
|
import { TaxonPage } from "./pages/taxonpage.js";
|
10
10
|
import { TOCPage } from "./pages/tocpage.js";
|
11
|
-
import { Taxa } from "../taxa.js";
|
12
11
|
|
13
12
|
class PlantBook extends EBook {
|
14
13
|
#taxa;
|
@@ -16,9 +15,8 @@ class PlantBook extends EBook {
|
|
16
15
|
#images;
|
17
16
|
|
18
17
|
/**
|
19
|
-
*
|
20
18
|
* @param {string} outputDir
|
21
|
-
* @param {
|
19
|
+
* @param {Config} config
|
22
20
|
* @param {Taxa} taxa
|
23
21
|
*/
|
24
22
|
constructor(outputDir, config, taxa) {
|
@@ -52,11 +50,8 @@ class PlantBook extends EBook {
|
|
52
50
|
}
|
53
51
|
|
54
52
|
// Create lists.
|
55
|
-
for (const
|
56
|
-
new PageListFlowerColor(
|
57
|
-
contentDir,
|
58
|
-
this.#taxa.getFlowerColor(colorName)
|
59
|
-
).create();
|
53
|
+
for (const color of this.#taxa.getFlowerColors()) {
|
54
|
+
new PageListFlowerColor(contentDir, color).create();
|
60
55
|
}
|
61
56
|
|
62
57
|
PageListFlowers.createPages(contentDir, this.#taxa);
|
@@ -84,7 +79,7 @@ class PlantBook extends EBook {
|
|
84
79
|
|
85
80
|
this.#glossary.renderPages();
|
86
81
|
|
87
|
-
new TOCPage(contentDir).create();
|
82
|
+
new TOCPage(contentDir, this.#taxa).create();
|
88
83
|
}
|
89
84
|
|
90
85
|
renderManifestEntries() {
|
@@ -95,8 +90,7 @@ class PlantBook extends EBook {
|
|
95
90
|
'<item id="lspecies" href="list_species.html" media-type="application/xhtml+xml" />';
|
96
91
|
xml +=
|
97
92
|
'<item id="lfamilies" href="list_families.html" media-type="application/xhtml+xml" />';
|
98
|
-
for (const
|
99
|
-
const color = this.#taxa.getFlowerColor(colorName);
|
93
|
+
for (const color of this.#taxa.getFlowerColors()) {
|
100
94
|
xml +=
|
101
95
|
'<item id="l' +
|
102
96
|
color.getColorName() +
|
@@ -142,8 +136,7 @@ class PlantBook extends EBook {
|
|
142
136
|
let xml = "";
|
143
137
|
|
144
138
|
// Add lists.
|
145
|
-
for (const
|
146
|
-
const color = this.#taxa.getFlowerColor(colorName);
|
139
|
+
for (const color of this.#taxa.getFlowerColors()) {
|
147
140
|
xml += '<itemref idref="l' + color.getColorName() + '"/>';
|
148
141
|
}
|
149
142
|
xml += PageListFlowers.getSpineEntries();
|
package/lib/exceptions.js
CHANGED
@@ -2,55 +2,71 @@ import { Config } from "./config.js";
|
|
2
2
|
import { Files } from "./files.js";
|
3
3
|
|
4
4
|
class Exceptions {
|
5
|
-
|
5
|
+
/** @type {Object<string,Object<string,Object<string,{}>>>} */
|
6
6
|
#exceptions = {};
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
/**
|
9
|
+
* @param {string} dir
|
10
|
+
*/
|
11
|
+
constructor(dir) {
|
12
|
+
/**
|
13
|
+
* @param {string} fileName
|
14
|
+
*/
|
15
|
+
function readConfig(fileName) {
|
16
|
+
return JSON.parse(Files.read(fileName));
|
12
17
|
}
|
13
18
|
|
14
19
|
// Read default configuration.
|
15
|
-
this.#exceptions = readConfig(
|
20
|
+
this.#exceptions = readConfig(
|
21
|
+
Config.getPackageDir() + "/data/exceptions.json"
|
22
|
+
);
|
16
23
|
|
17
24
|
// Add/overwrite with local configuration.
|
18
|
-
const localExceptions = readConfig(
|
19
|
-
for (
|
20
|
-
this.#exceptions[
|
25
|
+
const localExceptions = readConfig(dir + "/exceptions.json");
|
26
|
+
for (const [k, v] of Object.entries(localExceptions)) {
|
27
|
+
this.#exceptions[k] = v;
|
21
28
|
// Tag as a local exception so we can distinguish between global and local.
|
22
29
|
v.local = true;
|
23
30
|
}
|
24
|
-
|
25
31
|
}
|
26
32
|
|
27
33
|
getExceptions() {
|
28
|
-
return Object.entries(
|
34
|
+
return Object.entries(this.#exceptions);
|
29
35
|
}
|
30
36
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
/**
|
38
|
+
* @param {string} name
|
39
|
+
* @param {string} cat
|
40
|
+
* @param {string} subcat
|
41
|
+
* @param {string} defaultValue
|
42
|
+
*/
|
43
|
+
getValue(name, cat, subcat, defaultValue) {
|
44
|
+
const taxonData = this.#exceptions[name];
|
45
|
+
if (taxonData) {
|
46
|
+
const catData = taxonData[cat];
|
47
|
+
if (catData) {
|
48
|
+
const val = catData[subcat];
|
49
|
+
return val === undefined ? defaultValue : val;
|
38
50
|
}
|
39
51
|
}
|
40
52
|
return defaultValue;
|
41
53
|
}
|
42
54
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
55
|
+
/**
|
56
|
+
* @param {string} name
|
57
|
+
* @param {string} cat
|
58
|
+
* @param {string} subcat
|
59
|
+
*/
|
60
|
+
hasException(name, cat, subcat) {
|
61
|
+
const taxonData = this.#exceptions[name];
|
62
|
+
if (taxonData) {
|
63
|
+
const catData = taxonData[cat];
|
64
|
+
if (catData) {
|
65
|
+
return catData[subcat] !== undefined;
|
49
66
|
}
|
50
67
|
}
|
51
68
|
return false;
|
52
69
|
}
|
53
|
-
|
54
70
|
}
|
55
71
|
|
56
|
-
export { Exceptions };
|
72
|
+
export { Exceptions };
|