@@ -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 ( / ^ h t t p s ? : \/ \/ / , '' ) . replace ( / \/ $ / , '' ) ;
47- }
48-
49- function processLinks ( content ) {
50-
51- content = content . replace ( / \[ ( [ ^ \] ] + ) \] \( ( h t t p s ? : \/ \/ [ ^ ) ] + ) \) / 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 ( / (?< ! \] \( ) ( h t t p s ? : \/ \/ [ ^ \s < ) ] + ) / g, ( url ) => {
61- return `<a href="${ url } ">${ cleanUrl ( url ) } </a>` ;
62- } ) ;
63-
64- return content ;
65- }
6645
6746function 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+
176175function 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+
753796async 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 ) ;
0 commit comments