🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

cherry-box

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cherry-box - npm Package Compare versions

Comparing version
1.2.3
to
1.3.0
+7
.babelrc
{
"env": {
"test": {
"plugins": ["@babel/plugin-transform-modules-commonjs"]
}
}
}
/**
* Get total width of multiple fonts at once
* @param {ctx} ctx Canvas context
* @param {object} text Text to be displayed in the text box
* @param {int} fontSize Maximum font size of the text
* @param {int} spaceWidth Width of the space between words
* @returns {int} Width of the text
*/
function getTotalWidth(ctx, text, fontSize, spaceWidth=0) {
let width = 0;
for (let i = 0; i < text.length; i++) {
if (text[i].modifier == null) text[i].modifier = '';
ctx.font = `${text[i].modifier} ${fontSize}px ${text[i].font}`;
width += ctx.measureText(text[i].text).width + spaceWidth;
}
return width - spaceWidth;
}
export { getTotalWidth };
import paintText from './paintText.js';
import { getTotalWidth } from './textAttr.js';
/**
* Get lines of text that fit in the box
* @param {ctx} ctx Canvas context
* @param {object} text Text to be displayed in the text box
* @param {number} fontSize Font size of the text
* @param {number} width Width of the text
* @returns
*/
function getLines(ctx, text, width, fontSize) {
let spaceWidth = fontSize / 4;
// Generate the lines
let lines = [];
let line = [];
for (let i = 0; i < text.length; i++) {
let splitText = text[i].text.split(' ');
for (let j = 0; j < splitText.length; j++) {
let textRich = text[i];
textRich.text = splitText[j];
// Remove unnecessary info in the object
textRich = JSON.parse(JSON.stringify(textRich));
let lineWidth = getTotalWidth(ctx, line, fontSize, spaceWidth);
let textWidth = getTotalWidth(ctx, [textRich], fontSize, spaceWidth);
if (lineWidth + textWidth + spaceWidth > width) {
lines.push(line);
line = [];
}
line.push(textRich);
}
}
lines.push(line);
return lines;
}
/**
* Text that adjusts to the size of the canvas, but it wraps
* @param {ctx} ctx Canvas context
* @param {int} x X coordinate of the text box
* @param {int} y Y coordinate of the text box
* @param {int} width Width of the text box
* @param {object} text Text to be displayed in the text box
* @param {int} fontSize Maximum font size of the text
* @param {string} align Alignment of the text
*/
function wrapText(ctx, x, y, width, text, fontSize, align=1) {
ctx.save();
let lines = getLines(ctx, text, width, fontSize);
let spaceWidth = fontSize / 4;
for (let i = 0; i < lines.length; i++) {
let textWidth = getTotalWidth(ctx, lines[i], fontSize, spaceWidth);
switch (align) {
case 1:
x += (width - textWidth) / 2;
break;
case 2:
x += width - textWidth;
break;
case 3:
let rawTextWidth = getTotalWidth(ctx, lines[i], fontSize);
spaceWidth = (width - rawTextWidth) / (lines[i].length - 1);
if (spaceWidth < 4) spaceWidth = 4;
if (spaceWidth > 30) spaceWidth = 10;
break;
}
paintText(ctx, lines[i], x, y+fontSize*(i+1), fontSize, spaceWidth);
}
ctx.restore();
}
export { wrapText, getLines };
import { getTotalHeight, getTotalWidth } from "../lib/textAttr";
import Canvas from "canvas";
const canvas = Canvas.createCanvas(100, 100);
const ctx = canvas.getContext("2d");
test("getTotalWidth", () => {
const text = [{ text: "test", font: "Arial" }];
expect( getTotalWidth(ctx, text, 20, 0) ).toBeCloseTo(32, -0.5);
expect( getTotalWidth(ctx, text, 40, 0) ).toBeCloseTo(64, -0.5);
expect( getTotalWidth(ctx, text, 60, 0) ).toBeCloseTo(96, -1);
expect( getTotalWidth(ctx, text, 80, 0) ).toBeCloseTo(128, -1);
expect( getTotalWidth(ctx, text, 0.1, 0) ).toBeCloseTo(0, 0);
});
import { getLines } from "../lib/wrapText";
import Canvas from "canvas";
const canvas = Canvas.createCanvas(100, 100);
const ctx = canvas.getContext("2d");
test("getLines", () => {
let text = [{
text: "I'd like to interject for a moment, what you reffered to as Linux was in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux. Linux is not an operating system unto itself, but rather another free component of a fully functioning GNU system made useful by the GNU corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX. Many computer users run a modified version of the GNU system every day, without realizing it. Through a peculiar turn of events, the version of GNU which is widely used today is often called \"Linux\", and many of its users are not aware that it is basically the GNU system, developed by the GNU Project. The Free Software Foundation obviously intends Linux to be free software like any other free program, and whoever works for the Free Software Foundation will do whatever it takes to ensure that the GNU system remains free. Linux is the kernel: the program in the system that allocates the machine's resources to the other programs that you run. The kernel is an essential part of an operating system, but useless by itself; it can only function in the context of a complete operating system. Linux is normally used in combination with the GNU operating system: the whole system is basically GNU with Linux added, or GNU/Linux. All the so-called \"Linux\" distributions are really distributions of GNU/Linux.",
font: 'Arial',
}]
let lines = getLines(ctx, text, 1000, 20);
expect(lines.length).toBe(13);
expect(lines[0]).toStrictEqual([
{ text: "I'd", font: 'Arial' },
{ text: 'like', font: 'Arial' },
{ text: 'to', font: 'Arial' },
{ text: 'interject', font: 'Arial' },
{ text: 'for', font: 'Arial' },
{ text: 'a', font: 'Arial' },
{ text: 'moment,', font: 'Arial' },
{ text: 'what', font: 'Arial' },
{ text: 'you', font: 'Arial' },
{ text: 'reffered', font: 'Arial' },
{ text: 'to', font: 'Arial' },
{ text: 'as', font: 'Arial' },
{ text: 'Linux', font: 'Arial' },
{ text: 'was', font: 'Arial' },
{ text: 'in', font: 'Arial' },
{ text: 'fact,', font: 'Arial' },
{ text: 'GNU/Linux,', font: 'Arial' },
{ text: 'or', font: 'Arial' },
{ text: 'as', font: 'Arial' },
{ text: "I've", font: 'Arial' },
{ text: 'recently', font: 'Arial' },
{ text: 'taken', font: 'Arial' },
{ text: 'to', font: 'Arial' }
]);
});
+2
-2

@@ -20,3 +20,3 @@ import { textBox, wrapText } from "cherry-box";

];
textBox(ctx, 0, 0, canvas.width, canvas.height-20, upperText, 80, ["bottom", "center"]);
textBox(ctx, 0, 0, canvas.width, canvas.height-20, upperText, 80, [2, 1]);

@@ -36,2 +36,2 @@ let wrapTextBox = [

]
wrapText(ctx, 25, 25, canvas.width-50, wrapTextBox, 20, 'justify');
wrapText(ctx, 25, 25, canvas.width-50, wrapTextBox, 20, 3);

@@ -39,3 +39,3 @@ import { textBox } from "cherry-box";

//Draw text
textBox(ctx, 0, 0, canvas.width, 80, upperText, 80, ["middle", "center"]);
textBox(ctx, 0, canvas.height-80, canvas.width, 80, lowerText, 80, ["middle", "center"]);
textBox(ctx, 0, 0, canvas.width, 80, upperText, 80, [1, 1]);
textBox(ctx, 0, canvas.height-80, canvas.width, 80, lowerText, 80, [1, 1]);

@@ -1,2 +0,3 @@

import { textBox, wrapText } from './lib/textBox.js';
export { textBox, wrapText };
import { textBox } from './lib/textBox.js';
import { wrapText, getLines } from './lib/wrapText.js';
export { textBox, wrapText, getLines };
/**
*
* Paint text using all the options provided.
* @param {ctx} ctx Canvas context

@@ -14,22 +14,23 @@ * @param {string} text Text to be displayed

text.forEach(({ text, color, shadow, font, modifier }) => {
for (let i = 0; i < text.length; i++) {
ctx.fillStyle = color;
ctx.fillStyle = text[i].color;
if (modifier == undefined) modifier = '';
ctx.font = `${modifier} ${fontSize}px ${font}`;
if (shadow) {
ctx.shadowColor = shadow.color;
ctx.shadowOffsetX = shadow.offset[0] * fontSize / 100;
ctx.shadowOffsetY = shadow.offset[1] * fontSize / 100;
ctx.shadowBlur = shadow.blur;
if (text[i].modifier == undefined) text[i].modifier = '';
ctx.font = `${text[i].modifier} ${fontSize}px ${text[i].font}`;
if (text[i].shadow) {
ctx.shadowColor = text[i].shadow.color;
ctx.shadowOffsetX = text[i].shadow.offset[0] * fontSize / 100;
ctx.shadowOffsetY = text[i].shadow.offset[1] * fontSize / 100;
ctx.shadowBlur = text[i].shadow.blur;
} else ctx.shadowColor = "transparent";
ctx.fillText(text, x, y);
x += ctx.measureText(text).width + spaceWidth;
});
ctx.fillText(text[i].text, x, y);
x += ctx.measureText(text[i].text).width + spaceWidth;
}
ctx.restore();

@@ -36,0 +37,0 @@ }

import paintText from './paintText.js';
import { getTotalWidth } from './textAttr.js';
/**
*
* Text that adjusts to the size of the canvas
* @param {ctx} ctx Canvas context
* @param {object} text Text to be displayed in the text box
* @param {int} fontSize Maximum font size of the text
* @param {int} spaceWidth Width of the space between words
* @returns {int} Width of the text
*/
function getTotalWidth(ctx, text, fontSize, spaceWidth=0) {
let width = 0;
text.forEach(({ text, font, modifier }) => {
if (modifier == undefined) modifier = '';
ctx.font = `${modifier} ${fontSize}px ${font}`;
width += ctx.measureText(text).width + spaceWidth;
});
return width - spaceWidth;
}
/**
*
* @param {ctx} ctx Canvas context
* @param {object} text Text to be displayed in the text box
* @param {int} fontSize Maximum font size of the text
* @returns {int} Height of the text
*/
function getTotalHeight(ctx, text, fontSize) {
let wordsTotal = "";
text.forEach(({ text, font }) => {
ctx.font = fontSize + "px " + font;
wordsTotal += text;
});
const metrics = ctx.measureText(wordsTotal);
return metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
}
/**
*
* @param {ctx} ctx Canvas context
* @param {x} x X coordinate of the text box

@@ -55,3 +15,3 @@ * @param {y} y Y coordinate of the text box

*/
function textBox (ctx, x, y, width, height, text, fontSize, align=['middle', 'center']) {
function textBox(ctx, x, y, width, height, text, fontSize, align=[1, 1]) {

@@ -64,94 +24,38 @@ ctx.save();

let textHeight = getTotalHeight(ctx, text, fontSize);
textWidth = getTotalWidth(ctx, text, fontSize);
// Calculate the position of the text
if (align[0] === 'top') y += textHeight
if (align[0] === 'bottom') y += height;
if (align[0] === 'middle') y += (textHeight + height) / 2;
if (align[1] === 'center') x += width / 2 - textWidth / 2;
if (align[1] === 'right') x += width - textWidth;
if (align[1] === 'left') x += 0;
paintText(ctx, text, x, y, fontSize);
ctx.restore()
}
/**
*
* @param {ctx} ctx Canvas context
* @param {int} x X coordinate of the text box
* @param {int} y Y coordinate of the text box
* @param {int} width Width of the text box
* @param {object} text Text to be displayed in the text box
* @param {int} fontSize Maximum font size of the text
* @param {string} align Alignment of the text
*/
function wrapText(ctx, x, y, width, text, fontSize, align='left') {
ctx.save();
let lines = [];
let line = [];
let spaceWidth = 10;
for (let i in text) {
let splitText = text[i].text.split(' ');
let j = 0;
for (j in splitText) {
let textRich = {
color: text[i].color,
text: splitText[j],
font: text[i].font,
modifier: text[i].modifier,
shadow: text[i].shadow
};
let lineWidth = getTotalWidth(ctx, line, fontSize, spaceWidth);
let textWidth = getTotalWidth(ctx, [textRich], fontSize, spaceWidth);
// TODO: Fix this
if (lineWidth + textWidth + 10 > width) {
lines.push(line);
line = [];
}
line.push(textRich);
}
switch (align[0]) {
case 0:
y += fontSize;
break;
case 1:
y += (fontSize + height) / 2;
break;
case 2:
y += height;
break;
}
lines.push(line);
for (let i in lines) {
let textWidth = getTotalWidth(ctx, lines[i], fontSize, spaceWidth);
let x_ = x;
if (align === 'center') x_ += width / 2 - textWidth / 2;
if (align === 'right') x_ += width - textWidth;
if (align === 'left') x_ += 0;
if (align === 'justify') {
let rawTextWidth = getTotalWidth(ctx, lines[i], fontSize);
spaceWidth = (width - rawTextWidth) / (lines[i].length - 1);
if (spaceWidth < 4) spaceWidth = 4;
if (spaceWidth > 50) spaceWidth = 10;
}
paintText(ctx, lines[i], x_, y+fontSize*(i)+fontSize, fontSize, spaceWidth);
switch (align[1]) {
case 1:
x += (width - textWidth) / 2;
break;
case 2:
x += width - textWidth;
break;
}
paintText(ctx, text, x, y, fontSize);
ctx.restore();
return {
x: x,
y: y,
width: textWidth,
height: fontSize,
};
}
export { textBox, getTotalWidth, getTotalHeight, wrapText };
export { textBox };
{
"name": "cherry-box",
"version": "1.2.3",
"version": "1.3.0",
"description": "A node-canvas package filled with utilities, manage text boxes easily and more",
"main": "index.js",
"scripts": {
"test": "node test.js"
"test": "jest"
},

@@ -16,9 +16,11 @@ "keywords": [

"type": "module",
"dependencies": {
"canvas": "^2.9.1"
},
"repository": {
"type": "git",
"url": "https://github.com/CheryX/cherry-box.git"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.17.9",
"canvas": "^2.9.1",
"jest": "^28.1.0"
}
}
+16
-10

@@ -25,3 +25,3 @@ # About

]
textBox(800, 600, textSchema, 200, ['middle', 'center']);
textBox(800, 600, textSchema, 200, [1, 1]);
```

@@ -88,12 +88,18 @@

### textBox Errors
Code | Description
--- | ---
601 | Text is too big to be displayed
### Align values
1. Horizontal: `left`, `center` or `right`
2. Vertical: `top`, `middle` or `bottom`
1. Horizontal: left `0`, center `1`, right `2`
2. Vertical: top `0`, middle `1`, bottom `2`
Example: `['top', 'middle']`
Example: `[1,1]`
Example use of textBox in your code:
```js
textBox(ctx, 0, 0, canvas.width, canvas.height-20, upperText, 80, ["bottom", "center"]);
textBox(ctx, 0, 0, canvas.width, canvas.height-20, upperText, 80, [2,1]);
```

@@ -119,10 +125,10 @@

* `left`
* `center`
* `right`
* `justify`
* left `0`
* center `1`
* right `2`
* justify `3`
Example use of `wrapText` in your code:
```js
wrapText(ctx, 0, 0, canvas.width, wrapTextBox, 20, 'justify');
wrapText(ctx, 0, 0, canvas.width, wrapTextBox, 20, 3);
```
function paintText(t,e,o,l,i,n=0){t.save(),e.forEach(({text:e,color:r,shadow:a,font:f,modifier:h})=>{t.fillStyle=r,null==h&&(h=""),t.font=`${h} ${i}px ${f}`,a?(t.shadowColor=a.color,t.shadowOffsetX=a.offset[0]*i/100,t.shadowOffsetY=a.offset[1]*i/100,t.shadowBlur=a.blur):t.shadowColor="transparent",t.fillText(e,o,l),o+=t.measureText(e).width+n}),t.restore()}function getTotalWidth(t,e,o,l=0){let i=0;return e.forEach(({text:e,font:n,modifier:r})=>{null==r&&(r=""),t.font=`${r} ${o}px ${n}`,i+=t.measureText(e).width+l}),i-l}function getTotalHeight(t,e,o){let l="";e.forEach(({text:e,font:i})=>{t.font=o+"px "+i,l+=e});const i=t.measureText(l);return i.actualBoundingBoxAscent+i.actualBoundingBoxDescent}function textBox(t,e,o,l,i,n,r,a=["middle","center"]){t.save();let f=getTotalWidth(t,n,r);f>l&&(r*=l/f);let h=getTotalHeight(t,n,r);f=getTotalWidth(t,n,r),"top"===a[0]&&(o+=h),"bottom"===a[0]&&(o+=i),"middle"===a[0]&&(o+=(h+i)/2),"center"===a[1]&&(e+=l/2-f/2),"right"===a[1]&&(e+=l-f),"left"===a[1]&&(e+=0),paintText(t,n,e,o,r),t.restore()}function wrapText(t,e,o,l,i,n,r="left"){t.save();let a=[],f=[],h=10;for(let e in i){let o=i[e].text.split(" "),r=0;for(r in o){let s={color:i[e].color,text:o[r],font:i[e].font,modifier:i[e].modifier,shadow:i[e].shadow},d=getTotalWidth(t,f,n,h),x=getTotalWidth(t,[s],n,h);d+x+10>l&&(a.push(f),f=[]),f.push(s)}}a.push(f);for(let i in a){let f=getTotalWidth(t,a[i],n,h),s=e;if("center"===r&&(s+=l/2-f/2),"right"===r&&(s+=l-f),"left"===r&&(s+=0),"justify"===r){let e=getTotalWidth(t,a[i],n);h=(l-e)/(a[i].length-1),h<4&&(h=4),h>50&&(h=10)}paintText(t,a[i],s,o+n*i+n,n,h)}t.restore()}export{textBox,getTotalWidth,getTotalHeight,wrapText,paintText};
//import { textBox, wrapText } from "./lib/textBox.js";
import { textBox, wrapText } from "./index.min.js";
import Canvas from "canvas";
import fs from "fs";
const canvas = new Canvas.createCanvas(800, 600);
const ctx = canvas.getContext("2d");
let upperText = [
{
text: "POV: Linux user",
color: "white",
modifier: "bold",
font: "ubuntu",
shadow: {
color: "red",
offset: [0, 0],
blur: 10
}
}
];
textBox(ctx, 0, 0, canvas.width, canvas.height-20, upperText, 80, ["bottom", "center"]);
let wrapTextBox = [
{
text: "I'd like to interject for a moment, what you reffered to as Linux was in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux. Linux is not an operating system unto itself, but rather another free component of a fully functioning GNU system made useful by the GNU corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX. Many computer users run a modified version of the GNU system every day, without realizing it. Through a peculiar turn of events, the version of GNU which is widely used today is often called \"Linux\", and many of its users are not aware that it is basically the GNU system, developed by the GNU Project. The Free Software Foundation obviously intends Linux to be free software like any other free program, and whoever works for the Free Software Foundation will do whatever it takes to ensure that the GNU system remains free. Linux is the kernel: the program in the system that allocates the machine's resources to the other programs that you run. The kernel is an essential part of an operating system, but useless by itself; it can only function in the context of a complete operating system. Linux is normally used in combination with the GNU operating system: the whole system is basically GNU with Linux added, or GNU/Linux. All the so-called \"Linux\" distributions are really distributions of GNU/Linux.",
color: "yellow",
font: 'Arial',
modifier: "bold",
shadow: {
color: "red",
offset: [10, 10],
blur: 10
}
}
]
wrapText(ctx, 25, 25, canvas.width-50, wrapTextBox, 20, 'justify');
// Save canvas to file
let out = fs.createWriteStream("./out.png");
let stream = canvas.createPNGStream();
stream.pipe(out);