Skip to content

Commit

Permalink
Add files' option to publish or save as draft
Browse files Browse the repository at this point in the history
Allows publishing pages and posts right away or save to publish later
  • Loading branch information
LebCit committed Dec 6, 2023
1 parent c463f5d commit 0270ccf
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 19 deletions.
12 changes: 8 additions & 4 deletions functions/blog-doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ class Blog_Doc {
const contents = new TextDecoder().decode(buffer)

const fileData = parseFrontMatter(contents) // Parse the front-matter of the file
// Since v5.3.0 to allow publishing now or later
Object.hasOwn(fileData.frontmatter, "published")
? fileData.frontmatter.published
: (fileData.frontmatter.published = "true")
const filePath = `${file}` // Get the file path
const fileDir = filePath.split("/")[0] // Get the file directory
const obj = { 0: fileName, 1: fileData } // Create the object that holds the file data
Expand Down Expand Up @@ -129,7 +133,7 @@ class Blog_Doc {

// Method to count the occurrence of each tag from the posts front-matter.
async postsByTagCount() {
const posts = await getPosts()
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")

// Create an array of the tags from all the posts and sort them alphabetically
const tagsArray = posts.flatMap((post) => post[1].frontmatter.tags).sort()
Expand All @@ -142,7 +146,7 @@ class Blog_Doc {

// Method to return the posts of a particular tag.
async postsByTagList(tag) {
const posts = await getPosts()
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")
// Filter the posts to retrieve an array of post(s) including the requested tag
// Check if the post have tags, otherwise define them as an empty array
const postsByTagArray = posts.filter((post) =>
Expand All @@ -154,7 +158,7 @@ class Blog_Doc {

// Method to return the previous and next posts of a particular post.
async prevNext(filename) {
const posts = await getPosts()
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")
// Get the index of each post in the posts array by it's filename
const actualPostIndex = posts.findIndex((post) => post[0] === filename)
// Get the previous post index while the actual post index is smaller than the posts array length - 1 (posts array length - 1 is the index of the last post)
Expand All @@ -180,7 +184,7 @@ class Blog_Doc {

// Method to return the related posts of a particular post.
async relatedPosts(filename) {
const posts = await getPosts()
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")
// Get the post in the posts array by it's filename
const actualPost = posts.find((post) => post[0] === filename)
// Get the related posts from the front-matter of the actual post
Expand Down
4 changes: 2 additions & 2 deletions functions/sitemap.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getPages, getPosts } from "../functions/blog-doc.js"
import { getSettings } from "../functions/settings.js"

const pages = await getPages()
const posts = await getPosts()
const pages = (await getPages()).filter((page) => page[1].frontmatter.published == "true")
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")

export async function sitemap() {
const settings = await getSettings()
Expand Down
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ import { adminRoutes, adminUpdateDelete } from "./routes/admin/adminRoute.js"
import { adminCreateRoute } from "./routes/admin/adminCreateRoute.js"
import { adminGalleryRoute } from "./routes/admin/adminGalleryRoute.js"
import { adminConfigRoute } from "./routes/admin/adminConfigRoute.js"
import { adminPreviewRoute } from "./routes/admin/adminPreviewRoute.js"
adminRoutes(app)
adminCreateRoute(app)
adminUpdateDelete(app)
adminGalleryRoute(app)
adminConfigRoute(app)
adminPreviewRoute(app)

// Routes
import { markdownRoute } from "./routes/markdownRoute.js"
Expand Down
13 changes: 11 additions & 2 deletions routes/admin/adminCreateRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@ export const adminCreateRoute = (app) => {
postDescription,
postImage,
postTags,
published,
} = fields

const pageContents = `---
title : ${pageTitle}
description: ${pageDescription}
featuredImage: ${pageImage}
published: ${published}
---
${fileContents}`

Expand All @@ -86,12 +88,15 @@ date: ${postDate.split("-").join("/")}
description: ${postDescription}
featuredImage: ${postImage}
tags: [${postTags}]
published: ${published}
---
${fileContents}`

const utf8Encoder = new TextEncoder()

if (fileType === "page") {
const path = published == "true" ? "/pages" : "/admin-preview-page"

const createdPageName = pageTitle
.toLowerCase()
.replace(/[^a-zA-Z0-9-_ ]/g, "") // Remove special characters except hyphen and underscore
Expand All @@ -103,9 +108,12 @@ ${fileContents}`

const utf8Array = utf8Encoder.encode(pageContents)
await drive.put(`pages/${createdPageName}.md`, { data: utf8Array })
res.writeHead(302, { Location: `/pages/${createdPageName}` })
res.writeHead(302, { Location: `${path}/${createdPageName}` })
res.end()
return
} else {
const path = published == "true" ? "/posts" : "/admin-preview-post"

const createdPostName = postTitle
.toLowerCase()
.replace(/[^a-zA-Z0-9-_ ]/g, "") // Remove special characters except hyphen and underscore
Expand All @@ -117,8 +125,9 @@ ${fileContents}`

const utf8Array = utf8Encoder.encode(postContents)
await drive.put(`posts/${createdPostName}.md`, { data: utf8Array })
res.writeHead(302, { Location: `/posts/${createdPostName}` })
res.writeHead(302, { Location: `${path}/${createdPostName}` })
res.end()
return
}
})
})
Expand Down
84 changes: 84 additions & 0 deletions routes/admin/adminPreviewRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { getPages, getPosts, prevNext } from "../../functions/blog-doc.js"
import { initializeApp } from "../../functions/initialize.js"
import { idsInHeadings } from "../../functions/helpers.js"
import { getSettings } from "../../functions/settings.js"
import { marked } from "marked"

const { eta } = initializeApp()

// Markdown Route
export function adminPreviewRoute(app) {
/**
* Due to Velocy architecture, a route without a defined start point cannot be reached.
* This is why two routes are created, one for the pages and the other for posts.
* In short, the following route "/:folder/:filename" doesn't work in Velocy.
*/
app.get("/admin-preview-page/:filename", async (req, res) => {
const settings = await getSettings()

const pages = await getPages()
const unpublishedPages = pages.filter((page) => page[1].frontmatter.published == "false")
const currentFile = unpublishedPages.find((file) => file.path === `pages/${req.params.filename}.md`)

if (currentFile) {
const fileData = currentFile[1].frontmatter
fileData.favicon = settings.favicon
const fileContent = marked.parse(currentFile[1].content)
const response = eta.render(`themes/${settings.currentTheme}/layouts/base.html`, {
// Passing Route data
mdRoute: true,
// Passing Markdown file data
data: fileData,
content: settings.addIdsToHeadings ? idsInHeadings(fileContent) : fileContent,
// Passing data to edit the file
editable: true,
filename: req.params.filename,
// Passing needed settings for the template
siteTitle: settings.siteTitle,
menuLinks: settings.menuLinks,
footerCopyright: settings.footerCopyright,
})
res.writeHead(200, { "Content-Type": "text/html" })
res.end(response)
} else {
// Proceed to the 404 route if no file is found
res.writeHead(302, { Location: "/404" })
res.end()
}
})

app.get("/admin-preview-post/:filename", async (req, res) => {
const settings = await getSettings()

const posts = await getPosts()
const unpublishedPosts = posts.filter((post) => post[1].frontmatter.published == "false")
const currentFile = unpublishedPosts.find((file) => file.path === `posts/${req.params.filename}.md`)

if (currentFile) {
const fileData = currentFile[1].frontmatter
fileData.favicon = settings.favicon
const fileContent = marked.parse(currentFile[1].content)
const response = eta.render(`themes/${settings.currentTheme}/layouts/base.html`, {
// Passing Route data
mdRoute: true,
// Passing Markdown file data
data: fileData,
content: settings.addIdsToHeadings ? idsInHeadings(fileContent) : fileContent,
prevNext: currentFile.dir === "posts" ? await prevNext(`${req.params.filename}.md`) : null,
// Passing data to edit the file
editable: true,
filename: req.params.filename,
// Passing needed settings for the template
siteTitle: settings.siteTitle,
menuLinks: settings.menuLinks,
footerCopyright: settings.footerCopyright,
})
res.writeHead(200, { "Content-Type": "text/html" })
res.end(response)
} else {
// Proceed to the 404 route if no file is found
res.writeHead(302, { Location: "/404" })
res.end()
}
})
}
11 changes: 9 additions & 2 deletions routes/admin/adminRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ const adminUpdateDelete = (app) => {
postImage,
postTags,
fileContents,
published,
} = fields

const updatedFile = filePath.split("/").pop().replace(".md", "")
Expand All @@ -142,14 +143,17 @@ const adminUpdateDelete = (app) => {
title: ${pageTitle}
description: ${pageDescription}
featuredImage: ${pageImage}
published: ${published}
---
${fileContents}`

const utf8Encoder = new TextEncoder()
const utf8Array = utf8Encoder.encode(pageContents)
const path = published == "true" ? "/pages" : "/admin-preview-page"

await drive.put(`${filePath}`, { data: utf8Array })
res.writeHead(302, { Location: `/pages/${updatedFile}` })

res.writeHead(302, { Location: `${path}/${updatedFile}` })
res.end()
return
} else {
Expand All @@ -159,14 +163,17 @@ date: ${postDate.split("-").join("/")}
description: ${postDescription}
featuredImage: ${postImage}
tags: [${postTags}]
published: ${published}
---
${fileContents}`

const utf8Encoder = new TextEncoder()
const utf8Array = utf8Encoder.encode(postContents)
const path = published == "true" ? "/posts" : "/admin-preview-post"

await drive.put(`${filePath}`, { data: utf8Array })
res.writeHead(302, { Location: `/posts/${updatedFile}` })

res.writeHead(302, { Location: `${path}/${updatedFile}` })
res.end()
return
}
Expand Down
2 changes: 1 addition & 1 deletion routes/archiveRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function archiveRoute(app) {
app.get("/posts", async (req, res) => {
const settings = await getSettings()

const posts = await getPosts()
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")

const data = {
title: "Archive",
Expand Down
4 changes: 2 additions & 2 deletions routes/mainRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function mainRoute(app) {
app.get("/", async (req, res) => {
const settings = await getSettings()

const posts = await getPosts()
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")
const paginatedPosts = paginator(posts, 1, settings.postsPerPage) // Paginate all the posts. Set the first page to 1 and X posts per page.
const newestPosts = paginatedPosts.data // Get the first X posts.
const lastPage = paginatedPosts.total_pages - 1 // Get the last page number by removing 1 from the total number of pages.
Expand Down Expand Up @@ -47,7 +47,7 @@ export function mainRoute(app) {
app.get("/page/:actualBlogPage", async (req, res) => {
const settings = await getSettings()

const posts = await getPosts()
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")
const paginatedPosts = paginator(posts, 1, settings.postsPerPage) // Paginate all the posts. Set the first page to 1 and X posts per page.
const lastPage = paginatedPosts.total_pages - 1 // Get the last page number by removing 1 from the total number of pages.

Expand Down
8 changes: 4 additions & 4 deletions routes/markdownRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export function markdownRoute(app) {
const settings = await getSettings()

const pages = await getPages()

const currentFile = pages.find((file) => file.path === `pages/${req.params.filename}.md`)
const publishedPages = pages.filter((page) => page[1].frontmatter.published == "true")
const currentFile = publishedPages.find((file) => file.path === `pages/${req.params.filename}.md`)

if (currentFile) {
const fileData = currentFile[1].frontmatter
Expand Down Expand Up @@ -51,8 +51,8 @@ export function markdownRoute(app) {
const settings = await getSettings()

const posts = await getPosts()

const currentFile = posts.find((file) => file.path === `posts/${req.params.filename}.md`)
const publishedPosts = posts.filter((post) => post[1].frontmatter.published == "true")
const currentFile = publishedPosts.find((file) => file.path === `posts/${req.params.filename}.md`)

if (currentFile) {
const fileData = currentFile[1].frontmatter
Expand Down
2 changes: 1 addition & 1 deletion routes/rssRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function rssRoute(app) {
const settings = await getSettings()

// Get the posts array
const posts = await getPosts()
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")

const response = eta.render(`themes/${settings.currentTheme}/layouts/rss.html`, {
// Passing needed settings for the template
Expand Down
2 changes: 1 addition & 1 deletion routes/searchRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { initializeApp } from "../functions/initialize.js"
const { eta } = initializeApp()

export async function searchRoute(app) {
const posts = await getPosts()
const posts = (await getPosts()).filter((post) => post[1].frontmatter.published == "true")

// Render the search form on the search route
app.get("/search", async (req, res) => {
Expand Down
30 changes: 30 additions & 0 deletions views/admin/components/publishSelect.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<% /* Since v5.3.0 to allow publishing now or later */ %>
<div class="mb-3">
<label for="publish-select" class="form-label">
<b>Publish* - REQUIRED!</b>
</label>

<select id="publish-select" name="published" class="form-select" required>
<option value="">Please choose an option</option>
<% if (it.adminCreate) { %>
<option value="true" selected>True</option>
<option value="false">False</option>
<% } else { %>
<!-- Start adminUpdate publish select -->
<% const published = JSON.parse(it.file[1].frontmatter.published) %>
<!-- Published value to string -->
<% const publishedString = JSON.stringify(published) %>
<!-- Published contrary value to string -->
<% const publishedContraryString = JSON.stringify(!published) %>

<option value="<%= published %>" selected>
<%= publishedString.charAt(0).toUpperCase() + publishedString.slice(1) %>
</option>

<option value="<%= !published %>">
<%= publishedContraryString.charAt(0).toUpperCase() + publishedContraryString.slice(1) %>
</option>
<!-- End adminUpdate publish select -->
<% } %>
</select>
</div>
2 changes: 2 additions & 0 deletions views/admin/layouts/adminCreate.html
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@
></textarea>
</div>
</div>

<%~ include('../components/publishSelect.html', it) %>
</div>

<div class="card-footer">
Expand Down
2 changes: 2 additions & 0 deletions views/admin/layouts/adminUpdate.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@
></textarea>
</div>
</div>

<%~ include('../components/publishSelect.html', it) %>
</div>

<div class="card-footer">
Expand Down

0 comments on commit 0270ccf

Please sign in to comment.