fix
This commit is contained in:
1151
dist/server/pages/_image.astro.mjs
vendored
Normal file
1151
dist/server/pages/_image.astro.mjs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
30
dist/server/pages/_page_.astro.mjs
vendored
Normal file
30
dist/server/pages/_page_.astro.mjs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import { c as createComponent, d as renderComponent, r as renderTemplate, b as createAstro, m as maybeRenderHead } from '../chunks/astro/server_DrnzQWw3.mjs';
|
||||
import 'kleur/colors';
|
||||
import { $ as $$BaseLayout } from '../chunks/BaseLayout_Bc2tHXHa.mjs';
|
||||
import { g as getStaticPageBySlug } from '../chunks/cms_CRTVymfB.mjs';
|
||||
export { renderers } from '../renderers.mjs';
|
||||
|
||||
const $$Astro = createAstro();
|
||||
const $$page = createComponent(($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$page;
|
||||
const page = getStaticPageBySlug(Astro2.params.page ?? "");
|
||||
if (!page) {
|
||||
return Astro2.redirect("/");
|
||||
}
|
||||
return renderTemplate`${renderComponent($$result, "BaseLayout", $$BaseLayout, { "title": `${page.title} | \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632`, "description": page.description }, { "default": ($$result2) => renderTemplate` ${maybeRenderHead()}<main class="max-w-4xl mx-auto px-4 lg:px-8 py-8"> <article class="bg-white rounded-2xl shadow-sm p-5 sm:p-8"> <span class="text-brand text-sm font-bold">روس امروز</span> <h1 class="text-2xl sm:text-4xl font-black leading-snug mt-2">${page.title}</h1> <p class="text-gray-500 leading-relaxed mt-4">${page.description}</p> <div class="space-y-5 text-gray-700 leading-8 text-base border-t border-gray-100 mt-6 pt-6"> ${page.body.map((paragraph) => renderTemplate`<p>${paragraph}</p>`)} </div> </article> </main> ` })}`;
|
||||
}, "/Users/drfelfel/ruseemrooz/src/pages/[page].astro", void 0);
|
||||
|
||||
const $$file = "/Users/drfelfel/ruseemrooz/src/pages/[page].astro";
|
||||
const $$url = "/[page]";
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$page,
|
||||
file: $$file,
|
||||
url: $$url
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
99
dist/server/pages/admin.astro.mjs
vendored
Normal file
99
dist/server/pages/admin.astro.mjs
vendored
Normal file
File diff suppressed because one or more lines are too long
35
dist/server/pages/admin/login.astro.mjs
vendored
Normal file
35
dist/server/pages/admin/login.astro.mjs
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import { c as createComponent, e as renderHead, r as renderTemplate, b as createAstro } from '../../chunks/astro/server_DrnzQWw3.mjs';
|
||||
import 'kleur/colors';
|
||||
import 'clsx';
|
||||
/* empty css */
|
||||
import { i as isAdminAuthenticated } from '../../chunks/adminAuth_CY4OwU1a.mjs';
|
||||
export { renderers } from '../../renderers.mjs';
|
||||
|
||||
const $$Astro = createAstro();
|
||||
const $$Login = createComponent(($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$Login;
|
||||
if (isAdminAuthenticated(Astro2)) {
|
||||
return Astro2.redirect("/admin/");
|
||||
}
|
||||
const error = Astro2.url.searchParams.has("error");
|
||||
return renderTemplate`<html lang="fa" dir="rtl"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ورود ادمین | روس امروز</title><link rel="stylesheet" href="https://rc0.ir/vazirmatn/Vazirmatn-font-face.css">${renderHead()}</head> <body class="bg-gray-100 font-vazir text-gray-900 min-h-screen flex items-center justify-center p-4"> <form action="/api/admin/login" method="post" class="bg-white rounded-2xl shadow-sm p-6 w-full max-w-sm space-y-4"> <div> <span class="text-brand text-sm font-bold">روس امروز</span> <h1 class="text-2xl font-black mt-1">ورود ادمین</h1> </div> ${error && renderTemplate`<p class="bg-red-50 text-brand text-sm rounded-xl px-3 py-2">نام کاربری یا رمز عبور اشتباه است.</p>`} <label class="block text-sm font-bold">
|
||||
نام کاربری
|
||||
<input name="username" value="admin" class="mt-2 w-full bg-gray-100 rounded-xl px-4 py-3 outline-none focus:ring-1 focus:ring-brand"> </label> <label class="block text-sm font-bold">
|
||||
رمز عبور
|
||||
<input name="password" type="password" placeholder="admin123" class="mt-2 w-full bg-gray-100 rounded-xl px-4 py-3 outline-none focus:ring-1 focus:ring-brand"> </label> <button class="w-full bg-brand text-white rounded-xl py-3 font-bold hover:bg-red-700 transition-colors">ورود</button> <p class="text-xs text-gray-400 leading-6">پیشفرض: \`admin\` / \`admin123\`؛ برای production از \`ADMIN_USER\` و \`ADMIN_PASSWORD\` استفاده کنید.</p> </form> </body></html>`;
|
||||
}, "/Users/drfelfel/ruseemrooz/src/pages/admin/login.astro", void 0);
|
||||
|
||||
const $$file = "/Users/drfelfel/ruseemrooz/src/pages/admin/login.astro";
|
||||
const $$url = "/admin/login";
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$Login,
|
||||
file: $$file,
|
||||
url: $$url
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
22
dist/server/pages/api/admin/login.astro.mjs
vendored
Normal file
22
dist/server/pages/api/admin/login.astro.mjs
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import { a as isValidLogin, s as setAdminSession } from '../../../chunks/adminAuth_CY4OwU1a.mjs';
|
||||
export { renderers } from '../../../renderers.mjs';
|
||||
|
||||
const POST = async (context) => {
|
||||
const formData = await context.request.formData();
|
||||
const username = String(formData.get("username") ?? "");
|
||||
const password = String(formData.get("password") ?? "");
|
||||
if (!isValidLogin(username, password)) {
|
||||
return context.redirect("/admin/login/?error=1", 302);
|
||||
}
|
||||
setAdminSession(context);
|
||||
return context.redirect("/admin/", 302);
|
||||
};
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
POST
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
16
dist/server/pages/api/admin/logout.astro.mjs
vendored
Normal file
16
dist/server/pages/api/admin/logout.astro.mjs
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { c as clearAdminSession } from '../../../chunks/adminAuth_CY4OwU1a.mjs';
|
||||
export { renderers } from '../../../renderers.mjs';
|
||||
|
||||
const POST = async (context) => {
|
||||
clearAdminSession(context);
|
||||
return context.redirect("/admin/login/", 302);
|
||||
};
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
POST
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
143
dist/server/pages/api/admin/save.astro.mjs
vendored
Normal file
143
dist/server/pages/api/admin/save.astro.mjs
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
import { r as requireAdmin } from '../../../chunks/adminAuth_CY4OwU1a.mjs';
|
||||
import { r as readCms, w as writeCms } from '../../../chunks/cms_CRTVymfB.mjs';
|
||||
import { p as publishPost } from '../../../chunks/publisher_Dj_UvF8J.mjs';
|
||||
import { g as getTassFeedLinks } from '../../../chunks/tassAgent_jxZgSz7r.mjs';
|
||||
export { renderers } from '../../../renderers.mjs';
|
||||
|
||||
const toList = (value) => String(value ?? "").split(/\r?\n|,/).map((item) => item.trim()).filter(Boolean);
|
||||
const toParagraphs = (value) => String(value ?? "").split(/\n\s*\n/).map((item) => item.trim()).filter(Boolean);
|
||||
const POST = async (context) => {
|
||||
const unauthorized = requireAdmin(context);
|
||||
if (unauthorized) {
|
||||
return unauthorized;
|
||||
}
|
||||
const formData = await context.request.formData();
|
||||
const action = String(formData.get("action") ?? "");
|
||||
const cms = await readCms();
|
||||
const tab = String(formData.get("tab") ?? "pending");
|
||||
if (action === "post-status") {
|
||||
const slug = String(formData.get("slug") ?? "");
|
||||
const status = String(formData.get("status") ?? "pending");
|
||||
cms.posts = cms.posts.map((post) => post.slug === slug ? { ...post, status } : post);
|
||||
}
|
||||
if (action === "toggle-post-flag") {
|
||||
const slug = String(formData.get("slug") ?? "");
|
||||
const flag = String(formData.get("flag") ?? "");
|
||||
cms.posts = cms.posts.map((post) => {
|
||||
if (post.slug !== slug) {
|
||||
return post;
|
||||
}
|
||||
if (flag === "urgent") {
|
||||
return { ...post, urgent: !post.urgent };
|
||||
}
|
||||
if (flag === "sidebar") {
|
||||
return { ...post, sidebar: !post.sidebar };
|
||||
}
|
||||
return post;
|
||||
});
|
||||
}
|
||||
if (action === "set-breaking-post") {
|
||||
const slug = String(formData.get("slug") ?? "");
|
||||
const post = cms.posts.find((item) => item.slug === slug);
|
||||
if (post) {
|
||||
cms.settings.breakingNews = {
|
||||
...cms.settings.breakingNews,
|
||||
href: `/posts/${post.slug}/`,
|
||||
items: [post.title],
|
||||
postSlugs: [post.slug]
|
||||
};
|
||||
}
|
||||
}
|
||||
if (action === "set-home-featured") {
|
||||
const slug = String(formData.get("slug") ?? "");
|
||||
cms.settings.homeLayout.featuredSlug = slug;
|
||||
}
|
||||
if (action === "clear-tass-memory") {
|
||||
cms.settings.agents = {
|
||||
...cms.settings.agents,
|
||||
tass: { processedLinks: [] }
|
||||
};
|
||||
}
|
||||
if (action === "fill-tass-memory") {
|
||||
const links = cms.posts.map((post) => post.sourceUrl).filter(Boolean);
|
||||
const feedLinks = await getTassFeedLinks(50);
|
||||
cms.settings.agents = {
|
||||
...cms.settings.agents,
|
||||
tass: { processedLinks: Array.from(/* @__PURE__ */ new Set([...links, ...feedLinks])) }
|
||||
};
|
||||
}
|
||||
if (action === "delete-post") {
|
||||
const slug = String(formData.get("slug") ?? "");
|
||||
const confirm = String(formData.get("confirm") ?? "");
|
||||
if (confirm !== "confirm") {
|
||||
return context.redirect(`/admin/?deleteError=1&tab=${encodeURIComponent(tab)}`, 302);
|
||||
}
|
||||
cms.posts = cms.posts.filter((post) => post.slug !== slug);
|
||||
}
|
||||
if (action === "delete-all-posts") {
|
||||
const confirm = String(formData.get("confirm") ?? "");
|
||||
if (confirm !== "confirm") {
|
||||
return context.redirect(`/admin/?deleteError=1&tab=${encodeURIComponent(tab)}`, 302);
|
||||
}
|
||||
cms.posts = [];
|
||||
}
|
||||
if (action === "save-post") {
|
||||
const originalSlug = String(formData.get("originalSlug") ?? "");
|
||||
const title = String(formData.get("title") ?? "").trim();
|
||||
const post = await publishPost({
|
||||
slug: String(formData.get("slug") ?? "") || title,
|
||||
title,
|
||||
category: String(formData.get("category") ?? cms.categories[0] ?? "عمومی"),
|
||||
time: String(formData.get("time") ?? "").trim() || "هماکنون",
|
||||
readTime: String(formData.get("readTime") ?? "").trim() || "۳ دقیقه",
|
||||
excerpt: String(formData.get("excerpt") ?? "").trim(),
|
||||
status: String(formData.get("status") ?? "pending"),
|
||||
body: toParagraphs(formData.get("body")),
|
||||
image: String(formData.get("image") ?? "").trim() || void 0,
|
||||
thumbnail: String(formData.get("thumbnail") ?? "").trim() || void 0,
|
||||
urgent: formData.get("urgent") === "on",
|
||||
sidebar: formData.get("sidebar") === "on"
|
||||
});
|
||||
if (originalSlug && originalSlug !== post.slug) {
|
||||
const updatedCms = await readCms();
|
||||
updatedCms.posts = updatedCms.posts.filter((post2) => post2.slug !== originalSlug);
|
||||
await writeCms(updatedCms);
|
||||
}
|
||||
return context.redirect(`/admin/?saved=1&tab=${post.status === "approved" ? "approved" : "pending"}`, 302);
|
||||
}
|
||||
if (action === "categories") {
|
||||
cms.categories = toList(formData.get("categories"));
|
||||
}
|
||||
if (action === "settings") {
|
||||
cms.settings.breakingNews = {
|
||||
label: String(formData.get("breakingLabel") ?? "فوری").trim(),
|
||||
href: String(formData.get("breakingHref") ?? "/").trim(),
|
||||
items: toList(formData.get("breakingItems")),
|
||||
postSlugs: toList(formData.get("breakingPostSlugs"))
|
||||
};
|
||||
cms.settings.hotTopics = toList(formData.get("hotTopics"));
|
||||
cms.settings.homeLayout = {
|
||||
featuredSlug: String(formData.get("featuredSlug") ?? "").trim(),
|
||||
sideFeaturedSlugs: toList(formData.get("sideFeaturedSlugs")).slice(0, 2),
|
||||
latestCount: Math.max(1, Number(formData.get("latestCount") ?? 4)),
|
||||
showAd: formData.get("showAd") === "on"
|
||||
};
|
||||
cms.settings.ad = {
|
||||
enabled: formData.get("adEnabled") === "on",
|
||||
label: String(formData.get("adLabel") ?? "آگهی").trim(),
|
||||
href: String(formData.get("adHref") ?? "/advertise/").trim(),
|
||||
text: String(formData.get("adText") ?? "").trim()
|
||||
};
|
||||
}
|
||||
await writeCms(cms);
|
||||
return context.redirect(`/admin/?saved=1&tab=${encodeURIComponent(tab)}`, 302);
|
||||
};
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
POST
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
30
dist/server/pages/api/admin/upload.astro.mjs
vendored
Normal file
30
dist/server/pages/api/admin/upload.astro.mjs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import { r as requireAdmin } from '../../../chunks/adminAuth_CY4OwU1a.mjs';
|
||||
import { s as storeImageBuffer } from '../../../chunks/images_DSuHPXn1.mjs';
|
||||
export { renderers } from '../../../renderers.mjs';
|
||||
|
||||
const POST = async (context) => {
|
||||
const unauthorized = requireAdmin(context);
|
||||
if (unauthorized) {
|
||||
return unauthorized;
|
||||
}
|
||||
const formData = await context.request.formData();
|
||||
const file = formData.get("image");
|
||||
if (!(file instanceof File) || file.size === 0) {
|
||||
return context.json({ error: "فایل تصویری ارسال نشده است." }, 400);
|
||||
}
|
||||
try {
|
||||
const storedImage = await storeImageBuffer(Buffer.from(await file.arrayBuffer()));
|
||||
return context.json(storedImage, 200);
|
||||
} catch {
|
||||
return context.json({ error: "پردازش تصویر ناموفق بود." }, 500);
|
||||
}
|
||||
};
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
POST
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
36
dist/server/pages/api/agents/tass.astro.mjs
vendored
Normal file
36
dist/server/pages/api/agents/tass.astro.mjs
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { r as requireApiToken } from '../../../chunks/apiAuth_DcNSM7D5.mjs';
|
||||
import { i as isAdminAuthenticated } from '../../../chunks/adminAuth_CY4OwU1a.mjs';
|
||||
import { r as runTassAgent } from '../../../chunks/tassAgent_jxZgSz7r.mjs';
|
||||
export { renderers } from '../../../renderers.mjs';
|
||||
|
||||
const POST = async (context) => {
|
||||
if (!isAdminAuthenticated(context)) {
|
||||
const unauthorized = requireApiToken(context);
|
||||
if (unauthorized) {
|
||||
return unauthorized;
|
||||
}
|
||||
}
|
||||
try {
|
||||
const contentType = context.request.headers.get("content-type") ?? "";
|
||||
const payload = contentType.includes("application/json") ? await context.request.json() : {};
|
||||
const limit = Math.min(Math.max(Number(payload.limit ?? 3), 1), 10);
|
||||
const result = await runTassAgent(limit);
|
||||
return new Response(JSON.stringify({ ok: true, ...result }), {
|
||||
headers: { "content-type": "application/json; charset=utf-8" }
|
||||
});
|
||||
} catch (error) {
|
||||
return new Response(JSON.stringify({ ok: false, error: error instanceof Error ? error.message : "Agent failed" }), {
|
||||
status: 500,
|
||||
headers: { "content-type": "application/json; charset=utf-8" }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
POST
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
50
dist/server/pages/api/posts/publish.astro.mjs
vendored
Normal file
50
dist/server/pages/api/posts/publish.astro.mjs
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
import { r as requireApiToken } from '../../../chunks/apiAuth_DcNSM7D5.mjs';
|
||||
import { p as publishPost } from '../../../chunks/publisher_Dj_UvF8J.mjs';
|
||||
import { d as downloadAndStoreImage } from '../../../chunks/images_DSuHPXn1.mjs';
|
||||
export { renderers } from '../../../renderers.mjs';
|
||||
|
||||
const POST = async (context) => {
|
||||
const unauthorized = requireApiToken(context);
|
||||
if (unauthorized) {
|
||||
return unauthorized;
|
||||
}
|
||||
try {
|
||||
const payload = await context.request.json();
|
||||
let image = payload.image;
|
||||
let thumbnail = payload.thumbnail;
|
||||
if (payload.imageUrl && !image) {
|
||||
const storedImage = await downloadAndStoreImage(String(payload.imageUrl));
|
||||
image = storedImage?.image;
|
||||
thumbnail = storedImage?.thumbnail;
|
||||
}
|
||||
const post = await publishPost({
|
||||
title: String(payload.title ?? ""),
|
||||
slug: payload.slug ? String(payload.slug) : void 0,
|
||||
category: payload.category ? String(payload.category) : void 0,
|
||||
time: payload.time ? String(payload.time) : void 0,
|
||||
readTime: payload.readTime ? String(payload.readTime) : void 0,
|
||||
excerpt: payload.excerpt ? String(payload.excerpt) : void 0,
|
||||
body: Array.isArray(payload.body) ? payload.body.map(String) : String(payload.body ?? ""),
|
||||
status: payload.status === "approved" ? "approved" : "pending",
|
||||
image,
|
||||
thumbnail
|
||||
});
|
||||
return new Response(JSON.stringify({ ok: true, post }), {
|
||||
headers: { "content-type": "application/json; charset=utf-8" }
|
||||
});
|
||||
} catch (error) {
|
||||
return new Response(JSON.stringify({ ok: false, error: error instanceof Error ? error.message : "Invalid request" }), {
|
||||
status: 400,
|
||||
headers: { "content-type": "application/json; charset=utf-8" }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
POST
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
33
dist/server/pages/categories/_category_.astro.mjs
vendored
Normal file
33
dist/server/pages/categories/_category_.astro.mjs
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { c as createComponent, d as renderComponent, r as renderTemplate, b as createAstro, m as maybeRenderHead } from '../../chunks/astro/server_DrnzQWw3.mjs';
|
||||
import 'kleur/colors';
|
||||
import { $ as $$BaseLayout } from '../../chunks/BaseLayout_Bc2tHXHa.mjs';
|
||||
import { $ as $$PostCard } from '../../chunks/PostCard_D8td2Gog.mjs';
|
||||
import { r as readCms, a as getPostsByCategory, b as getApprovedPosts } from '../../chunks/cms_CRTVymfB.mjs';
|
||||
export { renderers } from '../../renderers.mjs';
|
||||
|
||||
const $$Astro = createAstro();
|
||||
const $$category = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$category;
|
||||
const cms = await readCms();
|
||||
const category = decodeURIComponent(Astro2.params.category ?? "");
|
||||
if (!cms.categories.includes(category)) {
|
||||
return Astro2.redirect("/posts/");
|
||||
}
|
||||
const categoryPosts = getPostsByCategory(getApprovedPosts(cms), category);
|
||||
return renderTemplate`${renderComponent($$result, "BaseLayout", $$BaseLayout, { "title": `${category} | \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632`, "description": `\u0622\u062E\u0631\u06CC\u0646 \u0627\u062E\u0628\u0627\u0631 \u0648 \u062A\u062D\u0644\u06CC\u0644\u200C\u0647\u0627\u06CC ${category} \u062F\u0631 \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632` }, { "default": async ($$result2) => renderTemplate` ${maybeRenderHead()}<main class="max-w-7xl mx-auto px-4 lg:px-8 py-8"> <div class="mb-6"> <a href="/posts/" class="text-brand text-sm font-bold">آرشیو اخبار</a> <h1 class="text-2xl font-black mt-1">اخبار ${category}</h1> <p class="text-gray-500 text-sm mt-2">مجموعه خبرها و تحلیلهای منتشر شده در بخش ${category}</p> </div> <div class="grid grid-cols-1 lg:grid-cols-2 gap-4"> ${categoryPosts.map((post) => renderTemplate`${renderComponent($$result2, "PostCard", $$PostCard, { "post": post })}`)} </div> </main> ` })}`;
|
||||
}, "/Users/drfelfel/ruseemrooz/src/pages/categories/[category].astro", void 0);
|
||||
|
||||
const $$file = "/Users/drfelfel/ruseemrooz/src/pages/categories/[category].astro";
|
||||
const $$url = "/categories/[category]";
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$category,
|
||||
file: $$file,
|
||||
url: $$url
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
43
dist/server/pages/index.astro.mjs
vendored
Normal file
43
dist/server/pages/index.astro.mjs
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
import { c as createComponent, d as renderComponent, r as renderTemplate, b as createAstro, m as maybeRenderHead, a as addAttribute } from '../chunks/astro/server_DrnzQWw3.mjs';
|
||||
import 'kleur/colors';
|
||||
import { $ as $$BaseLayout } from '../chunks/BaseLayout_Bc2tHXHa.mjs';
|
||||
import { $ as $$Pagination } from '../chunks/Pagination_BeoGb-H9.mjs';
|
||||
import { $ as $$PostCard } from '../chunks/PostCard_D8td2Gog.mjs';
|
||||
import { r as readCms, b as getApprovedPosts, c as getPostBySlug, d as getPaginatedPosts, f as formatPostRelativeTime, e as getCategoryPath } from '../chunks/cms_CRTVymfB.mjs';
|
||||
export { renderers } from '../renderers.mjs';
|
||||
|
||||
const $$Astro = createAstro();
|
||||
const $$Index = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$Index;
|
||||
const cms = await readCms();
|
||||
const posts = getApprovedPosts(cms);
|
||||
const { homeLayout, hotTopics, ad } = cms.settings;
|
||||
const featuredPost = getPostBySlug(posts, homeLayout.featuredSlug) ?? posts[0];
|
||||
const pageParam = Number(Astro2.url.searchParams.get("page") ?? "1");
|
||||
const requestedPage = Number.isFinite(pageParam) ? pageParam : 1;
|
||||
const sideFeaturedPosts = [
|
||||
...posts.filter((post) => post.sidebar),
|
||||
...homeLayout.sideFeaturedSlugs.map((slug) => getPostBySlug(posts, slug)).filter(Boolean)
|
||||
].filter((post, index, list) => list.findIndex((item) => item.slug === post.slug) === index).slice(0, 2);
|
||||
const latestSource = posts.filter((post) => post.slug !== featuredPost?.slug);
|
||||
const { currentPage, totalPages, posts: latestPosts } = getPaginatedPosts(requestedPage, homeLayout.latestCount, latestSource);
|
||||
const mostViewedPosts = posts.slice(1, 6);
|
||||
return renderTemplate`${renderComponent($$result, "BaseLayout", $$BaseLayout, {}, { "default": async ($$result2) => renderTemplate` ${maybeRenderHead()}<main class="max-w-7xl mx-auto px-4 lg:px-8 py-6"> ${featuredPost && renderTemplate`<section class="grid grid-cols-1 lg:grid-cols-3 gap-4 items-start mb-5 lg:mb-6"> <a${addAttribute(`/posts/${featuredPost.slug}/`, "href")} class="lg:col-span-2 bg-white rounded-2xl overflow-hidden shadow-sm group"> <div class="img-placeholder h-64 sm:h-80 lg:h-[430px] w-full relative overflow-hidden"> ${featuredPost.image ? renderTemplate`<img${addAttribute(featuredPost.image, "src")}${addAttribute(featuredPost.title, "alt")} class="absolute inset-0 w-full h-full object-cover">` : renderTemplate`<div class="absolute inset-0 flex items-center justify-center text-gray-400"> <span class="material-icons text-5xl opacity-30">image</span> </div>`} <div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent"></div> <div class="absolute bottom-0 p-4 sm:p-6"> <span class="bg-brand text-white text-xs px-2.5 py-1 rounded-full font-bold">ویژه</span> <h1 class="text-white font-bold text-xl sm:text-2xl mt-2 leading-snug line-clamp-2 group-hover:text-red-200 transition-colors"> ${featuredPost.title} </h1> <p class="text-white/75 text-sm mt-1 hidden sm:block line-clamp-2">${featuredPost.excerpt}</p> <div class="flex items-center gap-3 mt-3 text-white/60 text-xs"> <span class="material-icons text-sm">schedule</span> <span>${formatPostRelativeTime(featuredPost)}</span> <span>·</span> <span>${featuredPost.category}</span> <span>·</span> <span>${featuredPost.readTime} مطالعه</span> </div> </div> </div> </a> <div class="flex flex-col gap-4 lg:col-span-1"> <div class="grid grid-cols-2 lg:grid-cols-1 gap-4"> ${sideFeaturedPosts.map((post) => renderTemplate`<a${addAttribute(`/posts/${post.slug}/`, "href")} class="bg-white rounded-2xl overflow-hidden shadow-sm group"> <div class="img-placeholder h-28 lg:h-36 w-full relative overflow-hidden"> ${post.thumbnail || post.image ? renderTemplate`<img${addAttribute(post.thumbnail || post.image, "src")}${addAttribute(post.title, "alt")} class="w-full h-full object-cover" loading="lazy">` : renderTemplate`<div class="absolute inset-0 flex items-center justify-center text-gray-400"> <span class="material-icons text-3xl opacity-30">image</span> </div>`} </div> <div class="p-3"> <span class="text-brand text-xs font-bold">${post.category}</span> <h2 class="font-semibold text-sm mt-1 leading-snug line-clamp-2 group-hover:text-brand transition-colors">${post.title}</h2> <p class="text-xs text-gray-400 mt-1">${formatPostRelativeTime(post)}</p> </div> </a>`)} </div> </div> </section>`} <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> <div class="lg:col-span-2"> <div class="flex items-center justify-between mb-4"> <h2 class="font-bold text-lg">آخرین اخبار</h2> <a href="/posts/" class="text-brand text-sm hover:underline">همه اخبار</a> </div> <div class="space-y-4"> ${latestPosts.map((post) => renderTemplate`${renderComponent($$result2, "PostCard", $$PostCard, { "post": post })}`)} </div> ${renderComponent($$result2, "Pagination", $$Pagination, { "currentPage": currentPage, "totalPages": totalPages, "basePath": "/" })} </div> <aside class="lg:col-span-1 space-y-6"> <div class="bg-white rounded-2xl p-4 shadow-sm"> <h3 class="font-bold text-base mb-4 flex items-center gap-2"> <span class="material-icons text-brand text-xl">trending_up</span>
|
||||
پربازدیدترین
|
||||
</h3> <ol class="space-y-3"> ${mostViewedPosts.map((item, index) => renderTemplate`<li class="flex items-start gap-3 group"> <span class="text-2xl font-black text-gray-100 leading-none flex-shrink-0 w-6 text-center">${index + 1}</span> <div> <a${addAttribute(`/posts/${item.slug}/`, "href")} class="text-sm font-medium leading-snug group-hover:text-brand transition-colors line-clamp-2">${item.title}</a> <a${addAttribute(getCategoryPath(item.category), "href")} class="text-xs text-brand">${item.category}</a> </div> </li>`)} </ol> </div> ${homeLayout.showAd && ad.enabled && renderTemplate`<a${addAttribute(ad.href, "href")} class="img-placeholder rounded-2xl h-48 flex items-center justify-center text-gray-400"> <div class="text-center"> <span class="material-icons text-4xl opacity-30">campaign</span> <p class="text-xs mt-1 opacity-40">${ad.label}</p> <p class="text-sm mt-2 text-gray-500">${ad.text}</p> </div> </a>`} <div class="bg-white rounded-2xl p-4 shadow-sm"> <h3 class="font-bold text-base mb-3">موضوعات داغ</h3> <div class="flex flex-wrap gap-2"> ${hotTopics.map((tag) => renderTemplate`<a${addAttribute(`/search/?q=${encodeURIComponent(tag)}`, "href")} class="bg-gray-100 hover:bg-red-50 hover:text-brand text-gray-600 text-xs px-3 py-1.5 rounded-full transition-colors">#${tag}</a>`)} </div> </div> </aside> </div> </main> ` })}`;
|
||||
}, "/Users/drfelfel/ruseemrooz/src/pages/index.astro", void 0);
|
||||
|
||||
const $$file = "/Users/drfelfel/ruseemrooz/src/pages/index.astro";
|
||||
const $$url = "";
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$Index,
|
||||
file: $$file,
|
||||
url: $$url
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
32
dist/server/pages/posts.astro.mjs
vendored
Normal file
32
dist/server/pages/posts.astro.mjs
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import { c as createComponent, d as renderComponent, r as renderTemplate, b as createAstro, m as maybeRenderHead } from '../chunks/astro/server_DrnzQWw3.mjs';
|
||||
import 'kleur/colors';
|
||||
import { $ as $$PostCard } from '../chunks/PostCard_D8td2Gog.mjs';
|
||||
import { $ as $$Pagination } from '../chunks/Pagination_BeoGb-H9.mjs';
|
||||
import { $ as $$BaseLayout } from '../chunks/BaseLayout_Bc2tHXHa.mjs';
|
||||
import { r as readCms, d as getPaginatedPosts, b as getApprovedPosts } from '../chunks/cms_CRTVymfB.mjs';
|
||||
export { renderers } from '../renderers.mjs';
|
||||
|
||||
const $$Astro = createAstro();
|
||||
const $$Index = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$Index;
|
||||
const cms = await readCms();
|
||||
const pageParam = Number(Astro2.url.searchParams.get("page") ?? "1");
|
||||
const requestedPage = Number.isFinite(pageParam) ? pageParam : 1;
|
||||
const { currentPage, totalPages, posts } = getPaginatedPosts(requestedPage, 4, getApprovedPosts(cms));
|
||||
return renderTemplate`${renderComponent($$result, "BaseLayout", $$BaseLayout, { "title": "\u0647\u0645\u0647 \u0627\u062E\u0628\u0627\u0631 | \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632" }, { "default": async ($$result2) => renderTemplate` ${maybeRenderHead()}<main class="max-w-7xl mx-auto px-4 lg:px-8 py-8"> <div class="mb-6"> <span class="text-brand text-sm font-bold">آرشیو</span> <h1 class="text-2xl font-black mt-1">همه اخبار</h1> <p class="text-gray-500 text-sm mt-2">لیست کامل نوشتهها و خبرهای منتشر شده در روس امروز</p> </div> <div class="grid grid-cols-1 lg:grid-cols-2 gap-4"> ${posts.map((post) => renderTemplate`${renderComponent($$result2, "PostCard", $$PostCard, { "post": post })}`)} </div> ${renderComponent($$result2, "Pagination", $$Pagination, { "currentPage": currentPage, "totalPages": totalPages })} </main> ` })}`;
|
||||
}, "/Users/drfelfel/ruseemrooz/src/pages/posts/index.astro", void 0);
|
||||
|
||||
const $$file = "/Users/drfelfel/ruseemrooz/src/pages/posts/index.astro";
|
||||
const $$url = "/posts";
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$Index,
|
||||
file: $$file,
|
||||
url: $$url
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
50
dist/server/pages/posts/_slug_.astro.mjs
vendored
Normal file
50
dist/server/pages/posts/_slug_.astro.mjs
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
import { c as createComponent, d as renderComponent, r as renderTemplate, b as createAstro, m as maybeRenderHead, a as addAttribute } from '../../chunks/astro/server_DrnzQWw3.mjs';
|
||||
import 'kleur/colors';
|
||||
import { $ as $$BaseLayout } from '../../chunks/BaseLayout_Bc2tHXHa.mjs';
|
||||
import { $ as $$PostCard } from '../../chunks/PostCard_D8td2Gog.mjs';
|
||||
import { r as readCms, b as getApprovedPosts, c as getPostBySlug, h as formatPostShamsiDate, e as getCategoryPath, p as parseImageBlock } from '../../chunks/cms_CRTVymfB.mjs';
|
||||
export { renderers } from '../../renderers.mjs';
|
||||
|
||||
const $$Astro = createAstro();
|
||||
const $$slug = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$slug;
|
||||
const cms = await readCms();
|
||||
const posts = getApprovedPosts(cms);
|
||||
const post = getPostBySlug(posts, Astro2.params.slug ?? "");
|
||||
if (!post) {
|
||||
return Astro2.redirect("/posts/");
|
||||
}
|
||||
const dateLabel = formatPostShamsiDate(post);
|
||||
const relatedPosts = posts.filter((item) => item.slug !== post.slug).slice(0, 3);
|
||||
return renderTemplate`${renderComponent($$result, "BaseLayout", $$BaseLayout, { "title": `${post.title} | \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632`, "description": post.excerpt }, { "default": async ($$result2) => renderTemplate` ${maybeRenderHead()}<main class="max-w-7xl mx-auto px-4 lg:px-8 py-8"> <article class="bg-white rounded-2xl shadow-sm overflow-hidden"> <div class="img-placeholder h-64 sm:h-80 lg:h-96 relative overflow-hidden"> ${post.image ? renderTemplate`<img${addAttribute(post.image, "src")}${addAttribute(post.title, "alt")} class="w-full h-full object-cover">` : renderTemplate`<div class="absolute inset-0 flex items-center justify-center text-gray-400"> <span class="material-icons text-6xl opacity-30">image</span> </div>`} </div> <div class="max-w-3xl mx-auto p-5 sm:p-8"> <a${addAttribute(getCategoryPath(post.category), "href")} class="text-brand text-sm font-bold">${post.category}</a> <h1 class="text-2xl sm:text-4xl font-black leading-snug mt-3">${post.title}</h1> <p class="text-gray-500 leading-relaxed mt-4">${post.excerpt}</p> <div class="flex flex-wrap items-center gap-3 text-xs text-gray-400 border-y border-gray-100 py-4 my-6"> <span class="material-icons text-base">schedule</span> <span>${dateLabel}</span> <span>·</span> <span>${post.readTime} مطالعه</span> <span>·</span> <span>تحریریه روس امروز</span> </div> <div class="space-y-5 text-gray-700 leading-8 text-base"> ${post.body.map((paragraph) => {
|
||||
const imageBlock = parseImageBlock(paragraph);
|
||||
if (imageBlock) {
|
||||
return renderTemplate`<figure class="my-7"> <img${addAttribute(imageBlock.src, "src")}${addAttribute(imageBlock.caption || post.title, "alt")} class="w-full rounded-2xl object-cover" loading="lazy"> ${imageBlock.caption && renderTemplate`<figcaption class="text-xs text-gray-400 mt-2 text-center">${imageBlock.caption}</figcaption>`} </figure>`;
|
||||
}
|
||||
if (paragraph === "---") {
|
||||
return renderTemplate`<hr class="border-gray-100 my-7">`;
|
||||
}
|
||||
if (paragraph.startsWith("## ")) {
|
||||
return renderTemplate`<h2 class="text-xl font-black text-gray-900 mt-8">${paragraph.replace(/^##\s+/, "")}</h2>`;
|
||||
}
|
||||
if (paragraph.startsWith("> ")) {
|
||||
return renderTemplate`<blockquote class="border-r-4 border-brand bg-red-50/60 rounded-l-xl px-4 py-3 text-gray-700">${paragraph.replace(/^>\s+/, "")}</blockquote>`;
|
||||
}
|
||||
return renderTemplate`<p>${paragraph}</p>`;
|
||||
})} </div> </div> </article> <section class="mt-10"> <div class="flex items-center justify-between mb-4"> <h2 class="font-bold text-lg">نوشتههای مرتبط</h2> <a href="/posts/" class="text-brand text-sm hover:underline">همه اخبار</a> </div> <div class="grid grid-cols-1 lg:grid-cols-3 gap-4"> ${relatedPosts.map((relatedPost) => renderTemplate`${renderComponent($$result2, "PostCard", $$PostCard, { "post": relatedPost })}`)} </div> </section> </main> ` })}`;
|
||||
}, "/Users/drfelfel/ruseemrooz/src/pages/posts/[slug].astro", void 0);
|
||||
|
||||
const $$file = "/Users/drfelfel/ruseemrooz/src/pages/posts/[slug].astro";
|
||||
const $$url = "/posts/[slug]";
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$slug,
|
||||
file: $$file,
|
||||
url: $$url
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
36
dist/server/pages/search.astro.mjs
vendored
Normal file
36
dist/server/pages/search.astro.mjs
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { c as createComponent, d as renderComponent, r as renderTemplate, b as createAstro, m as maybeRenderHead, a as addAttribute } from '../chunks/astro/server_DrnzQWw3.mjs';
|
||||
import 'kleur/colors';
|
||||
import { $ as $$BaseLayout } from '../chunks/BaseLayout_Bc2tHXHa.mjs';
|
||||
import { $ as $$PostCard } from '../chunks/PostCard_D8td2Gog.mjs';
|
||||
import { r as readCms, i as searchPosts, b as getApprovedPosts } from '../chunks/cms_CRTVymfB.mjs';
|
||||
export { renderers } from '../renderers.mjs';
|
||||
|
||||
const $$Astro = createAstro();
|
||||
const $$Index = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$Index;
|
||||
const cms = await readCms();
|
||||
const query = Astro2.url.searchParams.get("q")?.trim() ?? "";
|
||||
const results = searchPosts(getApprovedPosts(cms), query);
|
||||
const title = query ? `\u062C\u0633\u062A\u062C\u0648: ${query} | \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632` : "\u062C\u0633\u062A\u062C\u0648 | \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632";
|
||||
return renderTemplate`${renderComponent($$result, "BaseLayout", $$BaseLayout, { "title": title, "description": "\u062C\u0633\u062A\u062C\u0648 \u062F\u0631 \u062E\u0628\u0631\u0647\u0627 \u0648 \u062A\u062D\u0644\u06CC\u0644\u200C\u0647\u0627\u06CC \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632" }, { "default": async ($$result2) => renderTemplate` ${maybeRenderHead()}<main class="max-w-7xl mx-auto px-4 lg:px-8 py-8"> <div class="bg-white rounded-2xl shadow-sm p-5 sm:p-6 mb-6"> <span class="text-brand text-sm font-bold">جستجو</span> <h1 class="text-2xl font-black mt-1">جستجو در روس امروز</h1> <form action="/search/" method="get" class="mt-5 flex gap-2"> <input type="search" name="q"${addAttribute(query, "value")} placeholder="عبارت مورد نظر را وارد کنید..." class="flex-1 bg-gray-100 text-gray-700 text-sm rounded-xl px-4 py-3 outline-none focus:ring-1 focus:ring-brand focus:bg-white"> <button type="submit" class="bg-brand text-white text-sm font-bold px-5 py-3 rounded-xl hover:bg-red-700 transition-colors">
|
||||
جستجو
|
||||
</button> </form> </div> ${query ? renderTemplate`<section> <div class="flex items-center justify-between mb-4"> <h2 class="font-bold text-lg">نتایج برای «${query}»</h2> <span class="text-sm text-gray-400">${results.length} نتیجه</span> </div> ${results.length > 0 ? renderTemplate`<div class="grid grid-cols-1 lg:grid-cols-2 gap-4"> ${results.map((post) => renderTemplate`${renderComponent($$result2, "PostCard", $$PostCard, { "post": post })}`)} </div>` : renderTemplate`<div class="bg-white rounded-2xl shadow-sm p-8 text-center text-gray-500">
|
||||
نتیجهای برای این عبارت پیدا نشد.
|
||||
</div>`} </section>` : renderTemplate`<section class="bg-white rounded-2xl shadow-sm p-5"> <h2 class="font-bold text-base mb-3">موضوعات پیشنهادی</h2> <div class="flex flex-wrap gap-2"> ${cms.settings.hotTopics.map((tag) => renderTemplate`<a${addAttribute(`/search/?q=${encodeURIComponent(tag)}`, "href")} class="bg-gray-100 hover:bg-red-50 hover:text-brand text-gray-600 text-xs px-3 py-1.5 rounded-full transition-colors">
|
||||
#${tag} </a>`)} </div> </section>`} </main> ` })}`;
|
||||
}, "/Users/drfelfel/ruseemrooz/src/pages/search/index.astro", void 0);
|
||||
|
||||
const $$file = "/Users/drfelfel/ruseemrooz/src/pages/search/index.astro";
|
||||
const $$url = "/search";
|
||||
|
||||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: $$Index,
|
||||
file: $$file,
|
||||
url: $$url
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
const page = () => _page;
|
||||
|
||||
export { page };
|
||||
Reference in New Issue
Block a user