mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-12-17 09:46:05 +00:00
Update route.ts
This commit is contained in:
parent
5faf3fd61c
commit
f2e93ad69e
@ -10,39 +10,42 @@ interface ChangelogEntry {
|
|||||||
title: string
|
title: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function escapeXml(text: string): string {
|
||||||
|
return text
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''')
|
||||||
|
}
|
||||||
|
|
||||||
function formatContentForRSS(content: string): string {
|
function formatContentForRSS(content: string): string {
|
||||||
return (
|
return (
|
||||||
content
|
content
|
||||||
.replace(/https:\/\/macrimi\.github\.io\/ProxMenux/g, "https://proxmenux.com")
|
.replace(/https:\/\/macrimi\.github\.io\/ProxMenux/g, "https://proxmenux.com")
|
||||||
.replace(/`([^`]+)`/g, "<code>$1</code>")
|
.replace(/`([^`]+)`/g, "<code>$1</code>")
|
||||||
.replace(/!\[([^\]]*)\]$$([^)]+)$$/g, (match, alt, url) => {
|
.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (match, alt, url) => {
|
||||||
// Convert relative URLs to absolute
|
|
||||||
let absoluteUrl = url
|
let absoluteUrl = url
|
||||||
if (url.startsWith("/")) {
|
if (url.startsWith("/")) {
|
||||||
absoluteUrl = `https://proxmenux.com${url}`
|
absoluteUrl = `https://proxmenux.com${url}`
|
||||||
} else if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
} else if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||||
// Relative path, make it absolute
|
|
||||||
absoluteUrl = `https://proxmenux.com/${url}`
|
absoluteUrl = `https://proxmenux.com/${url}`
|
||||||
}
|
}
|
||||||
return `<img src="${absoluteUrl}" alt="${alt}" style="max-width: 100%; height: auto; display: block; margin: 1em 0;" />`
|
return `<div style="margin: 1.5em 0; text-align: center;">
|
||||||
|
<img src="${absoluteUrl}" alt="${alt}" style="max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);" />
|
||||||
|
</div>`
|
||||||
})
|
})
|
||||||
// Convert markdown links to HTML
|
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>')
|
||||||
.replace(/\[([^\]]+)\]$$([^)]+)$$/g, '<a href="$2">$1</a>')
|
|
||||||
// Convert ### headers to <h3> tags
|
|
||||||
.replace(/^### (.+)$/gm, "<h3>$1</h3>")
|
.replace(/^### (.+)$/gm, "<h3>$1</h3>")
|
||||||
// Convert ** bold ** to <strong> tags
|
|
||||||
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
||||||
// Convert code blocks to <pre><code> tags
|
|
||||||
.replace(/```[\s\S]*?```/g, (match) => {
|
.replace(/```[\s\S]*?```/g, (match) => {
|
||||||
const code = match.replace(/```/g, "").trim()
|
const code = match.replace(/```/g, "").trim()
|
||||||
return `<pre><code>${code}</code></pre>`
|
return `<pre><code>${code}</code></pre>`
|
||||||
})
|
})
|
||||||
// Convert - bullet points to <li> tags
|
|
||||||
.replace(/^- (.+)$/gm, "<li>$1</li>")
|
.replace(/^- (.+)$/gm, "<li>$1</li>")
|
||||||
// Wrap consecutive <li> tags in <ul>
|
|
||||||
.replace(/(<li>.*?<\/li>\s*)+/g, (match) => `<ul>${match}</ul>`)
|
.replace(/(<li>.*?<\/li>\s*)+/g, (match) => `<ul>${match}</ul>`)
|
||||||
.replace(/\n/g, "<br>")
|
.replace(/^---$/gm, '<hr style="border: none; border-top: 2px solid #eee; margin: 2em 0;" />')
|
||||||
// Clean up extra spaces
|
.replace(/\n/g, "<br/>")
|
||||||
.replace(/\s+/g, " ")
|
.replace(/\s+/g, " ")
|
||||||
.trim()
|
.trim()
|
||||||
)
|
)
|
||||||
@ -59,20 +62,15 @@ async function parseChangelog(): Promise<ChangelogEntry[]> {
|
|||||||
const fileContents = fs.readFileSync(changelogPath, "utf8")
|
const fileContents = fs.readFileSync(changelogPath, "utf8")
|
||||||
const entries: ChangelogEntry[] = []
|
const entries: ChangelogEntry[] = []
|
||||||
|
|
||||||
// Split by ## headers (both versions and dates)
|
|
||||||
const lines = fileContents.split("\n")
|
const lines = fileContents.split("\n")
|
||||||
let currentEntry: Partial<ChangelogEntry> | null = null
|
let currentEntry: Partial<ChangelogEntry> | null = null
|
||||||
let contentLines: string[] = []
|
let contentLines: string[] = []
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
// Check for version header: ## [1.1.1] - 2025-03-21
|
|
||||||
const versionMatch = line.match(/^##\s+\[([^\]]+)\]\s*-\s*(\d{4}-\d{2}-\d{2})/)
|
const versionMatch = line.match(/^##\s+\[([^\]]+)\]\s*-\s*(\d{4}-\d{2}-\d{2})/)
|
||||||
|
|
||||||
// Check for date-only header: ## 2025-05-13
|
|
||||||
const dateMatch = line.match(/^##\s+(\d{4}-\d{2}-\d{2})$/)
|
const dateMatch = line.match(/^##\s+(\d{4}-\d{2}-\d{2})$/)
|
||||||
|
|
||||||
if (versionMatch || dateMatch) {
|
if (versionMatch || dateMatch) {
|
||||||
// Save previous entry if exists
|
|
||||||
if (currentEntry && contentLines.length > 0) {
|
if (currentEntry && contentLines.length > 0) {
|
||||||
const rawContent = contentLines.join("\n").trim()
|
const rawContent = contentLines.join("\n").trim()
|
||||||
currentEntry.content = formatContentForRSS(rawContent)
|
currentEntry.content = formatContentForRSS(rawContent)
|
||||||
@ -81,7 +79,6 @@ async function parseChangelog(): Promise<ChangelogEntry[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start new entry
|
|
||||||
if (versionMatch) {
|
if (versionMatch) {
|
||||||
const version = versionMatch[1]
|
const version = versionMatch[1]
|
||||||
const date = versionMatch[2]
|
const date = versionMatch[2]
|
||||||
@ -103,14 +100,12 @@ async function parseChangelog(): Promise<ChangelogEntry[]> {
|
|||||||
|
|
||||||
contentLines = []
|
contentLines = []
|
||||||
} else if (currentEntry && line.trim()) {
|
} else if (currentEntry && line.trim()) {
|
||||||
// Add content lines (skip empty lines at the beginning)
|
|
||||||
if (contentLines.length > 0 || line.trim() !== "") {
|
if (contentLines.length > 0 || line.trim() !== "") {
|
||||||
contentLines.push(line)
|
contentLines.push(line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't forget the last entry
|
|
||||||
if (currentEntry && contentLines.length > 0) {
|
if (currentEntry && contentLines.length > 0) {
|
||||||
const rawContent = contentLines.join("\n").trim()
|
const rawContent = contentLines.join("\n").trim()
|
||||||
currentEntry.content = formatContentForRSS(rawContent)
|
currentEntry.content = formatContentForRSS(rawContent)
|
||||||
@ -119,7 +114,7 @@ async function parseChangelog(): Promise<ChangelogEntry[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries.slice(0, 20) // Latest 20 entries
|
return entries.slice(0, 20)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error parsing changelog:", error)
|
console.error("Error parsing changelog:", error)
|
||||||
return []
|
return []
|
||||||
@ -146,8 +141,9 @@ export async function GET() {
|
|||||||
.map(
|
.map(
|
||||||
(entry) => `
|
(entry) => `
|
||||||
<item>
|
<item>
|
||||||
<title>${entry.title}</title>
|
<title>${escapeXml(entry.title)}</title>
|
||||||
<description><![CDATA[${entry.content}]]></description>
|
<description>${escapeXml(entry.content.replace(/<[^>]*>/g, '').substring(0, 200))}...</description>
|
||||||
|
<content:encoded><![CDATA[${entry.content}]]></content:encoded>
|
||||||
<link>${entry.url}</link>
|
<link>${entry.url}</link>
|
||||||
<guid isPermaLink="true">${entry.url}</guid>
|
<guid isPermaLink="true">${entry.url}</guid>
|
||||||
<pubDate>${new Date(entry.date).toUTCString()}</pubDate>
|
<pubDate>${new Date(entry.date).toUTCString()}</pubDate>
|
||||||
@ -164,4 +160,4 @@ export async function GET() {
|
|||||||
"Cache-Control": "public, max-age=3600, s-maxage=3600",
|
"Cache-Control": "public, max-age=3600, s-maxage=3600",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user