mirror of https://gitgud.io/fatchan/jschan.git
Merge pull request #27 from fatchan/html-generate
commit
2ccafcdb06
59 changed files with 975 additions and 503 deletions
@ -0,0 +1,97 @@ |
||||
'use strict'; |
||||
|
||||
const Posts = require(__dirname+'/db/posts.js') |
||||
, Boards = require(__dirname+'/db/boards.js') |
||||
, uploadDirectory = require(__dirname+'/helpers/uploadDirectory.js') |
||||
, render = require(__dirname+'/helpers/render.js'); |
||||
|
||||
module.exports = { |
||||
|
||||
buildCatalog: async (board) => { |
||||
const threads = await Posts.getCatalog(board._id); |
||||
return render(`${board._id}/catalog.html`, 'catalog.pug', { |
||||
board, |
||||
threads |
||||
}); |
||||
}, |
||||
|
||||
buildThread: async (threadId, board) => { |
||||
//console.log('building thread', `${board._id || board}/thread/${threadId}.html`);
|
||||
if (!board._id) { |
||||
board = await Boards.findOne(board); |
||||
} |
||||
const thread = await Posts.getThread(board._id, threadId) |
||||
if (!thread) { |
||||
return; //this thread may have been an OP that was deleted during a rebuild
|
||||
} |
||||
return render(`${board._id}/thread/${threadId}.html`, 'thread.pug', { |
||||
board, |
||||
thread |
||||
}); |
||||
}, |
||||
|
||||
buildBoard: async (board, page, maxPage=null) => { |
||||
//console.log('building board page', `${board._id}/${page === 1 ? 'index' : page}.html`);
|
||||
const threads = await Posts.getRecent(board._id, page); |
||||
if (!maxPage) { |
||||
maxPage = Math.ceil((await Posts.getPages(board._id)) / 10); |
||||
} |
||||
return render(`${board._id}/${page === 1 ? 'index' : page}.html`, 'board.pug', { |
||||
board, |
||||
threads, |
||||
maxPage, |
||||
page |
||||
}); |
||||
}, |
||||
|
||||
//building multiple pages (for rebuilds)
|
||||
buildBoardMultiple: async (board, startpage=1, endpage=10) => { |
||||
const maxPage = Math.ceil((await Posts.getPages(board._id)) / 10); |
||||
if (endpage === 0) { |
||||
//deleted only/all posts, so only 1 page will remain
|
||||
endpage = 1; |
||||
} else if (maxPage < endpage) { |
||||
//else just build up to the max page if it is greater than input page number
|
||||
endpage = maxPage |
||||
} |
||||
const difference = endpage-startpage + 1; //+1 because for single pagemust be > 0
|
||||
const threads = await Posts.getRecent(board._id, startpage, difference*10); |
||||
const buildArray = []; |
||||
for (let i = startpage; i <= endpage; i++) { |
||||
//console.log('multi building board page', `${board._id}/${i === 1 ? 'index' : i}.html`);
|
||||
let spliceStart = (i-1)*10; |
||||
if (spliceStart > 0) { |
||||
spliceStart = spliceStart - 1; |
||||
} |
||||
buildArray.push( |
||||
render(`${board._id}/${i === 1 ? 'index' : i}.html`, 'board.pug', { |
||||
board, |
||||
threads: threads.splice(0,10), |
||||
maxPage, |
||||
page: i, |
||||
}) |
||||
); |
||||
} |
||||
return Promise.all(buildArray); |
||||
}, |
||||
|
||||
buildHomepage: async () => { |
||||
const boards = await Boards.find(); |
||||
return render('index.html', 'home.pug', { |
||||
boards |
||||
}); |
||||
}, |
||||
|
||||
buildChangePassword: () => { |
||||
return render('changepassword.html', 'changepassword.pug'); |
||||
}, |
||||
|
||||
buildLogin: () => { |
||||
return render('login.html', 'login.pug'); |
||||
}, |
||||
|
||||
buildRegister: () => { |
||||
return render('register.html', 'register.pug'); |
||||
}, |
||||
|
||||
} |
@ -1,15 +1,12 @@ |
||||
'use strict'; |
||||
|
||||
const path = require('path') |
||||
, util = require('util') |
||||
, fs = require('fs') |
||||
, unlink = util.promisify(fs.unlink) |
||||
const remove = require('fs-extra').remove |
||||
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js'); |
||||
|
||||
module.exports = async (filenames, folder) => { |
||||
|
||||
await Promise.all(filenames.map(async filename => { |
||||
unlink(`${uploadDirectory}${folder}/${filename}`) |
||||
remove(`${uploadDirectory}${folder}/${filename}`) |
||||
})); |
||||
|
||||
} |
||||
|
@ -0,0 +1,19 @@ |
||||
'use strict'; |
||||
|
||||
const uploadDirectory = require(__dirname+'/../uploadDirectory.js') |
||||
, gm = require('@tohru/gm'); |
||||
|
||||
module.exports = (file, filename, folder) => { |
||||
|
||||
return new Promise((resolve, reject) => { |
||||
gm(file.tempFilePath) |
||||
.noProfile() |
||||
.write(`${uploadDirectory}${folder}/${filename}`, function (err) { |
||||
if (err) { |
||||
return reject(err); |
||||
} |
||||
return resolve(); |
||||
}); |
||||
}); |
||||
|
||||
}; |
@ -1,9 +1,8 @@ |
||||
'use strict'; |
||||
|
||||
const configs = require(__dirname+'/../../configs/main.json') |
||||
, uploadDirectory = require(__dirname+'/../uploadDirectory.js'); |
||||
const uploadDirectory = require(__dirname+'/../uploadDirectory.js'); |
||||
|
||||
module.exports = (req, res, file, filename, folder) => { |
||||
module.exports = (file, filename, folder) => { |
||||
|
||||
return new Promise((resolve, reject) => { |
||||
file.mv(`${uploadDirectory}${folder}/${filename}`, function (err) { |
@ -0,0 +1,12 @@ |
||||
'use strict'; |
||||
|
||||
const outputFile = require('fs-extra').outputFile |
||||
, pug = require('pug') |
||||
, path = require('path') |
||||
, uploadDirectory = require(__dirname+'/uploadDirectory.js') |
||||
, templateDirectory = path.join(__dirname+'/../views/pages/'); |
||||
|
||||
module.exports = async (htmlName, templateName, options) => { |
||||
const html = pug.renderFile(`${templateDirectory}${templateName}`, { ...options, cache: true }); |
||||
return outputFile(`${uploadDirectory}html/${htmlName}`, html); |
||||
}; |
@ -1,14 +0,0 @@ |
||||
'use strict'; |
||||
|
||||
const util = require('util') |
||||
, fs = require('fs') |
||||
, pug = require('pug') |
||||
, path = require('path') |
||||
, writeFile = util.promisify(fs.writeFile) |
||||
, uploadDirectory = require(__dirname+'/uploadDirectory.js') |
||||
, pugDirectory = path.join(__dirname+'/../views/pages'); |
||||
|
||||
module.exports = async (htmlName, pugName, pugVars) => { |
||||
const html = pug.renderFile(`${pugDirectory}/${pugName}`, pugVars); |
||||
return writeFile(`${uploadDirectory}html/${htmlName}`, html); |
||||
}; |
@ -1,26 +1,22 @@ |
||||
'use strict'; |
||||
|
||||
const Posts = require(__dirname+'/../../db/posts.js')l |
||||
const Posts = require(__dirname+'/../../db/posts.js') |
||||
, { buildBoard } = require(__dirname+'/../../build.js') |
||||
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
const page = req.params.page === 'index' ? 1 : (req.params.page || 1); |
||||
let threads; |
||||
let pages; |
||||
const page = req.params.page === 'index' ? 1 : req.params.page; |
||||
try { |
||||
pages = Math.ceil((await Posts.getPages(req.params.board)) / 10) |
||||
if (page > pages && pages > 0) { |
||||
const maxPage = Math.ceil((await Posts.getPages(req.params.board)) / 10); |
||||
if (page > maxPage && maxPage > 0) { |
||||
return next(); |
||||
} |
||||
threads = await Posts.getRecent(req.params.board, page); |
||||
await buildBoard(res.locals.board, page, maxPage); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
return res.render('board', { |
||||
threads: threads || [], |
||||
pages, |
||||
page, |
||||
}); |
||||
return res.sendFile(`${uploadDirectory}html/${req.params.board}/${page === 1 ? 'index' : page}.html`); |
||||
|
||||
} |
||||
|
@ -1,20 +1,16 @@ |
||||
'use strict'; |
||||
|
||||
const Posts = require(__dirname+'/../../db/posts.js'); |
||||
const { buildCatalog } = require(__dirname+'/../../build.js') |
||||
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
// get all threads
|
||||
let threads; |
||||
try { |
||||
threads = await Posts.getCatalog(req.params.board); |
||||
await buildCatalog(res.locals.board); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
//render the page
|
||||
res.render('catalog', { |
||||
threads: threads || [], |
||||
}); |
||||
return res.sendFile(`${uploadDirectory}html/${req.params.board}/catalog.html`); |
||||
|
||||
} |
||||
|
@ -1,8 +1,16 @@ |
||||
'use strict'; |
||||
|
||||
module.exports = (req, res, next) => { |
||||
const { buildChangePassword } = require(__dirname+'/../../build.js') |
||||
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js'); |
||||
|
||||
//render the page
|
||||
res.render('changepassword'); |
||||
module.exports = async (req, res, next) => { |
||||
|
||||
try { |
||||
await buildChangePassword(); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
return res.sendFile(`${uploadDirectory}html/changepassword.html`); |
||||
|
||||
} |
||||
|
@ -1,17 +1,16 @@ |
||||
'use strict'; |
||||
|
||||
const Boards = require(__dirname+'/../../db/boards.js'); |
||||
const { buildHomepage } = require(__dirname+'/../../build.js') |
||||
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
//get a list of boards
|
||||
let boards; |
||||
try { |
||||
boards = await Boards.find(); |
||||
await buildHomepage(); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
res.render('home', { boards }); |
||||
return res.sendFile(`${uploadDirectory}html/index.html`); |
||||
|
||||
} |
||||
|
@ -1,11 +1,16 @@ |
||||
'use strict'; |
||||
|
||||
module.exports = (req, res, next) => { |
||||
const { buildLogin } = require(__dirname+'/../../build.js') |
||||
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js'); |
||||
|
||||
//render the page
|
||||
res.render('login', { |
||||
csrf: req.csrfToken(), |
||||
redirect: req.query.redirect, |
||||
}); |
||||
module.exports = async (req, res, next) => { |
||||
|
||||
try { |
||||
await buildLogin(); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
return res.sendFile(`${uploadDirectory}html/login.html`); |
||||
|
||||
} |
||||
|
@ -1,10 +1,16 @@ |
||||
'use strict'; |
||||
|
||||
module.exports = (req, res, next) => { |
||||
const { buildRegister } = require(__dirname+'/../../build.js') |
||||
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js'); |
||||
|
||||
//render the page
|
||||
res.render('register', { |
||||
csrf: req.csrfToken() |
||||
}); |
||||
module.exports = async (req, res, next) => { |
||||
|
||||
try { |
||||
await buildRegister(); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
return res.sendFile(`${uploadDirectory}html/register.html`); |
||||
|
||||
} |
||||
|
@ -1,23 +1,16 @@ |
||||
'use strict'; |
||||
|
||||
const Posts = require(__dirname+'/../../db/posts.js'); |
||||
const { buildThread } = require(__dirname+'/../../build.js') |
||||
, uploadDirectory = require(__dirname+'/../../helpers/uploadDirectory.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
//get the recently bumped thread & preview posts
|
||||
let thread; |
||||
try { |
||||
thread = await Posts.getThread(req.params.board, req.params.id); |
||||
await buildThread(res.locals.thread.postId, res.locals.board); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
} |
||||
|
||||
if (!thread) { |
||||
return res.status(404).render('404'); |
||||
} |
||||
return res.sendFile(`${uploadDirectory}html/${req.params.board}/thread/${req.params.id}.html`); |
||||
|
||||
//render the page
|
||||
res.render('thread', { |
||||
thread |
||||
}); |
||||
} |
||||
|
@ -1,57 +1,56 @@ |
||||
label.toggle-label Toggle Post Actions |
||||
input.toggle(type='checkbox') |
||||
.action-wrapper.togglable |
||||
.actions |
||||
h4.no-m-p Actions: |
||||
label |
||||
input.post-check(type='checkbox', name='delete' value=1) |
||||
| Delete |
||||
label |
||||
input.post-check(type='checkbox', name='delete_file' value=1) |
||||
| Delete File Only |
||||
label |
||||
input.post-check(type='checkbox', name='spoiler' value=1) |
||||
| Spoiler Images |
||||
label |
||||
input#password(type='text', name='password', placeholder='post password' autocomplete='off') |
||||
label |
||||
input.post-check(type='checkbox', name='report' value=1) |
||||
| Report |
||||
label |
||||
input.post-check(type='checkbox', name='global_report' value=1) |
||||
| Global Report |
||||
label |
||||
input#report(type='text', name='report_reason', placeholder='report reason' autocomplete='off') |
||||
.actions |
||||
h4.no-m-p Mod Actions: |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_board' value=1) |
||||
| Delete from IP on board |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_global' value=1) |
||||
| Delete from IP globally |
||||
label |
||||
input.post-check(type='checkbox', name='sticky' value=1) |
||||
| Sticky |
||||
label |
||||
input.post-check(type='checkbox', name='lock' value=1) |
||||
| Lock |
||||
label |
||||
input.post-check(type='checkbox', name='sage' value=1) |
||||
| Sage |
||||
label |
||||
input.post-check(type='checkbox', name='ban' value=1) |
||||
| Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='global_ban' value=1) |
||||
| Global Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='preserve_post' value=1) |
||||
| Show Post In Ban |
||||
label |
||||
input#report(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off') |
||||
.actions |
||||
h4.no-m-p Captcha: |
||||
img.captcha(src='/captcha' width=200 height=80) |
||||
input#captcha(type='text', name='captcha', autocomplete='off' placeholder='captcha text' maxlength='6') |
||||
input(type='submit', value='submit') |
||||
details.toggle-label |
||||
summary Show Post Actions |
||||
.actions |
||||
h4.no-m-p Actions: |
||||
label |
||||
input.post-check(type='checkbox', name='delete' value=1) |
||||
| Delete |
||||
label |
||||
input.post-check(type='checkbox', name='delete_file' value=1) |
||||
| Delete File Only |
||||
label |
||||
input.post-check(type='checkbox', name='spoiler' value=1) |
||||
| Spoiler Images |
||||
label |
||||
input#password(type='text', name='password', placeholder='post password' autocomplete='off') |
||||
label |
||||
input.post-check(type='checkbox', name='report' value=1) |
||||
| Report |
||||
label |
||||
input.post-check(type='checkbox', name='global_report' value=1) |
||||
| Global Report |
||||
label |
||||
input#report(type='text', name='report_reason', placeholder='report reason' autocomplete='off') |
||||
.actions |
||||
h4.no-m-p Mod Actions: |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_board' value=1) |
||||
| Delete from IP on board |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_global' value=1) |
||||
| Delete from IP globally |
||||
label |
||||
input.post-check(type='checkbox', name='sticky' value=1) |
||||
| Sticky |
||||
label |
||||
input.post-check(type='checkbox', name='lock' value=1) |
||||
| Lock |
||||
label |
||||
input.post-check(type='checkbox', name='sage' value=1) |
||||
| Sage |
||||
label |
||||
input.post-check(type='checkbox', name='ban' value=1) |
||||
| Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='global_ban' value=1) |
||||
| Global Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='preserve_post' value=1) |
||||
| Show Post In Ban |
||||
label |
||||
input#report(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off') |
||||
.actions |
||||
h4.no-m-p Captcha: |
||||
img.captcha(src='/captcha' width=200 height=80) |
||||
input#captcha(type='text', name='captcha', autocomplete='off' placeholder='captcha text' maxlength='6') |
||||
input(type='submit', value='submit') |
||||
|
@ -1,32 +1,28 @@ |
||||
label.toggle-label Toggle Post Actions |
||||
input.toggle(type='checkbox') |
||||
.action-wrapper.togglable |
||||
.actions |
||||
h4.no-m-p Actions: |
||||
label |
||||
input.post-check(type='checkbox', name='delete' value=1) |
||||
| Delete |
||||
label |
||||
input.post-check(type='checkbox', name='delete_file' value=1) |
||||
| Delete File Only |
||||
label |
||||
input.post-check(type='checkbox', name='spoiler' value=1) |
||||
| Spoiler Images |
||||
label |
||||
input#report(type='text', name='report_reason', placeholder='report reason' autocomplete='off') |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_global' value=1) |
||||
| Delete from IP globally |
||||
label |
||||
input.post-check(type='checkbox', name='global_dismiss' value=1) |
||||
| Dismiss Global Reports |
||||
label |
||||
input.post-check(type='checkbox', name='global_ban' value=1) |
||||
| Global Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='preserve_post' value=1) |
||||
| Show Post In Ban |
||||
label |
||||
input#ban_reason(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off') |
||||
input(type='submit', value='submit') |
||||
|
||||
details.toggle-label |
||||
summary Show Post Actions |
||||
.actions |
||||
h4.no-m-p Actions: |
||||
label |
||||
input.post-check(type='checkbox', name='delete' value=1) |
||||
| Delete |
||||
label |
||||
input.post-check(type='checkbox', name='delete_file' value=1) |
||||
| Delete File Only |
||||
label |
||||
input.post-check(type='checkbox', name='spoiler' value=1) |
||||
| Spoiler Images |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_global' value=1) |
||||
| Delete from IP globally |
||||
label |
||||
input.post-check(type='checkbox', name='global_dismiss' value=1) |
||||
| Dismiss Global Reports |
||||
label |
||||
input.post-check(type='checkbox', name='global_ban' value=1) |
||||
| Global Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='preserve_post' value=1) |
||||
| Show Post In Ban |
||||
label |
||||
input#ban_reason(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off') |
||||
input(type='submit', value='submit') |
||||
|
@ -1,36 +1,39 @@ |
||||
label.toggle-label Toggle Post Actions |
||||
input.toggle(type='checkbox') |
||||
.action-wrapper.togglable |
||||
.actions |
||||
h4.no-m-p Actions: |
||||
label |
||||
input.post-check(type='checkbox', name='delete' value=1) |
||||
| Delete |
||||
label |
||||
input.post-check(type='checkbox', name='delete_file' value=1) |
||||
| Delete File Only |
||||
label |
||||
input.post-check(type='checkbox', name='spoiler' value=1) |
||||
| Spoiler Images |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_board' value=1) |
||||
| Delete from IP on board |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_global' value=1) |
||||
| Delete from IP globally |
||||
label |
||||
input.post-check(type='checkbox', name='dismiss' value=1) |
||||
| Dismiss Reports |
||||
label |
||||
input.post-check(type='checkbox', name='ban' value=1) |
||||
| Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='global_ban' value=1) |
||||
| Global Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='preserve_post' value=1) |
||||
| Show Post In Ban |
||||
label |
||||
input#ban_reason(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off') |
||||
input(type='submit', value='submit') |
||||
|
||||
details.toggle-label |
||||
summary Show Post Actions |
||||
.actions |
||||
h4.no-m-p Actions: |
||||
label |
||||
input.post-check(type='checkbox', name='delete' value=1) |
||||
| Delete |
||||
label |
||||
input.post-check(type='checkbox', name='delete_file' value=1) |
||||
| Delete File Only |
||||
label |
||||
input.post-check(type='checkbox', name='spoiler' value=1) |
||||
| Spoiler Images |
||||
label |
||||
input.post-check(type='checkbox', name='global_report' value=1) |
||||
| Global Report |
||||
label |
||||
input#report(type='text', name='report_reason', placeholder='report reason' autocomplete='off') |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_board' value=1) |
||||
| Delete from IP on board |
||||
label |
||||
input.post-check(type='checkbox', name='delete_ip_global' value=1) |
||||
| Delete from IP globally |
||||
label |
||||
input.post-check(type='checkbox', name='dismiss' value=1) |
||||
| Dismiss Reports |
||||
label |
||||
input.post-check(type='checkbox', name='ban' value=1) |
||||
| Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='global_ban' value=1) |
||||
| Global Ban Poster |
||||
label |
||||
input.post-check(type='checkbox', name='preserve_post' value=1) |
||||
| Show Post In Ban |
||||
label |
||||
input#ban_reason(type='text', name='ban_reason', placeholder='ban reason' autocomplete='off') |
||||
input(type='submit', value='submit') |
||||
|
@ -1,6 +1,6 @@ |
||||
section.board-header |
||||
if board.banners.length > 0 |
||||
object.board-banner(data=`/banners?board=${board._id}` width='300' height='100') |
||||
a.no-decoration(href=`/${board._id}/index`) |
||||
object.board-banner(data=`/banners?board=${board._id}` width='300' height='100') |
||||
br |
||||
a.no-decoration(href=`/${board._id}/index.html`) |
||||
h1.board-title /#{board._id}/ - #{board.name} |
||||
h4.board-description #{board.description} |
||||
|
@ -1,2 +1,2 @@ |
||||
.footer |
||||
a(href='https://github.com/fatchan/jschan/') not lynxchan ™ |
||||
a(href='https://github.com/fatchan/jschan/') not lynxchan™ |
||||
|
@ -1,8 +1,5 @@ |
||||
nav.navbar |
||||
a.nav-item(href='/') Home |
||||
a.nav-item.right(href='/logout') Logout |
||||
if board |
||||
a.nav-item.right(href=`/login?redirect=/${board._id}/index`) Login |
||||
a.nav-item.right(href=`/${board._id}/manage`) Manage |
||||
else |
||||
a.nav-item.right(href='/login') Login |
||||
a.nav-item.right(href=`/${board ? board._id+'/' : 'global'}manage.html`) Manage |
||||
a.nav-item.right(href='/login.html') Login |
||||
|
@ -1,15 +1,15 @@ |
||||
| Page: |
||||
span |
||||
a(href=`/${board._id}/index`) [#{1}] |
||||
if page === 1 |
||||
a(href=`/${board._id}/index.html`) [#{1}] |
||||
| |
||||
- for(let i = 2; i <= pages; i++) |
||||
else |
||||
a(href=`/${board._id}/index.html`) #{1} |
||||
| |
||||
- for(let i = 2; i <= maxPage; i++) |
||||
if i === page |
||||
span |
||||
a(href=`/${board._id}/${i}`) [#{i}] |
||||
| |
||||
|
||||
a(href=`/${board._id}/${i}.html`) [#{i}] |
||||
| |
||||
else |
||||
span |
||||
a(href=`/${board._id}/${i}`) #{i} |
||||
| |
||||
a(href=`/${board._id}/${i}.html`) #{i} |
||||
| |
||||
| | |
||||
|
@ -1,45 +1,47 @@ |
||||
section.form-wrapper.flex-center.mv-10 |
||||
form.form-post(action=`/forms/board/${board._id}/post`, enctype='multipart/form-data', method='POST') |
||||
//input(type='hidden' name='_csrf' value=csrf) |
||||
input(type='hidden' name='thread' value=thread != null ? thread.postId : null) |
||||
unless board.settings.forceAnon |
||||
section.postform-row |
||||
.postform-label Name |
||||
input#name(type='text', name='name', placeholder=board.defaultName autocomplete='off' maxlength='50') |
||||
section.postform-row |
||||
.postform-label Subject |
||||
input#title(type='text', name='subject', autocomplete='off' maxlength='50') |
||||
section.postform-row |
||||
.postform-label Email |
||||
input#name(type='text', name='email', autocomplete='off' maxlength='50') |
||||
else |
||||
section.postform-row |
||||
.postform-label Sage |
||||
label.postform-style.ph-5 |
||||
input#spoiler(type='checkbox', name='email', value='sage') |
||||
| Sage |
||||
if !thread |
||||
section.form-wrapper.flex-center |
||||
details.toggle-label |
||||
summary Show Post Form |
||||
form.form-post(action=`/forms/board/${board._id}/post`, enctype='multipart/form-data', method='POST') |
||||
//input(type='hidden' name='_csrf' value=csrf) |
||||
input(type='hidden' name='thread' value=thread != null ? thread.postId : null) |
||||
unless board.settings.forceAnon |
||||
section.postform-row |
||||
.postform-label Name |
||||
input#name(type='text', name='name', placeholder=board.defaultName autocomplete='off' maxlength='50') |
||||
section.postform-row |
||||
.postform-label Subject |
||||
input#title(type='text', name='subject', autocomplete='off' maxlength='50') |
||||
section.postform-row |
||||
.postform-label Message |
||||
textarea#message(name='message', rows='5', autocomplete='off' maxlength='2000') |
||||
section.postform-row |
||||
.postform-label Files |
||||
input#file(type='file', name='file' multiple='multiple') |
||||
label.postform-style.ph-5.ml-1 |
||||
input#spoiler(type='checkbox', name='spoiler', value='true') |
||||
| Spoiler |
||||
section.postform-row |
||||
.postform-label Password |
||||
input#password(type='password', name='password', autocomplete='off' placeholder='password for deleting post later' maxlength='50') |
||||
section.postform-row |
||||
.postform-label Captcha |
||||
.postform-col |
||||
img.captcha(src='/captcha' width=200 height=80) |
||||
input#captcha(type='text', name='captcha', autocomplete='off' placeholder='captcha text' maxlength='6') |
||||
if !thread |
||||
input(type='submit', value='New Thread') |
||||
else |
||||
input(type='submit', value='Reply') |
||||
section.postform-row |
||||
.postform-label Email |
||||
input#name(type='text', name='email', autocomplete='off' maxlength='50') |
||||
else |
||||
section.postform-row |
||||
.postform-label Sage |
||||
label.postform-style.ph-5 |
||||
input#spoiler(type='checkbox', name='email', value='sage') |
||||
| Sage |
||||
if !thread |
||||
section.postform-row |
||||
.postform-label Subject |
||||
input#title(type='text', name='subject', autocomplete='off' maxlength='50') |
||||
section.postform-row |
||||
.postform-label Message |
||||
textarea#message(name='message', rows='5', autocomplete='off' maxlength='2000') |
||||
if board.settings.maxFiles !== 0 |
||||
section.postform-row |
||||
.postform-label Files |
||||
input#file(type='file', name='file' multiple='multiple') |
||||
label.postform-style.ph-5.ml-1 |
||||
input#spoiler(type='checkbox', name='spoiler', value='true') |
||||
| Spoiler |
||||
section.postform-row |
||||
.postform-label Password |
||||
input#password(type='password', name='password', autocomplete='off' placeholder='password for deleting post later' maxlength='50') |
||||
if board.settings.captcha |
||||
section.postform-row |
||||
.postform-label Captcha |
||||
.postform-col |
||||
img.captcha(src='/captcha' width=200 height=80) |
||||
input#captcha(type='text', name='captcha', autocomplete='off' placeholder='captcha text' maxlength='6') |
||||
input(type='submit', value=`New ${threads ? 'Thread' : 'Reply'}`) |
||||
//.mode Posting mode: #{threads ? 'Thread' : 'Reply'} |
||||
|
@ -1,23 +1,30 @@ |
||||
mixin catalogtile(board, post, truncate) |
||||
article(class='catalog-tile') |
||||
- const postURL = `/${board._id}/thread/${post.postId}#${post.postId}` |
||||
- const postURL = `/${board._id}/thread/${post.postId}.html#${post.postId}` |
||||
a.catalog-tile-button(href=postURL) Open Thread |
||||
if post.subject |
||||
span: a.no-decoration.post-subject(href=postURL) #{post.subject} |
||||
.catalog-tile-content |
||||
if post.files.length > 0 |
||||
.post-file-src |
||||
a(href=`/${board._id}/thread/${post.postId}#${post.postId}`) |
||||
a(href=postURL) |
||||
if post.spoiler |
||||
object(data='/img/spoiler.png' width='64' height='64') |
||||
else |
||||
object.catalog-thumb(data=`/img/thumb-${post.files[0].filename.split('.')[0]}.jpg` width='64' height='64') |
||||
header.post-info |
||||
span: a(href=postURL) ##{post.postId} |
||||
if post.sticky |
||||
img(src='/img/sticky.svg' height='12') |
||||
if post.saged |
||||
img(src='/img/saged.svg' height='12') |
||||
if post.locked |
||||
img(src='/img/locked.svg' height='12') |
||||
| |
||||
span: a(href=postURL) No.#{post.postId} |
||||
| |
||||
span Replies: #{post.replyposts} |
||||
| |
||||
span Images: #{post.replyfiles} |
||||
br |
||||
if post.message |
||||
br |
||||
blockquote.no-m-p.post-message !{post.message} |
||||
|
Loading…
Reference in new issue