mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-13 15:07:49 +00:00
Compare commits
3 commits
227f0e51c2
...
eacb891cba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eacb891cba | ||
|
|
4b88726c96 | ||
|
|
895d126ab7 |
16 changed files with 1025 additions and 488 deletions
22
app/Liquid/Filters/Data.php
Normal file
22
app/Liquid/Filters/Data.php
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Liquid\Filters;
|
||||||
|
|
||||||
|
use Keepsuit\Liquid\Filters\FiltersProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data filters for Liquid templates
|
||||||
|
*/
|
||||||
|
class Data extends FiltersProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Convert a variable to JSON
|
||||||
|
*
|
||||||
|
* @param mixed $value The variable to convert
|
||||||
|
* @return string JSON representation of the variable
|
||||||
|
*/
|
||||||
|
public function json(mixed $value): string
|
||||||
|
{
|
||||||
|
return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
app/Liquid/Filters/Localization.php
Normal file
52
app/Liquid/Filters/Localization.php
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Liquid\Filters;
|
||||||
|
|
||||||
|
use DateTimeInterface;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Keepsuit\Liquid\Filters\FiltersProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Localization filters for Liquid templates
|
||||||
|
*
|
||||||
|
* Uses Laravel's translator for word translations. Translation files are located in the
|
||||||
|
* lang/{locale}/custom_plugins.php files.
|
||||||
|
*/
|
||||||
|
class Localization extends FiltersProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Localize a date with strftime syntax
|
||||||
|
*
|
||||||
|
* @param mixed $date The date to localize (string or DateTime)
|
||||||
|
* @param string $format The strftime format string
|
||||||
|
* @param string|null $locale The locale to use for localization
|
||||||
|
* @return string The localized date string
|
||||||
|
*/
|
||||||
|
public function l_date(mixed $date, string $format = 'Y-m-d', ?string $locale = null): string
|
||||||
|
{
|
||||||
|
$carbon = $date instanceof DateTimeInterface ? Carbon::instance($date) : Carbon::parse($date);
|
||||||
|
if ($locale) {
|
||||||
|
$carbon->locale($locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $carbon->translatedFormat($format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate a common word to another language
|
||||||
|
*
|
||||||
|
* @param string $word The word to translate
|
||||||
|
* @param string $locale The locale to translate to
|
||||||
|
* @return string The translated word
|
||||||
|
*/
|
||||||
|
public function l_word(string $word, string $locale): string
|
||||||
|
{
|
||||||
|
$translation = trans('custom_plugins.'.mb_strtolower($word), locale: $locale);
|
||||||
|
|
||||||
|
if ($translation === 'custom_plugins.'.mb_strtolower($word)) {
|
||||||
|
return $word;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $translation;
|
||||||
|
}
|
||||||
|
}
|
||||||
54
app/Liquid/Filters/Numbers.php
Normal file
54
app/Liquid/Filters/Numbers.php
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Liquid\Filters;
|
||||||
|
|
||||||
|
use Illuminate\Support\Number;
|
||||||
|
use Keepsuit\Liquid\Filters\FiltersProvider;
|
||||||
|
|
||||||
|
class Numbers extends FiltersProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Format a number with delimiters (default: comma)
|
||||||
|
*
|
||||||
|
* @param mixed $value The number to format
|
||||||
|
* @param string $delimiter The delimiter to use (default: comma)
|
||||||
|
* @param string $separator The separator for decimal part (default: period)
|
||||||
|
*/
|
||||||
|
public function number_with_delimiter(mixed $value, string $delimiter = ',', string $separator = '.'): string
|
||||||
|
{
|
||||||
|
// 2 decimal places for floats, 0 for integers
|
||||||
|
$decimal = is_float($value + 0) ? 2 : 0;
|
||||||
|
|
||||||
|
return number_format($value, decimals: $decimal, decimal_separator: $separator, thousands_separator: $delimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a number as currency
|
||||||
|
*
|
||||||
|
* @param mixed $value The number to format
|
||||||
|
* @param string $currency Currency symbol or locale code
|
||||||
|
* @param string $delimiter The delimiter to use (default: comma)
|
||||||
|
* @param string $separator The separator for decimal part (default: period)
|
||||||
|
*/
|
||||||
|
public function number_to_currency(mixed $value, string $currency = 'USD', string $delimiter = ',', string $separator = '.'): string
|
||||||
|
{
|
||||||
|
if ($currency === '$') {
|
||||||
|
$currency = 'USD';
|
||||||
|
} elseif ($currency === '€') {
|
||||||
|
$currency = 'EUR';
|
||||||
|
} elseif ($currency === '£') {
|
||||||
|
$currency = 'GBP';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($delimiter === '.' && $separator === ',') {
|
||||||
|
$locale = 'de';
|
||||||
|
} else {
|
||||||
|
$locale = 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 decimal places for floats, 0 for integers
|
||||||
|
$decimal = is_float($value + 0) ? 2 : 0;
|
||||||
|
|
||||||
|
return Number::currency($value, in: $currency, precision: $decimal, locale: $locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
61
app/Liquid/Filters/StringMarkup.php
Normal file
61
app/Liquid/Filters/StringMarkup.php
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Liquid\Filters;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Keepsuit\Liquid\Filters\FiltersProvider;
|
||||||
|
use League\CommonMark\CommonMarkConverter;
|
||||||
|
use League\CommonMark\Exception\CommonMarkException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String, Markup, and HTML filters for Liquid templates
|
||||||
|
*/
|
||||||
|
class StringMarkup extends FiltersProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Pluralize a word based on count
|
||||||
|
*
|
||||||
|
* @param string $word The word to pluralize
|
||||||
|
* @param int $count The count to determine pluralization
|
||||||
|
* @return string The pluralized word with count
|
||||||
|
*/
|
||||||
|
public function pluralize(string $word, int $count = 2): string
|
||||||
|
{
|
||||||
|
if ($count === 1) {
|
||||||
|
return "{$count} {$word}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "{$count} ".Str::plural($word, $count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert markdown to HTML
|
||||||
|
*
|
||||||
|
* @param string $markdown The markdown text to convert
|
||||||
|
* @return string The HTML representation of the markdown
|
||||||
|
*/
|
||||||
|
public function markdown_to_html(string $markdown): ?string
|
||||||
|
{
|
||||||
|
$converter = new CommonMarkConverter();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return $converter->convert($markdown);
|
||||||
|
} catch (CommonMarkException $e) {
|
||||||
|
Log::error('Markdown conversion error: '.$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strip HTML tags from a string
|
||||||
|
*
|
||||||
|
* @param string $html The HTML string to strip
|
||||||
|
* @return string The string without HTML tags
|
||||||
|
*/
|
||||||
|
public function strip_html(string $html): string
|
||||||
|
{
|
||||||
|
return strip_tags($html);
|
||||||
|
}
|
||||||
|
}
|
||||||
43
app/Liquid/Filters/Uniqueness.php
Normal file
43
app/Liquid/Filters/Uniqueness.php
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Liquid\Filters;
|
||||||
|
|
||||||
|
use Keepsuit\Liquid\Concerns\ContextAware;
|
||||||
|
use Keepsuit\Liquid\Filters\FiltersProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uniqueness filters for Liquid templates
|
||||||
|
*/
|
||||||
|
class Uniqueness extends FiltersProvider
|
||||||
|
{
|
||||||
|
use ContextAware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a random string to ensure uniqueness within a template
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix to append the random string to
|
||||||
|
* @return string The prefix with a random string appended
|
||||||
|
*/
|
||||||
|
public function append_random(string $prefix): string
|
||||||
|
{
|
||||||
|
return $prefix.$this->generateRandomString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random string
|
||||||
|
*
|
||||||
|
* @param int $length The length of the random string
|
||||||
|
* @return string A random string
|
||||||
|
*/
|
||||||
|
private function generateRandomString(int $length = 4): string
|
||||||
|
{
|
||||||
|
$characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
$randomString = '';
|
||||||
|
|
||||||
|
for ($i = 0; $i < $length; ++$i) {
|
||||||
|
$randomString .= $characters[rand(0, mb_strlen($characters) - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $randomString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Liquid\Filters\Data;
|
||||||
|
use App\Liquid\Filters\Localization;
|
||||||
|
use App\Liquid\Filters\Numbers;
|
||||||
|
use App\Liquid\Filters\StringMarkup;
|
||||||
|
use App\Liquid\Filters\Uniqueness;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
|
|
@ -95,6 +100,14 @@ class Plugin extends Model
|
||||||
|
|
||||||
if ($this->markup_language === 'liquid') {
|
if ($this->markup_language === 'liquid') {
|
||||||
$environment = App::make('liquid.environment');
|
$environment = App::make('liquid.environment');
|
||||||
|
|
||||||
|
// Register all custom filters
|
||||||
|
$environment->filterRegistry->register(Numbers::class);
|
||||||
|
$environment->filterRegistry->register(Data::class);
|
||||||
|
$environment->filterRegistry->register(StringMarkup::class);
|
||||||
|
$environment->filterRegistry->register(Uniqueness::class);
|
||||||
|
$environment->filterRegistry->register(Localization::class);
|
||||||
|
|
||||||
$template = $environment->parseString($this->render_markup);
|
$template = $environment->parseString($this->render_markup);
|
||||||
$context = $environment->newRenderContext(data: ['size' => $size, 'data' => $this->data_payload]);
|
$context = $environment->newRenderContext(data: ['size' => $size, 'data' => $this->data_payload]);
|
||||||
$renderedContent = $template->render($context);
|
$renderedContent = $template->render($context);
|
||||||
|
|
|
||||||
104
composer.lock
generated
104
composer.lock
generated
|
|
@ -62,16 +62,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "aws/aws-sdk-php",
|
"name": "aws/aws-sdk-php",
|
||||||
"version": "3.349.3",
|
"version": "3.351.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||||
"reference": "b2d4718786398f47626add9c29840fc416175ef2"
|
"reference": "2f00efa2544d158ea366c1e1174097ef330ec883"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/b2d4718786398f47626add9c29840fc416175ef2",
|
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2f00efa2544d158ea366c1e1174097ef330ec883",
|
||||||
"reference": "b2d4718786398f47626add9c29840fc416175ef2",
|
"reference": "2f00efa2544d158ea366c1e1174097ef330ec883",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -153,9 +153,9 @@
|
||||||
"support": {
|
"support": {
|
||||||
"forum": "https://github.com/aws/aws-sdk-php/discussions",
|
"forum": "https://github.com/aws/aws-sdk-php/discussions",
|
||||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.349.3"
|
"source": "https://github.com/aws/aws-sdk-php/tree/3.351.5"
|
||||||
},
|
},
|
||||||
"time": "2025-07-09T18:10:17+00:00"
|
"time": "2025-07-23T18:04:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bnussbau/laravel-trmnl-blade",
|
"name": "bnussbau/laravel-trmnl-blade",
|
||||||
|
|
@ -1629,16 +1629,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/framework",
|
"name": "laravel/framework",
|
||||||
"version": "v12.20.0",
|
"version": "v12.21.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/framework.git",
|
"url": "https://github.com/laravel/framework.git",
|
||||||
"reference": "1b9a00f8caf5503c92aa436279172beae1a484ff"
|
"reference": "ac8c4e73bf1b5387b709f7736d41427e6af1c93b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/framework/zipball/1b9a00f8caf5503c92aa436279172beae1a484ff",
|
"url": "https://api.github.com/repos/laravel/framework/zipball/ac8c4e73bf1b5387b709f7736d41427e6af1c93b",
|
||||||
"reference": "1b9a00f8caf5503c92aa436279172beae1a484ff",
|
"reference": "ac8c4e73bf1b5387b709f7736d41427e6af1c93b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1840,7 +1840,7 @@
|
||||||
"issues": "https://github.com/laravel/framework/issues",
|
"issues": "https://github.com/laravel/framework/issues",
|
||||||
"source": "https://github.com/laravel/framework"
|
"source": "https://github.com/laravel/framework"
|
||||||
},
|
},
|
||||||
"time": "2025-07-08T15:02:21+00:00"
|
"time": "2025-07-22T15:41:55+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/prompts",
|
"name": "laravel/prompts",
|
||||||
|
|
@ -1903,16 +1903,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/sanctum",
|
"name": "laravel/sanctum",
|
||||||
"version": "v4.1.2",
|
"version": "v4.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/sanctum.git",
|
"url": "https://github.com/laravel/sanctum.git",
|
||||||
"reference": "e4c09e69aecd5a383e0c1b85a6bb501c997d7491"
|
"reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/sanctum/zipball/e4c09e69aecd5a383e0c1b85a6bb501c997d7491",
|
"url": "https://api.github.com/repos/laravel/sanctum/zipball/fd6df4f79f48a72992e8d29a9c0ee25422a0d677",
|
||||||
"reference": "e4c09e69aecd5a383e0c1b85a6bb501c997d7491",
|
"reference": "fd6df4f79f48a72992e8d29a9c0ee25422a0d677",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -1963,7 +1963,7 @@
|
||||||
"issues": "https://github.com/laravel/sanctum/issues",
|
"issues": "https://github.com/laravel/sanctum/issues",
|
||||||
"source": "https://github.com/laravel/sanctum"
|
"source": "https://github.com/laravel/sanctum"
|
||||||
},
|
},
|
||||||
"time": "2025-07-01T15:49:32+00:00"
|
"time": "2025-07-09T19:45:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/serializable-closure",
|
"name": "laravel/serializable-closure",
|
||||||
|
|
@ -2094,16 +2094,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/commonmark",
|
"name": "league/commonmark",
|
||||||
"version": "2.7.0",
|
"version": "2.7.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/thephpleague/commonmark.git",
|
"url": "https://github.com/thephpleague/commonmark.git",
|
||||||
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405"
|
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
|
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca",
|
||||||
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
|
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -2132,7 +2132,7 @@
|
||||||
"symfony/process": "^5.4 | ^6.0 | ^7.0",
|
"symfony/process": "^5.4 | ^6.0 | ^7.0",
|
||||||
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
|
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
|
||||||
"unleashedtech/php-coding-standard": "^3.1.1",
|
"unleashedtech/php-coding-standard": "^3.1.1",
|
||||||
"vimeo/psalm": "^4.24.0 || ^5.0.0"
|
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
|
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
|
||||||
|
|
@ -2197,7 +2197,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-05-05T12:20:28+00:00"
|
"time": "2025-07-20T12:47:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/config",
|
"name": "league/config",
|
||||||
|
|
@ -2856,22 +2856,22 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "maennchen/zipstream-php",
|
"name": "maennchen/zipstream-php",
|
||||||
"version": "3.1.2",
|
"version": "3.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
||||||
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f"
|
"reference": "9712d8fa4cdf9240380b01eb4be55ad8dcf71416"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f",
|
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/9712d8fa4cdf9240380b01eb4be55ad8dcf71416",
|
||||||
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
|
"reference": "9712d8fa4cdf9240380b01eb4be55ad8dcf71416",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"ext-zlib": "*",
|
"ext-zlib": "*",
|
||||||
"php-64bit": "^8.2"
|
"php-64bit": "^8.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"brianium/paratest": "^7.7",
|
"brianium/paratest": "^7.7",
|
||||||
|
|
@ -2880,7 +2880,7 @@
|
||||||
"guzzlehttp/guzzle": "^7.5",
|
"guzzlehttp/guzzle": "^7.5",
|
||||||
"mikey179/vfsstream": "^1.6",
|
"mikey179/vfsstream": "^1.6",
|
||||||
"php-coveralls/php-coveralls": "^2.5",
|
"php-coveralls/php-coveralls": "^2.5",
|
||||||
"phpunit/phpunit": "^11.0",
|
"phpunit/phpunit": "^12.0",
|
||||||
"vimeo/psalm": "^6.0"
|
"vimeo/psalm": "^6.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
|
@ -2922,7 +2922,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
|
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
|
||||||
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
|
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.2.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -2930,7 +2930,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-01-27T12:07:53+00:00"
|
"time": "2025-07-17T11:15:13+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
|
|
@ -4333,16 +4333,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/laravel-package-tools",
|
"name": "spatie/laravel-package-tools",
|
||||||
"version": "1.92.6",
|
"version": "1.92.7",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/spatie/laravel-package-tools.git",
|
"url": "https://github.com/spatie/laravel-package-tools.git",
|
||||||
"reference": "afa90e37741a953d33728e7106a1f24a13fdd808"
|
"reference": "f09a799850b1ed765103a4f0b4355006360c49a5"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/afa90e37741a953d33728e7106a1f24a13fdd808",
|
"url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/f09a799850b1ed765103a4f0b4355006360c49a5",
|
||||||
"reference": "afa90e37741a953d33728e7106a1f24a13fdd808",
|
"reference": "f09a799850b1ed765103a4f0b4355006360c49a5",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -4382,7 +4382,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/spatie/laravel-package-tools/issues",
|
"issues": "https://github.com/spatie/laravel-package-tools/issues",
|
||||||
"source": "https://github.com/spatie/laravel-package-tools/tree/1.92.6"
|
"source": "https://github.com/spatie/laravel-package-tools/tree/1.92.7"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -4390,7 +4390,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-07-14T08:02:47+00:00"
|
"time": "2025-07-17T15:46:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/temporary-directory",
|
"name": "spatie/temporary-directory",
|
||||||
|
|
@ -7614,16 +7614,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "larastan/larastan",
|
"name": "larastan/larastan",
|
||||||
"version": "v3.5.0",
|
"version": "v3.6.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/larastan/larastan.git",
|
"url": "https://github.com/larastan/larastan.git",
|
||||||
"reference": "e8ccd73008487ba91da9877b373f8c447743f1ce"
|
"reference": "6431d010dd383a9279eb8874a76ddb571738564a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/larastan/larastan/zipball/e8ccd73008487ba91da9877b373f8c447743f1ce",
|
"url": "https://api.github.com/repos/larastan/larastan/zipball/6431d010dd383a9279eb8874a76ddb571738564a",
|
||||||
"reference": "e8ccd73008487ba91da9877b373f8c447743f1ce",
|
"reference": "6431d010dd383a9279eb8874a76ddb571738564a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -7691,7 +7691,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/larastan/larastan/issues",
|
"issues": "https://github.com/larastan/larastan/issues",
|
||||||
"source": "https://github.com/larastan/larastan/tree/v3.5.0"
|
"source": "https://github.com/larastan/larastan/tree/v3.6.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -7699,7 +7699,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-06-19T22:41:50+00:00"
|
"time": "2025-07-11T06:52:52+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/pail",
|
"name": "laravel/pail",
|
||||||
|
|
@ -7851,16 +7851,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/sail",
|
"name": "laravel/sail",
|
||||||
"version": "v1.43.1",
|
"version": "v1.44.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/sail.git",
|
"url": "https://github.com/laravel/sail.git",
|
||||||
"reference": "3e7d899232a8c5e3ea4fc6dee7525ad583887e72"
|
"reference": "a09097bd2a8a38e23ac472fa6a6cf5b0d1c1d3fe"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/sail/zipball/3e7d899232a8c5e3ea4fc6dee7525ad583887e72",
|
"url": "https://api.github.com/repos/laravel/sail/zipball/a09097bd2a8a38e23ac472fa6a6cf5b0d1c1d3fe",
|
||||||
"reference": "3e7d899232a8c5e3ea4fc6dee7525ad583887e72",
|
"reference": "a09097bd2a8a38e23ac472fa6a6cf5b0d1c1d3fe",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -7910,7 +7910,7 @@
|
||||||
"issues": "https://github.com/laravel/sail/issues",
|
"issues": "https://github.com/laravel/sail/issues",
|
||||||
"source": "https://github.com/laravel/sail"
|
"source": "https://github.com/laravel/sail"
|
||||||
},
|
},
|
||||||
"time": "2025-05-19T13:19:21+00:00"
|
"time": "2025-07-04T16:17:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mockery/mockery",
|
"name": "mockery/mockery",
|
||||||
|
|
@ -8963,16 +8963,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan",
|
"name": "phpstan/phpstan",
|
||||||
"version": "2.1.17",
|
"version": "2.1.19",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpstan/phpstan.git",
|
"url": "https://github.com/phpstan/phpstan.git",
|
||||||
"reference": "89b5ef665716fa2a52ecd2633f21007a6a349053"
|
"reference": "473a8c30e450d87099f76313edcbb90852f9afdf"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053",
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/473a8c30e450d87099f76313edcbb90852f9afdf",
|
||||||
"reference": "89b5ef665716fa2a52ecd2633f21007a6a349053",
|
"reference": "473a8c30e450d87099f76313edcbb90852f9afdf",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -9017,7 +9017,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-05-21T20:55:28+00:00"
|
"time": "2025-07-21T19:58:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-code-coverage",
|
"name": "phpunit/php-code-coverage",
|
||||||
|
|
|
||||||
7
lang/de/custom_plugins.php
Normal file
7
lang/de/custom_plugins.php
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'today' => 'heute',
|
||||||
|
'tomorrow' => 'morgen',
|
||||||
|
'yesterday' => 'gestern',
|
||||||
|
];
|
||||||
822
package-lock.json
generated
822
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -276,6 +276,34 @@ Route::post('/display/update', function (Request $request) {
|
||||||
->name('display.update')
|
->name('display.update')
|
||||||
->middleware('auth:sanctum', 'ability:update-screen');
|
->middleware('auth:sanctum', 'ability:update-screen');
|
||||||
|
|
||||||
|
Route::post('/screens', function (Request $request) {
|
||||||
|
$mac_address = $request->header('id');
|
||||||
|
$access_token = $request->header('access-token');
|
||||||
|
$device = Device::where('mac_address', $mac_address)
|
||||||
|
->where('api_key', $access_token)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (! $device) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'MAC Address not registered or invalid access token',
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'image' => 'array|required',
|
||||||
|
'image.content' => 'string|required',
|
||||||
|
'image.file_name' => 'string',
|
||||||
|
]);
|
||||||
|
$content = $request['image']['content'];
|
||||||
|
|
||||||
|
$view = Blade::render($content);
|
||||||
|
GenerateScreenJob::dispatchSync($device->id, null, $view);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'success',
|
||||||
|
]);
|
||||||
|
})->name('screens.update');
|
||||||
|
|
||||||
Route::get('/display/status', function (Request $request) {
|
Route::get('/display/status', function (Request $request) {
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'device_id' => 'required|exists:devices,id',
|
'device_id' => 'required|exists:devices,id',
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Jobs\GenerateScreenJob;
|
||||||
use App\Models\Device;
|
use App\Models\Device;
|
||||||
use App\Models\Playlist;
|
use App\Models\Playlist;
|
||||||
use App\Models\PlaylistItem;
|
use App\Models\PlaylistItem;
|
||||||
|
|
@ -838,3 +839,42 @@ test('device returns sleep.png and correct refresh time when paused', function (
|
||||||
expect($json['image_url'])->toContain('sleep.png');
|
expect($json['image_url'])->toContain('sleep.png');
|
||||||
expect($json['refresh_rate'])->toBeLessThanOrEqual(3600); // ~60 min
|
expect($json['refresh_rate'])->toBeLessThanOrEqual(3600); // ~60 min
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('screens endpoint accepts nullable file_name', function () {
|
||||||
|
Queue::fake();
|
||||||
|
|
||||||
|
$device = Device::factory()->create([
|
||||||
|
'mac_address' => '00:11:22:33:44:55',
|
||||||
|
'api_key' => 'test-api-key',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'id' => $device->mac_address,
|
||||||
|
'access-token' => $device->api_key,
|
||||||
|
])->post('/api/screens', [
|
||||||
|
'image' => [
|
||||||
|
'content' => '<div>Test content</div>',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->assertOk();
|
||||||
|
|
||||||
|
Queue::assertPushed(GenerateScreenJob::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('screens endpoint returns 404 for invalid device credentials', function () {
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'id' => 'invalid-mac',
|
||||||
|
'access-token' => 'invalid-key',
|
||||||
|
])->post('/api/screens', [
|
||||||
|
'image' => [
|
||||||
|
'content' => '<div>Test content</div>',
|
||||||
|
'file_name' => 'test.blade.php',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->assertNotFound()
|
||||||
|
->assertJson([
|
||||||
|
'message' => 'MAC Address not registered or invalid access token',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
|
||||||
55
tests/Unit/Liquid/Filters/DataTest.php
Normal file
55
tests/Unit/Liquid/Filters/DataTest.php
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Liquid\Filters\Data;
|
||||||
|
|
||||||
|
test('json filter converts arrays to JSON', function () {
|
||||||
|
$filter = new Data();
|
||||||
|
$array = ['foo' => 'bar', 'baz' => 'qux'];
|
||||||
|
|
||||||
|
expect($filter->json($array))->toBe('{"foo":"bar","baz":"qux"}');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('json filter converts objects to JSON', function () {
|
||||||
|
$filter = new Data();
|
||||||
|
$object = new stdClass();
|
||||||
|
$object->foo = 'bar';
|
||||||
|
$object->baz = 'qux';
|
||||||
|
|
||||||
|
expect($filter->json($object))->toBe('{"foo":"bar","baz":"qux"}');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('json filter handles nested structures', function () {
|
||||||
|
$filter = new Data();
|
||||||
|
$nested = [
|
||||||
|
'foo' => 'bar',
|
||||||
|
'nested' => [
|
||||||
|
'baz' => 'qux',
|
||||||
|
'items' => [1, 2, 3],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
expect($filter->json($nested))->toBe('{"foo":"bar","nested":{"baz":"qux","items":[1,2,3]}}');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('json filter handles scalar values', function () {
|
||||||
|
$filter = new Data();
|
||||||
|
|
||||||
|
expect($filter->json('string'))->toBe('"string"');
|
||||||
|
expect($filter->json(123))->toBe('123');
|
||||||
|
expect($filter->json(true))->toBe('true');
|
||||||
|
expect($filter->json(null))->toBe('null');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('json filter preserves unicode characters', function () {
|
||||||
|
$filter = new Data();
|
||||||
|
$data = ['message' => 'Hello, 世界'];
|
||||||
|
|
||||||
|
expect($filter->json($data))->toBe('{"message":"Hello, 世界"}');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('json filter does not escape slashes', function () {
|
||||||
|
$filter = new Data();
|
||||||
|
$data = ['url' => 'https://example.com/path'];
|
||||||
|
|
||||||
|
expect($filter->json($data))->toBe('{"url":"https://example.com/path"}');
|
||||||
|
});
|
||||||
62
tests/Unit/Liquid/Filters/LocalizationTest.php
Normal file
62
tests/Unit/Liquid/Filters/LocalizationTest.php
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Liquid\Filters\Localization;
|
||||||
|
|
||||||
|
test('l_date formats date with default format', function () {
|
||||||
|
$filter = new Localization();
|
||||||
|
$date = '2025-01-11';
|
||||||
|
|
||||||
|
$result = $filter->l_date($date);
|
||||||
|
|
||||||
|
// Default format is 'Y-m-d', which should output something like '2025-01-11'
|
||||||
|
// The exact output might vary depending on the locale, but it should contain the year, month, and day
|
||||||
|
expect($result)->toContain('2025');
|
||||||
|
expect($result)->toContain('01');
|
||||||
|
expect($result)->toContain('11');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('l_date formats date with custom format', function () {
|
||||||
|
$filter = new Localization();
|
||||||
|
$date = '2025-01-11';
|
||||||
|
|
||||||
|
$result = $filter->l_date($date, '%y %b');
|
||||||
|
|
||||||
|
// Format '%y %b' should output something like '25 Jan'
|
||||||
|
// The month name might vary depending on the locale
|
||||||
|
expect($result)->toContain('25');
|
||||||
|
// We can't check for 'Jan' specifically as it might be localized
|
||||||
|
});
|
||||||
|
|
||||||
|
test('l_date handles DateTime objects', function () {
|
||||||
|
$filter = new Localization();
|
||||||
|
$date = new DateTimeImmutable('2025-01-11');
|
||||||
|
|
||||||
|
$result = $filter->l_date($date, 'Y-m-d');
|
||||||
|
|
||||||
|
expect($result)->toContain('2025-01-11');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('l_word translates common words', function () {
|
||||||
|
$filter = new Localization();
|
||||||
|
|
||||||
|
expect($filter->l_word('today', 'de'))->toBe('heute');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('l_word returns original word if no translation exists', function () {
|
||||||
|
$filter = new Localization();
|
||||||
|
|
||||||
|
expect($filter->l_word('hello', 'es-ES'))->toBe('hello');
|
||||||
|
expect($filter->l_word('world', 'ko'))->toBe('world');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('l_word is case-insensitive', function () {
|
||||||
|
$filter = new Localization();
|
||||||
|
|
||||||
|
expect($filter->l_word('TODAY', 'de'))->toBe('heute');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('l_word returns original word for unknown locales', function () {
|
||||||
|
$filter = new Localization();
|
||||||
|
|
||||||
|
expect($filter->l_word('today', 'unknown-locale'))->toBe('today');
|
||||||
|
});
|
||||||
47
tests/Unit/Liquid/Filters/NumbersTest.php
Normal file
47
tests/Unit/Liquid/Filters/NumbersTest.php
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Liquid\Filters\Numbers;
|
||||||
|
|
||||||
|
test('number_with_delimiter formats numbers with commas by default', function () {
|
||||||
|
$filter = new Numbers();
|
||||||
|
|
||||||
|
expect($filter->number_with_delimiter(1234))->toBe('1,234');
|
||||||
|
expect($filter->number_with_delimiter(1000000))->toBe('1,000,000');
|
||||||
|
expect($filter->number_with_delimiter(0))->toBe('0');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('number_with_delimiter handles custom delimiters', function () {
|
||||||
|
$filter = new Numbers();
|
||||||
|
|
||||||
|
expect($filter->number_with_delimiter(1234, '.'))->toBe('1.234');
|
||||||
|
expect($filter->number_with_delimiter(1000000, ' '))->toBe('1 000 000');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('number_with_delimiter handles decimal values with custom separators', function () {
|
||||||
|
$filter = new Numbers();
|
||||||
|
|
||||||
|
expect($filter->number_with_delimiter(1234.57, ' ', ','))->toBe('1 234,57');
|
||||||
|
expect($filter->number_with_delimiter(1234.5, '.', ','))->toBe('1.234,50');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('number_to_currency formats numbers with dollar sign by default', function () {
|
||||||
|
$filter = new Numbers();
|
||||||
|
|
||||||
|
expect($filter->number_to_currency(1234))->toBe('$1,234');
|
||||||
|
expect($filter->number_to_currency(1234.5))->toBe('$1,234.50');
|
||||||
|
expect($filter->number_to_currency(0))->toBe('$0');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('number_to_currency handles custom currency symbols', function () {
|
||||||
|
$filter = new Numbers();
|
||||||
|
|
||||||
|
expect($filter->number_to_currency(1234, '£'))->toBe('£1,234');
|
||||||
|
expect($filter->number_to_currency(152350.69, '€'))->toBe('€152,350.69');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('number_to_currency handles custom delimiters and separators', function () {
|
||||||
|
$filter = new Numbers();
|
||||||
|
|
||||||
|
expect($filter->number_to_currency(1234.57, '£', '.', ','))->toBe('1.234,57 £');
|
||||||
|
expect($filter->number_to_currency(1234.57, '€', ',', '.'))->toBe('€1,234.57');
|
||||||
|
});
|
||||||
90
tests/Unit/Liquid/Filters/StringMarkupTest.php
Normal file
90
tests/Unit/Liquid/Filters/StringMarkupTest.php
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Liquid\Filters\StringMarkup;
|
||||||
|
|
||||||
|
test('pluralize returns singular form with count 1', function () {
|
||||||
|
$filter = new StringMarkup();
|
||||||
|
|
||||||
|
expect($filter->pluralize('book', 1))->toBe('1 book');
|
||||||
|
expect($filter->pluralize('person', 1))->toBe('1 person');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('pluralize returns plural form with count greater than 1', function () {
|
||||||
|
$filter = new StringMarkup();
|
||||||
|
|
||||||
|
expect($filter->pluralize('book', 2))->toBe('2 books');
|
||||||
|
expect($filter->pluralize('person', 4))->toBe('4 people');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('pluralize handles irregular plurals correctly', function () {
|
||||||
|
$filter = new StringMarkup();
|
||||||
|
|
||||||
|
expect($filter->pluralize('child', 3))->toBe('3 children');
|
||||||
|
expect($filter->pluralize('sheep', 5))->toBe('5 sheep');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('pluralize uses default count of 2 when not specified', function () {
|
||||||
|
$filter = new StringMarkup();
|
||||||
|
|
||||||
|
expect($filter->pluralize('book'))->toBe('2 books');
|
||||||
|
expect($filter->pluralize('person'))->toBe('2 people');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('markdown_to_html converts basic markdown to HTML', function () {
|
||||||
|
$filter = new StringMarkup();
|
||||||
|
$markdown = 'This is *italic* and **bold**.';
|
||||||
|
|
||||||
|
// The exact HTML output might vary depending on the Parsedown implementation
|
||||||
|
// So we'll check for the presence of HTML tags rather than the exact output
|
||||||
|
$result = $filter->markdown_to_html($markdown);
|
||||||
|
|
||||||
|
expect($result)->toContain('<em>italic</em>');
|
||||||
|
expect($result)->toContain('<strong>bold</strong>');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('markdown_to_html converts links correctly', function () {
|
||||||
|
$filter = new StringMarkup();
|
||||||
|
$markdown = 'This is [a link](https://example.com).';
|
||||||
|
|
||||||
|
$result = $filter->markdown_to_html($markdown);
|
||||||
|
|
||||||
|
expect($result)->toContain('<a href="https://example.com">a link</a>');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('markdown_to_html handles fallback when Parsedown is not available', function () {
|
||||||
|
// Create a mock that simulates Parsedown not being available
|
||||||
|
$filter = new class extends StringMarkup
|
||||||
|
{
|
||||||
|
public function markdown_to_html(string $markdown): string
|
||||||
|
{
|
||||||
|
// Force the fallback path
|
||||||
|
return nl2br(htmlspecialchars($markdown));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$markdown = 'This is *italic* and [a link](https://example.com).';
|
||||||
|
$result = $filter->markdown_to_html($markdown);
|
||||||
|
|
||||||
|
expect($result)->toBe('This is *italic* and [a link](https://example.com).');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('strip_html removes HTML tags', function () {
|
||||||
|
$filter = new StringMarkup();
|
||||||
|
$html = '<p>This is <strong>bold</strong> and <em>italic</em>.</p>';
|
||||||
|
|
||||||
|
expect($filter->strip_html($html))->toBe('This is bold and italic.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('strip_html preserves text content', function () {
|
||||||
|
$filter = new StringMarkup();
|
||||||
|
$html = '<div>Hello, <span>world</span>!</div>';
|
||||||
|
|
||||||
|
expect($filter->strip_html($html))->toBe('Hello, world!');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('strip_html handles nested tags', function () {
|
||||||
|
$filter = new StringMarkup();
|
||||||
|
$html = '<div><p>Paragraph <strong>with <em>nested</em> tags</strong>.</p></div>';
|
||||||
|
|
||||||
|
expect($filter->strip_html($html))->toBe('Paragraph with nested tags.');
|
||||||
|
});
|
||||||
13
tests/Unit/Liquid/Filters/UniquenessTest.php
Normal file
13
tests/Unit/Liquid/Filters/UniquenessTest.php
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Liquid\Filters\Uniqueness;
|
||||||
|
|
||||||
|
test('append_random appends a random string with 4 characters', function () {
|
||||||
|
$filter = new Uniqueness();
|
||||||
|
$result = $filter->append_random('chart-');
|
||||||
|
|
||||||
|
// Check that the result starts with the prefix
|
||||||
|
expect($result)->toStartWith('chart-');
|
||||||
|
// Check that the result is longer than just the prefix (has random part)
|
||||||
|
expect(mb_strlen($result))->toBe(mb_strlen('chart-') + 4);
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue