medias-fakerator 1.0.0-dra → 1.0.0-dra.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/test-output/brat-animated.webp +0 -0
- package/assets/test-output/brat-video-frame-1.png +0 -0
- package/assets/test-output/brat.png +0 -0
- package/assets/test-output/fake-call-android.png +0 -0
- package/assets/test-output/fake-call-iphone.png +0 -0
- package/assets/test-output/fake-chat-iphone.png +0 -0
- package/assets/test-output/fake-story.png +0 -0
- package/assets/test-output/fake-tweet.png +0 -0
- package/assets/test-output/google-lyrics.png +0 -0
- package/assets/test-output/google-search.png +0 -0
- package/assets/test-output/instagram-profile.png +0 -0
- package/assets/test-output/meme.png +0 -0
- package/assets/test-output/quote.png +0 -0
- package/assets/test-output/tiktok-profile.png +0 -0
- package/assets/test-output/twitter-profile.png +0 -0
- package/assets/test-output/youtube-profile.png +0 -0
- package/lib/quote-generator.js +25 -10
- package/lib/utils.js +117 -48
- package/package.json +2 -2
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/quote-generator.js
CHANGED
|
@@ -2,12 +2,31 @@ const fs = require("fs");
|
|
|
2
2
|
const path = require("path");
|
|
3
3
|
const runes = require("runes");
|
|
4
4
|
const sharp = require("sharp");
|
|
5
|
-
const EmojiDbLib = require("emoji-db");
|
|
6
5
|
const { LRUCache } = require("lru-cache");
|
|
7
|
-
const emojiDb = new EmojiDbLib({ useDefaultDb: true });
|
|
8
6
|
const emojiImageByBrandPromise = require("emoji-cache");
|
|
9
7
|
const ALLOWED_MEDIA_DIRECTORY = path.resolve(__dirname, "../");
|
|
10
8
|
const { createCanvas, loadImage, registerFont } = require("canvas");
|
|
9
|
+
const emoji = require("node-emoji");
|
|
10
|
+
const emojiRegex =
|
|
11
|
+
/(\p{Extended_Pictographic}(?:\u200d\p{Extended_Pictographic})*)/gu;
|
|
12
|
+
|
|
13
|
+
function searchEmojiFromText(text) {
|
|
14
|
+
const results = [];
|
|
15
|
+
let match;
|
|
16
|
+
|
|
17
|
+
while ((match = emojiRegex.exec(text)) !== null) {
|
|
18
|
+
const emojiChar = match[0];
|
|
19
|
+
|
|
20
|
+
results.push({
|
|
21
|
+
emoji: emojiChar, // emoji unicode
|
|
22
|
+
found: emojiChar, // key untuk emoji-cache
|
|
23
|
+
offset: match.index,
|
|
24
|
+
length: emojiChar.length,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return results;
|
|
29
|
+
}
|
|
11
30
|
|
|
12
31
|
async function loadFont() {
|
|
13
32
|
const fontsDir = path.join(__dirname, "../assets/fonts");
|
|
@@ -338,10 +357,8 @@ class QuoteGenerate {
|
|
|
338
357
|
for (let i = 0; i < charStyles.length; i++) charStyles[i].push(entities);
|
|
339
358
|
}
|
|
340
359
|
const styledWords = [];
|
|
341
|
-
const emojiData =
|
|
342
|
-
|
|
343
|
-
fixCodePoints: true,
|
|
344
|
-
});
|
|
360
|
+
const emojiData = searchEmojiFromText(text);
|
|
361
|
+
|
|
345
362
|
let currentIndex = 0;
|
|
346
363
|
const processPlainText = (plainText, startOffset) => {
|
|
347
364
|
if (!plainText) return;
|
|
@@ -540,10 +557,8 @@ class QuoteGenerate {
|
|
|
540
557
|
}
|
|
541
558
|
}
|
|
542
559
|
const styledWords = [];
|
|
543
|
-
const emojiData =
|
|
544
|
-
|
|
545
|
-
fixCodePoints: true,
|
|
546
|
-
});
|
|
560
|
+
const emojiData = searchEmojiFromText(text);
|
|
561
|
+
|
|
547
562
|
let currentIndex = 0;
|
|
548
563
|
const processPlainText = (plainText, startOffset) => {
|
|
549
564
|
if (!plainText) return;
|
package/lib/utils.js
CHANGED
|
@@ -1,66 +1,115 @@
|
|
|
1
|
-
const
|
|
1
|
+
const emojiRegex =
|
|
2
|
+
/(\p{Extended_Pictographic}(?:\u200d\p{Extended_Pictographic})*)/gu;
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
function searchEmojiFromText(text) {
|
|
5
|
+
const results = [];
|
|
6
|
+
let match;
|
|
7
|
+
|
|
8
|
+
while ((match = emojiRegex.exec(text)) !== null) {
|
|
9
|
+
const emojiChar = match[0];
|
|
10
|
+
results.push({
|
|
11
|
+
found: emojiChar,
|
|
12
|
+
emoji: emojiChar,
|
|
13
|
+
offset: match.index,
|
|
14
|
+
length: emojiChar.length,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return results;
|
|
10
19
|
}
|
|
11
20
|
|
|
12
21
|
function parseTextToSegments(text, ctx, fontSize) {
|
|
13
22
|
try {
|
|
14
|
-
if (typeof text !==
|
|
15
|
-
if (!ctx || typeof ctx.measureText !==
|
|
23
|
+
if (typeof text !== "string") text = String(text);
|
|
24
|
+
if (!ctx || typeof ctx.measureText !== "function")
|
|
25
|
+
throw new TypeError("Invalid canvas context");
|
|
16
26
|
const finalSegments = [];
|
|
17
|
-
const rawLines = text.split(
|
|
27
|
+
const rawLines = text.split("\n");
|
|
18
28
|
rawLines.forEach((line, index) => {
|
|
19
|
-
if (line ===
|
|
29
|
+
if (line === "") {
|
|
20
30
|
} else {
|
|
21
31
|
const segmentsInLine = [];
|
|
22
|
-
const emojiMatches =
|
|
32
|
+
const emojiMatches = searchEmojiFromText(line);
|
|
33
|
+
|
|
23
34
|
let lastIndex = 0;
|
|
24
35
|
const processChunk = (chunk) => {
|
|
25
36
|
if (!chunk) return;
|
|
26
|
-
const tokenizerRegex =
|
|
37
|
+
const tokenizerRegex =
|
|
38
|
+
/(\*_.*?_\*|_\*.*?\*_)|(\*.*?\*)|(_.*?_)|(~.*?~)|(```.*?```)|(\s+)|([^\s*~_`]+)/g;
|
|
27
39
|
let match;
|
|
28
40
|
while ((match = tokenizerRegex.exec(chunk)) !== null) {
|
|
29
|
-
const [
|
|
41
|
+
const [
|
|
42
|
+
fullMatch,
|
|
43
|
+
boldItalic,
|
|
44
|
+
bold,
|
|
45
|
+
italic,
|
|
46
|
+
strikethrough,
|
|
47
|
+
monospace,
|
|
48
|
+
whitespace,
|
|
49
|
+
textContent,
|
|
50
|
+
] = match;
|
|
30
51
|
if (boldItalic) {
|
|
31
52
|
const content = boldItalic.slice(2, -2);
|
|
32
53
|
ctx.font = `italic bold ${fontSize}px Arial`;
|
|
33
|
-
segmentsInLine.push({
|
|
54
|
+
segmentsInLine.push({
|
|
55
|
+
type: "bolditalic",
|
|
56
|
+
content,
|
|
57
|
+
width: ctx.measureText(content).width,
|
|
58
|
+
});
|
|
34
59
|
} else if (bold) {
|
|
35
60
|
const content = bold.slice(1, -1);
|
|
36
61
|
ctx.font = `bold ${fontSize}px Arial`;
|
|
37
|
-
segmentsInLine.push({
|
|
62
|
+
segmentsInLine.push({
|
|
63
|
+
type: "bold",
|
|
64
|
+
content,
|
|
65
|
+
width: ctx.measureText(content).width,
|
|
66
|
+
});
|
|
38
67
|
} else if (italic) {
|
|
39
68
|
const content = italic.slice(1, -1);
|
|
40
69
|
ctx.font = `italic ${fontSize}px Arial`;
|
|
41
|
-
segmentsInLine.push({
|
|
70
|
+
segmentsInLine.push({
|
|
71
|
+
type: "italic",
|
|
72
|
+
content,
|
|
73
|
+
width: ctx.measureText(content).width,
|
|
74
|
+
});
|
|
42
75
|
} else if (strikethrough) {
|
|
43
76
|
const content = strikethrough.slice(1, -1);
|
|
44
77
|
ctx.font = `${fontSize}px Arial`;
|
|
45
|
-
segmentsInLine.push({
|
|
78
|
+
segmentsInLine.push({
|
|
79
|
+
type: "strikethrough",
|
|
80
|
+
content,
|
|
81
|
+
width: ctx.measureText(content).width,
|
|
82
|
+
});
|
|
46
83
|
} else if (monospace) {
|
|
47
84
|
const content = monospace.slice(3, -3);
|
|
48
85
|
ctx.font = `${fontSize}px 'Courier New', monospace`;
|
|
49
|
-
segmentsInLine.push({
|
|
86
|
+
segmentsInLine.push({
|
|
87
|
+
type: "monospace",
|
|
88
|
+
content,
|
|
89
|
+
width: ctx.measureText(content).width,
|
|
90
|
+
});
|
|
50
91
|
} else if (whitespace) {
|
|
51
92
|
ctx.font = `${fontSize}px Arial`;
|
|
52
|
-
segmentsInLine.push({
|
|
93
|
+
segmentsInLine.push({
|
|
94
|
+
type: "whitespace",
|
|
95
|
+
content: whitespace,
|
|
96
|
+
width: ctx.measureText(whitespace).width,
|
|
97
|
+
});
|
|
53
98
|
} else if (textContent) {
|
|
54
99
|
ctx.font = `${fontSize}px Arial`;
|
|
55
|
-
segmentsInLine.push({
|
|
100
|
+
segmentsInLine.push({
|
|
101
|
+
type: "text",
|
|
102
|
+
content: textContent,
|
|
103
|
+
width: ctx.measureText(textContent).width,
|
|
104
|
+
});
|
|
56
105
|
}
|
|
57
106
|
}
|
|
58
107
|
};
|
|
59
|
-
emojiMatches.forEach(emojiInfo => {
|
|
108
|
+
emojiMatches.forEach((emojiInfo) => {
|
|
60
109
|
const plainText = line.substring(lastIndex, emojiInfo.offset);
|
|
61
110
|
processChunk(plainText);
|
|
62
111
|
segmentsInLine.push({
|
|
63
|
-
type:
|
|
112
|
+
type: "emoji",
|
|
64
113
|
content: emojiInfo.found,
|
|
65
114
|
width: fontSize * 1.2,
|
|
66
115
|
});
|
|
@@ -72,13 +121,13 @@ function parseTextToSegments(text, ctx, fontSize) {
|
|
|
72
121
|
finalSegments.push(...segmentsInLine);
|
|
73
122
|
}
|
|
74
123
|
if (index < rawLines.length - 1) {
|
|
75
|
-
finalSegments.push({ type:
|
|
124
|
+
finalSegments.push({ type: "newline", content: "\n", width: 0 });
|
|
76
125
|
}
|
|
77
126
|
});
|
|
78
127
|
ctx.font = `${fontSize}px Arial`;
|
|
79
128
|
return finalSegments;
|
|
80
129
|
} catch (error) {
|
|
81
|
-
console.error(
|
|
130
|
+
console.error("Error in parseTextToSegments:", error);
|
|
82
131
|
return [];
|
|
83
132
|
}
|
|
84
133
|
}
|
|
@@ -90,50 +139,70 @@ function rebuildLinesFromSegments(segments, maxWidth, ctx, fontSize) {
|
|
|
90
139
|
let currentLineWidth = 0;
|
|
91
140
|
const getFontString = (type, size) => {
|
|
92
141
|
switch (type) {
|
|
93
|
-
case
|
|
94
|
-
|
|
95
|
-
case
|
|
96
|
-
|
|
97
|
-
|
|
142
|
+
case "bold":
|
|
143
|
+
return `bold ${size}px Arial`;
|
|
144
|
+
case "italic":
|
|
145
|
+
return `italic ${size}px Arial`;
|
|
146
|
+
case "bolditalic":
|
|
147
|
+
return `italic bold ${size}px Arial`;
|
|
148
|
+
case "monospace":
|
|
149
|
+
return `${size}px 'Courier New', monospace`;
|
|
150
|
+
default:
|
|
151
|
+
return `${size}px Arial`;
|
|
98
152
|
}
|
|
99
153
|
};
|
|
100
|
-
segments.forEach(segment => {
|
|
101
|
-
if (segment.type ===
|
|
154
|
+
segments.forEach((segment) => {
|
|
155
|
+
if (segment.type === "newline") {
|
|
102
156
|
lines.push(currentLine);
|
|
103
157
|
currentLine = [];
|
|
104
158
|
currentLineWidth = 0;
|
|
105
159
|
return;
|
|
106
160
|
}
|
|
107
|
-
if (segment.width > maxWidth && segment.type !==
|
|
161
|
+
if (segment.width > maxWidth && segment.type !== "emoji") {
|
|
108
162
|
if (currentLine.length > 0) {
|
|
109
163
|
lines.push(currentLine);
|
|
110
164
|
currentLine = [];
|
|
111
165
|
currentLineWidth = 0;
|
|
112
166
|
}
|
|
113
|
-
let tempStr =
|
|
167
|
+
let tempStr = "";
|
|
114
168
|
const originalFont = getFontString(segment.type, fontSize);
|
|
115
169
|
ctx.font = originalFont;
|
|
116
170
|
for (const char of segment.content) {
|
|
117
171
|
const measuredWidth = ctx.measureText(tempStr + char).width;
|
|
118
172
|
if (measuredWidth > maxWidth) {
|
|
119
|
-
lines.push([
|
|
173
|
+
lines.push([
|
|
174
|
+
{
|
|
175
|
+
type: segment.type,
|
|
176
|
+
content: tempStr,
|
|
177
|
+
width: ctx.measureText(tempStr).width,
|
|
178
|
+
},
|
|
179
|
+
]);
|
|
120
180
|
tempStr = char;
|
|
121
181
|
} else {
|
|
122
182
|
tempStr += char;
|
|
123
183
|
}
|
|
124
184
|
}
|
|
125
185
|
if (tempStr) {
|
|
126
|
-
currentLine = [
|
|
186
|
+
currentLine = [
|
|
187
|
+
{
|
|
188
|
+
type: segment.type,
|
|
189
|
+
content: tempStr,
|
|
190
|
+
width: ctx.measureText(tempStr).width,
|
|
191
|
+
},
|
|
192
|
+
];
|
|
127
193
|
currentLineWidth = currentLine[0].width;
|
|
128
194
|
}
|
|
129
195
|
return;
|
|
130
196
|
}
|
|
131
|
-
if (
|
|
197
|
+
if (
|
|
198
|
+
currentLineWidth + segment.width > maxWidth &&
|
|
199
|
+
currentLine.length > 0
|
|
200
|
+
) {
|
|
132
201
|
lines.push(currentLine);
|
|
133
202
|
currentLine = [segment];
|
|
134
203
|
currentLineWidth = segment.width;
|
|
135
204
|
} else {
|
|
136
|
-
if (segment.type ===
|
|
205
|
+
if (segment.type === "whitespace" && currentLine.length === 0) return;
|
|
137
206
|
currentLine.push(segment);
|
|
138
207
|
currentLineWidth += segment.width;
|
|
139
208
|
}
|
|
@@ -143,24 +212,24 @@ function rebuildLinesFromSegments(segments, maxWidth, ctx, fontSize) {
|
|
|
143
212
|
}
|
|
144
213
|
return lines;
|
|
145
214
|
} catch (error) {
|
|
146
|
-
console.error(
|
|
215
|
+
console.error("Error in rebuildLinesFromSegments:", error);
|
|
147
216
|
return [[]];
|
|
148
217
|
}
|
|
149
218
|
}
|
|
150
219
|
|
|
151
220
|
function getContrastColor(hexColor) {
|
|
152
|
-
if (!hexColor || typeof hexColor !==
|
|
153
|
-
const hex = hexColor.replace(
|
|
154
|
-
if (hex.length !== 6) return
|
|
221
|
+
if (!hexColor || typeof hexColor !== "string") return "#FFFFFF";
|
|
222
|
+
const hex = hexColor.replace("#", "");
|
|
223
|
+
if (hex.length !== 6) return "#FFFFFF";
|
|
155
224
|
const r = parseInt(hex.substring(0, 2), 16);
|
|
156
225
|
const g = parseInt(hex.substring(2, 4), 16);
|
|
157
226
|
const b = parseInt(hex.substring(4, 6), 16);
|
|
158
|
-
const luminance =
|
|
159
|
-
return luminance > 140 ?
|
|
160
|
-
}
|
|
227
|
+
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
228
|
+
return luminance > 140 ? "#000000" : "#FFFFFF";
|
|
229
|
+
}
|
|
161
230
|
|
|
162
231
|
module.exports = {
|
|
163
232
|
parseTextToSegments,
|
|
164
233
|
rebuildLinesFromSegments,
|
|
165
|
-
getContrastColor
|
|
166
|
-
};
|
|
234
|
+
getContrastColor,
|
|
235
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "medias-fakerator",
|
|
3
|
-
"version": "1.0.0-dra",
|
|
3
|
+
"version": "1.0.0-dra.0",
|
|
4
4
|
"description": "AIO Faker generator by Iruka Devs",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Iruka Devs",
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
"@ffmpeg-installer/ffmpeg": "1.1.0",
|
|
12
12
|
"canvas": "^3.2.0",
|
|
13
13
|
"emoji-cache": "^2.0.1",
|
|
14
|
-
"emoji-db": "github:Terror-Machine/emoji-db#master",
|
|
15
14
|
"fluent-ffmpeg": "^2.1.3",
|
|
16
15
|
"fs-extra": "11.3.2",
|
|
17
16
|
"lru-cache": "^11.1.0",
|
|
17
|
+
"node-emoji": "^2.2.0",
|
|
18
18
|
"runes": "^0.4.3",
|
|
19
19
|
"sharp": "^0.34.3"
|
|
20
20
|
},
|