@ca-plant-list/ca-plant-list 0.4.17 → 0.4.19

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.
@@ -7,259 +7,262 @@ import { HTML } from "./html.js";
7
7
  import { HTMLTaxon, TAXA_LIST_COLS } from "./htmltaxon.js";
8
8
 
9
9
  const ENDANGERED_COLS = [
10
- TAXA_LIST_COLS.SPECIES,
11
- TAXA_LIST_COLS.COMMON_NAME,
12
- TAXA_LIST_COLS.CESA,
13
- TAXA_LIST_COLS.FESA,
10
+ TAXA_LIST_COLS.SPECIES,
11
+ TAXA_LIST_COLS.COMMON_NAME,
12
+ TAXA_LIST_COLS.CESA,
13
+ TAXA_LIST_COLS.FESA,
14
14
  ];
15
15
  const RPI_COLUMNS = [
16
- TAXA_LIST_COLS.SPECIES_BARE,
17
- TAXA_LIST_COLS.COMMON_NAME,
18
- TAXA_LIST_COLS.CNPS_RANK,
16
+ TAXA_LIST_COLS.SPECIES_BARE,
17
+ TAXA_LIST_COLS.COMMON_NAME,
18
+ TAXA_LIST_COLS.CNPS_RANK,
19
19
  ];
20
20
 
21
21
  class PageRenderer extends BasePageRenderer {
22
- /**
23
- * @param {string} outputDir
24
- * @param {import('./config.js').Config} config
25
- * @param {Taxa} taxa
26
- */
27
- static render(outputDir, config, taxa) {
28
- super.renderBasePages(outputDir, taxa);
22
+ /**
23
+ * @param {string} outputDir
24
+ * @param {import('./config.js').Config} config
25
+ * @param {import("./taxa.js").Taxa} taxa
26
+ */
27
+ static render(outputDir, config, taxa) {
28
+ super.renderBasePages(outputDir, taxa);
29
29
 
30
- this.renderLists(outputDir, config, taxa);
30
+ this.renderLists(outputDir, config, taxa);
31
31
 
32
- const taxonList = taxa.getTaxonList();
33
- for (const taxon of taxonList) {
34
- new PageTaxon(outputDir, config, taxon).render();
32
+ const taxonList = taxa.getTaxonList();
33
+ for (const taxon of taxonList) {
34
+ new PageTaxon(outputDir, config, taxon).render();
35
+ }
35
36
  }
36
- }
37
37
 
38
- /**
39
- * @param {string} outputDir
40
- * @param {Config} config
41
- * @param {Taxa} taxa
42
- */
43
- static renderLists(outputDir, config, taxa) {
44
38
  /**
45
- * @param {ListInfo[]} listInfo
46
- * @param {Object<string,string>} attributes
47
- * @param {TaxaCol[]} [columns]
48
- * @returns {string}
39
+ * @param {string} outputDir
40
+ * @param {import('./config.js').Config} config
41
+ * @param {import("./taxa.js").Taxa} taxa
49
42
  */
50
- function getListArray(listInfo, attributes = {}, columns) {
51
- const listArray = [];
52
- for (const list of listInfo) {
53
- const listTaxa = [];
54
- const calfloraTaxa = [];
55
- const iNatTaxa = [];
56
- for (const taxon of taxa.getTaxonList()) {
57
- if (list.include(taxon)) {
58
- listTaxa.push(taxon);
59
- calfloraTaxa.push(taxon.getCalfloraName());
60
- iNatTaxa.push(taxon.getINatName());
61
- }
62
- }
43
+ static renderLists(outputDir, config, taxa) {
44
+ /**
45
+ * @param {ListInfo[]} listInfo
46
+ * @param {Object<string,string>} attributes
47
+ * @param {import("./htmltaxon.js").TaxaColDef[]} [columns]
48
+ * @returns {string}
49
+ */
50
+ function getListArray(listInfo, attributes = {}, columns) {
51
+ const listArray = [];
52
+ for (const list of listInfo) {
53
+ const listTaxa = [];
54
+ const calfloraTaxa = [];
55
+ const iNatTaxa = [];
56
+ for (const taxon of taxa.getTaxonList()) {
57
+ if (list.include(taxon)) {
58
+ listTaxa.push(taxon);
59
+ calfloraTaxa.push(taxon.getCalfloraName());
60
+ iNatTaxa.push(taxon.getINatName());
61
+ }
62
+ }
63
63
 
64
- if (listTaxa.length === 0) {
65
- continue;
66
- }
64
+ if (listTaxa.length === 0) {
65
+ continue;
66
+ }
67
67
 
68
- Files.write(
69
- outputDir + "/calflora_" + list.filename + ".txt",
70
- calfloraTaxa.join("\n")
71
- );
72
- Files.write(
73
- outputDir + "/inat_" + list.filename + ".txt",
74
- iNatTaxa.join("\n")
75
- );
68
+ Files.write(
69
+ outputDir + "/calflora_" + list.filename + ".txt",
70
+ calfloraTaxa.join("\n"),
71
+ );
72
+ Files.write(
73
+ outputDir + "/inat_" + list.filename + ".txt",
74
+ iNatTaxa.join("\n"),
75
+ );
76
76
 
77
- const cols = columns ? columns : list.columns;
78
- new PageTaxonList(outputDir, list.name, list.filename).render(
79
- listTaxa,
80
- cols
81
- );
77
+ const cols = columns ? columns : list.columns;
78
+ new PageTaxonList(outputDir, list.name, list.filename).render(
79
+ listTaxa,
80
+ cols,
81
+ );
82
82
 
83
- // Check for sublists.
84
- const subListHTML = list.listInfo
85
- ? getListArray(list.listInfo, { class: "indent" }, cols)
86
- : "";
83
+ // Check for sublists.
84
+ const subListHTML = list.listInfo
85
+ ? getListArray(list.listInfo, { class: "indent" }, cols)
86
+ : "";
87
87
 
88
- listArray.push(
89
- HTML.getLink("./" + list.filename + ".html", list.name) +
90
- " (" +
91
- listTaxa.length +
92
- ")" +
93
- subListHTML
94
- );
95
- }
88
+ listArray.push(
89
+ HTML.getLink("./" + list.filename + ".html", list.name) +
90
+ " (" +
91
+ listTaxa.length +
92
+ ")" +
93
+ subListHTML,
94
+ );
95
+ }
96
96
 
97
- return renderList(listArray, attributes);
98
- }
97
+ return renderList(listArray, attributes);
98
+ }
99
99
 
100
- /**
101
- * @param {string[]} listsHTML
102
- * @param {Object<string,string>} attributes
103
- */
104
- function renderList(listsHTML, attributes = {}) {
105
- return HTML.wrap("ul", HTML.arrayToLI(listsHTML), attributes);
106
- }
100
+ /**
101
+ * @param {string[]} listsHTML
102
+ * @param {Object<string,string>} attributes
103
+ */
104
+ function renderList(listsHTML, attributes = {}) {
105
+ return HTML.wrap("ul", HTML.arrayToLI(listsHTML), attributes);
106
+ }
107
107
 
108
- /**
109
- * @param {string} title
110
- * @param {string} listsHTML
111
- */
112
- function renderSection(title, listsHTML) {
113
- let html = '<div class="section nobullet">';
114
- html += HTML.textElement("h2", title);
115
- html += listsHTML;
116
- html += "</div>";
117
- return html;
118
- }
108
+ /**
109
+ * @param {string} title
110
+ * @param {string} listsHTML
111
+ */
112
+ function renderSection(title, listsHTML) {
113
+ let html = '<div class="section nobullet">';
114
+ html += HTML.textElement("h2", title);
115
+ html += listsHTML;
116
+ html += "</div>";
117
+ return html;
118
+ }
119
119
 
120
- /** @typedef {{name:string,filename:string,include:function(Taxon):boolean,columns?:TaxaCol[],listInfo?:ListInfo[]}} ListInfo */
121
- /** @type {{title:string,listInfo:ListInfo[]}[]} */
122
- const sections = [
123
- {
124
- title: "All Species",
125
- listInfo: [
126
- {
127
- name: config.getLabel("native", "Native"),
128
- filename: "list_native",
129
- include: (t) => t.isNative(),
130
- },
131
- {
132
- name: config.getLabel("introduced", "Introduced"),
133
- filename: "list_introduced",
134
- include: (t) => !t.isNative(),
135
- },
136
- {
137
- name: "All Plants",
138
- filename: "list_all",
139
- include: () => true,
140
- },
141
- ],
142
- },
143
- {
144
- title: "Rare Plants",
145
- listInfo: [
146
- {
147
- name: "CNPS Ranked Plants",
148
- filename: "list_rpi",
149
- include: (t) => t.getRPIRank() !== undefined,
150
- columns: RPI_COLUMNS,
151
- listInfo: [
152
- {
153
- name: RarePlants.getRPIRankDescription("1A"),
154
- filename: "list_rpi_1a",
155
- include: (t) => t.getRPIRank() === "1A",
156
- },
157
- {
158
- name: RarePlants.getRPIRankDescription("1B"),
159
- filename: "list_rpi_1b",
160
- include: (t) => t.getRPIRank() === "1B",
161
- },
162
- {
163
- name: RarePlants.getRPIRankDescription("2A"),
164
- filename: "list_rpi_2a",
165
- include: (t) => t.getRPIRank() === "2A",
166
- },
167
- {
168
- name: RarePlants.getRPIRankDescription("2B"),
169
- filename: "list_rpi_2b",
170
- include: (t) => t.getRPIRank() === "2B",
171
- },
172
- {
173
- name: RarePlants.getRPIRankDescription("3"),
174
- filename: "list_rpi_3",
175
- include: (t) => t.getRPIRank() === "3",
176
- },
177
- {
178
- name: RarePlants.getRPIRankDescription("4"),
179
- filename: "list_rpi_4",
180
- include: (t) => t.getRPIRank() === "4",
181
- },
182
- ],
183
- },
184
- {
185
- name: "Endangered Species",
186
- filename: "list_endangered",
187
- include: (t) =>
188
- t.getCESA() !== undefined || t.getFESA() !== undefined,
189
- columns: ENDANGERED_COLS,
190
- },
191
- ],
192
- },
193
- ];
120
+ /** @typedef {{name:string,filename:string,include:function(import("./taxon.js").Taxon):boolean,columns?:import("./htmltaxon.js").TaxaColDef[],listInfo?:ListInfo[]}} ListInfo */
121
+ /** @type {{title:string,listInfo:ListInfo[]}[]} */
122
+ const sections = [
123
+ {
124
+ title: "All Species",
125
+ listInfo: [
126
+ {
127
+ name: config.getLabel("native", "Native"),
128
+ filename: "list_native",
129
+ include: (t) => t.isNative(),
130
+ },
131
+ {
132
+ name: config.getLabel("introduced", "Introduced"),
133
+ filename: "list_introduced",
134
+ include: (t) => !t.isNative(),
135
+ },
136
+ {
137
+ name: "All Plants",
138
+ filename: "list_all",
139
+ include: () => true,
140
+ },
141
+ ],
142
+ },
143
+ {
144
+ title: "Rare Plants",
145
+ listInfo: [
146
+ {
147
+ name: "CNPS Ranked Plants",
148
+ filename: "list_rpi",
149
+ include: (t) => t.getRPIRank() !== undefined,
150
+ columns: RPI_COLUMNS,
151
+ listInfo: [
152
+ {
153
+ name: RarePlants.getRPIRankDescription("1A"),
154
+ filename: "list_rpi_1a",
155
+ include: (t) => t.getRPIRank() === "1A",
156
+ },
157
+ {
158
+ name: RarePlants.getRPIRankDescription("1B"),
159
+ filename: "list_rpi_1b",
160
+ include: (t) => t.getRPIRank() === "1B",
161
+ },
162
+ {
163
+ name: RarePlants.getRPIRankDescription("2A"),
164
+ filename: "list_rpi_2a",
165
+ include: (t) => t.getRPIRank() === "2A",
166
+ },
167
+ {
168
+ name: RarePlants.getRPIRankDescription("2B"),
169
+ filename: "list_rpi_2b",
170
+ include: (t) => t.getRPIRank() === "2B",
171
+ },
172
+ {
173
+ name: RarePlants.getRPIRankDescription("3"),
174
+ filename: "list_rpi_3",
175
+ include: (t) => t.getRPIRank() === "3",
176
+ },
177
+ {
178
+ name: RarePlants.getRPIRankDescription("4"),
179
+ filename: "list_rpi_4",
180
+ include: (t) => t.getRPIRank() === "4",
181
+ },
182
+ ],
183
+ },
184
+ {
185
+ name: "Endangered Species",
186
+ filename: "list_endangered",
187
+ include: (t) =>
188
+ t.getCESA() !== undefined ||
189
+ t.getFESA() !== undefined,
190
+ columns: ENDANGERED_COLS,
191
+ },
192
+ ],
193
+ },
194
+ ];
194
195
 
195
- let html = '<div class="wrapper">';
196
- for (const section of sections) {
197
- const listHTML = getListArray(section.listInfo);
196
+ let html = '<div class="wrapper">';
197
+ for (const section of sections) {
198
+ const listHTML = getListArray(section.listInfo);
198
199
 
199
- if (listHTML.length > 0) {
200
- html += renderSection(section.title, listHTML);
201
- }
202
- }
203
- html += renderSection(
204
- "Taxonomy",
205
- renderList([HTML.getLink("./list_families.html", "Plant Families")])
206
- );
200
+ if (listHTML.length > 0) {
201
+ html += renderSection(section.title, listHTML);
202
+ }
203
+ }
204
+ html += renderSection(
205
+ "Taxonomy",
206
+ renderList([
207
+ HTML.getLink("./list_families.html", "Plant Families"),
208
+ ]),
209
+ );
207
210
 
208
- html += "</div>";
211
+ html += "</div>";
209
212
 
210
- // Write lists to includes directory so it can be inserted into pages.
211
- Files.write(outputDir + "/_includes/plantlists.html", html);
212
- }
213
+ // Write lists to includes directory so it can be inserted into pages.
214
+ Files.write(outputDir + "/_includes/plantlists.html", html);
215
+ }
213
216
  }
214
217
 
215
218
  class PageTaxonList extends GenericPage {
216
- /**
217
- * @param {string} outputDir
218
- * @param {string} title
219
- * @param {string} baseName
220
- */
221
- constructor(outputDir, title, baseName) {
222
- super(outputDir, title, baseName);
223
- }
219
+ /**
220
+ * @param {string} outputDir
221
+ * @param {string} title
222
+ * @param {string} baseName
223
+ */
224
+ constructor(outputDir, title, baseName) {
225
+ super(outputDir, title, baseName);
226
+ }
224
227
 
225
- /**
226
- *
227
- * @param {Taxon[]} taxa
228
- * @param {TaxaCol[]|undefined} columns
229
- */
230
- render(taxa, columns) {
231
- let html = this.getDefaultIntro();
228
+ /**
229
+ *
230
+ * @param {import("./taxon.js").Taxon[]} taxa
231
+ * @param {import("./htmltaxon.js").TaxaColDef[]|undefined} columns
232
+ */
233
+ render(taxa, columns) {
234
+ let html = this.getDefaultIntro();
232
235
 
233
- html += '<div class="wrapper">';
236
+ html += '<div class="wrapper">';
234
237
 
235
- html += '<div class="section">';
236
- html += HTMLTaxon.getTaxaTable(taxa, columns);
237
- html += "</div>";
238
+ html += '<div class="section">';
239
+ html += HTMLTaxon.getTaxaTable(taxa, columns);
240
+ html += "</div>";
238
241
 
239
- html += '<div class="section nobullet">';
240
- html += HTML.textElement("h2", "Download");
241
- html += "<ul>";
242
- html +=
243
- "<li>" +
244
- HTML.getLink(
245
- "./calflora_" + this.getBaseFileName() + ".txt",
246
- "Calflora List"
247
- ) +
248
- "</li>";
249
- html +=
250
- "<li>" +
251
- HTML.getLink(
252
- "./inat_" + this.getBaseFileName() + ".txt",
253
- "iNaturalist List"
254
- ) +
255
- "</li>";
256
- html += "</ul>";
257
- html += "</div>";
242
+ html += '<div class="section nobullet">';
243
+ html += HTML.textElement("h2", "Download");
244
+ html += "<ul>";
245
+ html +=
246
+ "<li>" +
247
+ HTML.getLink(
248
+ "./calflora_" + this.getBaseFileName() + ".txt",
249
+ "Calflora List",
250
+ ) +
251
+ "</li>";
252
+ html +=
253
+ "<li>" +
254
+ HTML.getLink(
255
+ "./inat_" + this.getBaseFileName() + ".txt",
256
+ "iNaturalist List",
257
+ ) +
258
+ "</li>";
259
+ html += "</ul>";
260
+ html += "</div>";
258
261
 
259
- html += "</div>";
262
+ html += "</div>";
260
263
 
261
- this.writeFile(html);
262
- }
264
+ this.writeFile(html);
265
+ }
263
266
  }
264
267
 
265
268
  export { PageRenderer };
package/lib/photo.js CHANGED
@@ -1,44 +1,74 @@
1
- const CC0 = "CC0";
2
- const CC_BY = "CC BY";
3
- const CC_BY_NC = "CC BY-NC";
4
- const COPYRIGHT = "C";
1
+ /**
2
+ * @typedef {"CC0" | "CC BY" | "CC BY-NC" | "C" | null} PhotoRights
3
+ * @typedef { "cc-by-nc-sa"
4
+ | "cc-by-nc"
5
+ | "cc-by-nc-nd"
6
+ | "cc-by"
7
+ | "cc-by-sa"
8
+ | "cc-by-nd"
9
+ | "pd"
10
+ | "gdfl"
11
+ | "cc0"} InatLicenseCode
12
+ */
5
13
 
6
- class Photo {
7
- /** @type {string?} */
8
- #url;
9
- /** @type {string?} */
10
- rightsHolder;
11
- /** @type {null | typeof COPYRIGHT | typeof CC_BY | typeof CC_BY_NC | typeof CC0} */
12
- rights;
14
+ export class Photo {
15
+ #id;
16
+ #ext;
17
+ #rightsHolder;
18
+ /** @type {PhotoRights} */
19
+ #rights;
13
20
 
14
21
  /**
15
- * @param {string?} url
16
- * @param {string?} rightsHolder
17
- * @param {null | typeof COPYRIGHT | typeof CC_BY | typeof CC_BY_NC | typeof CC0} rights
22
+ * @param {number} id
23
+ * @param {string} ext
24
+ * @param {InatLicenseCode} licenseCode
25
+ * @param {string} rightsHolder
18
26
  */
19
- constructor( url, rightsHolder, rights ) {
20
- this.#url = url;
21
- this.rightsHolder = rightsHolder;
22
- this.rights = rights;
27
+ constructor(id, ext, licenseCode, rightsHolder) {
28
+ this.#id = id;
29
+ this.#ext = ext;
30
+ this.#rightsHolder = rightsHolder;
31
+ if (licenseCode === "cc0") this.#rights = "CC0";
32
+ else if (licenseCode === "cc-by") this.#rights = "CC BY";
33
+ else if (licenseCode === "cc-by-nc") this.#rights = "CC BY-NC";
34
+ else this.#rights = "C";
23
35
  }
24
36
 
25
- getUrl() {
26
- return this.#url;
37
+ /**
38
+ * @returns {string}
39
+ */
40
+ getAttribution() {
41
+ if (this.#rights === "CC0") {
42
+ if (this.#rightsHolder) {
43
+ return `By ${this.#rightsHolder} (${this.#rights})`;
44
+ }
45
+ return this.#rights;
46
+ }
47
+ if (this.#rightsHolder) {
48
+ return `(c) ${this.#rightsHolder} (${this.#rights})`;
49
+ }
50
+ return `(c) (${this.#rights})`;
51
+ }
52
+
53
+ getExt() {
54
+ return this.#ext;
55
+ }
56
+
57
+ getId() {
58
+ return this.#id;
27
59
  }
28
60
 
29
61
  /**
30
- * Return URL of page from whence this photo came
31
- * @return {string?}
62
+ * @returns {string} The URL of the iNaturalist page with details about the image.
32
63
  */
33
64
  getSourceUrl() {
34
- return null;
65
+ return `https://www.inaturalist.org/photos/${this.#id}`;
35
66
  }
36
- }
37
67
 
38
- export {
39
- CC0,
40
- CC_BY,
41
- CC_BY_NC,
42
- COPYRIGHT,
43
- Photo
44
- };
68
+ /**
69
+ * @returns {string} The URL to retrieve the image file.
70
+ */
71
+ getUrl() {
72
+ return `https://inaturalist-open-data.s3.amazonaws.com/photos/${this.#id}/medium.${this.#ext}`;
73
+ }
74
+ }
package/lib/taxa.js CHANGED
@@ -7,10 +7,10 @@ import { Genera } from "./genera.js";
7
7
  import { Taxon } from "./taxon.js";
8
8
  import { Families } from "./families.js";
9
9
  import { FlowerColor } from "./flowercolor.js";
10
- import { InatPhoto } from "./inat_photo.js";
11
10
  import { TaxaCSV } from "./tools/taxacsv.js";
12
11
  import { ErrorLog } from "./errorlog.js";
13
12
  import { Program } from "./program.js";
13
+ import { Photo } from "./photo.js";
14
14
 
15
15
  const FLOWER_COLORS = [
16
16
  { name: "white", color: "white" },
@@ -138,7 +138,7 @@ class Taxa {
138
138
  continue;
139
139
  }
140
140
  taxon.addPhoto(
141
- new InatPhoto(
141
+ new Photo(
142
142
  csvPhoto.id,
143
143
  csvPhoto.ext,
144
144
  csvPhoto.licenseCode,
package/lib/taxon.js CHANGED
@@ -35,12 +35,12 @@ class Taxon {
35
35
  #rankGlobal;
36
36
  /** @type {string[]} */
37
37
  #synonyms = [];
38
- /** @type {Photo[]} */
38
+ /** @type {import("./photo.js").Photo[]}*/
39
39
  #photos = [];
40
40
 
41
41
  /**
42
42
  * @param {TaxonData} data
43
- * @param {Genera} genera
43
+ * @param {import("./genera.js").Genera} genera
44
44
  */
45
45
  constructor(data, genera) {
46
46
  this.#genera = genera;
@@ -98,12 +98,15 @@ class Taxon {
98
98
  }
99
99
 
100
100
  /**
101
- * @param {InatPhoto} photo
101
+ * @param {import("./photo.js").Photo} photo
102
102
  */
103
103
  addPhoto(photo) {
104
104
  this.#photos = this.#photos.concat([photo]);
105
105
  }
106
106
 
107
+ /**
108
+ * @returns {import("./photo.js").Photo[]}
109
+ */
107
110
  getPhotos() {
108
111
  return this.#photos;
109
112
  }
@@ -264,6 +267,9 @@ class Taxon {
264
267
  return this.#iNatSyn ? link + " (" + this.#iNatSyn + ")" : link;
265
268
  }
266
269
 
270
+ /**
271
+ * @returns {string}
272
+ */
267
273
  getJepsonID() {
268
274
  return this.#jepsonID;
269
275
  }
@@ -287,6 +293,9 @@ class Taxon {
287
293
  return this.#rankRPI.split(".")[0];
288
294
  }
289
295
 
296
+ /**
297
+ * @returns {string}
298
+ */
290
299
  getRPIRankAndThreat() {
291
300
  return this.#rankRPI;
292
301
  }