Compare commits
1 Commits
master
...
activitypu
Author | SHA1 | Date |
---|---|---|
|
2c3f8e55d6 |
|
@ -8,4 +8,3 @@ public/history/*.json
|
||||||
.well-known/
|
.well-known/
|
||||||
|
|
||||||
settings.json
|
settings.json
|
||||||
customHtmlAfterFooter.html
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<script>
|
|
||||||
$(document).ready(function() {
|
|
||||||
console.log('This runs after everything else is loaded.');
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "little-library",
|
"name": "little-library",
|
||||||
"version": "0.1.0",
|
"version": "0.0.0",
|
||||||
"description": "A digital give-a-book, take-a-book library for ebooks",
|
"description": "A digital give-a-book, take-a-book library for ebooks",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -12,7 +12,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "^1.18.3",
|
"body-parser": "^1.18.3",
|
||||||
"bulma": "^0.7.2",
|
"bulma": "^0.7.2",
|
||||||
"cookie-parser": "^1.4.3",
|
|
||||||
"express": "^4.16.4",
|
"express": "^4.16.4",
|
||||||
"express-fileupload": "^1.0.0",
|
"express-fileupload": "^1.0.0",
|
||||||
"fecha": "^3.0.2",
|
"fecha": "^3.0.2",
|
||||||
|
@ -24,7 +23,6 @@
|
||||||
"socket.io": "^2.2.0",
|
"socket.io": "^2.2.0",
|
||||||
"socket.io-client": "^2.2.0",
|
"socket.io-client": "^2.2.0",
|
||||||
"striptags": "^3.1.1",
|
"striptags": "^3.1.1",
|
||||||
"tinycolor2": "^1.4.1",
|
|
||||||
"unused-filename": "^1.0.0"
|
"unused-filename": "^1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,120 +1,4 @@
|
||||||
.is-clickable,
|
.is-clickable,
|
||||||
.modal-button {
|
.modal-button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bookshelf Styling */
|
|
||||||
.bookshelf {
|
|
||||||
border: 4px solid saddlebrown;
|
|
||||||
background: sienna;
|
|
||||||
}
|
|
||||||
|
|
||||||
.book-slot {
|
|
||||||
position: relative;
|
|
||||||
overflow: visible;
|
|
||||||
width: 100px;
|
|
||||||
height: 300px; /* The tallest a book could be */
|
|
||||||
border-bottom: 4px solid saddlebrown;
|
|
||||||
margin: 10px 1px -4px !important;
|
|
||||||
}
|
|
||||||
.book-slot.is-thin {
|
|
||||||
width: 80px;
|
|
||||||
}
|
|
||||||
.book-slot.is-thick {
|
|
||||||
width: 120px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.book {
|
|
||||||
position: absolute;
|
|
||||||
overflow: visible;
|
|
||||||
top: 30px;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
.book.is-short {
|
|
||||||
top: 60px;
|
|
||||||
}
|
|
||||||
.book.is-tall {
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.book .spine {
|
|
||||||
position: relative;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background: #c0ffee;
|
|
||||||
border: 1px solid #aaa;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
z-index: 1;
|
|
||||||
transition: all 0.25s;
|
|
||||||
}
|
|
||||||
.book:hover .spine {
|
|
||||||
width: 120%;
|
|
||||||
margin-left: -10%;
|
|
||||||
height: 120%;
|
|
||||||
margin-top: -20%;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
.book .spine.is-success {
|
|
||||||
-webkit-box-shadow: inset 0px 0px 99px 10px rgba(230,252,106,1);
|
|
||||||
-moz-box-shadow: inset 0px 0px 99px 10px rgba(230,252,106,1);
|
|
||||||
box-shadow: inset 0px 0px 99px 10px rgba(230,252,106,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.spine .text-container {
|
|
||||||
width: 260px;
|
|
||||||
height: 100px;
|
|
||||||
transform: rotate(90deg) translateX(82px) translateY(80px);
|
|
||||||
overflow: hidden;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
.spine .title {
|
|
||||||
font-size: 1.3em;
|
|
||||||
}
|
|
||||||
.spine .subtitle {
|
|
||||||
font-size: 1.1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.book-slot.is-thin .book .spine .text-container {
|
|
||||||
height: 80px;
|
|
||||||
transform: rotate(90deg) translateX(92px) translateY(92px);
|
|
||||||
}
|
|
||||||
.book-slot.is-thick .book .spine .text-container {
|
|
||||||
height: 120px;
|
|
||||||
transform: rotate(90deg) translateX(72px) translateY(72px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.book.is-short .spine .text-container {
|
|
||||||
width: 230px;
|
|
||||||
transform: rotate(90deg) translateX(68px) translateY(66px);
|
|
||||||
}
|
|
||||||
.book-slot.is-thin .book.is-short .spine .text-container {
|
|
||||||
transform: rotate(90deg) translateX(78px) translateY(76px);
|
|
||||||
}
|
|
||||||
.book-slot.is-thick .book.is-short .spine .text-container {
|
|
||||||
transform: rotate(90deg) translateX(58px) translateY(56px);
|
|
||||||
}
|
|
||||||
.book.is-short .spine .title {
|
|
||||||
font-size: 1.1em;
|
|
||||||
}
|
|
||||||
.book.is-short .spine .subtitle {
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
.book.is-tall .spine .text-container {
|
|
||||||
width: 290px;
|
|
||||||
transform: rotate(90deg) translateX(98px) translateY(95px);
|
|
||||||
}
|
|
||||||
.book-slot.is-thin .book.is-tall .spine .text-container {
|
|
||||||
transform: rotate(90deg) translateX(108px) translateY(106px);
|
|
||||||
}
|
|
||||||
.book-slot.is-thick .book.is-tall .spine .text-container {
|
|
||||||
transform: rotate(90deg) translateX(88px) translateY(86px);
|
|
||||||
}
|
|
||||||
.book.is-tall .spine .title {
|
|
||||||
font-size: 1.3em;
|
|
||||||
}
|
|
||||||
.book.is-tall .spine .subtitle {
|
|
||||||
font-size: 1.1em;
|
|
||||||
}
|
|
|
@ -33,12 +33,6 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#readableToggle').click(function() {
|
|
||||||
var useReadable = getCookieValue('useReadable');
|
|
||||||
document.cookie = 'useReadable=' + (useReadable !== 'yes' ? 'yes' : 'no');
|
|
||||||
window.location.reload();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.modal-background, .modal-close, .modal-card-head .delete, .modal .close').click(function() {
|
$('.modal-background, .modal-close, .modal-card-head .delete, .modal .close').click(function() {
|
||||||
$(this).closest('.modal').removeClass('is-active');
|
$(this).closest('.modal').removeClass('is-active');
|
||||||
downloadButton = undefined;
|
downloadButton = undefined;
|
||||||
|
@ -51,14 +45,9 @@ $(document).ready(function() {
|
||||||
|
|
||||||
$('.take-book').click(function() {
|
$('.take-book').click(function() {
|
||||||
var id = $(this).data('book');
|
var id = $(this).data('book');
|
||||||
var book = $('#book_' + id).find('.spine');
|
$('#book_' + id).find('.box')
|
||||||
if (book) {
|
.removeClass('box').addClass(['notification', 'is-success'])
|
||||||
book.addClass('is-success');
|
.attr('title', 'This can be downloaded until you leave this page');
|
||||||
} else {
|
|
||||||
book = $('#book_' + id).find('.box');
|
|
||||||
book.removeClass('box').addClass(['notification', 'is-success'])
|
|
||||||
}
|
|
||||||
book.attr('title', 'This can be downloaded until you leave this page');
|
|
||||||
socket.emit('take book', id);
|
socket.emit('take book', id);
|
||||||
downloadButton = this;
|
downloadButton = this;
|
||||||
$(this).addClass('is-loading');
|
$(this).addClass('is-loading');
|
||||||
|
@ -75,9 +64,4 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
$('#bookFileName').text(fileName ? fileName : 'None Selected');
|
$('#bookFileName').text(fileName ? fileName : 'None Selected');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getCookieValue(key) {
|
|
||||||
var matches = document.cookie.match('(^|;)\\s*' + key + '\\s*=\\s*([^;]+)');
|
|
||||||
return matches ? matches.pop() : ''
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
const settings = require('../../settings.json');
|
||||||
|
|
||||||
|
module.exports = function (app) {
|
||||||
|
app.server.get('/activitypub/actor', function (req, res) {
|
||||||
|
const actor = JSON.stringify({
|
||||||
|
'@context': [
|
||||||
|
'https://www.w3.org/ns/activitystreams',
|
||||||
|
'https://w3id.org/security/v1',
|
||||||
|
],
|
||||||
|
|
||||||
|
id: `https://${settings.domain}/activitypub/actor`,
|
||||||
|
type: 'Person',
|
||||||
|
preferredUsername: 'shelf',
|
||||||
|
inbox: `https://${settings.domain}/activitypub/inbox`,
|
||||||
|
outbox: `https://${settings.domain}/activitypub/outbox`,
|
||||||
|
|
||||||
|
publicKey: {
|
||||||
|
id: `https://${settings.domain}/activitypub/actor#main-key`,
|
||||||
|
owner: `https://${settings.domain}/activitypub/actor`,
|
||||||
|
publicKeyPem: settings.publicKey,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'application/activity+json');
|
||||||
|
res.send(actor);
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
const settings = require('../../settings.json');
|
||||||
|
|
||||||
|
module.exports = function (app) {
|
||||||
|
app.server.get('/.well-known/webfinger', function (req, res) {
|
||||||
|
const webfinger = JSON.stringify({
|
||||||
|
subject: `acct:shelf@${settings.domain}`,
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
rel: 'self',
|
||||||
|
type: 'application/activity+json',
|
||||||
|
href: `https://${settings.domain}/activitypub/actor`,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'application/activity+json');
|
||||||
|
res.send(webfinger);
|
||||||
|
});
|
||||||
|
}
|
|
@ -30,7 +30,7 @@ module.exports = function (app) {
|
||||||
}),
|
}),
|
||||||
footer: '<a class="button close">Close</a>',
|
footer: '<a class="button close">Close</a>',
|
||||||
});
|
});
|
||||||
return app.templater.fill('./templates/elements/book_readable.html', {
|
return app.templater.fill('./templates/elements/book.html', {
|
||||||
id,
|
id,
|
||||||
title: bookData.title,
|
title: bookData.title,
|
||||||
author: bookData.author,
|
author: bookData.author,
|
||||||
|
|
|
@ -2,30 +2,21 @@ const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const snarkdown = require('snarkdown');
|
const snarkdown = require('snarkdown');
|
||||||
const fecha = require('fecha');
|
const fecha = require('fecha');
|
||||||
const tinycolor = require('tinycolor2');
|
|
||||||
|
|
||||||
const settings = require('../settings.json');
|
|
||||||
|
|
||||||
module.exports = function (app) {
|
module.exports = function (app) {
|
||||||
app.server.get('/', (req, res) => {
|
app.server.get('/', (req, res) => {
|
||||||
const useReadable = req.cookies['useReadable'] === 'yes';
|
|
||||||
const files = fs.readdirSync(app.fileLocation).filter(fileName => fileName.includes('.json'))
|
const files = fs.readdirSync(app.fileLocation).filter(fileName => fileName.includes('.json'))
|
||||||
.map(fileName => { // Cache the file data so sorting doesn't need to re-check each file
|
.map(fileName => { // Cache the file data so sorting doesn't need to re-check each file
|
||||||
const stats = fs.statSync(path.resolve(app.fileLocation, fileName));
|
return { name: fileName, time: fs.statSync(path.resolve(app.fileLocation, fileName)).mtime.getTime() };
|
||||||
return {
|
}).sort((a, b) => a.time - b.time).map(v => v.name); // Sort from oldest to newest.
|
||||||
name: fileName,
|
|
||||||
size: stats.size / (1000 * 1000),
|
|
||||||
time: stats.mtime.getTime(),
|
|
||||||
};
|
|
||||||
}).sort((a, b) => a.time - b.time); // Sort from oldest to newest.
|
|
||||||
|
|
||||||
let books = files.map(fileDetails => {
|
let books = files.map(fileName => {
|
||||||
const bookData = JSON.parse(fs.readFileSync(path.resolve(app.fileLocation, fileDetails.name), 'utf8'));
|
const bookData = JSON.parse(fs.readFileSync(path.resolve(app.fileLocation, fileName), 'utf8'));
|
||||||
if (bookData.hasOwnProperty('fileName')) return '';
|
if (bookData.hasOwnProperty('fileName')) return '';
|
||||||
bookData.author = bookData.author ? bookData.author : '<em>author not provided</em>';
|
bookData.author = bookData.author ? bookData.author : '<em>author not provided</em>';
|
||||||
bookData.contributor = bookData.contributor ? bookData.contributor : 'Anonymous';
|
bookData.contributor = bookData.contributor ? bookData.contributor : 'Anonymous';
|
||||||
|
|
||||||
const id = fileDetails.name.replace('.json', '');
|
const id = fileName.replace('.json', '');
|
||||||
const confirmId = 'confirm_' + id;
|
const confirmId = 'confirm_' + id;
|
||||||
const added = fecha.format(new Date(bookData.added), 'hh:mm:ssA on dddd MMMM Do, YYYY');
|
const added = fecha.format(new Date(bookData.added), 'hh:mm:ssA on dddd MMMM Do, YYYY');
|
||||||
const modal = app.templater.fill('./templates/elements/modalCard.html', {
|
const modal = app.templater.fill('./templates/elements/modalCard.html', {
|
||||||
|
@ -46,20 +37,10 @@ module.exports = function (app) {
|
||||||
}),
|
}),
|
||||||
footer: '<a class="button close">Close</a> <a class="button is-success modal-button" data-modal="' + confirmId + '">Take Book</a>',
|
footer: '<a class="button close">Close</a> <a class="button is-success modal-button" data-modal="' + confirmId + '">Take Book</a>',
|
||||||
});
|
});
|
||||||
const maxSize = settings.maxFileSize > 0 ? settings.maxFileSize : 10;
|
return app.templater.fill('./templates/elements/book.html', {
|
||||||
let spineColor = tinycolor('#' + id.substr(0, 6));
|
|
||||||
if (!spineColor.isValid()) {
|
|
||||||
spineColor = tinycolor.random();
|
|
||||||
}
|
|
||||||
return app.templater.fill(useReadable ? './templates/elements/book_readable.html' : './templates/elements/book.html', {
|
|
||||||
id,
|
id,
|
||||||
title: bookData.title,
|
title: bookData.title,
|
||||||
author: bookData.author,
|
author: bookData.author,
|
||||||
thickness: (fileDetails.size > (maxSize * 0.3)) || (bookData.title.length > 28)
|
|
||||||
? 'is-thick' : (fileDetails.size < (maxSize * 0.6) ? 'is-thin' : ''),
|
|
||||||
tallness: bookData.title.length > 16 ? 'is-tall' : (bookData.title.length < 8 ? 'is-short' : ''),
|
|
||||||
spineColor: spineColor.toString(),
|
|
||||||
textColor: spineColor.isLight() ? '#000000' : '#ffffff',
|
|
||||||
fileType: bookData.fileType,
|
fileType: bookData.fileType,
|
||||||
modal,
|
modal,
|
||||||
});
|
});
|
||||||
|
@ -69,11 +50,7 @@ module.exports = function (app) {
|
||||||
books = '<div class="column"><div class="content">The shelf is empty. Would you like to <a href="/give">add a book</a>?</div></div>';
|
books = '<div class="column"><div class="content">The shelf is empty. Would you like to <a href="/give">add a book</a>?</div></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
const body = '<h2 class="title is-inline">Available Books</h2>'
|
const body = '<h2 class="title">Available Books</h2><div class="columns is-multiline">' + books + '</div>';
|
||||||
+ '<a id="readableToggle" class="button is-pulled-right">' + (!useReadable ? 'Make it readable' : 'Make it look cool') + '</a>'
|
|
||||||
+ '<div class="columns is-multiline' + (!useReadable ? ' is-gapless is-mobile bookshelf' : '') + '" style="margin-top:5px;">'
|
|
||||||
+ books
|
|
||||||
+ '</div>';
|
|
||||||
const html = app.templater.fill('./templates/htmlContainer.html', {
|
const html = app.templater.fill('./templates/htmlContainer.html', {
|
||||||
title: 'View',
|
title: 'View',
|
||||||
resourcePath: (req.url.substr(-1) === '/' ? '../' : './'),
|
resourcePath: (req.url.substr(-1) === '/' ? '../' : './'),
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const settings = require('../settings.json');
|
|
||||||
|
|
||||||
module.exports = function (app) {
|
module.exports = function (app) {
|
||||||
app.server.get('/tools', (req, res) => {
|
app.server.get('/tools', (req, res) => {
|
||||||
if (req.query.pass === settings.toolsPassword) {
|
if (req.query.pass === settings.toolsPassword) {
|
||||||
|
|
|
@ -2,7 +2,6 @@ const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const helmet = require('helmet');
|
const helmet = require('helmet');
|
||||||
const cookieParser = require('cookie-parser');
|
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
const fileUpload = require('express-fileupload');
|
const fileUpload = require('express-fileupload');
|
||||||
|
|
||||||
|
@ -10,8 +9,6 @@ const settings = require('../settings.json');
|
||||||
|
|
||||||
module.exports = function (app) {
|
module.exports = function (app) {
|
||||||
app.server.use(helmet());
|
app.server.use(helmet());
|
||||||
|
|
||||||
app.server.use(cookieParser());
|
|
||||||
|
|
||||||
app.server.use(bodyParser.json()); // support json encoded bodies
|
app.server.use(bodyParser.json()); // support json encoded bodies
|
||||||
app.server.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
|
app.server.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const settings = require('../settings.json');
|
|
||||||
|
|
||||||
module.exports = function (app) {
|
module.exports = function (app) {
|
||||||
app.server.post('/tools', (req, res) => {
|
app.server.post('/tools', (req, res) => {
|
||||||
if (req.query.pass === settings.toolsPassword) {
|
if (req.query.pass === settings.toolsPassword) {
|
||||||
|
|
|
@ -50,6 +50,11 @@ function Server () {
|
||||||
require('./routes/post_tools')(this);
|
require('./routes/post_tools')(this);
|
||||||
|
|
||||||
require('./routes/socketio')(this);
|
require('./routes/socketio')(this);
|
||||||
|
|
||||||
|
if (settings.federate) {
|
||||||
|
require('./routes/activitypub/get_webfinger')(this);
|
||||||
|
require('./routes/activitypub/get_actor')(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Server.prototype.replaceBodyWithTooManyBooksWarning = function (body) {
|
Server.prototype.replaceBodyWithTooManyBooksWarning = function (body) {
|
||||||
|
@ -181,8 +186,8 @@ Server.prototype.start = function () {
|
||||||
console.log('Started server on port ' + (process.env.PORT || settings.port));
|
console.log('Started server on port ' + (process.env.PORT || settings.port));
|
||||||
});
|
});
|
||||||
if (this.https) {
|
if (this.https) {
|
||||||
this.https.listen(settings.sslPort, () => {
|
this.https.listen(443, () => {
|
||||||
console.log('Started SSL server on port ' + settings.sslPort);
|
console.log('Started SSL server on port 443');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,11 @@
|
||||||
"allowedFormats": [".epub", ".mobi", ".pdf"],
|
"allowedFormats": [".epub", ".mobi", ".pdf"],
|
||||||
"toolsPassword": "password",
|
"toolsPassword": "password",
|
||||||
"hideVisitors": false,
|
"hideVisitors": false,
|
||||||
"sslPort": 443,
|
|
||||||
"sslPrivateKey": null,
|
"sslPrivateKey": null,
|
||||||
"sslCertificate": null,
|
"sslCertificate": null,
|
||||||
"sslCertificateAuthority": null,
|
"sslCertificateAuthority": null,
|
||||||
"forceHTTPS": false
|
"forceHTTPS": false,
|
||||||
|
"federate": true,
|
||||||
|
"domain": "localhost",
|
||||||
|
"publicKey": null
|
||||||
}
|
}
|
|
@ -26,11 +26,6 @@ module.exports = class {
|
||||||
.replace(/\{\{allowedFormats\}\}/g, settings.allowedFormats.join(','))
|
.replace(/\{\{allowedFormats\}\}/g, settings.allowedFormats.join(','))
|
||||||
.replace(/\{\{maxFileSize\}\}/g, (settings.maxFileSize > 0 ? settings.maxFileSize + 'MB' : 'no'));
|
.replace(/\{\{maxFileSize\}\}/g, (settings.maxFileSize > 0 ? settings.maxFileSize + 'MB' : 'no'));
|
||||||
|
|
||||||
if (fs.existsSync(path.resolve('./customHtmlAfterFooter.html'))) {
|
|
||||||
const customHtmlAfterFooter = fs.readFileSync(path.resolve('./customHtmlAfterFooter.html'));
|
|
||||||
filledTemplate = filledTemplate.replace(/\{\{customHtmlAfterFooter\}\}/g, customHtmlAfterFooter);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let templateVar in templateVars) {
|
for (let templateVar in templateVars) {
|
||||||
const regExp = new RegExp('\{\{' + templateVar + '\}\}', 'g')
|
const regExp = new RegExp('\{\{' + templateVar + '\}\}', 'g')
|
||||||
filledTemplate = filledTemplate.replace(regExp, templateVars[templateVar]);
|
filledTemplate = filledTemplate.replace(regExp, templateVars[templateVar]);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<div class="book-slot {{thickness}} column is-narrow is-paddingless" id="book_{{id}}">
|
<div class="column is-one-quarter" id="book_{{id}}">
|
||||||
<div class="book {{tallness}} modal-button" data-modal="{{id}}">
|
<div class="box modal-button has-text-centered" data-modal="{{id}}">
|
||||||
<div class="spine" style="background:{{spineColor}}">
|
<h2 class="title is-4">{{title}}</h2>
|
||||||
<div class="text-container">
|
<h4 class="subtitle">{{author}}</h4>
|
||||||
<h2 class="title" style="color:{{textColor}}">{{title}}</h2>
|
<div class="tags has-addons">
|
||||||
<h4 class="subtitle" style="color:{{textColor}}">{{author}}</h4>
|
<span class="tag">File Format</span>
|
||||||
</div>
|
<span class="tag is-info">{{fileType}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
<div class="column is-one-quarter" id="book_{{id}}">
|
|
||||||
<div class="box modal-button has-text-centered" data-modal="{{id}}">
|
|
||||||
<h2 class="title is-4">{{title}}</h2>
|
|
||||||
<h4 class="subtitle">{{author}}</h4>
|
|
||||||
<div class="tags has-addons">
|
|
||||||
<span class="tag">File Format</span>
|
|
||||||
<span class="tag is-info">{{fileType}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{modal}}
|
|
||||||
</div>
|
|
|
@ -86,8 +86,6 @@
|
||||||
|
|
||||||
{{modal}}
|
{{modal}}
|
||||||
<script src="{{resourcePath}}js/little-library.js"></script>
|
<script src="{{resourcePath}}js/little-library.js"></script>
|
||||||
|
|
||||||
{{customHtmlAfterFooter}}
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
13
yarn.lock
13
yarn.lock
|
@ -164,14 +164,6 @@ content-type@~1.0.4:
|
||||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||||
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
||||||
|
|
||||||
cookie-parser@^1.4.3:
|
|
||||||
version "1.4.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.3.tgz#0fe31fa19d000b95f4aadf1f53fdc2b8a203baa5"
|
|
||||||
integrity sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=
|
|
||||||
dependencies:
|
|
||||||
cookie "0.3.1"
|
|
||||||
cookie-signature "1.0.6"
|
|
||||||
|
|
||||||
cookie-signature@1.0.6:
|
cookie-signature@1.0.6:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||||
|
@ -916,11 +908,6 @@ striptags@^3.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.1.1.tgz#c8c3e7fdd6fb4bb3a32a3b752e5b5e3e38093ebd"
|
resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.1.1.tgz#c8c3e7fdd6fb4bb3a32a3b752e5b5e3e38093ebd"
|
||||||
integrity sha1-yMPn/db7S7OjKjt1LltePjgJPr0=
|
integrity sha1-yMPn/db7S7OjKjt1LltePjgJPr0=
|
||||||
|
|
||||||
tinycolor2@^1.4.1:
|
|
||||||
version "1.4.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8"
|
|
||||||
integrity sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=
|
|
||||||
|
|
||||||
to-array@0.1.4:
|
to-array@0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
|
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
|
||||||
|
|
Loading…
Reference in New Issue