Skip to content

Commit 429f399

Browse files
author
vidy
committed
Implement named argument
1 parent 9108a26 commit 429f399

19 files changed

+703
-75
lines changed

README.md

+72-8
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,79 @@
1-
# Blade Filters
1+
Laravel Blade Filters
2+
======================
23

3-
Forked from [`conedevelopment/blade-filters`](https://github.com/conedevelopment/blade-filters), comparing with the original, your can resolve filters with custom resolver.
4+
- [Laravel Blade Filters](#laravel-blade-filters)
5+
- [Installation](#installation)
6+
- [Named filter arguments](#named-filter-arguments)
7+
- [Pass variables to filter arguments](#pass-variables-to-filter-arguments)
8+
- [Add simple custom filter](#add-simple-custom-filter)
9+
- [Filter provider](#filter-provider)
10+
- [Internal filters](#internal-filters)
11+
- [Testing](#testing)
412

13+
Originated from [`conedevelopment/blade-filters`](https://github.com/conedevelopment/blade-filters), but with huge improvements, the original doesn't support named arguments and a context for filter to run, which are essential in my case. this libary implements a custom lexer and parser to anyalize filter syntax.
14+
15+
Because this libary is almost refactored, this package renamed as `videni/blade-filters`, but the namespace still keeps it is.
16+
17+
## Installation
18+
19+
```
20+
composer require "videni/blade-filters": "^1.0@dev"
21+
```
22+
23+
## Named filter arguments
24+
25+
```
26+
{{ 'a wonderful place' | slug:separator='_', language='en' }}
27+
```
28+
29+
For slug filter which provided by `\Illuminate\Support\Str`, the first argument is the value being filtered, the second argument would be the `separator`, the third would be `language`, if a argument name doesn't not exists in slug method of `\Illuminate\Support\Str`, it will be simply ignored.
30+
31+
32+
## Pass variables to filter arguments
533

634
```
7-
$assetContextResolver = function(){
8-
return '(isset($local_asset_context)? $local_asset_context: $base_asset_context)->';
9-
};
10-
BladeFiltersCompiler::extend('theme_asset_url', $assetContextResolver);
11-
BladeFiltersCompiler::extend('theme_asset_import', $assetContextResolver);
35+
{{ "hello world" | slug:separator=$separator }}
1236
```
1337

38+
the `$separator` will be captured where the filter runs.
39+
40+
## Add simple custom filter
41+
42+
For the simplest case, you can add custom filter as following
43+
```
44+
\Pine\BladeFilters\BladeFilters::macro('script_tag', function (string $asset,$type = 'text/javascript', $async = null, $defer = null) {
45+
// Your code here
46+
}
47+
)
48+
```
1449

15-
Please check original repo for other documents.
50+
## Filter provider
51+
52+
You may not need this if you just want to add [simple custom filters](#add-simple-custom-filter).
53+
54+
The provided `StaticMacroableFilterProvider` class allows you to hook static methods and `Laravel Macroable` as Blade filters. usually, you don't need to add a `static macroable` class like `\Illuminate\Support\Str` and `\Pine\BladeFilters\BladeFilters`, but it may be helpful, if you want to support other third party utilities class.
55+
56+
```
57+
$registry = new BladeFilterProviderRegistry();
58+
$registry
59+
->register(new StaticMacroableFilterProvider(\Illuminate\Support\Str::class), 10);
60+
```
61+
62+
Uncommonly, your filter may be context aware, let's assume a context like this:
63+
64+
A filter named `cdn_url` which generated url for an asset.
65+
```php
66+
cdn_url('assets/carosel.css');
67+
```
68+
the domain of the CDN will change depending on the context where the filter run, the context itself is not part of the API of our filter, the user doen't need to worry about. this is the difference with `filter argument`. you can always pass a variable to your filter as an argument as [Pass variables to filter arguments](#pass-variables-to-filter-arguments), however, the variable must be filled by the filter's user(you or someone).
69+
70+
## Internal filters
71+
72+
all static methods from `Pine\BladeFilters\BladeFilters` and `\Illuminate\Support\Str` are provided as blade filters, it is quite simple, please check its source code reference.
73+
74+
75+
## Testing
76+
77+
```
78+
phpunit
79+
```

composer.json

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
{
2-
"name": "conedevelopment/blade-filters",
2+
"name": "videni/blade-filters",
33
"description": "Use filters easily in your blade templates.",
44
"type": "project",
55
"license": "MIT",
66
"authors": [
7+
{
8+
"name": "Vidy Videni",
9+
"email": "[email protected]"
10+
},
711
{
812
"name": "Cone Development",
913
"email": "[email protected]"
@@ -20,13 +24,12 @@
2024
}
2125
},
2226
"require": {
23-
"php": "^7.3 || ^8.0",
24-
"illuminate/support": "^8.0 || ^9.0",
25-
"illuminate/view": "^8.0 || ^9.0"
27+
"php": "^7.2.5 | ^8.0",
28+
"illuminate/support": "^6.0|^7.0|^8.0|^9.0"
2629
},
2730
"require-dev": {
28-
"laravel/laravel": "9.x-dev",
29-
"phpunit/phpunit": "^9.5"
31+
"laravel/laravel": "^6.0|^7.0|^8.0|^9.0",
32+
"phpunit/phpunit": "^9.0"
3033
},
3134
"extra": {
3235
"laravel": {

src/BladeFilterLexer.php

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
3+
namespace Pine\BladeFilters;
4+
5+
use Doctrine\Common\Lexer\AbstractLexer;
6+
7+
class BladeFilterLexer extends AbstractLexer
8+
{
9+
/**
10+
* All tokens that are not valid identifiers must be < 100
11+
*/
12+
public const T_NONE = 1;
13+
public const T_STRING = 2;
14+
public const T_VARIABLE = 7;
15+
public const T_LITERAL = 8;
16+
public const T_INTEGER = 9;
17+
public const T_FLOAT = 10;
18+
19+
/**
20+
* All tokens that are also identifiers should be >= 100,
21+
*/
22+
public const T_OPEN_PARENTHESIS = 100;
23+
public const T_CLOSE_PARENTHESIS = 101;
24+
public const T_EQUALS = 102;
25+
public const T_COLON = 103;
26+
public const T_COMMA = 104;
27+
public const T_PIPE = 105;
28+
29+
/**
30+
* @inheritdoc
31+
*/
32+
protected function getCatchablePatterns()
33+
{
34+
return [
35+
'\(.*?\)',
36+
//Expression
37+
38+
'[a-z_\\\][a-z0-9_]*[a-z0-9_]{1}',
39+
// safe string
40+
41+
"[\'\"](?:[^'\"]|'')*[\'\"]",
42+
// single or double quoted string
43+
44+
'(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
45+
//integer, float
46+
47+
'\$[a-z_][a-z0-9_]*(?:->[a-z_][a-z0-9_]*)*',
48+
// a variable
49+
];
50+
}
51+
52+
/**
53+
* @inheritdoc
54+
*/
55+
protected function getNonCatchablePatterns()
56+
{
57+
/**
58+
* whitespace
59+
*/
60+
return ['\s+'];
61+
}
62+
63+
/**
64+
* @inheritdoc
65+
*/
66+
protected function getType(&$value)
67+
{
68+
switch (true) {
69+
/**
70+
* Recognize numeric values
71+
*/
72+
case (is_numeric($value)):
73+
if (strpos($value, '.') !== false || stripos($value, 'e') !== false) {
74+
return self::T_FLOAT;
75+
}
76+
77+
return self::T_INTEGER;
78+
79+
/**
80+
* Recognize quoted strings
81+
*/
82+
case ($value[0] === '\'' || $value[0] == '"'):
83+
return self::T_STRING;
84+
/**
85+
* Recognize variables
86+
*/
87+
case ($value[0] === '$'):
88+
return self::T_VARIABLE;
89+
90+
/**
91+
* Recognize symbols
92+
*/
93+
case ($value === '|'):
94+
return self::T_PIPE;
95+
case ($value === ':'):
96+
return self::T_COLON;
97+
case ($value === ','):
98+
return self::T_COMMA;
99+
case ($value === '='):
100+
return self::T_EQUALS;
101+
default:
102+
return self::T_LITERAL;;
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)