💂‍♂️ fixed lint and prittier

This commit is contained in:
RJ
2025-11-14 15:33:00 +02:00
parent 5e9093cf9c
commit 820a2b88d5
43 changed files with 5717 additions and 423 deletions

View File

@@ -17,7 +17,8 @@ export function BlogCard({ post, variant }: BlogCardProps) {
<article className="border border-slate-700 bg-slate-900 p-6 h-full cyber-glitch-hover">
<div className="border-l-2 pl-4 mb-4" style={{ borderColor: 'var(--neon-pink)' }}>
<span className="font-mono text-xs text-zinc-100 uppercase tracking-wider">
{post.frontmatter.category} <span style={{ color: 'var(--neon-cyan)' }}>//</span> {formatDate(post.frontmatter.date)}
{post.frontmatter.category} <span style={{ color: 'var(--neon-cyan)' }}>//</span>{' '}
{formatDate(post.frontmatter.date)}
</span>
</div>
<h3 className="font-mono text-xl font-bold text-zinc-100 uppercase mb-3">
@@ -27,8 +28,11 @@ export function BlogCard({ post, variant }: BlogCardProps) {
{post.frontmatter.description}
</p>
<div className="flex flex-wrap gap-2 mb-4">
{post.frontmatter.tags.map((tag) => (
<span key={tag} className="px-3 py-1 bg-zinc-800 border border-slate-700 text-cyan-400 font-mono text-xs uppercase">
{post.frontmatter.tags.map(tag => (
<span
key={tag}
className="px-3 py-1 bg-zinc-800 border border-slate-700 text-cyan-400 font-mono text-xs uppercase"
>
#{tag}
</span>
))}
@@ -68,8 +72,11 @@ export function BlogCard({ post, variant }: BlogCardProps) {
{post.frontmatter.description}
</p>
<div className="flex flex-wrap gap-2 mb-4">
{post.frontmatter.tags.map((tag) => (
<span key={tag} className="px-3 py-1 bg-zinc-800 border border-slate-700 text-cyan-400 font-mono text-xs uppercase">
{post.frontmatter.tags.map(tag => (
<span
key={tag}
className="px-3 py-1 bg-zinc-800 border border-slate-700 text-cyan-400 font-mono text-xs uppercase"
>
#{tag}
</span>
))}
@@ -99,7 +106,8 @@ export function BlogCard({ post, variant }: BlogCardProps) {
<div className="p-6">
<div className="border-l-2 pl-4 mb-4" style={{ borderColor: 'var(--neon-pink)' }}>
<span className="font-mono text-xs text-zinc-100 uppercase tracking-wider">
{post.frontmatter.category} <span style={{ color: 'var(--neon-cyan)' }}>//</span> {formatDate(post.frontmatter.date)}
{post.frontmatter.category} <span style={{ color: 'var(--neon-cyan)' }}>//</span>{' '}
{formatDate(post.frontmatter.date)}
</span>
</div>
<h3 className="font-mono text-xl font-bold text-zinc-100 uppercase mb-3">
@@ -109,8 +117,11 @@ export function BlogCard({ post, variant }: BlogCardProps) {
{post.frontmatter.description}
</p>
<div className="flex flex-wrap gap-2 mb-4">
{post.frontmatter.tags.map((tag) => (
<span key={tag} className="px-3 py-1 bg-zinc-800 border border-slate-700 text-cyan-400 font-mono text-xs uppercase">
{post.frontmatter.tags.map(tag => (
<span
key={tag}
className="px-3 py-1 bg-zinc-800 border border-slate-700 text-cyan-400 font-mono text-xs uppercase"
>
#{tag}
</span>
))}

View File

@@ -23,7 +23,9 @@ export function CodeBlock({ code, language, filename, showLineNumbers = true }:
<div className="flex items-center justify-between px-4 py-2 bg-[rgb(var(--bg-secondary))] dark:bg-zinc-950 border-b-2 border-[var(--neon-purple)] relative">
<div className="flex items-center gap-3">
{filename && (
<span className="text-[var(--neon-cyan)] font-mono text-sm uppercase">&gt;&gt; {filename}</span>
<span className="text-[var(--neon-cyan)] font-mono text-sm uppercase">
&gt;&gt; {filename}
</span>
)}
<span className="px-2 py-1 border border-[var(--neon-purple)] text-[var(--neon-purple)] text-xs font-mono uppercase">
[{language}]

View File

@@ -1,13 +1,13 @@
'use client';
'use client'
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import Image from 'next/image';
import Link from 'next/link';
import { CodeBlock } from './code-block';
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import Image from 'next/image'
import Link from 'next/link'
import { CodeBlock } from './code-block'
interface MarkdownRendererProps {
content: string;
content: string
}
export default function MarkdownRenderer({ content }: MarkdownRendererProps) {
@@ -16,48 +16,42 @@ export default function MarkdownRenderer({ content }: MarkdownRendererProps) {
remarkPlugins={[remarkGfm]}
components={{
h1: ({ children }) => {
const text = String(children);
const id = text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
return <h1 id={id}>{children}</h1>;
const text = String(children)
const id = text
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/(^-|-$)/g, '')
return <h1 id={id}>{children}</h1>
},
h2: ({ children }) => {
const text = String(children);
const id = text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
return <h2 id={id}>{children}</h2>;
const text = String(children)
const id = text
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/(^-|-$)/g, '')
return <h2 id={id}>{children}</h2>
},
h3: ({ children }) => {
const text = String(children);
const id = text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
return <h3 id={id}>{children}</h3>;
const text = String(children)
const id = text
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/(^-|-$)/g, '')
return <h3 id={id}>{children}</h3>
},
code: ({ inline, className, children, ...props }: any) => {
const match = /language-(\w+)/.exec(className || '');
const match = /language-(\w+)/.exec(className || '')
if (!inline && match) {
return (
<CodeBlock
code={String(children).replace(/\n$/, '')}
language={match[1]}
/>
);
return <CodeBlock code={String(children).replace(/\n$/, '')} language={match[1]} />
}
return (
<code {...props}>
{children}
</code>
);
return <code {...props}>{children}</code>
},
img: ({ src, alt }) => {
if (!src || typeof src !== 'string') return null;
const isExternal = src.startsWith('http://') || src.startsWith('https://');
if (!src || typeof src !== 'string') return null
const isExternal = src.startsWith('http://') || src.startsWith('https://')
if (isExternal) {
return (
<img
src={src}
alt={alt || ''}
className="w-full h-auto"
/>
);
return <img src={src} alt={alt || ''} className="w-full h-auto" />
}
return (
@@ -70,33 +64,25 @@ export default function MarkdownRenderer({ content }: MarkdownRendererProps) {
style={{ width: '100%', height: 'auto' }}
/>
</div>
);
)
},
a: ({ href, children }) => {
if (!href) return <>{children}</>;
const isExternal = href.startsWith('http://') || href.startsWith('https://');
if (!href) return <>{children}</>
const isExternal = href.startsWith('http://') || href.startsWith('https://')
if (isExternal) {
return (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
>
<a href={href} target="_blank" rel="noopener noreferrer">
{children}
</a>
);
)
}
return (
<Link href={href}>
{children}
</Link>
);
return <Link href={href}>{children}</Link>
},
}}
>
{content}
</ReactMarkdown>
);
)
}

View File

@@ -28,11 +28,17 @@ export function Navbar() {
}, [lastScrollY])
return (
<nav className={`border-b-4 border-slate-700 bg-slate-900 dark:bg-zinc-950 sticky top-0 z-50 ${isVisible ? 'navbar-visible' : 'navbar-hidden'}`}>
<nav
className={`border-b-4 border-slate-700 bg-slate-900 dark:bg-zinc-950 sticky top-0 z-50 ${isVisible ? 'navbar-visible' : 'navbar-hidden'}`}
>
<div className="max-w-7xl mx-auto px-6 py-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-8">
<Link href="/" className="font-mono text-sm uppercase tracking-wider transition-colors cursor-pointer" style={{ color: 'var(--neon-cyan)' }}>
<Link
href="/"
className="font-mono text-sm uppercase tracking-wider transition-colors cursor-pointer"
style={{ color: 'var(--neon-cyan)' }}
>
&lt; HOME
</Link>
<span className="font-mono text-sm text-zinc-100 dark:text-zinc-300 uppercase tracking-wider">
@@ -40,7 +46,10 @@ export function Navbar() {
</span>
</div>
<div className="flex items-center gap-6">
<Link href="/about" className="font-mono text-sm text-zinc-400 dark:text-zinc-500 uppercase tracking-wider hover:text-cyan-400 dark:hover:text-cyan-300 transition-colors cursor-pointer">
<Link
href="/about"
className="font-mono text-sm text-zinc-400 dark:text-zinc-500 uppercase tracking-wider hover:text-cyan-400 dark:hover:text-cyan-300 transition-colors cursor-pointer"
>
[ABOUT]
</Link>
<ThemeToggle />

View File

@@ -25,15 +25,13 @@ export function ReadingProgress() {
className="h-full bg-gradient-to-r from-[var(--neon-cyan)] via-[var(--neon-magenta)] to-[var(--neon-pink)] transition-all duration-150"
style={{
width: `${progress}%`,
boxShadow: progress > 0 ? '0 0 8px var(--neon-cyan)' : 'none'
boxShadow: progress > 0 ? '0 0 8px var(--neon-cyan)' : 'none',
}}
/>
</div>
<div className="fixed top-4 right-4 z-50 px-3 py-1.5 bg-[rgb(var(--bg-primary))] border-2 border-[var(--neon-cyan)] text-xs font-mono font-bold text-[var(--neon-cyan)] relative">
<span className="relative z-10">
[{Math.round(progress)}%]
</span>
<span className="relative z-10">[{Math.round(progress)}%]</span>
</div>
</>
)

View File

@@ -6,12 +6,14 @@ interface SearchBarProps {
export function SearchBar({ searchQuery, onSearchChange }: SearchBarProps) {
return (
<div className="flex-1 flex items-center border border-slate-700 bg-zinc-900 transition-all focus-within:border-[var(--neon-cyan)] focus-within:shadow-[0_0_6px_rgba(0,255,255,0.4),inset_0_0_6px_rgba(0,255,255,0.05)]">
<span className="pl-4 pr-2 font-mono text-lg" style={{ color: 'var(--neon-cyan)' }}>&gt;</span>
<span className="pl-4 pr-2 font-mono text-lg" style={{ color: 'var(--neon-cyan)' }}>
&gt;
</span>
<input
type="text"
placeholder="SEARCH POSTS..."
value={searchQuery}
onChange={(e) => onSearchChange(e.target.value)}
onChange={e => onSearchChange(e.target.value)}
className="flex-1 bg-transparent font-mono text-zinc-100 dark:text-zinc-100 px-2 py-3 focus:outline-none placeholder:text-zinc-600 uppercase text-sm"
/>
</div>

View File

@@ -9,12 +9,30 @@ export function SortDropdown({ sortBy, onSortChange }: SortDropdownProps) {
return (
<select
value={sortBy}
onChange={(e) => onSortChange(e.target.value as SortOption)}
onChange={e => onSortChange(e.target.value as SortOption)}
className="border-2 border-slate-700 bg-zinc-900 dark:bg-zinc-900 text-zinc-100 dark:text-zinc-100 font-mono px-6 py-3 uppercase text-sm cyber-focus-pink transition-all hover:border-cyan-400 cursor-pointer"
>
<option value="newest" className="bg-zinc-900 text-zinc-100" style={{ backgroundColor: '#18181b', color: '#f4f4f5' }}>NEWEST FIRST</option>
<option value="oldest" className="bg-zinc-900 text-zinc-100" style={{ backgroundColor: '#18181b', color: '#f4f4f5' }}>OLDEST FIRST</option>
<option value="title" className="bg-zinc-900 text-zinc-100" style={{ backgroundColor: '#18181b', color: '#f4f4f5' }}>BY TITLE</option>
<option
value="newest"
className="bg-zinc-900 text-zinc-100"
style={{ backgroundColor: '#18181b', color: '#f4f4f5' }}
>
NEWEST FIRST
</option>
<option
value="oldest"
className="bg-zinc-900 text-zinc-100"
style={{ backgroundColor: '#18181b', color: '#f4f4f5' }}
>
OLDEST FIRST
</option>
<option
value="title"
className="bg-zinc-900 text-zinc-100"
style={{ backgroundColor: '#18181b', color: '#f4f4f5' }}
>
BY TITLE
</option>
</select>
)
}

View File

@@ -48,7 +48,9 @@ export function StickyFooter({ url, title }: StickyFooterProps) {
${isVisible ? 'translate-y-0' : 'translate-y-full'}
`}
style={{
boxShadow: isVisible ? '0 -8px 30px rgba(155,90,142,0.5), inset 0 4px 20px rgba(155,90,142,0.1)' : 'none'
boxShadow: isVisible
? '0 -8px 30px rgba(155,90,142,0.5), inset 0 4px 20px rgba(155,90,142,0.1)'
: 'none',
}}
>
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-[var(--neon-magenta)] to-transparent opacity-70" />
@@ -60,7 +62,10 @@ export function StickyFooter({ url, title }: StickyFooterProps) {
<div className="w-2 h-2 bg-[var(--neon-cyan)] shadow-[0_0_6px_rgba(90,139,149,1)]" />
<div className="w-2 h-2 bg-[var(--neon-pink)] shadow-[0_0_6px_rgba(155,90,110,1)]" />
</div>
<span className="text-[var(--neon-cyan)] font-mono text-xs uppercase tracking-wider" style={{ textShadow: '0 0 8px rgba(90,139,149,0.6)' }}>
<span
className="text-[var(--neon-cyan)] font-mono text-xs uppercase tracking-wider"
style={{ textShadow: '0 0 8px rgba(90,139,149,0.6)' }}
>
&gt;&gt; SHARE:
</span>
</div>
@@ -89,7 +94,9 @@ export function StickyFooter({ url, title }: StickyFooterProps) {
<button
onClick={handleCopyLink}
className="flex items-center gap-2 px-4 py-2 bg-black border-4 border-[var(--neon-pink)] text-[var(--neon-pink)] font-mono text-xs uppercase tracking-wider transition-all hover:shadow-[0_0_25px_rgba(155,90,110,0.8)] hover:bg-pink-900/20"
style={{ textShadow: copied ? '0 0 10px rgba(155,90,110,1)' : '0 0 8px rgba(155,90,110,0.6)' }}
style={{
textShadow: copied ? '0 0 10px rgba(155,90,110,1)' : '0 0 8px rgba(155,90,110,0.6)',
}}
>
{copied ? '[✓ COPIED]' : '[COPY]'}
</button>

View File

@@ -17,8 +17,8 @@ export function TableOfContents({ headings }: TOCProps) {
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
setActiveId(entry.target.id)
}
@@ -43,31 +43,45 @@ export function TableOfContents({ headings }: TOCProps) {
<div className="border-b border-[var(--neon-magenta)] pb-3 mb-4 relative">
<div className="flex gap-1.5 mb-2 justify-end">
<div className="w-3 h-3 border border-[var(--neon-cyan)]/40 hover:bg-[var(--neon-cyan)]/10 transition-colors cursor-pointer" title="Minimize" />
<div className="w-3 h-3 border border-[var(--neon-cyan)]/40 hover:bg-[var(--neon-cyan)]/10 transition-colors cursor-pointer" title="Maximize" />
<div className="w-3 h-3 border border-[var(--neon-pink)]/40 hover:bg-[var(--neon-pink)]/10 transition-colors cursor-pointer" title="Close" />
<div
className="w-3 h-3 border border-[var(--neon-cyan)]/40 hover:bg-[var(--neon-cyan)]/10 transition-colors cursor-pointer"
title="Minimize"
/>
<div
className="w-3 h-3 border border-[var(--neon-cyan)]/40 hover:bg-[var(--neon-cyan)]/10 transition-colors cursor-pointer"
title="Maximize"
/>
<div
className="w-3 h-3 border border-[var(--neon-pink)]/40 hover:bg-[var(--neon-pink)]/10 transition-colors cursor-pointer"
title="Close"
/>
</div>
<h3 className="text-xs font-mono font-bold text-[var(--neon-cyan)] uppercase tracking-wider" style={{ textShadow: '0 0 6px rgba(90,139,149,0.5)' }}>
<h3
className="text-xs font-mono font-bold text-[var(--neon-cyan)] uppercase tracking-wider"
style={{ textShadow: '0 0 6px rgba(90,139,149,0.5)' }}
>
&gt;&gt; NAVIGATION
</h3>
</div>
<nav className="space-y-1 relative">
{headings.map((heading) => (
{headings.map(heading => (
<a
key={heading.id}
href={`#${heading.id}`}
className={`
block text-sm font-mono py-2 border-l-2 transition-all duration-150
${heading.level === 2 ? 'pl-3' : 'pl-6'}
${activeId === heading.id
? 'text-[var(--neon-cyan)] border-[var(--neon-cyan)] bg-cyan-500/5 shadow-[0_0_8px_rgba(90,139,149,0.3)]'
: 'text-zinc-500 border-zinc-900 hover:border-[var(--neon-magenta)] hover:text-[var(--neon-magenta)] hover:bg-magenta-500/3 hover:shadow-[0_0_4px_rgba(155,90,142,0.2)]'
${
activeId === heading.id
? 'text-[var(--neon-cyan)] border-[var(--neon-cyan)] bg-cyan-500/5 shadow-[0_0_8px_rgba(90,139,149,0.3)]'
: 'text-zinc-500 border-zinc-900 hover:border-[var(--neon-magenta)] hover:text-[var(--neon-magenta)] hover:bg-magenta-500/3 hover:shadow-[0_0_4px_rgba(155,90,142,0.2)]'
}
`}
style={activeId === heading.id ? { textShadow: '0 0 4px rgba(90,139,149,0.5)' } : {}}
>
<span className="inline-block">{activeId === heading.id ? '▶ ' : '◆ '}</span>{heading.text}
<span className="inline-block">{activeId === heading.id ? '▶ ' : '◆ '}</span>
{heading.text}
</a>
))}
</nav>

View File

@@ -14,7 +14,7 @@ export function TagFilter({ allTags, selectedTags, onToggleTag, onClearTags }: T
FILTER BY TAG
</p>
<div className="flex flex-wrap gap-3">
{allTags.map((tag) => (
{allTags.map(tag => (
<button
key={tag}
onClick={() => onToggleTag(tag)}

View File

@@ -1,14 +1,14 @@
'use client';
'use client'
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Fragment } from 'react';
import { BreadcrumbsSchema } from './breadcrumbs-schema';
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { Fragment } from 'react'
import { BreadcrumbsSchema } from './breadcrumbs-schema'
interface BreadcrumbItem {
label: string;
href: string;
current?: boolean;
label: string
href: string
current?: boolean
}
function HomeIcon({ className }: { className?: string }) {
@@ -27,25 +27,15 @@ function HomeIcon({ className }: { className?: string }) {
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
</svg>
);
)
}
function ChevronIcon({ className }: { className?: string }) {
return (
<svg
className={className}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 5l7 7-7 7"
/>
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
);
)
}
function formatSegmentLabel(segment: string): string {
@@ -53,36 +43,36 @@ function formatSegmentLabel(segment: string): string {
blog: 'Blog',
tags: 'Tag-uri',
about: 'Despre',
};
}
if (specialCases[segment]) {
return specialCases[segment];
return specialCases[segment]
}
return segment
.split('-')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
.join(' ')
}
export function Breadcrumbs({ items }: { items?: BreadcrumbItem[] }) {
const pathname = usePathname();
const pathname = usePathname()
let breadcrumbs: BreadcrumbItem[] = items || [];
let breadcrumbs: BreadcrumbItem[] = items || []
if (!items) {
const segments = pathname.split('/').filter(Boolean);
const segments = pathname.split('/').filter(Boolean)
breadcrumbs = segments.map((segment, index) => {
const href = '/' + segments.slice(0, index + 1).join('/');
const label = formatSegmentLabel(segment);
const current = index === segments.length - 1;
const href = '/' + segments.slice(0, index + 1).join('/')
const label = formatSegmentLabel(segment)
const current = index === segments.length - 1
return { label, href, current };
});
return { label, href, current }
})
}
if (pathname === '/') {
return null;
return null
}
const schemaItems = [
@@ -92,7 +82,7 @@ export function Breadcrumbs({ items }: { items?: BreadcrumbItem[] }) {
name: item.label,
item: item.href,
})),
];
]
return (
<>
@@ -112,7 +102,7 @@ export function Breadcrumbs({ items }: { items?: BreadcrumbItem[] }) {
</Link>
</li>
{breadcrumbs.map((item) => (
{breadcrumbs.map(item => (
<Fragment key={item.href}>
<li className="text-gray-400 flex-shrink-0">
<ChevronIcon className="w-4 h-4" />
@@ -141,5 +131,5 @@ export function Breadcrumbs({ items }: { items?: BreadcrumbItem[] }) {
</nav>
<BreadcrumbsSchema items={schemaItems} />
</>
);
)
}

View File

@@ -1,25 +1,25 @@
interface BreadcrumbSchemaItem {
position: number;
name: string;
item: string;
position: number
name: string
item: string
}
export function BreadcrumbsSchema({ items }: { items: BreadcrumbSchemaItem[] }) {
const structuredData = {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: items.map((item) => ({
itemListElement: items.map(item => ({
'@type': 'ListItem',
position: item.position,
name: item.name,
item: `http://localhost:3000${item.item}`,
})),
};
}
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
/>
);
)
}

View File

@@ -43,18 +43,17 @@ export function ThemeToggle() {
className={`
relative font-mono text-xs uppercase tracking-wider
px-3 py-1 border-2 transition-all duration-300
${theme === 'dark'
? 'text-cyan-400 border-cyan-900 hover:border-cyan-700 bg-cyan-950/20'
: 'text-emerald-600 border-emerald-700 hover:border-emerald-500 bg-emerald-50/50'
${
theme === 'dark'
? 'text-cyan-400 border-cyan-900 hover:border-cyan-700 bg-cyan-950/20'
: 'text-emerald-600 border-emerald-700 hover:border-emerald-500 bg-emerald-50/50'
}
${isGlitching ? 'glitch-btn' : ''}
border-pulse overflow-hidden
`}
aria-label="Toggle theme"
>
<span className="relative z-10">
{theme === 'dark' ? '[DARK MODE]' : '[LIGHT MODE]'}
</span>
<span className="relative z-10">{theme === 'dark' ? '[DARK MODE]' : '[LIGHT MODE]'}</span>
{isGlitching && (
<>
<span className="glitch-layer" aria-hidden="true">