Skip to content

Commit 3bdc072

Browse files
committed
mp3 fix. target blank. desk
1 parent 9d504cc commit 3bdc072

File tree

3 files changed

+101
-25
lines changed

3 files changed

+101
-25
lines changed

www/compile.js

Lines changed: 82 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,6 @@ function isAllowedFile(filename) {
4242
return Object.values(ALLOWED_EXTENSIONS).flat().includes(ext);
4343
}
4444

45-
function cleanUrl(url) {
46-
return url.replace(/^https?:\/\//, '').replace(/\/$/, '');
47-
}
48-
49-
function processLinks(content) {
50-
51-
content = content.replace(/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g, (match, text, url) => {
52-
if (text === url || text === cleanUrl(url)) {
53-
54-
return `<a href="${url}">${cleanUrl(url)}</a>`;
55-
}
56-
57-
return `<a href="${url}">${text}</a>`;
58-
});
59-
60-
content = content.replace(/(?<!\]\()(https?:\/\/[^\s<)]+)/g, (url) => {
61-
return `<a href="${url}">${cleanUrl(url)}</a>`;
62-
});
63-
64-
return content;
65-
}
6645

6746
function removeMetaTags(content) {
6847
if (content.trim().startsWith('<!--') && content.includes('-->')) {
@@ -173,6 +152,26 @@ function copyImages(sourcePath, targetPath) {
173152
});
174153
}
175154

155+
function copyAudio(sourcePath, targetPath) {
156+
if (!fs.existsSync(sourcePath)) return;
157+
158+
const files = fs.readdirSync(sourcePath);
159+
files.forEach(file => {
160+
const curPath = path.join(sourcePath, file);
161+
const stat = fs.statSync(curPath);
162+
163+
if (stat.isDirectory()) {
164+
copyAudio(curPath, targetPath);
165+
} else {
166+
const ext = path.extname(file).toLowerCase();
167+
if (ALLOWED_EXTENSIONS.audio.includes(ext)) {
168+
const targetFile = path.join(targetPath, file);
169+
fs.copyFileSync(curPath, targetFile);
170+
}
171+
}
172+
});
173+
}
174+
176175
function generatePostId(post, language) {
177176
const date = new Date(post.date);
178177
const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
@@ -473,7 +472,9 @@ function createBlogContent(posts, language) {
473472
const postSlug = getPostSlug(post);
474473
const date = new Date(post.date);
475474
const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
476-
const path = language === 'uk' ? `/ua/${monthKey}/${postSlug}` : `/${monthKey}/${postSlug}`;
475+
const path = language === 'uk' ?
476+
`${siteUrl}ua/${monthKey}/${postSlug}/` :
477+
`${siteUrl}${monthKey}/${postSlug}/`;
477478
return `
478479
<div class="post-wrapper">
479480
<div class="post" data-title="${post.title.date}" data-time="${post.title.time}" data-date="${post.date}">
@@ -719,6 +720,10 @@ function createPage(title, content, activeMenu, posts = [], currentMonth = '', p
719720
720721
<title>${pageTitle}</title>
721722
723+
<!-- RSS фиды -->
724+
<link rel="alternate" type="application/rss+xml" title="Code With LLM Updates" href="/feed.xml" />
725+
<link rel="alternate" type="application/rss+xml" title="Як краще створювати код за допомогою LLM" href="/ua/feed.xml" />
726+
722727
<!-- Стили -->
723728
<link rel="stylesheet" href="/css/styles.css">
724729
@@ -750,6 +755,44 @@ function createSimpleContent(content) {
750755
</div>`;
751756
}
752757

758+
function generateRssFeed(posts, language) {
759+
const lang = language === 'uk' ? 'uk' : 'en';
760+
const feedUrl = language === 'uk' ? `${siteUrl}ua/feed.xml` : `${siteUrl}feed.xml`;
761+
const siteTitle = language === 'uk' ? 'Як краще створювати код за допомогою LLM' : 'Code With LLM Updates';
762+
const siteDescription = siteConfig.descriptions[lang === 'uk' ? 'ukr' : 'index'];
763+
764+
const items = posts.slice(0, 20).map(post => {
765+
const date = new Date(post.date);
766+
const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
767+
const postSlug = getPostSlug(post);
768+
const postUrl = language === 'uk' ?
769+
`${siteUrl}ua/${monthKey}/${postSlug}/` :
770+
`${siteUrl}${monthKey}/${postSlug}/`;
771+
772+
return `
773+
<item>
774+
<title><![CDATA[${post.title.date} ${post.title.time}]]></title>
775+
<link>${postUrl}</link>
776+
<guid isPermaLink="true">${postUrl}</guid>
777+
<description><![CDATA[${post.content}]]></description>
778+
<pubDate>${new Date(post.date).toUTCString()}</pubDate>
779+
</item>`;
780+
}).join('\n');
781+
782+
return `<?xml version="1.0" encoding="UTF-8"?>
783+
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
784+
<channel>
785+
<title>${siteTitle}</title>
786+
<link>${siteUrl}${language === 'uk' ? 'ua/' : ''}</link>
787+
<atom:link href="${feedUrl}" rel="self" type="application/rss+xml" />
788+
<description>${siteDescription}</description>
789+
<language>${lang}</language>
790+
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
791+
${items}
792+
</channel>
793+
</rss>`;
794+
}
795+
753796
async function compile() {
754797
try {
755798
if (!fs.existsSync(publicDir)) {
@@ -759,9 +802,13 @@ async function compile() {
759802
await removeDirectoryContentsWithRetry(publicDir);
760803

761804
const imgDir = path.join(publicDir, 'img');
805+
const audioDir = path.join(publicDir, 'audio');
762806
if (!fs.existsSync(imgDir)) {
763807
fs.mkdirSync(imgDir);
764808
}
809+
if (!fs.existsSync(audioDir)) {
810+
fs.mkdirSync(audioDir);
811+
}
765812

766813
// Копируем favicon
767814
const faviconPngPath = path.join('.', 'template', 'favicon.png');
@@ -807,11 +854,12 @@ async function compile() {
807854
console.warn('⚠️ styles.css не найден в папке template');
808855
}
809856

810-
// Копируем изображения
857+
// Копируем изображения и аудио
811858
for (const lang of Object.values(posts_source)) {
812859
lang.forEach(({path: yearDir}) => {
813860
const yearPath = path.join('..', yearDir);
814861
copyImages(yearPath, imgDir);
862+
copyAudio(yearPath, audioDir);
815863
});
816864
}
817865

@@ -930,6 +978,17 @@ async function compile() {
930978
createPageWithMenu('About - CodeWithLLM', createSimpleContent(about), 'about')
931979
);
932980

981+
// Генерируем RSS-фиды
982+
fs.writeFileSync(
983+
path.join(publicDir, 'feed.xml'),
984+
generateRssFeed(engPosts, 'en')
985+
);
986+
987+
fs.writeFileSync(
988+
path.join(publicDir, 'ua', 'feed.xml'),
989+
generateRssFeed(ukrPosts, 'uk')
990+
);
991+
933992
} catch (error) {
934993
console.error('Ошибка при компиляции:', error);
935994
process.exit(1);

www/config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ const siteConfig = {
5656
default: 'CodeWithLLM - Learn how to better create code using AI and LLM'
5757
},
5858
siteDescriptions: {
59-
en: 'Large Language Models (LLM) assist you in creating code. Here you\'ll find useful tips, examples, and instructions to use them effectively.',
60-
uk: 'Великі мовні моделі (LLM) допомагають вам у створенні коду. Тут ви знайдете корисні поради, приклади та інструкції, щоб використовувати їх ефективно.'
59+
en: '🤖 AI tools for smarter coding: practical examples, step-by-step instructions, and real-world LLM applications. Learn to work efficiently with modern code assistants.',
60+
uk: '🤖 Інструменти ШІ для програмування: практичні приклади, покрокові інструкції та реальні застосування LLM. Навчіться ефективно працювати з сучасними асистентами програмування.'
6161
},
6262
ui: {
6363
en: {

www/src/md2html.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
const marked = require('marked');
2+
const { ALLOWED_EXTENSIONS } = require('../config');
23
marked.use({ breaks: true, gfm: true });
34

45
marked.use({
56
renderer: {
7+
link(token) {
8+
const url = (token.href?.trim() || '');
9+
const ext = url.split('.').pop()?.toLowerCase();
10+
11+
if (ALLOWED_EXTENSIONS.audio.includes(`.${ext}`)) {
12+
return `
13+
<audio controls>
14+
<source src="/audio/${url}" type="audio/${ext}">
15+
${token.text} (аудио не поддерживается вашим браузером)
16+
</audio>
17+
`;
18+
}
19+
20+
return `<a target="_blank" href="${url}"${token.title ? ` title="${token.title}"` : ''}>${token.text}</a>`;
21+
},
22+
623
image(href, title, text) {
724
const url = (href?.href || href)?.trim() || '';
825

0 commit comments

Comments
 (0)