Compare commits

...

5 Commits

Author SHA1 Message Date
c8af978259 docs and also I improved the readability/user friendliness of the EJS 2025-09-03 22:28:50 +01:00
99e07389d0 * more proffesional language in rejecting AI
* footer uses locales
2025-08-27 19:00:49 +01:00
532010f873 bug fix for site_admin config field 2025-08-27 18:53:29 +01:00
5917789c5b add webadmin as a field in the config 2025-08-27 18:51:59 +01:00
4f0941262e Withdraw consent for AI scraping 2025-08-27 18:49:33 +01:00
17 changed files with 219 additions and 97 deletions

View File

@@ -48,3 +48,4 @@ See [docs/DOCUMENTATION.md](docs/DOCUMENTATION.md)
# Customisation:
Customisation of settings can be done via the config.json file (use example-config.json as an example) and see [the configuration guide](docs/CONFIG.md)<br/>
Additionaly, more complex configuration of the precise template of the whole site, can be done via [EJS](https://ejs.co/) (in /views) (see [the list of things variables and functions available in EJS](docs/EJS.md) (you will need to understand EJS syntax and JavaScript, to customise this (why did I use EJS? well I originally had this weird system of format indicators with percent (%) signs and stuff (like in unix's date (`date`)) but then I was told EJS is better and it sure is, though it is a bit harder to understand but MUCH more powerful!))
Also, if you want to change any of the strings on the website, please modify or create a new, customised locale in /locales

4
docs/CLASSES_AND_IDS.md Normal file
View File

@@ -0,0 +1,4 @@
Post:
![images/post-css.png](An image showing the css id's assosciated with each part of a post)

View File

@@ -1,4 +1,5 @@
# Installation
This program is currently just ran manually.<br/>
All you need to do is clone the git repository:<br/>
```git clone https://git.javalsai.tuxcord.net/deadvey/blogger-nodejs.git```<br/>
Then navigate to /src:<br/>
@@ -8,4 +9,4 @@ Then run the initialisation function:<br/>
Then you should modify config.json in / to suit your needs.<br/>
# Running
I would reccomend running the program in tmux so it does not stop running when you close the terminal window.<br/>
I might add support for running in the background later.
• There is currently no init system support. I might add this later (or you could open a PR).

BIN
docs/images/post-css.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

View File

@@ -1,4 +1,5 @@
{
"site_admin": "your name",
"seperator": "<hr/>",
"site_name": "My Blog",
"site_url": "https://example.com",

View File

@@ -12,6 +12,7 @@
"comment": "Comment",
"submit": "Sumbit",
"site_ran_by": "Site is ran by",
"signups_unavailable": "Sorry, this server does not allow signups",
"user_exists": "Sorry, this user already exists, try a different username",
"user_doesnt_exist": "Sorry, this user does not exist",
@@ -20,9 +21,11 @@
"incorrect_password": "Incorrect Password",
"rss_disabled": "Sorry, RSS is disabled",
"atom_disabled": "Sorry, ATOM is disabled",
"AI_consent": "The content on this website may not be copied, scraped, or used to train AI models or large language models (LLMs) without prior written consent.",
"rss_feed": "RSS Feed",
"atom_feed": "ATOM Feed",
"no_tags": "No Tags",
"new_post": "New Post",
"edit_post": "Edit Post",
"sign_up": "Sign Up",

View File

@@ -12,6 +12,7 @@
"comment": "Comment",
"submit": "Sumbit",
"site_ran_by": "Site is ran by",
"signups_unavailable": "Sorry, this server does not allow signups",
"user_exists": "Sorry, this user already exists, try a different username",
"user_doesnt_exist": "Sorry, this user does not exist",
@@ -20,9 +21,11 @@
"incorrect_password": "Incorrect Password",
"rss_disabled": "Sorry, RSS is disabled",
"atom_disabled": "Sorry, ATOM is disabled",
"AI_consent": "The·content·on·this·website·may·not·be·copied,·scraped,·or·used·to·train·AI·models·or·large·language·models·(LLMs)·without·prior·written·consent.",
"rss_feed": "RSS Feed",
"atom_feed": "ATOM Feed",
"no_tags": "No Tags",
"new_post": "New Post",
"edit_post": "Edit Post",
"sign_up": "Sign Up",

View File

@@ -1,4 +1,9 @@
{
"name": "blogger-nodejs",
"version": "0.0.5",
"description": "Simple web logging backend",
"author": "DeaDvey",
"license": "WTFPL",
"dependencies": {
"date-fns": "^4.1.0",
"ejs": "^3.1.10",

View File

@@ -1,5 +1,7 @@
import { createRequire } from 'module';
const require = createRequire(import.meta.url)
const config = require("../config.json")
const locale = require(`../locales/${config.locale}.json`)
// The configuration defines a date format using the date-fns (a datetime library) syntax
// eg "yyyy-MM-dd"
@@ -8,7 +10,6 @@ const require = createRequire(import.meta.url)
// returns the formatted date (string)
export function unix_time_to_date_format(unix_time) {
const { fromUnixTime, format, getUnixTime } = require("date-fns") // A date utility library
const config = require("../config.json")
let date = fromUnixTime(unix_time)
let formatted_date = format(date, config.date_format)
return formatted_date
@@ -20,7 +21,6 @@ export function unix_time_to_date_format(unix_time) {
// returns the formatted date (string)
export function unix_time_to_rss_date(unix_time) {
const { fromUnixTime, format, getUnixTime } = require("date-fns") // A date utility library
const config = require("../config.json")
let date = fromUnixTime(unix_time)
let formatted_date = format(date, "EEE, dd MMM yyyy HH:mm:ss")
return `${formatted_date} ${config.time_zone}`
@@ -37,14 +37,19 @@ export function unix_time_to_atom_date(unix_time) {
// eg "<a href="/tag/string1">string1</a>, <a href="/tag/string2">string2</a>, <a href="/tag/string3">string3</a>"
// this is so you can have a list of tags that each point to their individual tag page
// returns: string
export function hyperlink_tags(tags) {
export function render_tags(tags) {
let string = "" // Initialises the string
for (let tag_index = 0; tag_index < tags.length; tag_index++) { // Loop over each tag
string += `<a href="/tag/${tags[tag_index]}">${tags[tag_index]}</a>` // Adds the tag to the string as a HTML href
if (tag_index < tags.length - 1) { // If there are more tags, then insert a comma
string += ", ";
}
}
if (tags.length == 1 && tags[0] == "") {
string = locale.no_tags; // If there are no tags, output something
}
else {
for (let tag_index = 0; tag_index < tags.length; tag_index++) { // Loop over each tag
string += `<a href="/tag/${tags[tag_index]}">${tags[tag_index]}</a>` // Adds the tag to the string as a HTML href
if (tag_index < tags.length - 1) { // If there are more tags, then insert a comma
string += ", ";
}
}
}
return string
}
// The users are stored as a list of objects [ user_object, user_object, user_object ]
@@ -101,8 +106,6 @@ export function render_comment(comment_content) {
};
export function render_md(content) {
const markdownit = require("markdown-it")
const config = require("../config.json")
const locale = require(`../locales/${config.locale}.json`)
const md = markdownit({
html: false,
xhtmlOut: false,

View File

@@ -13,7 +13,7 @@
<% if ( posts[index].deleted != true) { %>
<% posts[index].tags.forEach((current_tag, tag_index) => { %>
<% if (current_tag == tag) { %>
<%- include('../posts/tag', {post: posts[index], postID: index}); %>
<%- include('../posts/tag', {post: posts[index], user: users[posts[index].userID], comments: comments[index]}); %>
<% } %>
<% }) %>
<% } %>

View File

@@ -18,7 +18,7 @@
<div id="posts">
<% for (let index = posts.length - 1; index >= 0; index--) { %>
<% if (posts[index]["deleted"] != true) { %>
<%- include('../posts/timeline', {post: posts[index], postID: index, user: users[posts[index].userID]}); %>
<%- include('../posts/timeline', {post: posts[index], postID: index, user: users[posts[index].userID], comments: comments[index]}); %>
<% } %>
<% } %>
</div>

View File

@@ -11,7 +11,7 @@
<div id="posts">
<% for (let index = posts.length - 1; index >= 0; index--) { %>
<% if (posts[index].userID == userID) { %>
<%- include('../posts/user', {post: posts[index], postID: index, user: user}); %>
<%- include('../posts/user', {post: posts[index], postID: index, user: user, comments: comments[index]}); %>
<% } %>
<% } %>
</div>

View File

@@ -1,2 +1,3 @@
Site is ran by deadvey<br/>
<%- locale.attribution %>
<%= locale.site_ran_by %> <%= config.site_admin %><br/>
<%- locale.attribution %><br/>
<%= locale.AI_consent %> <!-- remove consent for AI scrapers -->

View File

@@ -1,28 +1,48 @@
<h1>
<%= post.title %>
</h1>
<%- func.render_md(post.content) %><br/>
<i>
<%= locale.written_by %> <a href="/user/<%= user.username %>"><%= user.username %></a><br/>
</i>
<%- func.hyperlink_tags(post.tags) %><br/>
<a href="<%= config.edit_post_base_url %>/<%= postID %>"><%= locale.edit_post %></a><br/>
<i><%= locale.published %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
<i><%= locale.last_modified %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
<%- config.seperator %>
<!-- Comment form -->
<form method="POST" action="/submit_comment">
<input type="hidden" name="post_index" value="<%= postID %>">
<label><%= locale.username %>:</label><br/><input name="name"><br/><br/>
<label><%= locale.comment %>:</label><br/><textarea name="content"></textarea><br/>
<button type="submit"><%= locale.submit %></button>
</form>
<% comments.forEach((comment, postID) => { %>
<%- include('../partials/comment', {comment: comment}) %>
<% }) %>
<div id="post-header">
<h1>
<%= post.title %>
</h1>
</div>
<div id="post-content">
<p>
<%- func.render_md(post.content) %><br/>
</p>
</div>
<div id="post-details">
<div id="post-author">
<i><%= locale.written_by %> <a href="/user/<%= user.username %>"><%= user.username %></a><br/></i>
</div>
<div id="post-tags">
<%- func.render_tags(post.tags) %><br/>
</div>
<div id="post-edit">
<a href="<%= config.edit_post_base_url %>/<%= post["id"] %>"><%= locale.edit_post %></a><br/>
</div>
<div id="post-pubdate">
<i><%= locale.published %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
</div>
<div id="post-editdate">
<i><%= locale.last_modified %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
</div>
</div>
<div id="post-commentform">
<!-- Comment form -->
<form method="POST" action="/submit_comment">
<input type="hidden" name="post_index" value="<%= post["id"] %>">
<label><%= locale.username %>:</label><br/><input name="name"><br/><br/>
<label><%= locale.comment %>:</label><br/><textarea name="content"></textarea><br/>
<button type="submit"><%= locale.submit %></button>
</form>
</div>
<div id="post-comments">
<% comments.forEach((comment, index) => { %>
<div id="comment-no<%= comment.id %>" class="post-comment-<%= index %>">
<%- include('../partials/comment', {comment: comment}) %>
</div>
<% }) %>
</div>
<%- config.seperator %>

View File

@@ -1,23 +1,51 @@
<h3>
<%= post.title %>
</h3>
<%- func.render_md(post.content) %><br/>
<a href="<%= config.edit_post_base_url %>/<%= postID %>"><%= locale.edit_post %></a><br/>
<a href="/post/<%- postID %>"><%= locale.permalink %></a><br/>
<%- func.hyperlink_tags(post.tags) %>
<br/>
<div id="post-header">
<h1>
<%= post.title %>
</h1>
</div>
<div id="post-content">
<p>
<%- func.render_md(post.content) %><br/>
</p>
</div>
<div id="post-details">
<div id="post-author">
<i><%= locale.written_by %> <a href="/user/<%= user.username %>"><%= user.username %></a><br/></i>
</div>
<div id="post-permalink">
<a href="/post/<%= post["id"] %>"><%= locale.permalink %><a/>
</div>
<div id="post-tags">
<%- func.render_tags(post.tags) %><br/>
</div>
<div id="post-edit">
<a href="<%= config.edit_post_base_url %>/<%= post["id"] %>"><%= locale.edit_post %></a><br/>
</div>
<div id="post-pubdate">
<i><%= locale.published %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
</div>
<div id="post-editdate">
<i><%= locale.last_modified %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
</div>
</div>
<!-- Comment form -->
<form method="POST" action="/submit_comment">
<input type="hidden" name="post_index" value="<%= postID %>">
<label><%= locale.username %>:</label><br/><input name="name"><br/><br/>
<label><%= locale.comment %>:</label><br/><textarea name="content"></textarea><br/>
<button type="submit"><%= locale.submit %></button>
</form>
<div id="post-commentform">
<!-- Comment form -->
<form method="POST" action="/submit_comment">
<input type="hidden" name="post_index" value="<%= post["id"] %>">
<label><%= locale.username %>:</label><br/><input name="name"><br/><br/>
<label><%= locale.comment %>:</label><br/><textarea name="content"></textarea><br/>
<button type="submit"><%= locale.submit %></button>
</form>
</div>
<% comments[postID].forEach((comment) => { %>
<%- include('../partials/comment', {comment: comment}) %>
<% }) %>
<div id="post-comments">
<% comments.forEach((comment, index) => { %>
<div id="comment-no<%= comment.id %>" class="post-comment-<%= index %>">
<%- include('../partials/comment', {comment: comment}) %>
</div>
<% }) %>
</div>
<%- config.seperator %>

View File

@@ -1,25 +1,51 @@
<h3>
<%= post.title %>
</h3>
<%- func.render_md(post.content) %><br/>
<a href="<%= config.edit_post_base_url %>/<%= postID %>"><%= locale.edit_post %></a><br/>
<a href="/post/<%- postID %>"><%= locale.permalink %></a><br/>
<i>
<%= locale.written_by %> <a href="/user/<%= user.username %>"><%= user.username %></a><br/>
</i>
<br/>
<div id="post-header">
<h1>
<%= post.title %>
</h1>
</div>
<div id="post-content">
<p>
<%- func.render_md(post.content) %><br/>
</p>
</div>
<div id="post-details">
<div id="post-author">
<i><%= locale.written_by %> <a href="/user/<%= user.username %>"><%= user.username %></a><br/></i>
</div>
<div id="post-permalink">
<a href="/post/<%= post["id"] %>"><%= locale.permalink %><a/>
</div>
<div id="post-tags">
<%- func.render_tags(post.tags) %><br/>
</div>
<div id="post-edit">
<a href="<%= config.edit_post_base_url %>/<%= post["id"] %>"><%= locale.edit_post %></a><br/>
</div>
<div id="post-pubdate">
<i><%= locale.published %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
</div>
<div id="post-editdate">
<i><%= locale.last_modified %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
</div>
</div>
<!-- Comment form -->
<form method="POST" action="/submit_comment">
<input type="hidden" name="post_index" value="<%= postID %>">
<label><%= locale.username %>:</label><br/><input name="name"><br/><br/>
<label><%= locale.comment %>:</label><br/><textarea name="content"></textarea><br/>
<button type="submit"><%= locale.submit %></button>
</form>
<div id="post-commentform">
<!-- Comment form -->
<form method="POST" action="/submit_comment">
<input type="hidden" name="post_index" value="<%= post["id"] %>">
<label><%= locale.username %>:</label><br/><input name="name"><br/><br/>
<label><%= locale.comment %>:</label><br/><textarea name="content"></textarea><br/>
<button type="submit"><%= locale.submit %></button>
</form>
</div>
<% comments[postID].forEach((comment, postID) => { %>
<%- include('../partials/comment', {comment: comment}) %>
<% }) %>
<div id="post-comments">
<% comments.forEach((comment, index) => { %>
<div id="comment-no<%= comment.id %>" class="post-comment-<%= index %>">
<%- include('../partials/comment', {comment: comment}) %>
</div>
<% }) %>
</div>
<%- config.seperator %>

View File

@@ -1,22 +1,48 @@
<h3>
<%= post.title %>
</h3>
<%- func.render_md(post.content) %><br/>
<a href="<%= config.edit_post_base_url %>/<%= postID %>"><%= locale.edit_post %></a><br/>
<a href="/post/<%- postID %>"><%= locale.permalink %></a><br/>
<br/>
<div id="post-header">
<h1>
<%= post.title %>
</h1>
</div>
<div id="post-content">
<p>
<%- func.render_md(post.content) %><br/>
</p>
</div>
<div id="post-details">
<div id="post-permalink">
<a href="/post/<%= post["id"] %>"><%= locale.permalink %><a/>
</div>
<div id="post-tags">
<%- func.render_tags(post.tags) %><br/>
</div>
<div id="post-edit">
<a href="<%= config.edit_post_base_url %>/<%= post["id"] %>"><%= locale.edit_post %></a><br/>
</div>
<div id="post-pubdate">
<i><%= locale.published %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
</div>
<div id="post-editdate">
<i><%= locale.last_modified %>: <%= func.unix_time_to_date_format(post.pubdate) %></i><br/>
</div>
</div>
<!-- Comment form -->
<form method="POST" action="/submit_comment">
<input type="hidden" name="post_index" value="<%= postID %>">
<label><%= locale.username %>:</label><br/><input name="name"><br/><br/>
<label><%= locale.comment %>:</label><br/><textarea name="content"></textarea><br/>
<button type="submit"><%= locale.submit %></button>
</form>
<div id="post-commentform">
<!-- Comment form -->
<form method="POST" action="/submit_comment">
<input type="hidden" name="post_index" value="<%= post["id"] %>">
<label><%= locale.username %>:</label><br/><input name="name"><br/><br/>
<label><%= locale.comment %>:</label><br/><textarea name="content"></textarea><br/>
<button type="submit"><%= locale.submit %></button>
</form>
</div>
<% comments[postID].forEach((comment, postID) => { %>
<%- include('../partials/comment', {comment: comment}) %>
<% }) %>
<div id="post-comments">
<% comments.forEach((comment, index) => { %>
<div id="comment-no<%= comment.id %>" class="post-comment-<%= index %>">
<%- include('../partials/comment', {comment: comment}) %>
</div>
<% }) %>
</div>
<%- config.seperator %>