@ca-plant-list/ca-plant-list 0.3.1 → 0.3.3
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 +5 -0
- package/data/exceptions.json +88 -83
- package/data/glossary/ovary.md +3 -0
- package/data/glossary/pistil.md +3 -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 -2
- package/data/taxa.csv +56 -54
- package/data/text/Ceanothus-cuneatus-var-cuneatus.md +1 -0
- package/data/text/Ceanothus-leucodermis.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/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/Trillium-chloropetalum.md +1 -1
- 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 -28
- package/lib/csv.js +13 -0
- package/lib/dateutils.js +36 -16
- package/lib/ebook/pages/taxonpage.js +63 -36
- package/lib/errorlog.js +16 -11
- package/lib/exceptions.js +2 -0
- package/lib/families.js +109 -71
- package/lib/files.js +103 -45
- package/lib/generictaxaloader.js +15 -7
- package/lib/html.js +2 -2
- package/lib/index.js +38 -3
- package/lib/taxa.js +175 -86
- package/lib/taxaloader.js +28 -15
- package/lib/taxaprocessor.js +6 -8
- package/lib/taxon.js +109 -56
- package/lib/web/pagetaxon.js +1 -1
- package/package.json +6 -8
- package/scripts/build-ebook.js +30 -25
- package/lib/index.d.ts +0 -327
package/lib/files.js
CHANGED
@@ -3,91 +3,149 @@ import * as path from "node:path";
|
|
3
3
|
import { default as unzipper } from "unzipper";
|
4
4
|
|
5
5
|
class Files {
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
/**
|
7
|
+
* @param {string} srcDir
|
8
|
+
* @param {string} targetDir
|
9
|
+
*/
|
10
|
+
static copyDir(srcDir, targetDir) {
|
11
|
+
fs.cpSync(srcDir, targetDir, { recursive: true });
|
9
12
|
}
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
/**
|
15
|
+
* @param {string} fileName
|
16
|
+
* @param {*} inStream
|
17
|
+
* @access private
|
18
|
+
*/
|
19
|
+
static #createFileFromStream(fileName, inStream) {
|
20
|
+
/**
|
21
|
+
*
|
22
|
+
* @param {string} fileName
|
23
|
+
* @param {*} inStream
|
24
|
+
* @param {*} resolve
|
25
|
+
*/
|
26
|
+
function implementation(fileName, inStream, resolve) {
|
27
|
+
const outStream = fs.createWriteStream(fileName);
|
28
|
+
outStream.on("finish", () => {
|
29
|
+
resolve(true);
|
30
|
+
});
|
31
|
+
inStream.pipe(outStream);
|
17
32
|
}
|
18
33
|
|
19
|
-
return new Promise(
|
34
|
+
return new Promise((resolve) => {
|
35
|
+
implementation(fileName, inStream, resolve);
|
36
|
+
});
|
20
37
|
}
|
21
38
|
|
22
|
-
|
23
|
-
|
39
|
+
/**
|
40
|
+
* @param {string} path
|
41
|
+
* @returns {boolean}
|
42
|
+
*/
|
43
|
+
static exists(path) {
|
44
|
+
return fs.existsSync(path);
|
24
45
|
}
|
25
46
|
|
26
47
|
/**
|
27
48
|
* Retrieve data from a URL and write it to a file. If the response status is anything other than 200, an Error is thrown.
|
28
|
-
* @param {string|URL} url
|
49
|
+
* @param {string|URL} url
|
29
50
|
* @param {string|undefined} targetFileName If targetFileName is undefined, the data will be retrieved but not written to a file.
|
30
51
|
* @param {Object} [headers={}] Request Headers.
|
31
52
|
* @returns {Promise<Headers>} The Response headers.
|
32
53
|
*/
|
33
|
-
static async fetch(
|
34
|
-
const response = await fetch(
|
35
|
-
if (
|
36
|
-
throw new Error(
|
54
|
+
static async fetch(url, targetFileName, headers = {}) {
|
55
|
+
const response = await fetch(url, headers);
|
56
|
+
if (response.status !== 200) {
|
57
|
+
throw new Error(response.status + " retrieving " + url);
|
37
58
|
}
|
38
59
|
const data = await response.blob();
|
39
60
|
const arrayBuffer = await data.arrayBuffer();
|
40
|
-
const buffer = Buffer.from(
|
41
|
-
if (
|
42
|
-
fs.writeFileSync(
|
61
|
+
const buffer = Buffer.from(arrayBuffer);
|
62
|
+
if (targetFileName) {
|
63
|
+
fs.writeFileSync(targetFileName, buffer);
|
43
64
|
}
|
44
65
|
return response.headers;
|
45
66
|
}
|
46
67
|
|
47
|
-
|
48
|
-
|
68
|
+
/**
|
69
|
+
* @param {string} path
|
70
|
+
* @returns {string[]}
|
71
|
+
*/
|
72
|
+
static getDirEntries(path) {
|
73
|
+
return fs.readdirSync(path);
|
49
74
|
}
|
50
75
|
|
51
|
-
|
52
|
-
|
76
|
+
/**
|
77
|
+
* @param {string} path
|
78
|
+
* @returns {boolean}
|
79
|
+
*/
|
80
|
+
static isDir(path) {
|
81
|
+
const stats = fs.statSync(path, { throwIfNoEntry: false });
|
53
82
|
return stats !== undefined && stats.isDirectory();
|
54
83
|
}
|
55
84
|
|
56
|
-
|
57
|
-
|
85
|
+
/**
|
86
|
+
* @param {string[]} paths
|
87
|
+
* @returns {string}
|
88
|
+
*/
|
89
|
+
static join(...paths) {
|
90
|
+
return path.join(...paths).replaceAll("\\", "/");
|
58
91
|
}
|
59
92
|
|
60
|
-
|
61
|
-
|
93
|
+
/**
|
94
|
+
* @param {string} path
|
95
|
+
*/
|
96
|
+
static mkdir(path) {
|
97
|
+
fs.mkdirSync(path, { recursive: true });
|
62
98
|
}
|
63
99
|
|
64
|
-
|
65
|
-
|
100
|
+
/**
|
101
|
+
* @param {string} path
|
102
|
+
* @returns {string}
|
103
|
+
*/
|
104
|
+
static read(path) {
|
105
|
+
return fs.readFileSync(path, "utf8");
|
66
106
|
}
|
67
107
|
|
68
|
-
|
69
|
-
|
108
|
+
/**
|
109
|
+
* @param {string} dir
|
110
|
+
*/
|
111
|
+
static rmDir(dir) {
|
112
|
+
fs.rmSync(dir, {
|
113
|
+
force: true,
|
114
|
+
recursive: true,
|
115
|
+
maxRetries: 2,
|
116
|
+
retryDelay: 1000,
|
117
|
+
});
|
70
118
|
}
|
71
119
|
|
72
|
-
|
73
|
-
|
74
|
-
|
120
|
+
/**
|
121
|
+
* @param {string} path
|
122
|
+
* @param {string} data
|
123
|
+
* @param {boolean} overwrite
|
124
|
+
*/
|
125
|
+
static write(path, data, overwrite = false) {
|
126
|
+
if (!overwrite && this.exists(path)) {
|
127
|
+
throw new Error(path + " already exists");
|
75
128
|
}
|
76
|
-
fs.writeFileSync(
|
129
|
+
fs.writeFileSync(path, data);
|
77
130
|
}
|
78
131
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
132
|
+
/**
|
133
|
+
* @param {string} zipFilePath
|
134
|
+
* @param {string} fileNameToUnzip
|
135
|
+
* @param {string} targetFilePath
|
136
|
+
*/
|
137
|
+
static async zipFileExtract(zipFilePath, fileNameToUnzip, targetFilePath) {
|
138
|
+
const zipDir = await unzipper.Open.file(zipFilePath);
|
139
|
+
for (const entry of zipDir.files) {
|
140
|
+
if (entry.path === fileNameToUnzip) {
|
141
|
+
await this.#createFileFromStream(
|
142
|
+
targetFilePath,
|
143
|
+
entry.stream()
|
144
|
+
);
|
85
145
|
break;
|
86
146
|
}
|
87
147
|
}
|
88
|
-
|
89
148
|
}
|
90
|
-
|
91
149
|
}
|
92
150
|
|
93
|
-
export { Files };
|
151
|
+
export { Files };
|
package/lib/generictaxaloader.js
CHANGED
@@ -1,16 +1,22 @@
|
|
1
|
-
import { ErrorLog } from "./
|
1
|
+
import { ErrorLog } from "./index.js";
|
2
2
|
|
3
3
|
class GenericTaxaLoader {
|
4
|
-
|
5
4
|
#options;
|
6
5
|
#errorLog;
|
6
|
+
/** @type {import("./index.js").Taxa|undefined}*/
|
7
7
|
#taxa;
|
8
8
|
|
9
|
-
|
9
|
+
/**
|
10
|
+
* @param {*} options
|
11
|
+
*/
|
12
|
+
constructor(options) {
|
10
13
|
this.#options = options;
|
11
|
-
this.#errorLog = new ErrorLog(
|
14
|
+
this.#errorLog = new ErrorLog(options.outputdir + "/errors.tsv");
|
12
15
|
}
|
13
16
|
|
17
|
+
/**
|
18
|
+
* @returns {ErrorLog}
|
19
|
+
*/
|
14
20
|
getErrorLog() {
|
15
21
|
return this.#errorLog;
|
16
22
|
}
|
@@ -27,14 +33,16 @@ class GenericTaxaLoader {
|
|
27
33
|
this.#taxa = await this.loadTaxa();
|
28
34
|
}
|
29
35
|
|
36
|
+
/**
|
37
|
+
* @return {Promise<import("./index.js").Taxa>}
|
38
|
+
*/
|
30
39
|
async loadTaxa() {
|
31
|
-
throw new Error(
|
40
|
+
throw new Error("must be implemented by subclass");
|
32
41
|
}
|
33
42
|
|
34
43
|
writeErrorLog() {
|
35
44
|
this.#errorLog.write();
|
36
45
|
}
|
37
|
-
|
38
46
|
}
|
39
47
|
|
40
|
-
export { GenericTaxaLoader };
|
48
|
+
export { GenericTaxaLoader };
|
package/lib/html.js
CHANGED
@@ -52,8 +52,8 @@ export class HTML {
|
|
52
52
|
* Generate HTML for an <a> element.
|
53
53
|
* @param {string|undefined} href
|
54
54
|
* @param {string} linkText
|
55
|
-
* @param {Object} attributes
|
56
|
-
* @param {boolean} openInNewWindow true if the link should open in a new window.
|
55
|
+
* @param {Object} [attributes]
|
56
|
+
* @param {boolean} [openInNewWindow] true if the link should open in a new window.
|
57
57
|
* @returns {string} an HTML <a> element.
|
58
58
|
*/
|
59
59
|
static getLink( href, linkText, attributes = {}, openInNewWindow ) {
|
package/lib/index.js
CHANGED
@@ -1,3 +1,22 @@
|
|
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
|
+
* SRank:string;
|
15
|
+
* status:string;
|
16
|
+
* "RPI ID":string;
|
17
|
+
* taxon_name:string}} TaxonData
|
18
|
+
*/
|
19
|
+
|
1
20
|
import { BasePageRenderer } from "./basepagerenderer.js";
|
2
21
|
import { CommandProcessor } from "./commandprocessor.js";
|
3
22
|
import { CommandAndTaxaProcessor } from "./commandandtaxaprocessor.js";
|
@@ -17,6 +36,22 @@ import { TaxaProcessor } from "./taxaprocessor.js";
|
|
17
36
|
import { Taxon, TAXA_COLNAMES } from "./taxon.js";
|
18
37
|
|
19
38
|
export {
|
20
|
-
BasePageRenderer,
|
21
|
-
|
22
|
-
|
39
|
+
BasePageRenderer,
|
40
|
+
CommandProcessor,
|
41
|
+
CommandAndTaxaProcessor,
|
42
|
+
Config,
|
43
|
+
CSV,
|
44
|
+
ErrorLog,
|
45
|
+
Exceptions,
|
46
|
+
Families,
|
47
|
+
Files,
|
48
|
+
GenericTaxaLoader,
|
49
|
+
HTML,
|
50
|
+
Jekyll,
|
51
|
+
PlantBook,
|
52
|
+
Taxa,
|
53
|
+
TaxaLoader,
|
54
|
+
TaxaProcessor,
|
55
|
+
TAXA_COLNAMES,
|
56
|
+
Taxon,
|
57
|
+
};
|