@ca-plant-list/ca-plant-list 0.3.6 → 0.4.0

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 (94) hide show
  1. package/.vscode/settings.json +7 -1
  2. package/data/synonyms.csv +109 -3
  3. package/data/taxa.csv +65 -29
  4. package/data/text/Antennaria-media.md +1 -0
  5. package/data/text/Antennaria-rosea-subsp-rosea.md +1 -0
  6. package/data/text/Antirrhinum-thompsonii.md +1 -0
  7. package/data/text/Calyptridium-monospermum.md +1 -0
  8. package/data/text/Calyptridium-umbellatum.md +1 -0
  9. package/data/text/Camassia-leichtlinii-subsp-suksdorfii.md +1 -0
  10. package/data/text/Camassia-quamash-subsp-breviflora.md +1 -0
  11. package/data/text/Clarkia-affinis.md +1 -0
  12. package/data/text/Clarkia-breweri.md +1 -0
  13. package/data/text/Clarkia-concinna-subsp-automixa.md +1 -0
  14. package/data/text/Clarkia-modesta.md +1 -0
  15. package/data/text/Clarkia-purpurea-subsp-quadrivulnera.md +1 -0
  16. package/data/text/Clarkia-rubicunda.md +1 -0
  17. package/data/text/Delphinium-californicum-subsp-californicum.md +1 -1
  18. package/data/text/Delphinium-californicum-subsp-interius.md +1 -0
  19. package/data/text/Delphinium-glaucum.md +1 -0
  20. package/data/text/Delphinium-hesperium-subsp-hesperium.md +1 -1
  21. package/data/text/Delphinium-hesperium-subsp-pallescens.md +1 -0
  22. package/data/text/Delphinium-nuttallianum.md +1 -0
  23. package/data/text/Delphinium-parryi-subsp-parryi.md +1 -0
  24. package/data/text/Drymocallis-glandulosa-var-glandulosa.md +1 -0
  25. package/data/text/Drymocallis-lactea-var-austiniae.md +1 -0
  26. package/data/text/Erigeron-compositus.md +1 -0
  27. package/data/text/Erigeron-glacialis-var-glacialis.md +1 -0
  28. package/data/text/Erythranthe-breweri.md +1 -0
  29. package/data/text/Erythranthe-erubescens.md +1 -0
  30. package/data/text/Erythranthe-moschata.md +1 -0
  31. package/data/text/Erythranthe-primuloides.md +1 -0
  32. package/data/text/Erythranthe-tilingii.md +1 -0
  33. package/data/text/Lilium-pardalinum-subsp-shastense.md +1 -0
  34. package/data/text/Logfia-filaginoides.md +1 -0
  35. package/data/text/Logfia-gallica.md +1 -0
  36. package/data/text/Malacothamnus-arcuatus-var-elmeri.md +1 -0
  37. package/data/text/Malacothamnus-fremontii-var-fremontii.md +1 -0
  38. package/data/text/Navarretia-leptalea-subsp-bicolor.md +1 -0
  39. package/data/text/Navarretia-leptalea-subsp-leptalea.md +1 -0
  40. package/data/text/Polemonium-californicum.md +1 -0
  41. package/data/text/Polemonium-pulcherrimum-var-pulcherrimum.md +1 -0
  42. package/data/text/Primula-jeffreyi.md +1 -0
  43. package/data/text/Primula-tetrandra.md +1 -0
  44. package/data/text/Trifolium-obtusiflorum.md +1 -0
  45. package/data/text/Trifolium-willdenovii.md +1 -0
  46. package/lib/basepagerenderer.js +3 -4
  47. package/lib/config.js +42 -19
  48. package/lib/csv.js +54 -36
  49. package/lib/ebook/ebook.js +84 -57
  50. package/lib/ebook/ebookpage.js +22 -11
  51. package/lib/ebook/ebooksitegenerator.js +36 -14
  52. package/lib/ebook/glossarypages.js +20 -17
  53. package/lib/ebook/images.js +59 -42
  54. package/lib/ebook/pages/page_list_families.js +0 -2
  55. package/lib/ebook/pages/page_list_flower_color.js +14 -9
  56. package/lib/ebook/pages/page_list_flowers.js +59 -41
  57. package/lib/ebook/pages/page_list_species.js +15 -9
  58. package/lib/ebook/pages/taxonpage.js +3 -6
  59. package/lib/ebook/pages/tocpage.js +26 -20
  60. package/lib/ebook/plantbook.js +6 -13
  61. package/lib/ebook/{image.js → taxonimage.js} +2 -2
  62. package/lib/ebook/xhtml.js +3 -5
  63. package/lib/exceptions.js +42 -26
  64. package/lib/externalsites.js +11 -4
  65. package/lib/families.js +10 -10
  66. package/lib/flowercolor.js +42 -0
  67. package/lib/genera.js +13 -23
  68. package/lib/genericpage.js +38 -18
  69. package/lib/html.js +11 -23
  70. package/lib/htmltaxon.js +114 -14
  71. package/lib/index.d.ts +54 -0
  72. package/lib/index.js +2 -30
  73. package/lib/jekyll.js +49 -21
  74. package/lib/jepson.js +7 -8
  75. package/lib/markdown.js +13 -9
  76. package/lib/pagerenderer.js +162 -82
  77. package/lib/plants/glossary.js +14 -14
  78. package/lib/program.js +47 -0
  79. package/lib/rareplants.js +44 -30
  80. package/lib/sitegenerator.js +41 -24
  81. package/lib/taxa.js +25 -142
  82. package/lib/taxon.js +3 -5
  83. package/lib/web/glossarypages.js +37 -18
  84. package/lib/web/pagetaxon.js +1 -5
  85. package/package.json +5 -3
  86. package/schemas/exceptions.schema.json +57 -0
  87. package/scripts/build-ebook.js +39 -48
  88. package/scripts/build-site.js +49 -28
  89. package/types/classes.d.ts +154 -0
  90. package/lib/commandandtaxaprocessor.js +0 -25
  91. package/lib/commandprocessor.js +0 -108
  92. package/lib/generictaxaloader.js +0 -48
  93. package/lib/taxaloader.js +0 -48
  94. package/lib/taxaprocessor.js +0 -34
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
- constructor( baseDir ) {
9
- super( baseDir );
7
+ /**
8
+ * @param {string} baseDir
9
+ */
10
+ constructor(baseDir) {
11
+ super(baseDir);
10
12
  }
11
13
 
12
- static getFrontMatter( atts ) {
13
- const lines = [ FRONT_DELIM ];
14
- for ( const [ k, v ] of Object.entries( atts ) ) {
15
- lines.push( k + ": \"" + v + "\"" );
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 ( !atts.layout ) {
18
- lines.push( "layout: default" );
22
+ if (!atts.layout) {
23
+ lines.push("layout: default");
19
24
  }
20
- lines.push( FRONT_DELIM );
21
- return lines.join( "\n" ) + "\n";
25
+ lines.push(FRONT_DELIM);
26
+ return lines.join("\n") + "\n";
22
27
  }
23
28
 
24
- static hasInclude( baseDir, path ) {
25
- return Files.exists( baseDir + "/_includes/" + path );
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
- static include( path ) {
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 "{% capture my_include %}{% include " + path + " %}{% endcapture %}{{ my_include | markdownify }}";
42
+ return (
43
+ "{% capture my_include %}{% include " +
44
+ path +
45
+ " %}{% endcapture %}{{ my_include | markdownify }}"
46
+ );
31
47
  }
32
48
 
33
- static writeInclude( baseDir, path, data ) {
34
- Files.write( baseDir + "/_includes/" + path, data );
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
- writeTemplate( content, attributes, filename ) {
38
- Files.write( Files.join( this.getBaseDir(), filename ), Jekyll.getFrontMatter( attributes ) + content );
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, HTML_OPTIONS } from "./html.js";
1
+ import { HTML } from "./html.js";
2
2
 
3
3
  class Jepson {
4
-
5
- static getEFloraLink( id ) {
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
- HTML_OPTIONS.OPEN_NEW
12
+ true
12
13
  );
13
-
14
14
  }
15
-
16
15
  }
17
16
 
18
- export { Jepson };
17
+ export { Jepson };
package/lib/markdown.js CHANGED
@@ -1,18 +1,22 @@
1
1
  import markdownIt from "markdown-it";
2
- import { Files } from "@ca-plant-list/ca-plant-list";
2
+ import { Files } from "./files.js";
3
3
 
4
4
  class Markdown {
5
+ static #md = new markdownIt({ xhtmlOut: true });
5
6
 
6
- static #md = new markdownIt( { xhtmlOut: true } );
7
-
8
- static fileToHTML( filePath ) {
9
- return this.strToHTML( Files.read( filePath ) );
7
+ /**
8
+ * @param {string} filePath
9
+ */
10
+ static fileToHTML(filePath) {
11
+ return this.strToHTML(Files.read(filePath));
10
12
  }
11
13
 
12
- static strToHTML( str ) {
13
- return this.#md.render( str );
14
+ /**
15
+ * @param {string} str
16
+ */
17
+ static strToHTML(str) {
18
+ return this.#md.render(str);
14
19
  }
15
-
16
20
  }
17
21
 
18
- export { Markdown };
22
+ export { Markdown };
@@ -1,84 +1,144 @@
1
- import { Files, Taxa, HTML } from "@ca-plant-list/ca-plant-list";
2
- import { TAXA_LIST_COLS } from "./taxa.js";
3
1
  import { PageTaxon } from "./web/pagetaxon.js";
4
2
  import { RarePlants } from "./rareplants.js";
5
3
  import { BasePageRenderer } from "./basepagerenderer.js";
6
4
  import { GenericPage } from "./genericpage.js";
7
-
8
- const ENDANGERED_COLS = [ TAXA_LIST_COLS.SPECIES, TAXA_LIST_COLS.COMMON_NAME, TAXA_LIST_COLS.CESA, TAXA_LIST_COLS.FESA ];
9
- const RPI_COLUMNS = [ TAXA_LIST_COLS.SPECIES_BARE, TAXA_LIST_COLS.COMMON_NAME, TAXA_LIST_COLS.CNPS_RANK ];
5
+ import { Files } from "./files.js";
6
+ import { HTML } from "./html.js";
7
+ import { HTMLTaxon, TAXA_LIST_COLS } from "./htmltaxon.js";
8
+
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,
14
+ ];
15
+ const RPI_COLUMNS = [
16
+ TAXA_LIST_COLS.SPECIES_BARE,
17
+ TAXA_LIST_COLS.COMMON_NAME,
18
+ TAXA_LIST_COLS.CNPS_RANK,
19
+ ];
10
20
 
11
21
  class PageRenderer extends BasePageRenderer {
22
+ /**
23
+ * @param {string} outputDir
24
+ * @param {Config} config
25
+ * @param {Taxa} taxa
26
+ */
27
+ static render(outputDir, config, taxa) {
28
+ super.renderBasePages(outputDir, taxa);
12
29
 
13
- static render( outputDir, config, taxa ) {
14
-
15
- super.render( outputDir, taxa );
16
-
17
- this.renderLists( outputDir, config, taxa );
30
+ this.renderLists(outputDir, config, taxa);
18
31
 
19
32
  const taxonList = taxa.getTaxonList();
20
- for ( const taxon of taxonList ) {
21
- new PageTaxon( outputDir, config, taxon ).render();
33
+ for (const taxon of taxonList) {
34
+ new PageTaxon(outputDir, config, taxon).render();
22
35
  }
23
-
24
36
  }
25
37
 
26
- static renderLists( outputDir, config, taxa ) {
27
-
28
- function getListArray( listInfo, attributes = {}, columns ) {
29
-
38
+ /**
39
+ * @param {string} outputDir
40
+ * @param {Config} config
41
+ * @param {Taxa} taxa
42
+ */
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
+ */
50
+ function getListArray(listInfo, attributes = {}, columns) {
30
51
  const listArray = [];
31
- for ( const list of listInfo ) {
52
+ for (const list of listInfo) {
32
53
  const listTaxa = [];
33
54
  const calfloraTaxa = [];
34
55
  const iNatTaxa = [];
35
- for ( const taxon of taxa.getTaxonList() ) {
36
- if ( list.include( taxon ) ) {
37
- listTaxa.push( taxon );
38
- calfloraTaxa.push( taxon.getCalfloraName() );
39
- iNatTaxa.push( taxon.getINatName() );
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());
40
61
  }
41
62
  }
42
63
 
43
- if ( listTaxa.length === 0 ) {
64
+ if (listTaxa.length === 0) {
44
65
  continue;
45
66
  }
46
67
 
47
- Files.write( outputDir + "/calflora_" + list.filename + ".txt", calfloraTaxa.join( "\n" ) );
48
- Files.write( outputDir + "/inat_" + list.filename + ".txt", iNatTaxa.join( "\n" ) );
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
+ );
49
76
 
50
77
  const cols = columns ? columns : list.columns;
51
- new PageTaxonList( outputDir, list.name, list.filename ).render( listTaxa, cols );
78
+ new PageTaxonList(outputDir, list.name, list.filename).render(
79
+ listTaxa,
80
+ cols
81
+ );
52
82
 
53
83
  // Check for sublists.
54
- const subListHTML = list.listInfo ? getListArray( list.listInfo, { class: "indent" }, cols ) : "";
55
-
56
- listArray.push( HTML.getLink( "./" + list.filename + ".html", list.name ) + " (" + listTaxa.length + ")" + subListHTML );
84
+ const subListHTML = list.listInfo
85
+ ? getListArray(list.listInfo, { class: "indent" }, cols)
86
+ : "";
87
+
88
+ listArray.push(
89
+ HTML.getLink("./" + list.filename + ".html", list.name) +
90
+ " (" +
91
+ listTaxa.length +
92
+ ")" +
93
+ subListHTML
94
+ );
57
95
  }
58
96
 
59
- return renderList( listArray, attributes );
97
+ return renderList(listArray, attributes);
60
98
  }
61
99
 
62
- function renderList( listsHTML, attributes = {} ) {
63
- return HTML.wrap( "ul", HTML.arrayToLI( listsHTML ), attributes );
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);
64
106
  }
65
107
 
66
- function renderSection( title, listsHTML ) {
67
- let html = "<div class=\"section\">";
68
- html += HTML.textElement( "h2", title );
108
+ /**
109
+ * @param {string} title
110
+ * @param {string} listsHTML
111
+ */
112
+ function renderSection(title, listsHTML) {
113
+ let html = '<div class="section">';
114
+ html += HTML.textElement("h2", title);
69
115
  html += listsHTML;
70
116
  html += "</div>";
71
117
  return html;
72
118
  }
73
119
 
120
+ /** @typedef {{name:string,filename:string,include:function(Taxon):boolean,columns?:TaxaCol[],listInfo?:ListInfo[]}} ListInfo */
121
+ /** @type {{title:string,listInfo:ListInfo[]}[]} */
74
122
  const sections = [
75
123
  {
76
124
  title: "All Species",
77
125
  listInfo: [
78
- { name: config.getLabel( "native", "Native" ), filename: "list_native", include: ( t ) => t.isNative() },
79
- { name: config.getLabel( "introduced", "Introduced" ), filename: "list_introduced", include: ( t ) => !t.isNative() },
80
- { name: "All Plants", filename: "list_all", include: () => true },
81
- ]
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
+ ],
82
142
  },
83
143
  {
84
144
  title: "Rare Plants",
@@ -86,101 +146,121 @@ class PageRenderer extends BasePageRenderer {
86
146
  {
87
147
  name: "CNPS Ranked Plants",
88
148
  filename: "list_rpi",
89
- include: ( t ) => t.getRPIRank() !== undefined,
149
+ include: (t) => t.getRPIRank() !== undefined,
90
150
  columns: RPI_COLUMNS,
91
151
  listInfo: [
92
152
  {
93
- name: RarePlants.getRPIRankDescription( "1A" ),
153
+ name: RarePlants.getRPIRankDescription("1A"),
94
154
  filename: "list_rpi_1a",
95
- include: ( t ) => t.getRPIRank() === "1A",
155
+ include: (t) => t.getRPIRank() === "1A",
96
156
  },
97
157
  {
98
- name: RarePlants.getRPIRankDescription( "1B" ),
158
+ name: RarePlants.getRPIRankDescription("1B"),
99
159
  filename: "list_rpi_1b",
100
- include: ( t ) => t.getRPIRank() === "1B",
160
+ include: (t) => t.getRPIRank() === "1B",
101
161
  },
102
162
  {
103
- name: RarePlants.getRPIRankDescription( "2A" ),
163
+ name: RarePlants.getRPIRankDescription("2A"),
104
164
  filename: "list_rpi_2a",
105
- include: ( t ) => t.getRPIRank() === "2A",
165
+ include: (t) => t.getRPIRank() === "2A",
106
166
  },
107
167
  {
108
- name: RarePlants.getRPIRankDescription( "2B" ),
168
+ name: RarePlants.getRPIRankDescription("2B"),
109
169
  filename: "list_rpi_2b",
110
- include: ( t ) => t.getRPIRank() === "2B",
170
+ include: (t) => t.getRPIRank() === "2B",
111
171
  },
112
172
  {
113
- name: RarePlants.getRPIRankDescription( "3" ),
173
+ name: RarePlants.getRPIRankDescription("3"),
114
174
  filename: "list_rpi_3",
115
- include: ( t ) => t.getRPIRank() === "3",
175
+ include: (t) => t.getRPIRank() === "3",
116
176
  },
117
177
  {
118
- name: RarePlants.getRPIRankDescription( "4" ),
178
+ name: RarePlants.getRPIRankDescription("4"),
119
179
  filename: "list_rpi_4",
120
- include: ( t ) => t.getRPIRank() === "4",
180
+ include: (t) => t.getRPIRank() === "4",
121
181
  },
122
- ]
182
+ ],
123
183
  },
124
184
  {
125
185
  name: "Endangered Species",
126
186
  filename: "list_endangered",
127
- include: ( t ) => ( t.getCESA() || t.getFESA() ),
187
+ include: (t) =>
188
+ t.getCESA() !== undefined ||
189
+ t.getFESA() !== undefined,
128
190
  columns: ENDANGERED_COLS,
129
191
  },
130
- ]
192
+ ],
131
193
  },
132
194
  ];
133
195
 
134
- let html = "<div class=\"wrapper\">";
135
- for ( const section of sections ) {
196
+ let html = '<div class="wrapper">';
197
+ for (const section of sections) {
198
+ const listHTML = getListArray(section.listInfo);
136
199
 
137
- const listHTML = getListArray( section.listInfo, section.listInfo.columns );
138
-
139
- if ( listHTML.length > 0 ) {
140
- html += renderSection( section.title, listHTML );
200
+ if (listHTML.length > 0) {
201
+ html += renderSection(section.title, listHTML);
141
202
  }
142
-
143
203
  }
144
- html += renderSection( "Taxonomy", renderList( [ HTML.getLink( "./list_families.html", "Plant Families" ) ] ) );
204
+ html += renderSection(
205
+ "Taxonomy",
206
+ renderList([HTML.getLink("./list_families.html", "Plant Families")])
207
+ );
145
208
 
146
209
  html += "</div>";
147
210
 
148
211
  // Write lists to includes directory so it can be inserted into pages.
149
- Files.write( outputDir + "/_includes/plantlists.html", html );
150
-
212
+ Files.write(outputDir + "/_includes/plantlists.html", html);
151
213
  }
152
-
153
214
  }
154
215
 
155
216
  class PageTaxonList extends GenericPage {
156
-
157
- constructor( outputDir, title, baseName ) {
158
- super( outputDir, title, baseName );
217
+ /**
218
+ * @param {string} outputDir
219
+ * @param {string} title
220
+ * @param {string} baseName
221
+ */
222
+ constructor(outputDir, title, baseName) {
223
+ super(outputDir, title, baseName);
159
224
  }
160
225
 
161
- render( taxa, columns ) {
162
-
226
+ /**
227
+ *
228
+ * @param {Taxon[]} taxa
229
+ * @param {TaxaCol[]|undefined} columns
230
+ */
231
+ render(taxa, columns) {
163
232
  let html = this.getDefaultIntro();
164
233
 
165
- html += "<div class=\"wrapper\">";
234
+ html += '<div class="wrapper">';
166
235
 
167
- html += "<div class=\"section\">";
168
- html += Taxa.getHTMLTable( taxa, columns );
236
+ html += '<div class="section">';
237
+ html += HTMLTaxon.getTaxaTable(taxa, columns);
169
238
  html += "</div>";
170
239
 
171
- html += "<div class=\"section\">";
172
- html += HTML.textElement( "h2", "Download" );
240
+ html += '<div class="section">';
241
+ html += HTML.textElement("h2", "Download");
173
242
  html += "<ul>";
174
- html += "<li>" + HTML.getLink( "./calflora_" + this.getBaseFileName() + ".txt", "Calflora List" ) + "</li>";
175
- html += "<li>" + HTML.getLink( "./inat_" + this.getBaseFileName() + ".txt", "iNaturalist List" ) + "</li>";
243
+ html +=
244
+ "<li>" +
245
+ HTML.getLink(
246
+ "./calflora_" + this.getBaseFileName() + ".txt",
247
+ "Calflora List"
248
+ ) +
249
+ "</li>";
250
+ html +=
251
+ "<li>" +
252
+ HTML.getLink(
253
+ "./inat_" + this.getBaseFileName() + ".txt",
254
+ "iNaturalist List"
255
+ ) +
256
+ "</li>";
176
257
  html += "</ul>";
177
258
  html += "</div>";
178
259
 
179
260
  html += "</div>";
180
261
 
181
- this.writeFile( html );
182
-
262
+ this.writeFile(html);
183
263
  }
184
264
  }
185
265
 
186
- export { PageRenderer };
266
+ export { PageRenderer };
@@ -1,38 +1,39 @@
1
- import { Config, Files } from "@ca-plant-list/ca-plant-list";
1
+ import { Config } from "../config.js";
2
+ import { Files } from "../files.js";
2
3
 
3
4
  class Glossary {
4
-
5
5
  #srcPath;
6
+ /** @type {GlossaryEntry[]} */
6
7
  #srcEntries = [];
7
8
 
8
9
  constructor() {
9
-
10
10
  this.#srcPath = Config.getPackageDir() + "/data/glossary";
11
11
 
12
12
  // Find all entries in the glossary directory.
13
- const entries = Files.getDirEntries( this.#srcPath ).sort();
14
- for ( const entry of entries ) {
15
- this.#srcEntries.push( new GlossaryEntry( this.#srcPath, entry ) );
13
+ const entries = Files.getDirEntries(this.#srcPath).sort();
14
+ for (const entry of entries) {
15
+ this.#srcEntries.push(new GlossaryEntry(this.#srcPath, entry));
16
16
  }
17
-
18
17
  }
19
18
 
20
19
  getEntries() {
21
20
  return this.#srcEntries;
22
21
  }
23
-
24
22
  }
25
23
 
26
24
  class GlossaryEntry {
27
-
28
25
  #srcPath;
29
26
  #fileName;
30
27
  #term;
31
28
 
32
- constructor( srcPath, fileName ) {
29
+ /**
30
+ * @param {string} srcPath
31
+ * @param {string} fileName
32
+ */
33
+ constructor(srcPath, fileName) {
33
34
  this.#srcPath = srcPath;
34
35
  this.#fileName = fileName;
35
- this.#term = fileName.split( "." )[ 0 ];
36
+ this.#term = fileName.split(".")[0];
36
37
  }
37
38
 
38
39
  getHTMLFileName() {
@@ -40,13 +41,12 @@ class GlossaryEntry {
40
41
  }
41
42
 
42
43
  getMarkdown() {
43
- return Files.read( this.#srcPath + "/" + this.#fileName );
44
+ return Files.read(this.#srcPath + "/" + this.#fileName);
44
45
  }
45
46
 
46
47
  getTermName() {
47
48
  return this.#term;
48
49
  }
49
-
50
50
  }
51
51
 
52
- export { Glossary };
52
+ export { Glossary };
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 };