@maxlkatze/cms
Version:
A git based Nuxt Module CMS - zero effort, zero cost
93 lines (92 loc) • 3.48 kB
JavaScript
import { ref, onMounted } from "vue";
export function useGitHubNews() {
const newsArticles = ref([]);
const isLoading = ref(false);
const error = ref(null);
const baseUrl = `https://api.github.com/repos/maxlkatze/katzen-core/contents`;
const newsPath = "content/news";
const parseFrontmatter = (content) => {
const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/;
const match = content.match(frontmatterRegex);
if (!match) {
return { frontmatter: {}, body: content };
}
const [, frontmatterStr, body] = match;
const frontmatter = {};
frontmatterStr.split("\n").forEach((line) => {
const [key, ...valueParts] = line.split(":");
if (key && valueParts.length) {
let value = valueParts.join(":").trim();
if (value.startsWith("[") && value.endsWith("]")) {
value = value.slice(1, -1);
frontmatter[key.trim()] = value.split(",").map((v) => v.trim().replace(/"/g, "").replace(/'/g, ""));
} else {
frontmatter[key.trim()] = value.replace(/"/g, "").replace(/'/g, "");
}
}
});
return { frontmatter, body: body.trim() };
};
const fetchFile = async (path) => {
try {
const response = await fetch(`${baseUrl}/${path}?ref=master`);
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || "Failed to fetch file");
}
const data = await response.json();
const content = atob(data.content);
const { frontmatter, body } = parseFrontmatter(content);
const id = typeof frontmatter.id === "string" ? frontmatter.id : data.sha.substring(0, 8);
const title = typeof frontmatter.title === "string" ? frontmatter.title : "Untitled";
const date = typeof frontmatter.date === "string" ? frontmatter.date : (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
const author = typeof frontmatter.author === "string" ? frontmatter.author : "Unknown";
const tags = Array.isArray(frontmatter.tags) ? frontmatter.tags : [];
return {
id,
title,
content: body,
date,
author,
tags
};
} catch (err) {
console.error(`Error fetching file ${path}:`, err);
return null;
}
};
const fetchNewsArticles = async () => {
isLoading.value = true;
error.value = null;
try {
const response = await fetch(`${baseUrl}/${newsPath}?ref=master`);
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || "Failed to fetch news directory");
}
const data = await response.json();
const markdownFiles = data.filter(
(file) => file.type === "file" && file.name.endsWith(".md")
);
const articlesPromises = markdownFiles.map(
(file) => fetchFile(`${newsPath}/${file.name}`)
);
const articles = await Promise.all(articlesPromises);
newsArticles.value = articles.filter((article) => article !== null).sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
} catch (err) {
console.error("Error fetching news articles:", err);
error.value = err instanceof Error ? err.message : "Unknown error";
} finally {
isLoading.value = false;
}
};
onMounted(async () => {
await fetchNewsArticles();
});
return {
newsArticles,
isLoading,
error,
refreshNews: fetchNewsArticles
};
}