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

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 (48) hide show
  1. package/data/genera.json +36 -32
  2. package/data/synonyms.csv +2 -1
  3. package/data/taxa.csv +1899 -1898
  4. package/data/text/Rumex-conglomeratus.md +1 -0
  5. package/data/text/Rumex-obtusifolius.md +1 -0
  6. package/data/text/Rumex-pulcher.md +1 -0
  7. package/data/text/Rumex-salicifolius.md +1 -0
  8. package/lib/config.js +15 -1
  9. package/lib/csv.js +23 -1
  10. package/lib/ebook/glossarypages.js +3 -3
  11. package/lib/ebook/images.js +2 -2
  12. package/lib/ebook/pages/page_list_families.js +1 -1
  13. package/lib/ebook/pages/page_list_flower_color.js +2 -2
  14. package/lib/ebook/pages/page_list_flowers.js +8 -8
  15. package/lib/ebook/pages/tocpage.js +2 -2
  16. package/lib/ebook/plantbook.js +2 -2
  17. package/lib/externalsites.js +49 -18
  18. package/lib/families.js +1 -1
  19. package/lib/files.js +1 -1
  20. package/lib/flowercolor.js +2 -2
  21. package/lib/genera.js +5 -2
  22. package/lib/htmltaxon.js +13 -0
  23. package/lib/index.d.ts +49 -1
  24. package/lib/index.js +3 -2
  25. package/lib/photo.js +1 -10
  26. package/lib/plants/glossary.js +2 -4
  27. package/lib/program.js +10 -2
  28. package/lib/sitegenerator.js +13 -3
  29. package/lib/taxa.js +14 -10
  30. package/lib/taxon.js +18 -14
  31. package/lib/tools/calflora.js +41 -9
  32. package/lib/tools/calscape.js +4 -4
  33. package/lib/tools/cch2.js +95 -0
  34. package/lib/tools/inat.js +7 -7
  35. package/lib/tools/jepsoneflora.js +28 -4
  36. package/lib/tools/jepsonfamilies.js +102 -0
  37. package/lib/tools/rpi.js +5 -5
  38. package/lib/tools/supplementaltext.js +43 -0
  39. package/lib/tools/taxacsv.js +2 -2
  40. package/lib/utils/inat-tools.js +39 -2
  41. package/lib/web/glossarypages.js +6 -6
  42. package/lib/web/pagetaxon.js +11 -3
  43. package/package.json +6 -7
  44. package/scripts/cpl-photos.js +2 -2
  45. package/scripts/cpl-tools.js +23 -3
  46. package/scripts/inatobsphotos.js +10 -1
  47. package/scripts/inattaxonphotos.js +45 -43
  48. package/types/classes.d.ts +0 -205
@@ -0,0 +1 @@
1
+ [Perianth](./g/perianth.html) without teeth.
@@ -0,0 +1 @@
1
+ [Perianth](./g/perianth.html) with teeth.
@@ -0,0 +1 @@
1
+ [Perianth](./g/perianth.html) with teeth.
@@ -0,0 +1 @@
1
+ Leaves only on stem (no basal leaves).
package/lib/config.js CHANGED
@@ -2,9 +2,15 @@ import * as path from "node:path";
2
2
  import * as url from "node:url";
3
3
  import { Files } from "./files.js";
4
4
 
5
+ /** @type {Object<string,string>} */
6
+ const COUNTY_NAMES = {
7
+ ALA: "Alameda",
8
+ CCA: "Contra Costa",
9
+ };
10
+
5
11
  class Config {
6
12
  static #packageDir = path.dirname(
7
- path.dirname(url.fileURLToPath(import.meta.url))
13
+ path.dirname(url.fileURLToPath(import.meta.url)),
8
14
  );
9
15
 
10
16
  /** @type {Object<string,Object<string,Object<string,{}>>>} */
@@ -55,6 +61,14 @@ class Config {
55
61
  return [];
56
62
  }
57
63
 
64
+ /**
65
+ * @returns {string[]}
66
+ */
67
+ getCountyNames() {
68
+ const counties = this.getCountyCodes();
69
+ return counties.map((c) => COUNTY_NAMES[c]);
70
+ }
71
+
58
72
  /**
59
73
  * @param {string} name
60
74
  * @param {string} dflt
package/lib/csv.js CHANGED
@@ -13,7 +13,7 @@ class CSV {
13
13
  */
14
14
  static #getOptions(fileName, columns, delimiter) {
15
15
  /** @type {import("csv-parse").Options} */
16
- const options = { relax_column_count_less: true };
16
+ const options = { relax_column_count_less: true, bom: true };
17
17
  options.columns = columns;
18
18
  if (path.extname(fileName) === ".tsv") {
19
19
  options.delimiter = "\t";
@@ -44,6 +44,7 @@ class CSV {
44
44
  * @param {boolean|import("csv-parse").ColumnOption[]} columns
45
45
  * @param {string|undefined} delimiter
46
46
  * @param {function (any):void} callback
47
+ * @deprecated Use parseFileStream
47
48
  */
48
49
  static async parseStream(
49
50
  dir,
@@ -72,6 +73,27 @@ class CSV {
72
73
  await processFile();
73
74
  }
74
75
 
76
+ /**
77
+ * @template T
78
+ * @param {string} fileName
79
+ * @param {function (T):void} callback
80
+ */
81
+ static async parseFileStream(fileName, callback) {
82
+ const options = this.#getOptions(fileName, true, undefined);
83
+ const processFile = async () => {
84
+ const parser = fs.createReadStream(fileName).pipe(parse(options));
85
+ parser.on("readable", function () {
86
+ let record;
87
+ while ((record = parser.read()) !== null) {
88
+ callback(record);
89
+ }
90
+ });
91
+ await finished(parser);
92
+ };
93
+ // Parse the CSV content
94
+ await processFile();
95
+ }
96
+
75
97
  /**
76
98
  * @param {string} fileName
77
99
  * @param {boolean|import("csv-parse").ColumnOption[]|function (string[]):string[]} [columns]
@@ -3,7 +3,7 @@ import { EBook } from "./ebook.js";
3
3
 
4
4
  class GlossaryPages extends BaseGlossaryPages {
5
5
  /**
6
- * @param {SiteGenerator} siteGenerator
6
+ * @param {import("../sitegenerator.js").SiteGenerator} siteGenerator
7
7
  */
8
8
  constructor(siteGenerator) {
9
9
  super(siteGenerator);
@@ -19,8 +19,8 @@ class GlossaryPages extends BaseGlossaryPages {
19
19
  manifestEntries.push(
20
20
  EBook.getManifestEntry(
21
21
  "g" + index,
22
- "g/" + entry.getHTMLFileName()
23
- )
22
+ "g/" + entry.getHTMLFileName(),
23
+ ),
24
24
  );
25
25
  }
26
26
 
@@ -12,9 +12,9 @@ class Images {
12
12
  #taxa;
13
13
 
14
14
  /**
15
- * @param {SiteGenerator} siteGenerator
15
+ * @param {import("../sitegenerator.js").SiteGenerator} siteGenerator
16
16
  * @param {string} contentDir
17
- * @param {Taxa} taxa
17
+ * @param {import("../taxa.js").Taxa} taxa
18
18
  */
19
19
  constructor(siteGenerator, contentDir, taxa) {
20
20
  this.#siteGenerator = siteGenerator;
@@ -6,7 +6,7 @@ class PageListFamilies extends EBookPage {
6
6
 
7
7
  /**
8
8
  * @param {string} outputDir
9
- * @param {Families} families
9
+ * @param {import("../../families.js").Families} families
10
10
  */
11
11
  constructor(outputDir, families) {
12
12
  super(outputDir + "/list_families.html", "All Families");
@@ -6,12 +6,12 @@ class PageListFlowerColor extends EBookPage {
6
6
 
7
7
  /**
8
8
  * @param {string} outputDir
9
- * @param {FlowerColor} color
9
+ * @param {import("../../flowercolor.js").FlowerColor} color
10
10
  */
11
11
  constructor(outputDir, color) {
12
12
  super(
13
13
  outputDir + "/" + color.getFileName(),
14
- color.getColorName(true) + " Flowers"
14
+ color.getColorName(true) + " Flowers",
15
15
  );
16
16
  this.#color = color;
17
17
  }
@@ -8,7 +8,7 @@ const FN_FLOWER_TIME_INDEX = "fm.html";
8
8
  class PageListFlowers {
9
9
  /**
10
10
  * @param {string} contentDir
11
- * @param {Taxa} taxa
11
+ * @param {import("../../taxa.js").Taxa} taxa
12
12
  */
13
13
  static createPages(contentDir, taxa) {
14
14
  new PageListFlowerTimeIndex(contentDir).create();
@@ -21,14 +21,14 @@ class PageListFlowers {
21
21
  const manifestEntries = [];
22
22
 
23
23
  manifestEntries.push(
24
- EBook.getManifestEntry("fm0", FN_FLOWER_TIME_INDEX)
24
+ EBook.getManifestEntry("fm0", FN_FLOWER_TIME_INDEX),
25
25
  );
26
26
  for (let m1 = 1; m1 < 13; m1++) {
27
27
  manifestEntries.push(
28
28
  EBook.getManifestEntry(
29
29
  "fm" + m1,
30
- PageListFlowerTime.getFileNameBloomTime(m1)
31
- )
30
+ PageListFlowerTime.getFileNameBloomTime(m1),
31
+ ),
32
32
  );
33
33
  }
34
34
 
@@ -54,8 +54,8 @@ class PageListFlowers {
54
54
  PageListFlowerTime.getFileNameBloomTime(m1),
55
55
  DateUtils.getMonthName(m1) +
56
56
  " - " +
57
- DateUtils.getMonthName((m1 % 12) + 1)
58
- )
57
+ DateUtils.getMonthName((m1 % 12) + 1),
58
+ ),
59
59
  );
60
60
  }
61
61
  return XHTML.wrap("ol", XHTML.arrayToLI(links));
@@ -83,7 +83,7 @@ class PageListFlowerTime extends EBookPage {
83
83
 
84
84
  /**
85
85
  * @param {string} outputDir
86
- * @param {Taxa} taxa
86
+ * @param {import("../../taxa.js").Taxa} taxa
87
87
  * @param {number} month
88
88
  */
89
89
  constructor(outputDir, taxa, month) {
@@ -92,7 +92,7 @@ class PageListFlowerTime extends EBookPage {
92
92
  "Flowering in " +
93
93
  DateUtils.getMonthName(month) +
94
94
  " - " +
95
- DateUtils.getMonthName((month % 12) + 1)
95
+ DateUtils.getMonthName((month % 12) + 1),
96
96
  );
97
97
  this.#taxa = taxa;
98
98
  this.#m1 = month;
@@ -7,7 +7,7 @@ class TOCPage extends EBookPage {
7
7
 
8
8
  /**
9
9
  * @param {string} outputDir
10
- * @param {Taxa} taxa
10
+ * @param {import("../../taxa.js").Taxa} taxa
11
11
  */
12
12
  constructor(outputDir, taxa) {
13
13
  super(outputDir + "/toc.xhtml", "Table of Contents");
@@ -37,7 +37,7 @@ class TOCPage extends EBookPage {
37
37
  for (const color of this.#taxa.getFlowerColors()) {
38
38
  const colorName = color.getColorName();
39
39
  links.push(
40
- XHTML.getLink("list_fc_" + colorName + ".html", colorName)
40
+ XHTML.getLink("list_fc_" + colorName + ".html", colorName),
41
41
  );
42
42
  }
43
43
  return html + XHTML.wrap("ol", XHTML.arrayToLI(links));
@@ -17,7 +17,7 @@ class PlantBook extends EBook {
17
17
 
18
18
  /**
19
19
  * @param {string} outputDir
20
- * @param {Config} config
20
+ * @param {import("../config.js").Config} config
21
21
  * @param {import("../taxa.js").Taxa} taxa
22
22
  */
23
23
  constructor(outputDir, config, taxa) {
@@ -168,7 +168,7 @@ class PlantBook extends EBook {
168
168
  }
169
169
 
170
170
  /**
171
- * @param {Config} config
171
+ * @param {import("../config.js").Config} config
172
172
  * @param {string} name
173
173
  * @returns {string}
174
174
  */
@@ -1,27 +1,60 @@
1
- class ExternalSites {
1
+ /** @typedef {{
2
+ coords?: [number, number];
3
+ project_id?: string;
4
+ subview?: "grid" | "list" | "map";
5
+ taxon_id?: string;
6
+ }} InatObsOptions */
7
+
8
+ export class ExternalSites {
9
+ /**
10
+ * @param {import("./taxon.js").Taxon} taxon
11
+ * @param {import("./config.js").Config} config
12
+ * @returns {URL|undefined}
13
+ */
14
+ static getCCH2ObsLink(taxon, config) {
15
+ const url = new URL(
16
+ "https://www.cch2.org/portal/collections/listtabledisplay.php?usethes=1&taxontype=2&sortfield1=o.eventDate&sortorder=desc",
17
+ );
18
+ url.searchParams.set("county", config.getCountyNames().join(";"));
19
+ url.searchParams.set("taxa", taxon.getName());
20
+ return url;
21
+ }
22
+
23
+ /**
24
+ * @param {import("./taxon.js").Taxon} taxon
25
+ * @returns {URL|undefined}
26
+ */
27
+ static getCCH2RefLink(taxon) {
28
+ const id = taxon.getCCH2ID();
29
+ if (!id) {
30
+ return;
31
+ }
32
+ const url = new URL("https://www.cch2.org/portal/taxa/index.php");
33
+ url.searchParams.set("taxon", id);
34
+ return url;
35
+ }
36
+
2
37
  /**
3
38
  * @param {InatObsOptions} options
4
39
  */
5
40
  static getInatObsLink(options) {
6
41
  const url = new URL(
7
- "https://www.inaturalist.org/observations?subview=map"
42
+ "https://www.inaturalist.org/observations?subview=map",
8
43
  );
9
44
 
45
+ if (options.coords) {
46
+ const delta = 0.1;
47
+ const params = url.searchParams;
48
+ const lat = options.coords[1];
49
+ const lng = options.coords[0];
50
+ params.set("nelat", (lat + delta).toString());
51
+ params.set("swlat", (lat - delta).toString());
52
+ params.set("nelng", (lng + delta).toString());
53
+ params.set("swlng", (lng - delta).toString());
54
+ }
55
+
10
56
  for (const [k, v] of Object.entries(options)) {
11
57
  switch (k) {
12
- case "coords": {
13
- const delta = 0.1;
14
- const params = url.searchParams;
15
- /** @type {number} */
16
- const lat = v[1];
17
- /** @type {number} */
18
- const lng = v[0];
19
- params.set("nelat", (lat + delta).toString());
20
- params.set("swlat", (lat - delta).toString());
21
- params.set("nelng", (lng + delta).toString());
22
- params.set("swlng", (lng - delta).toString());
23
- break;
24
- }
25
58
  case "created_d1":
26
59
  case "list_id":
27
60
  case "place_id":
@@ -29,7 +62,7 @@ class ExternalSites {
29
62
  case "subview":
30
63
  case "taxon_id":
31
64
  case "taxon_name":
32
- if (v) {
65
+ if (typeof v === "string") {
33
66
  url.searchParams.set(k, v);
34
67
  }
35
68
  break;
@@ -39,5 +72,3 @@ class ExternalSites {
39
72
  return url.toString();
40
73
  }
41
74
  }
42
-
43
- export { ExternalSites };
package/lib/families.js CHANGED
@@ -5,7 +5,7 @@ import { Files } from "./files.js";
5
5
  import { Config } from "./config.js";
6
6
  import { HTMLTaxon } from "./htmltaxon.js";
7
7
 
8
- class Family {
8
+ export class Family {
9
9
  #name;
10
10
  #data;
11
11
 
package/lib/files.js CHANGED
@@ -140,7 +140,7 @@ class Files {
140
140
  if (entry.path === fileNameToUnzip) {
141
141
  await this.#createFileFromStream(
142
142
  targetFilePath,
143
- entry.stream()
143
+ entry.stream(),
144
144
  );
145
145
  break;
146
146
  }
@@ -3,7 +3,7 @@ import { TextUtils } from "./textutils.js";
3
3
  class FlowerColor {
4
4
  #colorName;
5
5
  #colorCode;
6
- /** @type {Taxon[]} */
6
+ /** @type {import("./taxon.js").Taxon[]} */
7
7
  #taxa = [];
8
8
 
9
9
  /**
@@ -16,7 +16,7 @@ class FlowerColor {
16
16
  }
17
17
 
18
18
  /**
19
- * @param {Taxon} taxon
19
+ * @param {import("./taxon.js").Taxon} taxon
20
20
  */
21
21
  addTaxon(taxon) {
22
22
  this.#taxa.push(taxon);
package/lib/genera.js CHANGED
@@ -6,7 +6,7 @@ class Genera {
6
6
  #genera;
7
7
 
8
8
  /**
9
- * @param {Families} families
9
+ * @param {import("./families.js").Families} families
10
10
  */
11
11
  constructor(families) {
12
12
  const dataDir = Config.getPackageDir() + "/data";
@@ -46,7 +46,7 @@ class Genus {
46
46
  #data;
47
47
 
48
48
  /**
49
- * @param {{family:string,familyObj:Family,taxa:Taxon[]}} data
49
+ * @param {{family:string,familyObj:import("./families.js").Family,taxa:import("./taxon.js").Taxon[]}} data
50
50
  */
51
51
  constructor(data) {
52
52
  this.#data = data;
@@ -56,6 +56,9 @@ class Genus {
56
56
  return this.#data.familyObj;
57
57
  }
58
58
 
59
+ /**
60
+ * @returns {import("./taxon.js").Taxon[]}
61
+ */
59
62
  getTaxa() {
60
63
  return this.#data.taxa.sort((a, b) =>
61
64
  a.getName().localeCompare(b.getName()),
package/lib/htmltaxon.js CHANGED
@@ -54,6 +54,19 @@ const DEFAULT_TAXA_COLUMNS = [
54
54
  ];
55
55
 
56
56
  class HTMLTaxon {
57
+ /**
58
+ * @param {string[]} links
59
+ * @param {URL|string|undefined} href
60
+ * @param {string} label
61
+ */
62
+ static addLink(links, href, label) {
63
+ if (href === undefined) {
64
+ return;
65
+ }
66
+ const link = HTML.getLink(href.toString(), label, {}, true);
67
+ links.push(link);
68
+ }
69
+
57
70
  /**
58
71
  * @param {import("./taxon.js").Taxon} taxon
59
72
  * @returns {string|undefined}
package/lib/index.d.ts CHANGED
@@ -1,5 +1,32 @@
1
1
  import { Command } from "commander";
2
2
 
3
+ // Types
4
+
5
+ export type NativeStatusCode = "N" | "NC" | "U" | "X";
6
+
7
+ export type TaxonData = {
8
+ bloom_end: string;
9
+ bloom_start: string;
10
+ calrecnum: string;
11
+ calscape_cn?: string;
12
+ cch2_id: string;
13
+ CESA: string;
14
+ "common name": string;
15
+ CRPR: string;
16
+ FESA: string;
17
+ flower_color: string;
18
+ GRank: string;
19
+ "inat id": string;
20
+ "jepson id": string;
21
+ life_cycle: string;
22
+ "RPI ID": string;
23
+ SRank: string;
24
+ status: NativeStatusCode;
25
+ taxon_name: string;
26
+ };
27
+
28
+ // Classes
29
+
3
30
  export class Config {
4
31
  constructor(dataDir: string);
5
32
  getConfigValue(
@@ -34,6 +61,15 @@ export class Exceptions {
34
61
  hasException(name: string, cat: string, subcat: string): boolean;
35
62
  }
36
63
 
64
+ export class ExternalSites {
65
+ static getCCH2ObsLink(taxon: Taxon, config: Config): URL | undefined;
66
+ static getCCH2RefLink(taxon: Taxon): URL | undefined;
67
+ }
68
+
69
+ export class Family {
70
+ getName(): string;
71
+ }
72
+
37
73
  export class Files {
38
74
  static exists(fileName: string): boolean;
39
75
  static fetch(
@@ -45,6 +81,12 @@ export class Files {
45
81
  static write(fileName: string, data: string, overwrite: boolean): void;
46
82
  }
47
83
 
84
+ export class Genera {}
85
+
86
+ export class Genus {
87
+ getTaxa(): Taxon[];
88
+ }
89
+
48
90
  export class HTML {
49
91
  static arrayToLI(items: string[]): string;
50
92
  static getLink(
@@ -66,6 +108,11 @@ export class HTML {
66
108
  }
67
109
 
68
110
  export class HTMLTaxon {
111
+ static addLink(
112
+ links: string[],
113
+ href: URL | string | undefined,
114
+ label: string,
115
+ ): void;
69
116
  static getFooterHTML(taxon: Taxon): string;
70
117
  static getListSectionHTML(
71
118
  list: string[],
@@ -101,7 +148,7 @@ export class Taxa {
101
148
  showFlowerErrors: boolean,
102
149
  taxonFactory?: (td: TaxonData, g: Genera) => Taxon,
103
150
  extraTaxa?: TaxonData[],
104
- extraSynonyms?: SynonymData[],
151
+ extraSynonyms?: Record<string, string>[],
105
152
  );
106
153
  getTaxon(name: string): Taxon;
107
154
  getTaxonList(): Taxon[];
@@ -115,6 +162,7 @@ export class Taxon {
115
162
  getCNDDBRank(): string | undefined;
116
163
  getCommonNames(): string[];
117
164
  getFamily(): Family;
165
+ getFileName(): string;
118
166
  getFESA(): string | undefined;
119
167
  getGenus(): Genus;
120
168
  getGenusName(): string;
package/lib/index.js CHANGED
@@ -3,6 +3,7 @@ import { Config } from "./config.js";
3
3
  import { CSV } from "./csv.js";
4
4
  import { ErrorLog } from "./errorlog.js";
5
5
  import { Exceptions } from "./exceptions.js";
6
+ import { ExternalSites } from "./externalsites.js";
6
7
  import { Families } from "./families.js";
7
8
  import { Files } from "./files.js";
8
9
  import { HTML } from "./html.js";
@@ -11,7 +12,7 @@ import { Jekyll } from "./jekyll.js";
11
12
  import { PlantBook } from "./ebook/plantbook.js";
12
13
  import { Program } from "./program.js";
13
14
  import { Taxa } from "./taxa.js";
14
- import { Taxon, TAXA_COLNAMES } from "./taxon.js";
15
+ import { Taxon } from "./taxon.js";
15
16
 
16
17
  export {
17
18
  BasePageRenderer,
@@ -19,6 +20,7 @@ export {
19
20
  CSV,
20
21
  ErrorLog,
21
22
  Exceptions,
23
+ ExternalSites,
22
24
  Families,
23
25
  Files,
24
26
  HTML,
@@ -27,6 +29,5 @@ export {
27
29
  PlantBook,
28
30
  Program,
29
31
  Taxa,
30
- TAXA_COLNAMES,
31
32
  Taxon,
32
33
  };
package/lib/photo.js CHANGED
@@ -1,14 +1,5 @@
1
1
  /**
2
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
3
  */
13
4
 
14
5
  export class Photo {
@@ -21,7 +12,7 @@ export class Photo {
21
12
  /**
22
13
  * @param {number} id
23
14
  * @param {string} ext
24
- * @param {InatLicenseCode} licenseCode
15
+ * @param {import("./utils/inat-tools.js").InatLicenseCode} licenseCode
25
16
  * @param {string} rightsHolder
26
17
  */
27
18
  constructor(id, ext, licenseCode, rightsHolder) {
@@ -1,7 +1,7 @@
1
1
  import { Config } from "../config.js";
2
2
  import { Files } from "../files.js";
3
3
 
4
- class Glossary {
4
+ export class Glossary {
5
5
  #srcPath;
6
6
  /** @type {GlossaryEntry[]} */
7
7
  #srcEntries = [];
@@ -21,7 +21,7 @@ class Glossary {
21
21
  }
22
22
  }
23
23
 
24
- class GlossaryEntry {
24
+ export class GlossaryEntry {
25
25
  #srcPath;
26
26
  #fileName;
27
27
  #term;
@@ -48,5 +48,3 @@ class GlossaryEntry {
48
48
  return this.#term;
49
49
  }
50
50
  }
51
-
52
- export { Glossary };
package/lib/program.js CHANGED
@@ -3,6 +3,14 @@ import { Files } from "./files.js";
3
3
  import { CSV } from "./csv.js";
4
4
  import path from "node:path";
5
5
 
6
+ /**
7
+ * @typedef {{
8
+ datadir: string;
9
+ outputdir: string;
10
+ "show-flower-errors": boolean;
11
+ }} CommandLineOptions
12
+ */
13
+
6
14
  class Program {
7
15
  /**
8
16
  * @param {string} dataDir
@@ -16,10 +24,10 @@ class Program {
16
24
  return true;
17
25
  }
18
26
 
19
- /** @type {TaxonData[]} */
27
+ /** @type {import("./index.js").TaxonData[]} */
20
28
  // @ts-ignore
21
29
  const includeCSV = CSV.readFile(path.join(dataDir, includeFileName));
22
- /** @type {Object<string,TaxonData>} */
30
+ /** @type {Object<string,import("./index.js").TaxonData>} */
23
31
  const include = {};
24
32
  for (const row of includeCSV) {
25
33
  include[row["taxon_name"]] = row;
@@ -14,12 +14,12 @@ class SiteGenerator {
14
14
  }
15
15
 
16
16
  /**
17
- * @param {FlowerColor[]} flowerColors
17
+ * @param {import("./flowercolor.js").FlowerColor[]} flowerColors
18
18
  */
19
19
  copyIllustrations(flowerColors) {
20
20
  /**
21
21
  * @param {string} outputDir
22
- * @param {FlowerColor[]} flowerColors
22
+ * @param {import("./flowercolor.js").FlowerColor[]} flowerColors
23
23
  */
24
24
  function createFlowerColorIcons(outputDir, flowerColors) {
25
25
  // Read generic input.
@@ -28,7 +28,7 @@ class SiteGenerator {
28
28
  for (const color of flowerColors) {
29
29
  Files.write(
30
30
  Files.join(outputDir, "f-" + color.getColorName() + ".svg"),
31
- srcSVG.replace("#ff0", color.getColorCode())
31
+ srcSVG.replace("#ff0", color.getColorCode()),
32
32
  );
33
33
  }
34
34
  // Delete input file.
@@ -69,6 +69,16 @@ class SiteGenerator {
69
69
  mkdir(path) {
70
70
  Files.mkdir(Files.join(this.#baseDir, path));
71
71
  }
72
+
73
+ /**
74
+ * @param {string} content
75
+ * @param {{title:string}} attributes
76
+ * @param {string} filename
77
+ */
78
+ // eslint-disable-next-line no-unused-vars
79
+ writeTemplate(content, attributes, filename) {
80
+ throw new Error("must be implemented by subclass");
81
+ }
72
82
  }
73
83
 
74
84
  export { SiteGenerator };