├── .dockerignore ├── .github └── workflows │ ├── deploy.yml │ └── test-deploy.yml ├── .gitignore ├── CNAME ├── README.md ├── babel.config.js ├── blog └── 2020-07-15-1-6-0.md ├── docs ├── advanced │ ├── client-side-apps.md │ ├── complete-data.md │ ├── distributions.md │ └── plants-fields.md ├── examples │ └── snippets.md └── guides │ ├── filtering.md │ ├── getting-started.md │ ├── pagination.md │ ├── reporting-errors.md │ ├── searching.md │ └── sorting.md ├── docusaurus.config.js ├── jargon.js ├── package.json ├── plugins └── plugin-token-fetcher │ ├── package.json │ └── src │ ├── fetcher.js │ └── index.js ├── sidebars.js ├── src ├── css │ ├── custom.css │ └── fonts.css ├── pages │ ├── index.js │ ├── reference.js │ └── styles.module.css └── theme │ ├── Footer │ ├── index.js │ └── styles.module.css │ └── MultiLanguageSnippet │ └── index.js ├── static ├── .nojekyll ├── CNAME ├── img │ ├── client-scheme.png │ ├── distributions-world.png │ ├── favicon.ico │ ├── logo.png │ └── logo.svg └── swagger.yaml └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | */node_modules 2 | *.log 3 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | # Review gh actions docs if you want to further define triggers, paths, etc 9 | # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on 10 | 11 | jobs: 12 | deploy: 13 | name: Deploy to GitHub Pages 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | - uses: actions/setup-node@v3 18 | with: 19 | node-version: 18 20 | cache: yarn 21 | 22 | - name: Install dependencies 23 | run: yarn install --frozen-lockfile 24 | - name: Build website 25 | run: yarn build 26 | 27 | # Popular action to deploy to GitHub Pages: 28 | # Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus 29 | - name: Deploy to GitHub Pages 30 | uses: peaceiris/actions-gh-pages@v3 31 | with: 32 | github_token: ${{ secrets.GITHUB_TOKEN }} 33 | # Build output to publish to the `gh-pages` branch: 34 | publish_dir: ./build 35 | # The following lines assign commit authorship to the official 36 | # GH-Actions bot for deploys to `gh-pages` branch: 37 | # https://github.com/actions/checkout/issues/13#issuecomment-724415212 38 | # The GH actions bot is used by default if you didn't specify the two fields. 39 | # You can swap them out with your own user credentials. 40 | user_name: github-actions[bot] 41 | user_email: 41898282+github-actions[bot]@users.noreply.github.com 42 | 43 | -------------------------------------------------------------------------------- /.github/workflows/test-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Test deployment 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - master 8 | # Review gh actions docs if you want to further define triggers, paths, etc 9 | # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on 10 | 11 | jobs: 12 | test-deploy: 13 | name: Test deployment 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | - uses: actions/setup-node@v3 18 | with: 19 | node-version: 18 20 | cache: yarn 21 | 22 | - name: Install dependencies 23 | run: yarn install --frozen-lockfile 24 | - name: Test build website 25 | run: yarn build 26 | 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | docs.trefle.io -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Trefle Documentation 2 | 3 | [🌎 Website](https://trefle.io) • [🚀 Getting started](https://docs.trefle.io) • [📖 API Documentation](https://docs.trefle.io/reference) • [💡 Ideas and features](https://github.com/orgs/treflehq/projects/3) • [🐛 Issues](https://github.com/orgs/treflehq/projects/2) 4 | 5 | [![View performance data on Skylight](https://badges.skylight.io/status/nz7MAOv6K6ra.svg)](https://oss.skylight.io/app/applications/nz7MAOv6K6ra) [![View performance data on Skylight](https://badges.skylight.io/rpm/nz7MAOv6K6ra.svg)](https://oss.skylight.io/app/applications/nz7MAOv6K6ra) [![View performance data on Skylight](https://badges.skylight.io/problem/nz7MAOv6K6ra.svg)](https://oss.skylight.io/app/applications/nz7MAOv6K6ra) [![View performance data on Skylight](https://badges.skylight.io/typical/nz7MAOv6K6ra.svg)](https://oss.skylight.io/app/applications/nz7MAOv6K6ra) 6 | 7 | This is the repository for the [Trefle documentation](https://docs.trefle.io). It's built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 8 | 9 | ### Installation 10 | 11 | ``` 12 | $ yarn 13 | ``` 14 | 15 | ### Local Development 16 | 17 | ``` 18 | $ yarn start 19 | ``` 20 | 21 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 22 | 23 | ### Build 24 | 25 | ``` 26 | $ yarn build 27 | ``` 28 | 29 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 30 | 31 | ### Deployment 32 | 33 | Deployment is automated by pushing on `master` branch. 34 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /blog/2020-07-15-1-6-0.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: 1-6-0-released 3 | title: "1.6.0" 4 | author: André Aubin 5 | author_title: Trefle Core Team 6 | author_url: https://twitter.com/lambda_2 7 | author_image_url: https://pbs.twimg.com/profile_images/1247213607353540608/i9oN_Gbg_400x400.jpg 8 | tags: [releases] 9 | --- 10 | 11 | This major release of Trefle brings a lot of new exciting features, such as distributions, farming fields and blazing fast search. 12 | 13 | 14 | 15 | ## What changed ? 16 | 17 | ### 📦 Endpoints versioning 18 | 19 | In order to avoid making breaking changes like this one in the future, API routes are now versionned. So the endpoint `/api/species` is now `/api/v1/species`. This let you the possibility to update when you're ready for the next releases. 20 | 21 | ### 📄 The data scructure changes 22 | 23 | One of the biggest struggles we noticed was the pagination. Parsing the pagination links in the response headers was really painful, even if it's a stardard. 24 | 25 | To solve this, **we decided to include pagination links directly in the JSON response**. 26 | 27 | Now, all API calls wraps a `data` field, along with a `links` field, for pagination links, and optionally a `meta` fields, for high level informations such as counts. 28 | 29 | ### 🔧 Plant and species fields names changes 30 | 31 | **We removed and added a lot of fields**. Most of USDA fields, such as `propagation` or products uses were removed, as they were too inaccurates. 32 | 33 | You can get: 34 | 35 | - [A simplified list of the current fields in the documentation](/docs/advanced/plants-fields). 36 | - [The full list in the reference](/reference/#operation/getSpecies). 37 | 38 | 39 | ### ✂️ The filters and sort parameter changes 40 | 41 | In order to avoid any name collision in parameters, **filters are now scoped in the `filter` parameter**. This means that `common_name=mint` is now `filter[common_name]=mint`. 42 | 43 | You now also can exclude null values from results with the `filter_not[ATTRIBUTE]` parameter. 44 | 45 | You can [read more about filters in the documentation](/docs/guides/filtering) or see the [The full list of filters in the reference](/reference/#operation/listSpecies). 46 | 47 | ### 📐 Ranges and orders 48 | 49 | You can now query the range of values between two values with the `range[FIELD]=min,max` parameter. 50 | 51 | For example, to query only species with a minimum height **between** 5 **and** 20 centimeters: `api/v1/species?token=YOUR_TREFLE_TOKEN&range[maximum_height_cm]=5,20`. 52 | 53 | Filtering on ranges also allow to set only minimum or maximum values. For example: 54 | 55 | - `/api/v1/species?range[maximum_height_cm]=5` only return species higher than 5 cm 56 | - `/api/v1/species?range[maximum_height_cm]=,5` only return species lower than 5 cm 57 | 58 | You can [read more about ranges in the documentation](/docs/guides/filtering#filter-on-ranges) or see the [The full list of ranges in the reference](/reference/#operation/listSpecies). 59 | 60 | 61 | ### 🖼 Better plants/species images 62 | 63 | Images were fully reviewed, and are now **splitted into categories**: flower, leaf, habit, fruit, bark and other. 64 | 65 | ### 🌍 Species distributions 66 | 67 | **We began to collect plant locations (ex: France) and establishments (ex: Native) per zone**, and they're now included in the `/species/{species_slug}` and `/plants/{species_slug}` endpoints. 68 | 69 | You can also filter species by distribution zones or by establishment. 70 | 71 | For example, to get plants native from Tibet: `/api/v1/distributions/tibet/plants?filter[establishment]=native`. 72 | 73 | ### 🔍 Blazing fast search engine 74 | 75 | A new search endpoint for plants and species is available: `/api/v1/species/search?q=term`. 76 | 77 | **This search was designed to respond in milliseconds**, and is ready for input autocomplete or "as you type" queries. [You can see it in action on the landing page](https://trefle.io). 78 | 79 | ### 🧰 Error reporting and data collection 80 | 81 | **You can now [report errors on species](/docs/guides/reporting-errors), or even [submit corrections / changes](/docs/advanced/complete-data) to us, directly from an API call.** 82 | 83 | This means a lot to us, as we want our data to be everyone's, and believe strongly in the power of the community. 84 | 85 | ### 📕 Adoption of better standards 86 | 87 | All units are following the [International System of Units (SI)](https://en.wikipedia.org/wiki/Metric_system), so **we replaced feets by centimeters, inches by millimeters and so on**. 88 | Temperatures are in celcuis and kelvin degrees for now, as the conversion is more complex than for standard units. 89 | 90 | Scientific names now follows the [Binomial nomenclature](https://en.wikipedia.org/wiki/Binomial_nomenclature). For the species, it represents its genus and its species within the genus, resulting in a single worldwide name for each organism. The scientific name of an infraspecific taxons (ranks below species, such as subspecies, forms, varieties...) is a combination of the name of a species and an infraspecific epithet. A connecting term is used to denote the rank. [See IAPT recommendation](https://www.iapt-taxon.org/nomen/pages/main/art_24.html). 91 | 92 | Distribution zones for plants/species are following the [World Geographical Scheme for Recording Plant Distributions (WGSRPD)](https://www.tdwg.org/standards/wgsrpd/). 93 | 94 | ### 📦 JSON responses when listing plants and species are more complete 95 | 96 | We added some fields in the response, such as an image url or the genus and family names, and embedded synonyms. 97 | 98 | For example, when listing plants: 99 | 100 | ```javascript 101 | [ 102 | { 103 | "id": 123486, 104 | "slug": "corylus-avellana" 105 | "scientific_name": "Corylus avellana", 106 | "common_name": "common filbert", 107 | "complete_data": false, 108 | "link": "http://trefle.io/api/plants/123486", 109 | } 110 | ] 111 | ``` 112 | 113 | Is now 114 | 115 | ```javascript 116 | { 117 | "data": [ 118 | { 119 | "id": 123486, 120 | "slug": "corylus-avellana", 121 | "scientific_name": "Corylus avellana", 122 | "common_name": "common filbert", 123 | "author": "L.", 124 | "bibliography": "Sp. Pl.: 998 (1753)", 125 | "family": "Betulaceae", 126 | "family_common_name": "Birch family", 127 | "genus": "Corylus", 128 | "genus_id": 2057, 129 | "image_url": "https://bs.floristic.org/image/o/0d92cadb0d66dce1b0a8b26913125d6501e31d68", 130 | "rank": "species", 131 | "status": "accepted", 132 | "synonyms": [ 133 | "Corylus sylvestris" 134 | ], 135 | "year": 1753, 136 | "links": { 137 | "genus": "/api/v1/genus/corylus", 138 | "plant": "/api/v1/plants/corylus-avellana", 139 | "self": "/api/v1/species/corylus-avellana" 140 | } 141 | } 142 | ], 143 | "links": { 144 | "first": "/api/v1/plants?filter%5Bscientific_name%5D=Corylus+avellana&page=1", 145 | "last": "/api/v1/plants?filter%5Bscientific_name%5D=Corylus+avellana&page=1", 146 | "self": "/api/v1/plants?filter%5Bscientific_name%5D=Corylus+avellana" 147 | }, 148 | "meta": { 149 | "total": 1 150 | } 151 | } 152 | ``` 153 | 154 | ### 📋 Synonyms separation 155 | 156 | Synonyms are no longer returned in the species or plants response, and are now included as an array in the response. 157 | 158 | ### 📐 Species fields scales changes 159 | 160 | "Scale-like" fields, such as "light" or "soil adaptation" are no longer with values like 'Low', 'Medium' and 'High', but are now on a scale from 0 to 10. 161 | 162 | ### 📋 Common names split 163 | 164 | Common names have been reviewed, and are now grouped by language. 165 | -------------------------------------------------------------------------------- /docs/advanced/client-side-apps.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: client-side-apps 3 | title: Client-side applications 4 | image: /img/client-scheme.png 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | 10 | The access token you get from [your account page](https://trefle.io/profile) allow you to makes queries on the Trefle API, but your token needs to be kept secret, so **you can't make queries from the browser as the user on your website will see the access token**, and could use it for their personal needs. Additionally this is not a good practice in developing software. 11 | 12 | ![client workflow](/img/client-scheme.png) 13 | 14 | If you need to perform client-side requests you will have to request a client-side token from your own backend and get a JWT token in return. This token will be usable on the client side. This call needs your secret access token and the url of the website that the client side requests will come from. 15 | 16 | :::info 17 | Because this is a **POST** request it can't be done directly from the browser. 18 | ::: 19 | 20 | 21 | 29 | 30 | 31 | 32 | In your terminal: 33 | 34 | ```bash 35 | curl -X POST 'https://trefle.io/api/auth/claim?token=YOUR_TREFLE_TOKEN&origin=YOUR-WEBSITE-URL&ip=12.34.56.78"' 36 | ``` 37 | 38 | 39 | 40 | 41 | ```js 42 | const fetch = require('node-fetch'); 43 | 44 | // The parameters for our POST request 45 | const params = { 46 | origin: 'YOUR-WEBSITE-URL', 47 | ip: 'THE-WEBSITE-USER-IP', 48 | token: 'YOUR_TREFLE_TOKEN' 49 | } 50 | 51 | (async () => { 52 | const response = await fetch( 53 | 'https://trefle.io/api/auth/claim', { 54 | method: 'post', 55 | body: JSON.stringify(params), 56 | headers: { 'Content-Type': 'application/json' } 57 | }); 58 | const json = await response.json(); 59 | console.log(json); 60 | })(); 61 | ``` 62 | 63 | 64 | 65 | 66 | 67 | And we get: 68 | 69 | ```json 70 | { 71 | "token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMDYsIm9yaWdpbiI6IllPVVItV0VCU0lURS1VUkwiLCJpcCI6IlRIRS1XRUJTSVRFLVVTRVItSVAiLCJleHAiOjE1OTQ2NDIxNDh9.Vd2d3UK7zdNWZLBOn8y50NcUKuF8xFZgh6p7EB4fhVw", 72 | "expiration": "07-13-2020 14:09" 73 | } 74 | ``` 75 | 76 | You can then use this token directly from the browser. It can't be used from another origin, will expire and only works for your website. 77 | 78 | :::tip About the user IP 79 | Putting the user remote IP in the claim API call is optional, but it provides an additional security layer. We don't keep or store this information. 80 | ::: 81 | -------------------------------------------------------------------------------- /docs/advanced/complete-data.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: complete-data 3 | title: Complete our data 4 | --- 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | **If you notice missing informations on a species, you can help us by sending a correction.** 9 | 10 | In the correction, you'll send: 11 | 12 | - The record to correct (ex: Species `abies-alba`) 13 | - The field(s) to change, with their new values (ex: `minimum_ph`, `edible_part`, `author` etc...). Most of the fields can be corrected. 14 | - A trustable source for the changes (a field observation, a wikipedia page, a publication etc...) 15 | 16 | Once your correction is submitted, it will be validated by a peer, and then applied to the database. 17 | 18 | :::tip Report an error 19 | You can also simply report an error in the data, without correcting it. [Read more in this guide](/docs/guides/reporting-errors) 20 | ::: 21 | 22 | ### Things to know 23 | 24 | - Almost all the fields can be corrected, but relations such as `distributions` or `synonyms` can't be corrected yet. 25 | - The full list of available fields are [in the reference](/reference/#operation/createCorrection). 26 | - Several values can be separated with `|`. Ex: `{"bloom_months": "jan|feb|mar|apr"}` 27 | 28 | 29 | ### Submitting a correction 30 | 31 | Submitting a correction is done by doing a `POST` request on the `/api/v1/corrections/species/{species_id}` endpoint. [See in the reference](/reference/#operation/createCorrection). 32 | 33 | Let's say we want to correct the maximum height of the `Abies Alba` species, because we found out that the largest measured tree was 68 m tall. 34 | 35 | The payload we will send will be like: 36 | 37 | ```json 38 | { 39 | "notes": "This tree can grows up to 68 meters", 40 | "source_type": "external", 41 | "source_reference": "https://conifersociety.org/conifers/abies-alba/", 42 | "correction": { 43 | "maximum_height_value": 6800, 44 | "maximum_height_unit": "cm" 45 | } 46 | } 47 | ``` 48 | 49 | 50 | 51 | 59 | 60 | 61 | 62 | In your terminal: 63 | 64 | ```bash 65 | curl -XPOST -H "Content-type: application/json" \ 66 | -d '{"notes":"This tree can grows up to 68 meters","source_type":"external","source_reference":"https://conifersociety.org/conifers/abies-alba/","correction":{"maximum_height_value":6800,"maximum_height_unit":"cm"}}' \ 67 | 'https://trefle.io/api/v1/corrections/species/abies-alba?token=YOUR_TREFLE_TOKEN' 68 | ``` 69 | 70 | 71 | 72 | 73 | ```js 74 | const fetch = require('node-fetch'); 75 | 76 | // The parameters for our POST request 77 | const params = { 78 | notes: 'This tree can grows up to 68 meters', 79 | source_type: "external", 80 | source_reference: 'https://conifersociety.org/conifers/abies-alba/', 81 | correction: { 82 | maximum_height_value: 6800, 83 | maximum_height_unit: 'cm' 84 | } 85 | } 86 | 87 | (async () => { 88 | const response = await fetch( 89 | 'https://trefle.io/api/v1/corrections/species/abies-alba?token=YOUR_TREFLE_TOKEN', { 90 | method: 'post', 91 | body: JSON.stringify(params), 92 | headers: { 'Content-Type': 'application/json' } 93 | }); 94 | const json = await response.json(); 95 | console.log(json); 96 | })(); 97 | ``` 98 | 99 | 100 | 101 | 102 | 103 | And we got: 104 | 105 | ```json 106 | { 107 | "data": { 108 | "id": 8, 109 | "record_type": "Species", 110 | "record_id": 1164724, 111 | "user_id": 106, 112 | "warning_type": null, 113 | "change_status": "pending", 114 | "change_type": "update", 115 | "accepted_by": null, 116 | "notes": "This tree can grows up to 68 meters", 117 | "created_at": "2020-07-13T12:56:09.156Z", 118 | "updated_at": "2020-07-13T12:56:09.156Z", 119 | "correction": { 120 | "maximum_height_value": 6800, 121 | "maximum_height_unit": "cm", 122 | "scientific_name": "Abies alba" 123 | }, 124 | "changes": { 125 | "maximum_height_cm": [ 126 | 5000, 127 | 6800 128 | ] 129 | } 130 | }, 131 | "meta": { 132 | "last_modified": "2020-07-13T12:56:09.156Z" 133 | } 134 | } 135 | ``` 136 | 137 | This means that your submission has been created, and is pending validation. 138 | 139 | ### Testing 140 | 141 | If you want to test a correction on a species, set the `notes` field to `TEST`. They will be not reviewed, and automatically rejected after some time. 142 | 143 | For example: 144 | 145 | 146 | ```bash 147 | # This correction will not be reviewed, and rejected after some time 148 | curl -XPOST -H "Content-type: application/json" \ 149 | -d '{"notes":"TEST","source_type":"external","source_reference":"https://conifersociety.org/conifers/abies-alba/","correction":{"maximum_height_value":6800,"maximum_height_unit":"cm"}}' \ 150 | 'https://trefle.io/api/v1/corrections/species/abies-alba?token=YOUR_TREFLE_TOKEN' 151 | ``` 152 | 153 | ### Available fields 154 | 155 | 156 | | field | description | 157 | |-----------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 158 | | **scientific_name** (string) | | 159 | | **rank** (string) | Can be: `species`, `ssp`, `var`, `form`, `hybrid`, and `subvar`. | 160 | | **genus** (string) | | 161 | | **year** (integer) | | 162 | | **author** (string) | | 163 | | **bibliography** (string) | | 164 | | **common_name** (string) | The species common name(s) in english. Several values can be separated with "\|" | 165 | | **observations** (string) | | 166 | | **planting_description** (string) | A description on how the plant usually grows | 167 | | **planting_sowing_description** (string) | | 168 | | **duration** (string) | The duration(s) of the species. Several values can be separated with "\|"
Can be: `annual`, `biennial`, and `perennial`. | 169 | | **flower_color** (string) | The species flower color(s). Several values can be separated with "\|"
Can be: `white`, `red`, `brown`, `orange`, `yellow`, `lime`, `green`, `cyan`, `blue`, `purple`, `magenta`, `grey`, and `black`. | 170 | | **flower_conspicuous** (boolean) | | 171 | | **foliage_color** (string) | The species foliage color(s). Several values can be separated with "\|"
Can be: `white`, `red`, `brown`, `orange`, `yellow`, `lime`, `green`, `cyan`, `blue`, `purple`, `magenta`, `grey`, and `black`. | 172 | | **foliage_texture** (string) | Can be: `fine`, `medium`, and `coarse`. | 173 | | **leaf_retention** (boolean) | | 174 | | **fruit_color** (string) | The species fruit color(s). Several values can be separated with "\|"
Can be: `white`, `red`, `brown`, `orange`, `yellow`, `lime`, `green`, `cyan`, `blue`, `purple`, `magenta`, `grey`, and `black`. | 175 | | **fruit_conspicuous** (boolean) | | 176 | | **fruit_seed_persistence** (boolean) | | 177 | | **fruit_months** (string) | The months when his species have fruits. Several values can be separated by "\|"
Can be: `jan`, `feb`, `mar`, `apr`, `may`, `jun`, `jul`, `aug`, `sep`, `oct`, `nov`, and `dec`. | 178 | | **bloom_months** (string) | The months when this species blooms. Several values can be separated by "\|"
Can be: `jan`, `feb`, `mar`, `apr`, `may`, `jun`, `jul`, `aug`, `sep`, `oct`, `nov`, and `dec`. | 179 | | **ground_humidity** (integer) | Required humidity of the soil, on a scale from 0 (xerophile) to 10 (subaquatic) | 180 | | **growth_form** (string) | | 181 | | **growth_habit** (string) | | 182 | | **growth_months** (string) | The months when this species grows. Several values can be separated by "\|"
Can be: `jan`, `feb`, `mar`, `apr`, `may`, `jun`, `jul`, `aug`, `sep`, `oct`, `nov`, and `dec`. | 183 | | **growth_rate** (string) | | 184 | | **edible_part** (string) | The edible part of the species (if any). Several values can be separated by "\|"
Can be: `roots`, `stem`, `leaves`, `flowers`, `fruits`, and `seeds`. | 185 | | **vegetable** (boolean) | | 186 | | **light** (integer) | Required amount of light, on a scale from 0 (no light, <= 10 lux) to 10 (very intensive insolation, >= 100 000 lux) | 187 | | **atmospheric_humidity** (integer) | Required relative humidity in the air, on a scale from 0 (<=10%) to 10 (>= 90%) | 188 | | **adapted_to_coarse_textured_soils** (string) | | 189 | | **adapted_to_fine_textured_soils** (string) | | 190 | | **adapted_to_medium_textured_soils** (string) | | 191 | | **anaerobic_tolerance** (string) | | 192 | | **average_height_unit** (string) | Can be: `in`, `ft`, `cm`, and `m`. | 193 | | **average_height_value** (number) | | 194 | | **maximum_height_unit** (string) | Can be: `in`, `ft`, `cm`, and `m`. | 195 | | **maximum_height_value** (number) | | 196 | | **planting_row_spacing_unit** (string) | Can be: `in`, `ft`, `cm`, and `m`. | 197 | | **planting_row_spacing_value** (number) | The minimum spacing between each rows of plants | 198 | | **planting_spread_unit** (string) | Can be: `in`, `ft`, `cm`, and `m`. | 199 | | **planting_spread_value** (number) | The average spreading of the plant | 200 | | **planting_days_to_harvest** (integer) | | 201 | | **maximum_precipitation_unit** (string) | Can be: `in`, `ft`, `mm`, `cm`, and `m`. | 202 | | **maximum_precipitation_value** (number) | | 203 | | **minimum_precipitation_unit** (string) | Can be: `in`, `ft`, `mm`, `cm`, and `m`. | 204 | | **minimum_precipitation_value** (number) | | 205 | | **minimum_root_depth_unit** (string) | Can be: `in`, `ft`, `cm`, and `m`. | 206 | | **minimum_root_depth_value** (number) | | 207 | | **ph_maximum** (number) | | 208 | | **ph_minimum** (number) | | 209 | | **soil_nutriments** (integer) | Required quantity of nutriments in the soil, on a scale from 0 (oligotrophic) to 10 (hypereutrophic) | 210 | | **soil_salinity** (integer) | Tolerance to salinity, on a scale from 0 (untolerant) to 10 (hyperhaline) | 211 | | **minimum_temperature_deg_c** (number) | The minimum required temperature in celcius degrees | 212 | | **maximum_temperature_deg_c** (number) | The maximum required temperature in celcius degrees | 213 | | **soil_texture** (string) | Required texture of the soil, on a scale from 0 (clay) to 10 (rock)
Can be: `argile`, `intermediaire`, `limon`, `sable_fin`, `sable_grossier`, `graviers`, `galets`, `blocs_fentes_des_parois`, and `dalle`. | 214 | | **ligneous_type** (string) | Can be: `liana`, `subshrub`, `shrub`, `tree`, and `parasite`. | 215 | | **toxicity** (string) | Can be: `none`, `low`, `medium`, and `high`. | 216 | -------------------------------------------------------------------------------- /docs/advanced/distributions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: distributions 3 | title: Distributions 4 | image: /img/distributions-world.png 5 | --- 6 | 7 | ### Specification 8 | 9 | In Trefle, the distribution zones for _plants_ are following the [World Geographical Scheme for Recording Plant Distributions (WGSRPD)](https://www.tdwg.org/standards/wgsrpd/). 10 | 11 | WGSRPD provides an agreed system of geographical units at approximately "country" level and upwards for use in recording plant distributions. 12 | 13 | **The system offered covers the whole world and identifies units at four levels**, firstly continental, secondly regional (or subcontinental), thirdly at what may be called "Botanical Country" level (which may often ignore purely political considerations), and fourthly at a slightly lower level called "Basic Recording Units" where political integrity is fully recognised. 14 | 15 | In many cases, where Botanical Countries have no complicating political factors, the units at Level-3 and Level-4 are identical. Very large countries, however, have been subdivided into more conveniently sized units according to constituent states or provinces. It is a fundamental principle that units at all levels are bounded either by political boundaries which appear on modern maps or by coast lines. 16 | 17 | ### List of zones 18 | 19 | ![List of zones](/img/distributions-world.png) 20 | 21 | A complete list of zones is [available on Wikipedia](https://en.wikipedia.org/wiki/List_of_codes_used_in_the_World_Geographical_Scheme_for_Recording_Plant_Distributions) 22 | 23 | ### Mapping zones to a map 24 | 25 | Trefle does not provides coordinates for the species distribution zones yet. In the meantime, you can find GeoJSON files for each zones [on the TDWG Github repository](https://github.com/tdwg/wgsrpd/tree/master/geojson). 26 | -------------------------------------------------------------------------------- /docs/advanced/plants-fields.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: plants-fields 3 | title: Plants fields 4 | --- 5 | 6 | When you query a species (or a plant), you will have a lot of fields to dig into. This is a simplified version of the [reference](/reference) that tries to explain a bit what each fields represents. 7 | 8 | :::tip In doubt, refer to the reference 9 | This documentation is way lighter than the reference, and do not show all the fields. If you have any doubt, please check the [reference](/reference). 10 | ::: 11 | 12 | 13 | ## Species 14 | 15 | | field | description | 16 | |------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 17 | | **id** (integer) | An unique identifier | 18 | | **common_name** (string) | The usual common name, in english, of the species (if any). | 19 | | **slug** (string) | An unique human-readable identifier (if you can, prefer to use this over id) | 20 | | **scientific_name** (string) | The scientific name follows the [Binomial nomenclature](https://en.wikipedia.org/wiki/Binomial_nomenclature), and represents its genus and its species within the genus, resulting in a single worldwide name for each organism. The scientific name of an infraspecific taxons (ranks below species, such as subspecies, forms, varieties...) is a combination of the name of a species and an infraspecific epithet. A connecting term is used to denote the rank. [See IAPT recommendation](https://www.iapt-taxon.org/nomen/pages/main/art_24.html) | 21 | | **year** (integer) | The first publication year of a valid name of this species. [See author citation](https://en.wikipedia.org/wiki/Author_citation_(botany)) | 22 | | **bibliography** (string) | The first publication of a valid name of this species. [See author citation](https://en.wikipedia.org/wiki/Author_citation_(botany)) | 23 | | **author** (string) | The author(s) of the first publication of a valid name of this species. [See author citation](https://en.wikipedia.org/wiki/Author_citation_(botany)) | 24 | | **status** (string) | The acceptance status of this species by IPNI
Can be: `accepted` and `unknown`. | 25 | | **rank** (string) | The [taxonomic rank](https://en.wikipedia.org/wiki/Taxonomic_rank) of the species
Can be: `species`, `ssp`, `var`, `form`, `hybrid`, and `subvar`. | 26 | | **family_common_name** (string) | The common name (in english) of the species family | 27 | | **family** (string) | The scientific name of the species family | 28 | | **genus_id** (integer) | The id of the species genus | 29 | | **genus** (string) | The scientific name of the species genus | 30 | | **image_url** (string) | A main image url of the species | 31 | | **duration** (array of strings) | The plant duration(s), which can be:
- Annual: plants that live, reproduce, and die in one growing season.
- Biennial: plants that need two growing seasons to complete their life cycle, normally completing vegetative growth the first year and flowering the second year.
- Perennial: plants that live for more than two years, with the shoot system dying back to soil level each year.
| 32 | | **edible_part** (array of strings) | The plant edible part(s), if any. | 33 | | **edible** (boolean) | Is the species edible? | 34 | | **vegetable** (boolean) | Is the species a vegetable? | 35 | | **observations** (string) | Some habit observations on the species | 36 | | **common_names** (object) | Common names of the species per language | 37 | | **distribution** (object) | (Deprecated) Distribution of the species per establishment | 38 | | **synonyms** (array of objects) | The symonyms scientific names and authors | 39 | | **sources** (array of objects) | The symonyms scientific names and authors | 40 | | **extras** () | | 41 | 42 | ### links 43 | 44 | 45 | API endpoints to related resources 46 | 47 | | field | description | 48 | |--------------------|------------------------------------| 49 | | **self** (string) | API endpoint to the species itself | 50 | | **genus** (string) | API endpoint to the species genus | 51 | | **plant** (string) | API endpoint to the species plant | 52 | 53 | ### images 54 | 55 | | field | description | 56 | |-------------------------------|--------------------------------| 57 | | **flower** (array of objects) | Image(s) of the species flower | 58 | | **leaf** (array of objects) | Image(s) of the species leaf | 59 | | **habit** (array of objects) | Image(s) of the species habit | 60 | | **fruit** (array of objects) | Image(s) of the species fruit | 61 | | **bark** (array of objects) | Image(s) of the species bark | 62 | | **other** (array of objects) | Image(s) of the species other | 63 | 64 | ### distributions 65 | 66 | 67 | Distribution of the species per establishment 68 | 69 | | field | description | 70 | |-----------------------------------|-----------------------------------------------------------| 71 | | **native** (array of objects) | Zones the species is native from | 72 | | **introduced** (array of objects) | Zones the species has been introduced | 73 | | **doubtful** (array of objects) | Zones the species presence is doubtful | 74 | | **absent** (array of objects) | Zones the species is absent and has been wrongly recorded | 75 | | **extinct** (array of objects) | Zones the species is extinct | 76 | 77 | ### flower 78 | 79 | 80 | Flower related fields (the reproductive structure found in flowering plants) 81 | 82 | | field | description | 83 | |------------------------------|------------------------| 84 | | **color** (array of strings) | The flower color(s) | 85 | | **conspicuous** (boolean) | Is the flower visible? | 86 | 87 | ### foliage 88 | 89 | 90 | Foliage (or leaves) related fields 91 | 92 | | field | description | 93 | |------------------------------|-----------------------------------------------------------------------------------------| 94 | | **texture** (string) | The general texture of the plant’s foliage
Can be: `fine`, `medium`, and `coarse`. | 95 | | **color** (array of strings) | The leaves color(s) | 96 | | **leaf_retention** (boolean) | Does the leaves stay all year long? | 97 | 98 | ### fruit_or_seed 99 | 100 | 101 | Fruit or seed related fields 102 | 103 | | field | description | 104 | |--------------------------------|------------------------------------------------------------------------------| 105 | | **conspicuous** (boolean) | Is the fruit visible? | 106 | | **color** (array of strings) | The fruit color(s) | 107 | | **shape** (string) | Fruit shape | 108 | | **seed_persistence** (boolean) | Are the fruit or seed generally recognized as being persistent on the plant? | 109 | 110 | ### specifications 111 | 112 | 113 | Species's main characteristics 114 | 115 | | field | description | 116 | |------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 117 | | **ligneous_type** (string) | The ligneous type of the woody plant
Can be: `liana`, `subshrub`, `shrub`, `tree`, and `parasite`. | 118 | | **growth_form** (string) | The primary growth form on the landscape in relation to soil stabilization on slopes and streamsides? Each plant species is assigned the single growth form that most enhances its ability to stabilize soil | 119 | | **growth_habit** (string) | The general appearance, growth form, or architecture of the plant | 120 | | **growth_rate** (string) | The relative growth speed of the plant | 121 | | **average_height** (object) | The average height of the species, in centimeters | 122 | | **maximum_height** (object) | The maximum height of the species, in centimeters | 123 | | **nitrogen_fixation** (string) | Capability to fix nitrogen in monoculture | 124 | | **shape_and_orientation** (string) | The predominant shape of the species | 125 | | **toxicity** (string) | Relative toxicity of the species for humans or animals
Can be: `none`, `low`, `medium`, and `high`. | 126 | 127 | ### growth 128 | 129 | 130 | Growing of farming related fields 131 | 132 | | field | description | 133 | |--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------| 134 | | **days_to_harvest** (number) | The average numbers of days required to from planting to harvest | 135 | | **description** (string) | A description on how the plant usually grows | 136 | | **sowing** (string) | A description on how to sow the plant | 137 | | **ph_maximum** (number) | The maximum acceptable soil pH (of the top 30 centimeters of soil) for the plant | 138 | | **ph_minimum** (number) | The minimum acceptable soil pH (of the top 30 centimeters of soil) for the plant | 139 | | **light** (integer) | Required amount of light, on a scale from 0 (no light, <= 10 lux) to 10 (very intensive insolation, >= 100 000 lux) | 140 | | **atmospheric_humidity** (integer) | Required relative humidity in the air, on a scale from 0 (<=10%) to 10 (>= 90%) | 141 | | **growth_months** (array of strings) | The most active growth months of the species (usually all year round for perennial plants) | 142 | | **bloom_months** (array of strings) | The months the species usually blooms | 143 | | **fruit_months** (array of strings) | The months the species usually produces fruits | 144 | | **row_spacing** (object) | The minimum spacing between each rows of plants, in centimeters | 145 | | **spread** (object) | The average spreading of the plant, in centimeters | 146 | | **minimum_precipitation** (object) | Minimum precipitation per year, in milimeters per year | 147 | | **maximum_precipitation** (object) | Maximum precipitation per year, in milimeters per year | 148 | | **minimum_root_depth** (object) | Minimum depth of soil required for the species, in centimeters. Plants that do not have roots such as rootless aquatic plants have 0 | 149 | | **minimum_temperature** (object) | The minimum tolerable temperature for the species. In celsius or fahrenheit degrees | 150 | | **maximum_temperature** (object) | The maximum tolerable temperature for the species. In celsius or fahrenheit degrees | 151 | | **soil_nutriments** (integer) | Required quantity of nutriments in the soil, on a scale from 0 (oligotrophic) to 10 (hypereutrophic) | 152 | | **soil_salinity** (integer) | Tolerance to salinity, on a scale from 0 (untolerant) to 10 (hyperhaline) | 153 | | **soil_texture** (integer) | Required texture of the soil, on a scale from 0 (clay) to 10 (rock) | 154 | | **soil_humidity** (integer) | Required humidity of the soil, on a scale from 0 (xerophile) to 10 (subaquatic) | 155 | 156 | ### synonyms[] 157 | 158 | | field | description | 159 | |---------------------|------------------------------------| 160 | | **id** (integer) | An unique identifier | 161 | | **name** (string) | The scientific name of the symonym | 162 | | **author** (string) | The author of the symonym | 163 | 164 | ### sources[] 165 | 166 | | field | description | 167 | |--------------------------|--------------------------------------------------------------| 168 | | **id** (string) | An unique identifier from the source | 169 | | **name** (string) | The name of the source | 170 | | **citation** (string) | How to cite the source | 171 | | **url** (string) | The link on the source website, or the publication reference | 172 | | **last_update** (string) | The last time the source was checked | -------------------------------------------------------------------------------- /docs/examples/snippets.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: snippets 3 | title: Snippets 4 | --- 5 | 6 | import MultiLanguageSnippet from '@theme/MultiLanguageSnippet'; 7 | 8 | Here is some request samples 9 | 10 | :::tip Third party libraries 11 | The `node`, `ruby` and `python` snippets require third-party libraries: 12 | 13 | - **node**: [node-fetch](https://github.com/node-fetch/node-fetch) library. 14 | - **python**: [request](https://requests.readthedocs.io/en/master/) library. 15 | - **ruby**: [HTTParty](https://github.com/jnunemaker/httparty) library. 16 | 17 | ::: 18 | 19 |
20 | 21 |
22 | 23 | ## Genus 24 | 25 | 26 | ### Get all genus 27 | 28 | 29 | 30 |
31 | 32 |
33 | 34 | --------- 35 | 36 |
37 | 38 | ## Plants & Species 39 | 40 | :::tip Reminder 41 | **In all the following samples, `/plants` can be switched to `/species` and `/species` can be switched to `/plants`.** 42 | The only difference is that `/species` API calls will return matching species, subspecies, varieties etc..., and `/plants` API calls will only return main species (without all the children species). 43 | ::: 44 | 45 | 46 | ### Get all plants 47 | 48 | 49 | 50 | 51 |
52 | 53 | ### Get all species 54 | 55 | 56 | 57 |
58 | 59 | ### Get only edible plants 60 | 61 | 62 | 63 |
64 | 65 | 66 | ### Get tallest trees 67 | 68 | :::tip Explanation 69 | - Get all plants 70 | - With **tree** ligneous type `filter[ligneous_type]=tree` 71 | - Without plants with no maximum height `filter_not[maximum_height_cm]=null` 72 | - Ordered by maximum height descending (highest first) `order[maximum_height_cm]=desc` 73 | ::: 74 | 75 | 83 | 84 |
85 | 86 | ### Get plants in Antartica 87 | 88 | > See [Distributions](/docs/advanced/distributions) to learn more about distributions zones. 89 | 90 | 91 | 95 | 96 |
97 | 98 | ### Get plants introduced in Marion-Prince Edward 99 | 100 | 106 | 107 |
108 | 109 | ### Get plants native from Tibet 110 | 111 | 117 | 118 |
119 | 120 | ### Get species with height between 5cm and 20cm 121 | 122 | 123 | 124 | 125 |
126 | 127 | ### Get species with red flowers 128 | 129 | 130 | 131 | 132 |
133 | 134 | ### Get search for coconut species 135 | 136 | 137 | 138 | 139 |
140 | 141 | ### Get species with oldest discoveries first 142 | 143 | 144 | 145 | 146 |
147 | 148 | --------- 149 | 150 |
151 | 152 | 153 | ## Zones & Distributions 154 | 155 | > See [Distributions](/docs/advanced/distributions) to learn more about distributions zones. 156 | 157 | ### Get all countries / zones 158 | 159 | 160 | 161 |
162 | 163 | ### Get countries / zones with less than 10 species 164 | 165 | 169 | -------------------------------------------------------------------------------- /docs/guides/filtering.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: filtering 3 | title: Filtering 4 | --- 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | As you may have seen, there is a lot of plants here. In order to find what you're looking for, you can add filters to your query. The full list of available filters are in the reference. 10 | 11 | :::tip In short 12 | We can filter on one or several values, with the `filter[FIELD]=value1,value2,value3...` parameter, or on a range of values, with the `range[FIELD]=min,max` parameter. 13 | ::: 14 | 15 | ### Filter on a single value 16 | 17 | Let's query only plants with the "Beach Strawberry" common name:. 18 | 19 | https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&filter[common_name]=beach%20strawberry 20 | 21 | 22 | 31 | 32 | 33 | Open your browser and navigate to 34 | 35 | [`https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&filter[common_name]=beach%20strawberry`](https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&filter[common_name]=beach%20strawberry) 36 | 37 | 38 | 39 | 40 | In your terminal: 41 | 42 | ```bash 43 | curl 'https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&filter[common_name]=beach%20strawberry' 44 | ``` 45 | 46 | 47 | 48 | 49 | ```js 50 | const fetch = require('node-fetch'); 51 | 52 | (async () => { 53 | const response = await fetch('https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&filter[common_name]=beach%20strawberry'); 54 | const json = await response.json(); 55 | console.log(json); 56 | })(); 57 | ``` 58 | 59 | 60 | 61 | 62 | 63 | And we got: 64 | 65 | 66 | ```json 67 | { 68 | "data": [ 69 | { 70 | "author": "(L.) Mill.", 71 | "bibliography": "Gard. Dict. ed. 8 : n.° 4 (1768)", 72 | "common_name": "beach strawberry", 73 | "complete_data": true, 74 | "family_common_name": "Rose family", 75 | "genus_id": 2585, 76 | "id": 131974, 77 | "image_url": null, 78 | "links": { 79 | "genus": "/api/v1/genus/fragaria", 80 | "self": "/api/v1/plants/fragaria-chiloensis", 81 | "species": "/api/v1/plants/fragaria-chiloensis/species" 82 | }, 83 | "main_species_id": 137607, 84 | "observations": "Bolivia, C. & S. Chile to S. Argentina", 85 | "scientific_name": "Fragaria chiloensis", 86 | "slug": "fragaria-chiloensis", 87 | "vegetable": false, 88 | "year": 1768 89 | } 90 | ], 91 | "links": { 92 | "first": "/api/v1/plants?filter%5Bcommon_name%5D=beach+strawberry&page=1", 93 | "last": "/api/v1/plants?filter%5Bcommon_name%5D=beach+strawberry&page=1", 94 | "self": "/api/v1/plants?filter%5Bcommon_name%5D=beach+strawberry" 95 | }, 96 | "meta": { 97 | "total": 1 98 | } 99 | } 100 | ``` 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | ### Filter on several values 114 | 115 | Now, we can add more criterias by separating our values with a comma (`,`). 116 | 117 | Let's query only species with edible roots **OR** leaves: 118 | 119 | https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&filter[edible_part]=roots,leaves 120 | 121 | 122 | 131 | 132 | 133 | Open your browser and navigate to 134 | 135 | [`https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&filter[edible_part]=roots,leaves`](https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&filter[edible_part]=roots,leaves) 136 | 137 | 138 | 139 | 140 | In your terminal: 141 | 142 | ```bash 143 | curl 'https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&filter[edible_part]=roots,leaves' 144 | ``` 145 | 146 | 147 | 148 | 149 | ```js 150 | const fetch = require('node-fetch'); 151 | 152 | (async () => { 153 | const response = await fetch('https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&filter[edible_part]=roots,leaves'); 154 | const json = await response.json(); 155 | console.log(json); 156 | })(); 157 | ``` 158 | 159 | 160 | 161 | 162 | 163 | And we got: 164 | 165 | 166 | ```json 167 | { 168 | "data": [ 169 | { 170 | "author": "L.", 171 | "bibliography": "Sp. pl. 1:219. 1753", 172 | "common_name": "lambsquarters", 173 | "family": "Amaranthaceae", 174 | "family_common_name": "Goosefoot family", 175 | "genus": "Chenopodium", 176 | "genus_id": 1690, 177 | "id": 119861, 178 | "image_url": "https://bs.floristic.org/image/o/7210dfc0c2a48bdde194bef37c7b7956974bc1b7", 179 | "links": { 180 | "genus": "/api/v1/genus/chenopodium", 181 | "plant": "/api/v1/plants/chenopodium-album", 182 | "self": "/api/v1/species/chenopodium-album" 183 | }, 184 | "plant_id": 114228, 185 | "rank": "species", 186 | "scientific_name": "Chenopodium album", 187 | "slug": "chenopodium-album", 188 | "status": "accepted", 189 | "synonyms": [ 190 | "Chenopodium album var. viride", 191 | "Chenopodium album var. candicans", 192 | "Chenopodium album var. album", 193 | "Chenopodium paucidentatum", 194 | "Chenopodium pedunculare", 195 | "Chenopodium album var. polymorphum" 196 | ], 197 | "year": 1753 198 | }, 199 | { 200 | "author": "L.", 201 | "bibliography": "Sp. Pl.: 813 (1753)", 202 | "common_name": "chicory", 203 | "family": "Asteraceae", 204 | "family_common_name": "Aster family", 205 | "genus": "Cichorium", 206 | "genus_id": 1778, 207 | "id": 120546, 208 | "image_url": "https://bs.floristic.org/image/o/eb049be6b9186aed76ada3c8d3cd54d762842aa8", 209 | "links": { 210 | "genus": "/api/v1/genus/cichorium", 211 | "plant": "/api/v1/plants/cichorium-intybus", 212 | "self": "/api/v1/species/cichorium-intybus" 213 | }, 214 | "plant_id": 114913, 215 | "rank": "species", 216 | "scientific_name": "Cichorium intybus", 217 | "slug": "cichorium-intybus", 218 | "status": "accepted", 219 | "synonyms": [ 220 | "Cichorium divaricatum", 221 | "Cichorium cicorea", 222 | "Cichorium byzantinum", 223 | "Huernia verekeri var. stenensonii" 224 | ], 225 | "year": 1753 226 | }, 227 | // ... 28 more items... 228 | ], 229 | "links": { 230 | "first": "/api/v1/species?filter%5Bedible_part%5D=roots%2Cleaves&page=1", 231 | "last": "/api/v1/species?filter%5Bedible_part%5D=roots%2Cleaves&page=4", 232 | "next": "/api/v1/species?filter%5Bedible_part%5D=roots%2Cleaves&page=2", 233 | "self": "/api/v1/species?filter%5Bedible_part%5D=roots%2Cleaves" 234 | }, 235 | "meta": { 236 | "total": 80 237 | } 238 | } 239 | ``` 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | ### Filter on ranges 252 | 253 | Now we want to filter on a range of values. 254 | 255 | Let's query only species with a minimum height **between** 5 **and** 20 centimeters: 256 | 257 | https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&range[maximum_height_cm]=5,20 258 | 259 | :::tip Minimum and maximum values 260 | 261 | Filtering on ranges also allow to set only minimum or maximum values. For example: 262 | 263 | - `/api/v1/species?range[maximum_height_cm]=5` only return species higher than 5 cm 264 | - `/api/v1/species?range[maximum_height_cm]=,5` only return species lower than 5 cm 265 | ::: 266 | 267 | 276 | 277 | 278 | Open your browser and navigate to 279 | 280 | [`https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&range[maximum_height_cm]=5,20`](https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&range[maximum_height_cm]=5,20) 281 | 282 | 283 | 284 | 285 | In your terminal: 286 | 287 | ```bash 288 | curl 'https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&range[maximum_height_cm]=5,20' 289 | ``` 290 | 291 | 292 | 293 | 294 | ```js 295 | const fetch = require('node-fetch'); 296 | 297 | (async () => { 298 | const response = await fetch('https://trefle.io/api/v1/species?token=YOUR_TREFLE_TOKEN&range[maximum_height_cm]=5,20'); 299 | const json = await response.json(); 300 | console.log(json); 301 | })(); 302 | ``` 303 | 304 | 305 | 306 | 307 | 308 | And we got: 309 | 310 | 311 | ```json 312 | { 313 | "data": [ 314 | { 315 | "author": "L.", 316 | "bibliography": "Sp. Pl.: 767 (1753)", 317 | "common_name": "white clover", 318 | "family": "Fabaceae", 319 | "family_common_name": "Pea family", 320 | "genus": "Trifolium", 321 | "genus_id": 5044, 322 | "id": 189539, 323 | "image_url": "https://bs.floristic.org/image/o/c766ed84c547abac6021244bc0014d665ba7726f", 324 | "links": { 325 | "genus": "/api/v1/genus/trifolium", 326 | "plant": "/api/v1/plants/trifolium-repens", 327 | "self": "/api/v1/species/trifolium-repens" 328 | }, 329 | "plant_id": 183906, 330 | "rank": "species", 331 | "scientific_name": "Trifolium repens", 332 | "slug": "trifolium-repens", 333 | "status": "accepted", 334 | "synonyms": [ 335 | "Trifolium repens var. atropurpureum", 336 | "Amoria repens" 337 | ], 338 | "year": 1753 339 | }, 340 | { 341 | "author": "L.", 342 | "bibliography": "Sp. Pl.: 112 (1753)", 343 | "common_name": "common plantain", 344 | "family": "Plantaginaceae", 345 | "family_common_name": "Plantain family", 346 | "genus": "Plantago", 347 | "genus_id": 5418, 348 | "id": 167892, 349 | "image_url": "https://bs.floristic.org/image/o/36c2225c7d24a897eaf055e99eac26b3f5ceffa3", 350 | "links": { 351 | "genus": "/api/v1/genus/plantago", 352 | "plant": "/api/v1/plants/plantago-major", 353 | "self": "/api/v1/species/plantago-major" 354 | },å 355 | "plant_id": 162259, 356 | "rank": "species", 357 | "scientific_name": "Plantago major", 358 | "slug": "plantago-major", 359 | "status": "accepted", 360 | "synonyms": [ 361 | "Plantago major var. pilgeri", 362 | "Plantago major var. pachyphylla", 363 | "Plantago minima", 364 | "Plantago major var. scopulorum" 365 | ], 366 | "year": 1753 367 | }, 368 | // ... 28 more items... 369 | ], 370 | "links": { 371 | "first": "/api/v1/species?page=1&range%5Bmaximum_height_cm%5D=5%2C20", 372 | "last": "/api/v1/species?page=11&range%5Bmaximum_height_cm%5D=5%2C20", 373 | "next": "/api/v1/species?page=2&range%5Bmaximum_height_cm%5D=5%2C20", 374 | "self": "/api/v1/species?range%5Bmaximum_height_cm%5D=5%2C20" 375 | }, 376 | "meta": { 377 | "total": 218 378 | } 379 | } 380 | ``` 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | ### Exclude null values 391 | 392 | Sometimes we need to exclude results with null or empty values. For that, we can use the `filter_not[ATTRIBUTE]=null` parameter, which will exclude from the response all entries where `ATTRIBUTE` is `null`. 393 | 394 | For example, if we want all edible plants, we can either: 395 | 396 | - **Query all plants with edible roots, stem, leaves, flowers, fruits and seeds:** 397 | 398 | ```http 399 | https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&filter[edible_part]=roots,stem,leaves,flowers,fruits,seeds 400 | ``` 401 | 402 | - **Exclude all plants without edible parts:** 403 | 404 | ```http 405 | https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&filter_not[edible_part]=null 406 | ``` 407 | -------------------------------------------------------------------------------- /docs/guides/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: getting-started 3 | title: Getting started 4 | --- 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | ### Introduction 10 | 11 | This is the Trefle API documentation. The Trefle API aims to deliver all plants informations under an accessible interface. 12 | 13 | All API access is over HTTPS, and accessed from https://trefle.io. All data is sent and received as JSON. 14 | 15 | ### What You Need 16 | 17 | In order to make queries, you'll need to create an account and get your personal access token first. 18 | 19 | :::note 20 | Your access token will allow you to makes queries on the Trefle API. Keep it private. 21 | ::: 22 | 23 | 1. Create an account on [trefle.io](https://trefle.io/users/sign_up) 24 | 2. Confirm your email address 25 | 3. Login on your account 26 | 4. Grab your **Trefle access token** 27 | 28 | ### Make your first query 29 | 30 | For the first examples, we will give you the choice between: 31 | - **Using your web browser**, which is the simplest, but will be limited when we'll need to code a bit. 32 | - **Using your terminal**, with `curl` 33 | - **Using javascipt**, with NodeJS and the [`node-fetch`](https://github.com/node-fetch/node-fetch) library (install it with `yarn add node-fetch`). 34 | 35 | We will first try to list all the plants. 36 | 37 | 46 | 47 | 48 | Open your browser and navigate to 49 | 50 | [`https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN`](https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN) 51 | 52 | 53 | 54 | 55 | In your terminal: 56 | 57 | ```bash 58 | curl 'https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN' 59 | ``` 60 | 61 | 62 | 63 | 64 | With the [node-fetch](https://github.com/node-fetch/node-fetch) library, that will be used in the next examples. 65 | 66 | ```js 67 | const fetch = require('node-fetch'); 68 | 69 | (async () => { 70 | const response = await fetch('https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN'); 71 | const json = await response.json(); 72 | console.log(json); 73 | })(); 74 | ``` 75 | 76 |
77 | Or with the native https node library 78 | 79 | ```js 80 | const https = require('https'); 81 | 82 | https.get('https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN', (resp) 83 | => { 84 | let data = ''; 85 | 86 | // A chunk of data has been recieved. 87 | resp.on('data', (chunk) => { 88 | data += chunk; 89 | }); 90 | 91 | // The whole response has been received. Print out the result. 92 | resp.on('end', () => { 93 | console.log(JSON.parse(data)); 94 | }); 95 | 96 | }).on("error", (err) => { 97 | console.log("Error: " + err.message); 98 | }); 99 | ``` 100 | 101 |
102 | 103 |
104 |
105 | 106 | 107 | It return a big JSON response like this: 108 | 109 | ```json 110 | { 111 | "data": [ 112 | { 113 | "author": "Schltr.", 114 | "bibliography": "Repert. Spec. Nov. Regni Veg. 16: 358 (1920)", 115 | "common_name": null, 116 | "family": "Orchidaceae", 117 | "family_common_name": null, 118 | "genus": "Aa", 119 | "genus_id": 14887, 120 | "id": 834556, 121 | "links": { 122 | "genus": "/api/v1/genus/aa", 123 | "plant": "/api/v1/plants/aa-achalensis", 124 | "self": "/api/v1/species/aa-achalensis" 125 | }, 126 | "plant_id": 423071, 127 | "rank": "species", 128 | "scientific_name": "Aa achalensis", 129 | "slug": "aa-achalensis", 130 | "status": "accepted", 131 | "synonyms": [], 132 | "year": 1920 133 | }, 134 | { 135 | "author": "Rchb.f.", 136 | "bibliography": "Xenia Orchid. 1: 18 (1854)", 137 | "common_name": null, 138 | "family": "Orchidaceae", 139 | "family_common_name": null, 140 | "genus": "Aa", 141 | "genus_id": 14887, 142 | "id": 834557, 143 | "links": { 144 | "genus": "/api/v1/genus/aa", 145 | "plant": "/api/v1/plants/aa-argyrolepis", 146 | "self": "/api/v1/species/aa-argyrolepis" 147 | }, 148 | "plant_id": 423072, 149 | "rank": "species", 150 | "scientific_name": "Aa argyrolepis", 151 | "slug": "aa-argyrolepis", 152 | "status": "accepted", 153 | "synonyms": [ 154 | "Altensteinia argyrolepis" 155 | ], 156 | "year": 1854 157 | }, // ... 28 more items 158 | ], 159 | "links": { 160 | "first": "/api/v1/species?page=1", 161 | "last": "/api/v1/species?page=20865", 162 | "next": "/api/v1/species?page=2", 163 | "self": "/api/v1/species" 164 | }, 165 | "meta": { 166 | "total": 417293 167 | } 168 | } 169 | ``` 170 | 171 | ### Rate limiting 172 | 173 | In order to allow all users to use the API in good conditions, **a limit of 120 requests per minute is applied**. If this limit is a limiting factor for your application (and you have valid reasons), feel free to contact us. 174 | 175 | ### The Trefle structure 176 | 177 | Before going further, we need to know a bit how data is organized in the trefle API. 178 | 179 | The whole API structure is defined by the following classification: 180 | 181 | ```text 182 | Kingdom 183 | -> Subkingdom 184 | -> Division 185 | -> Division class 186 | -> Division order 187 | -> Family 188 | -> Genus 189 | -> Plant 190 | -> Species 191 | ``` 192 | 193 | For example, the [balsam fir](https://en.wikipedia.org/wiki/Abies_balsamea) hierarchy is: 194 | 195 | ```text 196 | Kingdom -> Plantae – (Plants) 197 | Subkingdom -> Tracheobionta – (Vascular plants) 198 | Division -> Coniferophyta – (Conifers) 199 | Class -> Pinopsida 200 | Order -> Pinales 201 | Family -> Pinaceae – (Pine family) 202 | Genus -> Abies 203 | Plant -> Abies balsamea 204 | Species -> Abies balsamea 205 | ``` 206 | 207 | ### Plant and Species 208 | 209 | For commodity reasons, we added a `Plant` level between Genus and Species. A plant is the main species of a species, without all the forms, varieties, subspecies etc... 210 | 211 | For each plant, we have one main species and several other "sub" species (which can be subspecies, varieties, hybrids, cultivars etc...). 212 | 213 | For example, our [balsam fir](https://en.wikipedia.org/wiki/Abies_balsamea) have: 214 | 215 | - One species (which is our "plant"): `Abies balsamea` 216 | - One sub-species: `Abies balsamea ssp. lasiocarpa` 217 | - Two varieties: `Abies balsamea var. phanerolepis` and `Abies balsamea var. balsamea` 218 | 219 | -------------------------------------------------------------------------------- /docs/guides/pagination.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: pagination 3 | title: Pagination 4 | --- 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | When you query a collection (ex: `/api/v1/plants`), you'll notice that you have only 30 items returned. 10 | 11 | That's because results are paginated. You have links for the next page in the `links` attribute of the JSON response. 12 | 13 | You can specify the page you want with the `page` parameter. To query the second page, we have add the `page` parameter as follows: `page=2`. 14 | 15 | Let's query the second page of the plants. 16 | 17 | 26 | 27 | 28 | Open your browser and navigate to 29 | 30 | [`https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&page=2`](https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&page=2) 31 | 32 | 33 | 34 | 35 | In your terminal: 36 | 37 | ```bash 38 | curl 'https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&page=2' 39 | ``` 40 | 41 | 42 | 43 | 44 | ```js 45 | const fetch = require('node-fetch'); 46 | 47 | (async () => { 48 | const response = await fetch('https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&page=2'); 49 | const json = await response.json(); 50 | console.log(json); 51 | })(); 52 | ``` 53 | 54 | 55 | 56 | 57 | You now got the second page of the plants. 58 | 59 | 60 | ```json 61 | { 62 | "data": [ 63 | { 64 | "author": "Schltr.", 65 | "bibliography": "Repert. Spec. Nov. Regni Veg. Beih. 8: 38 (1921)", 66 | "common_name": null, 67 | "family": "Orchidaceae", 68 | "family_common_name": null, 69 | "genus": "Aa", 70 | "genus_id": 14887, 71 | "id": 834623, 72 | "links": { 73 | "genus": "/api/v1/genus/aa", 74 | "plant": "/api/v1/plants/aa-riobambae", 75 | "self": "/api/v1/species/aa-riobambae" 76 | }, 77 | "plant_id": 423099, 78 | "rank": "species", 79 | "scientific_name": "Aa riobambae", 80 | "slug": "aa-riobambae", 81 | "status": "accepted", 82 | "synonyms": [ 83 | "Altensteinia riobambae" 84 | ], 85 | "year": 1921 86 | }, 87 | { 88 | "author": "Ames", 89 | "bibliography": "Proc. Biol. Soc. Washington 35: 81 (1922)", 90 | "common_name": null, 91 | "family": "Orchidaceae", 92 | "family_common_name": null, 93 | "genus": "Aa", 94 | "genus_id": 14887, 95 | "id": 834625, 96 | "links": { 97 | "genus": "/api/v1/genus/aa", 98 | "plant": "/api/v1/plants/aa-rosei", 99 | "self": "/api/v1/species/aa-rosei" 100 | }, 101 | "plant_id": 423100, 102 | "rank": "species", 103 | "scientific_name": "Aa rosei", 104 | "slug": "aa-rosei", 105 | "status": "accepted", 106 | "synonyms": [ 107 | "Altensteinia rosei" 108 | ], 109 | "year": 1922 110 | }, // ... 28 more items 111 | ], 112 | "links": { 113 | "first": "/api/v1/species?page=1", 114 | "last": "/api/v1/species?page=20865", 115 | "next": "/api/v1/species?page=3", 116 | "prev": "/api/v1/species?page=1", 117 | "self": "/api/v1/species?page=2" 118 | }, 119 | "meta": { 120 | "total": 417293 121 | }} 122 | ``` 123 | -------------------------------------------------------------------------------- /docs/guides/reporting-errors.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: reporting-errors 3 | title: Reporting an error 4 | sidebar_label: Reporting errors 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | The team behind Trefle is working hard to complete, correct and check the data, but **there is a lot**. 10 | 11 | In order to help us, you can report an error when you see one. That's really helpful for us. 12 | 13 | Reporting an error is done by doing a `POST` request on the `/api/v1/species/{species_id}/report` endpoint, with an optional `notes` parameter. [See in the reference](/reference/#operation/reportSpecies). 14 | 15 | ### Sending the report 16 | 17 | Let's say we want to report an error on the `Abies Alba` species, because we found out that the maximum height is wrong. 18 | 19 | The payload we will send will be like: 20 | 21 | ```json 22 | { 23 | "notes": "The height is wrong", 24 | } 25 | ``` 26 | 27 | 35 | 36 | 37 | 38 | In your terminal: 39 | 40 | ```bash 41 | curl -XPOST -H "Content-type: application/json" \ 42 | -d '{"notes":"The height is wrong"}' \ 43 | 'https://trefle.io/api/v1/species/abies-alba/report?token=YOUR_TREFLE_TOKEN' 44 | ``` 45 | 46 | 47 | 48 | 49 | ```js 50 | const fetch = require('node-fetch'); 51 | 52 | // The parameters for our POST request 53 | const params = { 54 | notes: 'The height is wrong' 55 | } 56 | 57 | (async () => { 58 | const response = await fetch( 59 | 'https://trefle.io/api/v1/species/abies-alba/report?token=YOUR_TREFLE_TOKEN', { 60 | method: 'post', 61 | body: JSON.stringify(params), 62 | headers: { 'Content-Type': 'application/json' } 63 | }); 64 | const json = await response.json(); 65 | console.log(json); 66 | })(); 67 | ``` 68 | 69 | 70 | 71 | 72 | 73 | And we got: 74 | 75 | ```json 76 | { 77 | "data": { 78 | "id": 9, 79 | "record_type": "Species", 80 | "record_id": 1164724, 81 | "user_id": 106, 82 | "warning_type": "report", 83 | "change_status": "pending", 84 | "change_type": "update", 85 | "accepted_by": null, 86 | "notes": "The height is wrong", 87 | "created_at": "2020-07-13T17:53:51.537Z", 88 | "updated_at": "2020-07-13T17:53:51.542Z", 89 | "correction": null, 90 | "changes": null 91 | }, 92 | "meta": { 93 | "last_modified": "2020-07-13T17:53:51.542Z" 94 | } 95 | } 96 | ``` 97 | 98 | This means that your report has been created, and is pending validation. 99 | 100 | :::tip Please send a note 101 | The `notes` parameter is optional, meaning that you could just do a POST request on `https://trefle.io/api/v1/species/abies-alba/report` to send us a report. Unless the errors is obvious, please don't do that, as we won't really know where to start. 102 | ::: 103 | 104 | ### Fixing the data yourself 105 | 106 | If you're not intimidated by big API calls, you can help us more by **correcting the data yourself**. You can see how to do it in the ["How to complete data" section of the guide](/docs/advanced/complete-data). 107 | 108 | 109 | ### Testing 110 | 111 | If you want to test a report of a species, set the `notes` field to `TEST`. They will be not reviewed, and automatically rejected after some time. 112 | 113 | For example: 114 | 115 | ```bash 116 | # This correction will not be reviewed, and rejected after some time 117 | curl -XPOST -H "Content-type: application/json" \ 118 | -d '{"notes":"TEST"}' \ 119 | 'https://trefle.io/api/v1/species/abies-alba/report?token=YOUR_TREFLE_TOKEN' 120 | ``` 121 | -------------------------------------------------------------------------------- /docs/guides/searching.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: searching 3 | title: Searching through species 4 | sidebar_label: Searching 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | 10 | You can use the `q` parameter on the `v1/plants/search` endpoint to search through plants, and on the `v1/species/search` endpoint to search through species. 11 | 12 | Let's search for cocounut plants: 13 | 14 | ``` 15 | https://trefle.io/api/v1/plants/search?token=YOUR_TREFLE_TOKEN&q=coconut 16 | ``` 17 | 18 | 27 | 28 | 29 | Open your browser and navigate to 30 | 31 | [`https://trefle.io/api/v1/plants/search?token=YOUR_TREFLE_TOKEN&q=coconut`](https://trefle.io/api/v1/plants/search?token=YOUR_TREFLE_TOKEN&q=coconut) 32 | 33 | 34 | 35 | 36 | In your terminal: 37 | 38 | ```bash 39 | curl 'https://trefle.io/api/v1/plants/search?token=YOUR_TREFLE_TOKEN&q=coconut' 40 | ``` 41 | 42 | 43 | 44 | 45 | ```js 46 | const fetch = require('node-fetch'); 47 | 48 | (async () => { 49 | const response = await fetch('https://trefle.io/api/v1/plants/search?token=YOUR_TREFLE_TOKEN&q=coconut'); 50 | const json = await response.json(); 51 | console.log(json); 52 | })(); 53 | ``` 54 | 55 | 56 | 57 | 58 | 59 | And we get: 60 | 61 | ```json 62 | { 63 | "data": [ 64 | { 65 | "author": "L.", 66 | "bibliography": "Sp. pl. 2:1188. 1753", 67 | "common_name": "coconut palm", 68 | "family": "Arecaceae", 69 | "family_common_name": "Palm family", 70 | "genus": "Cocos", 71 | "genus_id": 1916, 72 | "id": 122263, 73 | "image_url": "https://bs.floristic.org/image/o/3d907876dd89dcf4880c50fb0786191a1cb95589", 74 | "links": { 75 | "genus": "/api/v1/genus/cocos", 76 | "plant": "/api/v1/plants/cocos-nucifera", 77 | "self": "/api/v1/species/cocos-nucifera" 78 | }, 79 | "rank": "species", 80 | "scientific_name": "Cocos nucifera", 81 | "slug": "cocos-nucifera", 82 | "status": "accepted", 83 | "synonyms": [ 84 | "Calappa nucifera", 85 | "Cocos nana", 86 | "Cocos indica", 87 | "Palma cocos", 88 | "Cocos mamillaris", 89 | "Cocos nucifera var. synphyllica", 90 | "Diplothemium henryanum", 91 | "Cocos nucifera var. spicata" 92 | ], 93 | "year": 1753 94 | }, 95 | { 96 | "author": "Lodd. ex R.Keith (Jacq.)", 97 | "bibliography": "Miller's Dict. Gard.: 63 (1834)", 98 | "common_name": "Coyol palm", 99 | "family": "Arecaceae", 100 | "family_common_name": "Palm family", 101 | "genus": "Acrocomia", 102 | "genus_id": 83, 103 | "id": 228773, 104 | "image_url": "https://bs.floristic.org/image/o/a9c613b38da1de08ba3627a2e4a622c3c969c369", 105 | "links": { 106 | "genus": "/api/v1/genus/acrocomia", 107 | "plant": "/api/v1/plants/acrocomia-aculeata", 108 | "self": "/api/v1/species/acrocomia-aculeata" 109 | }, 110 | "rank": "species", 111 | "scientific_name": "Acrocomia aculeata", 112 | "slug": "acrocomia-aculeata", 113 | "status": "accepted", 114 | "synonyms": [ 115 | "Acrocomia vinifera", 116 | "Bactris minor", 117 | "Acrocomia tenuifrons", 118 | "Cocos aculeata", 119 | "Acrocomia sclerocarpa var. wallaceana", 120 | "Acrocomia spinosa", 121 | "Acrocomia zapotecis", 122 | "Acrocomia mokayayba", 123 | "Acrocomia globosa", 124 | "Acrocomia antioquiensis", 125 | "Palma mocaia", 126 | "Acrocomia guianensis" 127 | ], 128 | "year": 1834 129 | }, 130 | { 131 | "author": "Pers. (J.F.Gmel.)", 132 | "bibliography": "Syn. pl. 2(2):630. 1807", 133 | "common_name": "double coconut", 134 | "family": "Arecaceae", 135 | "family_common_name": "Palm family", 136 | "genus": "Lodoicea", 137 | "genus_id": 4249, 138 | "id": 151095, 139 | "image_url": "https://bs.floristic.org/image/o/1ad4853b6c359bac439ef21a714a9b5568c91b63", 140 | "links": { 141 | "genus": "/api/v1/genus/lodoicea", 142 | "plant": "/api/v1/plants/lodoicea-maldivica", 143 | "self": "/api/v1/species/lodoicea-maldivica" 144 | }, 145 | "rank": "species", 146 | "scientific_name": "Lodoicea maldivica", 147 | "slug": "lodoicea-maldivica", 148 | "status": "accepted", 149 | "synonyms": [ 150 | "Cocos maldivica", 151 | "Borassus sonneratii", 152 | "Lodoicea callypige", 153 | "Cocos maritima", 154 | "Lodoicea sonneratii", 155 | "Lodoicea sechellarum" 156 | ], 157 | "year": 1807 158 | }, 159 | { 160 | "author": "Burret", 161 | "bibliography": "Burret M (1930) Eine neue Palmengattung aus Südamerika. Notizblatt Des Königl. Botanischen Gartens Und Museums Zu Berlin 11(35): 48-51. doi: 10.2307/3994696.", 162 | "common_name": "Bolivian mountain coconut", 163 | "family": "Arecaceae", 164 | "family_common_name": "Palm family", 165 | "genus": "Parajubaea", 166 | "genus_id": 8244, 167 | "id": 228441, 168 | "image_url": "https://bs.floristic.org/image/o/35ef2aea9119a8f9192d22431ccb7c8c9b212c7d", 169 | "links": { 170 | "genus": "/api/v1/genus/parajubaea", 171 | "plant": "/api/v1/plants/parajubaea-torallyi", 172 | "self": "/api/v1/species/parajubaea-torallyi" 173 | }, 174 | "rank": "species", 175 | "scientific_name": "Parajubaea torallyi", 176 | "slug": "parajubaea-torallyi", 177 | "status": "accepted", 178 | "synonyms": [ 179 | "Jubaea torallyi", 180 | "Allagoptera torallyi", 181 | "Polyandrococos torallyi", 182 | "Diplothemium torallyi" 183 | ], 184 | "year": 1930 185 | }, 186 | { 187 | "author": "Lindl.", 188 | "bibliography": "Edwards's Bot. Reg. 23: t. 1986 (1837)", 189 | "common_name": "Coconut pie orchid", 190 | "family": "Orchidaceae", 191 | "family_common_name": null, 192 | "genus": "Maxillaria", 193 | "genus_id": 4497, 194 | "id": 896835, 195 | "image_url": "https://bs.floristic.org/image/o/327f7d62562099979106620f74003bff7fdc283e", 196 | "links": { 197 | "genus": "/api/v1/genus/maxillaria", 198 | "plant": "/api/v1/plants/maxillaria-tenuifolia", 199 | "self": "/api/v1/species/maxillaria-tenuifolia" 200 | }, 201 | "rank": "species", 202 | "scientific_name": "Maxillaria tenuifolia", 203 | "slug": "maxillaria-tenuifolia", 204 | "status": "accepted", 205 | "synonyms": [ 206 | "Maxillaria gracilifolia", 207 | "Maxillariella tenuifolia" 208 | ], 209 | "year": 1837 210 | } 211 | ], 212 | "links": { 213 | "first": "/api/v1/plants/search?page=1&q=coconut", 214 | "last": "/api/v1/plants/search?page=1&q=coconut", 215 | "self": "/api/v1/plants/search?q=coconut" 216 | }, 217 | "meta": { 218 | "total": 5 219 | } 220 | } 221 | ``` 222 | 223 | -------------------------------------------------------------------------------- /docs/guides/sorting.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: sorting 3 | title: Ordering results 4 | sidebar_label: Sorting 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | 10 | Sometimes, we also need to specify a particular order for sorting the results. 11 | 12 | :::tip In short 13 | You can order results by a specific value with the `order[FIELD]=asc|desc...` parameter. 14 | ::: 15 | 16 | ### Basic sorting 17 | 18 | Let's sort plants by year, in a **ascending** order: 19 | 20 | https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&order[year]=asc 21 | 22 | 23 | 32 | 33 | 34 | Open your browser and navigate to 35 | 36 | [`https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&order[year]=asc`](https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&order[year]=asc) 37 | 38 | 39 | 40 | 41 | In your terminal: 42 | 43 | ```bash 44 | curl 'https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&order[year]=asc' 45 | ``` 46 | 47 | 48 | 49 | 50 | ```js 51 | const fetch = require('node-fetch'); 52 | 53 | (async () => { 54 | const response = await fetch('https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&order[year]=asc'); 55 | const json = await response.json(); 56 | console.log(json); 57 | })(); 58 | ``` 59 | 60 | 61 | 62 | 63 | 64 | And we got: 65 | 66 | ```json 67 | { 68 | "data": [ 69 | { 70 | "author": "(Herder) C.Winkl.", 71 | "bibliography": "Trudy Imp. S.-Peterburgsk. Bot. Sada 11: 170 (890)", 72 | "common_name": null, 73 | "complete_data": null, 74 | "family_common_name": null, 75 | "genus_id": 8723, 76 | "id": 290225, 77 | "image_url": null, 78 | "links": { 79 | "genus": "/api/v1/genus/jurinea", 80 | "self": "/api/v1/plants/jurinea-semenovii", 81 | "species": "/api/v1/plants/jurinea-semenovii/species" 82 | }, 83 | "main_species_id": 433678, 84 | "observations": "C. Asia", 85 | "scientific_name": "Jurinea semenovii", 86 | "slug": "jurinea-semenovii", 87 | "vegetable": false, 88 | "year": 890 89 | }, 90 | // 29 more 91 | ], 92 | "links": { 93 | "first": "/api/v1/plants?order%5Byear%5D=asc&page=1", 94 | "last": "/api/v1/plants?order%5Byear%5D=asc&page=21005", 95 | "next": "/api/v1/plants?order%5Byear%5D=asc&page=2", 96 | "self": "/api/v1/plants?order%5Byear%5D=asc" 97 | }, 98 | "meta": { 99 | "total": 420092 100 | } 101 | } 102 | ``` 103 | 104 | 105 | ### Multiple sorting 106 | 107 | You can also add secondary sortings by chaining another `order` parameter: 108 | 109 | Let's sort plants by year, in a **ascending** order, then by scientific_name, in **descending** order: 110 | 111 | ``` 112 | https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&order[year]=asc&order[scientific_name]=desc 113 | ``` 114 | 115 | 116 | ### Excluding null values 117 | 118 | Sorting on a value that is possibly null will show the entries with null values first. 119 | For example, if we want to get the tallest trees, we will have trees with `null` maxmimum height first: 120 | 121 | ```bash 122 | # Get all plants 123 | # -> with tree ligneous type (filter[ligneous_type]=tree) 124 | # -> ordered by maximum height descending (highest first) (order[maximum_height_cm]=desc) 125 | curl "https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&filter[ligneous_type]=tree&order[maximum_height_cm]=desc" 126 | ``` 127 | 128 | To avoid that, you can exclude null values ([see Filtering](filtering#exclude-null-values)): 129 | 130 | ```bash 131 | # Get all plants 132 | # -> with tree ligneous type (filter[ligneous_type]=tree) 133 | # -> ordered by maximum height descending (highest first) (order[maximum_height_cm]=desc) 134 | # -> and without plants having a null maximum height (filter_not[maximum_height_cm]=null) 135 | curl "https://trefle.io/api/v1/plants?token=YOUR_TREFLE_TOKEN&filter[ligneous_type]=tree&order[maximum_height_cm]=desc&&filter_not[maximum_height_cm]=null" 136 | ``` 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /docusaurus.config.js: -------------------------------------------------------------------------------- 1 | // const path = require('path'); 2 | // const remarkJargon = require('remark-jargon'); 3 | // const remarkOpenAPI = require('remark-openapi'); 4 | // var jargon = require('./jargon.js') 5 | 6 | module.exports = { 7 | title: 'Trefle documentation', 8 | customFields: { 9 | swagger: '/swagger.yaml', 10 | }, 11 | tagline: 'Get started using the Trefle REST API', 12 | url: 'https://docs.trefle.io', 13 | baseUrl: '/', 14 | favicon: 'img/favicon.ico', 15 | organizationName: 'treflehq', 16 | projectName: 'documentation', 17 | // themes: ['@docusaurus/theme-search-algolia'], 18 | themeConfig: { 19 | prism: { 20 | additionalLanguages: ['ruby'], 21 | }, 22 | algolia: { 23 | // The application ID provided by Algolia 24 | appId: 'O1KF1XSVP7', 25 | 26 | // Public API key: it is safe to commit it 27 | apiKey: '2b61f11494ff46769eaa32e321c46831', 28 | 29 | indexName: 'trefle', 30 | 31 | }, 32 | colorMode: { 33 | disableSwitch: true, 34 | }, 35 | navbar: { 36 | title: 'Trefle documentation', 37 | hideOnScroll: true, 38 | logo: { 39 | alt: 'Trefle documentation', 40 | src: 'img/logo.svg', 41 | }, 42 | items: [ 43 | { 44 | to: 'docs/guides/getting-started', 45 | activeBasePath: 'docs', 46 | label: 'Docs', 47 | position: 'left', 48 | }, 49 | { 50 | to: 'reference/', 51 | activeBasePath: 'reference', 52 | label: 'Reference', 53 | position: 'left', 54 | }, 55 | {to: 'blog', label: 'Blog', position: 'left'}, 56 | { 57 | href: 'https://github.com/treflehq/documentation', 58 | label: 'GitHub', 59 | position: 'right', 60 | }, 61 | { 62 | href: 'https://trefle.io/profile', 63 | label: 'Account', 64 | position: 'right', 65 | }, 66 | { 67 | href: 'https://trefle.io/profile', 68 | label: 'Sign in', 69 | position: 'right', 70 | }, 71 | ], 72 | }, 73 | }, 74 | presets: [ 75 | [ 76 | '@docusaurus/preset-classic', 77 | { 78 | docs: { 79 | // It is recommended to set document id as docs home page (`docs/` path). 80 | // homePageId: 'getting-started', 81 | sidebarPath: require.resolve('./sidebars.js'), 82 | showLastUpdateAuthor: true, 83 | showLastUpdateTime: true, 84 | editUrl: 85 | 'https://github.com/treflehq/documentation/edit/master/', 86 | }, 87 | blog: { 88 | showReadingTime: true, 89 | feedOptions: { 90 | type: 'all', 91 | copyright: `Copyright © ${new Date().getFullYear()} Trefle.`, 92 | }, 93 | // Please change this to your repo. 94 | editUrl: 95 | 'https://github.com/treflehq/documentation/edit/master/blog/', 96 | }, 97 | theme: { 98 | customCss: require.resolve('./src/css/custom.css'), 99 | }, 100 | googleAnalytics: { 101 | trackingID: 'UA-105084612-2', 102 | anonymizeIP: true, 103 | } 104 | }, 105 | ], 106 | ], 107 | stylesheets: [ 108 | 'https://unicons.iconscout.com/release/v2.1.9/css/unicons.css', 109 | ], 110 | // plugins: [ 111 | // [path.resolve(__dirname, 'plugins/plugin-token-fetcher/'), {}], 112 | // ], 113 | }; 114 | -------------------------------------------------------------------------------- /jargon.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plants: "remark is a markdown processor powered by plugins. See remark.js.org.", 3 | remark: "remark is a markdown processor powered by plugins. See remark.js.org.", 4 | freesewing: "FreeSewing is an open source platform for made-to-measure sewing patterns. See freesewing.org" 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trefle-docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "docusaurus start", 7 | "build": "docusaurus build", 8 | "swizzle": "docusaurus swizzle", 9 | "deploy": "docusaurus deploy" 10 | }, 11 | "dependencies": { 12 | "@docusaurus/core": "^2.0", 13 | "@docusaurus/plugin-google-analytics": "^2.2.0", 14 | "@docusaurus/preset-classic": "^2.0", 15 | "@docusaurus/theme-search-algolia": "^2.2.0", 16 | "buffer": "^5.6.0", 17 | "clsx": "^1.1.1", 18 | "core-js": "^3.6.5", 19 | "jquery-param": "^1.1.2", 20 | "mobx": "^6.0.0", 21 | "query-string": "^6.13.1", 22 | "react": "^16.8.4", 23 | "react-dom": "^16.8.4", 24 | "redoc": "^2.0", 25 | "remark-jargon": "^2.6.0", 26 | "remark-openapi": "^0.1.1", 27 | "styled-components": "^5.1.1" 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.2%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | }, 41 | "devDependencies": { 42 | "node-fetch": "^2.6.1" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /plugins/plugin-token-fetcher/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plugin-token-fetcher", 3 | "version": "2.0.0-alpha.58", 4 | "description": "Replace client token on trefle", 5 | "main": "src/index.js", 6 | "publishConfig": { 7 | "access": "public" 8 | }, 9 | "license": "MIT", 10 | "peerDependencies": { 11 | "@docusaurus/core": "^2.0.0" 12 | }, 13 | "engines": { 14 | "node": ">=10.15.1" 15 | } 16 | } -------------------------------------------------------------------------------- /plugins/plugin-token-fetcher/src/fetcher.js: -------------------------------------------------------------------------------- 1 | import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; 2 | 3 | export default (function () { 4 | if (!ExecutionEnvironment.canUseDOM) { 5 | return null; 6 | } 7 | 8 | console.log("Mama mia !", this); 9 | 10 | // window.addEventListener("DOMContentLoaded", (event) => { 11 | // const mw = document.querySelector('.main-wrapper') 12 | // mw.innerHTML = mw.innerHTML.replace(/YOUR_TREFLE_TOKEN/g, 'xxx-yyy-zzz') 13 | // }) 14 | 15 | return { 16 | // onRouteUpdate({ location, ...other }) { 17 | // console.log("[ftcher] onRouteUpdate !", { location, other }); 18 | // const mw = document.querySelector('.main-wrapper') 19 | // mw.innerHTML = mw.innerHTML.replace(/YOUR_TREFLE_TOKEN/g, 'xxx-yyy-zzz') 20 | 21 | // }, 22 | }; 23 | })(); 24 | -------------------------------------------------------------------------------- /plugins/plugin-token-fetcher/src/index.js: -------------------------------------------------------------------------------- 1 | 2 | const path = require('path'); 3 | 4 | module.exports = function (context) { 5 | // const { siteConfig } = context; 6 | // const { themeConfig } = siteConfig; 7 | // const { googleAnalytics } = themeConfig || {}; 8 | 9 | // if (!googleAnalytics) { 10 | // throw new Error( 11 | // `You need to specify 'googleAnalytics' object in 'themeConfig' with 'trackingId' field in it to use plugin-token-fetcher`, 12 | // ); 13 | // } 14 | 15 | // const { trackingID, anonymizeIP } = googleAnalytics; 16 | 17 | // if (!trackingID) { 18 | // throw new Error( 19 | // 'You specified the `googleAnalytics` object in `themeConfig` but the `trackingID` field was missing. ' + 20 | // 'Please ensure this is not a mistake.', 21 | // ); 22 | // } 23 | 24 | const isProd = process.env.NODE_ENV === 'production'; 25 | 26 | return { 27 | name: 'plugin-token-fetcher', 28 | async loadContent() { 29 | console.log("Pluging loaded"); 30 | }, 31 | async contentLoaded({ content, actions }) { 32 | console.log("contentLoaded", { content, actions }); 33 | }, 34 | 35 | getClientModules() { 36 | return [path.resolve(__dirname, './fetcher')]; 37 | }, 38 | 39 | injectHtmlTags() { 40 | // if (!isProd) { 41 | // return {}; 42 | // } 43 | return { 44 | headTags: [ 45 | // { 46 | // tagName: 'link', 47 | // attributes: { 48 | // rel: 'preconnect', 49 | // href: 'https://www.google-analytics.com', 50 | // }, 51 | // }, 52 | // // https://developers.google.com/analytics/devguides/collection/analyticsjs/#alternative_async_tag 53 | // { 54 | // tagName: 'script', 55 | // innerHTML: ` 56 | // window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date; 57 | // ga('create', '${trackingID}', 'auto'); 58 | // ${anonymizeIP ? "ga('set', 'anonymizeIp', true);\n" : ''} 59 | // ga('send', 'pageview'); 60 | // `, 61 | // }, 62 | // { 63 | // tagName: 'script', 64 | // attributes: { 65 | // async: true, 66 | // src: 'https://www.google-analytics.com/analytics.js', 67 | // }, 68 | // }, 69 | ], 70 | }; 71 | }, 72 | }; 73 | }; -------------------------------------------------------------------------------- /sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | someSidebar: [ 3 | { 4 | type: 'category', 5 | label: 'Guides', 6 | collapsed: false, 7 | items: [ 8 | 'guides/getting-started', 9 | 'guides/pagination', 10 | 'guides/filtering', 11 | 'guides/sorting', 12 | 'guides/searching', 13 | 'guides/reporting-errors', 14 | ], 15 | }, 16 | { 17 | type: 'category', 18 | label: 'Advanced', 19 | collapsed: false, 20 | items: [ 21 | 'advanced/plants-fields', 22 | 'advanced/client-side-apps', 23 | 'advanced/complete-data', 24 | 'advanced/distributions', 25 | ] 26 | }, 27 | { 28 | type: 'category', 29 | label: 'Examples', 30 | collapsed: false, 31 | items: [ 32 | 'examples/snippets' 33 | ] 34 | }, 35 | { 36 | type: 'link', 37 | label: 'Reference', // The label that should be displayed (string). 38 | href: '/reference' // The target URL (string). 39 | }, 40 | ] 41 | }; 42 | -------------------------------------------------------------------------------- /src/css/custom.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * Any CSS included here will be global. The classic template 4 | * bundles Infima by default. Infima is a CSS framework designed to 5 | * work well for content-centric websites. 6 | */ 7 | @import url('https://fonts.googleapis.com/css?family=Roboto+Mono:300,400,500,700'); 8 | 9 | /** 10 | * Suggested responsive breakpoints: 11 | * 12 | * Small: 480px 13 | * Medium: 768px 14 | * Large: 992px 15 | * Extra large: 1200px (Why is this still considered "extra large" in 2020? 🤔) 16 | */ 17 | 18 | /* You can override the default Infima variables here. */ 19 | :root { 20 | --ifm-color-primary: #2d7b0f; 21 | --ifm-color-primary-dark: #1e5409; 22 | --ifm-color-primary-darker: #1e5409; 23 | --ifm-color-primary-darkest: #1e5409; 24 | --ifm-color-primary-light: #44a71e; 25 | --ifm-color-primary-lighter: #51bd28; 26 | --ifm-color-primary-lightest: #78d654; 27 | --ifm-code-font-size: 95%; 28 | --fa-primary-color: #2d7b0f; 29 | 30 | } 31 | 32 | * { 33 | -webkit-font-smoothing: antialiased; 34 | -webkit-overflow-scrolling: touch; 35 | -webkit-tap-highlight-color: rgba(0,0,0,0); 36 | -webkit-text-size-adjust: none; 37 | -webkit-touch-callout: none; 38 | box-sizing: border-box; 39 | } 40 | 41 | html { 42 | min-width: 100vw; 43 | } 44 | 45 | body { 46 | -moz-osx-font-smoothing: grayscale; 47 | -webkit-font-smoothing: antialiased; 48 | color: #363636; 49 | font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif; 50 | font-size: 15px; 51 | letter-spacing: 0; 52 | margin: 0; 53 | overflow-x: hidden; 54 | } 55 | 56 | .main-wrapper { 57 | padding: 1em; 58 | } 59 | 60 | h1, h2, h3 { 61 | font-family: 'Roboto Mono', monospace; 62 | } 63 | 64 | .docusaurus-highlight-code-line { 65 | background-color: rgb(72, 77, 91); 66 | display: block; 67 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 68 | padding: 0 var(--ifm-pre-padding); 69 | } 70 | 71 | span.token.number { 72 | font-size: inherit; 73 | background: inherit; 74 | height: inherit; 75 | width: inherit; 76 | margin: inherit; 77 | padding: inherit; 78 | border-radius: inherit; 79 | display: initial; 80 | } 81 | 82 | .redoc-json code { 83 | background-color: initial; 84 | color: #a2a2a2; 85 | } 86 | 87 | table th, table td { 88 | border: inherit; 89 | } 90 | 91 | :root { 92 | --ifm-color-success: #e8f5e3; 93 | --ifm-color-info: #ddf7ff; 94 | --ifm-alert-color: #333; 95 | } 96 | -------------------------------------------------------------------------------- /src/css/fonts.css: -------------------------------------------------------------------------------- 1 | /* cyrillic-ext */ 2 | @font-face { 3 | font-family: 'Roboto Mono'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: url(https://fonts.gstatic.com/s/robotomono/v11/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vq_SeW-AJi8SJQtQ4Y.woff) format('woff'); 7 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; 8 | } 9 | /* cyrillic */ 10 | @font-face { 11 | font-family: 'Roboto Mono'; 12 | font-style: normal; 13 | font-weight: 400; 14 | src: url(https://fonts.gstatic.com/s/robotomono/v11/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vq_QOW-AJi8SJQtQ4Y.woff) format('woff'); 15 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 16 | } 17 | /* greek */ 18 | @font-face { 19 | font-family: 'Roboto Mono'; 20 | font-style: normal; 21 | font-weight: 400; 22 | src: url(https://fonts.gstatic.com/s/robotomono/v11/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vq_R-W-AJi8SJQtQ4Y.woff) format('woff'); 23 | unicode-range: U+0370-03FF; 24 | } 25 | /* vietnamese */ 26 | @font-face { 27 | font-family: 'Roboto Mono'; 28 | font-style: normal; 29 | font-weight: 400; 30 | src: url(https://fonts.gstatic.com/s/robotomono/v11/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vq_S-W-AJi8SJQtQ4Y.woff) format('woff'); 31 | unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; 32 | } 33 | /* latin-ext */ 34 | @font-face { 35 | font-family: 'Roboto Mono'; 36 | font-style: normal; 37 | font-weight: 400; 38 | src: url(https://fonts.gstatic.com/s/robotomono/v11/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vq_SuW-AJi8SJQtQ4Y.woff) format('woff'); 39 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 40 | } 41 | /* latin */ 42 | @font-face { 43 | font-family: 'Roboto Mono'; 44 | font-style: normal; 45 | font-weight: 400; 46 | src: url(https://fonts.gstatic.com/s/robotomono/v11/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vq_ROW-AJi8SJQt.woff) format('woff'); 47 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 48 | } 49 | /* cyrillic-ext */ 50 | @font-face { 51 | font-family: 'Source Sans Pro'; 52 | font-style: normal; 53 | font-weight: 300; 54 | src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwmhdu3cOWxy40.woff2) format('woff2'); 55 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; 56 | } 57 | /* cyrillic */ 58 | @font-face { 59 | font-family: 'Source Sans Pro'; 60 | font-style: normal; 61 | font-weight: 300; 62 | src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwkxdu3cOWxy40.woff2) format('woff2'); 63 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 64 | } 65 | /* greek-ext */ 66 | @font-face { 67 | font-family: 'Source Sans Pro'; 68 | font-style: normal; 69 | font-weight: 300; 70 | src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwmxdu3cOWxy40.woff2) format('woff2'); 71 | unicode-range: U+1F00-1FFF; 72 | } 73 | /* greek */ 74 | @font-face { 75 | font-family: 'Source Sans Pro'; 76 | font-style: normal; 77 | font-weight: 300; 78 | src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlBdu3cOWxy40.woff2) format('woff2'); 79 | unicode-range: U+0370-03FF; 80 | } 81 | /* vietnamese */ 82 | @font-face { 83 | font-family: 'Source Sans Pro'; 84 | font-style: normal; 85 | font-weight: 300; 86 | src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwmBdu3cOWxy40.woff2) format('woff2'); 87 | unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; 88 | } 89 | /* latin-ext */ 90 | @font-face { 91 | font-family: 'Source Sans Pro'; 92 | font-style: normal; 93 | font-weight: 300; 94 | src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwmRdu3cOWxy40.woff2) format('woff2'); 95 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 96 | } 97 | /* latin */ 98 | @font-face { 99 | font-family: 'Source Sans Pro'; 100 | font-style: normal; 101 | font-weight: 300; 102 | src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlxdu3cOWxw.woff2) format('woff2'); 103 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 104 | } 105 | /* cyrillic-ext */ 106 | @font-face { 107 | font-family: 'Source Sans Pro'; 108 | font-style: normal; 109 | font-weight: 400; 110 | src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNa7lujVj9_mf.woff2) format('woff2'); 111 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; 112 | } 113 | /* cyrillic */ 114 | @font-face { 115 | font-family: 'Source Sans Pro'; 116 | font-style: normal; 117 | font-weight: 400; 118 | src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qPK7lujVj9_mf.woff2) format('woff2'); 119 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 120 | } 121 | /* greek-ext */ 122 | @font-face { 123 | font-family: 'Source Sans Pro'; 124 | font-style: normal; 125 | font-weight: 400; 126 | src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNK7lujVj9_mf.woff2) format('woff2'); 127 | unicode-range: U+1F00-1FFF; 128 | } 129 | /* greek */ 130 | @font-face { 131 | font-family: 'Source Sans Pro'; 132 | font-style: normal; 133 | font-weight: 400; 134 | src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qO67lujVj9_mf.woff2) format('woff2'); 135 | unicode-range: U+0370-03FF; 136 | } 137 | /* vietnamese */ 138 | @font-face { 139 | font-family: 'Source Sans Pro'; 140 | font-style: normal; 141 | font-weight: 400; 142 | src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qN67lujVj9_mf.woff2) format('woff2'); 143 | unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; 144 | } 145 | /* latin-ext */ 146 | @font-face { 147 | font-family: 'Source Sans Pro'; 148 | font-style: normal; 149 | font-weight: 400; 150 | src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNq7lujVj9_mf.woff2) format('woff2'); 151 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 152 | } 153 | /* latin */ 154 | @font-face { 155 | font-family: 'Source Sans Pro'; 156 | font-style: normal; 157 | font-weight: 400; 158 | src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7lujVj9w.woff2) format('woff2'); 159 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 160 | } 161 | /* cyrillic-ext */ 162 | @font-face { 163 | font-family: 'Source Sans Pro'; 164 | font-style: normal; 165 | font-weight: 600; 166 | src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmhdu3cOWxy40.woff2) format('woff2'); 167 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; 168 | } 169 | /* cyrillic */ 170 | @font-face { 171 | font-family: 'Source Sans Pro'; 172 | font-style: normal; 173 | font-weight: 600; 174 | src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwkxdu3cOWxy40.woff2) format('woff2'); 175 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 176 | } 177 | /* greek-ext */ 178 | @font-face { 179 | font-family: 'Source Sans Pro'; 180 | font-style: normal; 181 | font-weight: 600; 182 | src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmxdu3cOWxy40.woff2) format('woff2'); 183 | unicode-range: U+1F00-1FFF; 184 | } 185 | /* greek */ 186 | @font-face { 187 | font-family: 'Source Sans Pro'; 188 | font-style: normal; 189 | font-weight: 600; 190 | src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwlBdu3cOWxy40.woff2) format('woff2'); 191 | unicode-range: U+0370-03FF; 192 | } 193 | /* vietnamese */ 194 | @font-face { 195 | font-family: 'Source Sans Pro'; 196 | font-style: normal; 197 | font-weight: 600; 198 | src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmBdu3cOWxy40.woff2) format('woff2'); 199 | unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; 200 | } 201 | /* latin-ext */ 202 | @font-face { 203 | font-family: 'Source Sans Pro'; 204 | font-style: normal; 205 | font-weight: 600; 206 | src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwmRdu3cOWxy40.woff2) format('woff2'); 207 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 208 | } 209 | /* latin */ 210 | @font-face { 211 | font-family: 'Source Sans Pro'; 212 | font-style: normal; 213 | font-weight: 600; 214 | src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xKydSBYKcSV-LCoeQqfX1RYOo3i54rwlxdu3cOWxw.woff2) format('woff2'); 215 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 216 | } -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import Layout from '@theme/Layout'; 4 | import Link from '@docusaurus/Link'; 5 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 6 | import useBaseUrl from '@docusaurus/useBaseUrl'; 7 | import styles from './styles.module.css'; 8 | 9 | const features = [ 10 | { 11 | icon: <>, 12 | title: <>Get started, 13 | link: '/docs/guides/getting-started', 14 | description: ( 15 | <> 16 | Discover how to get started with the Trefle API basis, step by step. 17 | 18 | ), 19 | }, 20 | { 21 | icon: <>, 22 | title: <>Advanced topics, 23 | link: '/docs/advanced/plants-fields', 24 | description: ( 25 | <> 26 | Understand trefle schemas and specifications in depth. 27 | 28 | ), 29 | }, 30 | { 31 | icon: <>, 32 | title: <>Examples and samples, 33 | link: '/docs/examples/snippets', 34 | description: ( 35 | <> 36 | See sample queries and code snippets. 37 | 38 | ), 39 | }, 40 | { 41 | icon: <>, 42 | title: <>API Reference, 43 | link: '/reference', 44 | description: ( 45 | <> 46 | In depth reference of Trefle API endpoints, parameters and data structure. 47 | 48 | ), 49 | }, 50 | ]; 51 | 52 | function Feature({link, title, icon, description}) { 53 | return ( 54 | 55 | 58 |
59 |

{title}

60 |

{description}

61 |
62 | 63 | ); 64 | } 65 | 66 | function Home(props) { 67 | const context = useDocusaurusContext(); 68 | const {siteConfig = {}} = context; 69 | console.log({ props, context }) 70 | return ( 71 | 74 |
75 |
76 |

{siteConfig.title}

77 |

{siteConfig.tagline}

78 |
79 | 80 | 87 | Get Started 88 | 89 | 96 | API reference 97 | 98 |
99 |
100 |
101 |
102 |
103 | {features && features.length > 0 && ( 104 |
105 | {features.map((props, idx) => ( 106 | 107 | ))} 108 |
109 | )} 110 |
111 | 112 |
113 |
114 | 117 | 118 | 119 | Back to Trefle website 120 | 121 | 122 |
123 |
124 |
125 |
126 | ); 127 | } 128 | 129 | export default Home; 130 | -------------------------------------------------------------------------------- /src/pages/reference.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Layout from '@theme/Layout'; 3 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 4 | import { RedocStandalone } from 'redoc'; 5 | 6 | function Home() { 7 | const context = useDocusaurusContext(); 8 | const { siteConfig = { customFields: {} } } = context; 9 | console.log({ siteConfig }) 10 | return ( 11 | 14 |
15 | 34 |
35 |
36 | ); 37 | } 38 | 39 | export default Home; 40 | -------------------------------------------------------------------------------- /src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | 3 | /** 4 | * CSS files with the .module.css suffix will be treated as CSS modules 5 | * and scoped locally. 6 | */ 7 | 8 | /* Hero */ 9 | 10 | .heroBanner { 11 | padding: 4rem 0; 12 | text-align: center; 13 | position: relative; 14 | overflow: hidden; 15 | } 16 | 17 | .heroTitle { 18 | font-size: 3rem; 19 | } 20 | 21 | .heroSubtitle { 22 | font-size: 1.5rem; 23 | } 24 | 25 | @media screen and (max-width: 966px) { 26 | .heroBanner { 27 | padding: 2rem; 28 | } 29 | } 30 | 31 | /* //// */ 32 | 33 | .buttons { 34 | display: flex; 35 | align-items: center; 36 | justify-content: center; 37 | color: #fff; 38 | flex-wrap: wrap; 39 | } 40 | 41 | .bigButton { 42 | color: #fff; 43 | max-width: 200px; 44 | flex: 1 1 auto; 45 | margin: 1em; 46 | display: inline-block; 47 | transition: opacity .20s; 48 | } 49 | 50 | .bigButton:hover { 51 | opacity: .75; 52 | } 53 | 54 | .features { 55 | display: flex; 56 | align-items: center; 57 | padding: 2rem 0; 58 | width: 100%; 59 | max-width: 800px; 60 | margin: auto; 61 | 62 | display: grid; 63 | grid-template-columns: repeat(2, 1fr); 64 | grid-template-rows: repeat(2, 1fr); 65 | grid-column-gap: 10px; 66 | grid-row-gap: 10px; 67 | 68 | } 69 | 70 | .feature { 71 | display: flex; 72 | /* align-items: flex-start; */ 73 | align-items: center; 74 | /* margin: 1em 0; */ 75 | padding: .5em; 76 | background-color: rgba(0, 0, 0, .02); 77 | border-radius: 3px; 78 | /* justify-content: center; */ 79 | } 80 | 81 | .feature p { 82 | color: #363636; 83 | text-decoration: none; 84 | } 85 | 86 | .feature p:last-child { 87 | margin-bottom: 0; 88 | } 89 | 90 | .features h3 { 91 | text-align: center; 92 | margin-bottom: .5em; 93 | } 94 | 95 | .featureAside { 96 | padding: 0 10px; 97 | display: flex; 98 | font-size: 3em; 99 | color: #2d7b0f; 100 | align-items: center; 101 | justify-content: center; 102 | } 103 | 104 | .featureMain { 105 | display: flex; 106 | flex-direction: column; 107 | align-items: flex-start; 108 | justify-content: stretch; 109 | } 110 | 111 | 112 | .featureImage { 113 | height: 200px; 114 | width: 200px; 115 | } 116 | 117 | /* Responsive */ 118 | 119 | @media screen and (max-width: 480px) { 120 | 121 | /* Hero */ 122 | 123 | .heroTitle { 124 | font-size: 2rem; 125 | word-wrap: normal; 126 | text-align: left; 127 | } 128 | 129 | .heroBanner { 130 | padding: 0; 131 | } 132 | 133 | .heroSubtitle { 134 | font-size: 1rem; 135 | } 136 | 137 | /* Features grid */ 138 | 139 | .features { 140 | grid-template-columns: repeat(1, 1fr); 141 | padding-top: 1.5em; 142 | } 143 | 144 | .features .feature { 145 | align-items: flex-start; 146 | } 147 | 148 | .features .feature h3 { 149 | text-align: left; 150 | } 151 | 152 | .features .featureAside > i { 153 | display: inherit; 154 | } 155 | 156 | } -------------------------------------------------------------------------------- /src/theme/Footer/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import clsx from 'clsx'; 10 | 11 | import Link from '@docusaurus/Link'; 12 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 13 | import useBaseUrl from '@docusaurus/useBaseUrl'; 14 | import styles from './styles.module.css'; 15 | 16 | function FooterLink({to, href, label, prependBaseUrlToHref, ...props}) { 17 | const toUrl = useBaseUrl(to); 18 | const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true}); 19 | 20 | return ( 21 | 33 | {label} 34 | 35 | ); 36 | } 37 | 38 | const FooterLogo = ({url, alt}) => ( 39 | {alt} 40 | ); 41 | 42 | function Footer() { 43 | const context = useDocusaurusContext(); 44 | const {siteConfig = {}} = context; 45 | const {themeConfig = {}} = siteConfig; 46 | const {footer} = themeConfig; 47 | 48 | const {copyright, links = [], logo = {}} = footer || {}; 49 | const logoUrl = useBaseUrl(logo.src); 50 | 51 | if (!footer) { 52 | return null; 53 | } 54 | 55 | return ( 56 |
60 |
61 | {links && links.length > 0 && ( 62 |
63 | {links.map((linkItem, i) => ( 64 |
65 | {linkItem.title != null ? ( 66 |

{linkItem.title}

67 | ) : null} 68 | {linkItem.items != null && 69 | Array.isArray(linkItem.items) && 70 | linkItem.items.length > 0 ? ( 71 |
    72 | {linkItem.items.map((item, key) => 73 | item.html ? ( 74 |
  • 81 | ) : ( 82 |
  • 83 | 84 |
  • 85 | ), 86 | )} 87 |
88 | ) : null} 89 |
90 | ))} 91 |
92 | )} 93 | {(logo || copyright) && ( 94 |
95 | {logo && logo.src && ( 96 |
97 | {logo.href ? ( 98 | 103 | 104 | 105 | ) : ( 106 | 107 | )} 108 |
109 | )} 110 | 111 |
116 |
117 | )} 118 |
119 |
120 | ); 121 | } 122 | 123 | export default Footer; 124 | -------------------------------------------------------------------------------- /src/theme/Footer/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .footerLogoLink { 9 | opacity: 0.5; 10 | transition: opacity 0.15s ease-in-out; 11 | } 12 | 13 | .footerLogoLink:hover { 14 | opacity: 1; 15 | } 16 | -------------------------------------------------------------------------------- /src/theme/MultiLanguageSnippet/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Tabs from '@theme/Tabs'; 3 | import TabItem from '@theme/TabItem'; 4 | import CodeBlock from '@theme/CodeBlock'; 5 | import qs from 'jquery-param'; 6 | 7 | 8 | const MultiLanguageSnippet = ({ 9 | endpoint, 10 | method = 'GET', 11 | query = {}, 12 | body = {}, 13 | ...props 14 | }) => { 15 | 16 | console.log({ endpoint, method, query, props }); 17 | const qparams = { 18 | ...query, 19 | token: 'YOUR_TREFLE_TOKEN' 20 | }; 21 | 22 | const searchParams = qs(qparams); 23 | 24 | const values = [ 25 | { label: 'CURL', value: 'curl' }, 26 | { label: 'Browser', value: 'browser' }, 27 | { label: 'NodeJS', value: 'node' }, 28 | { label: 'Python', value: 'python' }, 29 | { label: 'Ruby', value: 'ruby' }, 30 | ] 31 | 32 | const renderCodeBlock = ({ value }) => { 33 | 34 | switch (value) { 35 | case "browser": 36 | return ( 37 | Open your browser and navigate to {`https://trefle.io${endpoint}?${searchParams.toString()}`} 38 | 39 | ) 40 | 41 | case "curl": 42 | return ( 43 | {` 44 | curl -X ${method.toString().toUpperCase()} "https://trefle.io${endpoint}?${searchParams.toString()}" 45 | `} 46 | ) 47 | 48 | case "node": 49 | return ( 50 | {` 51 | const fetch = require('node-fetch'); 52 | 53 | (async () => { 54 | const response = await fetch('https://trefle.io${endpoint}?${searchParams.toString()}'); 55 | const json = await response.json(); 56 | console.log(json); 57 | })(); 58 | `} 59 | 60 | ) 61 | 62 | case "python": 63 | return ( 64 | {` 65 | import requests 66 | 67 | r = requests.${method.toString().toLowerCase()}('https://trefle.io${endpoint}?${searchParams.toString()}') 68 | r.json 69 | `} 70 | 71 | ) 72 | 73 | 74 | case "ruby": 75 | return ( 76 | {` 77 | require 'httparty' 78 | 79 | r = HTTParty.${method.toString().toLowerCase()}( 80 | 'https://trefle.io${endpoint}', 81 | query: ${JSON.stringify(qparams, null, 2).split("\n").join("\n ")} 82 | ) 83 | r.parsed_response 84 | `} 85 | 86 | ) 87 | 88 | default: 89 | return ( 90 | ? 91 | ) 92 | } 93 | } 94 | 95 | return ( 96 |
97 | 102 | {values.map(renderCodeBlock)} 103 | 104 |
105 | ) 106 | } 107 | 108 | export default MultiLanguageSnippet -------------------------------------------------------------------------------- /static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/treflehq/documentation/d3cb35ea58cefbca5f296acf4e829fdd27fc25eb/static/.nojekyll -------------------------------------------------------------------------------- /static/CNAME: -------------------------------------------------------------------------------- 1 | docs.trefle.io -------------------------------------------------------------------------------- /static/img/client-scheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/treflehq/documentation/d3cb35ea58cefbca5f296acf4e829fdd27fc25eb/static/img/client-scheme.png -------------------------------------------------------------------------------- /static/img/distributions-world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/treflehq/documentation/d3cb35ea58cefbca5f296acf4e829fdd27fc25eb/static/img/distributions-world.png -------------------------------------------------------------------------------- /static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/treflehq/documentation/d3cb35ea58cefbca5f296acf4e829fdd27fc25eb/static/img/favicon.ico -------------------------------------------------------------------------------- /static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/treflehq/documentation/d3cb35ea58cefbca5f296acf4e829fdd27fc25eb/static/img/logo.png --------------------------------------------------------------------------------