Skip to content

Commit 047dd36

Browse files
authored
velog-readm-stats 1.3.0 (#32)
* feat: 문자열 escape 문제를 수정합니다 * feat: 뱃지 문자열에 따른 넓이 문제를 수정합니다 fix: 문자열 넓이 구하는 함수를 jsdom방식으로 변경합니다 fix: fix: 필요 없는 코드 제거 feat: 뱃지 문자열에 따른 넓이 문제를 수정합니다 * chore: 필요없는 dependency 제거 * chore: .vscode settings
1 parent e40a504 commit 047dd36

17 files changed

+226
-466
lines changed

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v18.12.1

.vscode/settings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"editor.tabSize": 2,
3+
"editor.formatOnSave": true,
4+
"editor.codeActionsOnSave": {
5+
"source.fixAll.eslint": true
6+
}
7+
}

api/badge.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
const createBadge = require("../src/cards/velog-badge");
1+
import createBadge from "../src/cards/velog-badge.js";
22

3-
module.exports = async (req, res) => {
3+
export default async (req, res) => {
44
const { name } = req.query;
55
res.setHeader("Content-Type", "image/svg+xml");
6+
67
try {
78
return res.send(createBadge(name));
89
} catch (e) {

api/index.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
const createCard = require("../src/cards/new-log");
2-
const createCardDark = require("../src/cards/new-log-black");
3-
const fetchPost = require("../src/fetchers/post-fetcher");
4-
const fetchReadPost = require("../src/fetchers/readpost-fetcher");
1+
import createCard from "../src/cards/new-log.js";
2+
import createCardDark from "../src/cards/new-log-black.js";
3+
import fetchPost from "../src/fetchers/post-fetcher.js";
4+
import fetchReadPost from "../src/fetchers/readpost-fetcher.js";
55

6-
module.exports = async (req, res) => {
6+
export default async (req, res) => {
77
const { name, tag, color, slug } = req.query;
88
res.setHeader("Content-Type", "image/svg+xml");
99
try {

api/list.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const createLatestPostsCard = require("../src/cards/latest-posts");
2-
const fetchPosts = require("../src/fetchers/posts-fetcher");
1+
import createLatestPostsCard from "../src/cards/latest-posts.js";
2+
import fetchPosts from "../src/fetchers/posts-fetcher.js";
33

4-
module.exports = async (req, res) => {
4+
export default async (req, res) => {
55
const { name } = req.query;
66
res.setHeader("Content-Type", "image/svg+xml");
77
try {

api/redirect.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
const fetchPost = require("../src/fetchers/post-fetcher");
1+
import fetchPost from "../src/fetchers/post-fetcher.js";
22

3-
module.exports = async (req, res) => {
3+
export default async (req, res) => {
44
const { name, tag } = req.query;
55
try {
66
const post = await fetchPost(name, tag);

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
"main": "./api/index.js",
66
"scripts": {
77
"start": "node ./api/index.js",
8-
"dev": "vercel dev",
8+
"dev:vercel": "vercel dev --debug",
99
"test": "echo \"Error: no test specified\" && exit 1"
1010
},
1111
"author": "",
1212
"license": "MIT",
1313
"dependencies": {
14-
"axios": "^0.21.4",
15-
"express": "^4.17.1",
16-
"graphql-request": "^3.4.0"
14+
"@napi-rs/canvas": "^0.1.44",
15+
"axios": "^1.5.1",
16+
"graphql-request": "^6.1.0"
1717
},
18-
"type": "commonjs"
18+
"type": "module",
19+
"devDependencies": {}
1920
}

src/cards/latest-posts.js

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { escapeHtml } from "../utils/index.js";
2+
13
const createLatestCardTitle = (username) => {
24
return `
35
<g data-testid="card-title" transform="translate(25, 35)">
@@ -9,37 +11,28 @@ const createLatestCardTitle = (username) => {
911
};
1012

1113
const createLatestCardBody = ({ posts }) => {
12-
const post_urls = posts.map(
14+
const postUrls = posts.map(
1315
(post) => `https://velog.io/@${post.user.username}/` + post.url_slug
1416
);
17+
1518
return `
1619
<g data-testid="main-card-body" transform="translate(0, 45)">
1720
<svg data-testid="lang-items" x="25" width="400" height="400" viewBox="0 0 400 400">
1821
<g transform="translate(0, 0)">
19-
<text data-testid="lang-list" class="list-style" x="5" y="20">•</text>
20-
<a href="${post_urls[0]}">
21-
<text data-testid="lang-name" x="20" y="20" class="log-title">${
22-
posts[0]?.title || "-"
23-
}</text>
24-
</a>
25-
<text data-testid="lang-list" class="list-style" x="5" y="43">•</text>
26-
<a href="${post_urls[1]}">
27-
<text data-testid="lang-name" x="20" y="43" class="log-title">${
28-
posts[1]?.title || "-"
29-
}</text>
30-
</a>
31-
<text data-testid="lang-list" class="list-style" x="5" y="66">•</text>
32-
<a href="${post_urls[2]}">
33-
<text data-testid="lang-name" x="20" y="66" class="log-title">${
34-
posts[2]?.title || "-"
35-
}</text>
36-
</a>
37-
<text data-testid="lang-list" class="list-style" x="5" y="89">•</text>
38-
<a href="${post_urls[3]}">
39-
<text data-testid="lang-name" x="20" y="89" class="log-title">${
40-
posts[3]?.title || "-"
41-
}</text>
42-
</a>
22+
${postUrls.map((url, index) => {
23+
return `
24+
<text data-testid="lang-list" class="list-style" x="5" y="${
25+
20 + index * 23
26+
}">•</text>
27+
<a href="${url}">
28+
<text data-testid="lang-name" x="20" y="${
29+
20 + index * 23
30+
}" class="log-title">${
31+
escapeHtml(posts[index]?.title) || "-"
32+
}</text>
33+
</a>
34+
`;
35+
})}
4336
</g>
4437
</svg>
4538
</g>
@@ -73,4 +66,4 @@ const createLatestCard = (data) => {
7366
`;
7467
};
7568

76-
module.exports = createLatestCard;
69+
export default createLatestCard;

src/cards/new-log-black.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { koCheck, replaceAll } = require("../utils");
1+
import { koCheck, replaceAll } from "../utils/index.js";
22

33
const createCardTitle = (username, likes) => {
44
const likeX = likes > 99 ? 365 : likes > 9 ? 370 : 380;
@@ -20,11 +20,11 @@ const createCardBody = ({ title, short_description }) => {
2020
<g data-testid="main-card-body" transform="translate(0, 45)">
2121
<svg data-testid="lang-items" x="25" width="400" height="40" viewBox="0 0 400 40">
2222
<g transform="translate(0, 0)">
23-
<text data-testid="lang-name" x="2" y="15" class="log-title">${title}</text>
24-
<text ata-testid="lang-description" x="2" y="35" class="log-description">${replaceAll(
25-
short_description,
26-
"<",
27-
"&lt;"
23+
<text data-testid="lang-name" x="2" y="15" class="log-title">${escapeHtml(
24+
title
25+
)}</text>
26+
<text ata-testid="lang-description" x="2" y="35" class="log-description">${escapeHtml(
27+
short_description
2828
)}</text>
2929
</g>
3030
</svg>
@@ -85,4 +85,4 @@ const createCardDark = (data) => {
8585
`;
8686
};
8787

88-
module.exports = createCardDark;
88+
export default createCardDark;

src/cards/new-log.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { koCheck, replaceAll } = require("../utils");
1+
import { koCheck, escapeHtml, replaceAll } from "../utils/index.js";
22

33
const createCardTitle = (username, likes) => {
44
const likeX = likes > 99 ? 365 : likes > 9 ? 370 : 380;
@@ -20,11 +20,11 @@ const createCardBody = ({ title, short_description }) => {
2020
<g data-testid="main-card-body" transform="translate(0, 45)">
2121
<svg data-testid="lang-items" x="25" width="400" height="40" viewBox="0 0 400 40">
2222
<g transform="translate(0, 0)">
23-
<text data-testid="lang-name" x="2" y="15" class="log-title">${title}</text>
24-
<text ata-testid="lang-description" x="2" y="35" class="log-description">${replaceAll(
25-
short_description,
26-
"<",
27-
"&lt;"
23+
<text data-testid="lang-name" x="2" y="15" class="log-title">${escapeHtml(
24+
title
25+
)}</text>
26+
<text ata-testid="lang-description" x="2" y="35" class="log-description">${escapeHtml(
27+
short_description
2828
)}</text>
2929
</g>
3030
</svg>
@@ -85,4 +85,4 @@ const createCard = (data) => {
8585
`;
8686
};
8787

88-
module.exports = createCard;
88+
export default createCard;

src/cards/velog-badge.js

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
1+
import { getTextWidth } from "../utils/index.js";
2+
13
const createBadge = (name) => {
2-
const size = name.length * 9;
4+
const size = getTextWidth(name, "13px --apple-system") * 1.1;
5+
6+
const rectWidth = size + 16;
7+
const rectX = 22;
8+
const containerWidth = rectWidth + rectX;
9+
310
return `
4-
<svg width="117" height="34" viewBox="0 0 117 34" fill="none" xmlns="http://www.w3.org/2000/svg">
11+
<svg width="${containerWidth}" height="25" fill="none" xmlns="http://www.w3.org/2000/svg">
512
<style>
613
.name{ fill: #ffffff; font-weight: 500; font-size: 13px;}
714
</style>
8-
<svg width="98" height="25" viewBox="0 0 98 25" fill="none" xmlns="http://www.w3.org/2000/svg">
9-
<g>
10-
<rect x="22" width="${size}" height="25" fill="#20C997"/>
11-
<text x="30" y="17" class="name">${name}</text>
15+
<g>
16+
<g fill="#20C997">
17+
<rect x="${rectX}" width="${rectWidth}" height="25" />
18+
<text x="${
19+
rectX + 8
20+
}" y="17" textLength="${size}" class="name">${name}</text>
1221
</g>
1322
<path d="M3.125 0H21.875C23.6009 0 25 1.39911 25 3.125V21.875C25 23.6009 23.6009 25 21.875 25H3.125C1.39911 25 0 23.6009 0 21.875V3.125C0 1.39911 1.39911 0 3.125 0Z" fill="#20C997"/>
1423
<path d="M18.6199 8.526V7.54163C17.9949 7.3385 17.2605 7.11975 16.4167 6.88538C15.573 6.63538 15.0027 6.51038 14.7058 6.51038C14.0496 6.51038 13.6589 6.82288 13.5339 7.44788L12.0105 16.0963C11.5261 15.4557 11.1277 14.9166 10.8152 14.4791C10.3308 13.7916 9.8855 13.0026 9.47925 12.1119C9.05737 11.2213 8.84644 10.4244 8.84644 9.72131C8.84644 9.29944 8.96362 8.9635 9.198 8.7135C9.41675 8.44788 9.83081 8.11194 10.4402 7.70569C9.81519 6.90881 9.03393 6.51038 8.09643 6.51038C7.59644 6.51038 7.18237 6.65881 6.85425 6.95569C6.5105 7.25256 6.33862 7.69006 6.33862 8.26819C6.33862 9.23694 6.74487 10.4479 7.55737 11.901C8.35425 13.3385 9.89331 15.5026 12.1746 18.3932L14.4949 18.5573L16.2761 8.526H18.6199Z" fill="white"/>
15-
</svg>
24+
</g>
1625
</svg>
1726
`;
1827
};
1928

20-
module.exports = createBadge;
29+
export default createBadge;

src/fetchers/post-fetcher.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { request } = require("../utils");
1+
import { request } from "../utils/index.js";
22

33
const fetcher = (variables) => {
44
return request({
@@ -37,4 +37,4 @@ async function fetchPost(name, tag) {
3737
}
3838
}
3939

40-
module.exports = fetchPost;
40+
export default fetchPost;

src/fetchers/posts-fetcher.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { request } = require("../utils");
1+
import { request } from "../utils/index.js";
22

33
const fetcher = (variables) => {
44
return request({
@@ -37,4 +37,4 @@ async function fetchPosts(name) {
3737
}
3838
}
3939

40-
module.exports = fetchPosts;
40+
export default fetchPosts;

src/fetchers/readpost-fetcher.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { request } = require("../utils");
1+
import { request } from "../utils/index.js";
22

33
const fetcher = (variables) => {
44
return request({
@@ -37,4 +37,4 @@ async function fetchReadPost(name, slug) {
3737
}
3838
}
3939

40-
module.exports = fetchReadPost;
40+
export default fetchReadPost;

src/utils/index.js

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,40 @@
1-
const axios = require("axios");
2-
function request(data) {
1+
import axios from "axios";
2+
import canvas from "@napi-rs/canvas";
3+
4+
export function request(data) {
35
return axios({
46
url: "https://v2.velog.io/graphql",
57
method: "post",
68
data,
79
});
810
}
9-
function koCheck(lang) {
11+
12+
export function koCheck(lang) {
1013
var check = /[-|-|-]/;
1114
return check.test(lang);
1215
}
13-
function replaceAll(str, searchStr, replaceStr) {
16+
17+
export function replaceAll(str, searchStr, replaceStr) {
1418
return str.split(searchStr).join(replaceStr);
1519
}
1620

17-
module.exports = {
18-
request,
19-
koCheck,
20-
replaceAll,
21-
};
21+
export function escapeHtml(text) {
22+
const map = {
23+
"&": "&amp;",
24+
"<": "&lt;",
25+
">": "&gt;",
26+
'"': "&quot;",
27+
"'": "&#039;",
28+
};
29+
return text.replace(/[&<>"']/g, function (m) {
30+
return map[m];
31+
});
32+
}
33+
34+
export function getTextWidth(text, font) {
35+
const ctx = canvas.createCanvas(1, 1).getContext("2d");
36+
ctx.font = font;
37+
const textMetrics = ctx.measureText(text);
38+
39+
return textMetrics.width;
40+
}

vercel.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
2-
"redirects": [
3-
{
4-
"source": "/",
5-
"destination": "https://github.com/eungyeole/velog-readme-stats"
6-
}
7-
]
2+
"redirects": [
3+
{
4+
"source": "/",
5+
"destination": "https://github.com/eungyeole/velog-readme-stats"
6+
}
7+
]
88
}

0 commit comments

Comments
 (0)