add eslint

This commit is contained in:
Fabrice Lamant
2024-07-10 11:11:40 +01:00
parent 371982f547
commit c82cdbcbe1
5 changed files with 1108 additions and 119 deletions

26
eslint.config.mjs Normal file
View File

@ -0,0 +1,26 @@
import globals from "globals";
import pluginJs from "@eslint/js";
export default [
{
files: ["**/*.js"],
languageOptions: {
sourceType: "commonjs",
},
},
{
languageOptions: {
globals: globals.node,
},
},
pluginJs.configs.recommended,
{
rules: {
"comma-dangle": ["error", "always-multiline"],
complexity: ["error", 8],
quotes: ["error", "double"],
semi: ["error", "always"],
},
},
];

239
index.js
View File

@ -1,8 +1,8 @@
const cheerio = require('cheerio'); const cheerio = require("cheerio");
const fs = require('fs'); const fs = require("fs");
const autoprefixer = require('autoprefixer'); const autoprefixer = require("autoprefixer");
const postcss = require('postcss'); const postcss = require("postcss");
const tailwindcss = require('tailwindcss'); const tailwindcss = require("tailwindcss");
const downloadSchedule = async (sportKey) => { const downloadSchedule = async (sportKey) => {
const cacheFile = `${__dirname}/cache/${sportKey}.html`; const cacheFile = `${__dirname}/cache/${sportKey}.html`;
@ -13,87 +13,96 @@ const downloadSchedule = async (sportKey) => {
fs.writeFileSync(cacheFile, content); fs.writeFileSync(cacheFile, content);
} }
const html = fs.readFileSync(cacheFile, 'utf-8'); const html = fs.readFileSync(cacheFile, "utf-8");
const $ = cheerio.load(html); const $ = cheerio.load(html);
return JSON.parse($('#__NEXT_DATA__').text()); return JSON.parse($("#__NEXT_DATA__").text());
}; };
const getSportIcon = (sport) => { const getSportIcon = (sport) => {
switch (sport.toLowerCase()) { const sports = {
case "3x3-basketball": return "🏀③" "3x3-basketball": "🏀③",
case "basketball": return "🏀"; "basketball": "🏀",
case "football": return "⚽"; "football": "⚽",
case "handball": return "🤾"; "handball": "🤾",
case "hockey": return "🏑"; "hockey": "🏑",
case "rugby-sevens": return "🏉"; "rugby-sevens": "🏉",
case "volleyball": return "🏐"; "volleyball": "🏐",
case "water-polo": return "🤽"; "water-polo": "🤽",
default: throw new Error(`No icon set for ${sport}`); };
if (sports[sport]) {
return sports[sport];
} }
throw new Error(`No icon set for ${sport}`);
}; };
const getFlagIcon = (country) => { const getFlagIcon = (country) => {
if (country.toLowerCase().startsWith("winner oqt")) { if (country.toLowerCase().startsWith("winner oqt")) {
return "🏳️"; return "🏳️";
} }
switch (country.toLowerCase()) {
case "angola": return "🇦🇴"; const teams = {
case "argentina": return "🇦🇷"; "angola": "🇦🇴",
case "australia": return "🇦🇺"; "argentina": "🇦🇷",
case "azerbaijan": return "🇦🇿"; "australia": "🇦🇺",
case "belgium": return "🇧🇪"; "azerbaijan": "🇦🇿",
case "brazil": return "🇧🇷"; "belgium": "🇧🇪",
case "canada": return "🇨🇦"; "brazil": "🇧🇷",
case "china": return "🇨🇳"; "canada": "🇨🇦",
case "colombia": return "🇨🇴"; "china": "🇨🇳",
case "croatia": return "🇭🇷"; "colombia": "🇨🇴",
case "denmark": return "🇩🇰"; "croatia": "🇭🇷",
case "dominican republic": return "🇩🇴"; "denmark": "🇩🇰",
case "fiji": return "🇫🇯"; "dominican republic": "🇩🇴",
case "france": return "🇫🇷"; "fiji": "🇫🇯",
case "egypt": return "🇪🇬"; "france": "🇫🇷",
case "germany": return "🇩🇪"; "egypt": "🇪🇬",
case "great britain": return "🇬🇧"; "germany": "🇩🇪",
case "greece": return "🇬🇷"; "great britain": "🇬🇧",
case "guinea": return "🇬🇳"; "greece": "🇬🇷",
case "hungary": return "🇭🇺"; "guinea": "🇬🇳",
case "india": return "🇮🇳"; "hungary": "🇭🇺",
case "iraq": return "🇮🇶"; "india": "🇮🇳",
case "ireland": return "🇮🇪"; "iraq": "🇮🇶",
case "israel": return "🇮🇱"; "ireland": "🇮🇪",
case "italy": return "🇮🇱"; "israel": "🇮🇱",
case "japan": return "🇯🇵"; "italy": "🇮🇱",
case "kenya": return "🇰🇪"; "japan": "🇯🇵",
case "latvia": return "🇱🇻"; "kenya": "🇰🇪",
case "lithuania": return "🇱🇹"; "latvia": "🇱🇻",
case "korea": return "🇰🇷"; "lithuania": "🇱🇹",
case "mali": return "🇲🇱"; "korea": "🇰🇷",
case "montenegro": return "🇲🇪"; "mali": "🇲🇱",
case "morocco": return "🇲🇦"; "montenegro": "🇲🇪",
case "nigeria": return "🇳🇬"; "morocco": "🇲🇦",
case "netherlands": return "🇳🇱"; "nigeria": "🇳🇬",
case "new zealand": return "🇳🇿"; "netherlands": "🇳🇱",
case "norway": return "🇳🇴"; "new zealand": "🇳🇿",
case "paraguay": return "🇵🇾"; "norway": "🇳🇴",
case "poland": return "🇵🇱"; "paraguay": "🇵🇾",
case "puerto rico": return "🇵🇷"; "poland": "🇵🇱",
case "romania": return "🇷🇴"; "puerto rico": "🇵🇷",
case "serbia": return "🇷🇸"; "romania": "🇷🇴",
case "south africa": return "🇿🇦"; "serbia": "🇷🇸",
case "south sudan": return "🇸🇸"; "south africa": "🇿🇦",
case "slovenia": return "🇸🇮"; "south sudan": "🇸🇸",
case "samoa": return "🇼🇸"; "slovenia": "🇸🇮",
case "spain": return "🇪🇸"; "samoa": "🇼🇸",
case "sweden": return "🇸🇪"; "spain": "🇪🇸",
case "türkiye": return "🇹🇷"; "sweden": "🇸🇪",
case "ukraine": return "🇺🇦"; "türkiye": "🇹🇷",
case "united states": return "🇺🇸"; "ukraine": "🇺🇦",
case "uruguay": return "🇺🇾"; "united states": "🇺🇸",
case "uzbekistan": return "🇺🇿"; "uruguay": "🇺🇾",
case "zambia": return "🇿🇲"; "uzbekistan": "🇺🇿",
default: throw new Error(`No flag set for ${country}`); "zambia": "🇿🇲",
};
if (teams[country.toLowerCase()]) {
return teams[country.toLowerCase()];
} }
} throw new Error(`No flag set for ${country}`);
};
const SPORTS = []; const SPORTS = [];
const TEAMS = []; const TEAMS = [];
@ -103,28 +112,28 @@ const OUTPUT = [];
const generateCalendar = (title, key, events) => { const generateCalendar = (title, key, events) => {
const lines = []; const lines = [];
lines.push(`BEGIN:VCALENDAR`); lines.push("BEGIN:VCALENDAR");
lines.push(`VERSION:2.0`); lines.push("VERSION:2.0");
lines.push(`PRODID:-//fabrice404//olympics-calendar//${key}//EN`); lines.push(`PRODID:-//fabrice404//olympics-calendar//${key}//EN`);
lines.push(`X-WR-CALNAME:${title}`); lines.push(`X-WR-CALNAME:${title}`);
lines.push(`NAME:${title}`); lines.push(`NAME:${title}`);
events.forEach((event) => { events.forEach((event) => {
lines.push(`BEGIN:VEVENT`); lines.push("BEGIN:VEVENT");
lines.push( lines.push(
...Object.entries(event) ...Object.entries(event)
.filter(([key, value]) => !key.startsWith('_')) .filter(([key]) => !key.startsWith("_"))
.map(([key, value]) => `${key}:${value}`) .map(([key, value]) => `${key}:${value}`),
); );
lines.push(`END:VEVENT`); lines.push("END:VEVENT");
}); });
lines.push(`END:VCALENDAR`); lines.push("END:VCALENDAR");
const folder = `${__dirname}/docs/${key}.ics`.split('/').slice(0, -1).join('/'); const folder = `${__dirname}/docs/${key}.ics`.split("/").slice(0, -1).join("/");
fs.mkdirSync(folder, { recursive: true }) fs.mkdirSync(folder, { recursive: true });
fs.writeFileSync(`${__dirname}/docs/${key}.ics`, lines.join('\r\n')); fs.writeFileSync(`${__dirname}/docs/${key}.ics`, lines.join("\r\n"));
} };
const generateSportCalendar = (sportKey) => { const generateSportCalendar = (sportKey) => {
const sport = SPORTS.find((sport) => sport.key === sportKey); const sport = SPORTS.find((sport) => sport.key === sportKey);
@ -143,7 +152,7 @@ const generateSportCalendar = (sportKey) => {
</div> </div>
</div> </div>
`); `);
} };
const generateSportTeamCalendar = (sportKey, teamKey) => { const generateSportTeamCalendar = (sportKey, teamKey) => {
const sport = SPORTS.find((sport) => sport.key === sportKey); const sport = SPORTS.find((sport) => sport.key === sportKey);
@ -182,7 +191,7 @@ const addSport = (name, key, icon) => {
if (!SPORTS.find((sport) => sport.key === key)) { if (!SPORTS.find((sport) => sport.key === key)) {
SPORTS.push({ name, key, icon, teams: [] }); SPORTS.push({ name, key, icon, teams: [] });
} }
} };
const addTeam = (name, key, icon) => { const addTeam = (name, key, icon) => {
if (!TEAMS.find((team) => team.key === key)) { if (!TEAMS.find((team) => team.key === key)) {
@ -195,7 +204,7 @@ const addSportTeam = (sportKey, teamKey) => {
if (sport && !sport.teams.includes(teamKey)) { if (sport && !sport.teams.includes(teamKey)) {
sport.teams.push(teamKey); sport.teams.push(teamKey);
} }
} };
const isValidTeam = (team) => !team.toLowerCase().startsWith("winner oqt"); const isValidTeam = (team) => !team.toLowerCase().startsWith("winner oqt");
@ -211,15 +220,15 @@ const teamSport = async (sportKey) => {
schedule.units.forEach(unit => { schedule.units.forEach(unit => {
const event = { const event = {
UID: `${sportKey}-${unit.startDateTimeUtc.replace(/[:-]/g, '')}`, UID: `${sportKey}-${unit.startDateTimeUtc.replace(/[:-]/g, "")}`,
DTSTAMP: unit.startDateTimeUtc.replace(/[:-]/g, ''), DTSTAMP: unit.startDateTimeUtc.replace(/[:-]/g, ""),
DTSTART: unit.startDateTimeUtc.replace(/[:-]/g, ''), DTSTART: unit.startDateTimeUtc.replace(/[:-]/g, ""),
DTEND: unit.endDateTimeUtc.replace(/[:-]/g, ''), DTEND: unit.endDateTimeUtc.replace(/[:-]/g, ""),
DESCRIPTION: `${sportName} - ${unit.description}`, DESCRIPTION: `${sportName} - ${unit.description}`,
SUMMARY: `${sportIcon} ${unit.description}`, SUMMARY: `${sportIcon} ${unit.description}`,
LOCATION: schedule.venue ? schedule.venue.description : unit.venue.description, LOCATION: schedule.venue ? schedule.venue.description : unit.venue.description,
_SPORT: sportKey, _SPORT: sportKey,
} };
if (unit.match && if (unit.match &&
unit.match.team1 && isValidTeam(unit.match.team1.description) && unit.match.team1 && isValidTeam(unit.match.team1.description) &&
@ -230,14 +239,14 @@ const teamSport = async (sportKey) => {
key: unit.match.team1.teamCode, key: unit.match.team1.teamCode,
icon: getFlagIcon(unit.match.team1.description), icon: getFlagIcon(unit.match.team1.description),
}; };
addTeam(team1.name, team1.key, team1.icon) addTeam(team1.name, team1.key, team1.icon);
const team2 = { const team2 = {
name: unit.match.team2.description, name: unit.match.team2.description,
key: unit.match.team2.teamCode, key: unit.match.team2.teamCode,
icon: getFlagIcon(unit.match.team2.description), icon: getFlagIcon(unit.match.team2.description),
}; };
addTeam(team2.name, team2.key, team2.icon) addTeam(team2.name, team2.key, team2.icon);
event.UID += `-${team1.key}-${team2.key}`; event.UID += `-${team1.key}-${team2.key}`;
event.SUMMARY = `${sportIcon} ${team1.key} ${team1.icon} - ${team2.icon} ${team2.key}`; event.SUMMARY = `${sportIcon} ${team1.key} ${team1.icon} - ${team2.icon} ${team2.key}`;
@ -251,55 +260,55 @@ const teamSport = async (sportKey) => {
}); });
}); });
} };
const teamSports = async () => { const teamSports = async () => {
await Promise.all( await Promise.all(
[ [
'3x3-basketball', "3x3-basketball",
'basketball', "basketball",
'football', "football",
'handball', "handball",
'hockey', "hockey",
'rugby-sevens', "rugby-sevens",
'volleyball', "volleyball",
'water-polo', "water-polo",
] ]
.map((key) => teamSport(key)) .map((key) => teamSport(key)),
); );
SPORTS.sort((a, b) => a.name > b.name ? 1 : -1).forEach((sport) => { SPORTS.sort((a, b) => a.name > b.name ? 1 : -1).forEach((sport) => {
const sportKey = sport.key; const sportKey = sport.key;
generateSportCalendar(sportKey); generateSportCalendar(sportKey);
OUTPUT.push("<ul>") OUTPUT.push("<ul>");
sport.teams sport.teams
.sort((a, b) => a > b ? 1 : -1) .sort((a, b) => a > b ? 1 : -1)
.forEach((teamKey) => { .forEach((teamKey) => {
generateSportTeamCalendar(sportKey, teamKey); generateSportTeamCalendar(sportKey, teamKey);
}); });
OUTPUT.push("</ul>") OUTPUT.push("</ul>");
}); });
OUTPUT.push(`<div class="text-3xl pb-4 pt-8">🌍 Teams</div>`); OUTPUT.push("<div class=\"text-3xl pb-4 pt-8\">🌍 Teams</div>");
TEAMS TEAMS
.sort((a, b) => a.name > b.name ? 1 : -1) .sort((a, b) => a.name > b.name ? 1 : -1)
.forEach((team) => { .forEach((team) => {
generateTeamCalendar(team.key); generateTeamCalendar(team.key);
}); });
} };
const main = async () => { const main = async () => {
await teamSports(); await teamSports();
const template = fs.readFileSync(`${__dirname}/template.html`, 'utf-8'); const template = fs.readFileSync(`${__dirname}/template.html`, "utf-8");
const output = template.replace('{{calendars}}', OUTPUT.join('\n')); const output = template.replace("{{calendars}}", OUTPUT.join("\n"));
fs.writeFileSync('docs/index.html', output); fs.writeFileSync("docs/index.html", output);
postcss([autoprefixer, tailwindcss]) postcss([autoprefixer, tailwindcss])
.process(fs.readFileSync(`${__dirname}/template.css`, 'utf-8'), { from: 'template.css', to: 'docs/style.css' }) .process(fs.readFileSync(`${__dirname}/template.css`, "utf-8"), { from: "template.css", to: "docs/style.css" })
.then((result) => { .then((result) => {
fs.writeFileSync('docs/style.css', result.css); fs.writeFileSync("docs/style.css", result.css);
}) });
}; };

955
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,19 @@
"version": "1.0.0", "version": "1.0.0",
"main": "handball.js", "main": "handball.js",
"scripts": { "scripts": {
"start": "node index.js",
"lint": "eslint .",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"description": "", "description": "",
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.6.0",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"cheerio": "^1.0.0-rc.12", "cheerio": "^1.0.0-rc.12",
"eslint": "^9.6.0",
"globals": "^15.8.0",
"postcss": "^8.4.39", "postcss": "^8.4.39",
"tailwindcss": "^3.4.4" "tailwindcss": "^3.4.4"
} }

View File

@ -5,5 +5,5 @@ module.exports = {
extend: {}, extend: {},
}, },
plugins: [], plugins: [],
} };