From c8b1e90bf2b9a41bf41b2e6b77365088db287399 Mon Sep 17 00:00:00 2001 From: Him-an-shi Date: Tue, 9 Jun 2026 00:25:30 +0530 Subject: [PATCH 1/3] Added Word Of The Day Feature --- README.md | 14 +++++++- api/widget.js | 3 +- index.html | 94 +++++++++++++++++++++++++++++++++++++++++++++++++- lib/widgets.js | 70 +++++++++++++++++++++++++++++++++++++ vercel.json | 2 +- 5 files changed, 179 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7010ab2..7177679 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,15 @@ Combines your avatar, role, bio, skills, and handle into a clean profile header. Quote Preview -### 6. Location & Timezone +### 6. Word of the Day + +```md +![Word of the Day](https://readmeme.eu.cc/api/word.svg?theme=paper&label=Vocabulary&showOrigin=1) +``` + +Word of the Day Preview + +### 7. Location & Timezone ```md ![Country Flag](https://readmeme.eu.cc/api/flag.svg?theme=forest&country=JP&label=Based+In) @@ -202,6 +210,10 @@ Combines your avatar, role, bio, skills, and handle into a clean profile header. * `unit` * `platform` +### Word of the Day + +* `showOrigin` + ## Local Development Clone the repository: diff --git a/api/widget.js b/api/widget.js index 5b54354..74213f8 100644 --- a/api/widget.js +++ b/api/widget.js @@ -10,7 +10,7 @@ const { renderWidget } = require('../lib/widgets'); * 60 s max-age keeps clocks fresh without hammering the origin. * - date : Changes once per day; 1-hour cache is safe. * - music : Static mock data; 5-minute cache balances freshness and load. - * - streak / quote / profile: Daily-changing or mostly-static data; 1-hour cache is appropriate. + * - streak / quote / word / profile: Daily-changing or mostly-static data; 1-hour cache is appropriate. * - flag : Country data never changes; 24-hour cache maximises CDN hits. */ const CACHE_POLICIES = { @@ -22,6 +22,7 @@ const CACHE_POLICIES = { // Daily-change widgets — refresh every hour date: 'public, max-age=3600, s-maxage=3600, stale-while-revalidate=600', quote: 'public, max-age=3600, s-maxage=3600, stale-while-revalidate=600', + word: 'public, max-age=3600, s-maxage=3600, stale-while-revalidate=600', streak: 'public, max-age=3600, s-maxage=3600, stale-while-revalidate=600', profile: 'public, max-age=3600, s-maxage=3600, stale-while-revalidate=600', diff --git a/index.html b/index.html index b1ba4d0..249acf3 100644 --- a/index.html +++ b/index.html @@ -287,7 +287,7 @@

- 8 + 10
Widget Types @@ -525,6 +525,7 @@

Stylish Readme

{ id:'clock', label:'Digital Clock', icon:'watch' }, { id:'date', label:'Date Stamp', icon:'calendar' }, { id:'quote', label:'Daily Quote', icon:'quote' }, + { id:'word', label:'Word of the Day', icon:'book-open' }, { id:'flag', label:'Country Flag', icon:'flag' }, { id:'timezone',label:'Timezone Banner', icon:'globe' }, { id:'streak', label:'Coding Streak', icon:'flame' }, @@ -723,6 +724,19 @@

Stylish Readme

{ q:'Simplicity is the soul of efficiency.', a:'Austin Freeman' } ]; + const WORDS = [ + { word:'Serendipity', pronunciation:'/ser-en-DIP-i-tee/', partOfSpeech:'Noun', definition:'The occurrence of finding something valuable or pleasant by chance.', example:'Meeting my mentor at the conference was pure serendipity.', synonyms:'chance, fortune, luck', origin:'Coined from The Three Princes of Serendip, a tale about accidental discoveries.' }, + { word:'Eloquent', pronunciation:'/EL-uh-kwent/', partOfSpeech:'Adjective', definition:'Fluent, expressive, and persuasive in speech or writing.', example:'Her eloquent README made the project feel instantly approachable.', synonyms:'expressive, articulate, persuasive', origin:'From Latin eloqui, meaning to speak out.' }, + { word:'Resilient', pronunciation:'/ri-ZIL-yent/', partOfSpeech:'Adjective', definition:'Able to recover quickly from difficulty or change.', example:'The resilient team shipped a cleaner fix after the outage.', synonyms:'adaptable, tough, flexible', origin:'From Latin resilire, meaning to spring back.' }, + { word:'Lucid', pronunciation:'/LOO-sid/', partOfSpeech:'Adjective', definition:'Clear, easy to understand, or rational.', example:'A lucid explanation can make complex code feel friendly.', synonyms:'clear, coherent, intelligible', origin:'From Latin lucidus, meaning bright or clear.' }, + { word:'Meticulous', pronunciation:'/meh-TIK-yuh-lus/', partOfSpeech:'Adjective', definition:'Showing great attention to detail.', example:'The meticulous review caught a subtle accessibility issue.', synonyms:'careful, precise, thorough', origin:'From Latin meticulosus, originally meaning fearful or timid.' }, + { word:'Ephemeral', pronunciation:'/ih-FEM-er-uhl/', partOfSpeech:'Adjective', definition:'Lasting for a very short time.', example:'The ephemeral preview refreshed as soon as the settings changed.', synonyms:'brief, fleeting, temporary', origin:'From Greek ephemeros, meaning lasting only a day.' }, + { word:'Pragmatic', pronunciation:'/prag-MAT-ik/', partOfSpeech:'Adjective', definition:'Focused on practical results and real-world usefulness.', example:'A pragmatic design kept the widget simple to customize.', synonyms:'practical, realistic, sensible', origin:'From Greek pragmatikos, meaning fit for action.' }, + { word:'Tenacious', pronunciation:'/tuh-NAY-shus/', partOfSpeech:'Adjective', definition:'Persistent and determined, especially when facing obstacles.', example:'Her tenacious debugging turned a vague error into a clear fix.', synonyms:'persistent, determined, steadfast', origin:'From Latin tenere, meaning to hold.' }, + { word:'Nuance', pronunciation:'/NOO-ahns/', partOfSpeech:'Noun', definition:'A subtle difference in meaning, feeling, or expression.', example:'Good documentation captures the nuance behind each option.', synonyms:'subtlety, shade, distinction', origin:'From French nuance, meaning shade or subtle variation.' }, + { word:'Candid', pronunciation:'/KAN-did/', partOfSpeech:'Adjective', definition:'Truthful, direct, and sincere.', example:'The candid changelog explained both the fix and the tradeoff.', synonyms:'honest, frank, open', origin:'From Latin candidus, meaning white or shining.' } + ]; + const SONGS = [ // Bollywood { title:'Tum Hi Ho', artist:'Arijit Singh', year:'2013', genre:'Bollywood' }, @@ -757,6 +771,8 @@

Stylish Readme

country: 'IN', // Quote quoteCategory: 'programming', + // Word of the day + showOrigin: true, // Clock style clockStyle: 'digital', // Streak @@ -921,6 +937,27 @@

Stylish Readme

`; } + else if (state.widget==='word'){ + html += ` +
+ + ${themeSwatches()} +
+
+ + +
+
+ +
+
+ Note: A new vocabulary word is selected each day with pronunciation, definition, example, and synonyms. +
+ `; + } else if (state.widget==='flag'){ html += `
@@ -1183,6 +1220,58 @@

Stylish Readme

`; } + function wordLines(text, maxLen, maxLines){ + const words = String(text||'').split(/\s+/).filter(Boolean); + const lines=[]; let line=''; + words.forEach(w=>{ + if(lines.length>=maxLines) return; + if((line+' '+w).trim().length>maxLen){ + if(line) lines.push(line.trim()); + line=w; + } else { + line=(line+' '+w).trim(); + } + }); + if(line && lines.length + + + ${(state.label||'WORD OF THE DAY').toUpperCase()} + ${item.word} + ${item.pronunciation} + + ${item.partOfSpeech.toUpperCase()} + + DEFINITION + ${definition.map((line,i)=>`${line}`).join('')} + EXAMPLE + ${example.map((line,i)=>`${line}`).join('')} + SYNONYMS + ${item.synonyms} + ${state.showOrigin?` + ORIGIN + ${origin.map((line,i)=>`${line}`).join('')} + `:''} + `; + } + function svgFlag(){ const theme = themeObj(state.theme); const country = COUNTRIES.find(c=>c.code===state.country) || COUNTRIES[0]; @@ -1371,6 +1460,7 @@

Stylish Readme

case 'clock': return svgClock(); case 'date': return svgDate(); case 'quote': return svgQuote(); + case 'word': return svgWord(); case 'flag': return svgFlag(); case 'timezone': return svgTimezone(); case 'streak': return svgStreak(); @@ -1393,6 +1483,7 @@

Stylish Readme

clock: ['timezone','theme','timeFormat','showSeconds','label'], date: ['timezone','theme','label'], quote: ['theme','quoteCategory','label'], + word: ['theme','label','showOrigin'], flag: ['country','theme','label'], timezone: ['timezone','theme','timeFormat'], streak: ['startDate','unit','theme','customLabel','platform'], @@ -1465,6 +1556,7 @@

Stylish Readme

{ title:'Tokyo Time', w:'time', overrides:{timezone:'Asia/Tokyo',theme:'terminal',label:'Tokyo'} }, { title:'New York Clock', w:'clock', overrides:{timezone:'America/New_York',theme:'paper',label:'Eastern'} }, { title:'Daily Quote', w:'quote', overrides:{theme:'crimson',label:'Today'} }, + { title:'Word of the Day', w:'word', overrides:{theme:'paper',label:'Vocabulary',showOrigin:true} }, { title:'London Date', w:'date', overrides:{theme:'retro',timezone:'Europe/London',label:'Today'} }, { title:'NYC Timezone', w:'timezone', overrides:{theme:'ocean',timezone:'America/New_York'} }, { title:'India Flag', w:'flag', overrides:{country:'IN',theme:'forest',label:'From'} }, diff --git a/lib/widgets.js b/lib/widgets.js index f6bb809..1412c23 100644 --- a/lib/widgets.js +++ b/lib/widgets.js @@ -80,6 +80,19 @@ const QUOTE_SETS = { }; QUOTE_SETS.random = [].concat(QUOTE_SETS.programming, QUOTE_SETS.motivation, QUOTE_SETS.wisdom); +const WORDS = [ + { word:'Serendipity', pronunciation:'/ser-en-DIP-i-tee/', partOfSpeech:'Noun', definition:'The occurrence of finding something valuable or pleasant by chance.', example:'Meeting my mentor at the conference was pure serendipity.', synonyms:'chance, fortune, luck', origin:'Coined from The Three Princes of Serendip, a tale about accidental discoveries.' }, + { word:'Eloquent', pronunciation:'/EL-uh-kwent/', partOfSpeech:'Adjective', definition:'Fluent, expressive, and persuasive in speech or writing.', example:'Her eloquent README made the project feel instantly approachable.', synonyms:'expressive, articulate, persuasive', origin:'From Latin eloqui, meaning to speak out.' }, + { word:'Resilient', pronunciation:'/ri-ZIL-yent/', partOfSpeech:'Adjective', definition:'Able to recover quickly from difficulty or change.', example:'The resilient team shipped a cleaner fix after the outage.', synonyms:'adaptable, tough, flexible', origin:'From Latin resilire, meaning to spring back.' }, + { word:'Lucid', pronunciation:'/LOO-sid/', partOfSpeech:'Adjective', definition:'Clear, easy to understand, or rational.', example:'A lucid explanation can make complex code feel friendly.', synonyms:'clear, coherent, intelligible', origin:'From Latin lucidus, meaning bright or clear.' }, + { word:'Meticulous', pronunciation:'/meh-TIK-yuh-lus/', partOfSpeech:'Adjective', definition:'Showing great attention to detail.', example:'The meticulous review caught a subtle accessibility issue.', synonyms:'careful, precise, thorough', origin:'From Latin meticulosus, originally meaning fearful or timid.' }, + { word:'Ephemeral', pronunciation:'/ih-FEM-er-uhl/', partOfSpeech:'Adjective', definition:'Lasting for a very short time.', example:'The ephemeral preview refreshed as soon as the settings changed.', synonyms:'brief, fleeting, temporary', origin:'From Greek ephemeros, meaning lasting only a day.' }, + { word:'Pragmatic', pronunciation:'/prag-MAT-ik/', partOfSpeech:'Adjective', definition:'Focused on practical results and real-world usefulness.', example:'A pragmatic design kept the widget simple to customize.', synonyms:'practical, realistic, sensible', origin:'From Greek pragmatikos, meaning fit for action.' }, + { word:'Tenacious', pronunciation:'/tuh-NAY-shus/', partOfSpeech:'Adjective', definition:'Persistent and determined, especially when facing obstacles.', example:'Her tenacious debugging turned a vague error into a clear fix.', synonyms:'persistent, determined, steadfast', origin:'From Latin tenere, meaning to hold.' }, + { word:'Nuance', pronunciation:'/NOO-ahns/', partOfSpeech:'Noun', definition:'A subtle difference in meaning, feeling, or expression.', example:'Good documentation captures the nuance behind each option.', synonyms:'subtlety, shade, distinction', origin:'From French nuance, meaning shade or subtle variation.' }, + { word:'Candid', pronunciation:'/KAN-did/', partOfSpeech:'Adjective', definition:'Truthful, direct, and sincere.', example:'The candid changelog explained both the fix and the tradeoff.', synonyms:'honest, frank, open', origin:'From Latin candidus, meaning white or shining.' } +]; + // ----- Country flag SVG fragments (viewBox 60x40) ----- const FLAGS = { IN: ` @@ -508,6 +521,61 @@ function renderQuote(p) { `, "'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace"); } +function wrapText(text, maxLen, maxLines) { + const words = String(text || '').split(/\s+/).filter(Boolean); + const lines = []; + let line = ''; + words.forEach(w => { + if (lines.length >= maxLines) return; + if ((line + ' ' + w).trim().length > maxLen) { + if (line) lines.push(line.trim()); + line = w; + } else { + line = (line + ' ' + w).trim(); + } + }); + if (line && lines.length < maxLines) lines.push(line.trim()); + return lines; +} + +function pickWord() { + const dayKey = Math.floor(Date.now() / 86400000); + return WORDS[dayKey % WORDS.length]; +} + +function renderWord(p) { + const th = theme(p.theme); + const rx = p.radius; + const bgFill = p.bgColor || th.bg; + const border = p.borderColor ? `stroke="${p.borderColor}" stroke-width="2"` : (th.border ? `stroke="${th.fg}" stroke-width="2"` : ''); + const item = pickWord(); + const W = 560, H = 230; + const definition = wrapText(item.definition, 48, 2); + const example = wrapText(item.example, 50, 2); + const origin = wrapText(item.origin, 48, 2); + return svgWrap(W, H, ` + ${shadowFilter('sh', p.shadow)} + + + ${escXml((p.label || 'Word of the Day').toUpperCase())} + ${escXml(item.word)} + ${escXml(item.pronunciation)} + + ${escXml(item.partOfSpeech.toUpperCase())} + + DEFINITION + ${definition.map((line, i) => `${escXml(line)}`).join('')} + EXAMPLE + ${example.map((line, i) => `${escXml(line)}`).join('')} + SYNONYMS + ${escXml(item.synonyms)} + ${p.showOrigin ? ` + ORIGIN + ${origin.map((line, i) => `${escXml(line)}`).join('')} + ` : ''} + `); +} + function renderFlag(p) { const th = theme(p.theme); const rx = p.radius; @@ -1075,6 +1143,7 @@ function normalizeParams(q) { borderColor: validateBorderColor(q.borderColor), country: q.country || 'IN', quoteCategory: q.quoteCategory || 'programming', + showOrigin: normalizeBool(q.showOrigin, true), clockStyle: q.clockStyle || 'digital', startDate: (() => { const raw = q.startDate || '2024-01-01'; @@ -1107,6 +1176,7 @@ async function renderWidget(type, query) { case 'clock': return renderClock(p); case 'date': return renderDate(p); case 'quote': return renderQuote(p); + case 'word': return renderWord(p); case 'flag': return renderFlag(p); case 'timezone': return renderTimezone(p); case 'streak': return renderStreak(p); diff --git a/vercel.json b/vercel.json index c081abe..6dbd5b6 100644 --- a/vercel.json +++ b/vercel.json @@ -21,7 +21,7 @@ ] }, { - "source": "/api/(date|quote|streak|profile).svg", + "source": "/api/(date|quote|word|streak|profile).svg", "headers": [ { "key": "Content-Type", "value": "image/svg+xml; charset=utf-8" }, { "key": "Cache-Control", "value": "public, max-age=3600, s-maxage=3600, stale-while-revalidate=600" }, From 0f7d09bd880b3b824729f84250de40535cd13750 Mon Sep 17 00:00:00 2001 From: Him-an-shi Date: Tue, 9 Jun 2026 00:30:41 +0530 Subject: [PATCH 2/3] Changes with layout --- index.html | 12 ++++++------ lib/widgets.js | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/index.html b/index.html index 249acf3..c3436db 100644 --- a/index.html +++ b/index.html @@ -1245,10 +1245,10 @@

Stylish Readme

const theme = themeObj(state.theme); const borderStyle = theme.border?`stroke:${theme.fg};stroke-width:2;`:''; const item = wordOfDay(); - const width=560, height=230; + const width=560, height=270; const definition = wordLines(item.definition, 48, 2); const example = wordLines(item.example, 50, 2); - const origin = wordLines(item.origin, 48, 2); + const origin = wordLines(item.origin, 58, 2); return ` @@ -1263,11 +1263,11 @@

Stylish Readme

${definition.map((line,i)=>`${line}`).join('')} EXAMPLE ${example.map((line,i)=>`${line}`).join('')} - SYNONYMS - ${item.synonyms} + SYNONYMS + ${item.synonyms} ${state.showOrigin?` - ORIGIN - ${origin.map((line,i)=>`${line}`).join('')} + ORIGIN + ${origin.map((line,i)=>`${line}`).join('')} `:''} `; } diff --git a/lib/widgets.js b/lib/widgets.js index 1412c23..4973b82 100644 --- a/lib/widgets.js +++ b/lib/widgets.js @@ -549,10 +549,10 @@ function renderWord(p) { const bgFill = p.bgColor || th.bg; const border = p.borderColor ? `stroke="${p.borderColor}" stroke-width="2"` : (th.border ? `stroke="${th.fg}" stroke-width="2"` : ''); const item = pickWord(); - const W = 560, H = 230; + const W = 560, H = 270; const definition = wrapText(item.definition, 48, 2); const example = wrapText(item.example, 50, 2); - const origin = wrapText(item.origin, 48, 2); + const origin = wrapText(item.origin, 58, 2); return svgWrap(W, H, ` ${shadowFilter('sh', p.shadow)} @@ -567,11 +567,11 @@ function renderWord(p) { ${definition.map((line, i) => `${escXml(line)}`).join('')} EXAMPLE ${example.map((line, i) => `${escXml(line)}`).join('')} - SYNONYMS - ${escXml(item.synonyms)} + SYNONYMS + ${escXml(item.synonyms)} ${p.showOrigin ? ` - ORIGIN - ${origin.map((line, i) => `${escXml(line)}`).join('')} + ORIGIN + ${origin.map((line, i) => `${escXml(line)}`).join('')} ` : ''} `); } From 5716ca5409d1947585279cd245d055791ef19a0a Mon Sep 17 00:00:00 2001 From: HIMANSHI PATHAK Date: Tue, 9 Jun 2026 23:04:19 +0530 Subject: [PATCH 3/3] Fix headers in vercel.json and resolve conflicts Removed duplicate header entries and resolved merge conflict. --- vercel.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vercel.json b/vercel.json index 4f2a5ab..c46878b 100644 --- a/vercel.json +++ b/vercel.json @@ -11,7 +11,6 @@ { "source": "/api/(time|clock|timezone|skyline).svg", "headers": [ -<<<<<<< HEAD { "key": "Content-Type", "value": "image/svg+xml; charset=utf-8" }, { "key": "Cache-Control", "value": "public, max-age=60, s-maxage=60, stale-while-revalidate=30" }, { "key": "Vary", "value": "Accept-Encoding" }, @@ -23,10 +22,8 @@ "headers": [ { "key": "Content-Type", "value": "image/svg+xml; charset=utf-8" }, { "key": "Cache-Control", "value": "public, max-age=3600, s-maxage=3600, stale-while-revalidate=600" }, -======= { "key": "Content-Type", "value": "image/svg+xml; charset=utf-8" }, { "key": "Cache-Control", "value": "public, max-age=60, s-maxage=60, stale-while-revalidate=30" }, ->>>>>>> 4140561cbdc6c521444ae7205935e4a2d5ab9bb7 { "key": "Vary", "value": "Accept-Encoding" }, { "key": "Access-Control-Allow-Origin", "value": "*" } ] @@ -59,4 +56,4 @@ ] } ] -} \ No newline at end of file +}