@ca-plant-list/ca-plant-list 0.3.7 → 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 (69) hide show
  1. package/.vscode/settings.json +7 -1
  2. package/data/synonyms.csv +85 -2
  3. package/data/taxa.csv +38 -16
  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/Erythranthe-breweri.md +1 -0
  15. package/data/text/Erythranthe-erubescens.md +1 -0
  16. package/data/text/Navarretia-leptalea-subsp-bicolor.md +1 -0
  17. package/data/text/Navarretia-leptalea-subsp-leptalea.md +1 -0
  18. package/data/text/Polemonium-californicum.md +1 -0
  19. package/data/text/Polemonium-pulcherrimum-var-pulcherrimum.md +1 -0
  20. package/data/text/Primula-jeffreyi.md +1 -0
  21. package/data/text/Primula-tetrandra.md +1 -0
  22. package/lib/basepagerenderer.js +3 -4
  23. package/lib/config.js +42 -19
  24. package/lib/csv.js +54 -36
  25. package/lib/ebook/ebook.js +84 -57
  26. package/lib/ebook/ebookpage.js +22 -11
  27. package/lib/ebook/ebooksitegenerator.js +36 -14
  28. package/lib/ebook/glossarypages.js +20 -17
  29. package/lib/ebook/images.js +13 -5
  30. package/lib/ebook/pages/page_list_families.js +0 -2
  31. package/lib/ebook/pages/page_list_flower_color.js +14 -9
  32. package/lib/ebook/pages/page_list_flowers.js +59 -41
  33. package/lib/ebook/pages/taxonpage.js +1 -1
  34. package/lib/ebook/pages/tocpage.js +26 -20
  35. package/lib/ebook/plantbook.js +6 -13
  36. package/lib/ebook/{image.js → taxonimage.js} +2 -2
  37. package/lib/exceptions.js +42 -26
  38. package/lib/externalsites.js +11 -4
  39. package/lib/families.js +10 -8
  40. package/lib/flowercolor.js +42 -0
  41. package/lib/genera.js +13 -21
  42. package/lib/genericpage.js +12 -0
  43. package/lib/html.js +11 -23
  44. package/lib/htmltaxon.js +89 -6
  45. package/lib/index.d.ts +54 -0
  46. package/lib/index.js +2 -30
  47. package/lib/jekyll.js +49 -21
  48. package/lib/jepson.js +7 -8
  49. package/lib/markdown.js +6 -0
  50. package/lib/pagerenderer.js +43 -8
  51. package/lib/plants/glossary.js +5 -0
  52. package/lib/program.js +47 -0
  53. package/lib/rareplants.js +44 -30
  54. package/lib/sitegenerator.js +41 -24
  55. package/lib/taxa.js +20 -134
  56. package/lib/taxon.js +1 -1
  57. package/lib/web/glossarypages.js +6 -0
  58. package/lib/web/pagetaxon.js +1 -5
  59. package/package.json +6 -3
  60. package/schemas/exceptions.schema.json +57 -0
  61. package/scripts/build-ebook.js +38 -47
  62. package/scripts/build-site.js +25 -14
  63. package/types/classes.d.ts +136 -8
  64. package/lib/commandandtaxaprocessor.js +0 -25
  65. package/lib/commandprocessor.js +0 -108
  66. package/lib/generictaxaloader.js +0 -48
  67. package/lib/taxaloader.js +0 -50
  68. package/lib/taxaprocessor.js +0 -34
  69. /package/data/text/{Calyptridium-ubellatum.md → Calyptridium-umbellatum.md} +0 -0
@@ -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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ca-plant-list/ca-plant-list",
3
- "version": "0.3.7",
3
+ "version": "0.4.0",
4
4
  "description": "Tools to create Jekyll files for a website listing plants in an area of California.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -12,6 +12,7 @@
12
12
  "exports": {
13
13
  ".": "./lib/index.js"
14
14
  },
15
+ "types": "./lib/index.d.ts",
15
16
  "bin": {
16
17
  "ca-plant-list": "scripts/build-site.js",
17
18
  "ca-plant-book": "scripts/build-ebook.js"
@@ -19,8 +20,7 @@
19
20
  "dependencies": {
20
21
  "@ca-plant-list/tools": "file:../ca-tools",
21
22
  "archiver": "^5.3.1",
22
- "command-line-args": "^5.2.1",
23
- "command-line-usage": "^6.1.3",
23
+ "commander": "^12.1.0",
24
24
  "csv-parse": "^5.3.1",
25
25
  "image-size": "^1.1.1",
26
26
  "markdown-it": "^13.0.1",
@@ -29,8 +29,11 @@
29
29
  "unzipper": "^0.10.11"
30
30
  },
31
31
  "devDependencies": {
32
+ "@types/archiver": "^6.0.2",
33
+ "@types/markdown-it": "^14.1.2",
32
34
  "@types/node": "^18.11.9",
33
35
  "@types/unzipper": "^0.10.9",
36
+ "ajv-cli": "^5.0.0",
34
37
  "dts-bundle-generator": "^9.3.1",
35
38
  "eslint": "^8.26.0",
36
39
  "typescript": "^5.3.3"
@@ -0,0 +1,57 @@
1
+ {
2
+ "type": "object",
3
+ "additionalProperties": {
4
+ "type": "object",
5
+ "properties": {
6
+ "calflora": {
7
+ "type": "object",
8
+ "properties": {
9
+ "badjepsonid": {
10
+ "const": true
11
+ },
12
+ "notintaxondata": {
13
+ "const": true
14
+ }
15
+ },
16
+ "additionalProperties": false
17
+ },
18
+ "comment": {
19
+ "type": "string"
20
+ },
21
+ "inat": {
22
+ "type": "object",
23
+ "properties": {
24
+ "notintaxondata": {
25
+ "const": true
26
+ }
27
+ },
28
+ "additionalProperties": false
29
+ },
30
+ "jepson": {
31
+ "type": "object",
32
+ "properties": {
33
+ "allowsynonym": {
34
+ "const": true
35
+ },
36
+ "notineflora": {
37
+ "const": true
38
+ }
39
+ },
40
+ "additionalProperties": false
41
+ },
42
+ "rpi": {
43
+ "type": "object",
44
+ "properties": {
45
+ "translation": {
46
+ "type": "string"
47
+ },
48
+ "translation-to-rpi": {
49
+ "type": "string"
50
+ }
51
+ },
52
+ "additionalProperties": false
53
+ }
54
+ },
55
+ "additionalProperties": false
56
+ }
57
+ }