feat: release meme protocol v1.1.0

Add one-click meme copying, complete viewer actions, fixed-footer pagination, protocol lore, and the Homo Reseticus download chooser.

Install dedicated social and favicon assets, expand local demo data, and synchronize the changelog, documentation, package, and OpenAPI release metadata.
This commit is contained in:
2026-08-14 18:54:37 -03:00
parent 0bf215555a
commit 48f05bcf8a
24 changed files with 702 additions and 81 deletions
+18 -2
View File
@@ -75,6 +75,18 @@ const server = http.createServer(async (req, res) => {
}));
}
if (req.method === 'GET' && (url.pathname === '/lore' || url.pathname === '/lore/')) {
const nonce = crypto.randomBytes(16).toString('base64');
withSecurityHeaders(res, { scriptNonce: nonce });
return sendHtml(res, 200, renderIndex({
template: indexTemplate,
baseUrl,
nonce,
approvedCount: store.count('approved'),
lore: true
}));
}
const memePageMatch = url.pathname.match(/^\/meme\/([a-f0-9]{64})\/?$/);
if (req.method === 'GET' && memePageMatch) {
const meme = store.get(memePageMatch[1]);
@@ -112,6 +124,10 @@ const server = http.createServer(async (req, res) => {
return sendJson(res, 200, manifest(baseUrl));
}
if (req.method === 'GET' && url.pathname === '/favicon.ico') {
return sendFile(res, './public/assets/favicon/favicon.ico');
}
if (req.method === 'GET' && url.pathname === '/feed.json') {
return sendJson(res, 200, feedJson(baseUrl, store.listForReview({ status: 'approved' }).memes));
}
@@ -203,7 +219,7 @@ const server = http.createServer(async (req, res) => {
if (req.method === 'POST' && url.pathname === '/api/memes') {
noIndex(res);
const { meme, quota } = await submitMeme(req);
const { meme, quota } = await addMeme(req);
return sendJson(res, meme.status === 'approved' ? 201 : 202, {
meme,
quota,
@@ -361,7 +377,7 @@ function broadcastMetric(meme) {
}
}
async function submitMeme(req) {
async function addMeme(req) {
const contentLength = Number.parseInt(req.headers['content-length'] || '0', 10);
if (!Number.isFinite(contentLength) || contentLength <= 0) {
const error = new Error('Missing upload size.');