Skip to content

Commit 3564377

Browse files
committed
perf: remove recursion
1 parent 434ec47 commit 3564377

File tree

3 files changed

+122
-54
lines changed

3 files changed

+122
-54
lines changed

CONTRIBUTING.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Contributing to Hexashades
2+
3+
First off, thank you for considering contributing to Hexashades! I welcome contributions from everyone, whether you're fixing a typo or submitting a major feature. To make the contribution process smooth and consistent, I ask that you follow these guidelines.
4+
5+
## Table of Contents
6+
7+
- [Code of Conduct](#code-of-conduct)
8+
- [How to Contribute](#how-to-contribute)
9+
- [Reporting Bugs](#reporting-bugs)
10+
- [Suggesting Enhancements](#suggesting-enhancements)
11+
- [Submitting a Pull Request](#submitting-a-pull-request)
12+
- [Development Setup](#development-setup)
13+
- [Commit Message Guidelines](#commit-message-guidelines)
14+
- [License](#license)
15+
16+
## Code of Conduct
17+
18+
By participating in this project, you agree to follow the [Code of Conduct](CODE_OF_CONDUCT.md). Please read it to ensure a positive experience for everyone.
19+
20+
## How to Contribute
21+
22+
### Reporting Bugs
23+
24+
If you find a bug in the project, please help by reporting it:
25+
26+
1. Check the issue tracker to see if the bug has already been reported.
27+
2. If not, open a new issue with a detailed description of the problem, including steps to reproduce it, your environment (OS, Node.js version, etc.), and any relevant logs or error messages.
28+
29+
### Suggesting Enhancements
30+
31+
If you have an idea for a new feature or improvement:
32+
33+
1. Check if the feature has already been suggested.
34+
2. If not, open a new issue with a clear description of the enhancement and why it would be useful. I love hearing your ideas!
35+
36+
### Submitting a Pull Request
37+
38+
I appreciate your contributions! To submit a pull request (PR), follow these steps:
39+
40+
1. Fork the repository and create a new branch for your changes.
41+
2. Write clear, concise commit messages that explain your changes.
42+
3. Ensure that your code adheres to the project's coding style and passes any existing tests.
43+
4. If applicable, write tests for your changes and make sure they pass.
44+
5. Open a pull request against the main branch (usually `main` or `master`).
45+
46+
I will review your PR and provide feedback. Be prepared to make revisions if necessary.
47+
48+
## Development Setup
49+
50+
To set up the project for local development, follow these steps:
51+
52+
1. Clone the repository:
53+
54+
```bash
55+
git clone https://github.com/arjunkdot/hexashades.git
56+
```
57+
58+
2. Install the dependencies:
59+
60+
```bash
61+
npm install
62+
```
63+
64+
or
65+
66+
```bash
67+
pnpm install
68+
```
69+
70+
Make sure to follow any additional setup instructions in the README.md if applicable.
71+
72+
## Commit Message Guidelines
73+
74+
I follow a simple convention for commit messages:
75+
76+
- Use the present tense: "Add feature" not "Added feature."
77+
- Use a short, descriptive message (50 characters or less).
78+
- If the change is related to an issue, reference the issue number using #.
79+
80+
## Example
81+
82+
Please refer to [Conventional Commits](https://www.conventionalcommits.org/) for more details.
83+
84+
License
85+
By contributing to this project, you agree that your contributions will be licensed under the [MIT License](LICENSE).

src/index.ts

Lines changed: 30 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,11 @@ type RgbType = {
55
};
66

77
export class Colors {
8-
result: string[];
9-
limit: number;
10-
prefix: boolean;
8+
result: string[] = [];
9+
limit: number = 0;
10+
prefix: boolean = false;
1111

12-
constructor() {
13-
this.result = [];
14-
this.limit = 0;
15-
this.prefix = false;
16-
}
12+
constructor() { }
1713

1814
#hex2Rgb(hex: string) {
1915
const sections = this.#hex2Groups(hex);
@@ -51,23 +47,28 @@ export class Colors {
5147
}
5248

5349
#padHex(color: string) {
54-
return `${color[0].padStart(2, color[0])}${color[1].padStart(2, color[1])}${color[2].padStart(2, color[2])}`;
50+
return `${color.padStart(6, color[0])}`
5551
}
5652

57-
#generateShades(rgb: RgbType, percentage: number) {
58-
const rgbShade = {
59-
red: this.#getShade(rgb.red, this.limit),
60-
green: this.#getShade(rgb.green, this.limit),
61-
blue: this.#getShade(rgb.blue, this.limit),
62-
};
63-
const hex = this.#rgb2hex(rgbShade);
64-
this.result.push(`${this.prefix ? '#' + hex : hex}`);
65-
this.limit += percentage;
66-
if (this.limit >= 100) {
67-
return;
53+
#generate(rgb: RgbType, percentage: number, type: 'shades' | 'tints') {
54+
const color: RgbType = { red: 0, green: 0, blue: 0 };
55+
56+
if (type === 'shades') {
57+
color.red = this.#getShade(rgb.red, this.limit);
58+
color.green = this.#getShade(rgb.green, this.limit);
59+
color.blue = this.#getShade(rgb.blue, this.limit);
60+
} else {
61+
color.red = this.#getTint(rgb.red, this.limit);
62+
color.green = this.#getTint(rgb.green, this.limit);
63+
color.blue = this.#getTint(rgb.blue, this.limit);
64+
}
65+
66+
while (this.limit < 100) {
67+
const hex = this.#rgb2hex(color);
68+
this.result.push(`${this.prefix ? '#' + hex : hex}`);
69+
this.limit += percentage;
6870
}
6971

70-
this.#generateShades(rgb, percentage);
7172
}
7273

7374
#getTint(color: number, percentage: number) {
@@ -76,21 +77,6 @@ export class Colors {
7677
return (tint > 255) ? 255 : tint;
7778
}
7879

79-
#generateTints(rgb: RgbType, percentage: number) {
80-
this.limit += percentage;
81-
const rgbTint = {
82-
red: this.#getTint(rgb.red, this.limit),
83-
green: this.#getTint(rgb.green, this.limit),
84-
blue: this.#getTint(rgb.blue, this.limit),
85-
};
86-
const hex = this.#rgb2hex(rgbTint);
87-
this.result.push(`${this.prefix ? '#' + hex : hex}`);
88-
if (this.limit >= 100) {
89-
return;
90-
}
91-
this.#generateTints(rgb, percentage);
92-
}
93-
9480
createColors(color: string, percentage: number, prefix: boolean = false) {
9581
// Check if the input exists
9682
if (!color || !percentage) {
@@ -100,14 +86,10 @@ export class Colors {
10086
if (typeof color !== 'string' || typeof percentage !== 'number' || typeof prefix !== 'boolean') {
10187
throw new Error('Invalid input. Wrong input types are given.');
10288
}
103-
// Check if the percentage is valid
104-
if (percentage < 0 || percentage > 100) {
105-
throw new Error('Invalid input. Invalid percentage value is given.')
106-
}
107-
// Check if HEX is valid
108-
if (color.length !== 3 && color.length !== 6) {
109-
throw new Error("Invalid input. Not a valid length.");
89+
if (color.length !== 3 && color.length !== 6 || percentage < 0 || percentage > 100) {
90+
throw new Error('Invalid input. Wrong input values are given.');
11091
}
92+
11193
// Pad the HEX string if it has only 3 characters
11294
if (color.length === 3) {
11395
color = this.#padHex(color);
@@ -118,15 +100,16 @@ export class Colors {
118100

119101
const rgb = this.#hex2Rgb(color);
120102
// Generate Tints
121-
this.#generateTints(rgb, percentage);
103+
this.#generate(rgb, percentage, 'tints');
122104
// Reset Limit
123105
this.limit = 0;
124106
// Generate Shades
125-
this.#generateShades(rgb, percentage);
107+
this.#generate(rgb, percentage, 'shades');
126108

127109
// Arrange colors in ascending order
128-
const tints = this.result.slice(0, this.result.length / 2).reverse();
129-
const shades = this.result.slice(this.result.length / 2, this.result.length).reverse();
110+
const mid = this.result.length / 2
111+
const tints = this.result.slice(0, mid).reverse();
112+
const shades = this.result.slice(mid).reverse();
130113
shades.unshift(`${this.prefix ? '#' + color : color}`);
131114

132115
// Reset global variables

tests/outputs/errors.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,28 @@ describe("throws an error", () => {
1717

1818
test("for invalid input length", () => {
1919
expect(() => ctx.createColors("66", 10)).toThrow(
20-
"Invalid input. Not a valid length."
20+
"Invalid input. Wrong input values are given."
2121
);
2222
expect(() => ctx.createColors("6", 10)).toThrow(
23-
"Invalid input. Not a valid length."
23+
"Invalid input. Wrong input values are given."
2424
);
2525
expect(() => ctx.createColors("6666", 10)).toThrow(
26-
"Invalid input. Not a valid length."
26+
"Invalid input. Wrong input values are given."
2727
);
2828
expect(() => ctx.createColors("66666", 10)).toThrow(
29-
"Invalid input. Not a valid length."
29+
"Invalid input. Wrong input values are given."
3030
);
3131
expect(() => ctx.createColors("6666666", 10)).toThrow(
32-
"Invalid input. Not a valid length."
32+
"Invalid input. Wrong input values are given."
3333
);
3434
});
3535

3636
test("for invalid percentage value", () => {
3737
expect(() => ctx.createColors("66", -10)).toThrow(
38-
"Invalid input. Invalid percentage value is given."
38+
"Invalid input. Wrong input values are given."
3939
);
4040
expect(() => ctx.createColors("66", 110)).toThrow(
41-
"Invalid input. Invalid percentage value is given."
41+
"Invalid input. Wrong input values are given."
4242
);
4343
});
4444

0 commit comments

Comments
 (0)