twitter-snap 0.0.2 → 0.0.4
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/dist/cli.d.ts +1 -0
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
- package/src/cli.ts +0 -30
- package/src/core/twitterSnap.ts +0 -183
- package/src/index.tsx +0 -12
- package/src/style/normal.tsx +0 -84
- package/src/utils/example.ts +0 -8
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
"use strict";
|
|
2
3
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
4
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -38,7 +39,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
38
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
40
|
var twitterSnap_1 = require("./core/twitterSnap");
|
|
40
41
|
var commander_1 = require("commander");
|
|
41
|
-
var version = "0.0.
|
|
42
|
+
var version = "0.0.4";
|
|
42
43
|
var font = "assets/NotoSansCJKjp-Regular.otf";
|
|
43
44
|
var boldFont = "assets/NotoSansCJKjp-Bold.otf";
|
|
44
45
|
var program = new commander_1.Command();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,kDAAiD;AACjD,uCAAoC;AAEpC,IAAM,OAAO,GAAG,OAAO,CAAC;AACxB,IAAM,IAAI,GAAG,kCAAkC,CAAC;AAChD,IAAM,QAAQ,GAAG,+BAA+B,CAAC;AAEjD,IAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAC9B,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9C,OAAO;KACJ,QAAQ,CAAC,UAAU,EAAE,uBAAuB,CAAC;KAC7C,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,EAAE,YAAY,CAAC;KAC/D,MAAM,CAAC,sBAAsB,EAAE,aAAa,EAAE,KAAK,CAAC;KACpD,MAAM,CAAC,uBAAuB,EAAE,cAAc,EAAE,KAAK,CAAC;KACtD,MAAM,CAAC,eAAe,EAAE,WAAW,EAAE,IAAI,CAAC;KAC1C,MAAM,CAAC,oBAAoB,EAAE,gBAAgB,EAAE,QAAQ,CAAC;KACxD,MAAM,CAAC,UAAO,IAAI,EAAE,EAAyC;QAAvC,MAAM,YAAA,EAAE,KAAK,WAAA,EAAE,MAAM,YAAA,EAAE,IAAI,UAAA,EAAE,QAAQ,cAAA;;;;;;oBACpD,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;oBAChD,WAAW,GAAG,IAAI,yBAAW,CAAC;wBAClC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;wBACtB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;wBACxB,IAAI,EAAE,IAAI;wBACV,QAAQ,EAAE,QAAQ;qBACnB,CAAC,CAAC;oBACY,qBAAM,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,EAAA;;oBAArC,MAAM,GAAG,SAA4B;oBAC3C,qBAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAA;;oBAAzB,SAAyB,CAAC;oBAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;;;;CACjB,CAAC,CAAC;AACL,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "twitter-snap",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev:cli": "npx tsx src/cli.ts 1720560121485595093",
|
|
6
6
|
"dev:style": "react-scripts start",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"build": "npx tsc && npx cpx2 assets/* dist/assets"
|
|
9
9
|
},
|
|
10
10
|
"bin": {
|
|
11
|
-
"twitter-snap": "
|
|
11
|
+
"twitter-snap": "dist/bin.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@napi-rs/image": "^1.7.0",
|
package/src/cli.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { TwitterSnap } from "./core/twitterSnap";
|
|
2
|
-
import { Command } from "commander";
|
|
3
|
-
|
|
4
|
-
const version = "0.0.2";
|
|
5
|
-
const font = "assets/NotoSansCJKjp-Regular.otf";
|
|
6
|
-
const boldFont = "assets/NotoSansCJKjp-Bold.otf";
|
|
7
|
-
|
|
8
|
-
const program = new Command();
|
|
9
|
-
program.name("twitter-snap").version(version);
|
|
10
|
-
|
|
11
|
-
program
|
|
12
|
-
.argument("<string>", "tweet url or tweet id")
|
|
13
|
-
.option("-o, --output <path>", "output file path", "output.png")
|
|
14
|
-
.option("-w, --width <number>", "image width", "600")
|
|
15
|
-
.option("-h, --height <number>", "image height", "400")
|
|
16
|
-
.option("--font <path>", "font path", font)
|
|
17
|
-
.option("--bold-font <path>", "bold font path", boldFont)
|
|
18
|
-
.action(async (text, { output, width, height, font, boldFont }) => {
|
|
19
|
-
const id = isNaN(text) ? text.split("/").pop() : text;
|
|
20
|
-
const twitterSnap = new TwitterSnap({
|
|
21
|
-
width: parseInt(width),
|
|
22
|
-
height: parseInt(height),
|
|
23
|
-
font: font,
|
|
24
|
-
boldFont: boldFont,
|
|
25
|
-
});
|
|
26
|
-
const writer = await twitterSnap.render(id);
|
|
27
|
-
await writer.save(output);
|
|
28
|
-
process.exit(0);
|
|
29
|
-
});
|
|
30
|
-
program.parse(process.argv);
|
package/src/core/twitterSnap.ts
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import satori, { SatoriOptions } from "satori";
|
|
2
|
-
import { Transformer } from "@napi-rs/image";
|
|
3
|
-
import Normal from "./../style/normal";
|
|
4
|
-
import * as fs from "fs";
|
|
5
|
-
|
|
6
|
-
import { TwitterOpenApi } from "twitter-openapi-typescript";
|
|
7
|
-
|
|
8
|
-
export type StyleComponent = (props: {
|
|
9
|
-
name: string;
|
|
10
|
-
id: string;
|
|
11
|
-
icon: string;
|
|
12
|
-
text: string;
|
|
13
|
-
}) => React.ReactElement;
|
|
14
|
-
|
|
15
|
-
type TwitterSnapParams = {
|
|
16
|
-
width: number;
|
|
17
|
-
height: number;
|
|
18
|
-
font: string;
|
|
19
|
-
boldFont: string;
|
|
20
|
-
lang?: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export class TwitterSnap {
|
|
24
|
-
width!: number;
|
|
25
|
-
height!: number;
|
|
26
|
-
option!: SatoriOptions;
|
|
27
|
-
|
|
28
|
-
constructor(param: TwitterSnapParams) {
|
|
29
|
-
this.width = param.width;
|
|
30
|
-
this.height = param.height;
|
|
31
|
-
|
|
32
|
-
this.option = {
|
|
33
|
-
width: this.width,
|
|
34
|
-
height: this.height,
|
|
35
|
-
fonts: [
|
|
36
|
-
{
|
|
37
|
-
name: "Regular",
|
|
38
|
-
data: fs.readFileSync(param.font),
|
|
39
|
-
weight: 400,
|
|
40
|
-
style: "normal",
|
|
41
|
-
lang: param.lang,
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
name: "Bold",
|
|
45
|
-
data: fs.readFileSync(param.boldFont),
|
|
46
|
-
weight: 700,
|
|
47
|
-
style: "normal",
|
|
48
|
-
lang: param.lang,
|
|
49
|
-
},
|
|
50
|
-
],
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
render = async (id: string) => {
|
|
55
|
-
const client = await new TwitterOpenApi().getGuestClient();
|
|
56
|
-
const tweet = await client.getDefaultApi().getTweetResultByRestId({
|
|
57
|
-
tweetId: id,
|
|
58
|
-
});
|
|
59
|
-
const data = {
|
|
60
|
-
name: tweet!.data!.user!.legacy.name,
|
|
61
|
-
id: tweet!.data!.user!.legacy.screenName,
|
|
62
|
-
icon: tweet.data!.user.legacy.profileImageUrlHttps,
|
|
63
|
-
text: tweet.data!.tweet.legacy!.fullText,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const svg = await satori(Normal(data), this.option);
|
|
67
|
-
return new TwitterSnapWriter({
|
|
68
|
-
width: this.width,
|
|
69
|
-
height: this.height,
|
|
70
|
-
svg: svg,
|
|
71
|
-
});
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
type TwitterSnapWriterParams = {
|
|
76
|
-
width: number;
|
|
77
|
-
height: number;
|
|
78
|
-
svg: string;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
export class TwitterSnapWriter {
|
|
82
|
-
width!: number;
|
|
83
|
-
height!: number;
|
|
84
|
-
data!: string;
|
|
85
|
-
_trasformer: Transformer | undefined;
|
|
86
|
-
|
|
87
|
-
constructor(param: TwitterSnapWriterParams) {
|
|
88
|
-
this.width = param.width;
|
|
89
|
-
this.height = param.height;
|
|
90
|
-
this.data = param.svg;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
get trasformer() {
|
|
94
|
-
if (!this._trasformer) {
|
|
95
|
-
this._trasformer = Transformer.fromSvg(this.data);
|
|
96
|
-
this._trasformer.crop(0, 0, this.width, this.height);
|
|
97
|
-
}
|
|
98
|
-
return this._trasformer;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
save = async (output: string) => {
|
|
102
|
-
const ext = output.split(".").pop();
|
|
103
|
-
const exts: {
|
|
104
|
-
[key: string]: (output: string) => Promise<void>;
|
|
105
|
-
} = {
|
|
106
|
-
raw: this.raw,
|
|
107
|
-
svg: this.svg,
|
|
108
|
-
png: this.png,
|
|
109
|
-
jpeg: this.jpeg,
|
|
110
|
-
jpg: this.jpeg,
|
|
111
|
-
jpe: this.jpeg,
|
|
112
|
-
bmp: this.bmp,
|
|
113
|
-
dib: this.bmp,
|
|
114
|
-
rle: this.bmp,
|
|
115
|
-
"2bp": this.bmp,
|
|
116
|
-
"2pbb": this.bmp,
|
|
117
|
-
ico: this.ico,
|
|
118
|
-
cur: this.ico,
|
|
119
|
-
tif: this.tiff,
|
|
120
|
-
webp: this.webp,
|
|
121
|
-
avif: this.avif,
|
|
122
|
-
pnm: this.pnm,
|
|
123
|
-
tga: this.tga,
|
|
124
|
-
tpic: this.tga,
|
|
125
|
-
ff: this.farbfeld,
|
|
126
|
-
};
|
|
127
|
-
const method = exts[ext!];
|
|
128
|
-
if (!method) {
|
|
129
|
-
throw new Error("Unsupported file format");
|
|
130
|
-
}
|
|
131
|
-
await method(output);
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
svg = async (output: string) => {
|
|
135
|
-
await fs.promises.writeFile(output, this.data);
|
|
136
|
-
};
|
|
137
|
-
raw = async (output: string) => {
|
|
138
|
-
await fs.promises.writeFile(output, this.data);
|
|
139
|
-
};
|
|
140
|
-
jpeg = async (output: string) => {
|
|
141
|
-
const data = await this.trasformer.jpeg();
|
|
142
|
-
await fs.promises.writeFile(output, data);
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
png = async (output: string) => {
|
|
146
|
-
const data = await this.trasformer.png();
|
|
147
|
-
await fs.promises.writeFile(output, data);
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
bmp = async (output: string) => {
|
|
151
|
-
const data = await this.trasformer.bmp();
|
|
152
|
-
await fs.promises.writeFile(output, data);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
ico = async (output: string) => {
|
|
156
|
-
const data = await this.trasformer.ico();
|
|
157
|
-
await fs.promises.writeFile(output, data);
|
|
158
|
-
};
|
|
159
|
-
tiff = async (output: string) => {
|
|
160
|
-
const data = await this.trasformer.tiff();
|
|
161
|
-
await fs.promises.writeFile(output, data);
|
|
162
|
-
};
|
|
163
|
-
webp = async (output: string) => {
|
|
164
|
-
const data = await this.trasformer.webp();
|
|
165
|
-
await fs.promises.writeFile(output, data);
|
|
166
|
-
};
|
|
167
|
-
avif = async (output: string) => {
|
|
168
|
-
const data = await this.trasformer.avif();
|
|
169
|
-
await fs.promises.writeFile(output, data);
|
|
170
|
-
};
|
|
171
|
-
pnm = async (output: string) => {
|
|
172
|
-
const data = await this.trasformer.pnm();
|
|
173
|
-
await fs.promises.writeFile(output, data);
|
|
174
|
-
};
|
|
175
|
-
tga = async (output: string) => {
|
|
176
|
-
const data = await this.trasformer.tga();
|
|
177
|
-
await fs.promises.writeFile(output, data);
|
|
178
|
-
};
|
|
179
|
-
farbfeld = async (output: string) => {
|
|
180
|
-
const data = await this.trasformer.farbfeld();
|
|
181
|
-
await fs.promises.writeFile(output, data);
|
|
182
|
-
};
|
|
183
|
-
}
|
package/src/index.tsx
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import ReactDOM from "react-dom/client";
|
|
3
|
-
import Normal from "./style/normal";
|
|
4
|
-
import example from "./utils/example";
|
|
5
|
-
|
|
6
|
-
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
|
7
|
-
<React.StrictMode>
|
|
8
|
-
<div style={{ width: "100svw", height: "100vh" }}>
|
|
9
|
-
<Normal {...example} />
|
|
10
|
-
</div>
|
|
11
|
-
</React.StrictMode>
|
|
12
|
-
);
|
package/src/style/normal.tsx
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { StyleComponent } from "./../core/twitterSnap";
|
|
2
|
-
|
|
3
|
-
const Normal: StyleComponent = ({ name, id, icon, text }) => {
|
|
4
|
-
return (
|
|
5
|
-
<div
|
|
6
|
-
style={{
|
|
7
|
-
display: "flex",
|
|
8
|
-
justifyContent: "center",
|
|
9
|
-
alignItems: "center",
|
|
10
|
-
width: "100%",
|
|
11
|
-
height: "100%",
|
|
12
|
-
background:
|
|
13
|
-
"linear-gradient(-45deg, #0077F2ee 0%, #1DA1F2ee 50%,#4CFFE2ee 100%)",
|
|
14
|
-
}}
|
|
15
|
-
>
|
|
16
|
-
<div
|
|
17
|
-
style={{
|
|
18
|
-
width: "550px",
|
|
19
|
-
background: "white",
|
|
20
|
-
display: "flex",
|
|
21
|
-
flexDirection: "column",
|
|
22
|
-
borderRadius: "10px",
|
|
23
|
-
padding: "12px",
|
|
24
|
-
}}
|
|
25
|
-
>
|
|
26
|
-
<div
|
|
27
|
-
style={{
|
|
28
|
-
display: "flex",
|
|
29
|
-
}}
|
|
30
|
-
>
|
|
31
|
-
<img
|
|
32
|
-
alt="icon"
|
|
33
|
-
style={{
|
|
34
|
-
width: "40px",
|
|
35
|
-
height: "40px",
|
|
36
|
-
borderRadius: "50%",
|
|
37
|
-
marginRight: "12px",
|
|
38
|
-
}}
|
|
39
|
-
src={icon}
|
|
40
|
-
/>
|
|
41
|
-
<div
|
|
42
|
-
style={{
|
|
43
|
-
display: "flex",
|
|
44
|
-
flexDirection: "column",
|
|
45
|
-
}}
|
|
46
|
-
>
|
|
47
|
-
<p
|
|
48
|
-
style={{
|
|
49
|
-
fontSize: "15px",
|
|
50
|
-
fontWeight: "bold",
|
|
51
|
-
margin: "0px",
|
|
52
|
-
}}
|
|
53
|
-
>
|
|
54
|
-
{name}
|
|
55
|
-
</p>
|
|
56
|
-
<p
|
|
57
|
-
style={{
|
|
58
|
-
fontSize: "15px",
|
|
59
|
-
margin: "0px",
|
|
60
|
-
color: "#536471",
|
|
61
|
-
}}
|
|
62
|
-
>
|
|
63
|
-
{id}
|
|
64
|
-
</p>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
{text.split("\n").map((t, key) => (
|
|
68
|
-
<p
|
|
69
|
-
key={key}
|
|
70
|
-
style={{
|
|
71
|
-
fontSize: "17px",
|
|
72
|
-
margin: "0px",
|
|
73
|
-
marginTop: "12px",
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
76
|
-
{t}
|
|
77
|
-
</p>
|
|
78
|
-
))}
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
export default Normal;
|