import path from 'path' import fs from 'fs-extra' import { supportedLocales, defaultLocale, t, SupportedLocale, f } from './locales' import { loadQuizes, resolveInfo, getTags } from './list' import { toPlay, toQuizREADME, toAnswers } from './toUrl' import { Quiz, QuizMetaInfo } from './types' const DifficultyColors: Record = { warm: 'teal', easy: 'green', medium: 'f3c746', hard: 'red', extreme: 'purple', } const DifficultyRank = [ 'warm', 'easy', 'medium', 'hard', 'extreme', ] function escapeHtml(unsafe: string) { return unsafe .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, ''') } function toBadgeURL(label: string, text: string, color: string, args = '') { return `https://img.shields.io/badge/${encodeURIComponent(label.replace(/-/g, '--'))}-${encodeURIComponent(text.replace(/-/g, '--'))}-${color}${args}` } function toBadge(label: string, text: string, color: string, args = '') { return `${text}` } function toBadgeLink(url: string, label: string, text: string, color: string, args = '') { return `${toBadge(label, text, color, args)} ` } function toAuthorInfo(author: Partial = {}) { return `by ${author.name}${author.github ? ` @${author.github}` : ''}` } function toDifficultyBadge(difficulty: string, locale: SupportedLocale) { return toBadge('', t(locale, `difficulty.${difficulty}`), DifficultyColors[difficulty]) } async function insertInfoReadme(filepath: string, quiz: Quiz, locale: SupportedLocale) { if (!fs.existsSync(filepath)) return let text = await fs.readFile(filepath, 'utf-8') /* eslint-disable prefer-template */ if (!text.match(/[\s\S]*/)) text = `\n\n${text}` if (!text.match(/[\s\S]*/)) text = `${text}\n\n` const info = resolveInfo(quiz, locale) text = text .replace( /[\s\S]*/, '' + `

${escapeHtml(info.title || '')} ${toDifficultyBadge(quiz.difficulty, locale)} ${getTags(quiz, locale).map(i => toBadge('', `#${i}`, '999')).join(' ')}

` + `

${toAuthorInfo(info.author)}

` + toBadgeLink(toPlay(quiz.no, locale), '', t(locale, 'take-the-challenge'), 'blue', '?logo=typescript') + '

' + '', ) .replace( /[\s\S]*/, '' + toBadgeLink(`../../${f('README', locale, 'md')}`, '', t(locale, 'back'), 'grey') + toBadgeLink(toAnswers(quiz.no), '', t(locale, 'see-answers'), 'F59BAF', '?logo=awesome-lists&logoColor=white') + '', ) /* eslint-enable prefer-template */ await fs.writeFile(filepath, text, 'utf-8') } export async function build() { const quizes = await loadQuizes() quizes.sort((a, b) => DifficultyRank.indexOf(a.difficulty) - DifficultyRank.indexOf(b.difficulty)) const questionsDir = path.resolve(__dirname, '../questions') // update index README for (const locale of supportedLocales) { const filepath = path.resolve(__dirname, '..', f('README', locale, 'md')) let challengesREADME = '' let prev = '' for (const quiz of quizes) { if (prev !== quiz.difficulty) challengesREADME += `${prev ? '

' : ''}${toDifficultyBadge(quiz.difficulty, locale)}
` challengesREADME += toBadgeLink( toQuizREADME(quiz, locale), '', `#${quiz.no}・${quiz.info[locale]?.title || quiz.info[defaultLocale]?.title}`, DifficultyColors[quiz.difficulty], ) prev = quiz.difficulty } let readme = await fs.readFile(filepath, 'utf-8') readme = readme.replace( /[\s\S]*/m, `\n${challengesREADME}\n`, ) await fs.writeFile(filepath, readme, 'utf-8') } // update each questions' readme for (const quiz of quizes) { for (const locale of supportedLocales) { await insertInfoReadme( path.join( questionsDir, quiz.path, f('README', locale, 'md'), ), quiz, locale, ) } } } build()