1
1
const fs = require ( 'fs' ) ;
2
2
const path = require ( 'path' ) ;
3
3
const mdToHtml = require ( './src/md2html' ) ;
4
- const { commonStyles } = require ( './src/styles' ) ;
5
4
const { posts_source, siteUrl, ALLOWED_EXTENSIONS , menuItems, postsConfig } = require ( './config' ) ;
6
5
7
6
const publicDir = path . join ( __dirname , 'public' ) ;
@@ -366,8 +365,16 @@ function createBlogContent(posts, language) {
366
365
const topTags = extractTags ( recentPosts ) ;
367
366
368
367
return `
368
+ <div class="site-description-wrapper">
369
+ <div class="site-description">
370
+ ${ language === 'uk' ?
371
+ 'Тут ви знайдете корисні поради, приклади, інструкції та інші матеріали, які допоможуть вам у створенні коду з допомогою штучного інтелекту' :
372
+ "Here you'll find useful tips, examples, instructions, and other materials to help you create code with the help of AI" }
373
+ </div>
374
+ </div>
369
375
<div class="top-tags">
370
- ${ topTags . map ( ( [ tag , count ] ) => `<a href="javascript:void(0)" data-tag="${ tag } " data-count=" • ${ count } ">${ tag } </a>` ) . join ( ' ' ) }
376
+ <a href="javascript:void(0)" class="up-button" title="${ language === 'uk' ? 'Нагору' : 'Scroll to top' } ">${ language === 'uk' ? 'Початок' : 'Home' } </a>
377
+ ${ topTags . map ( ( [ tag , count ] ) => `<a href="javascript:void(0)" data-tag="${ tag } " data-count="${ count } • ">${ tag } </a>` ) . join ( ' ' ) }
371
378
</div>
372
379
<div class="container" style="grid-template-columns: 1fr">
373
380
<div class="posts">
@@ -389,10 +396,19 @@ function createBlogContent(posts, language) {
389
396
</div>
390
397
<script>
391
398
document.addEventListener('DOMContentLoaded', function() {
392
- const tagLinks = document.querySelectorAll('.top-tags a');
399
+ const tagLinks = document.querySelectorAll('.top-tags a:not(.up-button)');
400
+ const upButton = document.querySelector('.up-button');
393
401
const posts = document.querySelectorAll('.post');
394
402
const tagPositions = new Map();
395
403
404
+ upButton.addEventListener('click', function(e) {
405
+ e.preventDefault();
406
+ window.scrollTo({
407
+ top: 0,
408
+ behavior: 'smooth'
409
+ });
410
+ });
411
+
396
412
tagLinks.forEach(link => {
397
413
link.addEventListener('click', function(e) {
398
414
e.preventDefault();
@@ -540,7 +556,6 @@ function generateMenu(activeMenu, posts = [], currentMonth = '') {
540
556
}
541
557
542
558
function createPage ( title , content , activeMenu , posts = [ ] , currentMonth = '' , preGeneratedMenu = '' ) {
543
- // Если title это объект с date и time, используем date
544
559
const pageTitle = typeof title === 'object' && title . date ?
545
560
`${ title . date } ${ title . time } - CodeWithLLM` :
546
561
title . includes ( ' - CodeWithLLM' ) ? title : `${ title } - CodeWithLLM` ;
@@ -572,12 +587,16 @@ function createPage(title, content, activeMenu, posts = [], currentMonth = '', p
572
587
<meta property="twitter:description" content="${ description } ">
573
588
574
589
<title>${ pageTitle } </title>
575
- <style>
576
- ${ commonStyles }
577
- </style >
590
+
591
+ <!-- Стили -->
592
+ <link rel="stylesheet" href="/css/styles.css" >
578
593
579
594
<!-- Добавляем favicon -->
580
595
<link rel="icon" type="image/png" href="/img/favicon.png">
596
+
597
+ <!-- Подключаем lite-yt-embed -->
598
+ <link rel="stylesheet" href="/css/lite-yt-embed.css" />
599
+ <script src="/js/lite-yt-embed.js"></script>
581
600
</head>
582
601
<body>
583
602
<div class="wrapper">
@@ -614,8 +633,8 @@ async function compile() {
614
633
}
615
634
616
635
// Копируем favicon
617
- const faviconPngPath = path . join ( '.' , 'favicon ' , 'favicon.png' ) ;
618
- const faviconIcoPath = path . join ( '.' , 'favicon ' , 'favicon.ico' ) ;
636
+ const faviconPngPath = path . join ( '.' , 'template ' , 'favicon.png' ) ;
637
+ const faviconIcoPath = path . join ( '.' , 'template ' , 'favicon.ico' ) ;
619
638
620
639
if ( fs . existsSync ( faviconPngPath ) ) {
621
640
fs . copyFileSync ( faviconPngPath , path . join ( imgDir , 'favicon.png' ) ) ;
@@ -624,11 +643,39 @@ async function compile() {
624
643
}
625
644
626
645
if ( fs . existsSync ( faviconIcoPath ) ) {
627
- fs . copyFileSync ( faviconIcoPath , path . join ( imgDir , 'favicon.ico' ) ) ;
646
+ fs . copyFileSync ( faviconIcoPath , path . join ( publicDir , 'favicon.ico' ) ) ;
628
647
} else {
629
648
console . warn ( '⚠️ favicon.ico не найден в папке favicon' ) ;
630
649
}
631
650
651
+ // Копируем файлы для lite-yt-embed и стили
652
+ const cssDir = path . join ( publicDir , 'css' ) ;
653
+ const jsDir = path . join ( publicDir , 'js' ) ;
654
+ if ( ! fs . existsSync ( cssDir ) ) fs . mkdirSync ( cssDir ) ;
655
+ if ( ! fs . existsSync ( jsDir ) ) fs . mkdirSync ( jsDir ) ;
656
+
657
+ const liteYtCssPath = path . join ( '.' , 'template' , 'lite-yt-embed.css' ) ;
658
+ const liteYtJsPath = path . join ( '.' , 'template' , 'lite-yt-embed.js' ) ;
659
+ const stylesCssPath = path . join ( '.' , 'template' , 'styles.css' ) ;
660
+
661
+ if ( fs . existsSync ( liteYtCssPath ) ) {
662
+ fs . copyFileSync ( liteYtCssPath , path . join ( cssDir , 'lite-yt-embed.css' ) ) ;
663
+ } else {
664
+ console . warn ( '⚠️ lite-yt-embed.css не найден в папке template' ) ;
665
+ }
666
+
667
+ if ( fs . existsSync ( liteYtJsPath ) ) {
668
+ fs . copyFileSync ( liteYtJsPath , path . join ( jsDir , 'lite-yt-embed.js' ) ) ;
669
+ } else {
670
+ console . warn ( '⚠️ lite-yt-embed.js не найден в папке template' ) ;
671
+ }
672
+
673
+ if ( fs . existsSync ( stylesCssPath ) ) {
674
+ fs . copyFileSync ( stylesCssPath , path . join ( cssDir , 'styles.css' ) ) ;
675
+ } else {
676
+ console . warn ( '⚠️ styles.css не найден в папке template' ) ;
677
+ }
678
+
632
679
// Копируем изображения
633
680
for ( const lang of Object . values ( posts_source ) ) {
634
681
lang . forEach ( ( { path : yearDir } ) => {
0 commit comments