Compare commits
19 Commits
9c8181ac32
...
6521e2a057
Author | SHA1 | Date | |
---|---|---|---|
6521e2a057 | |||
709c97acfb | |||
3b59273c12 | |||
d6aa507e1a | |||
82af925f46 | |||
82d2c69e11 | |||
2b9d6d8657 | |||
8fbe06a4fa | |||
92ab6c07ad | |||
ea496f4182 | |||
a2c28ef377 | |||
2885cd1b86 | |||
b71e3faaf9 | |||
393aa52757 | |||
8faa7f472d | |||
6c0b81c883 | |||
132174d0c6 | |||
68fd34c830 | |||
53c5203f23 |
13
.prettierrc
13
.prettierrc
|
@ -1 +1,12 @@
|
||||||
{}
|
{
|
||||||
|
"plugins": ["prettier-plugin-astro"],
|
||||||
|
"bracketSameLine": true,
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": "*.astro",
|
||||||
|
"options": {
|
||||||
|
"parser": "astro"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
12
.vscode/settings.json
vendored
12
.vscode/settings.json
vendored
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"eslint.format.enable": true,
|
"eslint.format.enable": true,
|
||||||
"prettier.configPath": ".prettierrc",
|
"prettier.configPath": ".prettierrc",
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"[javascript]": {
|
"[javascript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1359
package-lock.json
generated
1359
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -13,12 +13,14 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "^0.5.10",
|
"@astrojs/check": "^0.5.10",
|
||||||
"@astrojs/tailwind": "^5.1.0",
|
"@astrojs/tailwind": "^5.1.0",
|
||||||
"astro": "^4.7.0",
|
"astro": "^4.10.0",
|
||||||
|
"htmx.org": "^1.9.12",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
"typescript": "^5.4.5"
|
"typescript": "^5.4.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cypress": "^13.11.0",
|
"cypress": "^13.11.0",
|
||||||
"prettier": "3.2.5"
|
"prettier": "^3.2.5",
|
||||||
|
"prettier-plugin-astro": "^0.14.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
public/favicon.png
Normal file
BIN
public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -1,9 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
|
||||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
|
||||||
<style>
|
|
||||||
path { fill: #000; }
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
path { fill: #FFF; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 749 B |
BIN
public/furkan_erdem_cv.pdf
Normal file
BIN
public/furkan_erdem_cv.pdf
Normal file
Binary file not shown.
14
src/components/Comment.astro
Normal file
14
src/components/Comment.astro
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="comment border-gray-400 border border-solid pt-1 pb-6 ml-4">
|
||||||
|
<p
|
||||||
|
class="font-semibold pl-3 pr-2 pb-1 border-b border-x-0 border-t-0 border-gray-400 border-solid">
|
||||||
|
Arafat Candan
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="pl-3 py-2 pr-4">
|
||||||
|
Daha önce hiç bu açıdan bakmamıştım, harika bir yazı olmuş.
|
||||||
|
</p>
|
||||||
|
</div>
|
90
src/components/CommentForm.astro
Normal file
90
src/components/CommentForm.astro
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
---
|
||||||
|
const { entryId } = Astro.props;
|
||||||
|
const backendHost = import.meta.env.PUBLIC_BACKEND_HOST;
|
||||||
|
---
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.textarea {
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
@apply font-sans text-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
@apply font-sans text-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
@apply text-sm;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<form
|
||||||
|
id="comment-form"
|
||||||
|
hx-post=`${backendHost}/api/blog/comments`
|
||||||
|
hx-target="#comments-container"
|
||||||
|
hx-swap="afterbegin"
|
||||||
|
hx-on:htmx:after-request="document.getElementById('no-comments-text')?.remove();this.reset()">
|
||||||
|
<div class="p-1 flex flex-col flex-end items-end gap-3">
|
||||||
|
<textarea
|
||||||
|
class="textarea py-2 px-3 w-full box-border"
|
||||||
|
rows="5"
|
||||||
|
placeholder="Yazı hakkındaki düşünceleriniz nelerdir?"
|
||||||
|
name="commentBody"
|
||||||
|
required></textarea>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="w-full py-2 px-3 box-border"
|
||||||
|
placeholder="İsminiz (Yazmazsanız yorumunuz anonim kalacaktır)"
|
||||||
|
name="username"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<input type="hidden" name="postId" value=`${entryId}` />
|
||||||
|
<button type="submit" class="px-3 py-1 w-fit" id="comment-form-button"
|
||||||
|
>Yorum Yap</button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div id="comment-form-error-container" class="mt-4">
|
||||||
|
<p id="comment-form-error-text" class="text-red-600"></p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function showError(errorString: string) {
|
||||||
|
const errorTextElement = document.getElementById("comment-form-error-text");
|
||||||
|
|
||||||
|
if (errorTextElement) {
|
||||||
|
errorTextElement.innerText = errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (errorTextElement) {
|
||||||
|
errorTextElement.innerText = "";
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
const formElement = document.getElementById("comment-form");
|
||||||
|
|
||||||
|
if (formElement) {
|
||||||
|
formElement.addEventListener(
|
||||||
|
"htmx:sendError" as keyof HTMLElementEventMap,
|
||||||
|
() => {
|
||||||
|
showError(
|
||||||
|
"Sunucuya ulaşılamadığı için yorumunuz kaydedilemedi, biraz bekledikten sonra tekrar deneyebilirsiniz.",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
formElement.addEventListener(
|
||||||
|
"htmx:responseError" as keyof HTMLElementEventMap,
|
||||||
|
() => {
|
||||||
|
showError(
|
||||||
|
"Suncudan kaynaklı bir hatadan dolayı yorumunuz kaydedilemedi, biraz bekledikten sonra tekrar deneyebilirsiniz.",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -15,35 +15,79 @@ const backendHost = import.meta.env.PUBLIC_BACKEND_HOST;
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
hx-post=`${backendHost}/blog/api/forms/emoji/post`
|
id="emoji-reaction-form"
|
||||||
|
hx-post=`${backendHost}/api/blog/forms/emoji`
|
||||||
hx-target="#reaction-buttons"
|
hx-target="#reaction-buttons"
|
||||||
>
|
hx-trigger="submit delay:0.5s">
|
||||||
<input type="hidden" name="postId" value=`${entryId}` />
|
<input type="hidden" name="postId" value=`${entryId}` />
|
||||||
<div
|
<div
|
||||||
id="reaction-buttons"
|
id="reaction-buttons"
|
||||||
hx-get=`${backendHost}/blog/api/forms/emoji?postId=${entryId}`
|
hx-get=`${backendHost}/api/blog/forms/emoji?postId=${entryId}`
|
||||||
hx-trigger="load"
|
hx-trigger="load"
|
||||||
hx-swap="innerHTML"
|
hx-swap="innerHTML">
|
||||||
>
|
|
||||||
<div class="emoji-buttons-container">
|
<div class="emoji-buttons-container">
|
||||||
<button name="emojiInput" value="👍" type="submit" class="emoji-button"
|
<button name="emojiInput" value="👍" type="submit" class="emoji-button">
|
||||||
>👍 </button
|
👍
|
||||||
>
|
</button>
|
||||||
<button name="emojiInput" value="👎" type="submit" class="emoji-button"
|
<button name="emojiInput" value="👎" type="submit" class="emoji-button">
|
||||||
>👎 </button
|
👎
|
||||||
>
|
</button>
|
||||||
<button name="emojiInput" value="😀" type="submit" class="emoji-button"
|
<button name="emojiInput" value="😀" type="submit" class="emoji-button">
|
||||||
>😀 </button
|
😀
|
||||||
>
|
</button>
|
||||||
<button name="emojiInput" value="😑" type="submit" class="emoji-button"
|
<button name="emojiInput" value="😑" type="submit" class="emoji-button">
|
||||||
>😑 </button
|
😑
|
||||||
>
|
</button>
|
||||||
<button name="emojiInput" value="🤢" type="submit" class="emoji-button"
|
<button name="emojiInput" value="🤢" type="submit" class="emoji-button">
|
||||||
>🤢 </button
|
🤢
|
||||||
>
|
</button>
|
||||||
<button name="emojiInput" value="👀" type="submit" class="emoji-button"
|
<button name="emojiInput" value="👀" type="submit" class="emoji-button">
|
||||||
>👀 </button
|
👀
|
||||||
>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="emoji-form-error-container" class="mt-4">
|
||||||
|
<p id="emoji-form-error-text" class="text-red-600"></p>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function showError(errorString: string) {
|
||||||
|
const errorTextElement = document.getElementById("emoji-form-error-text");
|
||||||
|
|
||||||
|
if (errorTextElement) {
|
||||||
|
errorTextElement.innerText = errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (errorTextElement) {
|
||||||
|
errorTextElement.innerText = "";
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
const formElement = document.getElementById("emoji-reaction-form");
|
||||||
|
|
||||||
|
if (formElement) {
|
||||||
|
formElement.addEventListener(
|
||||||
|
"htmx:sendError" as keyof HTMLElementEventMap,
|
||||||
|
(event) => {
|
||||||
|
// @ts-ignore detail attribute is added by htmx
|
||||||
|
if (event.detail.elt.id != "reaction-buttons") {
|
||||||
|
showError(
|
||||||
|
"Sunucuya ulaşılamadığı için tepkiniz kaydedilemedi, biraz bekledikten sonra tekrar deneyebilirsiniz.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
formElement.addEventListener(
|
||||||
|
"htmx:responseError" as keyof HTMLElementEventMap,
|
||||||
|
() => {
|
||||||
|
showError(
|
||||||
|
"Sunucudan kaynaklanan bir hatadan dolayı tepkiniz kaydedilemedi, biraz bekledikten sonra tekrar deneyebilirsiniz.",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
|
@ -4,5 +4,5 @@
|
||||||
|
|
||||||
<div class="flex flex-row items-center gap-2 text-gray-500 text-sm">
|
<div class="flex flex-row items-center gap-2 text-gray-500 text-sm">
|
||||||
<p class="copyright">© 2024 Furkan Erdem</p>
|
<p class="copyright">© 2024 Furkan Erdem</p>
|
||||||
<a class="text-inherit" href="#">Hakkımda</a>
|
<a class="text-inherit" href="/about">Hakkımda</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,50 +18,61 @@
|
||||||
|
|
||||||
<div class="flex flex-col justify-start gap-2">
|
<div class="flex flex-col justify-start gap-2">
|
||||||
<ul class="flex flex-row items-center list-none p-0 gap-3 contact-links">
|
<ul class="flex flex-row items-center list-none p-0 gap-3 contact-links">
|
||||||
<li><a href="#">Eposta</a></li>
|
<li><a href="mailto:ffrknerdm@gmail.com">Eposta</a></li>
|
||||||
<li><a href="#">Github</a></li>
|
<li><a href="https://github.com/log101" target="_blank">Github</a></li>
|
||||||
<li><a href="#">LinkedIn</a></li>
|
<li>
|
||||||
<li><a href="#">CV</a></li>
|
<a
|
||||||
|
href="https://www.linkedin.com/in/furkan-erdem-506548218/"
|
||||||
|
target="_blank">LinkedIn</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li><a href="/furkan_erdem_cv.pdf" target="_blank">CV</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="flex flex-row gap-2 items-center md:h-20 h-16">
|
<div
|
||||||
<a href="/" class="no-underline text-inherit"
|
class="flex flex-row gap-2 items-center md:h-20 h-16"
|
||||||
><h1 class="font-mono md:text-6xl text-5xl -ml-[0.27rem]">Log101</h1></a
|
id="title-container">
|
||||||
>
|
<a href="/" class="no-underline text-inherit -ml-[0.27rem]" id="title">
|
||||||
|
<h1 class="font-mono md:text-6xl text-5xl">Log101</h1>
|
||||||
|
</a>
|
||||||
<div id="board" class="board"></div>
|
<div id="board" class="board"></div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="border-b border-x-0 border-t-0 border-slate-900 border-solid">
|
||||||
<ul
|
<ul
|
||||||
class="flex md:flex-row flex-col md:items-center justify-between list-none p-0 gap-3 nav-links"
|
class="flex md:flex-row flex-col md:items-center justify-between list-none p-0 gap-3 nav-links">
|
||||||
>
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/category/fikir">Fikir</a>
|
<a href="/fikir/1">Fikir</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/category/teknik">Teknik</a>
|
<a href="/teknik/1">Teknik</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/category/edebiyat">Babür'ün Serüvenleri</a>
|
<a href="/edebiyat/1">Babür'ün Serüvenleri</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/category/ansiklopedi">Ansiklopedi</a>
|
<a href="/ansiklopedi/1">Ansiklopedi</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr class="mb-0 mt-2" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ConwaySimulator from "../scripts/conway-simulator";
|
import ConwaySimulator from "../scripts/conway-simulator";
|
||||||
let rows = 8;
|
const title = document.getElementById("title");
|
||||||
let cols = 24;
|
const titleContainer = document.getElementById("title-container");
|
||||||
|
|
||||||
|
const titleWidth = title?.offsetWidth ?? 194;
|
||||||
|
const titleContainerWidth = titleContainer?.offsetWidth ?? 750;
|
||||||
|
|
||||||
let pixelSize = 6;
|
let pixelSize = 6;
|
||||||
|
let rows = 8;
|
||||||
|
let cols = (titleContainerWidth - titleWidth) / pixelSize;
|
||||||
let delay = 250;
|
let delay = 250;
|
||||||
|
|
||||||
if (screen.availWidth > 768) {
|
if (screen.availWidth > 768) {
|
||||||
cols = 46;
|
cols = 60;
|
||||||
pixelSize = 8;
|
pixelSize = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
src/components/HorizontalLine.astro
Normal file
5
src/components/HorizontalLine.astro
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="border-b border-x-0 border-t-0 border-solid border-slate-700"></div>
|
|
@ -39,7 +39,7 @@ switch (componentType) {
|
||||||
// Options should not mutated further
|
// Options should not mutated further
|
||||||
Object.freeze(options);
|
Object.freeze(options);
|
||||||
|
|
||||||
// Format datae
|
// Format date
|
||||||
const postDateFormatted = post.data.date.toLocaleDateString("tr-TR", {
|
const postDateFormatted = post.data.date.toLocaleDateString("tr-TR", {
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
month: "long",
|
month: "long",
|
||||||
|
@ -47,7 +47,7 @@ const postDateFormatted = post.data.date.toLocaleDateString("tr-TR", {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create post link
|
// Create post link
|
||||||
const postLink = `/category/${post.data.category}/${post.slug}`;
|
const postLink = `/${post.data.category}/${post.slug}`;
|
||||||
|
|
||||||
// Create post content as an astro component
|
// Create post content as an astro component
|
||||||
const { Content } = await post.render();
|
const { Content } = await post.render();
|
||||||
|
@ -71,9 +71,9 @@ import calendar from "@/images/calendar.svg";
|
||||||
<div class="flex flex-col gap-3">
|
<div class="flex flex-col gap-3">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<p class="tracking-wide text-slate-700">{post.data.subcategory}</p>
|
<p class="tracking-wide text-slate-700">{post.data.subcategory}</p>
|
||||||
<a class="no-underline text-inherit" href={postLink}
|
<a class="no-underline text-inherit" href={postLink}>
|
||||||
><h4 class="text-3xl font-normal">{post.data.title}</h4></a
|
<h4 class="text-3xl font-normal">{post.data.title}</h4>
|
||||||
>
|
</a>
|
||||||
<div class="flex flex-row gap-2">
|
<div class="flex flex-row gap-2">
|
||||||
{
|
{
|
||||||
options.showTags && (
|
options.showTags && (
|
||||||
|
@ -107,8 +107,7 @@ import calendar from "@/images/calendar.svg";
|
||||||
{post.body.length > 500 && (
|
{post.body.length > 500 && (
|
||||||
<a
|
<a
|
||||||
class="text-inherit text-sm"
|
class="text-inherit text-sm"
|
||||||
href={`/category/${post.data.category}/${post.slug}`}
|
href={`/${post.data.category}/${post.slug}`}>
|
||||||
>
|
|
||||||
Devamını Oku
|
Devamını Oku
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
|
|
6
src/env.d.ts
vendored
6
src/env.d.ts
vendored
|
@ -1,2 +1,8 @@
|
||||||
/// <reference path="../.astro/types.d.ts" />
|
/// <reference path="../.astro/types.d.ts" />
|
||||||
/// <reference types="astro/client" />
|
/// <reference types="astro/client" />
|
||||||
|
|
||||||
|
export declare global {
|
||||||
|
interface Window {
|
||||||
|
htmx: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,16 +13,20 @@ import "../styles/main.css";
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="description" content="Astro description" />
|
<meta name="description" content="Astro description" />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||||
<meta name="generator" content={Astro.generator} />
|
<meta name="generator" content={Astro.generator} />
|
||||||
<script src="../scripts/htmx.min.js"></script>
|
<meta name="htmx-config" content='{code:"204", swap: false}' />
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="flex justify-center font-sans">
|
<body class="flex justify-center font-sans">
|
||||||
<div
|
<div
|
||||||
class="md:max-w-[750px] w-full flex flex-col gap-8 md:gap-6 my-6 md:mx-0 mx-4 overflow-hidden"
|
class="md:max-w-[750px] w-full flex flex-col gap-8 md:gap-6 my-6 md:mx-0 mx-4 overflow-hidden">
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
<script>
|
||||||
|
import htmx from "htmx.org";
|
||||||
|
|
||||||
|
window.htmx = htmx;
|
||||||
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
|
86
src/pages/[category]/[page]/index.astro
Normal file
86
src/pages/[category]/[page]/index.astro
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
---
|
||||||
|
import type { Page } from "astro";
|
||||||
|
import { getCollection } from "astro:content";
|
||||||
|
import { CATEGORIES } from "@/content/config";
|
||||||
|
|
||||||
|
import Header from "@/components/Header.astro";
|
||||||
|
import Footer from "@/components/Footer.astro";
|
||||||
|
import Layout from "@/layouts/Layout.astro";
|
||||||
|
import Post from "@/components/Post.astro";
|
||||||
|
|
||||||
|
export async function getStaticPaths({ paginate }: { paginate: any }) {
|
||||||
|
const blogEntries = await getCollection("blog");
|
||||||
|
|
||||||
|
return CATEGORIES.flatMap((category) => {
|
||||||
|
const filteredPosts = blogEntries.filter(
|
||||||
|
(post) => post.data.category == category,
|
||||||
|
);
|
||||||
|
return paginate(filteredPosts, {
|
||||||
|
params: { category },
|
||||||
|
pageSize: 3,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
page: Page;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { page } = Astro.props;
|
||||||
|
|
||||||
|
const posts = page.data;
|
||||||
|
|
||||||
|
const pages = Array.from({ length: page.lastPage }, (_, i) => i + 1);
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title="log101">
|
||||||
|
<Header />
|
||||||
|
<div class="posts">
|
||||||
|
{
|
||||||
|
posts.length > 0 ? (
|
||||||
|
posts
|
||||||
|
.sort((p1, p2) => p2.data.date.getTime() - p1.data.date.getTime())
|
||||||
|
.map((p) => <Post post={p} componentType="long" />)
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
Henüz bu kategoride bir yazı yayınlanmadı. Yazarımızın ilhama veya
|
||||||
|
teşviğe ihtiyacı olabilir!
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
page.lastPage != 1 && (
|
||||||
|
<>
|
||||||
|
<div id="pagination-container" class="flex gap-2">
|
||||||
|
<button>
|
||||||
|
<a href={page.url.prev} class="no-underline text-inherit">
|
||||||
|
geri git
|
||||||
|
</a>
|
||||||
|
</button>
|
||||||
|
{pages.map((pageNumber) => {
|
||||||
|
switch (pageNumber) {
|
||||||
|
case page.currentPage:
|
||||||
|
return <a>{pageNumber}</a>;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={`${page.url.current.slice(0, -1)}${pageNumber}`}
|
||||||
|
class="text-inherit">
|
||||||
|
{pageNumber}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
<button>
|
||||||
|
<a href={page.url.next} class="no-underline text-inherit">
|
||||||
|
ileri git
|
||||||
|
</a>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<Footer />
|
||||||
|
</Layout>
|
|
@ -6,11 +6,16 @@ import Header from "@/components/Header.astro";
|
||||||
import Layout from "@/layouts/Layout.astro";
|
import Layout from "@/layouts/Layout.astro";
|
||||||
import Post from "@/components/Post.astro";
|
import Post from "@/components/Post.astro";
|
||||||
import EmojiReactionForm from "@/components/EmojiReactionForm.astro";
|
import EmojiReactionForm from "@/components/EmojiReactionForm.astro";
|
||||||
|
import CommentForm from "@/components/CommentForm.astro";
|
||||||
|
import HorizontalLine from "@/components/HorizontalLine.astro";
|
||||||
|
|
||||||
const { entry } = Astro.props;
|
const { entry } = Astro.props;
|
||||||
|
|
||||||
|
const backendHost = import.meta.env.PUBLIC_BACKEND_HOST;
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const blogEntries = await getCollection("blog");
|
const blogEntries = await getCollection("blog");
|
||||||
|
|
||||||
return blogEntries.map((entry) => ({
|
return blogEntries.map((entry) => ({
|
||||||
params: { category: entry.data.category, slug: entry.slug },
|
params: { category: entry.data.category, slug: entry.slug },
|
||||||
props: { entry },
|
props: { entry },
|
||||||
|
@ -22,5 +27,21 @@ export async function getStaticPaths() {
|
||||||
<Header />
|
<Header />
|
||||||
<Post post={entry} componentType="full" />
|
<Post post={entry} componentType="full" />
|
||||||
<EmojiReactionForm entryId={entry.id} />
|
<EmojiReactionForm entryId={entry.id} />
|
||||||
|
|
||||||
|
<section class="comments">
|
||||||
|
<h6 class="text-xl mb-3">Yorumlar</h6>
|
||||||
|
<div class="flex flex-col gap-6">
|
||||||
|
<div
|
||||||
|
hx-get=`${backendHost}/api/blog/comments?postId=${entry.id}`
|
||||||
|
hx-trigger="load"
|
||||||
|
hx-swap="innerHTML"
|
||||||
|
id="comments-container"
|
||||||
|
class="flex flex-col gap-6">
|
||||||
|
<p id="no-comments-text">Henüz yorum yok!</p>
|
||||||
|
</div>
|
||||||
|
<HorizontalLine />
|
||||||
|
<CommentForm entryId={entry.id} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
<Footer />
|
<Footer />
|
||||||
</Layout>
|
</Layout>
|
35
src/pages/about.astro
Normal file
35
src/pages/about.astro
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
import Header from "@/components/Header.astro";
|
||||||
|
import Footer from "@/components/Footer.astro";
|
||||||
|
import Layout from "@/layouts/Layout.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title="log101">
|
||||||
|
<Header />
|
||||||
|
<p>
|
||||||
|
İsmini açıklayamayacağım uzak bir gezegende, elektronik bilgisayarlar
|
||||||
|
yalnızca eğlence amaçlı kullanılıyor. Programlama ise orada bir spor
|
||||||
|
sayılıyor, hatta bir olimpiyat sporu! Bunları, yıllar önce benimle iletişime
|
||||||
|
geçen Merhume isimli bir şahıstan öğrendim. Kendisini gezegenlerarası bir
|
||||||
|
gezgin olarak tanımlayan bu şahıs bana uzun uzun ziyaret maksadından,
|
||||||
|
geldiği yerden bahsettikten sonra elime eski püskü bir deri çanta tutuşturdu
|
||||||
|
ve esrarengiz, arabaya benzer aracıyla kaybolup gitti. Eve döndüğümde
|
||||||
|
çantanın içerisinde üzerlerine yayın tarihleri iliştirilmiş yüzlerce yazı
|
||||||
|
olduğunu gördüm. Bunlar çoğunlukla, programlamaya, bilgisayarlara dair kısa,
|
||||||
|
bir-iki sayfalık denemelerdi. Aralarında edebi, felsefi metinlere de
|
||||||
|
rastladım. Bir de "Babür'ün Serüvenleri" vardı, kalın, kara kapaklı bir
|
||||||
|
roman. Romanın sayfalarını karıştırırken kucağıma bir not kağıdı düştü.
|
||||||
|
Kağıdın üzerinde içe içe geçmiş birbirini kesen çemberler vardı, köşesinde
|
||||||
|
de bir şiir. Sebebini anlamasam da benden bu yazıları yayınlamamı
|
||||||
|
istediklerini anladım, işte bu genel ağ sayfası da böyle ortaya çıktı.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Tüm bu yazılar veya bu yaşadıklarım ne anlama geliyor, inanın bilmiyorum.
|
||||||
|
Üzerime düşen bu mütevazı vazifeyi yerine getirmekle yetindiğim ve bu
|
||||||
|
gizemin peşinde düşmediğim için beni mazur görün. Belki de Merhume'nin,
|
||||||
|
memleketinin, bu yazıların gizemi benden sonrakiler tarafından ortaya
|
||||||
|
çıkarılır.
|
||||||
|
</p>
|
||||||
|
<p><i>Saygı ve sevgilerimle, <br />Furkan Erdem</i></p>
|
||||||
|
<Footer />
|
||||||
|
</Layout>
|
|
@ -1,36 +0,0 @@
|
||||||
---
|
|
||||||
import { getCollection } from "astro:content";
|
|
||||||
import { CATEGORIES } from "@/content/config";
|
|
||||||
|
|
||||||
import Header from "@/components/Header.astro";
|
|
||||||
import Footer from "@/components/Footer.astro";
|
|
||||||
import Layout from "@/layouts/Layout.astro";
|
|
||||||
import Post from "@/components/Post.astro";
|
|
||||||
|
|
||||||
export function getStaticPaths() {
|
|
||||||
return CATEGORIES.map((category) => {
|
|
||||||
return {
|
|
||||||
params: { category },
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const { category } = Astro.params;
|
|
||||||
|
|
||||||
const allTeknikPosts = await getCollection(
|
|
||||||
"blog",
|
|
||||||
(post) => post.data.category === category
|
|
||||||
);
|
|
||||||
---
|
|
||||||
|
|
||||||
<Layout title="log101">
|
|
||||||
<Header />
|
|
||||||
<div class="posts">
|
|
||||||
{
|
|
||||||
allTeknikPosts
|
|
||||||
.sort((p1, p2) => p2.data.date.getTime() - p1.data.date.getTime())
|
|
||||||
.map((p) => <Post post={p} componentType="long" />)
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<Footer />
|
|
||||||
</Layout>
|
|
|
@ -18,6 +18,6 @@ const allTeknikPosts = await getCollection("blog");
|
||||||
.map((p) => <Post post={p} componentType="short" />)
|
.map((p) => <Post post={p} componentType="short" />)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<a class="text-inherit" href="#">Tüm Yayınlar</a>
|
<a class="text-inherit" href="/posts/1">Tüm Yayınlar</a>
|
||||||
<Footer />
|
<Footer />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
74
src/pages/posts/[page].astro
Normal file
74
src/pages/posts/[page].astro
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
---
|
||||||
|
import type { Page } from "astro";
|
||||||
|
import { getCollection } from "astro:content";
|
||||||
|
|
||||||
|
import Header from "@/components/Header.astro";
|
||||||
|
import Footer from "@/components/Footer.astro";
|
||||||
|
import Layout from "@/layouts/Layout.astro";
|
||||||
|
import Post from "@/components/Post.astro";
|
||||||
|
|
||||||
|
export async function getStaticPaths({ paginate }: { paginate: any }) {
|
||||||
|
const blogEntries = await getCollection("blog");
|
||||||
|
return paginate(blogEntries, {
|
||||||
|
pageSize: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
page: Page;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { page } = Astro.props;
|
||||||
|
|
||||||
|
const posts = page.data;
|
||||||
|
|
||||||
|
const pages = Array.from({ length: page.lastPage }, (_, i) => i + 1);
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title="log101">
|
||||||
|
<Header />
|
||||||
|
<div class="posts">
|
||||||
|
{
|
||||||
|
posts.length > 0 ? (
|
||||||
|
posts
|
||||||
|
.sort((p1, p2) => p2.data.date.getTime() - p1.data.date.getTime())
|
||||||
|
.map((p) => <Post post={p} componentType="long" />)
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
Henüz bu kategoride bir yazı yayınlanmadı. Yazarımızın ilhama veya
|
||||||
|
teşviğe ihtiyacı olabilir!
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
page.lastPage != 1 && (
|
||||||
|
<>
|
||||||
|
<div id="pagination-container" class="flex gap-2">
|
||||||
|
<a href={page.url.prev} class="no-underline text-inherit">
|
||||||
|
<button class="cursor-pointer">geri git</button>
|
||||||
|
</a>
|
||||||
|
{pages.map((pageNumber) => {
|
||||||
|
switch (pageNumber) {
|
||||||
|
case page.currentPage:
|
||||||
|
return <a>{pageNumber}</a>;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={`${page.url.current.slice(0, -1)}${pageNumber}`}
|
||||||
|
class="text-inherit">
|
||||||
|
{pageNumber}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
<a href={page.url.next} class="no-underline text-inherit">
|
||||||
|
<button class="cursor-pointer">ileri git</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<Footer />
|
||||||
|
</Layout>
|
|
@ -1,3 +1,5 @@
|
||||||
|
// https://github.com/Tebs-Lab/conways-game-of-life
|
||||||
|
|
||||||
import { heavyWeightSpaceshipCell } from "./utils";
|
import { heavyWeightSpaceshipCell } from "./utils";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
1
src/scripts/htmx.min.js
vendored
1
src/scripts/htmx.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user