@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.
Files changed (75) hide show
  1. package/.vscode/settings.json +7 -1
  2. package/data/synonyms.csv +95 -2
  3. package/data/taxa.csv +53 -22
  4. package/data/text/Antennaria-media.md +1 -0
  5. package/data/text/Antennaria-rosea-subsp-rosea.md +1 -0
  6. package/data/text/Camassia-leichtlinii-subsp-suksdorfii.md +1 -0
  7. package/data/text/Camassia-quamash-subsp-breviflora.md +1 -0
  8. package/data/text/Delphinium-glaucum.md +1 -0
  9. package/data/text/Delphinium-nuttallianum.md +1 -0
  10. package/data/text/Drymocallis-glandulosa-var-glandulosa.md +1 -0
  11. package/data/text/Drymocallis-lactea-var-austiniae.md +1 -0
  12. package/data/text/Erigeron-compositus.md +1 -0
  13. package/data/text/Erigeron-glacialis-var-glacialis.md +1 -0
  14. package/data/text/Eriogonum-incanum.md +1 -0
  15. package/data/text/Eriogonum-lobbii.md +1 -0
  16. package/data/text/Eriogonum-ovalifolium-var-nivale.md +1 -0
  17. package/data/text/Erythranthe-breweri.md +1 -0
  18. package/data/text/Erythranthe-erubescens.md +1 -0
  19. package/data/text/Navarretia-leptalea-subsp-bicolor.md +1 -0
  20. package/data/text/Navarretia-leptalea-subsp-leptalea.md +1 -0
  21. package/data/text/Polemonium-californicum.md +1 -0
  22. package/data/text/Polemonium-pulcherrimum-var-pulcherrimum.md +1 -0
  23. package/data/text/Primula-jeffreyi.md +1 -0
  24. package/data/text/Primula-tetrandra.md +1 -0
  25. package/data/text/Silene-douglasii-var-douglasii.md +1 -0
  26. package/data/text/Silene-lemmonii.md +1 -0
  27. package/data/text/Silene-sargentii.md +1 -0
  28. package/lib/basepagerenderer.js +3 -4
  29. package/lib/config.js +42 -19
  30. package/lib/csv.js +54 -36
  31. package/lib/ebook/ebook.js +84 -57
  32. package/lib/ebook/ebookpage.js +22 -11
  33. package/lib/ebook/ebooksitegenerator.js +36 -14
  34. package/lib/ebook/glossarypages.js +20 -17
  35. package/lib/ebook/images.js +13 -5
  36. package/lib/ebook/pages/page_list_families.js +0 -2
  37. package/lib/ebook/pages/page_list_flower_color.js +14 -9
  38. package/lib/ebook/pages/page_list_flowers.js +59 -41
  39. package/lib/ebook/pages/taxonpage.js +1 -1
  40. package/lib/ebook/pages/tocpage.js +26 -20
  41. package/lib/ebook/plantbook.js +6 -13
  42. package/lib/ebook/{image.js → taxonimage.js} +2 -2
  43. package/lib/exceptions.js +42 -26
  44. package/lib/externalsites.js +11 -4
  45. package/lib/families.js +10 -8
  46. package/lib/flowercolor.js +42 -0
  47. package/lib/genera.js +13 -21
  48. package/lib/genericpage.js +12 -0
  49. package/lib/html.js +11 -23
  50. package/lib/htmltaxon.js +89 -6
  51. package/lib/index.d.ts +54 -0
  52. package/lib/index.js +2 -30
  53. package/lib/jekyll.js +49 -21
  54. package/lib/jepson.js +7 -8
  55. package/lib/markdown.js +6 -0
  56. package/lib/pagerenderer.js +43 -8
  57. package/lib/plants/glossary.js +5 -0
  58. package/lib/program.js +47 -0
  59. package/lib/rareplants.js +44 -30
  60. package/lib/sitegenerator.js +41 -24
  61. package/lib/taxa.js +20 -134
  62. package/lib/taxon.js +1 -1
  63. package/lib/web/glossarypages.js +6 -0
  64. package/lib/web/pagetaxon.js +1 -5
  65. package/package.json +8 -7
  66. package/schemas/exceptions.schema.json +57 -0
  67. package/scripts/build-ebook.js +38 -47
  68. package/scripts/build-site.js +25 -14
  69. package/types/classes.d.ts +136 -8
  70. package/lib/commandandtaxaprocessor.js +0 -25
  71. package/lib/commandprocessor.js +0 -108
  72. package/lib/generictaxaloader.js +0 -48
  73. package/lib/taxaloader.js +0 -50
  74. package/lib/taxaprocessor.js +0 -34
  75. /package/data/text/{Calyptridium-ubellatum.md → Calyptridium-umbellatum.md} +0 -0
@@ -1,10 +1,10 @@
1
- import { Taxa, TAXA_LIST_COLS } from "./taxa.js";
2
1
  import { PageTaxon } from "./web/pagetaxon.js";
3
2
  import { RarePlants } from "./rareplants.js";
4
3
  import { BasePageRenderer } from "./basepagerenderer.js";
5
4
  import { GenericPage } from "./genericpage.js";
6
5
  import { Files } from "./files.js";
7
6
  import { HTML } from "./html.js";
7
+ import { HTMLTaxon, TAXA_LIST_COLS } from "./htmltaxon.js";
8
8
 
9
9
  const ENDANGERED_COLS = [
10
10
  TAXA_LIST_COLS.SPECIES,
@@ -19,8 +19,13 @@ const RPI_COLUMNS = [
19
19
  ];
20
20
 
21
21
  class PageRenderer extends BasePageRenderer {
22
+ /**
23
+ * @param {string} outputDir
24
+ * @param {Config} config
25
+ * @param {Taxa} taxa
26
+ */
22
27
  static render(outputDir, config, taxa) {
23
- super.render(outputDir, taxa);
28
+ super.renderBasePages(outputDir, taxa);
24
29
 
25
30
  this.renderLists(outputDir, config, taxa);
26
31
 
@@ -30,7 +35,18 @@ class PageRenderer extends BasePageRenderer {
30
35
  }
31
36
  }
32
37
 
38
+ /**
39
+ * @param {string} outputDir
40
+ * @param {Config} config
41
+ * @param {Taxa} taxa
42
+ */
33
43
  static renderLists(outputDir, config, taxa) {
44
+ /**
45
+ * @param {ListInfo[]} listInfo
46
+ * @param {Object<string,string>} attributes
47
+ * @param {TaxaCol[]} [columns]
48
+ * @returns {string}
49
+ */
34
50
  function getListArray(listInfo, attributes = {}, columns) {
35
51
  const listArray = [];
36
52
  for (const list of listInfo) {
@@ -81,10 +97,18 @@ class PageRenderer extends BasePageRenderer {
81
97
  return renderList(listArray, attributes);
82
98
  }
83
99
 
100
+ /**
101
+ * @param {string[]} listsHTML
102
+ * @param {Object<string,string>} attributes
103
+ */
84
104
  function renderList(listsHTML, attributes = {}) {
85
105
  return HTML.wrap("ul", HTML.arrayToLI(listsHTML), attributes);
86
106
  }
87
107
 
108
+ /**
109
+ * @param {string} title
110
+ * @param {string} listsHTML
111
+ */
88
112
  function renderSection(title, listsHTML) {
89
113
  let html = '<div class="section">';
90
114
  html += HTML.textElement("h2", title);
@@ -93,6 +117,8 @@ class PageRenderer extends BasePageRenderer {
93
117
  return html;
94
118
  }
95
119
 
120
+ /** @typedef {{name:string,filename:string,include:function(Taxon):boolean,columns?:TaxaCol[],listInfo?:ListInfo[]}} ListInfo */
121
+ /** @type {{title:string,listInfo:ListInfo[]}[]} */
96
122
  const sections = [
97
123
  {
98
124
  title: "All Species",
@@ -158,7 +184,9 @@ class PageRenderer extends BasePageRenderer {
158
184
  {
159
185
  name: "Endangered Species",
160
186
  filename: "list_endangered",
161
- include: (t) => t.getCESA() || t.getFESA(),
187
+ include: (t) =>
188
+ t.getCESA() !== undefined ||
189
+ t.getFESA() !== undefined,
162
190
  columns: ENDANGERED_COLS,
163
191
  },
164
192
  ],
@@ -167,10 +195,7 @@ class PageRenderer extends BasePageRenderer {
167
195
 
168
196
  let html = '<div class="wrapper">';
169
197
  for (const section of sections) {
170
- const listHTML = getListArray(
171
- section.listInfo,
172
- section.listInfo.columns
173
- );
198
+ const listHTML = getListArray(section.listInfo);
174
199
 
175
200
  if (listHTML.length > 0) {
176
201
  html += renderSection(section.title, listHTML);
@@ -189,17 +214,27 @@ class PageRenderer extends BasePageRenderer {
189
214
  }
190
215
 
191
216
  class PageTaxonList extends GenericPage {
217
+ /**
218
+ * @param {string} outputDir
219
+ * @param {string} title
220
+ * @param {string} baseName
221
+ */
192
222
  constructor(outputDir, title, baseName) {
193
223
  super(outputDir, title, baseName);
194
224
  }
195
225
 
226
+ /**
227
+ *
228
+ * @param {Taxon[]} taxa
229
+ * @param {TaxaCol[]|undefined} columns
230
+ */
196
231
  render(taxa, columns) {
197
232
  let html = this.getDefaultIntro();
198
233
 
199
234
  html += '<div class="wrapper">';
200
235
 
201
236
  html += '<div class="section">';
202
- html += Taxa.getHTMLTable(taxa, columns);
237
+ html += HTMLTaxon.getTaxaTable(taxa, columns);
203
238
  html += "</div>";
204
239
 
205
240
  html += '<div class="section">';
@@ -3,6 +3,7 @@ import { Files } from "../files.js";
3
3
 
4
4
  class Glossary {
5
5
  #srcPath;
6
+ /** @type {GlossaryEntry[]} */
6
7
  #srcEntries = [];
7
8
 
8
9
  constructor() {
@@ -25,6 +26,10 @@ class GlossaryEntry {
25
26
  #fileName;
26
27
  #term;
27
28
 
29
+ /**
30
+ * @param {string} srcPath
31
+ * @param {string} fileName
32
+ */
28
33
  constructor(srcPath, fileName) {
29
34
  this.#srcPath = srcPath;
30
35
  this.#fileName = fileName;
package/lib/program.js ADDED
@@ -0,0 +1,47 @@
1
+ import { Command } from "commander";
2
+ import { Files } from "./files.js";
3
+ import { CSV } from "./csv.js";
4
+
5
+ class Program {
6
+ /**
7
+ * @param {string} dataDir
8
+ */
9
+ static getIncludeList(dataDir) {
10
+ // Read inclusion list.
11
+ const includeFileName = "taxa_include.csv";
12
+ const includeFilePath = dataDir + "/" + includeFileName;
13
+ if (!Files.exists(includeFilePath)) {
14
+ console.log(includeFilePath + " not found; loading all taxa");
15
+ return true;
16
+ }
17
+ const includeCSV = CSV.parseFile(dataDir, includeFileName);
18
+ /** @type {Object<string,TaxonData>} */
19
+ const include = {};
20
+ for (const row of includeCSV) {
21
+ include[row["taxon_name"]] = row;
22
+ }
23
+ return include;
24
+ }
25
+
26
+ static getProgram() {
27
+ const program = new Command();
28
+ program
29
+ .option(
30
+ "-d, --datadir <dir>",
31
+ "The directory containing plant data.",
32
+ "./data"
33
+ )
34
+ .option(
35
+ "-f, --show-flower-errors",
36
+ "Include missing flower color/flowering time in the error log when loading taxa."
37
+ )
38
+ .option(
39
+ "-o, --outputdir <dir>",
40
+ "The directory to which output should be written.",
41
+ "./output"
42
+ );
43
+ return program;
44
+ }
45
+ }
46
+
47
+ export { Program };
package/lib/rareplants.js CHANGED
@@ -1,60 +1,74 @@
1
+ /** @type {Object<string,string>} */
1
2
  const RANK_DESCRIPS = {
2
3
  "1A": "Presumed Extirpated or Extinct",
3
4
  "1B": "Rare or Endangered",
4
5
  "2A": "Extirpated in California",
5
6
  "2B": "Rare or Endangered in California",
6
- "3": "Needs Review",
7
- "4": "Uncommon in California",
7
+ 3: "Needs Review",
8
+ 4: "Uncommon in California",
8
9
  };
9
10
 
11
+ /** @type {Object<string,string>} */
10
12
  const THREAT_DESCRIPS = {
11
- "1": "Seriously threatened in California",
12
- "2": "Moderately threatened in California",
13
- "3": "Not very threatened in California",
13
+ 1: "Seriously threatened in California",
14
+ 2: "Moderately threatened in California",
15
+ 3: "Not very threatened in California",
14
16
  };
15
17
 
18
+ /** @type {Object<string,string>} */
16
19
  const CESA_DESCRIPS = {
17
- "CC": "Candidate",
18
- "CE": "Endangered",
19
- "CR": "Rare",
20
- "CT": "Threatened",
20
+ CC: "Candidate",
21
+ CE: "Endangered",
22
+ CR: "Rare",
23
+ CT: "Threatened",
21
24
  };
22
25
 
26
+ /** @type {Object<string,string>} */
23
27
  const FESA_DESCRIPS = {
24
- "FE": "Endangered",
25
- "FT": "Threatened",
26
- "PE": "Proposed Endangered",
27
- "PT": "Proposed Threatened",
28
- "FC": "Candidate",
29
- "FD": "Delisted",
28
+ FE: "Endangered",
29
+ FT: "Threatened",
30
+ PE: "Proposed Endangered",
31
+ PT: "Proposed Threatened",
32
+ FC: "Candidate",
33
+ FD: "Delisted",
30
34
  };
31
35
 
32
36
  class RarePlants {
33
-
34
- static getCESADescription( cesa ) {
35
- if ( !cesa ) {
37
+ /**
38
+ * @param {string|undefined} cesa
39
+ */
40
+ static getCESADescription(cesa) {
41
+ if (!cesa) {
36
42
  return "";
37
43
  }
38
- return CESA_DESCRIPS[ cesa ];
44
+ return CESA_DESCRIPS[cesa];
39
45
  }
40
46
 
41
- static getFESADescription( fesa ) {
42
- if ( !fesa ) {
47
+ /**
48
+ * @param {string|undefined} fesa
49
+ */
50
+ static getFESADescription(fesa) {
51
+ if (!fesa) {
43
52
  return "";
44
53
  }
45
- return FESA_DESCRIPS[ fesa ];
54
+ return FESA_DESCRIPS[fesa];
46
55
  }
47
56
 
48
- static getRPIRankDescription( rank ) {
49
- const pieces = rank.split( "." );
50
- return RANK_DESCRIPS[ pieces[ 0 ] ];
57
+ /**
58
+ * @param {string} rank
59
+ */
60
+ static getRPIRankDescription(rank) {
61
+ const pieces = rank.split(".");
62
+ return RANK_DESCRIPS[pieces[0]];
51
63
  }
52
64
 
53
- static getRPIRankAndThreatDescriptions( rank ) {
54
- const pieces = rank.split( "." );
55
- return [ RANK_DESCRIPS[ pieces[ 0 ] ], THREAT_DESCRIPS[ pieces[ 1 ] ] ];
65
+ /**
66
+ * @param {string} rank
67
+ */
68
+ static getRPIRankAndThreatDescriptions(rank) {
69
+ const pieces = rank.split(".");
70
+ return [RANK_DESCRIPS[pieces[0]], THREAT_DESCRIPS[pieces[1]]];
56
71
  }
57
-
58
72
  }
59
73
 
60
- export { RarePlants };
74
+ export { RarePlants };
@@ -6,32 +6,46 @@ import { Files } from "./files.js";
6
6
  class SiteGenerator {
7
7
  #baseDir;
8
8
 
9
- constructor( baseDir ) {
9
+ /**
10
+ * @param {string} baseDir
11
+ */
12
+ constructor(baseDir) {
10
13
  this.#baseDir = baseDir;
11
14
  }
12
15
 
13
- copyIllustrations( flowerColors ) {
14
- function createFlowerColorIcons( outputDir, flowerColors ) {
16
+ /**
17
+ * @param {FlowerColor[]} flowerColors
18
+ */
19
+ copyIllustrations(flowerColors) {
20
+ /**
21
+ * @param {string} outputDir
22
+ * @param {FlowerColor[]} flowerColors
23
+ */
24
+ function createFlowerColorIcons(outputDir, flowerColors) {
15
25
  // Read generic input.
16
- const inputFileName = Files.join( outputDir, "flower.svg" );
17
- const srcSVG = Files.read( inputFileName );
18
- for ( const color of flowerColors ) {
26
+ const inputFileName = Files.join(outputDir, "flower.svg");
27
+ const srcSVG = Files.read(inputFileName);
28
+ for (const color of flowerColors) {
19
29
  Files.write(
20
- Files.join( outputDir, "f-" + color.name + ".svg" ),
21
- srcSVG.replace( "#ff0", color.color )
30
+ Files.join(outputDir, "f-" + color.getColorName() + ".svg"),
31
+ srcSVG.replace("#ff0", color.getColorCode())
22
32
  );
23
33
  }
24
34
  // Delete input file.
25
- Files.rmDir( inputFileName );
35
+ Files.rmDir(inputFileName);
26
36
  }
27
37
 
28
- function optimizeSVG( outputDir ) {
29
- const srcDir = Config.getPackageDir() + "/data/illustrations/inkscape";
30
- const entries = Files.getDirEntries( srcDir );
31
- for ( const entry of entries ) {
32
- const srcFile = Files.join( srcDir, entry );
33
- const srcSVG = Files.read( srcFile );
34
- const result = optimize( srcSVG, {
38
+ /**
39
+ * @param {string} outputDir
40
+ */
41
+ function optimizeSVG(outputDir) {
42
+ const srcDir =
43
+ Config.getPackageDir() + "/data/illustrations/inkscape";
44
+ const entries = Files.getDirEntries(srcDir);
45
+ for (const entry of entries) {
46
+ const srcFile = Files.join(srcDir, entry);
47
+ const srcSVG = Files.read(srcFile);
48
+ const result = optimize(srcSVG, {
35
49
  plugins: [
36
50
  {
37
51
  name: "preset-default",
@@ -55,24 +69,27 @@ class SiteGenerator {
55
69
  "minifyStyles",
56
70
  ],
57
71
  multipass: true,
58
- } );
59
- Files.write( Files.join( outputDir, entry ), result.data );
72
+ });
73
+ Files.write(Files.join(outputDir, entry), result.data);
60
74
  }
61
75
  }
62
76
 
63
- const outputDir = Files.join( this.#baseDir, "i" );
64
- Files.mkdir( outputDir );
77
+ const outputDir = Files.join(this.#baseDir, "i");
78
+ Files.mkdir(outputDir);
65
79
 
66
- optimizeSVG( outputDir );
67
- createFlowerColorIcons( outputDir, flowerColors );
80
+ optimizeSVG(outputDir);
81
+ createFlowerColorIcons(outputDir, flowerColors);
68
82
  }
69
83
 
70
84
  getBaseDir() {
71
85
  return this.#baseDir;
72
86
  }
73
87
 
74
- mkdir( path ) {
75
- Files.mkdir( Files.join( this.#baseDir, path ) );
88
+ /**
89
+ * @param {string} path
90
+ */
91
+ mkdir(path) {
92
+ Files.mkdir(Files.join(this.#baseDir, path));
76
93
  }
77
94
  }
78
95
 
package/lib/taxa.js CHANGED
@@ -1,11 +1,9 @@
1
1
  import { Config } from "./config.js";
2
- import { HTML } from "./html.js";
3
2
  import { CSV } from "./csv.js";
4
- import { RarePlants } from "./rareplants.js";
5
3
  import { Genera } from "./genera.js";
6
- import { TextUtils } from "./textutils.js";
7
4
  import { Taxon } from "./taxon.js";
8
5
  import { Families } from "./families.js";
6
+ import { FlowerColor } from "./flowercolor.js";
9
7
 
10
8
  const FLOWER_COLORS = [
11
9
  { name: "white", color: "white" },
@@ -19,74 +17,6 @@ const FLOWER_COLORS = [
19
17
  { name: "brown", color: "brown" },
20
18
  ];
21
19
 
22
- /**
23
- * @type {Object<string,{title:string,data:function (Taxon):string}>}
24
- */
25
- const TAXA_LIST_COLS = {
26
- CESA: {
27
- title: "California",
28
- data: (t) => RarePlants.getCESADescription(t.getCESA()),
29
- },
30
- COMMON_NAME: {
31
- title: "Common Name",
32
- data: (t) => t.getCommonNames().join(", "),
33
- },
34
- CNPS_RANK: {
35
- title: "CNPS Rank",
36
- data: (t) =>
37
- HTML.getToolTip(
38
- HTML.textElement("span", t.getRPIRankAndThreat()),
39
- t.getRPIRankAndThreatTooltip()
40
- ),
41
- },
42
- FESA: {
43
- title: "Federal",
44
- data: (t) => RarePlants.getFESADescription(t.getFESA()),
45
- },
46
- SPECIES: {
47
- title: "Species",
48
- data: (t) => t.getHTMLLink(true, true),
49
- },
50
- SPECIES_BARE: {
51
- title: "Species",
52
- data: (t) => t.getHTMLLink(true, false),
53
- },
54
- };
55
-
56
- const DEFAULT_COLUMNS = [TAXA_LIST_COLS.SPECIES, TAXA_LIST_COLS.COMMON_NAME];
57
-
58
- class FlowerColor {
59
- #color;
60
- /** @type {Taxon[]} */
61
- #taxa = [];
62
-
63
- /**
64
- * @param {string} color
65
- */
66
- constructor(color) {
67
- this.#color = color;
68
- }
69
-
70
- /**
71
- * @param {Taxon} taxon
72
- */
73
- addTaxon(taxon) {
74
- this.#taxa.push(taxon);
75
- }
76
-
77
- getColorName(uc = false) {
78
- return uc ? TextUtils.ucFirst(this.#color) : this.#color;
79
- }
80
-
81
- getFileName() {
82
- return "list_fc_" + this.#color + ".html";
83
- }
84
-
85
- getTaxa() {
86
- return this.#taxa;
87
- }
88
- }
89
-
90
20
  class Taxa {
91
21
  #families;
92
22
  #errorLog;
@@ -99,17 +29,18 @@ class Taxa {
99
29
  #isSubset;
100
30
 
101
31
  /**
102
- * @param {string[]|boolean} inclusionList
32
+ * @param {Object<string,TaxonData>|true} inclusionList
103
33
  * @param {ErrorLog} errorLog
104
34
  * @param {boolean} showFlowerErrors
105
- * @param {Taxon} taxonClass
35
+ * @param {function(TaxonData,Genera):Taxon} taxonFactory
36
+ * @param {TaxonData[]} [extraTaxa=[]]
37
+ * @param {SynonymData[]} [extraSynonyms=[]]
106
38
  */
107
39
  constructor(
108
40
  inclusionList,
109
41
  errorLog,
110
42
  showFlowerErrors,
111
- taxaMeta = {},
112
- taxonClass = Taxon,
43
+ taxonFactory = (td, g) => new Taxon(td, g),
113
44
  extraTaxa = [],
114
45
  extraSynonyms = []
115
46
  ) {
@@ -126,18 +57,11 @@ class Taxa {
126
57
  this.#families = new Families();
127
58
 
128
59
  const taxaCSV = CSV.parseFile(dataDir, "taxa.csv");
129
- this.#loadTaxa(
130
- taxaCSV,
131
- inclusionList,
132
- taxaMeta,
133
- taxonClass,
134
- showFlowerErrors
135
- );
60
+ this.#loadTaxa(taxaCSV, inclusionList, taxonFactory, showFlowerErrors);
136
61
  this.#loadTaxa(
137
62
  extraTaxa,
138
63
  inclusionList,
139
- taxaMeta,
140
- taxonClass,
64
+ taxonFactory,
141
65
  showFlowerErrors
142
66
  );
143
67
 
@@ -157,54 +81,14 @@ class Taxa {
157
81
  this.#loadSyns(extraSynonyms, inclusionList);
158
82
  }
159
83
 
160
- /**
161
- * @param {Taxon[]} taxa
162
- * @param {TaxaCol} columns
163
- */
164
- static getHTMLTable(taxa, columns = DEFAULT_COLUMNS) {
165
- let html = "<table><thead>";
166
- for (const col of columns) {
167
- const className = col.class;
168
- const atts = className ? { class: className } : {};
169
- html += HTML.textElement("th", col.title, atts);
170
- }
171
- html += "</thead>";
172
- html += "<tbody>";
173
-
174
- for (const taxon of taxa) {
175
- html += "<tr>";
176
- for (const col of columns) {
177
- const data = col.data(taxon);
178
- const className = col.class;
179
- const atts = className ? { class: className } : {};
180
- html += HTML.wrap("td", data, atts);
181
- }
182
- html += "</tr>";
183
- }
184
-
185
- html += "</tbody>";
186
- html += "</table>";
187
-
188
- return html;
189
- }
190
-
191
84
  getFamilies() {
192
85
  return this.#families;
193
86
  }
194
87
 
195
- /**
196
- * @param {string} name
197
- */
198
- getFlowerColor(name) {
199
- return this.#flower_colors[name];
200
- }
201
-
202
- static getFlowerColorNames() {
203
- return FLOWER_COLORS.map((o) => o.name);
204
- }
205
-
206
- static getFlowerColors() {
207
- return FLOWER_COLORS;
88
+ getFlowerColors() {
89
+ return Object.values(this.#flower_colors).filter(
90
+ (fc) => fc.getTaxa().length > 0
91
+ );
208
92
  }
209
93
 
210
94
  /**
@@ -234,8 +118,8 @@ class Taxa {
234
118
  }
235
119
 
236
120
  /**
237
- * @param {*} synCSV
238
- * @param {*} inclusionList
121
+ * @param {SynonymData[]} synCSV
122
+ * @param {Object<string,TaxonData>|boolean} inclusionList
239
123
  */
240
124
  #loadSyns(synCSV, inclusionList) {
241
125
  for (const syn of synCSV) {
@@ -257,14 +141,16 @@ class Taxa {
257
141
 
258
142
  /**
259
143
  * @param {TaxonData[]} taxaCSV
260
- * @param {Taxon} taxonClass
144
+ * @param {Object<string,TaxonData>|true} inclusionList
145
+ * @param {function(TaxonData,Genera):Taxon} taxonFactory
261
146
  * @param {boolean} showFlowerErrors
262
147
  */
263
- #loadTaxa(taxaCSV, inclusionList, taxaMeta, taxonClass, showFlowerErrors) {
148
+ #loadTaxa(taxaCSV, inclusionList, taxonFactory, showFlowerErrors) {
264
149
  const genera = new Genera(this.#families);
265
150
  for (const row of taxaCSV) {
266
151
  const name = row["taxon_name"];
267
152
 
153
+ /** @type {TaxonData|{status?:string}} */
268
154
  let taxon_overrides = {};
269
155
  if (inclusionList !== true) {
270
156
  taxon_overrides = inclusionList[name];
@@ -281,7 +167,7 @@ class Taxa {
281
167
  if (status !== undefined) {
282
168
  row["status"] = status;
283
169
  }
284
- const taxon = new taxonClass(row, genera, taxaMeta[name]);
170
+ const taxon = taxonFactory(row, genera);
285
171
  this.#taxa[name] = taxon;
286
172
  const colors = taxon.getFlowerColors();
287
173
  if (colors) {
@@ -326,4 +212,4 @@ class Taxa {
326
212
  }
327
213
  }
328
214
 
329
- export { Taxa, TAXA_LIST_COLS };
215
+ export { Taxa };
package/lib/taxon.js CHANGED
@@ -149,7 +149,7 @@ class Taxon {
149
149
  }
150
150
 
151
151
  getFamily() {
152
- return this.#genera.getFamily(this.#genus);
152
+ return this.getGenus().getFamily();
153
153
  }
154
154
 
155
155
  getFESA() {
@@ -9,11 +9,17 @@ class GlossaryPages {
9
9
  #siteGenerator;
10
10
  #glossary;
11
11
 
12
+ /**
13
+ * @param {SiteGenerator} siteGenerator
14
+ */
12
15
  constructor(siteGenerator) {
13
16
  this.#siteGenerator = siteGenerator;
14
17
  this.#glossary = new Glossary();
15
18
  }
16
19
 
20
+ /**
21
+ * @param {GlossaryEntry} entry
22
+ */
17
23
  #generateEntryPage(entry) {
18
24
  const title = entry.getTermName();
19
25
  let html = HTML.textElement("h1", title);
@@ -3,10 +3,6 @@ import { RarePlants } from "../rareplants.js";
3
3
  import { GenericPage } from "../genericpage.js";
4
4
  import { ExternalSites } from "../externalsites.js";
5
5
  import { HTML } from "../html.js";
6
- // eslint-disable-next-line no-unused-vars
7
- import { Config } from "../config.js";
8
- // eslint-disable-next-line no-unused-vars
9
- import { Taxon } from "../taxon.js";
10
6
  import { HTMLTaxon } from "../htmltaxon.js";
11
7
 
12
8
  class PageTaxon extends GenericPage {
@@ -178,7 +174,7 @@ class PageTaxon extends GenericPage {
178
174
 
179
175
  html += "</div>";
180
176
 
181
- html += HTMLTaxon.getFlowerInfo(this.#taxon);
177
+ html += HTMLTaxon.getFlowerInfo(this.#taxon, undefined, false);
182
178
 
183
179
  html += this.getMarkdown();
184
180