Skip to content

Commit ef22496

Browse files
committed
Initial commit
0 parents  commit ef22496

File tree

4 files changed

+670
-0
lines changed

4 files changed

+670
-0
lines changed

README.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# reddit-comment-renderer
2+
3+
Renders a Reddit comment as a png file.
4+
5+
# Usage
6+
```javascript
7+
render("AWildSketchAppeared" /* Username */, "Lorem ipsum dolor sit amet" /* Comment */, "16.5k" /* Upvotes */, "8h" /* Timestamp */, 1920 /* Image Width */, 1080 /* Image Height */, 3 /* "Zoom" */, "out.png" /* Output File */);
8+
```
9+
10+
### Expect future updates, planning on adding:
11+
- dark mode + custom colors
12+
- desktop theme (currently mobile theme)
13+
- replies to comments

index.js

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
const { createCanvas, registerFont } = require("canvas");
2+
const fs = require("fs");
3+
4+
module.exports = (username, comment, upvotes, timestamp="1h", width=1920, height=1080, zoom=3, output="out.png") => {
5+
const canvas = createCanvas(width, height);
6+
const ctx = canvas.getContext("2d");
7+
const separator = "•"
8+
9+
registerFont("./fonts/rfont.ttf", { family: "rfont" });
10+
11+
var zoom = 3.8;
12+
var fontSize = 13 * zoom;
13+
14+
// White background
15+
ctx.fillStyle = "#ffffff";
16+
ctx.fillRect(0, 0, width, height);
17+
18+
// Username
19+
var leftPadding = 10 * zoom;
20+
var topPadding = fontSize + 7 * zoom;
21+
ctx.font = fontSize + "px Helvetica";
22+
ctx.fillStyle = "#a5a4a4";
23+
ctx.fillText(username, leftPadding, topPadding)
24+
25+
// Separator
26+
leftPadding += ctx.measureText(username).width + 4 * zoom;
27+
ctx.fillStyle = "#efefed";
28+
ctx.fillText(separator, leftPadding, topPadding);
29+
30+
// Timestamp
31+
leftPadding += ctx.measureText(separator).width + 4 * zoom;
32+
ctx.fillStyle = "#a5a4a4";
33+
ctx.fillText(timestamp, leftPadding, topPadding);
34+
35+
// Comment
36+
ctx.fillStyle = "#222222";
37+
leftPadding = 10 * zoom;
38+
topPadding += 7 * zoom;
39+
var lines = getLines(comment);
40+
for (let line of lines) {
41+
topPadding += fontSize;
42+
ctx.fillText(line, leftPadding, topPadding);
43+
}
44+
45+
// Downvote
46+
47+
ctx.font = 24 * zoom + "px rfont";
48+
ctx.fillStyle = "#ccccca";
49+
topPadding += fontSize + 18 * zoom;
50+
leftPadding = width - 8 * zoom - ctx.measureText("\uF115").width;
51+
ctx.fillText("\uF115", leftPadding, topPadding + 2.3 * zoom); // not sure why 2.3 * zoom is needed but it is
52+
53+
// Upvotes
54+
ctx.font = 14 * zoom + "px rfont";
55+
leftPadding -= ctx.measureText(upvotes).width;
56+
ctx.fillText(upvotes, leftPadding, topPadding - 7 * zoom + 2.3 * zoom); // not sure about why - 7 * zoom is needed here ALSO not sure why 2.3 * zoom is needed but it is
57+
58+
// Upvote
59+
ctx.font = 24 * zoom + "px rfont";
60+
leftPadding -= ctx.measureText("\uF16E").width;
61+
ctx.fillText("\uF16E", leftPadding, topPadding + 2.3 * zoom); // not sure why 2.3 * zoom is needed but it is
62+
63+
// Divider
64+
leftPadding -= 8 * zoom;
65+
ctx.lineWidth = 1 * zoom;
66+
ctx.strokeStyle = "#efefed";
67+
ctx.beginPath();
68+
ctx.moveTo(leftPadding, topPadding - 20 * zoom);
69+
ctx.lineTo(leftPadding, topPadding);
70+
ctx.stroke();
71+
72+
// More
73+
leftPadding -= 9 * zoom + ctx.measureText("\uF159").width;
74+
ctx.font = 20 * zoom + "px rfont";
75+
ctx.fillText("\uF159", leftPadding, topPadding);
76+
77+
// Reply
78+
leftPadding -= 8 * zoom + ctx.measureText("\uF151").width;
79+
ctx.fillText("\uF151", leftPadding, topPadding);
80+
81+
function getLines(text) {
82+
var words = text.split(" ");
83+
var lines = [];
84+
var line = "";
85+
86+
for (var i = 0; i < words.length; i++) {
87+
var word = words[i];
88+
var testLine = line + word + " ";
89+
var testWidth = ctx.measureText(testLine).width;
90+
if (testWidth > width - 8 * zoom && i) {
91+
92+
/* This entire isolated chunk is for wrapping when the entire word is longer than the width.
93+
* There is probably a much more efficient way to do this. */
94+
if (line.match(/ /g).length === 1) {
95+
var characters = line.split("");
96+
line = "";
97+
for (let character of characters) {
98+
testLine = line + character //+ " ";
99+
testWidth = ctx.measureText(testLine).width;
100+
if (testWidth > width - 8 * zoom) {
101+
lines.push(line);
102+
line = character;
103+
} else {
104+
line = testLine;
105+
}
106+
}
107+
if (line) lines.push(line + " ");
108+
line = word + " ";
109+
} else {
110+
lines.push(line);
111+
line = word + " ";
112+
}
113+
114+
} else {
115+
line = testLine;
116+
}
117+
}
118+
if (line) lines.push(line);
119+
return lines;
120+
}
121+
122+
fs.writeFileSync(output, canvas.toDataURL().replace("data:image/png;base64,", ""), "base64");
123+
}

0 commit comments

Comments
 (0)