Skip to content

Commit 0f0844b

Browse files
authored
[enhancement] nicely structured book pages (#233)
1 parent e458c78 commit 0f0844b

15 files changed

+285
-61
lines changed

_data/books/have_read.json

Lines changed: 109 additions & 44 deletions
Large diffs are not rendered by default.

_includes/assets/css/books.css

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/**
2+
* Bookshelf Styling
3+
**/
14
div.shelf {
25
display: flex;
36
flex-wrap: wrap;
@@ -34,3 +37,77 @@ div.shelvedbook:hover a,
3437
div.shelvedbook:focus a {
3538
background: none;
3639
}
40+
41+
/**
42+
* Book review stuff
43+
**/
44+
.review-container {
45+
display: grid;
46+
grid-template-columns: auto 1fr;
47+
gap: 2rem;
48+
margin-bottom: 2rem;
49+
}
50+
51+
.review-image {
52+
max-width: 100%;
53+
max-height: 500px;
54+
border: 2px solid black;
55+
}
56+
57+
@media (max-width: 850px) {
58+
.review-container {
59+
grid-template-columns: 1fr;
60+
margin-bottom: 0;
61+
}
62+
}
63+
64+
@media (max-width: 550px) {
65+
.review-container {
66+
grid-template-columns: 1fr;
67+
margin-bottom: 0;
68+
}
69+
}
70+
71+
/**
72+
* Timeline styling
73+
**/
74+
ul.timeline {
75+
list-style-type: none;
76+
padding-left: 2rem;
77+
/* margin-bottom: 0; */
78+
}
79+
80+
ul.timeline li {
81+
position: relative;
82+
margin: 0;
83+
padding-bottom: 2rem;
84+
padding-left: 2rem;
85+
}
86+
87+
ul.timeline li:after {
88+
content: "";
89+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-hidden='true' viewBox='0 0 32 32' focusable='false'%3E%3Ccircle stroke='none' fill='%23000' cx='16' cy='16' r='10'%3E%3C/circle%3E%3C/svg%3E");
90+
position: absolute;
91+
left: 0px;
92+
top: 2px;
93+
width: 16px;
94+
height: 16px;
95+
}
96+
97+
ul.timeline li:before {
98+
background-color: #000;
99+
width: 2px;
100+
content: "";
101+
position: absolute;
102+
top: 0px;
103+
bottom: 0px;
104+
left: 7px;
105+
}
106+
107+
ul.timeline li:first-child:before {
108+
top: 12px;
109+
}
110+
111+
ul.timeline li:last-child:before {
112+
height: 6px;
113+
}

_includes/bookreview.njk

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,43 @@
11
<h2>booklog: {{book.title}}</h2>
22

3-
I finished reading <a href="{{ book.link }}">{{ book.title }}</a> by {{ book.author }} on {{ book.finished | readableBookDate }}.
3+
<!-- book pic goes here --!>
4+
<div class="review-container">
5+
{% if book.situ %}
6+
<img alt="image of {{ book.title }} in-situ" src="{{ book.situ }}" class="review-image" />
7+
{% endif %}
8+
9+
{% if book.started %}
10+
<div class="review-text">
11+
<p>In {{ book.finished | bookDateYear }} I read <a href="{{ book.link }}">{{ book.title }}</a> by {{ book.author }}.</p>
12+
<h4>Timeline</h4>
13+
<ul class="timeline">
14+
<li><strong>{{ book.started | readableBookDate }}:</strong> started reading.</li>
15+
<li><strong>{{ book.finished | readableBookDate}}:</strong> finished reading.</li>
16+
</ul>
17+
{% else %}
18+
<div class="review-text">
19+
<p>In {{ book.finished | bookDateYear }} I read <a href="{{ book.link }}">{{ book.title }}</a> by {{ book.author }}.</p>
20+
<h4>Timeline</h4>
21+
<ul class="timeline">
22+
<li>...started reading at some point.</li>
23+
<li><strong>{{ book.finished | readableBookDate}}:</strong> finished reading.</li>
24+
</ul>
25+
{% endif %}
26+
27+
{% if book.review %}
28+
<h4>Review</h4>
29+
{{ book.review | safe }}
30+
<br /><br />
31+
{% endif %}
32+
</div>
33+
</div>
34+
35+
{% if book.publisher and book.pages and book.isbn %}
36+
<h4>Details</h4>
37+
<ul>
38+
<li><strong>Publisher:</strong> {{ book.publisher }}</li>
39+
<li><strong>Page Count:</strong> {{ book.pages }}</li>
40+
<li><strong>ISBN:</strong> {{ book.isbn }}</li>
41+
</ul>
42+
{% endif %}
443
<hr />

_includes/head.njk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<head>
22
<meta charset="utf-8"/>
33
{% if book.title %}
4-
{% set reviewtitle = ["Thoughts on ", book.title] | join %}
4+
{% set reviewtitle = ["Booklog: ", book.title] | join %}
55
{% endif %}
66
<title>{{ title or reviewtitle or metadata.title }}</title>
77

@@ -24,7 +24,7 @@
2424
{% set css %}
2525
{% include "assets/css/normalize.css" %}
2626
{% include "assets/css/base.css" %}
27-
{% if title === "shelf." %}
27+
{% if title === "shelf." or reviewtitle %}
2828
{% include "assets/css/books.css" %}
2929
{% endif %}
3030
{% if date %}

bin/fetch-currently-reading.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
const fs = require("fs");
2-
const { constants, fetchBooksFromRSS } = require("./shelf.js");
2+
const {
3+
constants,
4+
fetchBooksFromRSS,
5+
bookListsAreSame,
6+
saveUpdatedList,
7+
} = require("./shelf.js");
38

49
async function possiblyUpdateReadingFile(books) {
510
if (!fs.existsSync(constants.READING_FILE_PATH)) {
@@ -16,16 +21,13 @@ async function possiblyUpdateReadingFile(books) {
1621
const existingReading = await fs.promises.readFile(
1722
constants.READING_FILE_PATH,
1823
);
19-
if (JSON.stringify(books, null, 4) === existingReading.toString()) {
24+
25+
if (bookListsAreSame(JSON.parse(existingReading), books)) {
2026
console.log(`[shelflife] no change, leaving file as is.`);
2127
return;
2228
}
2329

24-
await fs.promises.writeFile(
25-
constants.READING_FILE_PATH,
26-
JSON.stringify(books, null, 4),
27-
{ encoding: "utf8" },
28-
);
30+
await saveUpdatedList(existingReading, books, constants.READ_FILE_PATH);
2931
console.log(`[shelflife] updated currently reading.`);
3032
}
3133

bin/fetch-read.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
const fs = require("fs");
2-
const { constants, fetchBooksFromRSS } = require("./shelf.js");
2+
const {
3+
constants,
4+
fetchBooksFromRSS,
5+
bookListsAreSame,
6+
saveUpdatedList,
7+
} = require("./shelf.js");
38

49
async function possiblyUpdateReadFile(books) {
510
if (!fs.existsSync(constants.READ_FILE_PATH)) {
@@ -14,16 +19,12 @@ async function possiblyUpdateReadFile(books) {
1419
}
1520

1621
const existingReading = await fs.promises.readFile(constants.READ_FILE_PATH);
17-
if (JSON.stringify(books, null, 4) === existingReading.toString()) {
22+
if (bookListsAreSame(JSON.parse(existingReading), books)) {
1823
console.log(`[shelflife] no change, leaving file as is.`);
1924
return;
2025
}
2126

22-
await fs.promises.writeFile(
23-
constants.READ_FILE_PATH,
24-
JSON.stringify(books, null, 4),
25-
{ encoding: "utf8" },
26-
);
27+
await saveUpdatedList(existingReading, books, constants.READ_FILE_PATH);
2728
console.log(`[shelflife] updated read books.`);
2829
}
2930

bin/shelf.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const fs = require("fs");
12
const { request } = require("undici");
23
const { XMLParser } = require("fast-xml-parser");
34
const parser = new XMLParser();
@@ -41,3 +42,42 @@ module.exports.fetchBooksFromRSS = async (rss) => {
4142
});
4243
return cleanBooks;
4344
};
45+
46+
module.exports.bookListsAreSame = (previousList, newlyFetchedList) => {
47+
const titleAndAuthorFilter = (book) => {
48+
return { title: book.title, author: book.author };
49+
};
50+
51+
const previousTitles = previousList.map(titleAndAuthorFilter);
52+
const newlyFetchedTitles = newlyFetchedList.map(titleAndAuthorFilter);
53+
54+
return JSON.stringify(previousTitles) === JSON.stringify(newlyFetchedTitles);
55+
};
56+
57+
const prependNewBooks = (previousList, newlyFetchedList) => {
58+
const newBooks = newlyFetchedList.filter(
59+
(bk) =>
60+
!previousList.some(
61+
(prevbk) => bk.title === prevbk.title && bk.author === prevbk.author,
62+
),
63+
);
64+
console.log("[cyberbspace] updating data files with new books:\n", newBooks);
65+
66+
previousList.unshift(...newBooks);
67+
return previousList;
68+
};
69+
70+
module.exports.saveUpdatedList = async (
71+
previousList,
72+
newlyFetchedList,
73+
file_path,
74+
) => {
75+
const newBookList = prependNewBooks(
76+
JSON.parse(previousList),
77+
newlyFetchedList,
78+
);
79+
80+
await fs.promises.writeFile(file_path, JSON.stringify(newBookList, null, 4), {
81+
encoding: "utf8",
82+
});
83+
};
547 KB
Loading

img/books/2023/the-overstory.png

606 KB
Loading

img/books/2024/living-things.png

556 KB
Loading

0 commit comments

Comments
 (0)