ejs stuff
This commit is contained in:
BIN
.nfs0000000000542e1500000001
Normal file
BIN
.nfs0000000000542e1500000001
Normal file
Binary file not shown.
44
README.md
44
README.md
@@ -6,7 +6,7 @@ See the software in action: [deadvey.com](https://deadvey.com)<br/>
|
|||||||
# Confiuration
|
# Confiuration
|
||||||
Read the [configuation guide](CONFIG.md) for configuration help (in config.json)
|
Read the [configuation guide](CONFIG.md) for configuration help (in config.json)
|
||||||
|
|
||||||
# features
|
# Features
|
||||||
* post creation via the web frontend (no need to remote to your server to make a post)
|
* post creation via the web frontend (no need to remote to your server to make a post)
|
||||||
* multi user
|
* multi user
|
||||||
* powerful customisation
|
* powerful customisation
|
||||||
@@ -17,17 +17,16 @@ Read the [configuation guide](CONFIG.md) for configuration help (in config.json)
|
|||||||
* Markdown syntax in posts
|
* Markdown syntax in posts
|
||||||
* Commenting on posts
|
* Commenting on posts
|
||||||
* sign up and delete account
|
* sign up and delete account
|
||||||
|
* ejs
|
||||||
|
|
||||||
# Bugs
|
# Bugs
|
||||||
* probably scales like shit
|
* probably scales like shit
|
||||||
* probably insecure as hell
|
* probably insecure as hell
|
||||||
|
|
||||||
# planned features/todo list
|
# Planned features/todo list
|
||||||
* custom CSS _file_
|
* custom CSS _file_
|
||||||
* custom strings use format indicators
|
* custom strings use format indicators
|
||||||
* seperate functions into modules
|
* seperate functions into modules
|
||||||
* builtin crypto
|
|
||||||
* ejs
|
|
||||||
* user specific RSS feeds
|
* user specific RSS feeds
|
||||||
* atom
|
* atom
|
||||||
* federation (looks tricky)
|
* federation (looks tricky)
|
||||||
@@ -37,30 +36,15 @@ Read the [configuation guide](CONFIG.md) for configuration help (in config.json)
|
|||||||
* inline comments and docs
|
* inline comments and docs
|
||||||
* give each post a hard postID to prevent potential issues
|
* give each post a hard postID to prevent potential issues
|
||||||
* clean up code a bit
|
* clean up code a bit
|
||||||
|
* comment pages?
|
||||||
|
|
||||||
# format indicators
|
TODO (not finished)
|
||||||
* %% - A literal %
|
# EJS variable names
|
||||||
* %A - List of tags
|
* config.variable_name - pass any variable in config.json
|
||||||
* %B - List of tags, each one with a hyperlink to that tag page
|
* hitcount - value in hitcount.txt (a single number)
|
||||||
* %C - Post content
|
## Posts (/views/posts/)
|
||||||
* %D - Published date in the format specified by date_format
|
* post - an object that includes the data for that post, eg post.title, post.content etc
|
||||||
* %E - Edited date in the format specified by date_format
|
* user - the object of the user who posted this
|
||||||
* %F - Pretty name
|
* index - an int that refers to the index of the current post
|
||||||
* %G - Tag name (used for the tag page only)
|
## Comments (/views/partials/comment.ejs)
|
||||||
* %H - Frontpage hit count
|
* comment - an object storing the comment, eg comment.name, comment.content
|
||||||
* %I - User description
|
|
||||||
* %J - URL delete account
|
|
||||||
* %L - URL Permanent link to the post
|
|
||||||
* %M - comments
|
|
||||||
* %N - the username of the user (poster)
|
|
||||||
* %P - URL to create a new post
|
|
||||||
* %O - URL to edit this post
|
|
||||||
* %Q - URL to sign up
|
|
||||||
* %R - Site wide RSS feed
|
|
||||||
* %S - post seperator as defined by post_seperator
|
|
||||||
* %T - Title
|
|
||||||
* %U - URL the the user (poster)
|
|
||||||
* %W - Site Description as defined by site_description
|
|
||||||
* %X - Comment submission box
|
|
||||||
* %Y - Site Name as defined by site_name
|
|
||||||
* %Z - Attribution (to me) and source code link and license
|
|
||||||
|
131
app.js
131
app.js
@@ -6,8 +6,10 @@ const crypto = require('crypto'); // For encrypting passwords, I use sha512
|
|||||||
// fromUnixTime(): Create a date from a Unix timestamp (in seconds). Decimal values will be discarded.
|
// fromUnixTime(): Create a date from a Unix timestamp (in seconds). Decimal values will be discarded.
|
||||||
// format(): Return the formatted date string in the given format. The result may vary by locale.
|
// format(): Return the formatted date string in the given format. The result may vary by locale.
|
||||||
// getUnixTime(): Get the seconds timestamp of the given date.
|
// getUnixTime(): Get the seconds timestamp of the given date.
|
||||||
// find out more at https://date-fns.org/ \or docs: https://date-fns.org/docs/Getting-Startedyyyyyyyy
|
// find out more at https://date-fns.org/ \or docs: https://date-fns.org/docs/Getting-Started
|
||||||
const { fromUnixTime, format, getUnixTime } = require("date-fns") // A date utility library
|
const { fromUnixTime, format, getUnixTime } = require("date-fns") // A date utility library
|
||||||
|
const ejs = require("ejs")
|
||||||
|
const func = require("./functions.js")
|
||||||
|
|
||||||
// There's only one possible argument, so we can just check if the user passed that one
|
// There's only one possible argument, so we can just check if the user passed that one
|
||||||
// TODO I plan on adding more such as --help and --post so I should make this more robust at some point
|
// TODO I plan on adding more such as --help and --post so I should make this more robust at some point
|
||||||
@@ -20,6 +22,7 @@ let users // contains a list of users, each user is an object containing usernam
|
|||||||
let posts // contains a list of posts,
|
let posts // contains a list of posts,
|
||||||
let comments // contains a list of comments
|
let comments // contains a list of comments
|
||||||
let config // contains a set of configuration for the site, see example-config.js for an example
|
let config // contains a set of configuration for the site, see example-config.js for an example
|
||||||
|
let ejs_templates
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// We're going to try and import the modules,
|
// We're going to try and import the modules,
|
||||||
@@ -27,6 +30,7 @@ try {
|
|||||||
posts = require('./posts.json');
|
posts = require('./posts.json');
|
||||||
comments = require('./comments.json');
|
comments = require('./comments.json');
|
||||||
config = require('./config.json');
|
config = require('./config.json');
|
||||||
|
ejs_templates = require("./ejs-templates.js")
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
// if they don't all import then
|
// if they don't all import then
|
||||||
@@ -56,6 +60,9 @@ const app = express();
|
|||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ extended: true }));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(express.static(config.root_path));
|
app.use(express.static(config.root_path));
|
||||||
|
// set the view engine to ejs
|
||||||
|
app.set('view engine', 'ejs');
|
||||||
|
|
||||||
// Initialise the program by creating users.js, comments.js, posts.js and config.js
|
// Initialise the program by creating users.js, comments.js, posts.js and config.js
|
||||||
// All require default content in them to start off with
|
// All require default content in them to start off with
|
||||||
// Then exit successfully
|
// Then exit successfully
|
||||||
@@ -110,16 +117,6 @@ function get_userID(username) {
|
|||||||
return -1 // If user is not present, return -1
|
return -1 // If user is not present, return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// The configuration defines a date format using the date-fns (a datetime library) syntax
|
|
||||||
// eg "yyyy-MM-dd"
|
|
||||||
// this converts unix time (an integer) into a string that is formatted according to config.js
|
|
||||||
// uses date-fns's fromUnixTime() and format() functions
|
|
||||||
// returns the formatted date (string)
|
|
||||||
function unix_time_to_date_format(unix_time) {
|
|
||||||
date = fromUnixTime(unix_time)
|
|
||||||
formatted_date = format(date, config.date_format)
|
|
||||||
return formatted_date
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is similar to the above function, however, instead of formatting to the users
|
// This is similar to the above function, however, instead of formatting to the users
|
||||||
// configuration, it formats to RFC-822 which is the date format used by RSS feeds
|
// configuration, it formats to RFC-822 which is the date format used by RSS feeds
|
||||||
@@ -173,8 +170,8 @@ function replace_format_indicators(template, post_index=-1, tag_name="tag", user
|
|||||||
.replaceAll("%A", (post_object["tags"]))
|
.replaceAll("%A", (post_object["tags"]))
|
||||||
.replaceAll("%B", (hyperlink_tags(post_object["tags"])))
|
.replaceAll("%B", (hyperlink_tags(post_object["tags"])))
|
||||||
.replaceAll("%C", converter.makeHtml(post_object["content"]))
|
.replaceAll("%C", converter.makeHtml(post_object["content"]))
|
||||||
.replaceAll("%D", unix_time_to_date_format(post_object["pubdate"]))
|
//.replaceAll("%D", unix_time_to_date_format(post_object["pubdate"]))
|
||||||
.replaceAll("%E", unix_time_to_date_format(post_object["editdate"]))
|
//.replaceAll("%E", unix_time_to_date_format(post_object["editdate"]))
|
||||||
.replaceAll("%F", users[post_object["userID"]]['prettyname'])
|
.replaceAll("%F", users[post_object["userID"]]['prettyname'])
|
||||||
.replaceAll("%G", tag_name)
|
.replaceAll("%G", tag_name)
|
||||||
.replaceAll("%I", converter.makeHtml(users[post_object['userID']]['description']))
|
.replaceAll("%I", converter.makeHtml(users[post_object['userID']]['description']))
|
||||||
@@ -235,13 +232,13 @@ function return_comments(post_id) {
|
|||||||
.replaceAll(/>> ([0-9]*)/g, "<a href='#$1'>>> $1</a>")
|
.replaceAll(/>> ([0-9]*)/g, "<a href='#$1'>>> $1</a>")
|
||||||
.replaceAll(/>> ([0-9]*)/g, "<a href='#$1'>>> $1</a>")
|
.replaceAll(/>> ([0-9]*)/g, "<a href='#$1'>>> $1</a>")
|
||||||
.replaceAll("\n", "<br/>")
|
.replaceAll("\n", "<br/>")
|
||||||
comment_content += `<div id="${comment['id']}">${comment['name']} ${unix_time_to_date_format(comment['pubdate'])} No. ${comment['id']}<br/>${comment['content']}</div><br/>`
|
//comment_content += `<div id="${comment['id']}">${comment['name']} ${unix_time_to_date_format(comment['pubdate'])} No. ${comment['id']}<br/>${comment['content']}</div><br/>`
|
||||||
}
|
}
|
||||||
return comment_content
|
return comment_content
|
||||||
}
|
}
|
||||||
|
|
||||||
// RSS protocol gets
|
// RSS protocol gets
|
||||||
app.get(config.rss_path, (req,res) => {
|
app.get(config.rss_url, (req,res) => {
|
||||||
if (config.rss == false) {
|
if (config.rss == false) {
|
||||||
res.send("Sorry, RSS is disabled!")
|
res.send("Sorry, RSS is disabled!")
|
||||||
}
|
}
|
||||||
@@ -275,6 +272,7 @@ app.get(config.rss_path, (req,res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.get("/", (req,res) => {
|
app.get("/", (req,res) => {
|
||||||
|
// Increment the hitcount
|
||||||
if (config.enable_hitcount) {
|
if (config.enable_hitcount) {
|
||||||
let hitcount = parseInt(fs.readFileSync('hitcount.txt'))
|
let hitcount = parseInt(fs.readFileSync('hitcount.txt'))
|
||||||
hitcount += 1
|
hitcount += 1
|
||||||
@@ -282,51 +280,68 @@ app.get("/", (req,res) => {
|
|||||||
fs.writeFileSync(`${__dirname}/hitcount.txt`, `${hitcount}`, 'utf-8');
|
fs.writeFileSync(`${__dirname}/hitcount.txt`, `${hitcount}`, 'utf-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
header_div = config.timeline_header
|
res.render("pages/timeline",
|
||||||
header_div = replace_format_indicators(header_div);
|
{
|
||||||
posts_div = "";
|
config: config,
|
||||||
counter = posts.length - 1;
|
posts: posts,
|
||||||
while ((counter >= 0) && (counter > (posts.length - (config.timeline_length + 1))))
|
users: users,
|
||||||
{
|
comments: comments.comments,
|
||||||
let post = config.timeline_post_format;
|
hitcount: fs.readFileSync("hitcount.txt"),
|
||||||
posts_div += replace_format_indicators(post, counter);
|
fromUnixTime: fromUnixTime,
|
||||||
counter -= 1;
|
format: format,
|
||||||
}
|
getUnixTime: getUnixTime,
|
||||||
res.send(`<html><head><meta charset="${config.charset}"><style>${config.css}</style></head><body><div id="header">${header_div}</div><div id="posts">${posts_div}</div></body><footer>${footer_div}</footer></html>`);
|
hyperlink_tags: hyperlink_tags,
|
||||||
|
})
|
||||||
}); // /
|
}); // /
|
||||||
app.get("/user/:username", (req, res) => {
|
app.get("/user/:username", (req, res) => {
|
||||||
header_div = config.user_page_header
|
const userID = get_userID(req.params.username)
|
||||||
header_div = replace_format_indicators(header_div,-1,"tag",get_userID(req.params.username))
|
console.log(userID)
|
||||||
posts_div = "";
|
console.log(users[userID].prettyname)
|
||||||
for (let post_index = posts.length-1; post_index >= 0; post_index--) {
|
res.render("pages/user",
|
||||||
if (users[posts[post_index]["userID"]]["username"] == req.params.username) {
|
{
|
||||||
let post = config.user_post_format;
|
config: config,
|
||||||
posts_div += replace_format_indicators(post, post_index);
|
posts: posts,
|
||||||
}
|
user: users[userID],
|
||||||
}
|
userID: userID,
|
||||||
res.send(`<html><head><meta charset="${config.charset}"><style>${config.css}</style></head><body><div id="header">${header_div}</div><div id="posts">${posts_div}</div></body><footer>${footer_div}</footer></html>`);
|
comments: comments.comments,
|
||||||
|
fromUnixTime: fromUnixTime,
|
||||||
|
format: format,
|
||||||
|
getUnixTime: getUnixTime,
|
||||||
|
hyperlink_tags: hyperlink_tags,
|
||||||
|
})
|
||||||
}); // /user/:username
|
}); // /user/:username
|
||||||
app.get("/post/:post_index", (req, res) => {
|
app.get("/post/:post_index", (req, res) => {
|
||||||
post_div = "";
|
const postID = req.params.post_index
|
||||||
let post = config.post_page_format;
|
res.render("pages/post",
|
||||||
post_div += replace_format_indicators(post, req.params.post_index);
|
{
|
||||||
res.send(`<html><head><meta charset="${config.charset}"><style>${config.css}</style></head><body><div id="posts">${post_div}</div></body><footer>${footer_div}</footer></html>`);
|
config,
|
||||||
|
post: posts[postID],
|
||||||
|
postID: postID,
|
||||||
|
user: users[posts[postID].userID],
|
||||||
|
comments: comments.comments[postID],
|
||||||
|
fromUnixTime,
|
||||||
|
format,
|
||||||
|
getUnixTime,
|
||||||
|
hyperlink_tags,
|
||||||
|
})
|
||||||
}); // /post/:post_index
|
}); // /post/:post_index
|
||||||
app.get("/tag/:tag", (req,res) => {
|
app.get("/tag/:tag", (req,res) => {
|
||||||
const tag = req.params.tag
|
const tag = req.params.tag
|
||||||
let header_div = config.tag_page_header
|
res.render("pages/tag",
|
||||||
header_div = replace_format_indicators(header_div,0,tag)
|
{
|
||||||
let page_content = ""
|
config: config,
|
||||||
for (let i = posts.length-1; i >= 0; i--) {
|
tag: tag,
|
||||||
if (posts[i]['tags'].includes(tag)) {
|
posts: posts,
|
||||||
let post = config.tag_post_format;
|
users: users,
|
||||||
page_content += replace_format_indicators(post, i);
|
comments: comments.comments,
|
||||||
};
|
fromUnixTime: fromUnixTime,
|
||||||
};
|
format: format,
|
||||||
res.send(`<html><style>${config.css}</style><body><div id="header">${header_div}</div><div id="posts">${page_content}</div></body><footer>${footer_div}</footer></html>`);
|
getUnixTime: getUnixTime,
|
||||||
|
hyperlink_tags: hyperlink_tags,
|
||||||
|
})
|
||||||
}); // /tag/:tag
|
}); // /tag/:tag
|
||||||
|
|
||||||
app.get("/post", (req,res) => {
|
app.get(config.new_post_url, (req,res) => {
|
||||||
res.send(`</html><head><meta charset="${config.charset}"><style>${config.css}</style></head><form action="/submit_post" method="POST">
|
res.send(`</html><head><meta charset="${config.charset}"><style>${config.css}</style></head><form action="/submit_post" method="POST">
|
||||||
<input placeholder="username" required name="username"><br/>
|
<input placeholder="username" required name="username"><br/>
|
||||||
<input placeholder="password" type="password" required id="password" name="password"><br/>
|
<input placeholder="password" type="password" required id="password" name="password"><br/>
|
||||||
@@ -337,7 +352,7 @@ app.get("/post", (req,res) => {
|
|||||||
<small>* Markdown supported</small>
|
<small>* Markdown supported</small>
|
||||||
</form></html>`);
|
</form></html>`);
|
||||||
}); // /post
|
}); // /post
|
||||||
app.get("/signup", (req,res) => {
|
app.get(config.signup_url, (req,res) => {
|
||||||
// if the server does allow signup
|
// if the server does allow signup
|
||||||
if (config.allow_signup == true) {
|
if (config.allow_signup == true) {
|
||||||
// Send the page for signing up to the server
|
// Send the page for signing up to the server
|
||||||
@@ -359,14 +374,14 @@ app.get("/signup", (req,res) => {
|
|||||||
console.log("Error, invalid value for allow_signup (bool)")
|
console.log("Error, invalid value for allow_signup (bool)")
|
||||||
}
|
}
|
||||||
}); // /signup
|
}); // /signup
|
||||||
app.get("/delete_account", (req,res) => {
|
app.get(config.delete_account_url, (req,res) => {
|
||||||
res.send(`</html><head><meta charset="${config.charset}"><style>${config.css}</style></head><form action="/submit_delete_account" method="POST">
|
res.send(`</html><head><meta charset="${config.charset}"><style>${config.css}</style></head><form action="/submit_delete_account" method="POST">
|
||||||
<input placeholder="username" required name="username"><br/>
|
<input placeholder="username" required name="username"><br/>
|
||||||
<input placeholder="password" type="password" required id="password" name="password"><br/>
|
<input placeholder="password" type="password" required id="password" name="password"><br/>
|
||||||
<label>${config.delete_account_confirmation}: </label><input type="checkbox" name="agreement" required><br/>
|
<label>${config.delete_account_confirmation}: </label><input type="checkbox" name="agreement" required><br/>
|
||||||
<input type="submit" value="Submit"><br/></form></html>`);
|
<input type="submit" value="Submit"><br/></form></html>`);
|
||||||
}); // /delete_account
|
}); // /delete_account
|
||||||
app.get("/edit/:post_id", (req,res) => {
|
app.get(`${config.edit_post_base_url}/:post_id`, (req,res) => {
|
||||||
const post_id = req.params.post_id
|
const post_id = req.params.post_id
|
||||||
const post = posts[post_id]
|
const post = posts[post_id]
|
||||||
const user = users[post['userID']]
|
const user = users[post['userID']]
|
||||||
@@ -409,13 +424,13 @@ app.post("/submit_post", (req,res) => {
|
|||||||
const content = escape_input(req.body.content)
|
const content = escape_input(req.body.content)
|
||||||
const tags = escape_input(req.body.tags).split(',');
|
const tags = escape_input(req.body.tags).split(',');
|
||||||
const unix_timestamp = getUnixTime(new Date())
|
const unix_timestamp = getUnixTime(new Date())
|
||||||
console.log(username, "is submitting a post titled:", title);
|
|
||||||
|
|
||||||
if (get_userID(username) == -1) {
|
if (get_userID(username) == -1) {
|
||||||
res.send("User does not exist")
|
res.send(`</html><head><meta charset="${config.charset}"><style>${config.css}</style></head><body>${config.user_doesnt_exit}</body></html>`)
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (users[get_userID(username)]['hash'] == password) { // Password matches
|
else if (users[get_userID(username)]['hash'] == password) { // Password matches
|
||||||
|
console.log(username, "is submitting a post titled:", title);
|
||||||
posts.push({
|
posts.push({
|
||||||
"userID": get_userID(username),
|
"userID": get_userID(username),
|
||||||
"title": title,
|
"title": title,
|
||||||
@@ -430,7 +445,7 @@ app.post("/submit_post", (req,res) => {
|
|||||||
res.redirect(302, "/");
|
res.redirect(302, "/");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res.send(`Invalid Password for user`,username);
|
res.send(`</html><head><meta charset="${config.charset}"><style>${config.css}</style></head><body>${config.incorrect_password}</body></html>`)
|
||||||
}
|
}
|
||||||
}); // /submit_post
|
}); // /submit_post
|
||||||
app.post("/submit_signup", (req,res) => {
|
app.post("/submit_signup", (req,res) => {
|
||||||
|
1
custom.css
Symbolic link
1
custom.css
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
example-custom.css
|
1
ejs-templates.js
Normal file
1
ejs-templates.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export let timeline = '<html><head><meta charset="<%=charset%>"><style></style></head><body><div id="header">${header_div}</div><div id="posts">${posts_div}</div></body><footer>${footer_div}</footer></html>'
|
@@ -9,9 +9,13 @@
|
|||||||
"enable_hitcount": true,
|
"enable_hitcount": true,
|
||||||
"charset": "UTF-8",
|
"charset": "UTF-8",
|
||||||
"root_path": "/path/to/root/of/website",
|
"root_path": "/path/to/root/of/website",
|
||||||
|
"delete_account_url": "/delete_account",
|
||||||
|
"new_post_url": "/post",
|
||||||
|
"signup_url": "/signup",
|
||||||
|
"edit_post_base_url": "/edit",
|
||||||
"default_comenter_username": "Anon",
|
"default_comenter_username": "Anon",
|
||||||
"rss": true,
|
"rss": true,
|
||||||
"rss_path": "/rss",
|
"rss_url": "/rss",
|
||||||
"date_format": "yyyy-MM-dd",
|
"date_format": "yyyy-MM-dd",
|
||||||
"time_zone": "+0000",
|
"time_zone": "+0000",
|
||||||
"timeline_header": "<h1>%Y</h1><h2>%W</h2><a href='%P'>Create Post</a><br/><a href='%R'>RSS Feed</a><br/><a href='%Q'>Sign Up</a><br/><a href='%D'>Delete Account</a><br/>Hit count: %H%S",
|
"timeline_header": "<h1>%Y</h1><h2>%W</h2><a href='%P'>Create Post</a><br/><a href='%R'>RSS Feed</a><br/><a href='%Q'>Sign Up</a><br/><a href='%D'>Delete Account</a><br/>Hit count: %H%S",
|
||||||
|
3
example-custom.css
Normal file
3
example-custom.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
body {
|
||||||
|
/* Put your custom css here */
|
||||||
|
}
|
10
functions.js
Normal file
10
functions.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// The configuration defines a date format using the date-fns (a datetime library) syntax
|
||||||
|
// eg "yyyy-MM-dd"
|
||||||
|
// this converts unix time (an integer) into a string that is formatted according to config.js
|
||||||
|
// uses date-fns's fromUnixTime() and format() functions
|
||||||
|
// returns the formatted date (string)
|
||||||
|
export function unix_time_to_date_format(unix_time, format) {
|
||||||
|
date = fromUnixTime(unix_time)
|
||||||
|
formatted_date = format(date, format)
|
||||||
|
return formatted_date
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"ejs": "^3.1.10",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"showdown": "^2.1.0"
|
"showdown": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
4
views/headers/tag.ejs
Normal file
4
views/headers/tag.ejs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<h1>
|
||||||
|
Post's tagged "<%- tag %>":
|
||||||
|
</h1>
|
||||||
|
<%- config.seperator %>
|
13
views/headers/timeline.ejs
Normal file
13
views/headers/timeline.ejs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<h1>
|
||||||
|
<%- config.site_name %>
|
||||||
|
</h1>
|
||||||
|
<h2>
|
||||||
|
<%- config.site_description %>
|
||||||
|
</h2>
|
||||||
|
<a href="<%= config.rss_url %>">RSS Feed</a><br/>
|
||||||
|
<a href="<%= config.signup_url %>">Sign Up</a><br/>
|
||||||
|
<a href="<%= config.delete_account_url %>">Delete Account</a><br/>
|
||||||
|
<% if (config.enable_hitcount == true) { %>
|
||||||
|
Hitcount: <%= hitcount %>
|
||||||
|
<% } %>
|
||||||
|
<%- config.seperator %>
|
4
views/headers/user.ejs
Normal file
4
views/headers/user.ejs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<h1>
|
||||||
|
<%- user.prettyname %>'s posts
|
||||||
|
</h1>
|
||||||
|
<%- config.seperator %>
|
14
views/pages/post.ejs
Normal file
14
views/pages/post.ejs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<%- include('../partials/head'); %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="posts">
|
||||||
|
<%- include('../posts/post'); %>
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
<%- include('../partials/footer'); %>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
23
views/pages/tag.ejs
Normal file
23
views/pages/tag.ejs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<%- include('../partials/head'); %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="header">
|
||||||
|
<%- include('../headers/tag'); %>
|
||||||
|
</div>
|
||||||
|
<div id="posts">
|
||||||
|
<% for (let index = posts.length - 1; index >= 0; index--) { %>
|
||||||
|
<% posts[index].tags.forEach((current_tag, tag_index) => { %>
|
||||||
|
<% if (current_tag == tag) { %>
|
||||||
|
<%- include('../posts/tag', {post: posts[index], postID: index}); %>
|
||||||
|
<% } %>
|
||||||
|
<% }) %>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
<%- include('../partials/footer'); %>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
19
views/pages/timeline.ejs
Normal file
19
views/pages/timeline.ejs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<%- include('../partials/head'); %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="header">
|
||||||
|
<%- include('../headers/timeline'); %>
|
||||||
|
</div>
|
||||||
|
<div id="posts">
|
||||||
|
<% for (let index = posts.length - 1; index >= 0; index--) { %>
|
||||||
|
<%- include('../posts/timeline', {post: posts[index], index: index, user: users[posts[index].userID]}); %>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
<%- include('../partials/footer'); %>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
21
views/pages/user.ejs
Normal file
21
views/pages/user.ejs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<%- include('../partials/head'); %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="header">
|
||||||
|
<%- include('../headers/user'); %>
|
||||||
|
</div>
|
||||||
|
<div id="posts">
|
||||||
|
<% for (let index = posts.length - 1; index >= 0; index--) { %>
|
||||||
|
<% if (posts[index].userID == userID) { %>
|
||||||
|
<%- include('../posts/user', {post: posts[index], index: index, user: user}); %>
|
||||||
|
<% } %>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
<%- include('../partials/footer'); %>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
2
views/partials/comment.ejs
Normal file
2
views/partials/comment.ejs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<b><%= comment.name %></b> <%= format(fromUnixTime(comment.pubdate), config.date_format) %> <i>No. <%= comment.id %></i>:<br/>
|
||||||
|
<%= comment.content %>
|
2
views/partials/footer.ejs
Normal file
2
views/partials/footer.ejs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Site is ran by deadvey<br/>
|
||||||
|
<%- config.attribution %>
|
8
views/partials/head.ejs
Normal file
8
views/partials/head.ejs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<meta charset="<%- config.charset %>">
|
||||||
|
<title><%= config.site_name %></title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="custom.css">
|
29
views/posts/post.ejs
Normal file
29
views/posts/post.ejs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<h1>
|
||||||
|
<%= post.title %>
|
||||||
|
</h1>
|
||||||
|
<%= post.content %><br/>
|
||||||
|
<i>
|
||||||
|
By <a href="/user/<%= user.username %>"><%= user.username %></a><br/>
|
||||||
|
</i>
|
||||||
|
<br/>
|
||||||
|
<%- hyperlink_tags(post.tags) %><br/>
|
||||||
|
<a href="<%= config.edit_post_base_url %>/<%= postID %>">Edit</a><br/>
|
||||||
|
<i>Published: <%= format(fromUnixTime(post.pubdate), config.date_format) %></i><br/>
|
||||||
|
<i>Last Modified: <%= format(fromUnixTime(post.editdate), config.date_format) %></i><br/>
|
||||||
|
|
||||||
|
<%- config.seperator %>
|
||||||
|
|
||||||
|
<!-- Comment form -->
|
||||||
|
<form method="POST" action="/submit_comment">
|
||||||
|
<input type="hidden" name="post_index" value="<%= postID %>">
|
||||||
|
<input placeholder="username" name="name"><br/>
|
||||||
|
<textarea placeholder="comment" name="content"></textarea><br/>
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<% comments.forEach((comment, postID) => { %>
|
||||||
|
<%- include('../partials/comment', {comment: comment}) %>
|
||||||
|
<% }) %>
|
||||||
|
|
||||||
|
<%- config.seperator %>
|
||||||
|
|
21
views/posts/tag.ejs
Normal file
21
views/posts/tag.ejs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<h3>
|
||||||
|
<%= post.title %>
|
||||||
|
</h3>
|
||||||
|
<%= post.content %><br/>
|
||||||
|
<a href="/post/<%- postID %>">Permalink</a><br/>
|
||||||
|
<%- hyperlink_tags(post.tags) %>
|
||||||
|
|
||||||
|
<!-- Comment form -->
|
||||||
|
<form method="POST" action="/submit_comment">
|
||||||
|
<input type="hidden" name="post_index" value="<%= postID %>">
|
||||||
|
<input placeholder="username" name="name"><br/>
|
||||||
|
<textarea placeholder="comment" name="content"></textarea><br/>
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<% comments[postID].forEach((comment) => { %>
|
||||||
|
<%- include('../partials/comment', {comment: comment}) %>
|
||||||
|
<% }) %>
|
||||||
|
|
||||||
|
<%- config.seperator %>
|
||||||
|
|
23
views/posts/timeline.ejs
Normal file
23
views/posts/timeline.ejs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<h3>
|
||||||
|
<%= post.title %>
|
||||||
|
</h3>
|
||||||
|
<%= post.content %><br/>
|
||||||
|
<a href="/post/<%- index %>">Permalink</a><br/>
|
||||||
|
<i>
|
||||||
|
By <a href="/user/<%= user.username %>"><%= user.username %></a><br/>
|
||||||
|
</i>
|
||||||
|
|
||||||
|
<!-- Comment form -->
|
||||||
|
<form method="POST" action="/submit_comment">
|
||||||
|
<input type="hidden" name="post_index" value="<%= index %>">
|
||||||
|
<input placeholder="username" name="name"><br/>
|
||||||
|
<textarea placeholder="comment" name="content"></textarea><br/>
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<% comments[index].forEach((comment, index) => { %>
|
||||||
|
<%- include('../partials/comment', {comment: comment}) %>
|
||||||
|
<% }) %>
|
||||||
|
|
||||||
|
<%- config.seperator %>
|
||||||
|
|
20
views/posts/user.ejs
Normal file
20
views/posts/user.ejs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<h3>
|
||||||
|
<%= post.title %>
|
||||||
|
</h3>
|
||||||
|
<%= post.content %><br/>
|
||||||
|
<a href="/post/<%- index %>">Permalink</a><br/>
|
||||||
|
|
||||||
|
<!-- Comment form -->
|
||||||
|
<form method="POST" action="/submit_comment">
|
||||||
|
<input type="hidden" name="post_index" value="<%= index %>">
|
||||||
|
<input placeholder="username" name="name"><br/>
|
||||||
|
<textarea placeholder="comment" name="content"></textarea><br/>
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<% comments[index].forEach((comment, index) => { %>
|
||||||
|
<%- include('../partials/comment', {comment: comment}) %>
|
||||||
|
<% }) %>
|
||||||
|
|
||||||
|
<%- config.seperator %>
|
||||||
|
|
Reference in New Issue
Block a user