Compare commits
2 commits
6c659fe1d0
...
bd1855a65e
Author | SHA1 | Date | |
---|---|---|---|
bd1855a65e | |||
ce869012ef |
73 changed files with 1390 additions and 794 deletions
1
.husky/pre-commit
Executable file
1
.husky/pre-commit
Executable file
|
@ -0,0 +1 @@
|
||||||
|
npx lint-staged
|
15
.prettierignore
Normal file
15
.prettierignore
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# output
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# deps
|
||||||
|
node_modules/
|
||||||
|
vendor/
|
||||||
|
|
||||||
|
# minified assets
|
||||||
|
*.min.js
|
||||||
|
*.min.css
|
||||||
|
*.bundle.js
|
||||||
|
*.bundle.css
|
||||||
|
|
||||||
|
# env
|
||||||
|
.env
|
14
.prettierrc
Normal file
14
.prettierrc
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"printWidth": 100,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"quoteProps": "as-needed",
|
||||||
|
"trailingComma": "none",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"arrowParens": "always",
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"proseWrap": "preserve",
|
||||||
|
"embeddedLanguageFormatting": "auto"
|
||||||
|
}
|
|
@ -12,15 +12,24 @@ import { runTasksMenu } from '../lib/tasks/index.js';
|
||||||
process.on('unhandledRejection', (err) => handleExitError(err, 'Unhandled rejection'));
|
process.on('unhandledRejection', (err) => handleExitError(err, 'Unhandled rejection'));
|
||||||
process.on('uncaughtException', (err) => handleExitError(err, 'Uncaught exception'));
|
process.on('uncaughtException', (err) => handleExitError(err, 'Uncaught exception'));
|
||||||
|
|
||||||
program.name('coryd').description('🪄 Handle tasks, run commands or jobs, download things and have fun.').version('3.2.5');
|
program
|
||||||
program.command('init').description('Initialize CLI and populate required config.').action(async () => {
|
.name('coryd')
|
||||||
|
.description('🪄 Handle tasks, run commands or jobs, download things and have fun.')
|
||||||
|
.version('3.2.5');
|
||||||
|
program
|
||||||
|
.command('init')
|
||||||
|
.description('Initialize CLI and populate required config.')
|
||||||
|
.action(async () => {
|
||||||
const { initConfig } = await import('../lib/config.js');
|
const { initConfig } = await import('../lib/config.js');
|
||||||
await initConfig();
|
await initConfig();
|
||||||
});
|
});
|
||||||
program.command('run [script]').description('Run site scripts and commands.').action(runRootScript);
|
program.command('run [script]').description('Run site scripts and commands.').action(runRootScript);
|
||||||
program.command('tasks').description('Handle repeated tasks.').action(runTasksMenu);
|
program.command('tasks').description('Handle repeated tasks.').action(runTasksMenu);
|
||||||
program.command('jobs').description('Trigger jobs and scripts.').action(runJobsMenu);
|
program.command('jobs').description('Trigger jobs and scripts.').action(runJobsMenu);
|
||||||
program.command('download').description('Download, name and store image assets.').action(async () => {
|
program
|
||||||
|
.command('download')
|
||||||
|
.description('Download, name and store image assets.')
|
||||||
|
.action(async () => {
|
||||||
const { downloadAsset } = await import('../lib/download.js');
|
const { downloadAsset } = await import('../lib/download.js');
|
||||||
await downloadAsset();
|
await downloadAsset();
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,42 +14,50 @@ const ASSET_TYPES = ['poster', 'backdrop'];
|
||||||
dotenv.config({ path: path.resolve(__dirname, '..', '..', '.env') });
|
dotenv.config({ path: path.resolve(__dirname, '..', '..', '.env') });
|
||||||
|
|
||||||
export const initConfig = async () => {
|
export const initConfig = async () => {
|
||||||
const existingConfig = await fs.pathExists(CONFIG_PATH) ? await fs.readJson(CONFIG_PATH) : {};
|
const existingConfig = (await fs.pathExists(CONFIG_PATH)) ? await fs.readJson(CONFIG_PATH) : {};
|
||||||
const config = { ...existingConfig };
|
const config = { ...existingConfig };
|
||||||
|
|
||||||
if (config.storageDir) {
|
if (config.storageDir) {
|
||||||
const { updateStorage } = await inquirer.prompt([{
|
const { updateStorage } = await inquirer.prompt([
|
||||||
|
{
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
name: 'updateStorage',
|
name: 'updateStorage',
|
||||||
message: `Storage directory is already set to "${config.storageDir}". Do you want to update it?`,
|
message: `Storage directory is already set to "${config.storageDir}". Do you want to update it?`,
|
||||||
default: false
|
default: false
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
if (updateStorage) {
|
if (updateStorage) {
|
||||||
const { storageDir } = await inquirer.prompt([{
|
const { storageDir } = await inquirer.prompt([
|
||||||
|
{
|
||||||
name: 'storageDir',
|
name: 'storageDir',
|
||||||
message: 'Where is your storage root directory?',
|
message: 'Where is your storage root directory?',
|
||||||
validate: fs.pathExists
|
validate: fs.pathExists
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
config.storageDir = storageDir;
|
config.storageDir = storageDir;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const { storageDir } = await inquirer.prompt([{
|
const { storageDir } = await inquirer.prompt([
|
||||||
|
{
|
||||||
name: 'storageDir',
|
name: 'storageDir',
|
||||||
message: 'Where is your storage root directory?',
|
message: 'Where is your storage root directory?',
|
||||||
validate: fs.pathExists
|
validate: fs.pathExists
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
config.storageDir = storageDir;
|
config.storageDir = storageDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { customize } = await inquirer.prompt([{
|
const { customize } = await inquirer.prompt([
|
||||||
|
{
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
name: 'customize',
|
name: 'customize',
|
||||||
message: 'Do you want to customize default media paths?',
|
message: 'Do you want to customize default media paths?',
|
||||||
default: false
|
default: false
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
config.mediaPaths = {};
|
config.mediaPaths = {};
|
||||||
|
|
||||||
|
@ -63,11 +71,13 @@ export const initConfig = async () => {
|
||||||
let subpath = defaultPath;
|
let subpath = defaultPath;
|
||||||
|
|
||||||
if (customize) {
|
if (customize) {
|
||||||
const response = await inquirer.prompt([{
|
const response = await inquirer.prompt([
|
||||||
|
{
|
||||||
name: 'subpath',
|
name: 'subpath',
|
||||||
message: `Subpath for ${mediaType}/${assetType} (relative to storage root):`,
|
message: `Subpath for ${mediaType}/${assetType} (relative to storage root):`,
|
||||||
default: defaultPath
|
default: defaultPath
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
subpath = response.subpath;
|
subpath = response.subpath;
|
||||||
}
|
}
|
||||||
|
@ -113,28 +123,34 @@ export const initConfig = async () => {
|
||||||
: 'Media assets/books';
|
: 'Media assets/books';
|
||||||
|
|
||||||
if (config.directus?.apiUrl) {
|
if (config.directus?.apiUrl) {
|
||||||
const { updateApiUrl } = await inquirer.prompt([{
|
const { updateApiUrl } = await inquirer.prompt([
|
||||||
|
{
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
name: 'updateApiUrl',
|
name: 'updateApiUrl',
|
||||||
message: `Directus API URL is already set to "${config.directus.apiUrl}". Do you want to update it?`,
|
message: `Directus API URL is already set to "${config.directus.apiUrl}". Do you want to update it?`,
|
||||||
default: false
|
default: false
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
if (updateApiUrl) {
|
if (updateApiUrl) {
|
||||||
const { apiUrl } = await inquirer.prompt([{
|
const { apiUrl } = await inquirer.prompt([
|
||||||
|
{
|
||||||
name: 'apiUrl',
|
name: 'apiUrl',
|
||||||
message: 'Enter your Directus instance URL:',
|
message: 'Enter your Directus instance URL:',
|
||||||
validate: input => input.startsWith('http') || 'Must be a valid URL'
|
validate: (input) => input.startsWith('http') || 'Must be a valid URL'
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
config.directus.apiUrl = apiUrl;
|
config.directus.apiUrl = apiUrl;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const { apiUrl } = await inquirer.prompt([{
|
const { apiUrl } = await inquirer.prompt([
|
||||||
|
{
|
||||||
name: 'apiUrl',
|
name: 'apiUrl',
|
||||||
message: 'Enter your Directus URL:',
|
message: 'Enter your Directus URL:',
|
||||||
validate: input => input.startsWith('http') || 'Must be a valid URL'
|
validate: (input) => input.startsWith('http') || 'Must be a valid URL'
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
config.directus = { ...(config.directus || {}), apiUrl };
|
config.directus = { ...(config.directus || {}), apiUrl };
|
||||||
}
|
}
|
||||||
|
@ -150,7 +166,7 @@ export const initConfig = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const loadConfig = async () => {
|
export const loadConfig = async () => {
|
||||||
if (!await fs.pathExists(CONFIG_PATH)) {
|
if (!(await fs.pathExists(CONFIG_PATH))) {
|
||||||
console.error('❌ Config not found. Run `coryd init` first.');
|
console.error('❌ Config not found. Run `coryd init` first.');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,9 @@ const request = async (method, endpoint, body = null) => {
|
||||||
method,
|
method,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${API_TOKEN}`,
|
Authorization: `Bearer ${API_TOKEN}`
|
||||||
},
|
},
|
||||||
body: body ? JSON.stringify(body) : null,
|
body: body ? JSON.stringify(body) : null
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
@ -63,8 +63,8 @@ export const searchItems = async (collection, query = '', filters = {}) => {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${API_TOKEN}`,
|
Authorization: `Bearer ${API_TOKEN}`
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ export const searchItems = async (collection, query = '', filters = {}) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateItem = async (collection, id, values) => await request('PATCH', `${collection}/${id}`, values);
|
export const updateItem = async (collection, id, values) =>
|
||||||
|
await request('PATCH', `${collection}/${id}`, values);
|
||||||
|
|
||||||
export const createItem = async (collection, values) => await request('POST', collection, values);
|
export const createItem = async (collection, values) => await request('POST', collection, values);
|
||||||
|
|
|
@ -25,13 +25,13 @@ export const promptForMultipleRelations = async (collection, label = collection)
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
name: 'selected',
|
name: 'selected',
|
||||||
message: `✔ Select ${label} to add:`,
|
message: `✔ Select ${label} to add:`,
|
||||||
choices: results.map(item => ({
|
choices: results.map((item) => ({
|
||||||
name: item.name || item.title || item.id,
|
name: item.name || item.title || item.id,
|
||||||
value: item.id
|
value: item.id
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
|
|
||||||
selected.forEach(id => selectedIds.add(id));
|
selected.forEach((id) => selectedIds.add(id));
|
||||||
|
|
||||||
const { again } = await inquirer.prompt({
|
const { again } = await inquirer.prompt({
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
|
|
|
@ -7,17 +7,22 @@ import { loadConfig } from './config.js';
|
||||||
import { sanitizeMediaString } from './sanitize.js';
|
import { sanitizeMediaString } from './sanitize.js';
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
const downloadImage = (url, dest) => new Promise((resolve, reject) => {
|
const downloadImage = (url, dest) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
const file = fs.createWriteStream(dest);
|
const file = fs.createWriteStream(dest);
|
||||||
|
|
||||||
https.get(url, response => {
|
https
|
||||||
if (response.statusCode !== 200) return reject(new Error(`Failed to download. Status: ${response.statusCode}`));
|
.get(url, (response) => {
|
||||||
|
if (response.statusCode !== 200)
|
||||||
|
return reject(new Error(`Failed to download. Status: ${response.statusCode}`));
|
||||||
|
|
||||||
response.pipe(file);
|
response.pipe(file);
|
||||||
file.on('finish', () => file.close(resolve));
|
file.on('finish', () => file.close(resolve));
|
||||||
}).on('error', reject);
|
})
|
||||||
|
.on('error', reject);
|
||||||
});
|
});
|
||||||
const isValidTMDBUrl = (val) => /^https:\/\/image\.tmdb\.org\/t\/p\//.test(val) || '❌ Must be a valid TMDB image url';
|
const isValidTMDBUrl = (val) =>
|
||||||
|
/^https:\/\/image\.tmdb\.org\/t\/p\//.test(val) || '❌ Must be a valid TMDB image url';
|
||||||
const overwriteImageDownloadPrompt = async (url, finalPath, fileName) => {
|
const overwriteImageDownloadPrompt = async (url, finalPath, fileName) => {
|
||||||
await fs.ensureDir(path.dirname(finalPath));
|
await fs.ensureDir(path.dirname(finalPath));
|
||||||
|
|
||||||
|
@ -60,7 +65,8 @@ export const downloadWatchingImages = async () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { posterUrl, backdropUrl } = await inquirer.prompt([{
|
const { posterUrl, backdropUrl } = await inquirer.prompt([
|
||||||
|
{
|
||||||
name: 'posterUrl',
|
name: 'posterUrl',
|
||||||
message: 'Enter the poster url:',
|
message: 'Enter the poster url:',
|
||||||
validate: (val) => {
|
validate: (val) => {
|
||||||
|
@ -77,8 +83,12 @@ export const downloadWatchingImages = async () => {
|
||||||
|
|
||||||
return isValidTMDBUrl(val);
|
return isValidTMDBUrl(val);
|
||||||
}
|
}
|
||||||
}]);
|
}
|
||||||
const types = [{ type: 'poster', url: posterUrl }, { type: 'backdrop', url: backdropUrl }];
|
]);
|
||||||
|
const types = [
|
||||||
|
{ type: 'poster', url: posterUrl },
|
||||||
|
{ type: 'backdrop', url: backdropUrl }
|
||||||
|
];
|
||||||
|
|
||||||
for (const { type, url } of types) {
|
for (const { type, url } of types) {
|
||||||
if (!url) continue;
|
if (!url) continue;
|
||||||
|
@ -98,7 +108,7 @@ export const downloadWatchingImages = async () => {
|
||||||
|
|
||||||
await overwriteImageDownloadPrompt(url, finalPath, fileName);
|
await overwriteImageDownloadPrompt(url, finalPath, fileName);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const downloadArtistImage = async () => {
|
export const downloadArtistImage = async () => {
|
||||||
const config = await loadConfig();
|
const config = await loadConfig();
|
||||||
|
@ -134,7 +144,7 @@ export const downloadArtistImage = async () => {
|
||||||
const finalPath = path.join(targetDir, fileName);
|
const finalPath = path.join(targetDir, fileName);
|
||||||
|
|
||||||
await overwriteImageDownloadPrompt(imageUrl, finalPath, fileName);
|
await overwriteImageDownloadPrompt(imageUrl, finalPath, fileName);
|
||||||
}
|
};
|
||||||
|
|
||||||
export const downloadAlbumImage = async () => {
|
export const downloadAlbumImage = async () => {
|
||||||
const config = await loadConfig();
|
const config = await loadConfig();
|
||||||
|
@ -190,7 +200,8 @@ export const downloadBookImage = async () => {
|
||||||
const { isbn } = await inquirer.prompt({
|
const { isbn } = await inquirer.prompt({
|
||||||
name: 'isbn',
|
name: 'isbn',
|
||||||
message: 'Enter the ISBN (no spaces):',
|
message: 'Enter the ISBN (no spaces):',
|
||||||
validate: (val) => /^[a-zA-Z0-9-]+$/.test(val) || 'ISBN must contain only letters, numbers, or hyphens'
|
validate: (val) =>
|
||||||
|
/^[a-zA-Z0-9-]+$/.test(val) || 'ISBN must contain only letters, numbers, or hyphens'
|
||||||
});
|
});
|
||||||
const { bookTitle } = await inquirer.prompt({
|
const { bookTitle } = await inquirer.prompt({
|
||||||
name: 'bookTitle',
|
name: 'bookTitle',
|
||||||
|
@ -223,8 +234,7 @@ export const downloadBookImage = async () => {
|
||||||
const finalPath = path.join(targetDir, fileName);
|
const finalPath = path.join(targetDir, fileName);
|
||||||
|
|
||||||
await overwriteImageDownloadPrompt(imageUrl, finalPath, fileName);
|
await overwriteImageDownloadPrompt(imageUrl, finalPath, fileName);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
export const downloadAsset = async () => {
|
export const downloadAsset = async () => {
|
||||||
const { type } = await inquirer.prompt({
|
const { type } = await inquirer.prompt({
|
||||||
|
@ -243,4 +253,4 @@ export const downloadAsset = async () => {
|
||||||
} else {
|
} else {
|
||||||
await downloadWatchingImages();
|
await downloadWatchingImages();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
export const handleExitError = (err, type = 'Unhandled error') => {
|
export const handleExitError = (err, type = 'Unhandled error') => {
|
||||||
const isExit = err?.name === 'ExitPromptError' || err?.code === 'ERR_CANCELED' || err?.message?.includes('SIGINT');
|
const isExit =
|
||||||
|
err?.name === 'ExitPromptError' ||
|
||||||
|
err?.code === 'ERR_CANCELED' ||
|
||||||
|
err?.message?.includes('SIGINT');
|
||||||
|
|
||||||
if (isExit) {
|
if (isExit) {
|
||||||
console.log('\n👋 Exiting. Cya!\n');
|
console.log('\n👋 Exiting. Cya!\n');
|
||||||
|
@ -8,4 +11,4 @@ export const handleExitError = (err, type = 'Unhandled error') => {
|
||||||
|
|
||||||
console.error(`❌ ${type}:`, err);
|
console.error(`❌ ${type}:`, err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
};
|
||||||
|
|
|
@ -45,12 +45,14 @@ export const runJobsMenu = async () => {
|
||||||
apiUrl: `${config.url}/api/artist-import.php`,
|
apiUrl: `${config.url}/api/artist-import.php`,
|
||||||
tokenEnvVar: 'ARTIST_IMPORT_TOKEN',
|
tokenEnvVar: 'ARTIST_IMPORT_TOKEN',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
paramsPrompt: [{
|
paramsPrompt: [
|
||||||
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'artistId',
|
name: 'artistId',
|
||||||
message: 'Enter the Navidrome artist ID:',
|
message: 'Enter the Navidrome artist ID:',
|
||||||
validate: input => input ? true : 'Artist ID is required'
|
validate: (input) => (input ? true : 'Artist ID is required')
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '📖 Import book',
|
name: '📖 Import book',
|
||||||
|
@ -58,12 +60,14 @@ export const runJobsMenu = async () => {
|
||||||
apiUrl: `${config.url}/api/book-import.php`,
|
apiUrl: `${config.url}/api/book-import.php`,
|
||||||
tokenEnvVar: 'BOOK_IMPORT_TOKEN',
|
tokenEnvVar: 'BOOK_IMPORT_TOKEN',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
paramsPrompt: [{
|
paramsPrompt: [
|
||||||
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'isbn',
|
name: 'isbn',
|
||||||
message: 'Enter the book\'s ISBN:',
|
message: "Enter the book's ISBN:",
|
||||||
validate: input => input ? true : 'ISBN is required'
|
validate: (input) => (input ? true : 'ISBN is required')
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '📽 Import movie or show',
|
name: '📽 Import movie or show',
|
||||||
|
@ -72,19 +76,20 @@ export const runJobsMenu = async () => {
|
||||||
tokenEnvVar: 'WATCHING_IMPORT_TOKEN',
|
tokenEnvVar: 'WATCHING_IMPORT_TOKEN',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
tokenIncludeInParams: true,
|
tokenIncludeInParams: true,
|
||||||
paramsPrompt: [{
|
paramsPrompt: [
|
||||||
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'tmdb_id',
|
name: 'tmdb_id',
|
||||||
message: 'Enter the TMDB ID:',
|
message: 'Enter the TMDB ID:',
|
||||||
validate: (input) =>
|
validate: (input) => (/^\d+$/.test(input) ? true : 'Please enter a valid TMDB ID')
|
||||||
/^\d+$/.test(input) ? true : 'Please enter a valid TMDB ID'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'media_type',
|
name: 'media_type',
|
||||||
message: 'Is this a movie or a show?',
|
message: 'Is this a movie or a show?',
|
||||||
choices: ['movie', 'show']
|
choices: ['movie', 'show']
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '📺 Import upcoming TV seasons',
|
name: '📺 Import upcoming TV seasons',
|
||||||
|
@ -92,9 +97,11 @@ export const runJobsMenu = async () => {
|
||||||
apiUrl: `${config.url}/api/seasons-import.php`,
|
apiUrl: `${config.url}/api/seasons-import.php`,
|
||||||
tokenEnvVar: 'SEASONS_IMPORT_TOKEN',
|
tokenEnvVar: 'SEASONS_IMPORT_TOKEN',
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
const { selectedJob } = await inquirer.prompt([{
|
const { selectedJob } = await inquirer.prompt([
|
||||||
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'selectedJob',
|
name: 'selectedJob',
|
||||||
message: 'Select a job to run:',
|
message: 'Select a job to run:',
|
||||||
|
@ -102,7 +109,8 @@ export const runJobsMenu = async () => {
|
||||||
name: job.name,
|
name: job.name,
|
||||||
value: index
|
value: index
|
||||||
}))
|
}))
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
const job = JOBS[selectedJob];
|
const job = JOBS[selectedJob];
|
||||||
|
|
||||||
|
@ -124,7 +132,7 @@ export const runJobsMenu = async () => {
|
||||||
|
|
||||||
const runCurl = async ({
|
const runCurl = async ({
|
||||||
urlEnvVar,
|
urlEnvVar,
|
||||||
apiUrl = "",
|
apiUrl = '',
|
||||||
tokenEnvVar,
|
tokenEnvVar,
|
||||||
method = 'POST',
|
method = 'POST',
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -15,12 +15,14 @@ export const runRootScript = async (scriptArg) => {
|
||||||
let script = scriptArg;
|
let script = scriptArg;
|
||||||
|
|
||||||
if (!script) {
|
if (!script) {
|
||||||
const { selected } = await inquirer.prompt([{
|
const { selected } = await inquirer.prompt([
|
||||||
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'selected',
|
name: 'selected',
|
||||||
message: 'Select a script to run:',
|
message: 'Select a script to run:',
|
||||||
choices: Object.keys(scripts)
|
choices: Object.keys(scripts)
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
script = selected;
|
script = selected;
|
||||||
}
|
}
|
||||||
|
@ -39,4 +41,4 @@ export const runRootScript = async (scriptArg) => {
|
||||||
console.error(`❌ Failed to run script "${script}"`);
|
console.error(`❌ Failed to run script "${script}"`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -6,6 +6,6 @@ export const sanitizeMediaString = (input) => {
|
||||||
const slugified = cleaned.replace(/[\s-]+/g, '-').toLowerCase();
|
const slugified = cleaned.replace(/[\s-]+/g, '-').toLowerCase();
|
||||||
|
|
||||||
return slugified.replace(/^-+|-+$/g, '');
|
return slugified.replace(/^-+|-+$/g, '');
|
||||||
}
|
};
|
||||||
|
|
||||||
export const removeUrlProtocol = (url) => url ? url.replace(/^https?:\/\//, '') : '';
|
export const removeUrlProtocol = (url) => (url ? url.replace(/^https?:\/\//, '') : '');
|
||||||
|
|
|
@ -8,7 +8,7 @@ export const addBlockedRobot = async () => {
|
||||||
initDirectusClient(config);
|
initDirectusClient(config);
|
||||||
|
|
||||||
const robots = await searchItems('robots', '/');
|
const robots = await searchItems('robots', '/');
|
||||||
let rootRobot = robots.find(r => r.path === '/');
|
let rootRobot = robots.find((r) => r.path === '/');
|
||||||
|
|
||||||
if (!rootRobot) {
|
if (!rootRobot) {
|
||||||
console.log('ℹ️ No robots entry for `/` found. Creating one...');
|
console.log('ℹ️ No robots entry for `/` found. Creating one...');
|
||||||
|
@ -23,7 +23,7 @@ export const addBlockedRobot = async () => {
|
||||||
const { userAgent } = await inquirer.prompt({
|
const { userAgent } = await inquirer.prompt({
|
||||||
name: 'userAgent',
|
name: 'userAgent',
|
||||||
message: '🤖 Enter the user-agent string to block:',
|
message: '🤖 Enter the user-agent string to block:',
|
||||||
validate: input => !!input || 'User-agent cannot be empty'
|
validate: (input) => !!input || 'User-agent cannot be empty'
|
||||||
});
|
});
|
||||||
|
|
||||||
const createdAgent = await createItem('user_agents', {
|
const createdAgent = await createItem('user_agents', {
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import inquirer from 'inquirer';
|
import inquirer from 'inquirer';
|
||||||
import { loadConfig } from '../config.js';
|
import { loadConfig } from '../config.js';
|
||||||
import { initDirectusClient, getDirectusClient, searchItems, createItem, updateItem } from '../directus/client.js';
|
import {
|
||||||
|
initDirectusClient,
|
||||||
|
getDirectusClient,
|
||||||
|
searchItems,
|
||||||
|
createItem,
|
||||||
|
updateItem
|
||||||
|
} from '../directus/client.js';
|
||||||
|
|
||||||
export const addEpisodeToShow = async () => {
|
export const addEpisodeToShow = async () => {
|
||||||
const config = await loadConfig();
|
const config = await loadConfig();
|
||||||
|
@ -10,7 +16,7 @@ export const addEpisodeToShow = async () => {
|
||||||
const directus = getDirectusClient();
|
const directus = getDirectusClient();
|
||||||
const showResults = await inquirer.prompt({
|
const showResults = await inquirer.prompt({
|
||||||
name: 'query',
|
name: 'query',
|
||||||
message: 'Search for a show:',
|
message: 'Search for a show:'
|
||||||
});
|
});
|
||||||
const matches = await searchItems('shows', showResults.query);
|
const matches = await searchItems('shows', showResults.query);
|
||||||
|
|
||||||
|
@ -24,31 +30,32 @@ export const addEpisodeToShow = async () => {
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'showId',
|
name: 'showId',
|
||||||
message: 'Select a show:',
|
message: 'Select a show:',
|
||||||
choices: matches.map(s => ({
|
choices: matches.map((s) => ({
|
||||||
name: s.title || s.name || s.id,
|
name: s.title || s.name || s.id,
|
||||||
value: s.id,
|
value: s.id
|
||||||
})),
|
}))
|
||||||
});
|
});
|
||||||
const { season_number, episode_number, plays } = await inquirer.prompt([
|
const { season_number, episode_number, plays } = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
name: 'season_number',
|
name: 'season_number',
|
||||||
message: 'Season number:',
|
message: 'Season number:',
|
||||||
validate: val => !isNaN(val),
|
validate: (val) => !isNaN(val)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'episode_number',
|
name: 'episode_number',
|
||||||
message: 'Episode number:',
|
message: 'Episode number:',
|
||||||
validate: val => !isNaN(val),
|
validate: (val) => !isNaN(val)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'plays',
|
name: 'plays',
|
||||||
message: 'Play count:',
|
message: 'Play count:',
|
||||||
default: 0,
|
default: 0,
|
||||||
validate: val => !isNaN(val),
|
validate: (val) => !isNaN(val)
|
||||||
},
|
}
|
||||||
]);
|
]);
|
||||||
const existing = await searchItems('episodes', `${season_number} ${episode_number}`);
|
const existing = await searchItems('episodes', `${season_number} ${episode_number}`);
|
||||||
const match = existing.find(e =>
|
const match = existing.find(
|
||||||
|
(e) =>
|
||||||
Number(e.season_number) === Number(season_number) &&
|
Number(e.season_number) === Number(season_number) &&
|
||||||
Number(e.episode_number) === Number(episode_number) &&
|
Number(e.episode_number) === Number(episode_number) &&
|
||||||
e.show === showId
|
e.show === showId
|
||||||
|
@ -59,7 +66,7 @@ export const addEpisodeToShow = async () => {
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
name: 'update',
|
name: 'update',
|
||||||
message: `Episode exists. Update play count from ${match.plays ?? 0} to ${plays}?`,
|
message: `Episode exists. Update play count from ${match.plays ?? 0} to ${plays}?`,
|
||||||
default: true,
|
default: true
|
||||||
});
|
});
|
||||||
|
|
||||||
if (update) {
|
if (update) {
|
||||||
|
@ -74,7 +81,7 @@ export const addEpisodeToShow = async () => {
|
||||||
season_number: Number(season_number),
|
season_number: Number(season_number),
|
||||||
episode_number: Number(episode_number),
|
episode_number: Number(episode_number),
|
||||||
plays: Number(plays),
|
plays: Number(plays),
|
||||||
show: showId,
|
show: showId
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`📺 Created episode S${season_number}E${episode_number}`);
|
console.log(`📺 Created episode S${season_number}E${episode_number}`);
|
||||||
|
|
|
@ -12,12 +12,12 @@ export const addLinkToShare = async () => {
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
message: '📝 Title for the link:',
|
message: '📝 Title for the link:',
|
||||||
validate: input => !!input || 'Title is required'
|
validate: (input) => !!input || 'Title is required'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'link',
|
name: 'link',
|
||||||
message: '🔗 URL to share:',
|
message: '🔗 URL to share:',
|
||||||
validate: input => input.startsWith('http') || 'Must be a valid URL'
|
validate: (input) => input.startsWith('http') || 'Must be a valid URL'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'description',
|
name: 'description',
|
||||||
|
@ -26,7 +26,7 @@ export const addLinkToShare = async () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'authorQuery',
|
name: 'authorQuery',
|
||||||
message: '👤 Search for an author:',
|
message: '👤 Search for an author:'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -38,13 +38,17 @@ export const addLinkToShare = async () => {
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
name: 'shouldCreate',
|
name: 'shouldCreate',
|
||||||
message: '❌ No authors found. Do you want to create a new one?',
|
message: '❌ No authors found. Do you want to create a new one?',
|
||||||
default: true,
|
default: true
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!shouldCreate) return;
|
if (!shouldCreate) return;
|
||||||
|
|
||||||
const { name, url, mastodon, rss, json, newsletter, blogroll } = await inquirer.prompt([
|
const { name, url, mastodon, rss, json, newsletter, blogroll } = await inquirer.prompt([
|
||||||
{ name: 'name', message: '👤 Author name:', validate: input => !!input || 'Name is required' },
|
{
|
||||||
|
name: 'name',
|
||||||
|
message: '👤 Author name:',
|
||||||
|
validate: (input) => !!input || 'Name is required'
|
||||||
|
},
|
||||||
{ name: 'url', message: '🔗 URL (optional):', default: '' },
|
{ name: 'url', message: '🔗 URL (optional):', default: '' },
|
||||||
{ name: 'mastodon', message: '🐘 Mastodon handle (optional):', default: '' },
|
{ name: 'mastodon', message: '🐘 Mastodon handle (optional):', default: '' },
|
||||||
{ name: 'rss', message: '📡 RSS feed (optional):', default: '' },
|
{ name: 'rss', message: '📡 RSS feed (optional):', default: '' },
|
||||||
|
@ -69,13 +73,13 @@ export const addLinkToShare = async () => {
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'author',
|
name: 'author',
|
||||||
message: 'Select an author:',
|
message: 'Select an author:',
|
||||||
choices: authorMatches.map(a => {
|
choices: authorMatches.map((a) => {
|
||||||
const cleanUrl = removeUrlProtocol(a.url);
|
const cleanUrl = removeUrlProtocol(a.url);
|
||||||
const display = cleanUrl ? `${a.name} (${cleanUrl})` : a.name;
|
const display = cleanUrl ? `${a.name} (${cleanUrl})` : a.name;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: display,
|
name: display,
|
||||||
value: a.id,
|
value: a.id
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -88,7 +92,7 @@ export const addLinkToShare = async () => {
|
||||||
while (true) {
|
while (true) {
|
||||||
const { query } = await inquirer.prompt({
|
const { query } = await inquirer.prompt({
|
||||||
name: 'query',
|
name: 'query',
|
||||||
message: '🏷 Search for tags (or leave blank to finish):',
|
message: '🏷 Search for tags (or leave blank to finish):'
|
||||||
});
|
});
|
||||||
|
|
||||||
const trimmedQuery = query.trim();
|
const trimmedQuery = query.trim();
|
||||||
|
@ -106,7 +110,7 @@ export const addLinkToShare = async () => {
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
name: 'selected',
|
name: 'selected',
|
||||||
message: '✔ Select tags to add:',
|
message: '✔ Select tags to add:',
|
||||||
choices: tags.map(tag => ({ name: tag.name, value: tag.id }))
|
choices: tags.map((tag) => ({ name: tag.name, value: tag.id }))
|
||||||
});
|
});
|
||||||
|
|
||||||
tagIds.push(...selected);
|
tagIds.push(...selected);
|
||||||
|
@ -115,7 +119,7 @@ export const addLinkToShare = async () => {
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
name: 'again',
|
name: 'again',
|
||||||
message: 'Search and select more tags?',
|
message: 'Search and select more tags?',
|
||||||
default: false,
|
default: false
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!again) break;
|
if (!again) break;
|
||||||
|
@ -126,7 +130,7 @@ export const addLinkToShare = async () => {
|
||||||
link,
|
link,
|
||||||
description,
|
description,
|
||||||
author,
|
author,
|
||||||
link_tags: tagIds.map(tagId => ({ tags_id: tagId })),
|
link_tags: tagIds.map((tagId) => ({ tags_id: tagId })),
|
||||||
date: new Date().toISOString()
|
date: new Date().toISOString()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,11 @@ export const addPost = async () => {
|
||||||
|
|
||||||
initDirectusClient(config);
|
initDirectusClient(config);
|
||||||
|
|
||||||
const { title, description, content, featured } = await inquirer.prompt([{
|
const { title, description, content, featured } = await inquirer.prompt([
|
||||||
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
message: '📝 Title:',
|
message: '📝 Title:',
|
||||||
validate: input => !!input || 'Title is required'
|
validate: (input) => !!input || 'Title is required'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'description',
|
name: 'description',
|
||||||
|
@ -38,14 +39,15 @@ export const addPost = async () => {
|
||||||
name: 'featured',
|
name: 'featured',
|
||||||
message: '⭐ Featured?',
|
message: '⭐ Featured?',
|
||||||
default: false
|
default: false
|
||||||
}]);
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
let tagIds = [];
|
let tagIds = [];
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const { query } = await inquirer.prompt({
|
const { query } = await inquirer.prompt({
|
||||||
name: 'query',
|
name: 'query',
|
||||||
message: '🏷 Search for tags (or leave blank to finish):',
|
message: '🏷 Search for tags (or leave blank to finish):'
|
||||||
});
|
});
|
||||||
const trimmedQuery = query.trim();
|
const trimmedQuery = query.trim();
|
||||||
|
|
||||||
|
@ -63,7 +65,7 @@ export const addPost = async () => {
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
name: 'selected',
|
name: 'selected',
|
||||||
message: '✔ Select tags to add:',
|
message: '✔ Select tags to add:',
|
||||||
choices: tags.map(tag => ({ name: tag.name, value: tag.id }))
|
choices: tags.map((tag) => ({ name: tag.name, value: tag.id }))
|
||||||
});
|
});
|
||||||
|
|
||||||
tagIds.push(...selected);
|
tagIds.push(...selected);
|
||||||
|
@ -72,7 +74,7 @@ export const addPost = async () => {
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
name: 'again',
|
name: 'again',
|
||||||
message: 'Search and select more tags?',
|
message: 'Search and select more tags?',
|
||||||
default: false,
|
default: false
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!again) break;
|
if (!again) break;
|
||||||
|
@ -113,7 +115,7 @@ export const addPost = async () => {
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'itemId',
|
name: 'itemId',
|
||||||
message: `Select an item from ${collection}:`,
|
message: `Select an item from ${collection}:`,
|
||||||
choices: results.map(item => ({
|
choices: results.map((item) => ({
|
||||||
name: item.title || item.name || item.id,
|
name: item.title || item.name || item.id,
|
||||||
value: item.id
|
value: item.id
|
||||||
}))
|
}))
|
||||||
|
@ -161,13 +163,16 @@ export const addPost = async () => {
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
name: 'selected',
|
name: 'selected',
|
||||||
message: `✔ Select ${mediaType} to associate:`,
|
message: `✔ Select ${mediaType} to associate:`,
|
||||||
choices: matches.map(m => ({
|
choices: matches.map((m) => ({
|
||||||
name: m.name_string || m.title || m.name || m.label || m.id,
|
name: m.name_string || m.title || m.name || m.label || m.id,
|
||||||
value: m.id
|
value: m.id
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
|
|
||||||
if (selected.length) associatedMediaPayload[`${mediaType}`] = selected.map(id => ({ [`${mediaType}_id`]: id }));
|
if (selected.length)
|
||||||
|
associatedMediaPayload[`${mediaType}`] = selected.map((id) => ({
|
||||||
|
[`${mediaType}_id`]: id
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +183,7 @@ export const addPost = async () => {
|
||||||
content,
|
content,
|
||||||
featured,
|
featured,
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
post_tags: tagIds.map(tagId => ({ tags_id: tagId })),
|
post_tags: tagIds.map((tagId) => ({ tags_id: tagId })),
|
||||||
blocks: selectedBlocks,
|
blocks: selectedBlocks,
|
||||||
...associatedMediaPayload
|
...associatedMediaPayload
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ const TASKS = [
|
||||||
{ name: '🔗 Add link to share', handler: addLinkToShare },
|
{ name: '🔗 Add link to share', handler: addLinkToShare },
|
||||||
{ name: '➕ Add episode to show', handler: addEpisodeToShow },
|
{ name: '➕ Add episode to show', handler: addEpisodeToShow },
|
||||||
{ name: '📚 Update reading progress', handler: updateReadingProgress },
|
{ name: '📚 Update reading progress', handler: updateReadingProgress },
|
||||||
{ name: '🤖 Block robot', handler: addBlockedRobot },
|
{ name: '🤖 Block robot', handler: addBlockedRobot }
|
||||||
];
|
];
|
||||||
|
|
||||||
export const runTasksMenu = async () => {
|
export const runTasksMenu = async () => {
|
||||||
|
@ -19,7 +19,7 @@ export const runTasksMenu = async () => {
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'task',
|
name: 'task',
|
||||||
message: 'Select a task to perform:',
|
message: 'Select a task to perform:',
|
||||||
choices: TASKS.map(t => ({ name: t.name, value: t.handler }))
|
choices: TASKS.map((t) => ({ name: t.name, value: t.handler }))
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const updateReadingProgress = async () => {
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'bookId',
|
name: 'bookId',
|
||||||
message: '📚 Select a book to update progress:',
|
message: '📚 Select a book to update progress:',
|
||||||
choices: readingBooks.map(book => {
|
choices: readingBooks.map((book) => {
|
||||||
const title = book.title || book.name || `Book #${book.id}`;
|
const title = book.title || book.name || `Book #${book.id}`;
|
||||||
const progress = book.progress ?? 0;
|
const progress = book.progress ?? 0;
|
||||||
|
|
||||||
|
@ -32,10 +32,10 @@ export const updateReadingProgress = async () => {
|
||||||
const { progress } = await inquirer.prompt({
|
const { progress } = await inquirer.prompt({
|
||||||
name: 'progress',
|
name: 'progress',
|
||||||
message: '📕 New progress percentage (0–100):',
|
message: '📕 New progress percentage (0–100):',
|
||||||
validate: input => {
|
validate: (input) => {
|
||||||
const num = Number(input);
|
const num = Number(input);
|
||||||
|
|
||||||
return !isNaN(num) && num >= 0 && num <= 100 || 'Enter a number from 0 to 100';
|
return (!isNaN(num) && num >= 0 && num <= 100) || 'Enter a number from 0 to 100';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import ics from "ics";
|
import ics from 'ics';
|
||||||
|
|
||||||
export const albumReleasesCalendar = (collection) => {
|
export const albumReleasesCalendar = (collection) => {
|
||||||
const collectionData = collection.getAll()[0];
|
const collectionData = collection.getAll()[0];
|
||||||
const { data } = collectionData;
|
const { data } = collectionData;
|
||||||
const { albumReleases: { all }, globals: { url } } = data;
|
const {
|
||||||
|
albumReleases: { all },
|
||||||
|
globals: { url }
|
||||||
|
} = data;
|
||||||
|
|
||||||
if (!all || all.length === 0) return "";
|
if (!all || all.length === 0) return '';
|
||||||
|
|
||||||
const events = all
|
const events = all
|
||||||
.map((album) => {
|
.map((album) => {
|
||||||
|
@ -13,27 +16,30 @@ export const albumReleasesCalendar = (collection) => {
|
||||||
|
|
||||||
if (isNaN(date.getTime())) return null;
|
if (isNaN(date.getTime())) return null;
|
||||||
|
|
||||||
const albumUrl = album.url?.includes("http") ? album.url : `${url}${album.url}`;
|
const albumUrl = album.url?.includes('http') ? album.url : `${url}${album.url}`;
|
||||||
const artistUrl = album.artist.url?.includes("http") ? album.artust.url : `${url}${album.artist.url}`;
|
const artistUrl = album.artist.url?.includes('http')
|
||||||
|
? album.artust.url
|
||||||
|
: `${url}${album.artist.url}`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
start: [date.getFullYear(), date.getMonth() + 1, date.getDate()],
|
start: [date.getFullYear(), date.getMonth() + 1, date.getDate()],
|
||||||
startInputType: "local",
|
startInputType: 'local',
|
||||||
startOutputType: "local",
|
startOutputType: 'local',
|
||||||
title: `Release: ${album.artist.name} - ${album.title}`,
|
title: `Release: ${album.artist.name} - ${album.title}`,
|
||||||
description: `Check out this new album release: ${albumUrl}. Read more about ${album.artist.name} at ${artistUrl}`,
|
description: `Check out this new album release: ${albumUrl}. Read more about ${album.artist.name} at ${artistUrl}`,
|
||||||
url: albumUrl,
|
url: albumUrl,
|
||||||
uid: `${album.release_timestamp}-${album.artist.name}-${album.title}`,
|
uid: `${album.release_timestamp}-${album.artist.name}-${album.title}`
|
||||||
};
|
};
|
||||||
}).filter((event) => event !== null);
|
})
|
||||||
|
.filter((event) => event !== null);
|
||||||
|
|
||||||
const { error, value } = ics.createEvents(events, {
|
const { error, value } = ics.createEvents(events, {
|
||||||
calName: "Album releases calendar • coryd.dev",
|
calName: 'Album releases calendar • coryd.dev'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error("Error creating events: ", error);
|
console.error('Error creating events: ', error);
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import fs from "fs";
|
import fs from 'fs';
|
||||||
import path from "path";
|
import path from 'path';
|
||||||
import { minify } from "terser";
|
import { minify } from 'terser';
|
||||||
|
|
||||||
export const minifyJsComponents = async () => {
|
export const minifyJsComponents = async () => {
|
||||||
const scriptsDir = "dist/assets/scripts";
|
const scriptsDir = 'dist/assets/scripts';
|
||||||
const minifyJsFilesInDir = async (dir) => {
|
const minifyJsFilesInDir = async (dir) => {
|
||||||
const files = fs.readdirSync(dir);
|
const files = fs.readdirSync(dir);
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ export const minifyJsComponents = async () => {
|
||||||
|
|
||||||
if (stat.isDirectory()) {
|
if (stat.isDirectory()) {
|
||||||
await minifyJsFilesInDir(filePath);
|
await minifyJsFilesInDir(filePath);
|
||||||
} else if (fileName.endsWith(".js")) {
|
} else if (fileName.endsWith('.js')) {
|
||||||
const fileContent = fs.readFileSync(filePath, "utf8");
|
const fileContent = fs.readFileSync(filePath, 'utf8');
|
||||||
const minified = await minify(fileContent);
|
const minified = await minify(fileContent);
|
||||||
|
|
||||||
if (minified.error) {
|
if (minified.error) {
|
||||||
|
|
|
@ -6,32 +6,32 @@ export default {
|
||||||
|
|
||||||
const $ = cheerio.load(htmlContent);
|
const $ = cheerio.load(htmlContent);
|
||||||
|
|
||||||
$("a[href]").each((_, link) => {
|
$('a[href]').each((_, link) => {
|
||||||
const $link = $(link);
|
const $link = $(link);
|
||||||
let href = $link.attr("href");
|
let href = $link.attr('href');
|
||||||
|
|
||||||
if (href.startsWith("#")) {
|
if (href.startsWith('#')) {
|
||||||
$link.replaceWith($("<span>").text($link.text()));
|
$link.replaceWith($('<span>').text($link.text()));
|
||||||
} else if (!href.startsWith("http://") && !href.startsWith("https://")) {
|
} else if (!href.startsWith('http://') && !href.startsWith('https://')) {
|
||||||
const normalizedDomain = domain.replace(/\/$/, '');
|
const normalizedDomain = domain.replace(/\/$/, '');
|
||||||
const normalizedHref = href.replace(/^\/+/, '');
|
const normalizedHref = href.replace(/^\/+/, '');
|
||||||
$link.attr("href", `${normalizedDomain}/${normalizedHref}`);
|
$link.attr('href', `${normalizedDomain}/${normalizedHref}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return $.html();
|
return $.html();
|
||||||
},
|
},
|
||||||
generatePermalink: (url, baseUrl) => {
|
generatePermalink: (url, baseUrl) => {
|
||||||
if (url?.includes("http") || !baseUrl) return url
|
if (url?.includes('http') || !baseUrl) return url;
|
||||||
return `${baseUrl}${url}`
|
return `${baseUrl}${url}`;
|
||||||
},
|
},
|
||||||
getRemoteFileSize: async (url) => {
|
getRemoteFileSize: async (url) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url, { method: "HEAD" });
|
const response = await fetch(url, { method: 'HEAD' });
|
||||||
|
|
||||||
if (!response.ok) return 0;
|
if (!response.ok) return 0;
|
||||||
|
|
||||||
const contentLength = response.headers.get("content-length");
|
const contentLength = response.headers.get('content-length');
|
||||||
|
|
||||||
if (!contentLength) return 0;
|
if (!contentLength) return 0;
|
||||||
|
|
||||||
|
@ -40,4 +40,4 @@ export default {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
import truncateHtml from "truncate-html";
|
import truncateHtml from 'truncate-html';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
encodeAmp: (string) => {
|
encodeAmp: (string) => {
|
||||||
if (!string) return;
|
if (!string) return;
|
||||||
|
|
||||||
const pattern = /&(?!(?:[a-zA-Z]+|#[0-9]+|#x[0-9a-fA-F]+);)/g;
|
const pattern = /&(?!(?:[a-zA-Z]+|#[0-9]+|#x[0-9a-fA-F]+);)/g;
|
||||||
const replacement = "&";
|
const replacement = '&';
|
||||||
|
|
||||||
return string.replace(pattern, replacement);
|
return string.replace(pattern, replacement);
|
||||||
},
|
},
|
||||||
replaceQuotes: (string) => {
|
replaceQuotes: (string) => {
|
||||||
if (!string) return '';
|
if (!string) return '';
|
||||||
return string.replace(/"/g, """);
|
return string.replace(/"/g, '"');
|
||||||
},
|
},
|
||||||
htmlTruncate: (content, limit = 50) => truncateHtml(content, limit, {
|
htmlTruncate: (content, limit = 50) =>
|
||||||
|
truncateHtml(content, limit, {
|
||||||
byWords: true,
|
byWords: true,
|
||||||
ellipsis: "...",
|
ellipsis: '...'
|
||||||
}),
|
}),
|
||||||
shuffleArray: (array) => {
|
shuffleArray: (array) => {
|
||||||
const shuffled = [...array];
|
const shuffled = [...array];
|
||||||
|
@ -29,9 +30,9 @@ export default {
|
||||||
|
|
||||||
return shuffled;
|
return shuffled;
|
||||||
},
|
},
|
||||||
mergeArray: (a, b) => Array.isArray(a) && Array.isArray(b) ? [...new Set([...a, ...b])] : [],
|
mergeArray: (a, b) => (Array.isArray(a) && Array.isArray(b) ? [...new Set([...a, ...b])] : []),
|
||||||
pluralize: (count, string, trailing) => {
|
pluralize: (count, string, trailing) => {
|
||||||
const countStr = String(count).replace(/,/g, "");
|
const countStr = String(count).replace(/,/g, '');
|
||||||
|
|
||||||
if (parseInt(countStr, 10) === 1) return string;
|
if (parseInt(countStr, 10) === 1) return string;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import feeds from "./feeds.js"
|
import feeds from './feeds.js';
|
||||||
import general from "./general.js";
|
import general from './general.js';
|
||||||
import media from "./media.js";
|
import media from './media.js';
|
||||||
import metadata from "./metadata.js";
|
import metadata from './metadata.js';
|
||||||
import navigation from "./navigation.js";
|
import navigation from './navigation.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...feeds,
|
...feeds,
|
||||||
...general,
|
...general,
|
||||||
...media,
|
...media,
|
||||||
...metadata,
|
...metadata,
|
||||||
...navigation,
|
...navigation
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
export default {
|
export default {
|
||||||
filterBooksByStatus: (books, status) => books.filter((book) => book.status === status),
|
filterBooksByStatus: (books, status) => books.filter((book) => book.status === status),
|
||||||
findFavoriteBooks: (books) => books.filter((book) => book.favorite === true),
|
findFavoriteBooks: (books) => books.filter((book) => book.favorite === true),
|
||||||
bookYearLinks: (years) => years.sort((a, b) => b.value - a.value).map((year, index) =>
|
bookYearLinks: (years) =>
|
||||||
|
years
|
||||||
|
.sort((a, b) => b.value - a.value)
|
||||||
|
.map(
|
||||||
|
(year, index) =>
|
||||||
`<a href="/reading/years/${year.value}">${year.value}</a>${
|
`<a href="/reading/years/${year.value}">${year.value}</a>${
|
||||||
index < years.length - 1 ? " • " : ""
|
index < years.length - 1 ? ' • ' : ''
|
||||||
}`).join(""),
|
}`
|
||||||
|
)
|
||||||
|
.join(''),
|
||||||
mediaLinks: (data, type, count = 10) => {
|
mediaLinks: (data, type, count = 10) => {
|
||||||
if (!data || !type) return "";
|
if (!data || !type) return '';
|
||||||
|
|
||||||
const dataSlice = data.slice(0, count);
|
const dataSlice = data.slice(0, count);
|
||||||
|
|
||||||
|
@ -14,23 +20,23 @@ export default {
|
||||||
|
|
||||||
const buildLink = (item) => {
|
const buildLink = (item) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "genre":
|
case 'genre':
|
||||||
return `<a href="${item.genre_url}">${item.genre_name}</a>`;
|
return `<a href="${item.genre_url}">${item.genre_name}</a>`;
|
||||||
case "artist":
|
case 'artist':
|
||||||
return `<a href="${item.url}">${item.name}</a>`;
|
return `<a href="${item.url}">${item.name}</a>`;
|
||||||
case "book":
|
case 'book':
|
||||||
return `<a href="${item.url}">${item.title}</a>`;
|
return `<a href="${item.url}">${item.title}</a>`;
|
||||||
default:
|
default:
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (dataSlice.length === 1) return buildLink(dataSlice[0]);
|
if (dataSlice.length === 1) return buildLink(dataSlice[0]);
|
||||||
|
|
||||||
const links = dataSlice.map(buildLink);
|
const links = dataSlice.map(buildLink);
|
||||||
const allButLast = links.slice(0, -1).join(", ");
|
const allButLast = links.slice(0, -1).join(', ');
|
||||||
const last = links[links.length - 1];
|
const last = links[links.length - 1];
|
||||||
|
|
||||||
return `${allButLast} and ${last}`;
|
return `${allButLast} and ${last}`;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
export default {
|
export default {
|
||||||
getMetadata: (data = {}, globals = {}, page = {}, title = "", description = "", schema = "") => {
|
getMetadata: (data = {}, globals = {}, page = {}, title = '', description = '', schema = '') => {
|
||||||
const metadata = data?.metadata;
|
const metadata = data?.metadata;
|
||||||
const baseUrl = globals.url || "";
|
const baseUrl = globals.url || '';
|
||||||
const ogPath = "/og/w800";
|
const ogPath = '/og/w800';
|
||||||
const image = metadata?.open_graph_image || globals.metadata?.open_graph_image || globals.avatar;
|
const image =
|
||||||
|
metadata?.open_graph_image || globals.metadata?.open_graph_image || globals.avatar;
|
||||||
const rawTitle = title || page.title || metadata?.title || globals.site_name;
|
const rawTitle = title || page.title || metadata?.title || globals.site_name;
|
||||||
const resolvedTitle = rawTitle === globals.site_name ? globals.site_name : `${rawTitle} • ${globals.site_name}`;
|
const resolvedTitle =
|
||||||
const resolvedDescription = description || metadata?.description || page.description || globals.site_description;
|
rawTitle === globals.site_name ? globals.site_name : `${rawTitle} • ${globals.site_name}`;
|
||||||
const url = metadata?.url || (page.url ? `${baseUrl}${page.url}` : "#");
|
const resolvedDescription =
|
||||||
|
description || metadata?.description || page.description || globals.site_description;
|
||||||
|
const url = metadata?.url || (page.url ? `${baseUrl}${page.url}` : '#');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: resolvedTitle,
|
title: resolvedTitle,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export default {
|
export default {
|
||||||
isLinkActive: (category, page) => page.includes(category) && page.split("/").filter((a) => a !== "").length <= 1,
|
isLinkActive: (category, page) =>
|
||||||
|
page.includes(category) && page.split('/').filter((a) => a !== '').length <= 1
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
import fs from "node:fs/promises";
|
import fs from 'node:fs/promises';
|
||||||
import path from "node:path";
|
import path from 'node:path';
|
||||||
import postcss from "postcss";
|
import postcss from 'postcss';
|
||||||
import postcssImport from "postcss-import";
|
import postcssImport from 'postcss-import';
|
||||||
import postcssImportExtGlob from "postcss-import-ext-glob";
|
import postcssImportExtGlob from 'postcss-import-ext-glob';
|
||||||
import cssnano from "cssnano";
|
import cssnano from 'cssnano';
|
||||||
|
|
||||||
export const cssConfig = (eleventyConfig) => {
|
export const cssConfig = (eleventyConfig) => {
|
||||||
eleventyConfig.addTemplateFormats("css");
|
eleventyConfig.addTemplateFormats('css');
|
||||||
eleventyConfig.addExtension("css", {
|
eleventyConfig.addExtension('css', {
|
||||||
outputFileExtension: "css",
|
outputFileExtension: 'css',
|
||||||
compile: async (inputContent, inputPath) => {
|
compile: async (inputContent, inputPath) => {
|
||||||
const outputPath = "dist/assets/css/index.css";
|
const outputPath = 'dist/assets/css/index.css';
|
||||||
|
|
||||||
if (inputPath.endsWith("index.css")) {
|
if (inputPath.endsWith('index.css')) {
|
||||||
return async () => {
|
return async () => {
|
||||||
let result = await postcss([
|
let result = await postcss([postcssImportExtGlob, postcssImport, cssnano]).process(
|
||||||
postcssImportExtGlob,
|
inputContent,
|
||||||
postcssImport,
|
{ from: inputPath }
|
||||||
cssnano,
|
);
|
||||||
]).process(inputContent, { from: inputPath });
|
|
||||||
|
|
||||||
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
||||||
await fs.writeFile(outputPath, result.css);
|
await fs.writeFile(outputPath, result.css);
|
||||||
|
@ -26,6 +25,6 @@ export const cssConfig = (eleventyConfig) => {
|
||||||
return result.css;
|
return result.css;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { cssConfig } from "./css-config.js";
|
import { cssConfig } from './css-config.js';
|
||||||
import { htmlConfig } from "./html-config.js";
|
import { htmlConfig } from './html-config.js';
|
||||||
import { markdownLib } from "./markdown.js";
|
import { markdownLib } from './markdown.js';
|
||||||
|
|
||||||
export default { cssConfig, htmlConfig, markdownLib };
|
export default { cssConfig, htmlConfig, markdownLib };
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import markdownIt from "markdown-it";
|
import markdownIt from 'markdown-it';
|
||||||
import markdownItAnchor from "markdown-it-anchor";
|
import markdownItAnchor from 'markdown-it-anchor';
|
||||||
import markdownItFootnote from "markdown-it-footnote";
|
import markdownItFootnote from 'markdown-it-footnote';
|
||||||
import markdownItLinkAttributes from "markdown-it-link-attributes";
|
import markdownItLinkAttributes from 'markdown-it-link-attributes';
|
||||||
import markdownItPrism from "markdown-it-prism";
|
import markdownItPrism from 'markdown-it-prism';
|
||||||
|
|
||||||
export const markdownLib = markdownIt({ html: true, linkify: true })
|
export const markdownLib = markdownIt({ html: true, linkify: true })
|
||||||
.use(markdownItAnchor, {
|
.use(markdownItAnchor, {
|
||||||
level: [1, 2],
|
level: [1, 2],
|
||||||
permalink: markdownItAnchor.permalink.headerLink({
|
permalink: markdownItAnchor.permalink.headerLink({
|
||||||
safariReaderFix: true,
|
safariReaderFix: true
|
||||||
}),
|
})
|
||||||
})
|
})
|
||||||
.use(markdownItLinkAttributes, [
|
.use(markdownItLinkAttributes, [
|
||||||
{
|
{
|
||||||
|
@ -17,9 +17,9 @@ export const markdownLib = markdownIt({ html: true, linkify: true })
|
||||||
return href.match(/^https?:\/\//);
|
return href.match(/^https?:\/\//);
|
||||||
},
|
},
|
||||||
attrs: {
|
attrs: {
|
||||||
rel: "noopener",
|
rel: 'noopener'
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
])
|
])
|
||||||
.use(markdownItFootnote)
|
.use(markdownItFootnote)
|
||||||
.use(markdownItPrism);
|
.use(markdownItPrism);
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { createRequire } from "module";
|
import { createRequire } from 'module';
|
||||||
import "dotenv/config";
|
import 'dotenv/config';
|
||||||
import filters from "./config/filters/index.js";
|
import filters from './config/filters/index.js';
|
||||||
import tablerIcons from "@cdransf/eleventy-plugin-tabler-icons";
|
import tablerIcons from '@cdransf/eleventy-plugin-tabler-icons';
|
||||||
import { minifyJsComponents } from "./config/events/minify-js.js";
|
import { minifyJsComponents } from './config/events/minify-js.js';
|
||||||
import { albumReleasesCalendar } from "./config/collections/index.js";
|
import { albumReleasesCalendar } from './config/collections/index.js';
|
||||||
import plugins from "./config/plugins/index.js";
|
import plugins from './config/plugins/index.js';
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
const appVersion = require("./package.json").version;
|
const appVersion = require('./package.json').version;
|
||||||
|
|
||||||
export default async function (eleventyConfig) {
|
export default async function (eleventyConfig) {
|
||||||
eleventyConfig.addPlugin(tablerIcons);
|
eleventyConfig.addPlugin(tablerIcons);
|
||||||
|
@ -18,23 +18,22 @@ export default async function (eleventyConfig) {
|
||||||
eleventyConfig.configureErrorReporting({ allowMissingExtensions: true });
|
eleventyConfig.configureErrorReporting({ allowMissingExtensions: true });
|
||||||
eleventyConfig.setLiquidOptions({ jsTruthy: true });
|
eleventyConfig.setLiquidOptions({ jsTruthy: true });
|
||||||
|
|
||||||
eleventyConfig.watchIgnores.add("queries/**");
|
eleventyConfig.watchIgnores.add('queries/**');
|
||||||
|
|
||||||
eleventyConfig.addPassthroughCopy("src/assets");
|
eleventyConfig.addPassthroughCopy('src/assets');
|
||||||
eleventyConfig.addPassthroughCopy("api");
|
eleventyConfig.addPassthroughCopy('api');
|
||||||
eleventyConfig.addPassthroughCopy("bootstrap.php");
|
eleventyConfig.addPassthroughCopy('bootstrap.php');
|
||||||
eleventyConfig.addPassthroughCopy({
|
eleventyConfig.addPassthroughCopy({
|
||||||
"node_modules/minisearch/dist/umd/index.js":
|
'node_modules/minisearch/dist/umd/index.js': 'assets/scripts/components/minisearch.js',
|
||||||
"assets/scripts/components/minisearch.js",
|
'node_modules/youtube-video-element/dist/youtube-video-element.js':
|
||||||
"node_modules/youtube-video-element/dist/youtube-video-element.js":
|
'assets/scripts/components/youtube-video-element.js'
|
||||||
"assets/scripts/components/youtube-video-element.js",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
eleventyConfig.addCollection("albumReleasesCalendar", albumReleasesCalendar);
|
eleventyConfig.addCollection('albumReleasesCalendar', albumReleasesCalendar);
|
||||||
|
|
||||||
eleventyConfig.setLibrary("md", plugins.markdownLib);
|
eleventyConfig.setLibrary('md', plugins.markdownLib);
|
||||||
|
|
||||||
eleventyConfig.addLiquidFilter("markdown", (content) => {
|
eleventyConfig.addLiquidFilter('markdown', (content) => {
|
||||||
if (!content) return;
|
if (!content) return;
|
||||||
return plugins.markdownLib.render(content);
|
return plugins.markdownLib.render(content);
|
||||||
});
|
});
|
||||||
|
@ -43,17 +42,17 @@ export default async function (eleventyConfig) {
|
||||||
eleventyConfig.addLiquidFilter(filterName, filters[filterName]);
|
eleventyConfig.addLiquidFilter(filterName, filters[filterName]);
|
||||||
});
|
});
|
||||||
|
|
||||||
eleventyConfig.addShortcode("appVersion", () => appVersion);
|
eleventyConfig.addShortcode('appVersion', () => appVersion);
|
||||||
|
|
||||||
eleventyConfig.on("afterBuild", minifyJsComponents);
|
eleventyConfig.on('afterBuild', minifyJsComponents);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dir: {
|
dir: {
|
||||||
input: "src",
|
input: 'src',
|
||||||
includes: "includes",
|
includes: 'includes',
|
||||||
layouts: "layouts",
|
layouts: 'layouts',
|
||||||
data: "data",
|
data: 'data',
|
||||||
output: "dist",
|
output: 'dist'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
542
package-lock.json
generated
542
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "coryd.dev",
|
"name": "coryd.dev",
|
||||||
"version": "10.0.4",
|
"version": "10.1.4",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "coryd.dev",
|
"name": "coryd.dev",
|
||||||
"version": "10.0.4",
|
"version": "10.1.4",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minisearch": "^7.1.2",
|
"minisearch": "^7.1.2",
|
||||||
|
@ -21,7 +21,9 @@
|
||||||
"cssnano": "^7.0.7",
|
"cssnano": "^7.0.7",
|
||||||
"dotenv": "16.5.0",
|
"dotenv": "16.5.0",
|
||||||
"html-minifier-terser": "7.2.0",
|
"html-minifier-terser": "7.2.0",
|
||||||
|
"husky": "9.1.7",
|
||||||
"ics": "^3.8.1",
|
"ics": "^3.8.1",
|
||||||
|
"lint-staged": "16.1.1",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
"markdown-it-anchor": "^9.2.0",
|
"markdown-it-anchor": "^9.2.0",
|
||||||
"markdown-it-footnote": "^4.0.0",
|
"markdown-it-footnote": "^4.0.0",
|
||||||
|
@ -30,6 +32,7 @@
|
||||||
"postcss": "^8.5.5",
|
"postcss": "^8.5.5",
|
||||||
"postcss-import": "^16.1.0",
|
"postcss-import": "^16.1.0",
|
||||||
"postcss-import-ext-glob": "^2.1.1",
|
"postcss-import-ext-glob": "^2.1.1",
|
||||||
|
"prettier": "3.5.3",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"terser": "^5.42.0",
|
"terser": "^5.42.0",
|
||||||
"truncate-html": "^1.2.2"
|
"truncate-html": "^1.2.2"
|
||||||
|
@ -292,6 +295,62 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@isaacs/cliui/node_modules/ansi-styles": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
|
||||||
|
"version": "9.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||||
|
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@isaacs/cliui/node_modules/string-width": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"eastasianwidth": "^0.2.0",
|
||||||
|
"emoji-regex": "^9.2.2",
|
||||||
|
"strip-ansi": "^7.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
|
||||||
|
"version": "8.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||||
|
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^6.1.0",
|
||||||
|
"string-width": "^5.0.1",
|
||||||
|
"strip-ansi": "^7.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.3.8",
|
"version": "0.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
||||||
|
@ -508,6 +567,22 @@
|
||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ansi-escapes": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"environment": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ansi-regex": {
|
"node_modules/ansi-regex": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||||
|
@ -911,6 +986,39 @@
|
||||||
"node": ">= 10.0"
|
"node": ">= 10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cli-cursor": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"restore-cursor": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cli-truncate": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"slice-ansi": "^5.0.0",
|
||||||
|
"string-width": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cliui": {
|
"node_modules/cliui": {
|
||||||
"version": "8.0.1",
|
"version": "8.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||||
|
@ -943,6 +1051,16 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/cliui/node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cliui/node_modules/string-width": {
|
"node_modules/cliui/node_modules/string-width": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
@ -1016,6 +1134,13 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/colorette": {
|
||||||
|
"version": "2.0.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
|
||||||
|
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "10.0.1",
|
"version": "10.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
||||||
|
@ -1415,9 +1540,9 @@
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
"version": "9.2.2",
|
"version": "10.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
|
||||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
"integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
@ -1458,6 +1583,19 @@
|
||||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/environment": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/errno": {
|
"node_modules/errno": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/errno/-/errno-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/errno/-/errno-1.0.0.tgz",
|
||||||
|
@ -1546,9 +1684,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eventemitter3": {
|
"node_modules/eventemitter3": {
|
||||||
"version": "4.0.7",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
@ -1742,6 +1880,19 @@
|
||||||
"node": "6.* || 8.* || >= 10.*"
|
"node": "6.* || 8.* || >= 10.*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/get-east-asian-width": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/glob": {
|
"node_modules/glob": {
|
||||||
"version": "11.0.3",
|
"version": "11.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
|
||||||
|
@ -1940,6 +2091,22 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/husky": {
|
||||||
|
"version": "9.1.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
|
||||||
|
"integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"husky": "bin.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/typicode"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
@ -2059,13 +2226,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-fullwidth-code-point": {
|
"node_modules/is-fullwidth-code-point": {
|
||||||
"version": "3.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
|
||||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
"integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-glob": {
|
"node_modules/is-glob": {
|
||||||
|
@ -2197,6 +2367,57 @@
|
||||||
"uc.micro": "^2.0.0"
|
"uc.micro": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lint-staged": {
|
||||||
|
"version": "16.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.1.1.tgz",
|
||||||
|
"integrity": "sha512-kVZvRAHw9WuufENnwuZLiB1X/8B8YpGszzjMET0bP+uJSjjB7KXeaX2ckYRtQyHfeQdCWMc6tRK34t4geHL9sg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^5.4.1",
|
||||||
|
"commander": "^14.0.0",
|
||||||
|
"debug": "^4.4.1",
|
||||||
|
"lilconfig": "^3.1.3",
|
||||||
|
"listr2": "^8.3.3",
|
||||||
|
"micromatch": "^4.0.8",
|
||||||
|
"nano-spawn": "^1.0.2",
|
||||||
|
"pidtree": "^0.6.0",
|
||||||
|
"string-argv": "^0.3.2",
|
||||||
|
"yaml": "^2.8.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"lint-staged": "bin/lint-staged.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/lint-staged"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lint-staged/node_modules/chalk": {
|
||||||
|
"version": "5.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
|
||||||
|
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lint-staged/node_modules/commander": {
|
||||||
|
"version": "14.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz",
|
||||||
|
"integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/liquidjs": {
|
"node_modules/liquidjs": {
|
||||||
"version": "10.21.1",
|
"version": "10.21.1",
|
||||||
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.21.1.tgz",
|
||||||
|
@ -2225,6 +2446,24 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/listr2": {
|
||||||
|
"version": "8.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz",
|
||||||
|
"integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cli-truncate": "^4.0.0",
|
||||||
|
"colorette": "^2.0.20",
|
||||||
|
"eventemitter3": "^5.0.1",
|
||||||
|
"log-update": "^6.1.0",
|
||||||
|
"rfdc": "^1.4.1",
|
||||||
|
"wrap-ansi": "^9.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
@ -2246,6 +2485,72 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/log-update": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-escapes": "^7.0.0",
|
||||||
|
"cli-cursor": "^5.0.0",
|
||||||
|
"slice-ansi": "^7.1.0",
|
||||||
|
"strip-ansi": "^7.1.0",
|
||||||
|
"wrap-ansi": "^9.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/log-update/node_modules/ansi-styles": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/log-update/node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"get-east-asian-width": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/log-update/node_modules/slice-ansi": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^6.2.1",
|
||||||
|
"is-fullwidth-code-point": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lower-case": {
|
"node_modules/lower-case": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
||||||
|
@ -2448,6 +2753,19 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mimic-function": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
@ -2508,6 +2826,19 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/nano-spawn": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sindresorhus/nano-spawn?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.11",
|
"version": "3.3.11",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||||
|
@ -2629,6 +2960,22 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/onetime": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mimic-function": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/p-finally": {
|
"node_modules/p-finally": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||||
|
@ -2656,6 +3003,13 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/p-queue/node_modules/eventemitter3": {
|
||||||
|
"version": "4.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||||
|
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/p-timeout": {
|
"node_modules/p-timeout": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
|
||||||
|
@ -2809,6 +3163,19 @@
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pidtree": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"pidtree": "bin/pidtree.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pify": {
|
"node_modules/pify": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||||
|
@ -3492,6 +3859,22 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prettier": {
|
||||||
|
"version": "3.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
|
||||||
|
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"prettier": "bin/prettier.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prismjs": {
|
"node_modules/prismjs": {
|
||||||
"version": "1.30.0",
|
"version": "1.30.0",
|
||||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
|
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
|
||||||
|
@ -3634,6 +4017,23 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/restore-cursor": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"onetime": "^7.0.0",
|
||||||
|
"signal-exit": "^4.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/reusify": {
|
"node_modules/reusify": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
||||||
|
@ -3645,6 +4045,13 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rfdc": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/rimraf": {
|
"node_modules/rimraf": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz",
|
||||||
|
@ -3836,6 +4243,36 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/slice-ansi": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^6.0.0",
|
||||||
|
"is-fullwidth-code-point": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/slice-ansi/node_modules/ansi-styles": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/slugify": {
|
"node_modules/slugify": {
|
||||||
"version": "1.6.6",
|
"version": "1.6.6",
|
||||||
"resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz",
|
"resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz",
|
||||||
|
@ -3907,19 +4344,29 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/string-argv": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string-width": {
|
"node_modules/string-width": {
|
||||||
"version": "5.1.2",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
|
||||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
"integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eastasianwidth": "^0.2.0",
|
"emoji-regex": "^10.3.0",
|
||||||
"emoji-regex": "^9.2.2",
|
"get-east-asian-width": "^1.0.0",
|
||||||
"strip-ansi": "^7.0.1"
|
"strip-ansi": "^7.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
@ -3958,6 +4405,16 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string-width-cjs/node_modules/strip-ansi": {
|
"node_modules/string-width-cjs/node_modules/strip-ansi": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
|
@ -4390,18 +4847,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/wrap-ansi": {
|
"node_modules/wrap-ansi": {
|
||||||
"version": "8.1.0",
|
"version": "9.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
|
||||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
"integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": "^6.1.0",
|
"ansi-styles": "^6.2.1",
|
||||||
"string-width": "^5.0.1",
|
"string-width": "^7.0.0",
|
||||||
"strip-ansi": "^7.0.1"
|
"strip-ansi": "^7.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
|
@ -4443,6 +4900,16 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
|
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
@ -4516,6 +4983,19 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/yaml": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
|
||||||
|
"integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"yaml": "bin.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yargs": {
|
"node_modules/yargs": {
|
||||||
"version": "17.7.2",
|
"version": "17.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||||
|
@ -4562,6 +5042,16 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/yargs/node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yargs/node_modules/string-width": {
|
"node_modules/yargs/node_modules/string-width": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
|
12
package.json
12
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "coryd.dev",
|
"name": "coryd.dev",
|
||||||
"version": "10.0.4",
|
"version": "10.1.4",
|
||||||
"description": "The source for my personal site. Built using 11ty (and other tools).",
|
"description": "The source for my personal site. Built using 11ty (and other tools).",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -13,9 +13,14 @@
|
||||||
"php": "export $(grep -v '^#' .env | xargs) && php -d error_reporting=E_ALL^E_DEPRECATED -S localhost:8080 -t dist",
|
"php": "export $(grep -v '^#' .env | xargs) && php -d error_reporting=E_ALL^E_DEPRECATED -S localhost:8080 -t dist",
|
||||||
"build": "eleventy",
|
"build": "eleventy",
|
||||||
"clean": "rimraf dist .cache",
|
"clean": "rimraf dist .cache",
|
||||||
|
"format": "npx prettier --write '**/*.{js,ts,json,css,md}'",
|
||||||
"update": "composer update && npm upgrade && npm --prefix cli upgrade && ncu && ncu --cwd cli",
|
"update": "composer update && npm upgrade && npm --prefix cli upgrade && ncu && ncu --cwd cli",
|
||||||
"setup": "sh ./scripts/setup.sh",
|
"setup": "sh ./scripts/setup.sh",
|
||||||
"setup:deploy": "sh ./scripts/setup.sh --deploy"
|
"setup:deploy": "sh ./scripts/setup.sh --deploy",
|
||||||
|
"prepare": "husky"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{js,json,css,md}": "prettier --write"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"11ty",
|
"11ty",
|
||||||
|
@ -41,7 +46,9 @@
|
||||||
"cssnano": "^7.0.7",
|
"cssnano": "^7.0.7",
|
||||||
"dotenv": "16.5.0",
|
"dotenv": "16.5.0",
|
||||||
"html-minifier-terser": "7.2.0",
|
"html-minifier-terser": "7.2.0",
|
||||||
|
"husky": "9.1.7",
|
||||||
"ics": "^3.8.1",
|
"ics": "^3.8.1",
|
||||||
|
"lint-staged": "16.1.1",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
"markdown-it-anchor": "^9.2.0",
|
"markdown-it-anchor": "^9.2.0",
|
||||||
"markdown-it-footnote": "^4.0.0",
|
"markdown-it-footnote": "^4.0.0",
|
||||||
|
@ -50,6 +57,7 @@
|
||||||
"postcss": "^8.5.5",
|
"postcss": "^8.5.5",
|
||||||
"postcss-import": "^16.1.0",
|
"postcss-import": "^16.1.0",
|
||||||
"postcss-import-ext-glob": "^2.1.1",
|
"postcss-import-ext-glob": "^2.1.1",
|
||||||
|
"prettier": "3.5.3",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"terser": "^5.42.0",
|
"terser": "^5.42.0",
|
||||||
"truncate-html": "^1.2.2"
|
"truncate-html": "^1.2.2"
|
||||||
|
|
|
@ -69,6 +69,9 @@ export $(grep -v '^#' .env | xargs)
|
||||||
echo "${COLOR_BLUE}📦 Installing root project dependencies...${COLOR_RESET}"
|
echo "${COLOR_BLUE}📦 Installing root project dependencies...${COLOR_RESET}"
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
|
echo "${COLOR_BLUE}🐺 Initializing Husky Git hooks...${COLOR_RESET}"
|
||||||
|
npm run prepare
|
||||||
|
|
||||||
echo "${COLOR_BLUE}📦 Installing PHP dependencies (composer)...${COLOR_RESET}"
|
echo "${COLOR_BLUE}📦 Installing PHP dependencies (composer)...${COLOR_RESET}"
|
||||||
composer install
|
composer install
|
||||||
|
|
||||||
|
|
|
@ -1,52 +1,52 @@
|
||||||
class SelectPagination extends HTMLElement {
|
class SelectPagination extends HTMLElement {
|
||||||
static register(tagName = 'select-pagination') {
|
static register(tagName = 'select-pagination') {
|
||||||
if ("customElements" in window) customElements.define(tagName, this)
|
if ('customElements' in window) customElements.define(tagName, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
return ['data-base-index']
|
return ['data-base-index'];
|
||||||
}
|
}
|
||||||
|
|
||||||
get baseIndex() {
|
get baseIndex() {
|
||||||
return parseInt(this.getAttribute('data-base-index') || '0', 10)
|
return parseInt(this.getAttribute('data-base-index') || '0', 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
if (this.shadowRoot) return
|
if (this.shadowRoot) return;
|
||||||
|
|
||||||
this.attachShadow({ mode: 'open' }).appendChild(document.createElement('slot'))
|
this.attachShadow({ mode: 'open' }).appendChild(document.createElement('slot'));
|
||||||
|
|
||||||
const uriSegments = window.location.pathname.split('/').filter(Boolean)
|
const uriSegments = window.location.pathname.split('/').filter(Boolean);
|
||||||
let pageNumber = this.extractPageNumber(uriSegments)
|
let pageNumber = this.extractPageNumber(uriSegments);
|
||||||
if (pageNumber === null) pageNumber = this.baseIndex
|
if (pageNumber === null) pageNumber = this.baseIndex;
|
||||||
|
|
||||||
this.control = this.querySelector('select')
|
this.control = this.querySelector('select');
|
||||||
this.control.value = pageNumber.toString()
|
this.control.value = pageNumber.toString();
|
||||||
this.control.addEventListener('change', (event) => {
|
this.control.addEventListener('change', (event) => {
|
||||||
pageNumber = parseInt(event.target.value)
|
pageNumber = parseInt(event.target.value);
|
||||||
const updatedUrlSegments = this.updateUrlSegments(uriSegments, pageNumber)
|
const updatedUrlSegments = this.updateUrlSegments(uriSegments, pageNumber);
|
||||||
window.location.href = `${window.location.origin}/${updatedUrlSegments.join('/')}`
|
window.location.href = `${window.location.origin}/${updatedUrlSegments.join('/')}`;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
extractPageNumber(segments) {
|
extractPageNumber(segments) {
|
||||||
const lastSegment = segments[segments.length - 1]
|
const lastSegment = segments[segments.length - 1];
|
||||||
return !isNaN(lastSegment) ? parseInt(lastSegment) : null
|
return !isNaN(lastSegment) ? parseInt(lastSegment) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUrlSegments(segments, pageNumber) {
|
updateUrlSegments(segments, pageNumber) {
|
||||||
const lastIsPage = !isNaN(segments[segments.length - 1])
|
const lastIsPage = !isNaN(segments[segments.length - 1]);
|
||||||
|
|
||||||
if (lastIsPage) {
|
if (lastIsPage) {
|
||||||
segments[segments.length - 1] = pageNumber.toString()
|
segments[segments.length - 1] = pageNumber.toString();
|
||||||
} else {
|
} else {
|
||||||
segments.push(pageNumber.toString())
|
segments.push(pageNumber.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageNumber === this.baseIndex) segments.pop()
|
if (pageNumber === this.baseIndex) segments.pop();
|
||||||
|
|
||||||
return segments
|
return segments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectPagination.register()
|
SelectPagination.register();
|
||||||
|
|
|
@ -21,7 +21,9 @@ window.addEventListener('load', () => {
|
||||||
if (isDynamic && !isLoaded) {
|
if (isDynamic && !isLoaded) {
|
||||||
const markdownFields = dialog.dataset.markdown || '';
|
const markdownFields = dialog.dataset.markdown || '';
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`/api/query.php?data=${isDynamic}&id=${dialogId}&markdown=${encodeURIComponent(markdownFields)}`);
|
const res = await fetch(
|
||||||
|
`/api/query.php?data=${isDynamic}&id=${dialogId}&markdown=${encodeURIComponent(markdownFields)}`
|
||||||
|
);
|
||||||
const [data] = await res.json();
|
const [data] = await res.json();
|
||||||
const firstField = markdownFields.split(',')[0]?.trim();
|
const firstField = markdownFields.split(',')[0]?.trim();
|
||||||
const html = data?.[`${firstField}_html`] || '<p>No notes available.</p>';
|
const html = data?.[`${firstField}_html`] || '<p>No notes available.</p>';
|
||||||
|
|
|
@ -7,22 +7,23 @@ const staticAssets = [
|
||||||
'/assets/fonts/dmi.woff2',
|
'/assets/fonts/dmi.woff2',
|
||||||
'/assets/fonts/ml.woff2',
|
'/assets/fonts/ml.woff2',
|
||||||
'/assets/scripts/index.js',
|
'/assets/scripts/index.js',
|
||||||
'/assets/scripts/components/select-pagination.js',
|
'/assets/scripts/components/select-pagination.js'
|
||||||
];
|
];
|
||||||
|
|
||||||
self.addEventListener('install', event => {
|
self.addEventListener('install', (event) => {
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
caches.open(cacheName)
|
caches
|
||||||
.then(cache => cache.addAll(staticAssets))
|
.open(cacheName)
|
||||||
|
.then((cache) => cache.addAll(staticAssets))
|
||||||
.then(() => self.skipWaiting())
|
.then(() => self.skipWaiting())
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('activate', event => {
|
self.addEventListener('activate', (event) => {
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
(async () => {
|
(async () => {
|
||||||
const keys = await caches.keys();
|
const keys = await caches.keys();
|
||||||
await Promise.all(keys.filter(key => key !== cacheName).map(key => caches.delete(key)));
|
await Promise.all(keys.filter((key) => key !== cacheName).map((key) => caches.delete(key)));
|
||||||
|
|
||||||
if (self.registration.navigationPreload) await self.registration.navigationPreload.enable();
|
if (self.registration.navigationPreload) await self.registration.navigationPreload.enable();
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ self.addEventListener('activate', event => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('fetch', event => {
|
self.addEventListener('fetch', (event) => {
|
||||||
const request = event.request;
|
const request = event.request;
|
||||||
|
|
||||||
if (request.method !== 'GET') return;
|
if (request.method !== 'GET') return;
|
||||||
|
@ -51,6 +52,5 @@ self.addEventListener('fetch', event => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.respondWith(caches.match(request).then(response => response || fetch(request))
|
event.respondWith(caches.match(request).then((response) => response || fetch(request)));
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,46 +1,46 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Space Grotesk";
|
font-family: 'Space Grotesk';
|
||||||
src: url("/assets/fonts/sg.woff2") format("woff2");
|
src: url('/assets/fonts/sg.woff2') format('woff2');
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "DM Sans";
|
font-family: 'DM Sans';
|
||||||
src: url("/assets/fonts/dm-regular.woff2") format("woff2");
|
src: url('/assets/fonts/dm-regular.woff2') format('woff2');
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "DM Sans";
|
font-family: 'DM Sans';
|
||||||
src: url("/assets/fonts/dm-bold.woff2") format("woff2");
|
src: url('/assets/fonts/dm-bold.woff2') format('woff2');
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "DM Sans";
|
font-family: 'DM Sans';
|
||||||
src: url("/assets/fonts/dm-regular-italic.woff2") format("woff2");
|
src: url('/assets/fonts/dm-regular-italic.woff2') format('woff2');
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-display: optional;
|
font-display: optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "DM Sans";
|
font-family: 'DM Sans';
|
||||||
src: url("/assets/fonts/dm-bold-italic.woff2") format("woff2");
|
src: url('/assets/fonts/dm-bold-italic.woff2') format('woff2');
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-display: optional;
|
font-display: optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "MonoLisa";
|
font-family: 'MonoLisa';
|
||||||
src: url("/assets/fonts/ml.woff2") format("woff2");
|
src: url('/assets/fonts/ml.woff2') format('woff2');
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
|
|
|
@ -302,7 +302,9 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* headers */
|
/* headers */
|
||||||
h1, h2, h3 {
|
h1,
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
font-family: var(--font-heading);
|
font-family: var(--font-heading);
|
||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
line-height: var(--line-height-md);
|
line-height: var(--line-height-md);
|
||||||
|
@ -440,7 +442,7 @@ td {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: "";
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset-block-start: 0;
|
inset-block-start: 0;
|
||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
|
@ -492,7 +494,7 @@ main {
|
||||||
|
|
||||||
main,
|
main,
|
||||||
footer {
|
footer {
|
||||||
width: calc(var(--sizing-full) * .8);
|
width: calc(var(--sizing-full) * 0.8);
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
max-width: 768px;
|
max-width: 768px;
|
||||||
|
|
|
@ -71,9 +71,10 @@
|
||||||
--border-gray: 1px solid var(--gray-light);
|
--border-gray: 1px solid var(--gray-light);
|
||||||
|
|
||||||
/* fonts */
|
/* fonts */
|
||||||
--font-body: "DM Sans", Helvetica Neue, Helvetica, Arial, system-ui, sans-serif;
|
--font-body: 'DM Sans', Helvetica Neue, Helvetica, Arial, system-ui, sans-serif;
|
||||||
--font-heading: "Space Grotesk", "Arial Black", "Arial Bold", Gadget, sans-serif;
|
--font-heading: 'Space Grotesk', 'Arial Black', 'Arial Bold', Gadget, sans-serif;
|
||||||
--font-code: "MonoLisa", SFMono-Regular, Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
--font-code:
|
||||||
|
'MonoLisa', SFMono-Regular, Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
||||||
|
|
||||||
/* text */
|
/* text */
|
||||||
--font-size-xs: 0.7rem;
|
--font-size-xs: 0.7rem;
|
||||||
|
@ -152,7 +153,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* transitions */
|
/* transitions */
|
||||||
--transition-ease-in-out: cubic-bezier(.4, 0, .2, 1);
|
--transition-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
--transition-duration-default: 300ms;
|
--transition-duration-default: 300ms;
|
||||||
|
|
||||||
/* transforms */
|
/* transforms */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import url("./text-toggle.css");
|
@import url('./text-toggle.css');
|
||||||
|
|
||||||
button:not([data-dialog-button]),
|
button:not([data-dialog-button]),
|
||||||
.button {
|
.button {
|
||||||
|
|
|
@ -1,11 +1,23 @@
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
from { opacity: 0; transform: scale(0.95); }
|
from {
|
||||||
to { opacity: 1; transform: scale(1); }
|
opacity: 0;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeOut {
|
@keyframes fadeOut {
|
||||||
from { opacity: 1; transform: scale(1); }
|
from {
|
||||||
to { opacity: 0; transform: scale(0.95); }
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-open,
|
.dialog-open,
|
||||||
|
@ -14,7 +26,8 @@
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
color: var(--section-color, var(--accent-color));
|
color: var(--section-color, var(--accent-color));
|
||||||
transform: var(--transform-icon-default);
|
transform: var(--transform-icon-default);
|
||||||
transition: color var(--transition-duration-default) var(--transition-ease-in-out),
|
transition:
|
||||||
|
color var(--transition-duration-default) var(--transition-ease-in-out),
|
||||||
transform var(--transition-duration-default) var(--transition-ease-in-out);
|
transform var(--transition-duration-default) var(--transition-ease-in-out);
|
||||||
|
|
||||||
&:is(:hover, :focus, :active) {
|
&:is(:hover, :focus, :active) {
|
||||||
|
@ -61,9 +74,9 @@ dialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
max-width: calc(var(--sizing-full) * .6);
|
max-width: calc(var(--sizing-full) * 0.6);
|
||||||
max-height: calc(var(--sizing-full) * .75);
|
max-height: calc(var(--sizing-full) * 0.75);
|
||||||
inset: calc(var(--sizing-full) * .125) calc(var(--sizing-full) * .2);
|
inset: calc(var(--sizing-full) * 0.125) calc(var(--sizing-full) * 0.2);
|
||||||
border: var(--border-gray);
|
border: var(--border-gray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
::placeholder {
|
::placeholder {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
accent-color: var(--section-color, var(--accent-color));
|
accent-color: var(--section-color, var(--accent-color));
|
||||||
}
|
}
|
||||||
|
|
||||||
input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]),
|
input:not([type='button']):not([type='submit']):not([type='reset']):not([type='checkbox']),
|
||||||
textarea {
|
textarea {
|
||||||
width: var(--sizing-full);
|
width: var(--sizing-full);
|
||||||
}
|
}
|
||||||
|
|
||||||
input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]),
|
input:not([type='button']):not([type='submit']):not([type='reset']):not([type='checkbox']),
|
||||||
textarea,
|
textarea,
|
||||||
select {
|
select {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
|
@ -23,7 +23,7 @@ select {
|
||||||
}
|
}
|
||||||
|
|
||||||
form,
|
form,
|
||||||
input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]),
|
input:not([type='button']):not([type='submit']):not([type='reset']):not([type='checkbox']),
|
||||||
textarea {
|
textarea {
|
||||||
margin-bottom: var(--spacing-base);
|
margin-bottom: var(--spacing-base);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ label svg {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail label:has(input[type="checkbox"]) {
|
detail label:has(input[type='checkbox']) {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
gap: var(--spacing-xs);
|
gap: var(--spacing-xs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
|
|
||||||
progress {
|
progress {
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
max-width: calc(var(--sizing-full) * .8);
|
max-width: calc(var(--sizing-full) * 0.8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
&::after {
|
&::after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
content: "";
|
content: '';
|
||||||
box-shadow: var(--box-shadow-text-toggle);
|
box-shadow: var(--box-shadow-text-toggle);
|
||||||
width: var(--sizing-full);
|
width: var(--sizing-full);
|
||||||
height: calc(var(--sizing-full) * .2);
|
height: calc(var(--sizing-full) * 0.2);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
@layer reset, defaults, base, page, components, plugins;
|
@layer reset, defaults, base, page, components, plugins;
|
||||||
|
|
||||||
/* style resets */
|
/* style resets */
|
||||||
@import url("./base/reset.css") layer(reset);
|
@import url('./base/reset.css') layer(reset);
|
||||||
|
|
||||||
/* core defaults */
|
/* core defaults */
|
||||||
@import url("./base/fonts.css") layer(defaults);
|
@import url('./base/fonts.css') layer(defaults);
|
||||||
@import url("./base/vars.css") layer(defaults);
|
@import url('./base/vars.css') layer(defaults);
|
||||||
|
|
||||||
/* base styles */
|
/* base styles */
|
||||||
@import url("./base/index.css") layer(base);
|
@import url('./base/index.css') layer(base);
|
||||||
|
|
||||||
/* page styles */
|
/* page styles */
|
||||||
@import url("./pages/contact.css") layer(page);
|
@import url('./pages/contact.css') layer(page);
|
||||||
@import url("./pages/links.css") layer(page);
|
@import url('./pages/links.css') layer(page);
|
||||||
@import url("./pages/media.css") layer(page);
|
@import url('./pages/media.css') layer(page);
|
||||||
@import url("./pages/music.css") layer(page);
|
@import url('./pages/music.css') layer(page);
|
||||||
@import url("./pages/reading.css") layer(page);
|
@import url('./pages/reading.css') layer(page);
|
||||||
@import url("./pages/watching.css") layer(page);
|
@import url('./pages/watching.css') layer(page);
|
||||||
@import url("./pages/webrings.css") layer(page);
|
@import url('./pages/webrings.css') layer(page);
|
||||||
|
|
||||||
/* plugins */
|
/* plugins */
|
||||||
@import url("./plugins/prism.css") layer(plugins);
|
@import url('./plugins/prism.css') layer(plugins);
|
||||||
|
|
||||||
/* component styles */
|
/* component styles */
|
||||||
@import url("./components/banners.css") layer(components);
|
@import url('./components/banners.css') layer(components);
|
||||||
@import url("./components/buttons.css") layer(components);
|
@import url('./components/buttons.css') layer(components);
|
||||||
@import url("./components/forms.css") layer(components);
|
@import url('./components/forms.css') layer(components);
|
||||||
@import url("./components/header.css") layer(components);
|
@import url('./components/header.css') layer(components);
|
||||||
@import url("./components/media-grid.css") layer(components);
|
@import url('./components/media-grid.css') layer(components);
|
||||||
@import url("./components/nav.css") layer(components);
|
@import url('./components/nav.css') layer(components);
|
||||||
@import url("./components/dialog.css") layer(components);
|
@import url('./components/dialog.css') layer(components);
|
||||||
@import url("./components/music-chart.css") layer(components);
|
@import url('./components/music-chart.css') layer(components);
|
||||||
@import url("./components/paginator.css") layer(components);
|
@import url('./components/paginator.css') layer(components);
|
||||||
@import url("./components/progress-bar.css") layer(components);
|
@import url('./components/progress-bar.css') layer(components);
|
||||||
@import url("./components/youtube-player.css") layer(components);
|
@import url('./components/youtube-player.css') layer(components);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* generic helper to hide client side content */
|
/* generic helper to hide client side content */
|
||||||
.client-side {
|
.client-side {
|
||||||
display:none
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unset text toggle implementation on artist + genre pages */
|
/* unset text toggle implementation on artist + genre pages */
|
||||||
|
|
|
@ -1,26 +1,23 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAlbumReleases = async () => {
|
const fetchAlbumReleases = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await EleventyFetch(
|
const data = await EleventyFetch(`${POSTGREST_URL}/optimized_album_releases`, {
|
||||||
`${POSTGREST_URL}/optimized_album_releases`,
|
duration: '1d',
|
||||||
{
|
type: 'json',
|
||||||
duration: "1d",
|
|
||||||
type: "json",
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const pacificNow = new Date().toLocaleString("en-US", {
|
const pacificNow = new Date().toLocaleString('en-US', {
|
||||||
timeZone: "America/Los_Angeles",
|
timeZone: 'America/Los_Angeles'
|
||||||
});
|
});
|
||||||
const pacificDate = new Date(pacificNow);
|
const pacificDate = new Date(pacificNow);
|
||||||
pacificDate.setHours(0, 0, 0, 0);
|
pacificDate.setHours(0, 0, 0, 0);
|
||||||
|
@ -32,25 +29,23 @@ const fetchAlbumReleases = async () => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...album,
|
...album,
|
||||||
description: album.artist?.description || "No description",
|
description: album.artist?.description || 'No description',
|
||||||
date: releaseDate.toLocaleDateString("en-US", {
|
date: releaseDate.toLocaleDateString('en-US', {
|
||||||
year: "numeric",
|
year: 'numeric',
|
||||||
month: "long",
|
month: 'long',
|
||||||
day: "numeric",
|
day: 'numeric'
|
||||||
}),
|
})
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort((a, b) => a.release_timestamp - b.release_timestamp);
|
.sort((a, b) => a.release_timestamp - b.release_timestamp);
|
||||||
|
|
||||||
const upcoming = all.filter(
|
const upcoming = all.filter(
|
||||||
(album) =>
|
(album) => album.release_timestamp > todayTimestamp && album.total_plays === 0
|
||||||
album.release_timestamp > todayTimestamp &&
|
|
||||||
album.total_plays === 0,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return { all, upcoming };
|
return { all, upcoming };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching and processing album releases:", error);
|
console.error('Error fetching and processing album releases:', error);
|
||||||
return { all: [], upcoming: [] };
|
return { all: [], upcoming: [] };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,27 +1,24 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
export default async function fetchAllActivity() {
|
export default async function fetchAllActivity() {
|
||||||
try {
|
try {
|
||||||
const data = await EleventyFetch(
|
const data = await EleventyFetch(`${POSTGREST_URL}/optimized_all_activity`, {
|
||||||
`${POSTGREST_URL}/optimized_all_activity`,
|
duration: '1h',
|
||||||
{
|
type: 'json',
|
||||||
duration: "1h",
|
|
||||||
type: "json",
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
);
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return data?.[0] || [];
|
return data?.[0] || [];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching activity:", error);
|
console.error('Error fetching activity:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchBlogroll = async () => {
|
const fetchBlogroll = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_blogroll`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_blogroll`, {
|
||||||
duration: "1d",
|
duration: '1d',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching and processing the blogroll:", error);
|
console.error('Error fetching and processing the blogroll:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,25 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAllBooks = async () => {
|
const fetchAllBooks = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_books?order=date_finished.desc`, {
|
||||||
`${POSTGREST_URL}/optimized_books?order=date_finished.desc`,
|
duration: '1h',
|
||||||
{
|
type: 'json',
|
||||||
duration: "1h",
|
|
||||||
type: "json",
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching books:", error);
|
console.error('Error fetching books:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -45,7 +42,7 @@ export default async function () {
|
||||||
const booksForCurrentYear =
|
const booksForCurrentYear =
|
||||||
sortedByYear
|
sortedByYear
|
||||||
.find((yearGroup) => yearGroup.value === currentYear)
|
.find((yearGroup) => yearGroup.value === currentYear)
|
||||||
?.data.filter((book) => book.status === "finished") || [];
|
?.data.filter((book) => book.status === 'finished') || [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
all: books,
|
all: books,
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAllConcerts = async () => {
|
const fetchAllConcerts = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_concerts`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_concerts`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching concerts:", error);
|
console.error('Error fetching concerts:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -24,7 +24,7 @@ const fetchAllConcerts = async () => {
|
||||||
const processConcerts = (concerts) =>
|
const processConcerts = (concerts) =>
|
||||||
concerts.map((concert) => ({
|
concerts.map((concert) => ({
|
||||||
...concert,
|
...concert,
|
||||||
artist: concert.artist || { name: concert.artist_name_string, url: null },
|
artist: concert.artist || { name: concert.artist_name_string, url: null }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
|
@ -32,7 +32,7 @@ export default async function () {
|
||||||
const concerts = await fetchAllConcerts();
|
const concerts = await fetchAllConcerts();
|
||||||
return processConcerts(concerts);
|
return processConcerts(concerts);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching and processing concerts data:", error);
|
console.error('Error fetching and processing concerts data:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchFeeds = async () => {
|
const fetchFeeds = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_feeds?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_feeds?select=*`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching feed metadata:", error);
|
console.error('Error fetching feed metadata:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -24,16 +24,16 @@ const fetchFeeds = async () => {
|
||||||
const fetchFeedData = async (feedKey) => {
|
const fetchFeedData = async (feedKey) => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/rpc/get_feed_data`, {
|
return await EleventyFetch(`${POSTGREST_URL}/rpc/get_feed_data`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
|
||||||
body: JSON.stringify({ feed_key: feedKey }),
|
|
||||||
},
|
},
|
||||||
|
body: JSON.stringify({ feed_key: feedKey })
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error fetching feed data for ${feedKey}:`, error);
|
console.error(`Error fetching feed data for ${feedKey}:`, error);
|
||||||
|
@ -48,9 +48,9 @@ export default async function () {
|
||||||
for (const feed of feeds) {
|
for (const feed of feeds) {
|
||||||
feedsWithData.push({
|
feedsWithData.push({
|
||||||
...feed,
|
...feed,
|
||||||
entries: await fetchFeedData(feed.data),
|
entries: await fetchFeedData(feed.data)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return feedsWithData;
|
return feedsWithData;
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,27 +1,24 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchGlobals = async () => {
|
const fetchGlobals = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await EleventyFetch(
|
const data = await EleventyFetch(`${POSTGREST_URL}/optimized_globals?select=*`, {
|
||||||
`${POSTGREST_URL}/optimized_globals?select=*`,
|
duration: '1d',
|
||||||
{
|
type: 'json',
|
||||||
duration: "1d",
|
|
||||||
type: "json",
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
return data[0];
|
return data[0];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching globals:", error);
|
console.error('Error fetching globals:', error);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,29 +1,31 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
const res = await EleventyFetch(`${POSTGREST_URL}/optimized_all_tags?order=tag.asc`, {
|
const res = await EleventyFetch(`${POSTGREST_URL}/optimized_all_tags?order=tag.asc`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
const tags = await res;
|
const tags = await res;
|
||||||
const groupedMap = new Map();
|
const groupedMap = new Map();
|
||||||
|
|
||||||
for (const tag of tags) {
|
for (const tag of tags) {
|
||||||
const letter = /^[a-zA-Z]/.test(tag.tag) ? tag.tag[0].toUpperCase() : "#";
|
const letter = /^[a-zA-Z]/.test(tag.tag) ? tag.tag[0].toUpperCase() : '#';
|
||||||
|
|
||||||
if (!groupedMap.has(letter)) groupedMap.set(letter, []);
|
if (!groupedMap.has(letter)) groupedMap.set(letter, []);
|
||||||
|
|
||||||
groupedMap.get(letter).push(tag);
|
groupedMap.get(letter).push(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...groupedMap.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([letter, tags]) => ({ letter, tags: tags.sort((a, b) => a.tag.localeCompare(b.tag)) }));
|
return [...groupedMap.entries()]
|
||||||
|
.sort(([a], [b]) => a.localeCompare(b))
|
||||||
|
.map(([letter, tags]) => ({ letter, tags: tags.sort((a, b) => a.tag.localeCompare(b.tag)) }));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchHeaders = async () => {
|
const fetchHeaders = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_headers?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_headers?select=*`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching header data:", error);
|
console.error('Error fetching header data:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAllLinks = async () => {
|
const fetchAllLinks = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_links?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_links?select=*`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching links:", error);
|
console.error('Error fetching links:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -26,6 +26,6 @@ export default async function () {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
all: links,
|
all: links,
|
||||||
feed: links.filter((links) => links.feed),
|
feed: links.filter((links) => links.feed)
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAllMovies = async () => {
|
const fetchAllMovies = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_movies?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_movies?select=*`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching movies:", error);
|
console.error('Error fetching movies:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -44,19 +44,17 @@ export default async function () {
|
||||||
movies,
|
movies,
|
||||||
watchHistory: movies.filter((movie) => movie.last_watched),
|
watchHistory: movies.filter((movie) => movie.last_watched),
|
||||||
recentlyWatched: recentlyWatchedMovies,
|
recentlyWatched: recentlyWatchedMovies,
|
||||||
favorites: favoriteMovies.sort((a, b) =>
|
favorites: favoriteMovies.sort((a, b) => a.title.localeCompare(b.title)),
|
||||||
a.title.localeCompare(b.title),
|
feed: movies.filter((movie) => movie.feed)
|
||||||
),
|
|
||||||
feed: movies.filter((movie) => movie.feed),
|
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching and processing movies data:", error);
|
console.error('Error fetching and processing movies data:', error);
|
||||||
return {
|
return {
|
||||||
movies: [],
|
movies: [],
|
||||||
watchHistory: [],
|
watchHistory: [],
|
||||||
recentlyWatched: [],
|
recentlyWatched: [],
|
||||||
favorites: [],
|
favorites: [],
|
||||||
feed: [],
|
feed: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchDataFromView = async (viewName) => {
|
const fetchDataFromView = async (viewName) => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/${viewName}?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/${viewName}?select=*`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error fetching data from view ${viewName}:`, error);
|
console.error(`Error fetching data from view ${viewName}:`, error);
|
||||||
|
@ -32,17 +32,17 @@ export default async function fetchMusicData() {
|
||||||
monthTracks,
|
monthTracks,
|
||||||
monthArtists,
|
monthArtists,
|
||||||
monthAlbums,
|
monthAlbums,
|
||||||
monthGenres,
|
monthGenres
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
fetchDataFromView("recent_tracks"),
|
fetchDataFromView('recent_tracks'),
|
||||||
fetchDataFromView("week_tracks"),
|
fetchDataFromView('week_tracks'),
|
||||||
fetchDataFromView("week_artists"),
|
fetchDataFromView('week_artists'),
|
||||||
fetchDataFromView("week_albums"),
|
fetchDataFromView('week_albums'),
|
||||||
fetchDataFromView("week_genres"),
|
fetchDataFromView('week_genres'),
|
||||||
fetchDataFromView("month_tracks"),
|
fetchDataFromView('month_tracks'),
|
||||||
fetchDataFromView("month_artists"),
|
fetchDataFromView('month_artists'),
|
||||||
fetchDataFromView("month_albums"),
|
fetchDataFromView('month_albums'),
|
||||||
fetchDataFromView("month_genres"),
|
fetchDataFromView('month_genres')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -52,9 +52,7 @@ export default async function fetchMusicData() {
|
||||||
artists: weekArtists,
|
artists: weekArtists,
|
||||||
albums: weekAlbums,
|
albums: weekAlbums,
|
||||||
genres: weekGenres,
|
genres: weekGenres,
|
||||||
totalTracks: weekTracks
|
totalTracks: weekTracks.reduce((acc, track) => acc + track.plays, 0).toLocaleString('en-US')
|
||||||
.reduce((acc, track) => acc + track.plays, 0)
|
|
||||||
.toLocaleString("en-US"),
|
|
||||||
},
|
},
|
||||||
month: {
|
month: {
|
||||||
tracks: monthTracks,
|
tracks: monthTracks,
|
||||||
|
@ -63,11 +61,11 @@ export default async function fetchMusicData() {
|
||||||
genres: monthGenres,
|
genres: monthGenres,
|
||||||
totalTracks: monthTracks
|
totalTracks: monthTracks
|
||||||
.reduce((acc, track) => acc + track.plays, 0)
|
.reduce((acc, track) => acc + track.plays, 0)
|
||||||
.toLocaleString("en-US"),
|
.toLocaleString('en-US')
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching and processing music data:", error);
|
console.error('Error fetching and processing music data:', error);
|
||||||
return {
|
return {
|
||||||
recent: [],
|
recent: [],
|
||||||
week: {
|
week: {
|
||||||
|
@ -75,15 +73,15 @@ export default async function fetchMusicData() {
|
||||||
artists: [],
|
artists: [],
|
||||||
albums: [],
|
albums: [],
|
||||||
genres: [],
|
genres: [],
|
||||||
totalTracks: "0",
|
totalTracks: '0'
|
||||||
},
|
},
|
||||||
month: {
|
month: {
|
||||||
tracks: [],
|
tracks: [],
|
||||||
artists: [],
|
artists: [],
|
||||||
albums: [],
|
albums: [],
|
||||||
genres: [],
|
genres: [],
|
||||||
totalTracks: "0",
|
totalTracks: '0'
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAllNavigation = async () => {
|
const fetchAllNavigation = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await EleventyFetch(
|
const data = await EleventyFetch(`${POSTGREST_URL}/optimized_navigation?select=*`, {
|
||||||
`${POSTGREST_URL}/optimized_navigation?select=*`,
|
duration: '1d',
|
||||||
{
|
type: 'json',
|
||||||
duration: "1d",
|
|
||||||
type: "json",
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const nav = data.reduce((acc, item) => {
|
const nav = data.reduce((acc, item) => {
|
||||||
const navItem = {
|
const navItem = {
|
||||||
|
@ -25,7 +22,7 @@ const fetchAllNavigation = async () => {
|
||||||
permalink: item.permalink || item.page_permalink,
|
permalink: item.permalink || item.page_permalink,
|
||||||
icon: item.icon,
|
icon: item.icon,
|
||||||
section: item.section,
|
section: item.section,
|
||||||
sort: item.sort,
|
sort: item.sort
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!acc[item.menu_location]) {
|
if (!acc[item.menu_location]) {
|
||||||
|
@ -43,7 +40,7 @@ const fetchAllNavigation = async () => {
|
||||||
|
|
||||||
return nav;
|
return nav;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching navigation data:", error);
|
console.error('Error fetching navigation data:', error);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAllPages = async () => {
|
const fetchAllPages = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_pages?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_pages?select=*`, {
|
||||||
duration: "1d",
|
duration: '1d',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching pages:", error);
|
console.error('Error fetching pages:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,25 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAllPosts = async () => {
|
const fetchAllPosts = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_posts?select=*&order=date.desc`, {
|
||||||
`${POSTGREST_URL}/optimized_posts?select=*&order=date.desc`,
|
duration: '1d',
|
||||||
{
|
type: 'json',
|
||||||
duration: "1d",
|
|
||||||
type: "json",
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching posts:", error);
|
console.error('Error fetching posts:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -29,6 +26,6 @@ export default async function () {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
all: posts,
|
all: posts,
|
||||||
feed: posts.filter((posts) => posts.feed),
|
feed: posts.filter((posts) => posts.feed)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,26 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
try {
|
try {
|
||||||
const data = await EleventyFetch(
|
const data = await EleventyFetch(`${POSTGREST_URL}/optimized_recent_activity`, {
|
||||||
`${POSTGREST_URL}/optimized_recent_activity`,
|
duration: '1h',
|
||||||
{
|
type: 'json',
|
||||||
duration: "1h",
|
|
||||||
type: "json",
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
);
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const feeds = data?.[0]?.feed || [];
|
const feeds = data?.[0]?.feed || [];
|
||||||
|
|
||||||
return feeds.filter((item) => item !== null);
|
return feeds.filter((item) => item !== null);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching recent activity:", error);
|
console.error('Error fetching recent activity:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchRedirects = async () => {
|
const fetchRedirects = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_redirects?select=*`, {
|
||||||
`${POSTGREST_URL}/optimized_redirects?select=*`,
|
duration: '1h',
|
||||||
{
|
type: 'json',
|
||||||
duration: "1h",
|
|
||||||
type: "json",
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching redirect data:", error);
|
console.error('Error fetching redirect data:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,33 +1,30 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAllRobots = async () => {
|
const fetchAllRobots = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await EleventyFetch(
|
const data = await EleventyFetch(`${POSTGREST_URL}/optimized_robots?select=path,user_agents`, {
|
||||||
`${POSTGREST_URL}/optimized_robots?select=path,user_agents`,
|
duration: '1h',
|
||||||
{
|
type: 'json',
|
||||||
duration: "1h",
|
|
||||||
type: "json",
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const sortedData = data.sort((a, b) => {
|
const sortedData = data.sort((a, b) => {
|
||||||
const aHasWildcard = a.user_agents.includes("*") ? 0 : 1;
|
const aHasWildcard = a.user_agents.includes('*') ? 0 : 1;
|
||||||
const bHasWildcard = b.user_agents.includes("*") ? 0 : 1;
|
const bHasWildcard = b.user_agents.includes('*') ? 0 : 1;
|
||||||
return aHasWildcard - bHasWildcard || a.path.localeCompare(b.path);
|
return aHasWildcard - bHasWildcard || a.path.localeCompare(b.path);
|
||||||
});
|
});
|
||||||
|
|
||||||
return sortedData;
|
return sortedData;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching robot data:", error);
|
console.error('Error fetching robot data:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchSitemap = async () => {
|
const fetchSitemap = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_sitemap?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_sitemap?select=*`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching sitemap entries:", error);
|
console.error('Error fetching sitemap entries:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchStats = async () => {
|
const fetchStats = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_stats?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_stats?select=*`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching stats data:", error);
|
console.error('Error fetching stats data:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
|
@ -7,21 +7,21 @@ const fetchTopAlbums = async () => {
|
||||||
const data = await EleventyFetch(
|
const data = await EleventyFetch(
|
||||||
`${POSTGREST_URL}/optimized_albums?select=table&order=total_plays_raw.desc&limit=8`,
|
`${POSTGREST_URL}/optimized_albums?select=table&order=total_plays_raw.desc&limit=8`,
|
||||||
{
|
{
|
||||||
duration: "1d",
|
duration: '1d',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching top albums:", error);
|
console.error('Error fetching top albums:', error);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
|
@ -7,21 +7,21 @@ const fetchTopArtists = async () => {
|
||||||
const data = await EleventyFetch(
|
const data = await EleventyFetch(
|
||||||
`${POSTGREST_URL}/optimized_artists?select=table&order=total_plays_raw.desc&limit=8`,
|
`${POSTGREST_URL}/optimized_artists?select=table&order=total_plays_raw.desc&limit=8`,
|
||||||
{
|
{
|
||||||
duration: "1d",
|
duration: '1d',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching top artists:", error);
|
console.error('Error fetching top artists:', error);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchTopTags = async () => {
|
const fetchTopTags = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/rpc/get_top_tag_groups`, {
|
return await EleventyFetch(`${POSTGREST_URL}/rpc/get_top_tag_groups`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching top tag entries:", error);
|
console.error('Error fetching top tag entries:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchAllShows = async () => {
|
const fetchAllShows = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_shows?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_shows?select=*`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching shows:", error);
|
console.error('Error fetching shows:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -25,9 +25,7 @@ export default async function () {
|
||||||
try {
|
try {
|
||||||
const shows = await fetchAllShows();
|
const shows = await fetchAllShows();
|
||||||
|
|
||||||
const watchedShows = shows.filter(
|
const watchedShows = shows.filter((show) => show.last_watched_at !== null);
|
||||||
(show) => show.last_watched_at !== null,
|
|
||||||
);
|
|
||||||
|
|
||||||
const episodes = watchedShows.map((show) => ({
|
const episodes = watchedShows.map((show) => ({
|
||||||
title: show.episode.title,
|
title: show.episode.title,
|
||||||
|
@ -37,7 +35,7 @@ export default async function () {
|
||||||
image: show.episode.image,
|
image: show.episode.image,
|
||||||
backdrop: show.episode.backdrop,
|
backdrop: show.episode.backdrop,
|
||||||
last_watched_at: show.episode.last_watched_at,
|
last_watched_at: show.episode.last_watched_at,
|
||||||
grid: show.grid,
|
grid: show.grid
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -45,15 +43,15 @@ export default async function () {
|
||||||
recentlyWatched: episodes.slice(0, 125),
|
recentlyWatched: episodes.slice(0, 125),
|
||||||
favorites: shows
|
favorites: shows
|
||||||
.filter((show) => show.favorite)
|
.filter((show) => show.favorite)
|
||||||
.sort((a, b) => a.title.localeCompare(b.title)),
|
.sort((a, b) => a.title.localeCompare(b.title))
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching and processing shows data:", error);
|
console.error('Error fetching and processing shows data:', error);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
shows: [],
|
shows: [],
|
||||||
recentlyWatched: [],
|
recentlyWatched: [],
|
||||||
favorites: [],
|
favorites: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import EleventyFetch from "@11ty/eleventy-fetch";
|
import EleventyFetch from '@11ty/eleventy-fetch';
|
||||||
|
|
||||||
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
const { POSTGREST_URL, POSTGREST_API_KEY } = process.env;
|
||||||
|
|
||||||
const fetchUpcomingShows = async () => {
|
const fetchUpcomingShows = async () => {
|
||||||
try {
|
try {
|
||||||
return await EleventyFetch(`${POSTGREST_URL}/optimized_scheduled_shows?select=*`, {
|
return await EleventyFetch(`${POSTGREST_URL}/optimized_scheduled_shows?select=*`, {
|
||||||
duration: "1h",
|
duration: '1h',
|
||||||
type: "json",
|
type: 'json',
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: `Bearer ${POSTGREST_API_KEY}`,
|
Authorization: `Bearer ${POSTGREST_API_KEY}`
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching upcoming shows:", error);
|
console.error('Error fetching upcoming shows:', error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -25,5 +25,5 @@ export default async function () {
|
||||||
const data = await fetchUpcomingShows();
|
const data = await fetchUpcomingShows();
|
||||||
const upcomingShows = data?.[0]?.scheduled_shows;
|
const upcomingShows = data?.[0]?.scheduled_shows;
|
||||||
|
|
||||||
return upcomingShows
|
return upcomingShows;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue