Files
citrus/resources/views/blog/show.blade.php
T

556 lines
28 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@extends('layouts.site')
@section('content')
<section class="wrapper !bg-[#edf2fc]">
<div class="container pt-10 pb-36 xl:pt-[4.5rem] lg:pt-[4.5rem] md:pt-[4.5rem] xl:pb-40 lg:pb-40 md:pb-40 !text-center">
<div class="flex flex-wrap mx-[-15px]">
<div class="md:w-10/12 lg:w-10/12 xl:w-8/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto">
<div class="post-header !mb-[.9rem]">
@if($post->category)
<div class="inline-flex uppercase !tracking-[0.02rem] text-[0.7rem] font-bold !text-[#aab0bc] !mb-[0.4rem] text-line relative align-top !pl-[1.4rem] before:content-[''] before:absolute before:inline-block before:translate-y-[-60%] before:w-3 before:h-[0.05rem] before:left-0 before:top-2/4 before:bg-[#e31e24]">
<a href="{{ route('blog.index', ['category' => $post->category->slug]) }}" class="hover !text-[#e31e24]" rel="category">{{ $post->category->name }}</a>
</div>
@endif
<h1 class="!text-[calc(1.365rem_+_1.38vw)] font-bold !leading-[1.2] xl:!text-[2.4rem] !mb-4">
{{ method_exists($post, 'translate') ? $post->translate('title') : $post->title }}
</h1>
<ul class="!text-[0.8rem] !text-[#aab0bc] m-0 p-0 list-none !mb-5">
<li class="post-date inline-block">
<i class="uil uil-calendar-alt pr-[0.2rem] align-[-.05rem] before:content-['\e9ba']"></i>
<span>{{ $post->published_at ? $post->published_at->format('d M Y') : $post->created_at->format('d M Y') }}</span>
</li>
<li class="post-author inline-block before:content-[''] before:inline-block before:w-[0.2rem] before:h-[0.2rem] before:opacity-50 before:m-[0_.6rem_0_.4rem] before:rounded-[100%] before:align-[.15rem] before:bg-[#aab0bc]">
<span class="!text-[0.8rem] !text-[#aab0bc]">
<i class="uil uil-user pr-[0.2rem] align-[-.05rem] before:content-['\ed6f']"></i>
<span>{{ $post->author ? $post->author->name : 'Trunçgil' }}</span>
</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<section class="wrapper !bg-[#ffffff]">
<div class="container !pb-[4.5rem] xl:!pb-24 lg:!pb-24 md:!pb-24">
<div class="flex flex-wrap mx-[-15px]">
<div class="xl:w-10/12 lg:w-10/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto">
<div class="blog single !mt-[-7rem]">
<div class="card !shadow-[0_0.25rem_1.75rem_rgba(30,34,40,0.07)]">
@if($post->featured_image || $post->featured_image_url)
<figure class="card-img-top">
<img src="{{ $post->featured_image ? asset('storage/' . $post->featured_image) : $post->featured_image_url }}" alt="{{ $post->title }}" style="width: 100%; max-height: 520px; object-fit: cover;" loading="lazy">
</figure>
@endif
<div class="card-body flex-[1_1_auto] p-[40px] xl:!p-[2.8rem_3rem_2.8rem] lg:!p-[2.8rem_3rem_2.8rem] md:!p-[2.8rem_3rem_2.8rem]">
<div class="classic-view">
<article class="post !mb-8">
<div class="relative !mb-5 post-content">
{!! method_exists($post, 'translate') ? $post->translate('content') : ($post->content ?? '') !!}
</div>
<div class="post-footer xl:!flex xl:!flex-row xl:!justify-between lg:!flex lg:!flex-row lg:!justify-between md:!flex md:!flex-row md:!justify-between !items-center !mt-8">
@if($post->tags && count($post->tags) > 0)
<div>
<ul class="pl-0 list-none tag-list !mb-0">
@foreach($post->tags as $tag)
<li class="!mt-0 !mb-[0.45rem] !mr-[0.2rem] inline-block">
<a href="{{ route('blog.index', ['tag' => $tag]) }}" class="btn btn-soft-ash btn-sm !rounded-[50rem] flex items-center hover:translate-y-[-0.15rem] hover:shadow-[0_0.25rem_0.75rem_rgba(30,34,40,.05)] before:not-italic before:content-['#'] before:font-normal before:!pr-[0.2rem]">{{ $tag }}</a>
</li>
@endforeach
</ul>
</div>
@endif
<div class="!mb-0 xl:!mb-2 lg:!mb-2 md:!mb-2">
<div class="dropdown share-dropdown btn-group">
<button class="btn btn-sm btn-red !text-white !bg-[#e31e24] border-[#e31e24] hover:text-white hover:bg-[#e31e24] hover:!border-[#e31e24] active:text-white active:bg-[#e31e24] active:border-[#e31e24] disabled:text-white disabled:bg-[#e31e24] disabled:border-[#e31e24] !rounded-[50rem] btn-icon btn-icon-start dropdown-toggle !mb-0 !mr-0 hover:translate-y-[-0.15rem] hover:shadow-[0_0.25rem_0.75rem_rgba(30,34,40,0.15)]" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="uil uil-share-alt !mr-[0.3rem] text-[0.8rem] before:content-['\ecb0']"></i> Paylaş </button>
<div class="dropdown-menu !shadow-[rgba(30,34,40,0.06)_0px_0px_25px_0px]">
<a class="dropdown-item text-[0.7rem] !p-[.25rem_1.15rem]" href="https://twitter.com/intent/tweet?url={{ urlencode(request()->fullUrl()) }}&text={{ urlencode($post->title) }}" target="_blank"><i class="uil uil-twitter w-4 text-[0.8rem] pr-[0.4rem] align-[-.1rem] before:content-['\ed59']"></i>Twitter</a>
<a class="dropdown-item text-[0.7rem] !p-[.25rem_1.15rem]" href="https://www.facebook.com/sharer/sharer.php?u={{ urlencode(request()->fullUrl()) }}" target="_blank"><i class="uil uil-facebook-f w-4 text-[0.8rem] pr-[0.4rem] align-[-.1rem] before:content-['\eae2']"></i>Facebook</a>
<a class="dropdown-item text-[0.7rem] !p-[.25rem_1.15rem]" href="https://www.linkedin.com/sharing/share-offsite/?url={{ urlencode(request()->fullUrl()) }}" target="_blank"><i class="uil uil-linkedin w-4 text-[0.8rem] pr-[0.4rem] align-[-.1rem] before:content-['\ebd1']"></i>Linkedin</a>
</div>
</div>
</div>
</div>
</article>
</div>
<hr>
<!-- Author Bio Widget -->
<div class="author-info xl:!flex lg:!flex md:!flex items-center !mb-3">
<div class="flex items-center">
<figure class="w-12 h-12 !relative !mr-4 rounded-[100%]">
<img class="rounded-[50%]" alt="image" src="{{ $post->author && $post->author->avatar ? asset('storage/' . $post->author->avatar) : asset('assets/img/avatars/u5.webp') }}" onerror="this.src='{{ asset('assets/img/avatars/u5.webp') }}'" loading="lazy">
</figure>
<div>
<h6><a href="#" class="!text-[#343f52] hover:!text-[#e31e24]">{{ $post->author ? $post->author->name : 'Trunçgil' }}</a></h6>
<span class="!text-[0.75rem] !text-[#aab0bc] m-0 p-0 list-none">{{ $post->author && $post->author->role ? $post->author->role : 'Trunçgil Teknoloji Editörü' }}</span>
</div>
</div>
<div class="!mt-3 xl:!mt-0 lg:!mt-0 md:!mt-0 !ml-auto">
<a href="{{ route('blog.index', ['author' => $post->author_id]) }}" class="btn btn-sm btn-soft-ash !rounded-[50rem] btn-icon btn-icon-start !mb-0 hover:translate-y-[-0.15rem] hover:shadow-[0_0.25rem_0.75rem_rgba(30,34,40,0.15)]"><i class="uil uil-file-alt !mr-[0.3rem] before:content-['\eaec'] text-[.8rem]"></i> Tüm Yazıları</a>
</div>
</div>
<p>Trunçgil Teknoloji editörleri tarafından kaleme alınmış bu makalede teknoloji, yazılım geliştirme ve dijital dönüşüm konularına dair güncel gelişmeleri incelediniz. Destek ve sorularınız için bizimle iletişime geçebilirsiniz.</p>
<!-- Social Links -->
<nav class="nav social !mt-4">
<a class="text-[1rem] transition-all duration-[0.2s] ease-in-out translate-y-0 motion-reduce:transition-none hover:translate-y-[-0.15rem] m-[0_.7rem_0_0]" href="https://twitter.com/truncgil" target="_blank"><i class="text-[1rem] !text-[#5daed5] before:content-['\ed59'] uil uil-twitter"></i></a>
<a class="text-[1rem] transition-all duration-[0.2s] ease-in-out translate-y-0 motion-reduce:transition-none hover:translate-y-[-0.15rem] m-[0_.7rem_0_0]" href="https://facebook.com/truncgil" target="_blank"><i class="text-[1rem] !text-[#4470cf] before:content-['\eae2'] uil uil-facebook-f"></i></a>
<a class="text-[1rem] transition-all duration-[0.2s] ease-in-out translate-y-0 motion-reduce:transition-none hover:translate-y-[-0.15rem] m-[0_.7rem_0_0]" href="https://instagram.com/truncgil" target="_blank"><i class="text-[1rem] !text-[#d53581] before:content-['\eb9c'] uil uil-instagram"></i></a>
<a class="text-[1rem] transition-all duration-[0.2s] ease-in-out translate-y-0 motion-reduce:transition-none hover:translate-y-[-0.15rem] m-[0_.7rem_0_0]" href="https://youtube.com/truncgil" target="_blank"><i class="text-[1rem] !text-[#c8312b] before:content-['\edb5'] uil uil-youtube"></i></a>
</nav>
<!-- Related Posts Section (You Might Also Like) -->
@if($relatedPosts && $relatedPosts->count() > 0)
<hr>
<h3 class="!mb-6">Bunları da Beğenebilirsiniz</h3>
<div class="swiper-container blog grid-view !mb-24 relative z-10" data-margin="30" data-dots="true" data-items-md="2" data-items-xs="1">
<div class="swiper">
<div class="swiper-wrapper">
@foreach($relatedPosts as $rPost)
@php
$rTitle = method_exists($rPost, 'translate') ? $rPost->translate('title') : $rPost->title;
$rCategoryName = $rPost->category ? $rPost->category->name : '';
$rImageUrl = $rPost->featured_image ? asset('storage/' . $rPost->featured_image) : asset('assets/img/photos/tb4.jpg');
$rUrl = route('blog.show', $rPost->slug);
$rDate = $rPost->published_at ? $rPost->published_at->format('d M Y') : $rPost->created_at->format('d M Y');
@endphp
<div class="swiper-slide">
<article>
<figure class="overlay overlay-1 hover-scale group rounded !mb-5">
<a href="{{ $rUrl }}">
<img class="!transition-all !duration-[0.35s] !ease-in-out group-hover:scale-105" src="{{ $rImageUrl }}" alt="{{ $rTitle }}" style="height: 220px; object-fit: cover; width: 100%;" loading="lazy">
</a>
<figcaption class="group-hover:opacity-100 absolute w-full h-full opacity-0 text-center px-4 py-3 inset-0 z-[5] pointer-events-none p-2">
<h5 class="from-top !mb-0 absolute w-full translate-y-[-80%] p-[.75rem_1rem] left-0 top-2/4 !text-white">Devamını Oku</h5>
</figcaption>
</figure>
<div class="post-header !mb-[.9rem]">
@if($rPost->category)
<div class="inline-flex !mb-[.4rem] uppercase !tracking-[0.02rem] text-[0.7rem] font-bold !text-[#aab0bc] relative align-top !pl-[1.4rem] before:content-[''] before:absolute before:inline-block before:translate-y-[-60%] before:w-3 before:h-[0.05rem] before:left-0 before:top-2/4 before:bg-[#e31e24]">
<a href="{{ route('blog.index', ['category' => $rPost->category->slug]) }}" class="hover !text-[#e31e24]" rel="category">{{ $rCategoryName }}</a>
</div>
@endif
<h2 class="post-title h3 !mt-1 !mb-3">
<a class="!text-[#343f52] hover:!text-[#e31e24]" href="{{ $rUrl }}">{{ \Illuminate\Support\Str::limit($rTitle, 50) }}</a>
</h2>
</div>
<div class="post-footer">
<ul class="!text-[0.7rem] !text-[#aab0bc] m-0 p-0 list-none !mb-0">
<li class="post-date inline-block"><i class="uil uil-calendar-alt pr-[0.2rem] align-[-.05rem] before:content-['\e9ba']"></i><span>{{ $rDate }}</span></li>
</ul>
</div>
</article>
</div>
@endforeach
</div>
</div>
<div class="swiper-controls">
<div class="swiper-pagination swiper-pagination-clickable swiper-pagination-bullets swiper-pagination-horizontal"></div>
</div>
</div>
@endif
</div>
</div>
</div>
</div>
</div>
</div>
</section>
@endsection
@push('structured-data')
@php
$postTitle = method_exists($post, 'translate') ? $post->translate('title') : $post->title;
$postExcerpt = method_exists($post, 'translate') ? $post->translate('excerpt') : ($post->excerpt ?? '');
$postContent = method_exists($post, 'translate') ? $post->translate('content') : ($post->content ?? '');
$postExcerptText = trim(strip_tags($postExcerpt));
if (empty($postExcerptText)) {
$postExcerptText = \Illuminate\Support\Str::limit(trim(strip_tags($postContent)), 160);
}
$postUrl = route('blog.show', $post->slug);
$imageUrl = $post->featured_image ? asset('storage/' . $post->featured_image) : ($post->featured_image_url ?? asset('assets/img/photos/tb10.jpg'));
$publishedDate = $post->published_at ? $post->published_at->toIso8601String() : $post->created_at->toIso8601String();
$modifiedDate = $post->updated_at ? $post->updated_at->toIso8601String() : $publishedDate;
$authorName = $post->author ? $post->author->name : 'Trunçgil';
$authorRole = $post->author && $post->author->role ? $post->author->role : 'Trunçgil Teknoloji Editörü';
$authorUrl = route('blog.index', ['author' => $post->author_id ?? 1]);
$siteName = setting('site_name', 'Trunçgil Teknoloji');
$siteLogo = setting('site_logo') ? (str_starts_with(setting('site_logo'), 'http') ? setting('site_logo') : asset('storage/' . ltrim(setting('site_logo'), '/'))) : asset('assets/img/logo.png');
$sitePhone = setting('contact_phone', '+902244431620');
$siteEmail = setting('contact_email', 'info@truncgil.com');
$siteAddress = setting('contact_address', 'Gaziantep Teknopark, Şahinbey, Gaziantep');
$socialLinksRaw = setting('social_links');
$socialLinks = [];
if ($socialLinksRaw) {
$decoded = json_decode($socialLinksRaw, true);
if (is_array($decoded)) {
$socialLinks = array_values(array_filter($decoded));
} elseif (is_string($socialLinksRaw)) {
$socialLinks = [$socialLinksRaw];
}
}
if (empty($socialLinks)) {
$socialLinks = [
'https://twitter.com/truncgil',
'https://facebook.com/truncgil',
'https://instagram.com/truncgil',
'https://youtube.com/truncgil',
'https://linkedin.com/company/truncgil'
];
}
// 1. Organization & LocalBusiness combined
$publisherData = [
"@context" => "https://schema.org",
"@type" => "ProfessionalService",
"@id" => url('/') . "#organization",
"name" => $siteName,
"url" => url('/'),
"logo" => [
"@type" => "ImageObject",
"url" => $siteLogo
],
"image" => $siteLogo,
"telephone" => $sitePhone,
"email" => $siteEmail,
"address" => [
"@type" => "PostalAddress",
"streetAddress" => $siteAddress,
"addressLocality" => "Şahinbey",
"addressRegion" => "Gaziantep",
"postalCode" => "27010",
"addressCountry" => "TR"
],
"geo" => [
"@type" => "GeoCoordinates",
"latitude" => 37.0274446,
"longitude" => 37.3074315
],
"hasMap" => "https://maps.google.com/?q=37.0274446,37.3074315",
"sameAs" => $socialLinks,
"areaServed" => [
["@type" => "Country", "name" => "TR"],
["@type" => "Country", "name" => "DE"],
["@type" => "Country", "name" => "RU"],
["@type" => "Country", "name" => "US"],
["@type" => "AdministrativeArea", "name" => "Gaziantep"],
["@type" => "AdministrativeArea", "name" => "Bursa"]
],
"priceRange" => "$$"
];
// 2. BreadcrumbList
$categoryName = $post->category ? $post->category->name : 'Genel';
$categorySlug = $post->category ? $post->category->slug : 'genel';
$categoryUrl = route('blog.index', ['category' => $categorySlug]);
$breadcrumbs = [
"@context" => "https://schema.org",
"@type" => "BreadcrumbList",
"itemListElement" => [
[
"@type" => "ListItem",
"position" => 1,
"name" => "Anasayfa",
"item" => url('/')
],
[
"@type" => "ListItem",
"position" => 2,
"name" => "Blog",
"item" => route('blog.index')
],
[
"@type" => "ListItem",
"position" => 3,
"name" => $categoryName,
"item" => $categoryUrl
],
[
"@type" => "ListItem",
"position" => 4,
"name" => $postTitle,
"item" => $postUrl
]
]
];
// 3. BlogPosting
$blogPosting = [
"@context" => "https://schema.org",
"@type" => "BlogPosting",
"@id" => $postUrl . "#blogposting",
"mainEntityOfPage" => [
"@type" => "WebPage",
"@id" => $postUrl
],
"headline" => $postTitle,
"description" => $postExcerptText,
"image" => $imageUrl,
"datePublished" => $publishedDate,
"dateModified" => $modifiedDate,
"author" => [
"@type" => "Person",
"name" => $authorName,
"jobTitle" => $authorRole,
"url" => $authorUrl
],
"publisher" => [
"@type" => "Organization",
"name" => $siteName,
"logo" => [
"@type" => "ImageObject",
"url" => $siteLogo
]
],
"articleSection" => $categoryName,
"keywords" => is_array($post->tags) ? implode(', ', $post->tags) : ($post->tags ?? '')
];
@endphp
<script type="application/ld+json">
{!! json_encode($publisherData, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) !!}
</script>
<script type="application/ld+json">
{!! json_encode($breadcrumbs, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) !!}
</script>
<script type="application/ld+json">
{!! json_encode($blogPosting, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) !!}
</script>
@endpush
@push('styles')
<!-- CodeMirror Styles -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.css" integrity="sha384-zaeBlB/vwYsDRSlFajnDd7OydJ0cWk+c2OWybl3eSUf6hW2EbhlCsQPqKr3gkznT" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/theme/material-darker.min.css" integrity="sha384-eZTPTN0EvJdn23s24UDYJmUM2T7C2ZFa3qFLypeBruJv8mZeTusKUAO/j5zPAQ6l" crossorigin="anonymous">
<!-- Google Fonts JetBrains Mono -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
<style>
/* Custom modern code block window styling */
.code-window {
background-color: #212529;
border-radius: 12px;
box-shadow: 0 12px 24px rgba(30, 34, 40, 0.08), 0 4px 12px rgba(30, 34, 40, 0.04);
margin: 2rem 0;
overflow: hidden;
border: 1px solid rgba(0, 0, 0, 0.08);
}
.code-window-header {
background-color: #1a1d20;
padding: 0.8rem 1.2rem;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.code-window-dots {
display: flex;
gap: 7px;
align-items: center;
}
.code-window-dot {
width: 11px;
height: 11px;
border-radius: 50%;
}
.dot-red { background-color: #ff5f56; }
.dot-yellow { background-color: #ffbd2e; }
.dot-green { background-color: #27c93f; }
.code-window-lang {
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: #aab0bc;
background-color: rgba(255, 255, 255, 0.08);
padding: 3px 10px;
border-radius: 6px;
font-family: 'Space Grotesk', system-ui, sans-serif;
}
/* Customizing CodeMirror specifically */
.CodeMirror {
font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', Courier, monospace !important;
font-size: 0.85rem !important;
line-height: 1.65 !important;
height: auto !important;
background: #212529 !important;
padding: 0.8rem 0 !important;
}
.CodeMirror-scroll {
max-height: 550px !important;
}
.CodeMirror-gutters {
background-color: #212529 !important;
border-right: 1px solid rgba(255, 255, 255, 0.05) !important;
width: 48px !important;
}
.CodeMirror-linenumber {
color: #4a505e !important;
padding-left: 12px !important;
}
.CodeMirror-cursor {
border-left: 1px solid transparent !important; /* Hide cursor for read-only blocks */
}
/* Styling selection */
.CodeMirror-selected {
background: rgba(255, 255, 255, 0.1) !important;
}
.CodeMirror-focused .CodeMirror-selected {
background: rgba(255, 255, 255, 0.15) !important;
}
</style>
@endpush
@push('scripts')
<!-- CodeMirror Core JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.js" integrity="sha384-uTzi9PU3axyLeKbgCPqQdNFT5Q23BRgFbmtrolYC7ROlbWVv7IggV+3r0ALSQd/s" crossorigin="anonymous"></script>
<!-- CodeMirror Modes -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/xml/xml.min.js" integrity="sha384-xPpkMo5nDgD98fIcuRVYhxkZV6/9Y4L8s3p0J5c4MxgJkyKJ8BJr+xfRkq7kn6Tw" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/javascript/javascript.min.js" integrity="sha384-g0o+WW9mdIxA7LaaCKTkRm0M5TVT+Bb4s9eocxPsI2G0Xm0POG9iD6G6qP1IIsfS" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/css/css.min.js" integrity="sha384-fpeIC2FZuPmw7mIsTvgB5BNc8QVxQC/nWg2W+CgPYOAiBiYVuHe2E8HiTWHBMIJQ" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/clike/clike.min.js" integrity="sha384-bZx++XMDqT0QRVoq6eVZnkq04LmwWZ0eLo0tFdSGkOJgH8qiqeMIIFJ+mRaM0wfb" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/php/php.min.js" integrity="sha384-1FUwPY2kaZKXw258/9CYBSS+zcc3CPggxE1zLjmYYiOdkcOw3KcXH5VNJWWbjw2U" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/python/python.min.js" integrity="sha384-Xy+2exU6lBoT4OpUOtnQb+cUpn+nlJQEHvRobWVtwz6wIsw4oNoO7xyd/l8rYgMy" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/sql/sql.min.js" integrity="sha384-HxXmA1hLc56V6Ja4yfcCwAprmbnS4tuvKYS0qKG3t6oxOFMflcnYq5fOnt6wVCda" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/shell/shell.min.js" integrity="sha384-dmPRq54XNtYnlnAo7QrwJnZNa5r0JP5gU8z4H0686Cgz37qrR2jmNaDHUXyMI4wn" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/yaml/yaml.min.js" integrity="sha384-LekyoEGHzBMGUx26EEtC5G6HD6iyIr0msuy3LP3F8V98vVS5ZoNfIyiirXsoqAt/" crossorigin="anonymous"></script>
<!-- Initialization Script -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const codeBlocks = document.querySelectorAll('.post-content pre code');
if (codeBlocks.length === 0) return;
codeBlocks.forEach(function(codeEl) {
// Extract raw code text securely (safely handled by textContent)
let rawCode = codeEl.textContent || codeEl.innerText;
// Fix double-escaped newlines if the code contains '\n' sequences
if (rawCode.includes('\\n')) {
const literalCount = (rawCode.match(/\\n/g) || []).length;
const actualCount = (rawCode.match(/\n/g) || []).length;
if (literalCount > actualCount) {
rawCode = rawCode.replace(/\\n/g, '\n');
}
}
// Retrieve and parse language from class
let lang = 'code';
const classes = codeEl.className.split(' ');
for (const cls of classes) {
if (cls.startsWith('language-') || cls.startsWith('lang-')) {
lang = cls.replace('language-', '').replace('lang-', '');
break;
}
}
// Map languages to CodeMirror modes
const modeMap = {
'js': 'javascript',
'javascript': 'javascript',
'ts': 'javascript',
'typescript': 'javascript',
'json': 'javascript',
'html': 'xml',
'xml': 'xml',
'svg': 'xml',
'css': 'css',
'php': 'php',
'python': 'python',
'py': 'python',
'sql': 'sql',
'bash': 'shell',
'sh': 'shell',
'shell': 'shell',
'yaml': 'yaml',
'yml': 'yaml'
};
const resolvedMode = modeMap[lang.toLowerCase()] || 'javascript';
// Display nice label for the language badge
const displayLang = lang === 'code' ? 'Code' : lang;
// Build premium macOS-style window wrapping structure strictly using secure DOM methods (no innerHTML)
const preEl = codeEl.parentNode;
if (!preEl || preEl.tagName !== 'PRE') return;
const codeWindow = document.createElement('div');
codeWindow.className = 'code-window';
const header = document.createElement('div');
header.className = 'code-window-header';
const dots = document.createElement('div');
dots.className = 'code-window-dots';
const dotRed = document.createElement('div');
dotRed.className = 'code-window-dot dot-red';
const dotYellow = document.createElement('div');
dotYellow.className = 'code-window-dot dot-yellow';
const dotGreen = document.createElement('div');
dotGreen.className = 'code-window-dot dot-green';
dots.appendChild(dotRed);
dots.appendChild(dotYellow);
dots.appendChild(dotGreen);
const langBadge = document.createElement('div');
langBadge.className = 'code-window-lang';
langBadge.textContent = displayLang; // Secure text content insertion
header.appendChild(dots);
header.appendChild(langBadge);
const editorContainer = document.createElement('div');
editorContainer.className = 'code-editor-container';
codeWindow.appendChild(header);
codeWindow.appendChild(editorContainer);
// Replace the legacy pre tag with our beautiful new code window
preEl.parentNode.replaceChild(codeWindow, preEl);
// Instantiate CodeMirror inside the new container
CodeMirror(editorContainer, {
value: rawCode.trim(),
mode: resolvedMode,
theme: 'material-darker',
lineNumbers: true,
lineWrapping: true,
readOnly: 'nocursor',
viewportMargin: Infinity
});
});
});
</script>
@endpush