Skip to content

Commit 17658ce

Browse files
committed
builder test
1 parent 6895612 commit 17658ce

File tree

12 files changed

+384
-2
lines changed

12 files changed

+384
-2
lines changed

.github/scripts/fetch-cats.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const https = require('https');
2+
const fs = require('fs');
3+
4+
const API_KEY = process.env.CAT_API_KEY;
5+
const OUTPUT_FILE = '_data/cats.json';
6+
7+
const options = {
8+
hostname: 'api.thecatapi.com',
9+
path: '/v1/images/search?size=small&mime_types=gif&limit=5',
10+
headers: {
11+
'x-api-key': API_KEY
12+
}
13+
};
14+
15+
https.get(options, (resp) => {
16+
let data = '';
17+
18+
resp.on('data', (chunk) => {
19+
data += chunk;
20+
});
21+
22+
resp.on('end', () => {
23+
// Create directory if it doesn't exist
24+
const dir = '_data';
25+
if (!fs.existsSync(dir)){
26+
fs.mkdirSync(dir);
27+
}
28+
29+
// Save the cat data
30+
fs.writeFileSync(OUTPUT_FILE, data);
31+
console.log('Cat data saved successfully!');
32+
});
33+
34+
}).on("error", (err) => {
35+
console.error("Error: " + err.message);
36+
process.exit(1);
37+
});

.github/workflows/publish.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Quarto Publish
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches: main
7+
8+
9+
jobs:
10+
build-deploy:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: write
14+
env:
15+
CAT_API_KEY: ${{ secrets.CAT_API_KEY }}
16+
17+
steps:
18+
- name: Check out repository
19+
uses: actions/checkout@v4
20+
21+
- name: Set up Quarto
22+
uses: quarto-dev/quarto-actions/setup@v2
23+
with:
24+
version: pre-release
25+
26+
- name: Install Node.js
27+
uses: actions/setup-node@v4
28+
with:
29+
node-version: '20'
30+
31+
- name: Fetch Cat Images
32+
run: |
33+
mkdir -p _data
34+
node .github/scripts/fetch-cats.js
35+
env:
36+
CAT_API_KEY: ${{ secrets.CAT_API_KEY }}
37+
38+
- name: Render Quarto Project
39+
run: quarto render
40+
41+
- name: Deploy to GitHub Pages
42+
uses: peaceiris/actions-gh-pages@v3
43+
with:
44+
github_token: ${{ secrets.GITHUB_TOKEN }}
45+
publish_dir: ./_site

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ _environment.local
66
_environment.required
77
/_*.local
88
_site/
9+
.jenv
10+
_data/
11+
.github/scripts/node_modules/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"hash": "3e4fe17afe91c7f7d0c66179b7ec3ce2",
3+
"result": {
4+
"engine": "jupyter",
5+
"markdown": "---\ntitle: \"What is an API?\"\nexecute:\n echo: false\nformat:\n html:\n code-fold: true\nlightbox: true\n---\n\n\n\n\nAn API (Application Programming Interface) is a set of rules and protocols enabling software programs to communicate and share information. While the term is often associated with \"web APIs,\" it encompasses a broader concept. For instance, an API might allow a library to share its collection data with a museum or enable a weather service to provide updates to a news organization. APIs operate based on predefined rules set by developers, specifying how data can be accessed and used. While some APIs are public, most are internal, facilitating communication between systems within an organization. \n\nFor those unfamiliar with computer science, APIs can be a bit abstract, so let's try to explain it better with this example using the [The Cat API](https://thecatapi.com/). This API allows you to get information about different cat and dog breeds, with images and descriptions. The information is not available through a public interface, so if you want to see a cat image, you must use the API.\n\nIn this example, let's get the information about the Ragdoll cat breed. To do this, we require to use this API endpoint: [https://api.thecatapi.com/v1/images/XFhRpYS_D](https://api.thecatapi.com/v1/images/XFhRpYS_D). \n\nYou can click on that link to view the information about the cat in a format similar to this:\n\n::: {#8f56110f .cell execution_count=1}\n\n::: {.cell-output .cell-output-stdout}\n```\n{\n \"id\": \"XFhRpYS_D\",\n \"url\": \"https://cdn2.thecatapi.com/images/XFhRpYS_D.jpg\",\n \"breeds\": [\n {\n \"weight\": {\n \"imperial\": \"12 - 20\",\n \"metric\": \"5 - 9\"\n },\n \"id\": \"ragd\",\n \"name\": \"Ragdoll\",\n \"cfa_url\": \"http://cfa.org/Breeds/BreedsKthruR/Ragdoll.aspx\",\n \"vetstreet_url\": \"http://www.vetstreet.com/cats/ragdoll\",\n \"vcahospitals_url\": \"https://vcahospitals.com/know-your-pet/cat-breeds/ragdoll\",\n \"temperament\": \"Affectionate, Friendly, Gentle, Quiet, Easygoing\",\n \"origin\": \"United States\",\n \"country_codes\": \"US\",\n \"country_code\": \"US\",\n \"description\": \"Ragdolls love their people, greeting them at the door, following them around the house, and leaping into a lap or snuggling in bed whenever given the chance. They are the epitome of a lap cat, enjoy being carried and collapsing into the arms of anyone who holds them.\",\n \"life_span\": \"12 - 17\",\n \"indoor\": 0,\n \"lap\": 1,\n \"alt_names\": \"Rag doll\",\n \"adaptability\": 5,\n \"affection_level\": 5,\n \"child_friendly\": 4,\n \"dog_friendly\": 5,\n \"energy_level\": 3,\n \"grooming\": 2,\n \"health_issues\": 3,\n \"intelligence\": 3,\n \"shedding_level\": 3,\n \"social_needs\": 5,\n \"stranger_friendly\": 3,\n \"vocalisation\": 1,\n \"experimental\": 0,\n \"hairless\": 0,\n \"natural\": 0,\n \"rare\": 0,\n \"rex\": 0,\n \"suppressed_tail\": 0,\n \"short_legs\": 0,\n \"wikipedia_url\": \"https://en.wikipedia.org/wiki/Ragdoll\",\n \"hypoallergenic\": 0,\n \"reference_image_id\": \"oGefY4YoG\"\n }\n ],\n \"width\": 800,\n \"height\": 1229\n}\n```\n:::\n:::\n\n\nThis format is called JSON, and its widely used in APIs to return data. We will see more about this format later, but for now, we can say that this output is called a **response**, and it contains **keys** and **values**. Keys are the names of the information we requested and values are the information we received. For instance, in this response, the url to the image of a Ragdoll cat can be found under the `url` key, and its value is `https://cdn2.thecatapi.com/images/XFhRpYS_D.jpg`.\n\n![JSON syntax](/static/imgs/JSON-syntax.png)\n\nNow, what we want to do is to get the image of the Ragdoll, not just the abstract information. To do this, we have to access the values associated with each key. The url to the image is under the `url` key, the name of the cat is under the `breeds` key and the description is under the `description` key. With a bit of coding, we can display the image of the cat:\n\n::: {#a7260912 .cell execution_count=2}\n\n::: {.cell-output .cell-output-display}\n![](what-is-an-api_files/figure-html/cell-3-output-1.png){width=554 height=384}\n:::\n:::\n\n\nCute, isn't it? \n\nWhat the API is doing, is to get the information from the server database, return it to the client in a format that can be easily parsed by a computer, and then the browser can use this information to display the cat image, or to get additional information about the cat. \n\n![A simple representation of an API (click to zoom)](/static/imgs/APIS.png)\n\nWith that information, we can display the information in a more readable format, and reutilize the method to get the image of other cats, for instance, a Bengal cat:\n\n::: {#ff40fbb0 .cell execution_count=3}\n\n::: {.cell-output .cell-output-display}\n![](what-is-an-api_files/figure-html/cell-4-output-1.png){width=566 height=384}\n:::\n:::\n\n\nYou can even get a random cat image!\n\n::: {#cat-container .cell-html}\n<script>\nwindow.getRandomCat = async function () {\n \n const response = await fetch(\"https://api.thecatapi.com/v1/images/search?size=med&mime_types=jpg&format=json&has_breeds=true&order=RANDOM&page=0&limit=1\");\n if (!response.ok) throw new Error(\"Failed to fetch random cat.\");\n const data = await response.json();\n \n\n const cat = data[0];\n\n const cat_id = cat.id;\n\n const cat_detailed_info = await fetch(`https://api.thecatapi.com/v1/images/${cat_id}`);\n const cat_detailed_info_json = await cat_detailed_info.json();\n\n // Safely access items that might be undefined or empty\n const breed = cat_detailed_info_json.breeds && cat_detailed_info_json.breeds.length > 0 ? cat_detailed_info_json.breeds[0].name : \"Unknown\";\n const description = cat_detailed_info_json.breeds && cat_detailed_info_json.breeds.length > 0 ? cat_detailed_info_json.breeds[0].description : \"Unknown\";\n\n document.getElementById(\"cat-image\").innerHTML = `\n <div class=\"card\" style=\"max-width: 300px; margin: 15px auto;\">\n <img src=\"${cat.url}\" class=\"card-img-top\" alt=\"Random Cat\">\n <div class=\"card-body\">\n <h5 class=\"card-title\">Breed: ${breed}</h5>\n <p class=\"card-text\">${description}</p>\n </div>\n </div>\n `;\n};\n\n</script>\n<button onclick=\"getRandomCat()\" class=\"btn btn-primary\" style=\"padding: 10px 20px; font-size: 16px; display: block; margin: 0 auto;\">Click here to get a random cat :)</button>\n<div id=\"cat-image\" style=\"margin-top: 15px;\"></div>\n:::\n\n<hr>\n\n::: {.callout-note collapse=\"false\"}\n## In summary\nAPIs provide access to structured data from a database without requiring knowledge of its underlying structure, and allow us to reformat the information, must be as a user friendly representation, or even translate that information to a tabular format.\n:::\n\n",
6+
"supporting": [
7+
"what-is-an-api_files"
8+
],
9+
"filters": [],
10+
"includes": {}
11+
}
12+
}
Loading
Loading

_freeze/site_libs/clipboard/clipboard.min.js

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

_freeze/site_libs/quarto-listing/list.min.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)