@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
package/lib/externalsites.js
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
class ExternalSites {
|
2
|
+
/**
|
3
|
+
* @param {InatObsOptions} options
|
4
|
+
*/
|
2
5
|
static getInatObsLink(options) {
|
3
6
|
const url = new URL(
|
4
7
|
"https://www.inaturalist.org/observations?subview=map"
|
@@ -9,10 +12,14 @@ class ExternalSites {
|
|
9
12
|
case "coords": {
|
10
13
|
const delta = 0.1;
|
11
14
|
const params = url.searchParams;
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
/** @type {number} */
|
16
|
+
const lat = v[1];
|
17
|
+
/** @type {number} */
|
18
|
+
const lng = v[0];
|
19
|
+
params.set("nelat", (lat + delta).toString());
|
20
|
+
params.set("swlat", (lat - delta).toString());
|
21
|
+
params.set("nelng", (lng + delta).toString());
|
22
|
+
params.set("swlng", (lng - delta).toString());
|
16
23
|
break;
|
17
24
|
}
|
18
25
|
case "created_d1":
|
package/lib/families.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
import { GenericPage } from "./genericpage.js";
|
2
2
|
import { HTML } from "./html.js";
|
3
3
|
import { Jepson } from "./jepson.js";
|
4
|
-
import { Taxa } from "./taxa.js";
|
5
4
|
import { Files } from "./files.js";
|
6
5
|
import { Config } from "./config.js";
|
6
|
+
import { HTMLTaxon } from "./htmltaxon.js";
|
7
7
|
|
8
8
|
class Family {
|
9
9
|
#name;
|
@@ -81,7 +81,7 @@ class Families {
|
|
81
81
|
|
82
82
|
/**
|
83
83
|
* @param {string} outputDir
|
84
|
-
* @param {
|
84
|
+
* @param {TaxaCol[]} taxaColumns
|
85
85
|
*/
|
86
86
|
renderPages(outputDir, taxaColumns) {
|
87
87
|
new PageFamilyList(outputDir, this.#families).render(taxaColumns);
|
@@ -109,7 +109,7 @@ class PageFamilyList extends GenericPage {
|
|
109
109
|
}
|
110
110
|
|
111
111
|
/**
|
112
|
-
* @param {
|
112
|
+
* @param {TaxaCol[]} taxaColumns
|
113
113
|
*/
|
114
114
|
render(taxaColumns) {
|
115
115
|
let html = this.getDefaultIntro();
|
@@ -176,8 +176,7 @@ class PageFamily extends GenericPage {
|
|
176
176
|
}
|
177
177
|
|
178
178
|
/**
|
179
|
-
*
|
180
|
-
* @param {import("./index.js").TaxaCol[]} columns
|
179
|
+
* @param {TaxaCol[]} columns
|
181
180
|
*/
|
182
181
|
render(columns) {
|
183
182
|
let html = this.getDefaultIntro();
|
@@ -188,7 +187,7 @@ class PageFamily extends GenericPage {
|
|
188
187
|
{ class: "section" }
|
189
188
|
);
|
190
189
|
|
191
|
-
html +=
|
190
|
+
html += HTMLTaxon.getTaxaTable(this.#family.getTaxa(), columns);
|
192
191
|
|
193
192
|
this.writeFile(html);
|
194
193
|
}
|
@@ -207,17 +206,20 @@ class PageSection extends GenericPage {
|
|
207
206
|
this.#taxa = taxa;
|
208
207
|
}
|
209
208
|
|
209
|
+
/**
|
210
|
+
* @param {TaxaCol[]} [columns]
|
211
|
+
*/
|
210
212
|
render(columns) {
|
211
213
|
let html = this.getDefaultIntro();
|
212
214
|
|
213
|
-
html +=
|
215
|
+
html += HTMLTaxon.getTaxaTable(this.#taxa, columns);
|
214
216
|
|
215
217
|
this.writeFile(html);
|
216
218
|
}
|
217
219
|
}
|
218
220
|
|
219
221
|
class Sections {
|
220
|
-
/** @type {Object<string,Taxon[]} */
|
222
|
+
/** @type {Object<string,Taxon[]>} */
|
221
223
|
static #sections = {};
|
222
224
|
|
223
225
|
/**
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import { TextUtils } from "./textutils.js";
|
2
|
+
|
3
|
+
class FlowerColor {
|
4
|
+
#colorName;
|
5
|
+
#colorCode;
|
6
|
+
/** @type {Taxon[]} */
|
7
|
+
#taxa = [];
|
8
|
+
|
9
|
+
/**
|
10
|
+
* @param {string} colorName
|
11
|
+
* @param {string} [colorCode]
|
12
|
+
*/
|
13
|
+
constructor(colorName, colorCode) {
|
14
|
+
this.#colorName = colorName;
|
15
|
+
this.#colorCode = colorCode ? colorCode : colorName;
|
16
|
+
}
|
17
|
+
|
18
|
+
/**
|
19
|
+
* @param {Taxon} taxon
|
20
|
+
*/
|
21
|
+
addTaxon(taxon) {
|
22
|
+
this.#taxa.push(taxon);
|
23
|
+
}
|
24
|
+
|
25
|
+
getColorCode() {
|
26
|
+
return this.#colorCode;
|
27
|
+
}
|
28
|
+
|
29
|
+
getColorName(uc = false) {
|
30
|
+
return uc ? TextUtils.ucFirst(this.#colorName) : this.#colorName;
|
31
|
+
}
|
32
|
+
|
33
|
+
getFileName() {
|
34
|
+
return "list_fc_" + this.#colorName + ".html";
|
35
|
+
}
|
36
|
+
|
37
|
+
getTaxa() {
|
38
|
+
return this.#taxa;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
export { FlowerColor };
|
package/lib/genera.js
CHANGED
@@ -6,7 +6,6 @@ class Genera {
|
|
6
6
|
#genera;
|
7
7
|
|
8
8
|
/**
|
9
|
-
*
|
10
9
|
* @param {Families} families
|
11
10
|
*/
|
12
11
|
constructor(families) {
|
@@ -22,21 +21,17 @@ class Genera {
|
|
22
21
|
const genusName = taxon.getGenusName();
|
23
22
|
const genusData = this.#genera[genusName];
|
24
23
|
if (!genusData) {
|
25
|
-
|
26
|
-
return;
|
24
|
+
throw new Error(taxon.getName() + " genus not found");
|
27
25
|
}
|
28
26
|
|
29
|
-
if (genusData.
|
27
|
+
if (genusData.familyObj === undefined) {
|
28
|
+
// Initialize genus data.
|
29
|
+
genusData.familyObj = this.#families.getFamily(genusData.family);
|
30
30
|
genusData.taxa = [];
|
31
31
|
}
|
32
|
-
genusData.
|
32
|
+
genusData.familyObj.addTaxon(taxon);
|
33
33
|
|
34
|
-
|
35
|
-
if (!family) {
|
36
|
-
console.log(taxon.getName() + " family not found");
|
37
|
-
return;
|
38
|
-
}
|
39
|
-
family.addTaxon(taxon);
|
34
|
+
genusData.taxa.push(taxon);
|
40
35
|
}
|
41
36
|
|
42
37
|
/**
|
@@ -45,25 +40,22 @@ class Genera {
|
|
45
40
|
getGenus(genusName) {
|
46
41
|
return new Genus(this.#genera[genusName]);
|
47
42
|
}
|
48
|
-
|
49
|
-
/**
|
50
|
-
* @param {string} genusName
|
51
|
-
*/
|
52
|
-
getFamily(genusName) {
|
53
|
-
const genus = this.#genera[genusName];
|
54
|
-
if (genus) {
|
55
|
-
return this.#families.getFamily(genus.family);
|
56
|
-
}
|
57
|
-
}
|
58
43
|
}
|
59
44
|
|
60
45
|
class Genus {
|
61
46
|
#data;
|
62
47
|
|
48
|
+
/**
|
49
|
+
* @param {{family:string,familyObj:Family,taxa:Taxon[]}} data
|
50
|
+
*/
|
63
51
|
constructor(data) {
|
64
52
|
this.#data = data;
|
65
53
|
}
|
66
54
|
|
55
|
+
getFamily() {
|
56
|
+
return this.#data.familyObj;
|
57
|
+
}
|
58
|
+
|
67
59
|
getTaxa() {
|
68
60
|
return this.#data.taxa.sort((a, b) =>
|
69
61
|
a.getName().localeCompare(b.getName())
|
package/lib/genericpage.js
CHANGED
@@ -10,6 +10,12 @@ class GenericPage {
|
|
10
10
|
#baseFileName;
|
11
11
|
#js;
|
12
12
|
|
13
|
+
/**
|
14
|
+
* @param {string} outputDir
|
15
|
+
* @param {string} title
|
16
|
+
* @param {string} baseFileName
|
17
|
+
* @param {string} [js]
|
18
|
+
*/
|
13
19
|
constructor(outputDir, title, baseFileName, js) {
|
14
20
|
this.#outputDir = outputDir;
|
15
21
|
this.#title = title;
|
@@ -53,6 +59,9 @@ class GenericPage {
|
|
53
59
|
return html;
|
54
60
|
}
|
55
61
|
|
62
|
+
/**
|
63
|
+
* @param {string} path
|
64
|
+
*/
|
56
65
|
#getMarkdown(path) {
|
57
66
|
const textPath = path + "/" + this.#baseFileName + ".md";
|
58
67
|
if (!Jekyll.hasInclude(this.#outputDir, textPath)) {
|
@@ -69,6 +78,9 @@ class GenericPage {
|
|
69
78
|
return this.#title;
|
70
79
|
}
|
71
80
|
|
81
|
+
/**
|
82
|
+
* @param {string} html
|
83
|
+
*/
|
72
84
|
writeFile(html) {
|
73
85
|
Files.write(this.#outputDir + "/" + this.#baseFileName + ".html", html);
|
74
86
|
}
|
package/lib/html.js
CHANGED
@@ -1,11 +1,3 @@
|
|
1
|
-
/**
|
2
|
-
* @deprecated
|
3
|
-
*/
|
4
|
-
export const HTML_OPTIONS = {
|
5
|
-
OPEN_NEW: 1,
|
6
|
-
NO_ESCAPE: 2,
|
7
|
-
};
|
8
|
-
|
9
1
|
/** HTML utility functions. */
|
10
2
|
export class HTML {
|
11
3
|
/**
|
@@ -35,19 +27,6 @@ export class HTML {
|
|
35
27
|
.replaceAll(">", ">");
|
36
28
|
}
|
37
29
|
|
38
|
-
/**
|
39
|
-
* @deprecated
|
40
|
-
*/
|
41
|
-
static getElement(elName, text, attributes = {}, options = 0) {
|
42
|
-
let html = "<" + elName;
|
43
|
-
html += this.renderAttributes(attributes);
|
44
|
-
if (!(options & HTML_OPTIONS.NO_ESCAPE)) {
|
45
|
-
text = this.escapeText(text);
|
46
|
-
}
|
47
|
-
html += ">" + text + "</" + elName + ">";
|
48
|
-
return html;
|
49
|
-
}
|
50
|
-
|
51
30
|
/**
|
52
31
|
* @param {string} elName
|
53
32
|
* @param {string} text
|
@@ -71,7 +50,7 @@ export class HTML {
|
|
71
50
|
* Generate HTML for an <a> element.
|
72
51
|
* @param {string|undefined} href
|
73
52
|
* @param {string} linkText
|
74
|
-
* @param {Object} [attributes]
|
53
|
+
* @param {string|Object<string,string>} [attributes]
|
75
54
|
* @param {boolean} [openInNewWindow] true if the link should open in a new window.
|
76
55
|
* @returns {string} an HTML <a> element.
|
77
56
|
*/
|
@@ -92,7 +71,7 @@ export class HTML {
|
|
92
71
|
* @param {string} text - The text or HTML that should trigger the tooltip on hover.
|
93
72
|
* @param {string} tooltip - The tooltip text or HTML.
|
94
73
|
* @param {Object} options
|
95
|
-
* @param {boolean} options.icon [true] display an icon after the text
|
74
|
+
* @param {boolean} [options.icon] [true] display an icon after the text
|
96
75
|
* @returns {string} A <span> element to be used as a Bootstrap tooltip.
|
97
76
|
*/
|
98
77
|
static getToolTip(text, tooltip, options = {}) {
|
@@ -103,6 +82,10 @@ export class HTML {
|
|
103
82
|
return func("span", text, { "data-bs-html": "true", title: tooltip });
|
104
83
|
}
|
105
84
|
|
85
|
+
/**
|
86
|
+
* @param {string} n
|
87
|
+
* @param {string} v
|
88
|
+
*/
|
106
89
|
static renderAttribute(n, v) {
|
107
90
|
return " " + n + '="' + this.escapeAttribute(v) + '"';
|
108
91
|
}
|
@@ -121,6 +104,11 @@ export class HTML {
|
|
121
104
|
return html;
|
122
105
|
}
|
123
106
|
|
107
|
+
/**
|
108
|
+
* @param {string} elName
|
109
|
+
* @param {string} text
|
110
|
+
* @param {Object<string,string>} attributes
|
111
|
+
*/
|
124
112
|
static textElement(elName, text, attributes = {}) {
|
125
113
|
return HTML.#getElement(elName, text, attributes, true);
|
126
114
|
}
|
package/lib/htmltaxon.js
CHANGED
@@ -1,21 +1,68 @@
|
|
1
1
|
import { DateUtils } from "./dateutils.js";
|
2
2
|
import { HTML } from "./html.js";
|
3
|
+
import { RarePlants } from "./rareplants.js";
|
3
4
|
import { TextUtils } from "./textutils.js";
|
4
5
|
|
6
|
+
/**
|
7
|
+
* @type {Object<string,{title:string,data:function (Taxon):string}>}
|
8
|
+
*/
|
9
|
+
const TAXA_LIST_COLS = {
|
10
|
+
CESA: {
|
11
|
+
title: "California",
|
12
|
+
data: (t) => RarePlants.getCESADescription(t.getCESA()),
|
13
|
+
},
|
14
|
+
COMMON_NAME: {
|
15
|
+
title: "Common Name",
|
16
|
+
data: (t) => t.getCommonNames().join(", "),
|
17
|
+
},
|
18
|
+
CNPS_RANK: {
|
19
|
+
title: "CNPS Rank",
|
20
|
+
data: (t) =>
|
21
|
+
HTML.getToolTip(
|
22
|
+
HTML.textElement("span", t.getRPIRankAndThreat()),
|
23
|
+
t.getRPIRankAndThreatTooltip()
|
24
|
+
),
|
25
|
+
},
|
26
|
+
FESA: {
|
27
|
+
title: "Federal",
|
28
|
+
data: (t) => RarePlants.getFESADescription(t.getFESA()),
|
29
|
+
},
|
30
|
+
SPECIES: {
|
31
|
+
title: "Species",
|
32
|
+
data: (t) => t.getHTMLLink(true, true),
|
33
|
+
},
|
34
|
+
SPECIES_BARE: {
|
35
|
+
title: "Species",
|
36
|
+
data: (t) => t.getHTMLLink(true, false),
|
37
|
+
},
|
38
|
+
};
|
39
|
+
|
40
|
+
const DEFAULT_TAXA_COLUMNS = [
|
41
|
+
TAXA_LIST_COLS.SPECIES,
|
42
|
+
TAXA_LIST_COLS.COMMON_NAME,
|
43
|
+
];
|
44
|
+
|
5
45
|
class HTMLTaxon {
|
6
46
|
/**
|
7
|
-
* @param {string[]} colors
|
47
|
+
* @param {string[]|undefined} colors
|
8
48
|
*/
|
9
|
-
static getFlowerColors(colors) {
|
49
|
+
static getFlowerColors(colors, includeColorLink = true) {
|
10
50
|
let html = "";
|
11
51
|
if (colors) {
|
12
52
|
for (const color of colors) {
|
13
|
-
|
53
|
+
const img = HTML.textElement("img", "", {
|
14
54
|
src: "./i/f-" + color + ".svg",
|
15
55
|
alt: color + " flowers",
|
16
56
|
title: color,
|
17
57
|
class: "flr-color",
|
18
58
|
});
|
59
|
+
if (includeColorLink) {
|
60
|
+
html += HTML.wrap("a", img, {
|
61
|
+
href: "./list_fc_" + color + ".html",
|
62
|
+
});
|
63
|
+
} else {
|
64
|
+
html += img;
|
65
|
+
}
|
19
66
|
}
|
20
67
|
}
|
21
68
|
return html;
|
@@ -24,8 +71,13 @@ class HTMLTaxon {
|
|
24
71
|
/**
|
25
72
|
* @param {Taxon} taxon
|
26
73
|
* @param {string} classNames
|
74
|
+
* @param {boolean} [includeColorLink=true]
|
27
75
|
*/
|
28
|
-
static getFlowerInfo(
|
76
|
+
static getFlowerInfo(
|
77
|
+
taxon,
|
78
|
+
classNames = "section",
|
79
|
+
includeColorLink = true
|
80
|
+
) {
|
29
81
|
const lifeCycle = taxon.getLifeCycle();
|
30
82
|
const colors = taxon.getFlowerColors();
|
31
83
|
const monthStart = taxon.getBloomStart();
|
@@ -40,7 +92,7 @@ class HTMLTaxon {
|
|
40
92
|
|
41
93
|
if (colors || monthStart) {
|
42
94
|
let html = "Flowers: ";
|
43
|
-
html += this.getFlowerColors(colors);
|
95
|
+
html += this.getFlowerColors(colors, includeColorLink);
|
44
96
|
if (monthStart && monthEnd) {
|
45
97
|
html += HTML.wrap(
|
46
98
|
"span",
|
@@ -64,6 +116,37 @@ class HTMLTaxon {
|
|
64
116
|
this.getFlowerColors(taxon.getFlowerColors())
|
65
117
|
);
|
66
118
|
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* @param {Taxon[]} taxa
|
122
|
+
* @param {TaxaCol[]} [columns]
|
123
|
+
*/
|
124
|
+
static getTaxaTable(taxa, columns = DEFAULT_TAXA_COLUMNS) {
|
125
|
+
let html = "<table><thead>";
|
126
|
+
for (const col of columns) {
|
127
|
+
const className = col.class;
|
128
|
+
const atts = className !== undefined ? className : {};
|
129
|
+
html += HTML.textElement("th", col.title, atts);
|
130
|
+
}
|
131
|
+
html += "</thead>";
|
132
|
+
html += "<tbody>";
|
133
|
+
|
134
|
+
for (const taxon of taxa) {
|
135
|
+
html += "<tr>";
|
136
|
+
for (const col of columns) {
|
137
|
+
const data = col.data(taxon);
|
138
|
+
const className = col.class;
|
139
|
+
const atts = className !== undefined ? className : {};
|
140
|
+
html += HTML.wrap("td", data, atts);
|
141
|
+
}
|
142
|
+
html += "</tr>";
|
143
|
+
}
|
144
|
+
|
145
|
+
html += "</tbody>";
|
146
|
+
html += "</table>";
|
147
|
+
|
148
|
+
return html;
|
149
|
+
}
|
67
150
|
}
|
68
151
|
|
69
|
-
export { HTMLTaxon };
|
152
|
+
export { HTMLTaxon, TAXA_LIST_COLS };
|
package/lib/index.d.ts
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
import { Command } from "commander";
|
2
|
+
|
3
|
+
export class Config {
|
4
|
+
constructor(dataDir: string);
|
5
|
+
getConfigValue(
|
6
|
+
prefix: string,
|
7
|
+
name: string,
|
8
|
+
subcategory?: string,
|
9
|
+
defaultValue?: string
|
10
|
+
): string;
|
11
|
+
getCountyCodes(): string[];
|
12
|
+
getLabel(name: string, dflt: string): string;
|
13
|
+
}
|
14
|
+
|
15
|
+
export class CSV {
|
16
|
+
static parseFile(dir: string, fileName: string);
|
17
|
+
}
|
18
|
+
|
19
|
+
export class ErrorLog {
|
20
|
+
constructor(fileName: string, echo?: boolean);
|
21
|
+
log(...msg: string[]);
|
22
|
+
write(): void;
|
23
|
+
}
|
24
|
+
|
25
|
+
export class Exceptions {
|
26
|
+
constructor(dataDir: string);
|
27
|
+
hasException(name: string, cat: string, subcat: string);
|
28
|
+
}
|
29
|
+
|
30
|
+
export class Files {
|
31
|
+
static exists(fileName: string): boolean;
|
32
|
+
static async fetch(url: string | URL, targetFileName: string | undefined);
|
33
|
+
static mkdir(dir: string);
|
34
|
+
static rmDir(dir: string);
|
35
|
+
static write(fileName: string, data: string, overwrite: boolean);
|
36
|
+
}
|
37
|
+
|
38
|
+
export class Program {
|
39
|
+
static getIncludeList(dataDir: string): string[];
|
40
|
+
static getProgram(): Command;
|
41
|
+
}
|
42
|
+
|
43
|
+
export class Taxa {
|
44
|
+
constructor(
|
45
|
+
inclusionList: Object<string, TaxonData> | true,
|
46
|
+
errorLog: ErrorLog,
|
47
|
+
showFlowerErrors: boolean,
|
48
|
+
taxonFactory?: (td: TaxonData, g: Genera) => Taxon,
|
49
|
+
extraTaxa?: TaxonData[],
|
50
|
+
extraSynonyms?: SynonymData[]
|
51
|
+
);
|
52
|
+
getTaxon(string): Taxon;
|
53
|
+
getTaxonList(): Taxon[];
|
54
|
+
}
|
package/lib/index.js
CHANGED
@@ -1,58 +1,30 @@
|
|
1
|
-
/**
|
2
|
-
* @typedef {{
|
3
|
-
* bloom_end:string;
|
4
|
-
* bloom_start:string;
|
5
|
-
* calrecnum:string;
|
6
|
-
* CESA:string;
|
7
|
-
* CRPR:string;
|
8
|
-
* "common name":string;
|
9
|
-
* FESA:string;
|
10
|
-
* flower_color:string;
|
11
|
-
* GRank:string;
|
12
|
-
* "inat id":string;
|
13
|
-
* "jepson id":string;
|
14
|
-
* life_cycle:"annual"|"perennial"|undefined
|
15
|
-
* SRank:string;
|
16
|
-
* status:string;
|
17
|
-
* "RPI ID":string;
|
18
|
-
* taxon_name:string}} TaxonData
|
19
|
-
*/
|
20
|
-
|
21
1
|
import { BasePageRenderer } from "./basepagerenderer.js";
|
22
|
-
import { CommandProcessor } from "./commandprocessor.js";
|
23
|
-
import { CommandAndTaxaProcessor } from "./commandandtaxaprocessor.js";
|
24
2
|
import { Config } from "./config.js";
|
25
3
|
import { CSV } from "./csv.js";
|
26
4
|
import { ErrorLog } from "./errorlog.js";
|
27
5
|
import { Exceptions } from "./exceptions.js";
|
28
6
|
import { Families } from "./families.js";
|
29
7
|
import { Files } from "./files.js";
|
30
|
-
import { GenericTaxaLoader } from "./generictaxaloader.js";
|
31
8
|
import { HTML } from "./html.js";
|
32
9
|
import { Jekyll } from "./jekyll.js";
|
33
10
|
import { PlantBook } from "./ebook/plantbook.js";
|
11
|
+
import { Program } from "./program.js";
|
34
12
|
import { Taxa } from "./taxa.js";
|
35
|
-
import { TaxaLoader } from "./taxaloader.js";
|
36
|
-
import { TaxaProcessor } from "./taxaprocessor.js";
|
37
13
|
import { Taxon, TAXA_COLNAMES } from "./taxon.js";
|
38
14
|
|
39
15
|
export {
|
40
16
|
BasePageRenderer,
|
41
|
-
CommandProcessor,
|
42
|
-
CommandAndTaxaProcessor,
|
43
17
|
Config,
|
44
18
|
CSV,
|
45
19
|
ErrorLog,
|
46
20
|
Exceptions,
|
47
21
|
Families,
|
48
22
|
Files,
|
49
|
-
GenericTaxaLoader,
|
50
23
|
HTML,
|
51
24
|
Jekyll,
|
52
25
|
PlantBook,
|
26
|
+
Program,
|
53
27
|
Taxa,
|
54
|
-
TaxaLoader,
|
55
|
-
TaxaProcessor,
|
56
28
|
TAXA_COLNAMES,
|
57
29
|
Taxon,
|
58
30
|
};
|
package/lib/jekyll.js
CHANGED
@@ -4,40 +4,68 @@ import { SiteGenerator } from "./sitegenerator.js";
|
|
4
4
|
const FRONT_DELIM = "---";
|
5
5
|
|
6
6
|
class Jekyll extends SiteGenerator {
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
/**
|
8
|
+
* @param {string} baseDir
|
9
|
+
*/
|
10
|
+
constructor(baseDir) {
|
11
|
+
super(baseDir);
|
10
12
|
}
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
/**
|
15
|
+
* @param {Object<string,string>} atts
|
16
|
+
*/
|
17
|
+
static getFrontMatter(atts) {
|
18
|
+
const lines = [FRONT_DELIM];
|
19
|
+
for (const [k, v] of Object.entries(atts)) {
|
20
|
+
lines.push(k + ': "' + v + '"');
|
16
21
|
}
|
17
|
-
if (
|
18
|
-
lines.push(
|
22
|
+
if (!atts.layout) {
|
23
|
+
lines.push("layout: default");
|
19
24
|
}
|
20
|
-
lines.push(
|
21
|
-
return lines.join(
|
25
|
+
lines.push(FRONT_DELIM);
|
26
|
+
return lines.join("\n") + "\n";
|
22
27
|
}
|
23
28
|
|
24
|
-
|
25
|
-
|
29
|
+
/**
|
30
|
+
* @param {string} baseDir
|
31
|
+
* @param {string} path
|
32
|
+
*/
|
33
|
+
static hasInclude(baseDir, path) {
|
34
|
+
return Files.exists(baseDir + "/_includes/" + path);
|
26
35
|
}
|
27
36
|
|
28
|
-
|
37
|
+
/**
|
38
|
+
* @param {string} path
|
39
|
+
*/
|
40
|
+
static include(path) {
|
29
41
|
// This works for .md includes; should have conditional logic to detect other types.
|
30
|
-
return
|
42
|
+
return (
|
43
|
+
"{% capture my_include %}{% include " +
|
44
|
+
path +
|
45
|
+
" %}{% endcapture %}{{ my_include | markdownify }}"
|
46
|
+
);
|
31
47
|
}
|
32
48
|
|
33
|
-
|
34
|
-
|
49
|
+
/**
|
50
|
+
* @param {string} baseDir
|
51
|
+
* @param {string} path
|
52
|
+
* @param {string} data
|
53
|
+
*/
|
54
|
+
static writeInclude(baseDir, path, data) {
|
55
|
+
Files.write(baseDir + "/_includes/" + path, data);
|
35
56
|
}
|
36
57
|
|
37
|
-
|
38
|
-
|
58
|
+
/**
|
59
|
+
* @param {string} content
|
60
|
+
* @param {Object<string,string>} attributes
|
61
|
+
* @param {string} filename
|
62
|
+
*/
|
63
|
+
writeTemplate(content, attributes, filename) {
|
64
|
+
Files.write(
|
65
|
+
Files.join(this.getBaseDir(), filename),
|
66
|
+
Jekyll.getFrontMatter(attributes) + content
|
67
|
+
);
|
39
68
|
}
|
40
|
-
|
41
69
|
}
|
42
70
|
|
43
|
-
export { Jekyll };
|
71
|
+
export { Jekyll };
|
package/lib/jepson.js
CHANGED
@@ -1,18 +1,17 @@
|
|
1
|
-
import { HTML
|
1
|
+
import { HTML } from "./html.js";
|
2
2
|
|
3
3
|
class Jepson {
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
/**
|
5
|
+
* @param {string} id
|
6
|
+
*/
|
7
|
+
static getEFloraLink(id) {
|
7
8
|
return HTML.getLink(
|
8
9
|
"https://ucjeps.berkeley.edu/eflora/eflora_display.php?tid=" + id,
|
9
10
|
"Jepson eFlora",
|
10
11
|
{},
|
11
|
-
|
12
|
+
true
|
12
13
|
);
|
13
|
-
|
14
14
|
}
|
15
|
-
|
16
15
|
}
|
17
16
|
|
18
|
-
export { Jepson };
|
17
|
+
export { Jepson };
|
package/lib/markdown.js
CHANGED
@@ -4,10 +4,16 @@ import { Files } from "./files.js";
|
|
4
4
|
class Markdown {
|
5
5
|
static #md = new markdownIt({ xhtmlOut: true });
|
6
6
|
|
7
|
+
/**
|
8
|
+
* @param {string} filePath
|
9
|
+
*/
|
7
10
|
static fileToHTML(filePath) {
|
8
11
|
return this.strToHTML(Files.read(filePath));
|
9
12
|
}
|
10
13
|
|
14
|
+
/**
|
15
|
+
* @param {string} str
|
16
|
+
*/
|
11
17
|
static strToHTML(str) {
|
12
18
|
return this.#md.render(str);
|
13
19
|
}
|