Initial commit

This commit is contained in:
2026-01-26 16:43:01 -05:00
commit 23cb27503e
39 changed files with 96557 additions and 0 deletions

142
code/bookmarklets/README.md Normal file
View File

@@ -0,0 +1,142 @@
# Bookmarklets
Browser-based JavaScript utilities that run with a single click from your bookmarks bar.
## 🚀 Creating a Bookmarklet
### 1. Write Your JavaScript
Create a new `.js` file in this directory with regular, readable JavaScript:
```javascript
/**
* My Awesome Bookmarklet
* Does something cool on any webpage
*/
// Your code here
const elements = document.querySelectorAll(".some-class");
elements.forEach((el) => {
// Do something
});
alert("Done!");
```
### 2. Generate the Bookmarklet
Run the generator:
```bash
npm run bookmarklet -- code/bookmarklets/your-file.js
```
The generator will:
- ✂️ Remove all comments
- 🗜️ Minify the code
- 📦 Wrap in bookmarklet format
- 📋 Copy to your clipboard
### 3. Install in Browser
1. Create a new bookmark (Cmd+D or Ctrl+D)
2. Paste the clipboard content as the URL
3. Name it and save
4. Click to use!
## 📚 Available Bookmarklets
### [highlight-links.js](highlight-links.js)
Highlights all links on a page in yellow and shows count.
**Generate:** `npm run bookmarklet -- code/bookmarklets/highlight-links.js`
### [example-bookmarklet.js](example-bookmarklet.js)
Example template showing basic structure.
## 💡 Tips
- **Test first**: Try your logic in the browser console before creating bookmarklet
- **Be browser-safe**: Stick to vanilla JS, avoid ES6+ features in production if supporting old browsers
- **Keep it simple**: Bookmarklets should be quick utilities, not full apps
- **Comment generously**: Comments are stripped out, so explain your code
- **Use descriptive names**: Variables and functions will be minified
## 🔧 Bookmarklet Generator
The generator ([code/utils/bookmarkletMaker.js](../utils/bookmarkletMaker.js)) handles:
- Comment removal (single-line `//` and multi-line `/* */`)
- Code minification (whitespace removal, single-line conversion)
- IIFE wrapping with `javascript:` protocol
- Clipboard copying
## 📝 Common Patterns
### Getting Page Info
```javascript
// Current URL
const url = window.location.href;
// Page title
const title = document.title;
// Selected text
const selected = window.getSelection().toString();
```
### Modifying the Page
```javascript
// Find elements
const elements = document.querySelectorAll(".selector");
// Style them
elements.forEach((el) => {
el.style.backgroundColor = "yellow";
});
// Add content
const div = document.createElement("div");
div.textContent = "Hello!";
document.body.appendChild(div);
```
### Opening New Windows
```javascript
// Open in new tab
window.open("https://example.com", "_blank");
// With specific size
window.open("https://example.com", "_blank", "width=800,height=600");
```
### Copying to Clipboard
```javascript
navigator.clipboard
.writeText("text to copy")
.then(() => alert("Copied!"))
.catch((err) => alert("Failed: " + err));
```
## 🐛 Debugging
If your bookmarklet doesn't work:
1. Open browser console (F12)
2. Paste your original code (without `javascript:` wrapper)
3. Debug errors
4. Update the source file
5. Regenerate bookmarklet
## 🔗 Resources
- [Bookmarklet Best Practices](https://en.wikipedia.org/wiki/Bookmarklet)
- [MDN: DOM API](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)
- [Browser Compatibility](https://caniuse.com/)

View File

@@ -0,0 +1,30 @@
/**
* Example Bookmarklet Template
*
* This is a template for creating browser bookmarklets.
* To use: Wrap in javascript: protocol and minify
*/
(function () {
"use strict";
// Example: Highlight all links on a page
const links = document.querySelectorAll("a");
links.forEach((link) => {
link.style.backgroundColor = "yellow";
link.style.padding = "2px";
});
// Show confirmation
alert(`Highlighted ${links.length} links!`);
})();
/**
* To convert to bookmarklet:
* 1. Minify the code
* 2. Wrap in: javascript:(function(){YOUR_MINIFIED_CODE})();
* 3. Add to browser bookmarks
*
* Example bookmarklet format:
* javascript:(function(){'use strict';const links=document.querySelectorAll('a');links.forEach(link=>{link.style.backgroundColor='yellow';});alert(`Highlighted ${links.length} links!`);})();
*/

View File

@@ -0,0 +1,23 @@
/**
* Highlight Links Bookmarklet
*
* Highlights all links on the current page with a yellow background
* and displays a count of total links found.
*
* Usage: Click the bookmarklet on any webpage
*/
// Find all anchor tags
const links = document.querySelectorAll("a");
// Style each link
links.forEach((link) => {
link.style.backgroundColor = "yellow";
link.style.padding = "2px 4px";
link.style.borderRadius = "3px";
});
// Show result
alert(
`Highlighted ${links.length} link${links.length !== 1 ? "s" : ""} on this page!`,
);

View File

@@ -0,0 +1,110 @@
/*
* This script extracts event data from a table on a webpage and generates an iCalendar (.ics) file for download.
* It looks for a table with specific headers ('event', 'date', 'venue', 'address'), parses the event details,
* and then creates an iCalendar file with the extracted event information. The file is then automatically
* downloaded to the user's device.
*/
javascript: (() => {
function extractEventData() {
let tables = document.querySelectorAll('table');
if (tables.length > 1) {
tables = [tables[0]];
}
const data = [];
tables.forEach(table => {
const headers = [];
const rows = table.querySelectorAll('tr');
const firstRow = rows[0];
firstRow.querySelectorAll('td').forEach(td => {
headers.push(td.textContent.trim().toLowerCase());
});
if (
headers.includes('event') &&
headers.includes('date') &&
headers.includes('venue') &&
headers.includes('address')
) {
Array.from(rows)
.slice(1)
.forEach(row => {
const cells = row.querySelectorAll('td');
const rowData = {};
cells.forEach((cell, j) => {
const header = headers[j];
let cellText = cell.innerHTML
.replace(/<br\s*\/?>/gi, ', ')
.trim();
cellText = cellText.replace(/<\/?[^>]+(>|$)/g, '').trim();
if (header === 'event') {
rowData.event = cellText;
} else if (header === 'date') {
const month = cellText.split(' ')[0];
const year = cellText.split(',')[1].trim();
const startDay = cellText
.split(' ')[1]
.split(cellText.includes(' ') ? ' ' : '')[0]
.trim();
const endDay = cellText
.split(cellText.includes(' ') ? ' ' : '')[1]
.split(',')[0]
.trim();
rowData.startDate = `${month} ${startDay}, ${year}`;
rowData.endDate = `${month} ${endDay}, ${year}`;
} else if (header === 'venue') {
rowData.venue = cellText;
} else if (header === 'location') {
rowData.address = cellText;
}
});
data.push(rowData);
});
}
});
console.log(data);
return data;
}
const data = extractEventData();
function createICal(events) {
let icalContent =
'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//FragginWagon//International-Championships\n';
events.forEach(event => {
icalContent += 'BEGIN:VEVENT\n';
icalContent += `DTSTART:${new Date(event.startDate).toISOString().replace(/[-:]/g, '').split('.')[0]}Z\n`;
icalContent += `DTEND:${new Date(event.endDate).toISOString().replace(/[-:]/g, '').split('.')[0]}Z\n`;
icalContent += `SUMMARY:${event.event} \n`;
icalContent += `LOCATION:${event.location}\n`;
icalContent += 'END:VEVENT\n';
});
icalContent += 'END:VCALENDAR';
return icalContent;
}
function downloadICal(content, filename) {
const blob = new Blob([content], { type: 'text/calendar' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
const newIcalContent = createICal(data);
downloadICal(
newIcalContent,
'play_pokemon_international_championships_events.ics'
);
})();

View File

@@ -0,0 +1,117 @@
/**
*
* This bookmarklet extracts event data from the first four tables on a webpage,
* specifically looking for tables that contain 'date', 'venue', and 'location' headers.
* It processes the event data to identify special events and formats the dates.
* The extracted data is then used to create an iCalendar (.ics) file, which is
* automatically downloaded to the user's device.
*
* Functions:
* - extractEventData: Extracts event data from the first four tables on the webpage.
* - createICal: Creates an iCalendar (.ics) content string from the extracted event data.
* - downloadICal: Initiates the download of the iCalendar (.ics) file with the given content and filename.
*/
javascript: (() => {
function extractEventData() {
let tables = document.querySelectorAll('table');
if (tables.length > 4) {
tables = Array.from(tables).slice(0, 4);
}
const data = [];
tables.forEach(table => {
const headers = [];
const rows = table.querySelectorAll('tr');
const firstRow = rows[0];
firstRow.querySelectorAll('td').forEach(td => {
headers.push(td.textContent.trim().toLowerCase());
});
if (
headers.includes('date') &&
headers.includes('venue') &&
headers.includes('location')
) {
Array.from(rows)
.slice(1)
.forEach(row => {
const cells = row.querySelectorAll('td');
const rowData = {};
if (
Array.from(cells).some(cell =>
cell.querySelector('span[style*="color: #2dc26b"]')
)
) {
rowData.specialEvent = true;
}
cells.forEach((cell, j) => {
const header = headers[j];
let cellText = cell.innerHTML.replace(/<br\s*\/?>/gi, ', ').trim();
cellText = cellText.replace(/<\/?[^>]+(>|$)/g, '').trim();
if (header === 'date') {
const month = cellText.split(' ')[0];
const year = cellText.split(',')[1].trim();
const startDay = cellText
.split(' ')[1]
.split(cellText.includes(' ') ? ' ' : '')[0]
.trim();
const endDay = cellText
.split(cellText.includes(' ') ? ' ' : '')[1]
.split(',')[0]
.trim();
rowData.startDate = `${month} ${startDay}, ${year}`;
rowData.endDate = `${month} ${endDay}, ${year}`;
} else if (header === 'venue') {
rowData.venue = cellText;
} else if (header === 'location') {
rowData.location = cellText;
}
});
data.push(rowData);
});
}
});
return data;
}
const data = extractEventData(tables);
function createICal(events) {
let icalContent =
'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//FragginWagon//P!P //Regional-Special-Championships\n';
events.forEach(event => {
icalContent += 'BEGIN:VEVENT\n';
icalContent += `DTSTART:${new Date(event.startDate).toISOString().replace(/[-:]/g, '').split('.')[0]}Z\n`;
icalContent += `DTEND:${new Date(event.endDate).toISOString().replace(/[-:]/g, '').split('.')[0]}Z\n`;
icalContent += `SUMMARY:${event.specialEvent ? 'Special Event' : 'Regional'} - ${event.venue} \n`;
icalContent += `LOCATION:${event.location}\n`;
icalContent += 'END:VEVENT\n';
});
icalContent += 'END:VCALENDAR';
return icalContent;
}
function downloadICal(content, filename) {
const blob = new Blob([content], { type: 'text/calendar' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
const newIcalContent = createICal(extractEventData());
downloadICal(newIcalContent, 'play_pokemon_regional_special_events.ics');
})();