Skip to content

Commit b3ed960

Browse files
committed
Initial
0 parents  commit b3ed960

File tree

5 files changed

+152
-0
lines changed

5 files changed

+152
-0
lines changed

.github/workflows/pages.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Deploy to GitHub Pages
2+
on:
3+
push:
4+
branches: [ main ]
5+
workflow_dispatch:
6+
7+
permissions:
8+
contents: read
9+
pages: write
10+
id-token: write
11+
12+
concurrency:
13+
group: "pages"
14+
cancel-in-progress: true
15+
16+
jobs:
17+
deploy:
18+
environment:
19+
name: github-pages
20+
url: ${{ steps.deployment.outputs.page_url }}
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
26+
# No build: es sitio estático puro
27+
- name: Upload artifact
28+
uses: actions/upload-pages-artifact@v3
29+
with:
30+
path: .
31+
32+
- name: Deploy to GitHub Pages
33+
id: deployment
34+
uses: actions/deploy-pages@v4

.nojekyll

Whitespace-only changes.

index.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>GitHub Folder Downloader</title>
6+
<link rel="stylesheet" href="style.css">
7+
</head>
8+
<body>
9+
<div class="container">
10+
<h1>📁 GitHub Folder Downloader</h1>
11+
<p>Paste a GitHub folder URL to download it as a ZIP.</p>
12+
<input type="text" id="folderUrl" placeholder="https://github.com/user/repo/tree/branch/folder">
13+
<button id="downloadBtn">Download Folder</button>
14+
<div id="status"></div>
15+
</div>
16+
<script src="script.js"></script>
17+
</body>
18+
</html>

script.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
async function fetchFolderContents(repo, branch, path) {
2+
const apiUrl = `https://api.github.com/repos/${repo}/contents/${path}?ref=${branch}`;
3+
const res = await fetch(apiUrl);
4+
if (!res.ok) throw new Error(`Failed to fetch ${apiUrl}`);
5+
return res.json();
6+
}
7+
8+
async function downloadFolder(repo, branch, path) {
9+
const JSZip = window.JSZip;
10+
const zip = new JSZip();
11+
12+
async function addFilesToZip(folder, currentPath) {
13+
for (const file of folder) {
14+
if (file.type === 'file') {
15+
const content = await fetch(file.download_url).then(r => r.blob());
16+
zip.file(currentPath + file.name, content);
17+
} else if (file.type === 'dir') {
18+
const subFolder = await fetchFolderContents(repo, branch, file.path);
19+
await addFilesToZip(subFolder, currentPath + file.name + '/');
20+
}
21+
}
22+
}
23+
24+
const rootFolder = await fetchFolderContents(repo, branch, path);
25+
await addFilesToZip(rootFolder, '');
26+
27+
const blob = await zip.generateAsync({ type: "blob" });
28+
const a = document.createElement("a");
29+
a.href = URL.createObjectURL(blob);
30+
a.download = path.split('/').pop() + ".zip";
31+
a.click();
32+
}
33+
34+
function parseGitHubUrl(url) {
35+
const match = url.match(/github\.com\/([^\/]+\/[^\/]+)\/tree\/([^\/]+)\/(.+)/);
36+
if (!match) throw new Error("Invalid GitHub folder URL");
37+
return {
38+
repo: match[1],
39+
branch: match[2],
40+
path: match[3]
41+
};
42+
}
43+
44+
document.getElementById("downloadBtn").addEventListener("click", async () => {
45+
const url = document.getElementById("folderUrl").value.trim();
46+
const status = document.getElementById("status");
47+
status.textContent = "⏳ Downloading...";
48+
49+
try {
50+
const { repo, branch, path } = parseGitHubUrl(url);
51+
await downloadFolder(repo, branch, path);
52+
status.textContent = "✅ Download complete!";
53+
} catch (e) {
54+
console.error(e);
55+
status.textContent = "❌ " + e.message;
56+
}
57+
});
58+
59+
// Load JSZip
60+
const script = document.createElement("script");
61+
script.src = "https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js";
62+
document.head.appendChild(script);
63+

style.css

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
body {
2+
font-family: sans-serif;
3+
background: #f5f5f5;
4+
display: flex;
5+
justify-content: center;
6+
padding-top: 50px;
7+
}
8+
9+
.container {
10+
background: white;
11+
padding: 2em;
12+
border-radius: 10px;
13+
box-shadow: 0 0 20px rgba(0,0,0,0.1);
14+
text-align: center;
15+
max-width: 600px;
16+
width: 100%;
17+
}
18+
19+
input {
20+
width: 100%;
21+
padding: 0.8em;
22+
margin-top: 1em;
23+
font-size: 1em;
24+
}
25+
26+
button {
27+
margin-top: 1em;
28+
padding: 0.8em 2em;
29+
font-size: 1em;
30+
cursor: pointer;
31+
}
32+
33+
#status {
34+
margin-top: 1em;
35+
color: #444;
36+
}
37+

0 commit comments

Comments
 (0)