@ca-plant-list/ca-plant-list 0.3.2 → 0.3.4
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 +4 -2
- package/data/exceptions.json +0 -3
- package/data/glossary/calyx.md +1 -0
- package/data/glossary/ovary.md +3 -0
- package/data/glossary/pedicel.md +1 -0
- package/data/glossary/pistil.md +3 -0
- package/data/glossary/sepal.md +1 -0
- package/data/glossary/stigma.md +3 -0
- package/data/glossary/style.md +3 -0
- package/data/illustrations/inkscape/pistil.svg +156 -0
- package/data/synonyms.csv +8 -3
- package/data/taxa.csv +77 -72
- package/data/text/Calochortus-argillosus.md +1 -0
- package/data/text/Calochortus-luteus.md +1 -0
- package/data/text/Calochortus-venustus.md +1 -0
- package/data/text/Ceanothus-cuneatus-var-cuneatus.md +1 -0
- package/data/text/Ceanothus-leucodermis.md +1 -0
- package/data/text/Claytonia-parviflora.md +1 -0
- package/data/text/Claytonia-perfoliata.md +1 -0
- package/data/text/Collinsia-heterophylla-var-heterophylla.md +1 -0
- package/data/text/Delphinium-californicum-subsp-californicum.md +1 -0
- package/data/text/Delphinium-decorum-subsp-decorum.md +1 -0
- package/data/text/Delphinium-hesperium-subsp-hesperium.md +1 -0
- package/data/text/Delphinium-patens-subsp-patens.md +1 -0
- package/data/text/Galium-andrewsii-subsp-gatense.md +1 -0
- package/data/text/Helianthella-californica-var-californica.md +1 -0
- package/data/text/Helianthella-castanea.md +1 -0
- package/data/text/Iris-macrosiphon.md +1 -0
- package/data/text/Lasthenia-californica-subsp-californica.md +1 -0
- package/data/text/Lasthenia-gracilis.md +1 -0
- package/data/text/Leptosiphon-ambiguus.md +1 -0
- package/data/text/Leptosiphon-androsaceus.md +1 -0
- package/data/text/Leptosiphon-bicolor.md +1 -1
- package/data/text/Leptosiphon-parviflorus.md +1 -0
- package/data/text/Lithophragma-affine.md +1 -1
- package/data/text/Lithophragma-parviflorum-var-parviflorum.md +1 -1
- package/data/text/Lomatium-californicum.md +0 -0
- package/data/text/Lomatium-dasycarpum-subsp-dasycarpum.md +1 -0
- package/data/text/Lomatium-utriculatum.md +1 -0
- package/data/text/Nemophila-heterophylla.md +1 -0
- package/data/text/Nemophila-parviflora-var-parviflora.md +1 -0
- package/data/text/Plectritis-ciliosa.md +1 -0
- package/data/text/Plectritis-macrocera.md +1 -0
- package/data/text/Primula-clevelandii-var-patula.md +1 -0
- package/data/text/Primula-hendersonii.md +1 -0
- package/data/text/Sidalcea-diploscypha.md +1 -0
- package/data/text/Thysanocarpus-curvipes.md +1 -0
- package/data/text/Thysanocarpus-laciniatus.md +1 -0
- package/data/text/Viola-douglasii.md +1 -0
- package/data/text/Viola-pedunculata.md +1 -0
- package/data/text/Viola-purpurea-subsp-quercetorum.md +1 -0
- package/ebook/css/main.css +5 -0
- package/lib/basepagerenderer.js +30 -29
- package/lib/dateutils.js +36 -16
- package/lib/ebook/pages/page_list_families.js +15 -9
- package/lib/ebook/pages/taxonpage.js +63 -36
- package/lib/ebook/plantbook.js +82 -48
- package/lib/errorlog.js +16 -11
- package/lib/families.js +109 -74
- package/lib/files.js +103 -45
- package/lib/genera.js +40 -26
- package/lib/generictaxaloader.js +15 -7
- package/lib/index.js +38 -3
- package/lib/taxa.js +174 -87
- package/lib/taxaloader.js +28 -15
- package/lib/taxaprocessor.js +6 -8
- package/lib/taxon.js +115 -57
- package/package.json +4 -6
- package/scripts/build-ebook.js +33 -25
- package/lib/index.d.ts +0 -345
package/lib/basepagerenderer.js
CHANGED
@@ -1,58 +1,59 @@
|
|
1
1
|
import { Config } from "./config.js";
|
2
|
-
import { Families } from "./families.js";
|
3
2
|
import { Files } from "./files.js";
|
4
3
|
import { Jekyll } from "./jekyll.js";
|
5
4
|
import { Taxa } from "./taxa.js";
|
6
5
|
import { GlossaryPages } from "./web/glossarypages.js";
|
7
6
|
|
8
7
|
class BasePageRenderer {
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
/**
|
9
|
+
* @param {string} outputDir
|
10
|
+
* @param {Taxa} taxa
|
11
|
+
* @param {*} familyCols
|
12
|
+
*/
|
13
|
+
static render(outputDir, taxa, familyCols) {
|
14
|
+
const siteGenerator = new Jekyll(outputDir);
|
13
15
|
|
14
16
|
// Copy static files
|
15
17
|
// First copy default Jekyll files from package.
|
16
|
-
Files.copyDir(
|
18
|
+
Files.copyDir(Config.getPackageDir() + "/jekyll", outputDir);
|
17
19
|
// Then copy Jekyll files from current dir (which may override default files).
|
18
|
-
Files.copyDir(
|
20
|
+
Files.copyDir("jekyll", outputDir);
|
19
21
|
|
20
22
|
// Copy illustrations.
|
21
|
-
siteGenerator.copyIllustrations(
|
23
|
+
siteGenerator.copyIllustrations(Taxa.getFlowerColors());
|
22
24
|
|
23
|
-
|
25
|
+
taxa.getFamilies().renderPages(outputDir, familyCols);
|
24
26
|
|
25
|
-
new GlossaryPages(
|
26
|
-
|
27
|
-
this.renderTools( outputDir, taxa );
|
27
|
+
new GlossaryPages(siteGenerator).renderPages();
|
28
28
|
|
29
|
+
this.renderTools(outputDir, taxa);
|
29
30
|
}
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
/**
|
33
|
+
* @param {string} outputDir
|
34
|
+
* @param {Taxa} taxa
|
35
|
+
*/
|
36
|
+
static renderTools(outputDir, taxa) {
|
33
37
|
const names = [];
|
34
|
-
for (
|
38
|
+
for (const taxon of taxa.getTaxonList()) {
|
35
39
|
const row = [];
|
36
|
-
row.push(
|
37
|
-
const cn = taxon.getCommonNames().join(
|
38
|
-
if (
|
39
|
-
row.push(
|
40
|
+
row.push(taxon.getName());
|
41
|
+
const cn = taxon.getCommonNames().join(", ");
|
42
|
+
if (cn) {
|
43
|
+
row.push(cn);
|
40
44
|
}
|
41
45
|
const synonyms = [];
|
42
|
-
for (
|
43
|
-
synonyms.push(
|
46
|
+
for (const syn of taxon.getSynonyms()) {
|
47
|
+
synonyms.push(syn);
|
44
48
|
}
|
45
|
-
if (
|
46
|
-
row[
|
49
|
+
if (synonyms.length > 0) {
|
50
|
+
row[2] = synonyms;
|
47
51
|
}
|
48
|
-
names.push(
|
52
|
+
names.push(row);
|
49
53
|
}
|
50
54
|
|
51
|
-
Files.write(
|
52
|
-
|
55
|
+
Files.write(outputDir + "/_includes/names.json", JSON.stringify(names));
|
53
56
|
}
|
54
|
-
|
55
|
-
|
56
57
|
}
|
57
58
|
|
58
|
-
export { BasePageRenderer };
|
59
|
+
export { BasePageRenderer };
|
package/lib/dateutils.js
CHANGED
@@ -14,30 +14,50 @@ const MONTH_NAMES = [
|
|
14
14
|
];
|
15
15
|
|
16
16
|
class DateUtils {
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
/**
|
18
|
+
* @param {number} monthNum Starting with 1 for January.
|
19
|
+
* @returns {string}
|
20
|
+
*/
|
21
|
+
static getMonthName(monthNum) {
|
22
|
+
return MONTH_NAMES[monthNum - 1];
|
20
23
|
}
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
/**
|
26
|
+
* @param {[number,number]} r1
|
27
|
+
* @param {[number,number]} r2
|
28
|
+
* @returns {boolean}
|
29
|
+
*/
|
30
|
+
static monthRangesOverlap(r1, r2) {
|
31
|
+
/**
|
32
|
+
* @param {[number,number]} r1
|
33
|
+
* @param {[number,number]} r2
|
34
|
+
*/
|
35
|
+
function contains(r1, r2) {
|
36
|
+
/**
|
37
|
+
* @param {number} v
|
38
|
+
* @param {[number,number]} r
|
39
|
+
*/
|
40
|
+
function inRange(v, r) {
|
41
|
+
return v >= r[0] && v <= r[1];
|
27
42
|
}
|
28
|
-
return inRange(
|
43
|
+
return inRange(r1[0], r2) || inRange(r1[1], r2);
|
29
44
|
}
|
30
45
|
|
31
46
|
// If ranges cross into next year, split them in 2.
|
32
|
-
if (
|
33
|
-
return
|
47
|
+
if (r1[0] > r1[1]) {
|
48
|
+
return (
|
49
|
+
this.monthRangesOverlap([r1[0], 12], r2) ||
|
50
|
+
this.monthRangesOverlap([1, r1[1]], r2)
|
51
|
+
);
|
34
52
|
}
|
35
|
-
if (
|
36
|
-
return
|
53
|
+
if (r2[0] > r2[1]) {
|
54
|
+
return (
|
55
|
+
this.monthRangesOverlap(r1, [r2[0], 12]) ||
|
56
|
+
this.monthRangesOverlap(r1, [1, r2[1]])
|
57
|
+
);
|
37
58
|
}
|
38
|
-
return contains(
|
59
|
+
return contains(r1, r2) || contains(r2, r1);
|
39
60
|
}
|
40
|
-
|
41
61
|
}
|
42
62
|
|
43
|
-
export { DateUtils };
|
63
|
+
export { DateUtils };
|
@@ -1,27 +1,33 @@
|
|
1
1
|
import { EBookPage } from "../ebookpage.js";
|
2
2
|
import { XHTML } from "../xhtml.js";
|
3
|
+
// eslint-disable-next-line no-unused-vars
|
3
4
|
import { Families } from "../../families.js";
|
4
5
|
|
5
6
|
class PageListFamilies extends EBookPage {
|
7
|
+
#families;
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
/**
|
10
|
+
* @param {string} outputDir
|
11
|
+
* @param {Families} families
|
12
|
+
*/
|
13
|
+
constructor(outputDir, families) {
|
14
|
+
super(outputDir + "/list_families.html", "All Families");
|
15
|
+
this.#families = families;
|
9
16
|
}
|
10
17
|
|
11
18
|
renderPageBody() {
|
12
|
-
|
13
|
-
const html = XHTML.textElement( "h1", this.getTitle() );
|
19
|
+
const html = XHTML.textElement("h1", this.getTitle());
|
14
20
|
|
15
21
|
const links = [];
|
16
|
-
for (
|
17
|
-
if (
|
22
|
+
for (const family of this.#families.getFamilies()) {
|
23
|
+
if (!family.getTaxa()) {
|
18
24
|
continue;
|
19
25
|
}
|
20
|
-
links.push(
|
26
|
+
links.push(XHTML.getLink(family.getFileName(), family.getName()));
|
21
27
|
}
|
22
28
|
|
23
|
-
return html + XHTML.wrap(
|
29
|
+
return html + XHTML.wrap("ol", XHTML.arrayToLI(links));
|
24
30
|
}
|
25
31
|
}
|
26
32
|
|
27
|
-
export { PageListFamilies };
|
33
|
+
export { PageListFamilies };
|
@@ -4,88 +4,115 @@ import { EBookPage } from "../ebookpage.js";
|
|
4
4
|
import { XHTML } from "../xhtml.js";
|
5
5
|
import { Markdown } from "../../markdown.js";
|
6
6
|
import { DateUtils } from "../../dateutils.js";
|
7
|
+
// eslint-disable-next-line no-unused-vars
|
8
|
+
import { Taxon } from "../../taxon.js";
|
7
9
|
|
8
10
|
class TaxonPage extends EBookPage {
|
9
|
-
|
10
11
|
#outputDir;
|
11
12
|
#taxon;
|
12
13
|
#photos;
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
/**
|
16
|
+
*
|
17
|
+
* @param {string} outputDir
|
18
|
+
* @param {Taxon} taxon
|
19
|
+
* @param {*} photos
|
20
|
+
*/
|
21
|
+
constructor(outputDir, taxon, photos) {
|
22
|
+
super(outputDir + "/" + taxon.getFileName(), taxon.getName());
|
16
23
|
this.#outputDir = outputDir;
|
17
24
|
this.#taxon = taxon;
|
18
25
|
this.#photos = photos;
|
19
26
|
}
|
20
27
|
|
21
28
|
renderPageBody() {
|
22
|
-
|
23
|
-
|
29
|
+
/**
|
30
|
+
* @param {Taxon} taxon
|
31
|
+
*/
|
32
|
+
function renderBloomInfo(taxon) {
|
24
33
|
const colors = taxon.getFlowerColors();
|
25
34
|
const monthStart = taxon.getBloomStart();
|
26
35
|
const monthEnd = taxon.getBloomEnd();
|
27
|
-
if (
|
36
|
+
if (!colors && !monthStart) {
|
28
37
|
return "";
|
29
38
|
}
|
30
39
|
let html = "";
|
31
|
-
if (
|
32
|
-
for (
|
33
|
-
html += XHTML.textElement(
|
40
|
+
if (colors) {
|
41
|
+
for (const color of colors) {
|
42
|
+
html += XHTML.textElement("img", "", {
|
43
|
+
src: "./i/f-" + color + ".svg",
|
44
|
+
class: "flr",
|
45
|
+
});
|
34
46
|
}
|
35
47
|
}
|
36
|
-
if (
|
37
|
-
html += XHTML.textElement(
|
38
|
-
|
48
|
+
if (monthStart && monthEnd) {
|
49
|
+
html += XHTML.textElement(
|
50
|
+
"div",
|
51
|
+
DateUtils.getMonthName(monthStart) +
|
52
|
+
"-" +
|
53
|
+
DateUtils.getMonthName(monthEnd)
|
54
|
+
);
|
39
55
|
}
|
40
|
-
return XHTML.wrap(
|
56
|
+
return XHTML.wrap("div", html, { class: "section flr" });
|
41
57
|
}
|
42
58
|
|
43
|
-
|
44
|
-
|
59
|
+
/**
|
60
|
+
* @param {string} name
|
61
|
+
*/
|
62
|
+
function renderCustomText(name) {
|
45
63
|
// See if there is custom text.
|
46
|
-
const fileName =
|
47
|
-
|
64
|
+
const fileName =
|
65
|
+
Config.getPackageDir() + "/data/text/" + name + ".md";
|
66
|
+
if (!Files.exists(fileName)) {
|
48
67
|
return "";
|
49
68
|
}
|
50
|
-
const text = Files.read(
|
51
|
-
return Markdown.strToHTML(
|
69
|
+
const text = Files.read(fileName);
|
70
|
+
return Markdown.strToHTML(text);
|
52
71
|
}
|
53
72
|
|
54
73
|
const name = this.#taxon.getName();
|
55
|
-
let html = XHTML.textElement(
|
74
|
+
let html = XHTML.textElement("h1", name);
|
56
75
|
|
57
76
|
const family = this.#taxon.getFamily();
|
58
|
-
html += XHTML.wrap(
|
77
|
+
html += XHTML.wrap(
|
78
|
+
"div",
|
79
|
+
XHTML.getLink(family.getFileName(), family.getName()),
|
80
|
+
{ class: "section" }
|
81
|
+
);
|
59
82
|
|
60
83
|
const cn = this.#taxon.getCommonNames();
|
61
|
-
if (
|
62
|
-
html += XHTML.textElement(
|
84
|
+
if (cn && cn.length > 0) {
|
85
|
+
html += XHTML.textElement("div", cn.join(", "), {
|
86
|
+
class: "section",
|
87
|
+
});
|
63
88
|
}
|
64
89
|
|
65
|
-
html += renderBloomInfo(
|
90
|
+
html += renderBloomInfo(this.#taxon);
|
66
91
|
|
67
|
-
html += renderCustomText(
|
92
|
+
html += renderCustomText(this.#taxon.getBaseFileName());
|
68
93
|
|
69
|
-
if (
|
94
|
+
if (this.#photos) {
|
70
95
|
let photoHTML = "";
|
71
|
-
for (
|
96
|
+
for (const photo of this.#photos) {
|
72
97
|
const src = photo.getSrc();
|
73
|
-
const dimensions = sizeOf(
|
74
|
-
let img = XHTML.textElement(
|
98
|
+
const dimensions = sizeOf(this.#outputDir + "/" + src);
|
99
|
+
let img = XHTML.textElement("img", "", {
|
100
|
+
src: src,
|
101
|
+
style: "max-width:" + dimensions.width + "px",
|
102
|
+
});
|
75
103
|
const caption = photo.getCaption();
|
76
|
-
if (
|
77
|
-
img += XHTML.textElement(
|
104
|
+
if (caption) {
|
105
|
+
img += XHTML.textElement("figcaption", caption);
|
78
106
|
}
|
79
|
-
photoHTML += XHTML.wrap(
|
107
|
+
photoHTML += XHTML.wrap("figure", img);
|
80
108
|
}
|
81
|
-
if (
|
82
|
-
html += XHTML.wrap(
|
109
|
+
if (photoHTML) {
|
110
|
+
html += XHTML.wrap("div", photoHTML);
|
83
111
|
}
|
84
112
|
}
|
85
113
|
|
86
114
|
return html;
|
87
115
|
}
|
88
|
-
|
89
116
|
}
|
90
117
|
|
91
|
-
export { TaxonPage };
|
118
|
+
export { TaxonPage };
|
package/lib/ebook/plantbook.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import { Families } from "@ca-plant-list/ca-plant-list";
|
2
1
|
import { EBook } from "./ebook.js";
|
3
2
|
import { EBookSiteGenerator } from "./ebooksitegenerator.js";
|
4
3
|
import { GlossaryPages } from "./glossarypages.js";
|
@@ -12,89 +11,124 @@ import { TOCPage } from "./pages/tocpage.js";
|
|
12
11
|
import { Taxa } from "../taxa.js";
|
13
12
|
|
14
13
|
class PlantBook extends EBook {
|
15
|
-
|
16
14
|
#taxa;
|
17
15
|
#glossary;
|
18
16
|
#images;
|
19
17
|
|
20
|
-
|
21
|
-
|
18
|
+
/**
|
19
|
+
*
|
20
|
+
* @param {string} outputDir
|
21
|
+
* @param {*} config
|
22
|
+
* @param {Taxa} taxa
|
23
|
+
*/
|
24
|
+
constructor(outputDir, config, taxa) {
|
22
25
|
super(
|
23
26
|
outputDir,
|
24
|
-
config.getConfigValue(
|
25
|
-
config.getConfigValue(
|
26
|
-
config.getConfigValue(
|
27
|
+
config.getConfigValue("ebook", "filename"),
|
28
|
+
config.getConfigValue("ebook", "pub_id"),
|
29
|
+
config.getConfigValue("ebook", "title")
|
27
30
|
);
|
28
31
|
|
29
32
|
this.#taxa = taxa;
|
30
|
-
const generator = new EBookSiteGenerator(
|
31
|
-
this.#glossary = new GlossaryPages(
|
32
|
-
this.#images = new Images(
|
33
|
-
|
33
|
+
const generator = new EBookSiteGenerator(this.getContentDir());
|
34
|
+
this.#glossary = new GlossaryPages(generator);
|
35
|
+
this.#images = new Images(generator, this.getContentDir(), taxa);
|
34
36
|
}
|
35
37
|
|
36
38
|
async createPages() {
|
37
|
-
|
38
39
|
const contentDir = this.getContentDir();
|
39
40
|
|
40
|
-
await this.#images.createImages(
|
41
|
+
await this.#images.createImages();
|
41
42
|
|
42
|
-
console.log(
|
43
|
+
console.log("creating taxon pages");
|
43
44
|
const taxonList = this.#taxa.getTaxonList();
|
44
|
-
for (
|
45
|
+
for (const taxon of taxonList) {
|
45
46
|
const name = taxon.getName();
|
46
|
-
new TaxonPage(
|
47
|
+
new TaxonPage(
|
48
|
+
contentDir,
|
49
|
+
taxon,
|
50
|
+
this.#images.getTaxonImages(name)
|
51
|
+
).create();
|
47
52
|
}
|
48
53
|
|
49
54
|
// Create lists.
|
50
|
-
for (
|
51
|
-
new PageListFlowerColor(
|
55
|
+
for (const colorName of Taxa.getFlowerColorNames()) {
|
56
|
+
new PageListFlowerColor(
|
57
|
+
contentDir,
|
58
|
+
this.#taxa.getFlowerColor(colorName)
|
59
|
+
).create();
|
52
60
|
}
|
53
61
|
|
54
|
-
PageListFlowers.createPages(
|
62
|
+
PageListFlowers.createPages(contentDir, this.#taxa);
|
55
63
|
|
56
|
-
new PageListFamilies(
|
57
|
-
for (
|
64
|
+
new PageListFamilies(contentDir, this.#taxa.getFamilies()).create();
|
65
|
+
for (const family of this.#taxa.getFamilies().getFamilies()) {
|
58
66
|
const taxa = family.getTaxa();
|
59
|
-
if (
|
67
|
+
if (!taxa) {
|
60
68
|
continue;
|
61
69
|
}
|
62
70
|
const name = family.getName();
|
63
|
-
new PageListSpecies(
|
71
|
+
new PageListSpecies(
|
72
|
+
contentDir,
|
73
|
+
taxa,
|
74
|
+
name + ".html",
|
75
|
+
name
|
76
|
+
).create();
|
64
77
|
}
|
65
|
-
new PageListSpecies(
|
78
|
+
new PageListSpecies(
|
79
|
+
contentDir,
|
80
|
+
taxonList,
|
81
|
+
"list_species.html",
|
82
|
+
"All Species"
|
83
|
+
).create();
|
66
84
|
|
67
85
|
this.#glossary.renderPages();
|
68
86
|
|
69
|
-
new TOCPage(
|
87
|
+
new TOCPage(contentDir).create();
|
70
88
|
}
|
71
89
|
|
72
90
|
renderManifestEntries() {
|
73
|
-
|
74
91
|
let xml = "";
|
75
92
|
|
76
93
|
// Add lists.
|
77
|
-
xml +=
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
94
|
+
xml +=
|
95
|
+
'<item id="lspecies" href="list_species.html" media-type="application/xhtml+xml" />';
|
96
|
+
xml +=
|
97
|
+
'<item id="lfamilies" href="list_families.html" media-type="application/xhtml+xml" />';
|
98
|
+
for (const colorName of Taxa.getFlowerColorNames()) {
|
99
|
+
const color = this.#taxa.getFlowerColor(colorName);
|
100
|
+
xml +=
|
101
|
+
'<item id="l' +
|
102
|
+
color.getColorName() +
|
103
|
+
'" href="' +
|
104
|
+
color.getFileName() +
|
105
|
+
'" media-type="application/xhtml+xml" />';
|
82
106
|
}
|
83
107
|
|
84
108
|
// Add family pages.
|
85
|
-
for (
|
109
|
+
for (const family of this.#taxa.getFamilies().getFamilies()) {
|
86
110
|
const taxa = family.getTaxa();
|
87
|
-
if (
|
111
|
+
if (!taxa) {
|
88
112
|
continue;
|
89
113
|
}
|
90
|
-
xml +=
|
114
|
+
xml +=
|
115
|
+
'<item id="fam' +
|
116
|
+
family.getName() +
|
117
|
+
'" href="' +
|
118
|
+
family.getFileName() +
|
119
|
+
'" media-type="application/xhtml+xml" />';
|
91
120
|
}
|
92
121
|
|
93
122
|
// Add taxon pages.
|
94
123
|
const taxa = this.#taxa.getTaxonList();
|
95
|
-
for (
|
96
|
-
const taxon = taxa[
|
97
|
-
xml +=
|
124
|
+
for (let index = 0; index < taxa.length; index++) {
|
125
|
+
const taxon = taxa[index];
|
126
|
+
xml +=
|
127
|
+
'<item id="t' +
|
128
|
+
index +
|
129
|
+
'" href="' +
|
130
|
+
taxon.getFileName() +
|
131
|
+
'" media-type="application/xhtml+xml" />';
|
98
132
|
}
|
99
133
|
|
100
134
|
xml += PageListFlowers.getManifestEntries();
|
@@ -108,27 +142,27 @@ class PlantBook extends EBook {
|
|
108
142
|
let xml = "";
|
109
143
|
|
110
144
|
// Add lists.
|
111
|
-
for (
|
112
|
-
const color = this.#taxa.getFlowerColor(
|
113
|
-
xml +=
|
145
|
+
for (const colorName of Taxa.getFlowerColorNames()) {
|
146
|
+
const color = this.#taxa.getFlowerColor(colorName);
|
147
|
+
xml += '<itemref idref="l' + color.getColorName() + '"/>';
|
114
148
|
}
|
115
149
|
xml += PageListFlowers.getSpineEntries();
|
116
150
|
|
117
|
-
xml +=
|
118
|
-
xml +=
|
151
|
+
xml += '<itemref idref="lfamilies"/>';
|
152
|
+
xml += '<itemref idref="lspecies"/>';
|
119
153
|
|
120
154
|
// Add families.
|
121
|
-
for (
|
155
|
+
for (const family of this.#taxa.getFamilies().getFamilies()) {
|
122
156
|
const taxa = family.getTaxa();
|
123
|
-
if (
|
157
|
+
if (!taxa) {
|
124
158
|
continue;
|
125
159
|
}
|
126
|
-
xml +=
|
160
|
+
xml += '<itemref idref="fam' + family.getName() + '"/>';
|
127
161
|
}
|
128
162
|
|
129
163
|
// Add taxa.
|
130
|
-
for (
|
131
|
-
xml +=
|
164
|
+
for (let index = 0; index < this.#taxa.getTaxonList().length; index++) {
|
165
|
+
xml += '<itemref idref="t' + index + '"/>';
|
132
166
|
}
|
133
167
|
|
134
168
|
xml += this.#glossary.getSpineEntries();
|
@@ -137,4 +171,4 @@ class PlantBook extends EBook {
|
|
137
171
|
}
|
138
172
|
}
|
139
173
|
|
140
|
-
export { PlantBook };
|
174
|
+
export { PlantBook };
|
package/lib/errorlog.js
CHANGED
@@ -2,30 +2,35 @@ import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
3
3
|
|
4
4
|
class ErrorLog {
|
5
|
-
|
6
5
|
#fileName;
|
7
6
|
#echo;
|
7
|
+
/** @type string[] */
|
8
8
|
#errors = [];
|
9
9
|
|
10
|
-
|
10
|
+
/**
|
11
|
+
* @param {string} fileName
|
12
|
+
* @param {boolean} echo
|
13
|
+
*/
|
14
|
+
constructor(fileName, echo = false) {
|
11
15
|
this.#fileName = fileName;
|
12
16
|
this.#echo = echo;
|
13
17
|
}
|
14
18
|
|
15
|
-
|
16
|
-
|
17
|
-
|
19
|
+
/**
|
20
|
+
* @param {...string} args
|
21
|
+
*/
|
22
|
+
log(...args) {
|
23
|
+
if (this.#echo) {
|
24
|
+
console.log(args.join());
|
18
25
|
}
|
19
|
-
this.#errors.push(
|
26
|
+
this.#errors.push(args.join("\t"));
|
20
27
|
}
|
21
28
|
|
22
29
|
write() {
|
23
30
|
// Make sure directory exists.
|
24
|
-
fs.mkdirSync(
|
25
|
-
|
26
|
-
fs.writeFileSync( this.#fileName, this.#errors.join( "\n" ) );
|
31
|
+
fs.mkdirSync(path.dirname(this.#fileName), { recursive: true });
|
32
|
+
fs.writeFileSync(this.#fileName, this.#errors.join("\n"));
|
27
33
|
}
|
28
|
-
|
29
34
|
}
|
30
35
|
|
31
|
-
export { ErrorLog };
|
36
|
+
export { ErrorLog };
|