xpict 0.0.1
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/README.md +1 -0
- package/dev-scripts/generate-exports.cjs +57 -0
- package/dev-scripts/index.ts +149 -0
- package/dev-scripts/prepare-package-json.js +31 -0
- package/dist/cjs/actions.js +232 -0
- package/dist/cjs/constants.js +26 -0
- package/dist/cjs/index.js +77 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/utils/clone-image.util.ts.js +12 -0
- package/dist/cjs/utils/color.util.js +21 -0
- package/dist/cjs/utils/create-image.util.js +18 -0
- package/dist/cjs/utils/index.js +14 -0
- package/dist/cjs/utils/open-image.util.js +10 -0
- package/dist/esm/actions.js +214 -0
- package/dist/esm/constants.js +20 -0
- package/dist/esm/index.js +71 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/utils/clone-image.util.ts.js +7 -0
- package/dist/esm/utils/color.util.js +17 -0
- package/dist/esm/utils/create-image.util.js +13 -0
- package/dist/esm/utils/index.js +4 -0
- package/dist/esm/utils/open-image.util.js +5 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/tsconfig.types.tsbuildinfo +1 -0
- package/dist/types/actions.d.ts +77 -0
- package/dist/types/constants.d.ts +19 -0
- package/dist/types/index.d.ts +31 -0
- package/dist/types/utils/clone-image.util.ts.d.ts +4 -0
- package/dist/types/utils/color.util.d.ts +4 -0
- package/dist/types/utils/create-image.util.d.ts +12 -0
- package/dist/types/utils/index.d.ts +4 -0
- package/dist/types/utils/open-image.util.d.ts +3 -0
- package/fonts/Curse Casual.ttf +0 -0
- package/fonts/Poppins-Black.ttf +0 -0
- package/fonts/Poppins-BlackItalic.ttf +0 -0
- package/fonts/Poppins-Bold.ttf +0 -0
- package/fonts/Poppins-BoldItalic.ttf +0 -0
- package/fonts/Poppins-ExtraBold.ttf +0 -0
- package/fonts/Poppins-ExtraBoldItalic.ttf +0 -0
- package/fonts/Poppins-ExtraLight.ttf +0 -0
- package/fonts/Poppins-ExtraLightItalic.ttf +0 -0
- package/fonts/Poppins-Italic.ttf +0 -0
- package/fonts/Poppins-Light.ttf +0 -0
- package/fonts/Poppins-LightItalic.ttf +0 -0
- package/fonts/Poppins-Medium.ttf +0 -0
- package/fonts/Poppins-MediumItalic.ttf +0 -0
- package/fonts/Poppins-Regular.ttf +0 -0
- package/fonts/Poppins-SemiBold.ttf +0 -0
- package/fonts/Poppins-SemiBoldItalic.ttf +0 -0
- package/fonts/Poppins-Thin.ttf +0 -0
- package/fonts/Poppins-ThinItalic.ttf +0 -0
- package/package.json +78 -0
- package/src/actions.ts +390 -0
- package/src/constants.ts +30 -0
- package/src/index.ts +124 -0
- package/src/utils/clone-image.util.ts.ts +11 -0
- package/src/utils/color.util.ts +25 -0
- package/src/utils/create-image.util.ts +34 -0
- package/src/utils/index.ts +11 -0
- package/src/utils/open-image.util.ts +9 -0
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.esm.json +7 -0
- package/tsconfig.json +15 -0
- package/tsconfig.types.json +8 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Xpict: Generation of standardized images from predefined templates and functions
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const fs = require("fs")
|
|
2
|
+
const path = require("path")
|
|
3
|
+
|
|
4
|
+
const distPath = path.join(__dirname, "..", "src")
|
|
5
|
+
|
|
6
|
+
const packageJsonPath = path.join(__dirname, "..", "package.json")
|
|
7
|
+
const packageJson = require(packageJsonPath)
|
|
8
|
+
|
|
9
|
+
function generateExports(dir, base = "") {
|
|
10
|
+
const entries = fs.readdirSync(dir)
|
|
11
|
+
let exports = {}
|
|
12
|
+
|
|
13
|
+
entries.forEach(entry => {
|
|
14
|
+
const fullPath = path.join(dir, entry)
|
|
15
|
+
const stat = fs.statSync(fullPath)
|
|
16
|
+
|
|
17
|
+
if (stat.isDirectory()) {
|
|
18
|
+
exports = {
|
|
19
|
+
...exports,
|
|
20
|
+
...generateExports(fullPath, `${base}/${entry}`)
|
|
21
|
+
}
|
|
22
|
+
} else if (path.extname(entry) === ".ts") {
|
|
23
|
+
const exportPath = `${base}/${entry.replace(".ts", "")}`
|
|
24
|
+
|
|
25
|
+
const cjsPath = `./dist/cjs${exportPath}.js`
|
|
26
|
+
const esmPath = `./dist/esm${exportPath}.js`
|
|
27
|
+
const dtsPath = `./dist/types${exportPath}.d.ts`
|
|
28
|
+
|
|
29
|
+
if (exportPath !== "/index") {
|
|
30
|
+
exports[`.${exportPath.replace("/index", "")}`] = {
|
|
31
|
+
import: esmPath,
|
|
32
|
+
require: cjsPath,
|
|
33
|
+
default: esmPath,
|
|
34
|
+
types: dtsPath
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
return exports
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const generatedExports = generateExports(distPath)
|
|
44
|
+
|
|
45
|
+
packageJson.exports = {
|
|
46
|
+
".": {
|
|
47
|
+
import: "./dist/index.js",
|
|
48
|
+
require: "./dist/index.js",
|
|
49
|
+
default: "./dist/index.js",
|
|
50
|
+
types: "./dist/index.d.ts",
|
|
51
|
+
},
|
|
52
|
+
...generatedExports
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
|
|
56
|
+
|
|
57
|
+
console.log("Exports gerados e adicionados ao package.json")
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// import fakeUa from "fake-useragent"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// import { extractInnerText, ParsingModel, PuppeteerClient, PuppeteerClientAction } from "../src"
|
|
5
|
+
|
|
6
|
+
// const randomizeViewportSize: PuppeteerClientAction = {
|
|
7
|
+
// type: "beforeRequest",
|
|
8
|
+
// func: async (page) => {
|
|
9
|
+
// const width = 1920 + Math.floor(Math.random() * 100)
|
|
10
|
+
// const height = 3000 + Math.floor(Math.random() * 100)
|
|
11
|
+
|
|
12
|
+
// await page.setViewport({
|
|
13
|
+
// width: width,
|
|
14
|
+
// height: height,
|
|
15
|
+
// deviceScaleFactor: 1,
|
|
16
|
+
// hasTouch: false,
|
|
17
|
+
// isLandscape: false,
|
|
18
|
+
// isMobile: false,
|
|
19
|
+
// })
|
|
20
|
+
// }
|
|
21
|
+
// }
|
|
22
|
+
|
|
23
|
+
// const skipAssetsLoading: PuppeteerClientAction = {
|
|
24
|
+
// type: "beforeRequest",
|
|
25
|
+
// func: async (page) => {
|
|
26
|
+
// await page.setRequestInterception(true)
|
|
27
|
+
|
|
28
|
+
// page.on("request", async (request) => {
|
|
29
|
+
// const isAssets = (
|
|
30
|
+
// request.resourceType() == "stylesheet" ||
|
|
31
|
+
// request.resourceType() == "font" ||
|
|
32
|
+
// request.resourceType() == "image"
|
|
33
|
+
// )
|
|
34
|
+
|
|
35
|
+
// if (isAssets) {
|
|
36
|
+
// await request.abort()
|
|
37
|
+
// } else {
|
|
38
|
+
// await request.continue()
|
|
39
|
+
// }
|
|
40
|
+
// })
|
|
41
|
+
// }
|
|
42
|
+
// }
|
|
43
|
+
|
|
44
|
+
// const passWebdriverCheck: PuppeteerClientAction = {
|
|
45
|
+
// type: "beforeRequest",
|
|
46
|
+
// func: async (page) => {
|
|
47
|
+
// await page.evaluateOnNewDocument(() => {
|
|
48
|
+
// Object.defineProperty(navigator, "webdriver", {
|
|
49
|
+
// get: () => false
|
|
50
|
+
// })
|
|
51
|
+
// })
|
|
52
|
+
// }
|
|
53
|
+
// }
|
|
54
|
+
|
|
55
|
+
// const passChromeCheck: PuppeteerClientAction = {
|
|
56
|
+
// type: "beforeRequest",
|
|
57
|
+
// func: async (page) => {
|
|
58
|
+
// await page.evaluateOnNewDocument(() => {
|
|
59
|
+
// (window as any).chrome = {
|
|
60
|
+
// runtime: {}
|
|
61
|
+
// }
|
|
62
|
+
// })
|
|
63
|
+
// }
|
|
64
|
+
// }
|
|
65
|
+
|
|
66
|
+
// const passNotificationsCheck: PuppeteerClientAction = {
|
|
67
|
+
// type: "beforeRequest",
|
|
68
|
+
// func: async (page) => {
|
|
69
|
+
// await page.evaluateOnNewDocument(() => {
|
|
70
|
+
// const originalQuery = window.navigator.permissions.query as any
|
|
71
|
+
|
|
72
|
+
// return window.navigator.permissions.query = (parameters) => {
|
|
73
|
+
// return parameters.name === "notifications" ?
|
|
74
|
+
// Promise.resolve({ state: Notification.permission }) :
|
|
75
|
+
// originalQuery(parameters)
|
|
76
|
+
// }
|
|
77
|
+
// })
|
|
78
|
+
// }
|
|
79
|
+
// }
|
|
80
|
+
|
|
81
|
+
// const mockPlugins: PuppeteerClientAction = {
|
|
82
|
+
// type: "beforeRequest",
|
|
83
|
+
// func: async (page) => {
|
|
84
|
+
// await page.evaluateOnNewDocument(() => {
|
|
85
|
+
// Object.defineProperty(navigator, "plugins", {
|
|
86
|
+
// get: () => [1, 2, 3, 4, 5],
|
|
87
|
+
// })
|
|
88
|
+
// })
|
|
89
|
+
// }
|
|
90
|
+
// }
|
|
91
|
+
|
|
92
|
+
// const mockLanguages: PuppeteerClientAction = {
|
|
93
|
+
// type: "beforeRequest",
|
|
94
|
+
// func: async (page) => {
|
|
95
|
+
// await page.evaluateOnNewDocument(() => {
|
|
96
|
+
// Object.defineProperty(navigator, "languages", {
|
|
97
|
+
// get: () => ["en-US", "en"],
|
|
98
|
+
// })
|
|
99
|
+
// })
|
|
100
|
+
// }
|
|
101
|
+
// }
|
|
102
|
+
|
|
103
|
+
// const hideAutomationExtensions: PuppeteerClientAction = {
|
|
104
|
+
// type: "beforeRequest",
|
|
105
|
+
// func: async (page) => {
|
|
106
|
+
// await page.evaluateOnNewDocument(() => {
|
|
107
|
+
// Object.defineProperty(navigator, "webdriver", {
|
|
108
|
+
// get: () => undefined
|
|
109
|
+
// })
|
|
110
|
+
|
|
111
|
+
// delete (navigator as any).__proto__.webdriver
|
|
112
|
+
// })
|
|
113
|
+
// }
|
|
114
|
+
// }
|
|
115
|
+
|
|
116
|
+
// ;(async () => {
|
|
117
|
+
// const client = new PuppeteerClient({
|
|
118
|
+
// headless: true,
|
|
119
|
+
// args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
|
120
|
+
// userAgent: fakeUa
|
|
121
|
+
// })
|
|
122
|
+
|
|
123
|
+
// const pageParser = await client.get({
|
|
124
|
+
// url: "https://www.terabyteshop.com.br/produto/17216/monitor-gamer-superframe-vision-24pol-fullhd-165hz-hdmidp-sfv2409s",
|
|
125
|
+
// actions: [
|
|
126
|
+
// randomizeViewportSize,
|
|
127
|
+
// skipAssetsLoading,
|
|
128
|
+
// passWebdriverCheck,
|
|
129
|
+
// passChromeCheck,
|
|
130
|
+
// passNotificationsCheck,
|
|
131
|
+
// mockPlugins,
|
|
132
|
+
// mockLanguages,
|
|
133
|
+
// hideAutomationExtensions
|
|
134
|
+
// ]
|
|
135
|
+
// })
|
|
136
|
+
|
|
137
|
+
// const pageParserModel = {
|
|
138
|
+
// title: {
|
|
139
|
+
// query: "title",
|
|
140
|
+
// extractor: extractInnerText
|
|
141
|
+
// }
|
|
142
|
+
// } satisfies ParsingModel
|
|
143
|
+
|
|
144
|
+
// const pageData = pageParser.parseItem({ model: pageParserModel })
|
|
145
|
+
|
|
146
|
+
// console.log(pageData.title)
|
|
147
|
+
|
|
148
|
+
// await client.close()
|
|
149
|
+
// })();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const path = require("path")
|
|
2
|
+
const fs = require("fs")
|
|
3
|
+
|
|
4
|
+
const distDir = path.join(__dirname, "..", "dist")
|
|
5
|
+
|
|
6
|
+
function createEsmModulePackageJson() {
|
|
7
|
+
fs.readdirSync(distDir)
|
|
8
|
+
.forEach((dir) => {
|
|
9
|
+
if (dir === "esm") {
|
|
10
|
+
const packageJsonFile = path.join(distDir, dir, "/package.json")
|
|
11
|
+
|
|
12
|
+
if (!fs.existsSync(packageJsonFile)) {
|
|
13
|
+
fs.writeFileSync(
|
|
14
|
+
packageJsonFile,
|
|
15
|
+
new Uint8Array(Buffer.from('{"type": "module"}')),
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
} else if (dir == "cjs") {
|
|
19
|
+
const packageJsonFile = path.join(distDir, dir, "/package.json")
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(packageJsonFile)) {
|
|
22
|
+
fs.writeFileSync(
|
|
23
|
+
packageJsonFile,
|
|
24
|
+
new Uint8Array(Buffer.from('{"type": "commonjs"}')),
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
createEsmModulePackageJson()
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toGrayScale = toGrayScale;
|
|
4
|
+
exports.cropImage = cropImage;
|
|
5
|
+
exports.resizeImage = resizeImage;
|
|
6
|
+
exports.rotateImage = rotateImage;
|
|
7
|
+
exports.blurImage = blurImage;
|
|
8
|
+
exports.modulateSaturation = modulateSaturation;
|
|
9
|
+
exports.modulateBrightness = modulateBrightness;
|
|
10
|
+
exports.invertColors = invertColors;
|
|
11
|
+
exports.addBorder = addBorder;
|
|
12
|
+
exports.adjustContrast = adjustContrast;
|
|
13
|
+
exports.modulateOpacity = modulateOpacity;
|
|
14
|
+
exports.flipImage = flipImage;
|
|
15
|
+
exports.flopImage = flopImage;
|
|
16
|
+
exports.insertText = insertText;
|
|
17
|
+
exports.insertCircle = insertCircle;
|
|
18
|
+
exports.insertRectangle = insertRectangle;
|
|
19
|
+
exports.insertLine = insertLine;
|
|
20
|
+
const canvas_1 = require("canvas");
|
|
21
|
+
const constants_1 = require("./constants");
|
|
22
|
+
function toGrayScale(grayscale = true) {
|
|
23
|
+
return (image) => image.grayscale(grayscale);
|
|
24
|
+
}
|
|
25
|
+
function cropImage(options) {
|
|
26
|
+
return (image) => image.extract(options);
|
|
27
|
+
}
|
|
28
|
+
function resizeImage({ width, height, fit = "inside" }) {
|
|
29
|
+
return (image) => image.resize(width, height, { fit: fit });
|
|
30
|
+
}
|
|
31
|
+
function rotateImage(angle) {
|
|
32
|
+
return (image) => image.rotate(angle);
|
|
33
|
+
}
|
|
34
|
+
function blurImage(sigma = 1) {
|
|
35
|
+
return (image) => image.blur(sigma);
|
|
36
|
+
}
|
|
37
|
+
function modulateSaturation(saturation) {
|
|
38
|
+
return (image) => image.modulate({ saturation });
|
|
39
|
+
}
|
|
40
|
+
function modulateBrightness(brightness) {
|
|
41
|
+
return (image) => image.modulate({ brightness });
|
|
42
|
+
}
|
|
43
|
+
function invertColors() {
|
|
44
|
+
return (image) => image.negate();
|
|
45
|
+
}
|
|
46
|
+
function addBorder({ size, color = constants_1.colors.black }) {
|
|
47
|
+
return (image) => image.extend({
|
|
48
|
+
top: size,
|
|
49
|
+
bottom: size,
|
|
50
|
+
left: size,
|
|
51
|
+
right: size,
|
|
52
|
+
background: color
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function adjustContrast(contrast) {
|
|
56
|
+
return (image) => {
|
|
57
|
+
const factor = (259 * (contrast + 255)) / (255 * (259 - contrast));
|
|
58
|
+
return image.linear(factor, -(128 * factor) + 128);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function modulateOpacity(opacity) {
|
|
62
|
+
return (image) => image.flatten({ background: { alpha: opacity } });
|
|
63
|
+
}
|
|
64
|
+
function flipImage() {
|
|
65
|
+
return (image) => image.flip();
|
|
66
|
+
}
|
|
67
|
+
function flopImage() {
|
|
68
|
+
return (image) => image.flop();
|
|
69
|
+
}
|
|
70
|
+
function insertText({ text, font, x, y, backgroundColor = constants_1.insertTextDefaultOptions.backgroundColor, anchor = constants_1.insertTextDefaultOptions.anchor, stroke, rotation = constants_1.insertTextDefaultOptions.rotation }) {
|
|
71
|
+
return async (image) => {
|
|
72
|
+
const imageMetadata = await image.metadata();
|
|
73
|
+
const width = imageMetadata.width;
|
|
74
|
+
const height = imageMetadata.height;
|
|
75
|
+
const canvas = (0, canvas_1.createCanvas)(width, height);
|
|
76
|
+
const context = canvas.getContext("2d");
|
|
77
|
+
if (backgroundColor !== "transparent") {
|
|
78
|
+
context.fillStyle = backgroundColor;
|
|
79
|
+
context.fillRect(0, 0, width, height);
|
|
80
|
+
}
|
|
81
|
+
if (font.filePath) {
|
|
82
|
+
(0, canvas_1.registerFont)(font.filePath, { family: font.name });
|
|
83
|
+
}
|
|
84
|
+
context.font = `${font.size}px ${font.name ?? constants_1.insertTextDefaultOptions.font.name}`;
|
|
85
|
+
context.fillStyle = font.color ?? constants_1.colors.black;
|
|
86
|
+
const textMetrics = context.measureText(text);
|
|
87
|
+
const textWidth = textMetrics.width;
|
|
88
|
+
const textHeight = font.size;
|
|
89
|
+
const anchorOffsets = {
|
|
90
|
+
"top-left": {
|
|
91
|
+
x: 0,
|
|
92
|
+
y: 0
|
|
93
|
+
},
|
|
94
|
+
"top-center": {
|
|
95
|
+
x: -textWidth / 2,
|
|
96
|
+
y: 0
|
|
97
|
+
},
|
|
98
|
+
"top-right": {
|
|
99
|
+
x: -textWidth,
|
|
100
|
+
y: 0
|
|
101
|
+
},
|
|
102
|
+
"middle-left": {
|
|
103
|
+
x: 0,
|
|
104
|
+
y: -textHeight / 2
|
|
105
|
+
},
|
|
106
|
+
"middle-center": {
|
|
107
|
+
x: -textWidth / 2,
|
|
108
|
+
y: -textHeight / 2
|
|
109
|
+
},
|
|
110
|
+
"middle-right": {
|
|
111
|
+
x: -textWidth,
|
|
112
|
+
y: -textHeight / 2
|
|
113
|
+
},
|
|
114
|
+
"bottom-left": {
|
|
115
|
+
x: 0,
|
|
116
|
+
y: -textHeight
|
|
117
|
+
},
|
|
118
|
+
"bottom-center": {
|
|
119
|
+
x: -textWidth / 2,
|
|
120
|
+
y: -textHeight
|
|
121
|
+
},
|
|
122
|
+
"bottom-right": {
|
|
123
|
+
x: -textWidth,
|
|
124
|
+
y: -textHeight
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const { x: offsetX, y: offsetY } = anchorOffsets[anchor] || { x: 0, y: 0 };
|
|
128
|
+
const adjustedX = x + offsetX;
|
|
129
|
+
const adjustedY = y + offsetY;
|
|
130
|
+
const adjustedRotation = rotation ?? 0;
|
|
131
|
+
context.save();
|
|
132
|
+
context.translate(adjustedX, adjustedY);
|
|
133
|
+
context.rotate((adjustedRotation * Math.PI) / 180);
|
|
134
|
+
if (stroke) {
|
|
135
|
+
context.strokeStyle = stroke.fill;
|
|
136
|
+
context.lineWidth = stroke.width;
|
|
137
|
+
context.lineJoin = "round";
|
|
138
|
+
context.strokeText(text, 0, 0);
|
|
139
|
+
}
|
|
140
|
+
context.fillStyle = font.color ?? constants_1.colors.black;
|
|
141
|
+
context.fillText(text, 0, 0);
|
|
142
|
+
context.restore();
|
|
143
|
+
const textBuffer = canvas.toBuffer();
|
|
144
|
+
return image.composite([
|
|
145
|
+
{
|
|
146
|
+
input: textBuffer,
|
|
147
|
+
top: 0,
|
|
148
|
+
left: 0
|
|
149
|
+
}
|
|
150
|
+
]);
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function insertCircle({ x, y, radius, fill }) {
|
|
154
|
+
return async (image) => {
|
|
155
|
+
const imageMetadata = await image.metadata();
|
|
156
|
+
const width = imageMetadata.width;
|
|
157
|
+
const height = imageMetadata.height;
|
|
158
|
+
const canvas = (0, canvas_1.createCanvas)(width, height);
|
|
159
|
+
const context = canvas.getContext("2d");
|
|
160
|
+
context.beginPath();
|
|
161
|
+
context.arc(x, y, radius, 0, Math.PI * 2, true);
|
|
162
|
+
context.closePath();
|
|
163
|
+
context.fillStyle = fill;
|
|
164
|
+
context.fill();
|
|
165
|
+
const circleBuffer = canvas.toBuffer();
|
|
166
|
+
return image.composite([
|
|
167
|
+
{
|
|
168
|
+
input: circleBuffer,
|
|
169
|
+
top: 0,
|
|
170
|
+
left: 0
|
|
171
|
+
}
|
|
172
|
+
]);
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function insertRectangle({ x, y, width, height, fill, borderRadius }) {
|
|
176
|
+
return async (image) => {
|
|
177
|
+
const imageMetadata = await image.metadata();
|
|
178
|
+
const canvasWidth = imageMetadata.width;
|
|
179
|
+
const canvasHeight = imageMetadata.height;
|
|
180
|
+
const canvas = (0, canvas_1.createCanvas)(canvasWidth, canvasHeight);
|
|
181
|
+
const context = canvas.getContext("2d");
|
|
182
|
+
context.fillStyle = fill;
|
|
183
|
+
if (borderRadius && borderRadius > 0) {
|
|
184
|
+
context.beginPath();
|
|
185
|
+
context.moveTo(x + borderRadius, y);
|
|
186
|
+
context.lineTo(x + width - borderRadius, y);
|
|
187
|
+
context.arcTo(x + width, y, x + width, y + height, borderRadius);
|
|
188
|
+
context.lineTo(x + width, y + height - borderRadius);
|
|
189
|
+
context.arcTo(x + width, y + height, x, y + height, borderRadius);
|
|
190
|
+
context.lineTo(x + borderRadius, y + height);
|
|
191
|
+
context.arcTo(x, y + height, x, y, borderRadius);
|
|
192
|
+
context.lineTo(x, y + borderRadius);
|
|
193
|
+
context.arcTo(x, y, x + width, y, borderRadius);
|
|
194
|
+
context.closePath();
|
|
195
|
+
context.fill();
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
context.fillRect(x, y, width, height);
|
|
199
|
+
}
|
|
200
|
+
const rectangleBuffer = canvas.toBuffer();
|
|
201
|
+
return image.composite([
|
|
202
|
+
{
|
|
203
|
+
input: rectangleBuffer,
|
|
204
|
+
top: 0,
|
|
205
|
+
left: 0
|
|
206
|
+
}
|
|
207
|
+
]);
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function insertLine({ x1, y1, x2, y2, color, width }) {
|
|
211
|
+
return async (image) => {
|
|
212
|
+
const imageMetadata = await image.metadata();
|
|
213
|
+
const canvasWidth = imageMetadata.width;
|
|
214
|
+
const canvasHeight = imageMetadata.height;
|
|
215
|
+
const canvas = (0, canvas_1.createCanvas)(canvasWidth, canvasHeight);
|
|
216
|
+
const context = canvas.getContext("2d");
|
|
217
|
+
context.strokeStyle = color;
|
|
218
|
+
context.lineWidth = width;
|
|
219
|
+
context.beginPath();
|
|
220
|
+
context.moveTo(x1, y1);
|
|
221
|
+
context.lineTo(x2, y2);
|
|
222
|
+
context.stroke();
|
|
223
|
+
const lineBuffer = canvas.toBuffer();
|
|
224
|
+
return image.composite([
|
|
225
|
+
{
|
|
226
|
+
input: lineBuffer,
|
|
227
|
+
top: 0,
|
|
228
|
+
left: 0
|
|
229
|
+
}
|
|
230
|
+
]);
|
|
231
|
+
};
|
|
232
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.insertTextDefaultOptions = exports.createImageDefaultOptions = exports.defautltTemplateAcitonType = exports.colors = void 0;
|
|
4
|
+
const color_util_1 = require("./utils/color.util");
|
|
5
|
+
const colors = {
|
|
6
|
+
black: "#000000",
|
|
7
|
+
white: "#FFFFFF"
|
|
8
|
+
};
|
|
9
|
+
exports.colors = colors;
|
|
10
|
+
const defautltTemplateAcitonType = "beforeLayersProccess";
|
|
11
|
+
exports.defautltTemplateAcitonType = defautltTemplateAcitonType;
|
|
12
|
+
const createImageDefaultOptions = {
|
|
13
|
+
chnannels: 4,
|
|
14
|
+
fill: (0, color_util_1.rgba)(0, 0, 0, 0),
|
|
15
|
+
format: "png"
|
|
16
|
+
};
|
|
17
|
+
exports.createImageDefaultOptions = createImageDefaultOptions;
|
|
18
|
+
const insertTextDefaultOptions = {
|
|
19
|
+
font: {
|
|
20
|
+
name: "sans-serif",
|
|
21
|
+
},
|
|
22
|
+
anchor: "top-left",
|
|
23
|
+
backgroundColor: "transparent",
|
|
24
|
+
rotation: 0
|
|
25
|
+
};
|
|
26
|
+
exports.insertTextDefaultOptions = insertTextDefaultOptions;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.processImageTemplate = processImageTemplate;
|
|
7
|
+
exports.extendImageTemplate = extendImageTemplate;
|
|
8
|
+
const constants_1 = require("./constants");
|
|
9
|
+
const clone_image_util_ts_1 = __importDefault(require("./utils/clone-image.util.ts"));
|
|
10
|
+
function extractActions(actions) {
|
|
11
|
+
const actionsLayersProccess = [];
|
|
12
|
+
const actionsAfterLayersProccess = [];
|
|
13
|
+
if (!actions) {
|
|
14
|
+
actions = [];
|
|
15
|
+
}
|
|
16
|
+
for (const action of actions) {
|
|
17
|
+
const actionType = typeof action === "function" ? constants_1.defautltTemplateAcitonType : action.type;
|
|
18
|
+
const actionFunc = typeof action === "function" ? action : action.func;
|
|
19
|
+
if (actionType === "beforeLayersProccess") {
|
|
20
|
+
actionsLayersProccess.push(actionFunc);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
actionsAfterLayersProccess.push(actionFunc);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
before: actionsLayersProccess,
|
|
28
|
+
after: actionsAfterLayersProccess
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async function processImageTemplate(template) {
|
|
32
|
+
const actions = extractActions(template.actions);
|
|
33
|
+
let image = template.image;
|
|
34
|
+
for (const action of actions.before) {
|
|
35
|
+
const imageResult = await action(image);
|
|
36
|
+
image = await (0, clone_image_util_ts_1.default)(imageResult);
|
|
37
|
+
}
|
|
38
|
+
if (template.layers) {
|
|
39
|
+
const layerImages = [];
|
|
40
|
+
for (const layer of template.layers) {
|
|
41
|
+
const currentImage = await processImageTemplate(layer.template);
|
|
42
|
+
const currentImageBuffer = await currentImage.png().toBuffer();
|
|
43
|
+
layerImages.push({
|
|
44
|
+
input: currentImageBuffer,
|
|
45
|
+
top: layer.y,
|
|
46
|
+
left: layer.x
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
image = image.composite(layerImages);
|
|
50
|
+
}
|
|
51
|
+
for (const action of actions.after) {
|
|
52
|
+
const imageResult = await action(image);
|
|
53
|
+
image = await (0, clone_image_util_ts_1.default)(imageResult);
|
|
54
|
+
}
|
|
55
|
+
return image;
|
|
56
|
+
}
|
|
57
|
+
function extendImageTemplate(template, extendTemplate) {
|
|
58
|
+
const actions = [];
|
|
59
|
+
const layers = [];
|
|
60
|
+
if (template.layers) {
|
|
61
|
+
layers.push(...template.layers);
|
|
62
|
+
}
|
|
63
|
+
if (extendTemplate.layers) {
|
|
64
|
+
layers.push(...extendTemplate.layers);
|
|
65
|
+
}
|
|
66
|
+
if (template.actions) {
|
|
67
|
+
actions.push(...template.actions);
|
|
68
|
+
}
|
|
69
|
+
if (extendTemplate.actions) {
|
|
70
|
+
actions.push(...extendTemplate.actions);
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
image: template.image,
|
|
74
|
+
actions: actions,
|
|
75
|
+
layers: layers
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "commonjs"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const sharp_1 = __importDefault(require("sharp"));
|
|
7
|
+
async function cloneImage(image) {
|
|
8
|
+
const imageBuffer = await image.toBuffer();
|
|
9
|
+
const clonedImage = (0, sharp_1.default)(imageBuffer);
|
|
10
|
+
return clonedImage;
|
|
11
|
+
}
|
|
12
|
+
exports.default = cloneImage;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rgb = rgb;
|
|
4
|
+
exports.rgba = rgba;
|
|
5
|
+
exports.hex = hex;
|
|
6
|
+
function componentToHex(component) {
|
|
7
|
+
const hex = component.toString(16);
|
|
8
|
+
return hex.padStart(2, "0");
|
|
9
|
+
}
|
|
10
|
+
function rgb(red, green, blue) {
|
|
11
|
+
return `#${componentToHex(red)}${componentToHex(green)}${componentToHex(blue)}`;
|
|
12
|
+
}
|
|
13
|
+
function rgba(red, green, blue, alpha) {
|
|
14
|
+
const alphaHex = componentToHex(Math.round(alpha * 255));
|
|
15
|
+
return `#${componentToHex(red)}${componentToHex(green)}${componentToHex(blue)}${alphaHex}`;
|
|
16
|
+
}
|
|
17
|
+
function hex(value) {
|
|
18
|
+
const hexadecimalValue = value.toString(16);
|
|
19
|
+
const fromatedHexadecimal = `#${hexadecimalValue.padStart(6, "0")}`;
|
|
20
|
+
return fromatedHexadecimal;
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const sharp_1 = __importDefault(require("sharp"));
|
|
7
|
+
const constants_1 = require("../constants");
|
|
8
|
+
function createImage({ width, height, fill = constants_1.createImageDefaultOptions.fill, channels = constants_1.createImageDefaultOptions.chnannels, format = constants_1.createImageDefaultOptions.format, }) {
|
|
9
|
+
return (0, sharp_1.default)({
|
|
10
|
+
create: {
|
|
11
|
+
width: width,
|
|
12
|
+
height: height,
|
|
13
|
+
channels: channels,
|
|
14
|
+
background: fill,
|
|
15
|
+
},
|
|
16
|
+
})[format]();
|
|
17
|
+
}
|
|
18
|
+
exports.default = createImage;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.hex = exports.rgb = exports.rgba = exports.openImage = exports.createImage = void 0;
|
|
7
|
+
const create_image_util_1 = __importDefault(require("./create-image.util"));
|
|
8
|
+
exports.createImage = create_image_util_1.default;
|
|
9
|
+
const color_util_1 = require("./color.util");
|
|
10
|
+
Object.defineProperty(exports, "rgb", { enumerable: true, get: function () { return color_util_1.rgb; } });
|
|
11
|
+
Object.defineProperty(exports, "rgba", { enumerable: true, get: function () { return color_util_1.rgba; } });
|
|
12
|
+
Object.defineProperty(exports, "hex", { enumerable: true, get: function () { return color_util_1.hex; } });
|
|
13
|
+
const open_image_util_1 = __importDefault(require("./open-image.util"));
|
|
14
|
+
exports.openImage = open_image_util_1.default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const sharp_1 = __importDefault(require("sharp"));
|
|
7
|
+
function openImage(filePath) {
|
|
8
|
+
return (0, sharp_1.default)(filePath);
|
|
9
|
+
}
|
|
10
|
+
exports.default = openImage;
|