Skip to content

Commit

Permalink
feat: Added Letter Spacing option (#302)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
mpa12 and github-actions[bot] authored Jul 2, 2024
1 parent 2349195 commit d57e8c2
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 22 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
vendor/
.vscode/
.env
.env
.idea
33 changes: 17 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,22 +120,23 @@ Feel free to [open a PR](https://github.com/DenverCoder1/readme-typing-svg/issue

## 🔧 Options

| Parameter | Details | Type | Example |
| :----------: | :-------------------------------------------------------------------------: | :-----: | :---------------------------------: |
| `lines` | Text to display with lines separated by `;` and `+` for spaces | string | `First+line;Second+line;Third+line` |
| `height` | Height of the output SVG in pixels (default: `50`) | integer | Any positive number |
| `width` | Width of the output SVG in pixels (default: `400`) | integer | Any positive number |
| `size` | Font size in pixels (default: `20`) | integer | Any positive number |
| `font` | Font family (default: `monospace`) | string | Any font from Google Fonts |
| `color` | Color of the text (default: `36BCF7`) | string | Hex code without # (eg. `F724A9`) |
| `background` | Background color of the text (default: `00000000`) | string | Hex code without # (eg. `FEFF4C`) |
| `center` | `true` to center text or `false` for left aligned (default: `false`) | boolean | `true` or `false` |
| `vCenter` | `true` to center vertically or `false`(default) to align above the center | boolean | `true` or `false` |
| `multiline` | `true` to wrap lines or `false` to retype on one line (default: `false`) | boolean | `true` or `false` |
| `duration` | Duration of the printing of a single line in milliseconds (default: `5000`) | integer | Any positive number |
| `pause` | Duration of the pause between lines in milliseconds (default: `0`) | integer | Any non-negative number |
| `repeat` | `true` to loop around to the first line after the last (default: `true`) | boolean | `true` or `false` |
| `separator` | Separator used between lines in the lines parameter (default: `;`) | string | `;`, `;;`, `/`, etc. |
| Parameter | Details | Type | Example |
| :-------------: | :-------------------------------------------------------------------------: | :-----: | :---------------------------------------------------------------------------------------------------------------: |
| `lines` | Text to display with lines separated by `;` and `+` for spaces | string | `First+line;Second+line;Third+line` |
| `height` | Height of the output SVG in pixels (default: `50`) | integer | Any positive number |
| `width` | Width of the output SVG in pixels (default: `400`) | integer | Any positive number |
| `size` | Font size in pixels (default: `20`) | integer | Any positive number |
| `font` | Font family (default: `monospace`) | string | Any font from Google Fonts |
| `color` | Color of the text (default: `36BCF7`) | string | Hex code without # (eg. `F724A9`) |
| `background` | Background color of the text (default: `00000000`) | string | Hex code without # (eg. `FEFF4C`) |
| `center` | `true` to center text or `false` for left aligned (default: `false`) | boolean | `true` or `false` |
| `vCenter` | `true` to center vertically or `false`(default) to align above the center | boolean | `true` or `false` |
| `multiline` | `true` to wrap lines or `false` to retype on one line (default: `false`) | boolean | `true` or `false` |
| `duration` | Duration of the printing of a single line in milliseconds (default: `5000`) | integer | Any positive number |
| `pause` | Duration of the pause between lines in milliseconds (default: `0`) | integer | Any non-negative number |
| `repeat` | `true` to loop around to the first line after the last (default: `true`) | boolean | `true` or `false` |
| `separator` | Separator used between lines in the lines parameter (default: `;`) | string | `;`, `;;`, `/`, etc. |
| `letterSpacing` | Letter spacing (default: `normal`) | string | Any css values for the [letter-spacing](https://developer.mozilla.org/en-US/docs/Web/CSS/letter-spacing) property |

## 📤 Deploying it on your own

Expand Down
11 changes: 11 additions & 0 deletions src/demo/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ function gtag() {
<label for="size">Font size</label>
<input class="param" type="number" id="size" name="size" alt="Font size" placeholder="20" value="20">

<div class="label-group">
<label for="letterSpacing">Letter spacing</label>
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/letter-spacing" target="_blank" class="icon tooltip" title="Enter any css value for the letter-spacing property">
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
<path d="M12 6C9.831 6 8.066 7.765 8.066 9.934h2C10.066 8.867 10.934 8 12 8s1.934.867 1.934 1.934c0 .598-.481 1.032-1.216 1.626-.255.207-.496.404-.691.599C11.029 13.156 11 14.215 11 14.333V15h2l-.001-.633c.001-.016.033-.386.441-.793.15-.15.339-.3.535-.458.779-.631 1.958-1.584 1.958-3.182C15.934 7.765 14.169 6 12 6zM11 16H13V18H11z"></path>
<path d="M12,2C6.486,2,2,6.486,2,12s4.486,10,10,10s10-4.486,10-10S17.514,2,12,2z M12,20c-4.411,0-8-3.589-8-8s3.589-8,8-8 s8,3.589,8,8S16.411,20,12,20z"></path>
</svg>
</a>
</div>
<input class="param" type="text" id="letterSpacing" name="letterSpacing" alt="Letter spacing" placeholder="normal" value="normal">

<label for="duration">Duration (ms per line)</label>
<input class="param" type="number" id="duration" name="duration" alt="Print duration (ms)" placeholder="5000" value="5000">

Expand Down
1 change: 1 addition & 0 deletions src/demo/js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ let preview = {
color: "36BCF7",
background: "00000000",
size: "20",
letterSpacing: "normal",
center: "false",
vCenter: "false",
multiline: "false",
Expand Down
44 changes: 44 additions & 0 deletions src/models/RendererModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class RendererModel
/** @var string $fontCSS CSS required for displaying the selected font */
public $fontCSS;

/** @var string $letterSpacing Letter spacing */
public $letterSpacing;

/** @var string $template Path to template file */
public $template;

Expand All @@ -78,6 +81,7 @@ class RendererModel
"repeat" => "true",
"separator" => ";",
"random" => "false",
"letterSpacing" => "normal",
];

/**
Expand Down Expand Up @@ -106,6 +110,7 @@ public function __construct($template, $params)
$this->pause = $this->checkNumberNonNegative($params["pause"] ?? $this->DEFAULTS["pause"], "pause");
$this->repeat = $this->checkBoolean($params["repeat"] ?? $this->DEFAULTS["repeat"]);
$this->fontCSS = $this->fetchFontCSS($this->font, $this->weight, $params["lines"]);
$this->letterSpacing = $this->checkLetterSpacing($params["letterSpacing"] ?? $this->DEFAULTS["letterSpacing"]);
}

/**
Expand Down Expand Up @@ -224,4 +229,43 @@ private function fetchFontCSS($font, $weight, $text)
// font is not found
return "";
}

/**
* Validate unit for size properties
*
* This method validates if the given unit is a valid CSS size unit.
* It supports various units such as px, em, rem, pt, pc, in, cm, mm,
* ex, ch, vh, vw, vmin, vmax, and percentages.
*
* @param string $unit Unit for validation
* @return bool True if valid, false otherwise
*/
private function isValidUnit($unit)
{
return (bool) preg_match("/^(-?\\d+(\\.\\d+)?(px|em|rem|pt|pc|in|cm|mm|ex|ch|vh|vw|vmin|vmax|%))$/", $unit);
}

/**
* Validate letter spacing
*
* This method validates the letter spacing property for fonts.
* It allows specific keywords (normal, inherit, initial, revert, revert-layer, unset)
* and valid CSS size units.
*
* @param string $letterSpacing Letter spacing for validation
* @return string Validated letter spacing
*/
private function checkLetterSpacing($letterSpacing)
{
// List of valid keywords for letter-spacing
$keywords = "normal|inherit|initial|revert|revert-layer|unset";

// Check if the input matches one of the keywords or a valid unit
if (preg_match("/^($keywords)$/", $letterSpacing) || $this->isValidUnit($letterSpacing)) {
return $letterSpacing;
}

// Return the default letter spacing value if the input is invalid
return $this->DEFAULTS["letterSpacing"];
}
}
3 changes: 2 additions & 1 deletion src/templates/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
</path>
<text font-family='"<?= $font ?>", monospace' fill='<?= $color ?>' font-size='<?= $size ?>'
dominant-baseline='<?= $vCenter ? "middle" : "auto" ?>'
x='<?= $center ? "50%" : "0%" ?>' text-anchor='<?= $center ? "middle" : "start" ?>'>
x='<?= $center ? "50%" : "0%" ?>' text-anchor='<?= $center ? "middle" : "start" ?>'
letter-spacing='<?= $letterSpacing ?>'>
<textPath xlink:href='#path<?= $i ?>'>
<?= $lines[$i] . "\n" ?>
</textPath>
Expand Down
1 change: 1 addition & 0 deletions src/views/RendererView.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public function render()
"duration" => $this->model->duration,
"pause" => $this->model->pause,
"repeat" => $this->model->repeat,
"letterSpacing" => $this->model->letterSpacing,
]);
// render SVG with output buffering
ob_start();
Expand Down
29 changes: 29 additions & 0 deletions tests/OptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -367,4 +367,33 @@ public function testRandom(): void
$model = new RendererModel("src/templates/main.php", $params);
$this->assertEquals(false, $model->random);
}

/**
* Test Letter Spacing
*/
public function testLetterSpacing(): void
{
// default
$params = [
"lines" => "text",
];
$model = new RendererModel("src/templates/main.php", $params);
$this->assertEquals("normal", $model->letterSpacing);

// invalid
$params = [
"lines" => "text",
"letterSpacing" => "invalid",
];
$model = new RendererModel("src/templates/main.php", $params);
$this->assertEquals("normal", $model->letterSpacing);

// valid
$params = [
"lines" => "text",
"letterSpacing" => "10px",
];
$model = new RendererModel("src/templates/main.php", $params);
$this->assertEquals("10px", $model->letterSpacing);
}
}
20 changes: 20 additions & 0 deletions tests/RendererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -326,4 +326,24 @@ public function testRandom(): void
$this->assertStringContainsString("> $line </textPath>", $actualSVG);
}
}

/**
* Test Letter Spacing
*/
public function testLetterSpacing()
{
$params = [
"lines" => implode(";", [
"Full-stack web and app developer",
"Self-taught UI/UX Designer",
"10+ years of coding experience",
"Always learning new things",
]),
"letterSpacing" => "10px",
];
$controller = new RendererController($params);
$actualSVG = preg_replace("/\s+/", " ", $controller->render());
$this->assertStringContainsString("letter-spacing='10px'", $actualSVG);
$this->assertStringNotContainsString("letter-spacing='normal'", $actualSVG);
}
}
12 changes: 8 additions & 4 deletions tests/svg/test_normal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d57e8c2

Please sign in to comment.