@ca-plant-list/ca-plant-list 0.3.5 → 0.3.7
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/synonyms.csv +24 -1
- package/data/taxa.csv +117 -99
- package/data/text/Antirrhinum-thompsonii.md +1 -0
- package/data/text/Calyptridium-monospermum.md +1 -0
- package/data/text/Calyptridium-ubellatum.md +1 -0
- package/data/text/Clarkia-affinis.md +1 -0
- package/data/text/Clarkia-breweri.md +1 -0
- package/data/text/Clarkia-concinna-subsp-automixa.md +1 -0
- package/data/text/Clarkia-modesta.md +1 -0
- package/data/text/Clarkia-purpurea-subsp-quadrivulnera.md +1 -0
- package/data/text/Clarkia-rubicunda.md +1 -0
- package/data/text/Delphinium-californicum-subsp-californicum.md +1 -1
- package/data/text/Delphinium-californicum-subsp-interius.md +1 -0
- package/data/text/Delphinium-hesperium-subsp-hesperium.md +1 -1
- package/data/text/Delphinium-hesperium-subsp-pallescens.md +1 -0
- package/data/text/Delphinium-parryi-subsp-parryi.md +1 -0
- package/data/text/Delphinium-variegatum-subsp-variegatum.md +1 -0
- package/data/text/Erythranthe-moschata.md +1 -0
- package/data/text/Erythranthe-primuloides.md +1 -0
- package/data/text/Erythranthe-tilingii.md +1 -0
- package/data/text/Fritillaria-affinis.md +1 -0
- package/data/text/Fritillaria-agrestis.md +1 -0
- package/data/text/Fritillaria-liliacea.md +1 -0
- package/data/text/Lilium-pardalinum-subsp-shastense.md +1 -0
- package/data/text/Logfia-filaginoides.md +1 -0
- package/data/text/Logfia-gallica.md +1 -0
- package/data/text/Malacothamnus-arcuatus-var-elmeri.md +1 -0
- package/data/text/Malacothamnus-fremontii-var-fremontii.md +1 -0
- package/data/text/Trifolium-obtusiflorum.md +1 -0
- package/data/text/Trifolium-willdenovii.md +1 -0
- package/ebook/css/main.css +4 -0
- package/jekyll/assets/css/main.css +4 -0
- package/lib/ebook/images.js +49 -40
- package/lib/ebook/pages/page_list_species.js +15 -9
- package/lib/ebook/pages/taxonpage.js +3 -6
- package/lib/ebook/xhtml.js +3 -5
- package/lib/externalsites.js +14 -21
- package/lib/families.js +0 -2
- package/lib/genera.js +1 -3
- package/lib/genericpage.js +26 -18
- package/lib/generictaxaloader.js +1 -1
- package/lib/htmltaxon.js +35 -17
- package/lib/markdown.js +7 -9
- package/lib/pagerenderer.js +127 -82
- package/lib/plants/glossary.js +9 -14
- package/lib/taxa.js +14 -15
- package/lib/taxaloader.js +3 -1
- package/lib/taxon.js +2 -4
- package/lib/web/glossarypages.js +31 -18
- package/lib/web/pagetaxon.js +0 -10
- package/package.json +2 -3
- package/scripts/build-ebook.js +1 -1
- package/scripts/build-site.js +34 -24
- package/types/classes.d.ts +26 -0
@@ -0,0 +1 @@
|
|
1
|
+
Similar to _T. obtusiflorum_, but with shorter teeth on leaves, [calyx](./g/calyx.html) not hairy or bumpy.
|
package/ebook/css/main.css
CHANGED
package/lib/ebook/images.js
CHANGED
@@ -3,88 +3,97 @@ import path from "node:path";
|
|
3
3
|
|
4
4
|
import sharp from "sharp";
|
5
5
|
|
6
|
-
import { Config, CSV, Files } from "@ca-plant-list/ca-plant-list";
|
7
|
-
|
8
6
|
import { Image } from "./image.js";
|
9
7
|
import { EBook } from "./ebook.js";
|
10
8
|
import { Taxa } from "../taxa.js";
|
9
|
+
import { Config } from "../config.js";
|
10
|
+
import { CSV } from "../csv.js";
|
11
|
+
import { Files } from "../files.js";
|
11
12
|
|
12
13
|
class Images {
|
13
|
-
|
14
14
|
#siteGenerator;
|
15
15
|
#contentDir;
|
16
16
|
#taxa;
|
17
17
|
#images = {};
|
18
18
|
|
19
|
-
constructor(
|
19
|
+
constructor(siteGenerator, contentDir, taxa) {
|
20
20
|
this.#siteGenerator = siteGenerator;
|
21
21
|
this.#contentDir = contentDir;
|
22
22
|
this.#taxa = taxa;
|
23
23
|
}
|
24
24
|
|
25
25
|
async createImages() {
|
26
|
-
|
27
26
|
const photoDirSrc = "external_data/photos";
|
28
27
|
const imagePrefix = "i";
|
29
28
|
const photoDirTarget = this.#contentDir + "/" + imagePrefix;
|
30
|
-
fs.mkdirSync(
|
31
|
-
fs.mkdirSync(
|
32
|
-
|
33
|
-
const rows = CSV.parseFile(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
29
|
+
fs.mkdirSync(photoDirSrc, { recursive: true });
|
30
|
+
fs.mkdirSync(photoDirTarget, { recursive: true });
|
31
|
+
|
32
|
+
const rows = CSV.parseFile(
|
33
|
+
Config.getPackageDir() + "/data",
|
34
|
+
"photos.csv"
|
35
|
+
);
|
36
|
+
for (const row of rows) {
|
37
|
+
const name = row["taxon_name"];
|
38
|
+
const taxon = this.#taxa.getTaxon(name);
|
39
|
+
if (!taxon) {
|
39
40
|
continue;
|
40
41
|
}
|
41
42
|
|
42
|
-
let imageList = this.#images[
|
43
|
-
if (
|
43
|
+
let imageList = this.#images[name];
|
44
|
+
if (!imageList) {
|
44
45
|
imageList = [];
|
45
|
-
this.#images[
|
46
|
+
this.#images[name] = imageList;
|
46
47
|
}
|
47
48
|
|
48
|
-
const src = new URL(
|
49
|
-
const parts = path.parse(
|
50
|
-
const prefix = src.host.includes(
|
51
|
-
const filename = prefix + parts.slice(
|
49
|
+
const src = new URL(row["source"]);
|
50
|
+
const parts = path.parse(src.pathname).dir.split("/");
|
51
|
+
const prefix = src.host.includes("calflora") ? "cf-" : "inat-";
|
52
|
+
const filename = prefix + parts.slice(-1)[0] + ".jpg";
|
52
53
|
const srcFileName = photoDirSrc + "/" + filename;
|
53
54
|
const targetFileName = photoDirTarget + "/" + filename;
|
54
55
|
|
55
|
-
if (
|
56
|
+
if (!fs.existsSync(srcFileName)) {
|
56
57
|
// File is not there; retrieve it.
|
57
|
-
console.log(
|
58
|
-
await Files.fetch(
|
58
|
+
console.log("retrieving " + srcFileName);
|
59
|
+
await Files.fetch(src, srcFileName);
|
59
60
|
}
|
60
61
|
|
61
|
-
await new sharp(
|
62
|
-
|
63
|
-
|
62
|
+
await new sharp(srcFileName)
|
63
|
+
.resize({ width: 300 })
|
64
|
+
.jpeg({ quality: 40 })
|
65
|
+
.toFile(targetFileName);
|
64
66
|
|
67
|
+
imageList.push(
|
68
|
+
new Image(imagePrefix + "/" + filename, row["credit"])
|
69
|
+
);
|
65
70
|
}
|
66
71
|
|
67
|
-
this.#siteGenerator.copyIllustrations(
|
68
|
-
|
72
|
+
this.#siteGenerator.copyIllustrations(Taxa.getFlowerColors());
|
69
73
|
}
|
70
74
|
|
71
75
|
getManifestEntries() {
|
72
|
-
|
73
76
|
const entries = [];
|
74
|
-
const images = Files.getDirEntries(
|
75
|
-
|
76
|
-
for (
|
77
|
-
const fileName = images[
|
78
|
-
const ext = fileName.split(
|
79
|
-
entries.push(
|
77
|
+
const images = Files.getDirEntries(this.#contentDir + "/i").sort();
|
78
|
+
|
79
|
+
for (let index = 0; index < images.length; index++) {
|
80
|
+
const fileName = images[index];
|
81
|
+
const ext = fileName.split(".")[1];
|
82
|
+
entries.push(
|
83
|
+
EBook.getManifestEntry(
|
84
|
+
"i" + index,
|
85
|
+
"i/" + fileName,
|
86
|
+
EBook.getMediaTypeForExt(ext)
|
87
|
+
)
|
88
|
+
);
|
80
89
|
}
|
81
90
|
|
82
|
-
return entries.join(
|
91
|
+
return entries.join("");
|
83
92
|
}
|
84
93
|
|
85
|
-
getTaxonImages(
|
86
|
-
return this.#images[
|
94
|
+
getTaxonImages(name) {
|
95
|
+
return this.#images[name];
|
87
96
|
}
|
88
97
|
}
|
89
98
|
|
90
|
-
export { Images };
|
99
|
+
export { Images };
|
@@ -1,26 +1,32 @@
|
|
1
|
+
import { HTMLTaxon } from "../../htmltaxon.js";
|
1
2
|
import { EBookPage } from "../ebookpage.js";
|
2
3
|
import { XHTML } from "../xhtml.js";
|
3
4
|
|
4
5
|
class PageListSpecies extends EBookPage {
|
5
|
-
|
6
6
|
#taxa;
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
/**
|
9
|
+
*
|
10
|
+
* @param {string} outputDir
|
11
|
+
* @param {Taxon[]} taxa
|
12
|
+
* @param {string} filename
|
13
|
+
* @param {string} title
|
14
|
+
*/
|
15
|
+
constructor(outputDir, taxa, filename, title) {
|
16
|
+
super(outputDir + "/" + filename, title);
|
10
17
|
this.#taxa = taxa;
|
11
18
|
}
|
12
19
|
|
13
20
|
renderPageBody() {
|
14
|
-
|
15
|
-
const html = XHTML.textElement( "h1", this.getTitle() );
|
21
|
+
const html = XHTML.textElement("h1", this.getTitle());
|
16
22
|
|
17
23
|
const links = [];
|
18
|
-
for (
|
19
|
-
links.push(
|
24
|
+
for (const taxon of this.#taxa) {
|
25
|
+
links.push(HTMLTaxon.getLink(taxon));
|
20
26
|
}
|
21
27
|
|
22
|
-
return html + XHTML.wrap(
|
28
|
+
return html + XHTML.wrap("ol", XHTML.arrayToLI(links));
|
23
29
|
}
|
24
30
|
}
|
25
31
|
|
26
|
-
export { PageListSpecies };
|
32
|
+
export { PageListSpecies };
|
@@ -1,13 +1,10 @@
|
|
1
1
|
import imageSize from "image-size";
|
2
|
-
import { Config, Files } from "@ca-plant-list/ca-plant-list";
|
3
2
|
import { EBookPage } from "../ebookpage.js";
|
4
3
|
import { XHTML } from "../xhtml.js";
|
5
4
|
import { Markdown } from "../../markdown.js";
|
6
|
-
// eslint-disable-next-line no-unused-vars
|
7
|
-
import { Taxon } from "../../taxon.js";
|
8
|
-
// eslint-disable-next-line no-unused-vars
|
9
|
-
import { Image } from "../image.js";
|
10
5
|
import { HTMLTaxon } from "../../htmltaxon.js";
|
6
|
+
import { Config } from "../../config.js";
|
7
|
+
import { Files } from "../../files.js";
|
11
8
|
|
12
9
|
class TaxonPage extends EBookPage {
|
13
10
|
#outputDir;
|
@@ -58,7 +55,7 @@ class TaxonPage extends EBookPage {
|
|
58
55
|
});
|
59
56
|
}
|
60
57
|
|
61
|
-
html += HTMLTaxon.getFlowerInfo(this.#taxon);
|
58
|
+
html += HTMLTaxon.getFlowerInfo(this.#taxon, "section flr");
|
62
59
|
|
63
60
|
html += renderCustomText(this.#taxon.getBaseFileName());
|
64
61
|
|
package/lib/ebook/xhtml.js
CHANGED
package/lib/externalsites.js
CHANGED
@@ -1,23 +1,18 @@
|
|
1
1
|
class ExternalSites {
|
2
|
+
static getInatObsLink(options) {
|
3
|
+
const url = new URL(
|
4
|
+
"https://www.inaturalist.org/observations?subview=map"
|
5
|
+
);
|
2
6
|
|
3
|
-
|
4
|
-
|
5
|
-
return url.toString();
|
6
|
-
}
|
7
|
-
|
8
|
-
static getInatObsLink( options ) {
|
9
|
-
|
10
|
-
const url = new URL( "https://www.inaturalist.org/observations?subview=map" );
|
11
|
-
|
12
|
-
for ( const [ k, v ] of Object.entries( options ) ) {
|
13
|
-
switch ( k ) {
|
7
|
+
for (const [k, v] of Object.entries(options)) {
|
8
|
+
switch (k) {
|
14
9
|
case "coords": {
|
15
|
-
const delta = .1;
|
10
|
+
const delta = 0.1;
|
16
11
|
const params = url.searchParams;
|
17
|
-
params.set(
|
18
|
-
params.set(
|
19
|
-
params.set(
|
20
|
-
params.set(
|
12
|
+
params.set("nelat", v[1] + delta);
|
13
|
+
params.set("swlat", v[1] - delta);
|
14
|
+
params.set("nelng", v[0] + delta);
|
15
|
+
params.set("swlng", v[0] - delta);
|
21
16
|
break;
|
22
17
|
}
|
23
18
|
case "created_d1":
|
@@ -27,17 +22,15 @@ class ExternalSites {
|
|
27
22
|
case "subview":
|
28
23
|
case "taxon_id":
|
29
24
|
case "taxon_name":
|
30
|
-
if (
|
31
|
-
url.searchParams.set(
|
25
|
+
if (v) {
|
26
|
+
url.searchParams.set(k, v);
|
32
27
|
}
|
33
28
|
break;
|
34
29
|
}
|
35
30
|
}
|
36
31
|
|
37
32
|
return url.toString();
|
38
|
-
|
39
33
|
}
|
40
|
-
|
41
34
|
}
|
42
35
|
|
43
|
-
export { ExternalSites };
|
36
|
+
export { ExternalSites };
|
package/lib/families.js
CHANGED
package/lib/genera.js
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
import { Config } from "./config.js";
|
2
|
-
import { Families } from "./families.js";
|
3
2
|
import { Files } from "./files.js";
|
4
|
-
// eslint-disable-next-line no-unused-vars
|
5
|
-
import { Taxon } from "./taxon.js";
|
6
3
|
|
7
4
|
class Genera {
|
8
5
|
#families;
|
9
6
|
#genera;
|
10
7
|
|
11
8
|
/**
|
9
|
+
*
|
12
10
|
* @param {Families} families
|
13
11
|
*/
|
14
12
|
constructor(families) {
|
package/lib/genericpage.js
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
import { Config
|
1
|
+
import { Config } from "./config.js";
|
2
|
+
import { Files } from "./files.js";
|
3
|
+
import { HTML } from "./html.js";
|
4
|
+
import { Jekyll } from "./jekyll.js";
|
2
5
|
import { Markdown } from "./markdown.js";
|
3
6
|
|
4
7
|
class GenericPage {
|
5
|
-
|
6
8
|
#outputDir;
|
7
9
|
#title;
|
8
10
|
#baseFileName;
|
9
11
|
#js;
|
10
12
|
|
11
|
-
constructor(
|
13
|
+
constructor(outputDir, title, baseFileName, js) {
|
12
14
|
this.#outputDir = outputDir;
|
13
15
|
this.#title = title;
|
14
16
|
this.#baseFileName = baseFileName;
|
@@ -25,31 +27,38 @@ class GenericPage {
|
|
25
27
|
}
|
26
28
|
|
27
29
|
getFrontMatter() {
|
28
|
-
return
|
29
|
-
|
30
|
-
|
31
|
-
+
|
30
|
+
return (
|
31
|
+
"---\n" +
|
32
|
+
'title: "' +
|
33
|
+
this.#title +
|
34
|
+
'"\n' +
|
35
|
+
(this.#js ? "js: " + this.#js + "\n" : "") +
|
36
|
+
"---\n"
|
37
|
+
);
|
32
38
|
}
|
33
39
|
|
34
40
|
getMarkdown() {
|
35
41
|
// Include site-specific markdown.
|
36
|
-
let html = this.#getMarkdown(
|
42
|
+
let html = this.#getMarkdown("intros");
|
37
43
|
|
38
44
|
// Include package markdown.
|
39
|
-
const mdPath =
|
40
|
-
|
41
|
-
|
45
|
+
const mdPath =
|
46
|
+
Config.getPackageDir() + "/data/text/" + this.#baseFileName + ".md";
|
47
|
+
if (Files.exists(mdPath)) {
|
48
|
+
html += HTML.wrap("div", Markdown.fileToHTML(mdPath), {
|
49
|
+
class: "section",
|
50
|
+
});
|
42
51
|
}
|
43
52
|
|
44
53
|
return html;
|
45
54
|
}
|
46
55
|
|
47
|
-
#getMarkdown(
|
56
|
+
#getMarkdown(path) {
|
48
57
|
const textPath = path + "/" + this.#baseFileName + ".md";
|
49
|
-
if (
|
58
|
+
if (!Jekyll.hasInclude(this.#outputDir, textPath)) {
|
50
59
|
return "";
|
51
60
|
}
|
52
|
-
return HTML.wrap(
|
61
|
+
return HTML.wrap("div", Jekyll.include(textPath), { class: "section" });
|
53
62
|
}
|
54
63
|
|
55
64
|
getOutputDir() {
|
@@ -60,10 +69,9 @@ class GenericPage {
|
|
60
69
|
return this.#title;
|
61
70
|
}
|
62
71
|
|
63
|
-
writeFile(
|
64
|
-
Files.write(
|
72
|
+
writeFile(html) {
|
73
|
+
Files.write(this.#outputDir + "/" + this.#baseFileName + ".html", html);
|
65
74
|
}
|
66
|
-
|
67
75
|
}
|
68
76
|
|
69
|
-
export { GenericPage };
|
77
|
+
export { GenericPage };
|
package/lib/generictaxaloader.js
CHANGED
package/lib/htmltaxon.js
CHANGED
@@ -1,14 +1,31 @@
|
|
1
1
|
import { DateUtils } from "./dateutils.js";
|
2
2
|
import { HTML } from "./html.js";
|
3
|
-
// eslint-disable-next-line no-unused-vars
|
4
|
-
import { Taxon } from "./taxon.js";
|
5
3
|
import { TextUtils } from "./textutils.js";
|
6
4
|
|
7
5
|
class HTMLTaxon {
|
6
|
+
/**
|
7
|
+
* @param {string[]} colors
|
8
|
+
*/
|
9
|
+
static getFlowerColors(colors) {
|
10
|
+
let html = "";
|
11
|
+
if (colors) {
|
12
|
+
for (const color of colors) {
|
13
|
+
html += HTML.textElement("img", "", {
|
14
|
+
src: "./i/f-" + color + ".svg",
|
15
|
+
alt: color + " flowers",
|
16
|
+
title: color,
|
17
|
+
class: "flr-color",
|
18
|
+
});
|
19
|
+
}
|
20
|
+
}
|
21
|
+
return html;
|
22
|
+
}
|
23
|
+
|
8
24
|
/**
|
9
25
|
* @param {Taxon} taxon
|
26
|
+
* @param {string} classNames
|
10
27
|
*/
|
11
|
-
static getFlowerInfo(taxon) {
|
28
|
+
static getFlowerInfo(taxon, classNames = "section") {
|
12
29
|
const lifeCycle = taxon.getLifeCycle();
|
13
30
|
const colors = taxon.getFlowerColors();
|
14
31
|
const monthStart = taxon.getBloomStart();
|
@@ -16,23 +33,14 @@ class HTMLTaxon {
|
|
16
33
|
|
17
34
|
const parts = [];
|
18
35
|
if (lifeCycle) {
|
19
|
-
|
20
|
-
HTML.wrap("span", TextUtils.ucFirst(lifeCycle), "lc") + "."
|
21
|
-
);
|
36
|
+
const text =
|
37
|
+
HTML.wrap("span", TextUtils.ucFirst(lifeCycle), "lc") + ".";
|
38
|
+
parts.push(HTML.wrap("span", text, "lcs"));
|
22
39
|
}
|
23
40
|
|
24
41
|
if (colors || monthStart) {
|
25
42
|
let html = "Flowers: ";
|
26
|
-
|
27
|
-
for (const color of colors) {
|
28
|
-
html += HTML.textElement("img", "", {
|
29
|
-
src: "./i/f-" + color + ".svg",
|
30
|
-
alt: color + " flowers",
|
31
|
-
title: color,
|
32
|
-
class: "flr-color",
|
33
|
-
});
|
34
|
-
}
|
35
|
-
}
|
43
|
+
html += this.getFlowerColors(colors);
|
36
44
|
if (monthStart && monthEnd) {
|
37
45
|
html += HTML.wrap(
|
38
46
|
"span",
|
@@ -44,7 +52,17 @@ class HTMLTaxon {
|
|
44
52
|
}
|
45
53
|
parts.push(HTML.wrap("span", html));
|
46
54
|
}
|
47
|
-
return HTML.wrap("div", parts.join("
|
55
|
+
return HTML.wrap("div", parts.join(""), { class: classNames });
|
56
|
+
}
|
57
|
+
|
58
|
+
/**
|
59
|
+
* @param {Taxon} taxon
|
60
|
+
*/
|
61
|
+
static getLink(taxon) {
|
62
|
+
return (
|
63
|
+
HTML.getLink(taxon.getFileName(), taxon.getName()) +
|
64
|
+
this.getFlowerColors(taxon.getFlowerColors())
|
65
|
+
);
|
48
66
|
}
|
49
67
|
}
|
50
68
|
|
package/lib/markdown.js
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
import markdownIt from "markdown-it";
|
2
|
-
import { Files } from "
|
2
|
+
import { Files } from "./files.js";
|
3
3
|
|
4
4
|
class Markdown {
|
5
|
+
static #md = new markdownIt({ xhtmlOut: true });
|
5
6
|
|
6
|
-
static
|
7
|
-
|
8
|
-
static fileToHTML( filePath ) {
|
9
|
-
return this.strToHTML( Files.read( filePath ) );
|
7
|
+
static fileToHTML(filePath) {
|
8
|
+
return this.strToHTML(Files.read(filePath));
|
10
9
|
}
|
11
10
|
|
12
|
-
static strToHTML(
|
13
|
-
return this.#md.render(
|
11
|
+
static strToHTML(str) {
|
12
|
+
return this.#md.render(str);
|
14
13
|
}
|
15
|
-
|
16
14
|
}
|
17
15
|
|
18
|
-
export { Markdown };
|
16
|
+
export { Markdown };
|