@ca-plant-list/ca-plant-list 0.2.18 → 0.3.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.
- package/data/exceptions.json +83 -68
- package/data/illustrations/inkscape/asteraceae_floret.svg +125 -83
- package/data/illustrations/inkscape/peduncle.svg +38 -34
- package/data/synonyms.csv +20 -20
- package/data/taxa.csv +11 -14
- package/ebook/css/main.css +3 -6
- package/jekyll/_layouts/default.html +56 -0
- package/jekyll/_layouts/html.html +5 -56
- package/jekyll/assets/css/main.css +5 -0
- package/lib/basepagerenderer.js +7 -3
- package/lib/commandandtaxaprocessor.js +3 -0
- package/lib/ebook/ebooksitegenerator.js +34 -0
- package/lib/ebook/glossarypages.js +6 -67
- package/lib/ebook/images.js +10 -8
- package/lib/ebook/pages/taxonpage.js +5 -1
- package/lib/ebook/pages/tocpage.js +2 -2
- package/lib/ebook/plantbook.js +12 -9
- package/lib/errorlog.js +4 -0
- package/lib/files.js +5 -0
- package/lib/index.d.ts +17 -2
- package/lib/jekyll.js +13 -1
- package/lib/sitegenerator.js +79 -0
- package/lib/taxa.js +30 -7
- package/lib/taxaprocessor.js +1 -1
- package/lib/web/glossarypages.js +23 -18
- package/package.json +3 -2
- package/data/illustrations/optimized/asteraceae_floret.svg +0 -28
- package/data/illustrations/optimized/f-blue.svg +0 -11
- package/data/illustrations/optimized/f-orange.svg +0 -11
- package/data/illustrations/optimized/f-pink.svg +0 -11
- package/data/illustrations/optimized/f-red.svg +0 -11
- package/data/illustrations/optimized/f-white.svg +0 -11
- package/data/illustrations/optimized/f-yellow.svg +0 -11
- package/data/illustrations/optimized/peduncle.svg +0 -21
- package/jekyll/glossary.md +0 -5
package/lib/ebook/plantbook.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import { Families } from "@ca-plant-list/ca-plant-list";
|
2
2
|
import { EBook } from "./ebook.js";
|
3
|
+
import { EBookSiteGenerator } from "./ebooksitegenerator.js";
|
3
4
|
import { GlossaryPages } from "./glossarypages.js";
|
4
5
|
import { Images } from "./images.js";
|
5
6
|
import { PageListFamilies } from "./pages/page_list_families.js";
|
@@ -8,7 +9,7 @@ import { PageListFlowers } from "./pages/page_list_flowers.js";
|
|
8
9
|
import { PageListSpecies } from "./pages/page_list_species.js";
|
9
10
|
import { TaxonPage } from "./pages/taxonpage.js";
|
10
11
|
import { TOCPage } from "./pages/tocpage.js";
|
11
|
-
import {
|
12
|
+
import { Taxa } from "../taxa.js";
|
12
13
|
|
13
14
|
class PlantBook extends EBook {
|
14
15
|
|
@@ -26,8 +27,9 @@ class PlantBook extends EBook {
|
|
26
27
|
);
|
27
28
|
|
28
29
|
this.#taxa = taxa;
|
29
|
-
|
30
|
-
this.#
|
30
|
+
const generator = new EBookSiteGenerator( this.getContentDir() );
|
31
|
+
this.#glossary = new GlossaryPages( generator );
|
32
|
+
this.#images = new Images( generator, this.getContentDir(), taxa );
|
31
33
|
|
32
34
|
}
|
33
35
|
|
@@ -35,15 +37,17 @@ class PlantBook extends EBook {
|
|
35
37
|
|
36
38
|
const contentDir = this.getContentDir();
|
37
39
|
|
40
|
+
await this.#images.createImages( contentDir );
|
41
|
+
|
38
42
|
console.log( "creating taxon pages" );
|
39
43
|
const taxonList = this.#taxa.getTaxonList();
|
40
44
|
for ( const taxon of taxonList ) {
|
41
45
|
const name = taxon.getName();
|
42
|
-
new TaxonPage( contentDir, taxon, this.#images
|
46
|
+
new TaxonPage( contentDir, taxon, this.#images.getTaxonImages( name ) ).create();
|
43
47
|
}
|
44
48
|
|
45
49
|
// Create lists.
|
46
|
-
for ( const colorName of
|
50
|
+
for ( const colorName of Taxa.getFlowerColorNames() ) {
|
47
51
|
new PageListFlowerColor( contentDir, this.#taxa.getFlowerColor( colorName ) ).create();
|
48
52
|
}
|
49
53
|
|
@@ -60,8 +64,7 @@ class PlantBook extends EBook {
|
|
60
64
|
}
|
61
65
|
new PageListSpecies( contentDir, taxonList, "list_species.html", "All Species" ).create();
|
62
66
|
|
63
|
-
|
64
|
-
this.#glossary.createPages( contentDir );
|
67
|
+
this.#glossary.renderPages();
|
65
68
|
|
66
69
|
new TOCPage( contentDir ).create();
|
67
70
|
}
|
@@ -73,7 +76,7 @@ class PlantBook extends EBook {
|
|
73
76
|
// Add lists.
|
74
77
|
xml += "<item id=\"lspecies\" href=\"list_species.html\" media-type=\"application/xhtml+xml\" />";
|
75
78
|
xml += "<item id=\"lfamilies\" href=\"list_families.html\" media-type=\"application/xhtml+xml\" />";
|
76
|
-
for ( const colorName of
|
79
|
+
for ( const colorName of Taxa.getFlowerColorNames() ) {
|
77
80
|
const color = this.#taxa.getFlowerColor( colorName );
|
78
81
|
xml += "<item id=\"l" + color.getColorName() + "\" href=\"" + color.getFileName() + "\" media-type=\"application/xhtml+xml\" />";
|
79
82
|
}
|
@@ -105,7 +108,7 @@ class PlantBook extends EBook {
|
|
105
108
|
let xml = "";
|
106
109
|
|
107
110
|
// Add lists.
|
108
|
-
for ( const colorName of
|
111
|
+
for ( const colorName of Taxa.getFlowerColorNames() ) {
|
109
112
|
const color = this.#taxa.getFlowerColor( colorName );
|
110
113
|
xml += "<itemref idref=\"l" + color.getColorName() + "\"/>";
|
111
114
|
}
|
package/lib/errorlog.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import * as fs from "node:fs";
|
2
|
+
import * as path from "node:path";
|
2
3
|
|
3
4
|
class ErrorLog {
|
4
5
|
|
@@ -19,6 +20,9 @@ class ErrorLog {
|
|
19
20
|
}
|
20
21
|
|
21
22
|
write() {
|
23
|
+
// Make sure directory exists.
|
24
|
+
fs.mkdirSync( path.dirname( this.#fileName ), { recursive: true } );
|
25
|
+
|
22
26
|
fs.writeFileSync( this.#fileName, this.#errors.join( "\n" ) );
|
23
27
|
}
|
24
28
|
|
package/lib/files.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import * as fs from "node:fs";
|
2
|
+
import * as path from "node:path";
|
2
3
|
import { default as unzipper } from "unzipper";
|
3
4
|
|
4
5
|
class Files {
|
@@ -52,6 +53,10 @@ class Files {
|
|
52
53
|
return stats !== undefined && stats.isDirectory();
|
53
54
|
}
|
54
55
|
|
56
|
+
static join( ...paths ) {
|
57
|
+
return path.join( ...paths ).replaceAll( "\\", "/" );
|
58
|
+
}
|
59
|
+
|
55
60
|
static mkdir( path ) {
|
56
61
|
fs.mkdirSync( path, { recursive: true } );
|
57
62
|
}
|
package/lib/index.d.ts
CHANGED
@@ -76,6 +76,7 @@ export class Files {
|
|
76
76
|
static fetch(url: string | URL, targetFileName: string | undefined, headers?: any): Promise<Headers>;
|
77
77
|
static getDirEntries(path: any): string[];
|
78
78
|
static isDir(path: any): boolean;
|
79
|
+
static join(...paths: any[]): any;
|
79
80
|
static mkdir(path: any): void;
|
80
81
|
static read(path: any): string;
|
81
82
|
static rmDir(dir: any): void;
|
@@ -174,12 +175,14 @@ import { TaxaProcessor } from "./taxaprocessor.js";
|
|
174
175
|
import { TAXA_COLNAMES } from "./taxon.js";
|
175
176
|
import { Taxon } from "./taxon.js";
|
176
177
|
export { BasePageRenderer, CommandProcessor, CommandAndTaxaProcessor, Config, CSV, ErrorLog, Exceptions, Families, Files, GenericTaxaLoader, HTML, Jekyll, PlantBook, Taxa, TaxaLoader, TaxaProcessor, TAXA_COLNAMES, Taxon };
|
177
|
-
export class Jekyll {
|
178
|
+
export class Jekyll extends SiteGenerator {
|
178
179
|
static getFrontMatter(atts: any): string;
|
179
180
|
static hasInclude(baseDir: any, path: any): boolean;
|
180
181
|
static include(path: any): string;
|
181
182
|
static writeInclude(baseDir: any, path: any, data: any): void;
|
183
|
+
writeTemplate(content: any, attributes: any, filename: any): void;
|
182
184
|
}
|
185
|
+
import { SiteGenerator } from "./sitegenerator.js";
|
183
186
|
export class Jepson {
|
184
187
|
static getEFloraLink(id: any): string;
|
185
188
|
}
|
@@ -194,16 +197,28 @@ export class RarePlants {
|
|
194
197
|
static getRPIRankDescription(rank: any): any;
|
195
198
|
static getRPIRankAndThreatDescriptions(rank: any): any[];
|
196
199
|
}
|
197
|
-
export
|
200
|
+
export class SiteGenerator {
|
201
|
+
constructor(baseDir: any);
|
202
|
+
copyIllustrations(flowerColors: any): void;
|
203
|
+
getBaseDir(): any;
|
204
|
+
mkdir(path: any): void;
|
205
|
+
#private;
|
206
|
+
}
|
198
207
|
export class Taxa {
|
199
208
|
static getHTMLTable(taxa: any, columns?: {
|
200
209
|
title: string;
|
201
210
|
data: (t: any) => any;
|
202
211
|
}[]): string;
|
212
|
+
static getFlowerColorNames(): string[];
|
213
|
+
static getFlowerColors(): {
|
214
|
+
name: string;
|
215
|
+
color: string;
|
216
|
+
}[];
|
203
217
|
constructor(inclusionList: any, errorLog: any, showFlowerErrors: any, taxaMeta?: {}, taxonClass?: typeof Taxon, extraTaxa?: any[], extraSynonyms?: any[]);
|
204
218
|
getFlowerColor(name: any): any;
|
205
219
|
getTaxon(name: any): any;
|
206
220
|
getTaxonList(): any[];
|
221
|
+
hasSynonym(formerName: any): boolean;
|
207
222
|
#private;
|
208
223
|
}
|
209
224
|
export namespace TAXA_LIST_COLS {
|
package/lib/jekyll.js
CHANGED
@@ -1,14 +1,22 @@
|
|
1
1
|
import { Files } from "./files.js";
|
2
|
+
import { SiteGenerator } from "./sitegenerator.js";
|
2
3
|
|
3
4
|
const FRONT_DELIM = "---";
|
4
5
|
|
5
|
-
class Jekyll {
|
6
|
+
class Jekyll extends SiteGenerator {
|
7
|
+
|
8
|
+
constructor( baseDir ) {
|
9
|
+
super( baseDir );
|
10
|
+
}
|
6
11
|
|
7
12
|
static getFrontMatter( atts ) {
|
8
13
|
const lines = [ FRONT_DELIM ];
|
9
14
|
for ( const [ k, v ] of Object.entries( atts ) ) {
|
10
15
|
lines.push( k + ": \"" + v + "\"" );
|
11
16
|
}
|
17
|
+
if ( !atts.layout ) {
|
18
|
+
lines.push( "layout: default" );
|
19
|
+
}
|
12
20
|
lines.push( FRONT_DELIM );
|
13
21
|
return lines.join( "\n" ) + "\n";
|
14
22
|
}
|
@@ -26,6 +34,10 @@ class Jekyll {
|
|
26
34
|
Files.write( baseDir + "/_includes/" + path, data );
|
27
35
|
}
|
28
36
|
|
37
|
+
writeTemplate( content, attributes, filename ) {
|
38
|
+
Files.write( Files.join( this.getBaseDir(), filename ), Jekyll.getFrontMatter( attributes ) + content );
|
39
|
+
}
|
40
|
+
|
29
41
|
}
|
30
42
|
|
31
43
|
export { Jekyll };
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import { optimize } from "svgo";
|
2
|
+
|
3
|
+
import { Config } from "./config.js";
|
4
|
+
import { Files } from "./files.js";
|
5
|
+
|
6
|
+
class SiteGenerator {
|
7
|
+
#baseDir;
|
8
|
+
|
9
|
+
constructor( baseDir ) {
|
10
|
+
this.#baseDir = baseDir;
|
11
|
+
}
|
12
|
+
|
13
|
+
copyIllustrations( flowerColors ) {
|
14
|
+
function createFlowerColorIcons( outputDir, flowerColors ) {
|
15
|
+
// Read generic input.
|
16
|
+
const inputFileName = Files.join( outputDir, "flower.svg" );
|
17
|
+
const srcSVG = Files.read( inputFileName );
|
18
|
+
for ( const color of flowerColors ) {
|
19
|
+
Files.write(
|
20
|
+
Files.join( outputDir, "f-" + color.name + ".svg" ),
|
21
|
+
srcSVG.replace( "#ff0", color.color )
|
22
|
+
);
|
23
|
+
}
|
24
|
+
// Delete input file.
|
25
|
+
Files.rmDir( inputFileName );
|
26
|
+
}
|
27
|
+
|
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, {
|
35
|
+
plugins: [
|
36
|
+
{
|
37
|
+
name: "preset-default",
|
38
|
+
params: {
|
39
|
+
overrides: {
|
40
|
+
// minifyStyles changes font-weight: normal to 400, which keeps it from being removed as a default.
|
41
|
+
// Disable it here and run it last.
|
42
|
+
minifyStyles: false,
|
43
|
+
removeViewBox: false,
|
44
|
+
},
|
45
|
+
},
|
46
|
+
},
|
47
|
+
"convertStyleToAttrs",
|
48
|
+
{
|
49
|
+
name: "removeAttrs",
|
50
|
+
params: {
|
51
|
+
attrs: "(style)",
|
52
|
+
},
|
53
|
+
},
|
54
|
+
"removeDimensions",
|
55
|
+
"minifyStyles",
|
56
|
+
],
|
57
|
+
multipass: true,
|
58
|
+
} );
|
59
|
+
Files.write( Files.join( outputDir, entry ), result.data );
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
const outputDir = Files.join( this.#baseDir, "i" );
|
64
|
+
Files.mkdir( outputDir );
|
65
|
+
|
66
|
+
optimizeSVG( outputDir );
|
67
|
+
createFlowerColorIcons( outputDir, flowerColors );
|
68
|
+
}
|
69
|
+
|
70
|
+
getBaseDir() {
|
71
|
+
return this.#baseDir;
|
72
|
+
}
|
73
|
+
|
74
|
+
mkdir( path ) {
|
75
|
+
Files.mkdir( Files.join( this.#baseDir, path ) );
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
export { SiteGenerator };
|
package/lib/taxa.js
CHANGED
@@ -4,7 +4,14 @@ import { HTML } from "./html.js";
|
|
4
4
|
import { CSV } from "./csv.js";
|
5
5
|
import { RarePlants } from "./rareplants.js";
|
6
6
|
|
7
|
-
const
|
7
|
+
const FLOWER_COLORS = [
|
8
|
+
{ name: "white", color: "white" },
|
9
|
+
{ name: "red", color: "red" },
|
10
|
+
{ name: "pink", color: "pink" },
|
11
|
+
{ name: "orange", color: "orange" },
|
12
|
+
{ name: "yellow", color: "yellow" },
|
13
|
+
{ name: "blue", color: "blue" },
|
14
|
+
];
|
8
15
|
|
9
16
|
const TAXA_LIST_COLS = {
|
10
17
|
CESA: {
|
@@ -68,13 +75,14 @@ class Taxa {
|
|
68
75
|
#taxa = {};
|
69
76
|
#flower_colors = {};
|
70
77
|
#sortedTaxa;
|
78
|
+
#synonyms = new Set();
|
71
79
|
|
72
80
|
constructor( inclusionList, errorLog, showFlowerErrors, taxaMeta = {}, taxonClass = Taxon, extraTaxa = [], extraSynonyms = [] ) {
|
73
81
|
|
74
82
|
this.#errorLog = errorLog;
|
75
83
|
|
76
|
-
for ( const color of
|
77
|
-
this.#flower_colors[ color ] = new FlowerColor( color );
|
84
|
+
for ( const color of FLOWER_COLORS ) {
|
85
|
+
this.#flower_colors[ color.name ] = new FlowerColor( color.name );
|
78
86
|
}
|
79
87
|
|
80
88
|
const dataDir = Config.getPackageDir() + "/data";
|
@@ -130,6 +138,14 @@ class Taxa {
|
|
130
138
|
return this.#flower_colors[ name ];
|
131
139
|
}
|
132
140
|
|
141
|
+
static getFlowerColorNames() {
|
142
|
+
return FLOWER_COLORS.map( ( o ) => o.name );
|
143
|
+
}
|
144
|
+
|
145
|
+
static getFlowerColors() {
|
146
|
+
return FLOWER_COLORS;
|
147
|
+
}
|
148
|
+
|
133
149
|
getTaxon( name ) {
|
134
150
|
return this.#taxa[ name ];
|
135
151
|
}
|
@@ -138,18 +154,25 @@ class Taxa {
|
|
138
154
|
return this.#sortedTaxa;
|
139
155
|
}
|
140
156
|
|
157
|
+
hasSynonym( formerName ) {
|
158
|
+
return this.#synonyms.has( formerName );
|
159
|
+
}
|
160
|
+
|
141
161
|
#loadSyns( synCSV, inclusionList ) {
|
142
162
|
for ( const syn of synCSV ) {
|
143
163
|
const currName = syn[ "Current" ];
|
144
164
|
const taxon = this.getTaxon( currName );
|
145
165
|
if ( !taxon ) {
|
146
|
-
if ( inclusionList === true ) {
|
147
|
-
// If including all taxa, note the error
|
166
|
+
if ( inclusionList === true && !syn.Type ) {
|
167
|
+
// If including all taxa, note the error - the target is not defined, and this is not
|
168
|
+
// a synonym for a non-Jepson system.
|
148
169
|
console.log( "synonym target not found: " + currName );
|
149
170
|
}
|
150
171
|
continue;
|
151
172
|
}
|
152
|
-
|
173
|
+
const formerName = syn[ "Former" ];
|
174
|
+
this.#synonyms.add( formerName );
|
175
|
+
taxon.addSynonym( formerName, syn[ "Type" ] );
|
153
176
|
}
|
154
177
|
}
|
155
178
|
|
@@ -206,4 +229,4 @@ class Taxa {
|
|
206
229
|
|
207
230
|
}
|
208
231
|
|
209
|
-
export {
|
232
|
+
export { Taxa, TAXA_LIST_COLS };
|
package/lib/taxaprocessor.js
CHANGED
@@ -27,8 +27,8 @@ class TaxaProcessor {
|
|
27
27
|
console.log( "loading data" );
|
28
28
|
this.#taxaLoader = new this.#taxaLoaderClass( this.#options );
|
29
29
|
await this.#taxaLoader.load();
|
30
|
-
await commandRunner( this );
|
31
30
|
this.#taxaLoader.writeErrorLog();
|
31
|
+
await commandRunner( this );
|
32
32
|
}
|
33
33
|
|
34
34
|
}
|
package/lib/web/glossarypages.js
CHANGED
@@ -1,49 +1,54 @@
|
|
1
1
|
import { Files, HTML } from "@ca-plant-list/ca-plant-list";
|
2
2
|
import { Glossary } from "../plants/glossary.js";
|
3
|
-
import {
|
3
|
+
import { Markdown } from "../markdown.js";
|
4
|
+
|
5
|
+
const ENTRY_DIR = "g";
|
4
6
|
|
5
7
|
class GlossaryPages {
|
6
8
|
|
7
|
-
#
|
8
|
-
#entryDir;
|
9
|
+
#siteGenerator;
|
9
10
|
#glossary;
|
10
11
|
|
11
|
-
constructor(
|
12
|
-
this.#
|
13
|
-
this.#entryDir = outputDir + "/g";
|
12
|
+
constructor( siteGenerator ) {
|
13
|
+
this.#siteGenerator = siteGenerator;
|
14
14
|
this.#glossary = new Glossary();
|
15
15
|
}
|
16
16
|
|
17
17
|
#generateEntryPage( entry ) {
|
18
|
-
const
|
19
|
-
|
20
|
-
|
18
|
+
const title = entry.getTermName();
|
19
|
+
let html = HTML.textElement( "h1", title );
|
20
|
+
html += HTML.wrap( "div", Markdown.strToHTML( entry.getMarkdown() ), { class: "glossary" } );
|
21
|
+
this.#siteGenerator.writeTemplate( html, { title: title }, Files.join( ENTRY_DIR, title + ".html" ) );
|
21
22
|
}
|
22
23
|
|
23
24
|
#generateEntryPages() {
|
25
|
+
|
26
|
+
// Make sure output directory exists.
|
27
|
+
this.#siteGenerator.mkdir( ENTRY_DIR );
|
28
|
+
|
24
29
|
const entries = this.#glossary.getEntries();
|
25
30
|
for ( const entry of entries ) {
|
26
31
|
this.#generateEntryPage( entry );
|
27
32
|
}
|
28
33
|
}
|
29
34
|
|
30
|
-
#
|
31
|
-
|
35
|
+
#generateIndexPage() {
|
32
36
|
const links = [];
|
33
37
|
const entries = this.#glossary.getEntries();
|
34
38
|
for ( const entry of entries ) {
|
35
|
-
links.push( HTML.getLink(
|
39
|
+
links.push( HTML.getLink( Files.join( ENTRY_DIR, entry.getHTMLFileName() ), entry.getTermName() ) );
|
36
40
|
}
|
41
|
+
let html = HTML.wrap( "h1", "Glossary" );
|
42
|
+
html += HTML.wrap( "ol", HTML.arrayToLI( links ) );
|
43
|
+
this.#siteGenerator.writeTemplate( html, { title: "Glossary" }, "glossary.html" );
|
44
|
+
}
|
37
45
|
|
38
|
-
|
39
|
-
|
46
|
+
getGlossary() {
|
47
|
+
return this.#glossary;
|
40
48
|
}
|
41
49
|
|
42
50
|
renderPages() {
|
43
|
-
|
44
|
-
Files.mkdir( this.#entryDir );
|
45
|
-
|
46
|
-
this.#generateIncludeFile();
|
51
|
+
this.#generateIndexPage();
|
47
52
|
this.#generateEntryPages();
|
48
53
|
}
|
49
54
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@ca-plant-list/ca-plant-list",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.3.1",
|
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": {
|
@@ -30,6 +30,7 @@
|
|
30
30
|
"image-size": "^1.0.2",
|
31
31
|
"markdown-it": "^13.0.1",
|
32
32
|
"sharp": "^0.32.1",
|
33
|
+
"svgo": "^3.0.3",
|
33
34
|
"unzipper": "^0.10.11"
|
34
35
|
},
|
35
36
|
"devDependencies": {
|
@@ -37,4 +38,4 @@
|
|
37
38
|
"eslint": "^8.26.0",
|
38
39
|
"typescript": "^4.9.3"
|
39
40
|
}
|
40
|
-
}
|
41
|
+
}
|
@@ -1,28 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
3
|
-
<svg width="82.437mm" height="84.504mm" version="1.1" viewBox="0 0 82.437 84.504" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
4
|
-
<defs>
|
5
|
-
<marker id="Triangle" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
|
6
|
-
<path transform="scale(.5)" d="m5.77 0-8.65 5v-10z" fill="context-stroke" fill-rule="evenodd" stroke="context-stroke" stroke-width="1pt"/>
|
7
|
-
</marker>
|
8
|
-
</defs>
|
9
|
-
<g transform="translate(-48.054 -6.5123)">
|
10
|
-
<g fill="#959595">
|
11
|
-
<path d="m79.276 37.945a8.4667 31.089 0 0 1 1.8353 33.88 8.4667 31.089 0 0 1-7.8222 19.191 8.4667 31.089 0 0 1-7.8222-19.191 8.4667 31.089 0 0 1 1.8353-33.88z"/>
|
12
|
-
<path d="m48.253 13.074 19.05 24.871" stroke="#888" stroke-width=".5"/>
|
13
|
-
<path id="path3" d="m98.326 13.074-19.05 24.871" fill="#959595" stroke="#888" stroke-width=".5"/>
|
14
|
-
</g>
|
15
|
-
<use transform="rotate(-17.226 77.257 49.068)" xlink:href="#path3"/>
|
16
|
-
<path d="m55.686 9.6812 13.798 28.126" fill="#959595" stroke="#888" stroke-width=".5"/>
|
17
|
-
<path d="m62.705 7.5473 8.2896 30.212" fill="#959595" stroke="#888" stroke-width=".5"/>
|
18
|
-
<use transform="rotate(-5.8666 77.05 56.397)" xlink:href="#path3"/>
|
19
|
-
<use transform="rotate(-27.32 76.391 49.027)" xlink:href="#path3"/>
|
20
|
-
<g>
|
21
|
-
<path d="m69.881 6.5376 3.171 31.167" fill="#959595" stroke="#888" stroke-width=".5"/>
|
22
|
-
<text x="114.47877" y="66.073151" fill="#050000" font-family="Arial" font-size="4.9389px" stroke="#020000" stroke-width="0" xml:space="preserve"><tspan x="114.47877" y="66.073151" fill="#050000" font-family="Arial" font-size="4.9389px" stroke="#020000" stroke-width="0">achene</tspan></text>
|
23
|
-
<text x="114.47877" y="28.502281" fill="#050000" font-family="Arial" font-size="4.9389px" stroke="#020000" stroke-width="0" xml:space="preserve"><tspan x="114.47877" y="28.502281" fill="#050000" font-family="Arial" font-size="4.9389px" stroke="#020000" stroke-width="0">pappus</tspan></text>
|
24
|
-
<path d="m88.996 65.009 20.886-0.12554" marker-start="url(#Triangle)" stroke="#000" stroke-width=".42043"/>
|
25
|
-
<path d="m90.584 27.967 20.886-0.12554" marker-start="url(#Triangle)" stroke="#000" stroke-width=".42043"/>
|
26
|
-
</g>
|
27
|
-
</g>
|
28
|
-
</svg>
|
@@ -1,11 +0,0 @@
|
|
1
|
-
<svg version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"
|
2
|
-
xmlns:xlink="http://www.w3.org/1999/xlink">
|
3
|
-
<ellipse id="a" cx="15" cy="15" rx="2.5" ry="15" fill="blue" stroke-width="0" />
|
4
|
-
<use xlink:href="#a" />
|
5
|
-
<use transform="rotate(30,15,15)" xlink:href="#a" />
|
6
|
-
<use transform="rotate(60,15,15)" xlink:href="#a" />
|
7
|
-
<use transform="rotate(90,15,15)" xlink:href="#a" />
|
8
|
-
<use transform="rotate(120,15,15)" xlink:href="#a" />
|
9
|
-
<use transform="rotate(150,15,15)" xlink:href="#a" />
|
10
|
-
</svg>
|
11
|
-
|
@@ -1,11 +0,0 @@
|
|
1
|
-
<svg version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"
|
2
|
-
xmlns:xlink="http://www.w3.org/1999/xlink">
|
3
|
-
<ellipse id="a" cx="15" cy="15" rx="2.5" ry="15" fill="orange" stroke-width="0" />
|
4
|
-
<use xlink:href="#a" />
|
5
|
-
<use transform="rotate(30,15,15)" xlink:href="#a" />
|
6
|
-
<use transform="rotate(60,15,15)" xlink:href="#a" />
|
7
|
-
<use transform="rotate(90,15,15)" xlink:href="#a" />
|
8
|
-
<use transform="rotate(120,15,15)" xlink:href="#a" />
|
9
|
-
<use transform="rotate(150,15,15)" xlink:href="#a" />
|
10
|
-
</svg>
|
11
|
-
|
@@ -1,11 +0,0 @@
|
|
1
|
-
<svg version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"
|
2
|
-
xmlns:xlink="http://www.w3.org/1999/xlink">
|
3
|
-
<ellipse id="a" cx="15" cy="15" rx="2.5" ry="15" fill="pink" stroke-width="0" />
|
4
|
-
<use xlink:href="#a" />
|
5
|
-
<use transform="rotate(30,15,15)" xlink:href="#a" />
|
6
|
-
<use transform="rotate(60,15,15)" xlink:href="#a" />
|
7
|
-
<use transform="rotate(90,15,15)" xlink:href="#a" />
|
8
|
-
<use transform="rotate(120,15,15)" xlink:href="#a" />
|
9
|
-
<use transform="rotate(150,15,15)" xlink:href="#a" />
|
10
|
-
</svg>
|
11
|
-
|
@@ -1,11 +0,0 @@
|
|
1
|
-
<svg version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"
|
2
|
-
xmlns:xlink="http://www.w3.org/1999/xlink">
|
3
|
-
<ellipse id="a" cx="15" cy="15" rx="2.5" ry="15" fill="red" stroke-width="0" />
|
4
|
-
<use xlink:href="#a" />
|
5
|
-
<use transform="rotate(30,15,15)" xlink:href="#a" />
|
6
|
-
<use transform="rotate(60,15,15)" xlink:href="#a" />
|
7
|
-
<use transform="rotate(90,15,15)" xlink:href="#a" />
|
8
|
-
<use transform="rotate(120,15,15)" xlink:href="#a" />
|
9
|
-
<use transform="rotate(150,15,15)" xlink:href="#a" />
|
10
|
-
</svg>
|
11
|
-
|
@@ -1,11 +0,0 @@
|
|
1
|
-
<svg version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"
|
2
|
-
xmlns:xlink="http://www.w3.org/1999/xlink">
|
3
|
-
<ellipse id="a" cx="15" cy="15" rx="2.5" ry="15" fill="white" stroke-width="0" />
|
4
|
-
<use xlink:href="#a" />
|
5
|
-
<use transform="rotate(30,15,15)" xlink:href="#a" />
|
6
|
-
<use transform="rotate(60,15,15)" xlink:href="#a" />
|
7
|
-
<use transform="rotate(90,15,15)" xlink:href="#a" />
|
8
|
-
<use transform="rotate(120,15,15)" xlink:href="#a" />
|
9
|
-
<use transform="rotate(150,15,15)" xlink:href="#a" />
|
10
|
-
</svg>
|
11
|
-
|
@@ -1,11 +0,0 @@
|
|
1
|
-
<svg version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"
|
2
|
-
xmlns:xlink="http://www.w3.org/1999/xlink">
|
3
|
-
<ellipse id="a" cx="15" cy="15" rx="2.5" ry="15" fill="yellow" stroke-width="0" />
|
4
|
-
<use xlink:href="#a" />
|
5
|
-
<use transform="rotate(30,15,15)" xlink:href="#a" />
|
6
|
-
<use transform="rotate(60,15,15)" xlink:href="#a" />
|
7
|
-
<use transform="rotate(90,15,15)" xlink:href="#a" />
|
8
|
-
<use transform="rotate(120,15,15)" xlink:href="#a" />
|
9
|
-
<use transform="rotate(150,15,15)" xlink:href="#a" />
|
10
|
-
</svg>
|
11
|
-
|
@@ -1,21 +0,0 @@
|
|
1
|
-
<svg version="1.1" viewBox="0 0 102.55 60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
2
|
-
<defs>
|
3
|
-
<marker id="b" overflow="visible" markerHeight="1" markerWidth="1" orient="auto-start-reverse" preserveAspectRatio="xMidYMid" viewBox="0 0 1 1">
|
4
|
-
<path transform="scale(.5)" d="m5.77 0-8.65 5v-10z" fill="context-stroke" fill-rule="evenodd" stroke="context-stroke" stroke-width="1pt"/>
|
5
|
-
</marker>
|
6
|
-
</defs>
|
7
|
-
<path d="m15 60v-45" fill="#14140c" stroke="#160707"/>
|
8
|
-
<use xlink:href="#a"/>
|
9
|
-
<use transform="rotate(30,15,15)" xlink:href="#a"/>
|
10
|
-
<use transform="rotate(60,15,15)" xlink:href="#a"/>
|
11
|
-
<use transform="rotate(90,15,15)" xlink:href="#a"/>
|
12
|
-
<use transform="rotate(120,15,15)" xlink:href="#a"/>
|
13
|
-
<use transform="rotate(150,15,15)" xlink:href="#a"/>
|
14
|
-
<ellipse id="a" cx="15" cy="15" rx="2.5" ry="15" fill="#ff0" stroke-width="0"/>
|
15
|
-
<g fill="#14140c" stroke="#160707">
|
16
|
-
<path d="m20 45h25" marker-start="url(#b)" stroke-width=".5"/>
|
17
|
-
<text x="50" y="47.068359" font-family="Arial" font-size="8px" letter-spacing=".5px" opacity=".55843" stroke-width=".1" xml:space="preserve"><tspan x="50" y="47.068359" font-family="Arial" font-size="8px" letter-spacing=".5px" stroke-width=".1" style="font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal">peduncle</tspan></text>
|
18
|
-
<path d="m35 15h10" marker-start="url(#b)" stroke-width=".5"/>
|
19
|
-
<text x="49.696735" y="17.068359" font-family="Arial" font-size="8px" letter-spacing=".5px" opacity=".55843" stroke-width=".1" xml:space="preserve"><tspan x="49.696735" y="17.068359" font-family="Arial" font-size="8px" letter-spacing=".5px" stroke-width=".1" style="font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal">inflorescence</tspan></text>
|
20
|
-
</g>
|
21
|
-
</svg>
|