mirror of
https://github.com/filamentphp/plugin-skeleton.git
synced 2025-12-06 13:38:53 +08:00
Merge pull request #7 from filamentphp/asset-stubs
This commit is contained in:
21
.github/workflows/fix-php-code-style-issues.yml
vendored
Normal file
21
.github/workflows/fix-php-code-style-issues.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: Fix PHP code style issues
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
php-code-styling:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Fix PHP code style issues
|
||||
uses: aglipanci/laravel-pint-action@1.0.0
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Fix styling
|
||||
23
.github/workflows/php-cs-fixer.yml
vendored
23
.github/workflows/php-cs-fixer.yml
vendored
@@ -1,23 +0,0 @@
|
||||
name: Check & fix styling
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
php-cs-fixer:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Run PHP CS Fixer
|
||||
uses: docker://oskarstark/php-cs-fixer-ga
|
||||
with:
|
||||
args: --config=.php_cs.dist.php --allow-risky=yes
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Fix styling
|
||||
4
.github/workflows/phpstan.yml
vendored
4
.github/workflows/phpstan.yml
vendored
@@ -11,12 +11,12 @@ jobs:
|
||||
name: phpstan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.0'
|
||||
php-version: '8.1'
|
||||
coverage: none
|
||||
|
||||
- name: Install composer dependencies
|
||||
|
||||
6
.github/workflows/run-tests.yml
vendored
6
.github/workflows/run-tests.yml
vendored
@@ -13,18 +13,18 @@ jobs:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
php: [8.0, 8.1]
|
||||
php: [8.1]
|
||||
laravel: [9.*]
|
||||
stability: [prefer-lowest, prefer-stable]
|
||||
include:
|
||||
- laravel: 9.*
|
||||
testbench: ^7.0
|
||||
testbench: 7.*
|
||||
|
||||
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
|
||||
2
.github/workflows/update-changelog.yml
vendored
2
.github/workflows/update-changelog.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: main
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
$finder = Symfony\Component\Finder\Finder::create()
|
||||
->in([
|
||||
__DIR__ . '/src',
|
||||
__DIR__ . '/tests',
|
||||
])
|
||||
->name('*.php')
|
||||
->notName('*.blade.php')
|
||||
->ignoreDotFiles(true)
|
||||
->ignoreVCS(true);
|
||||
|
||||
return (new PhpCsFixer\Config())
|
||||
->setRules([
|
||||
'@PSR12' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'ordered_imports' => ['sort_algorithm' => 'alpha'],
|
||||
'no_unused_imports' => true,
|
||||
'not_operator_with_successor_space' => true,
|
||||
'trailing_comma_in_multiline' => true,
|
||||
'phpdoc_scalar' => true,
|
||||
'unary_operator_spaces' => true,
|
||||
'binary_operator_spaces' => true,
|
||||
'blank_line_before_statement' => [
|
||||
'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'],
|
||||
],
|
||||
'phpdoc_single_line_var_spacing' => true,
|
||||
'phpdoc_var_without_name' => true,
|
||||
'class_attributes_separation' => [
|
||||
'elements' => [
|
||||
'method' => 'one',
|
||||
],
|
||||
],
|
||||
'method_argument_space' => [
|
||||
'on_multiline' => 'ensure_fully_multiline',
|
||||
'keep_multiple_spaces_after_comma' => true,
|
||||
],
|
||||
'single_trait_insert_per_statement' => true,
|
||||
])
|
||||
->setFinder($finder);
|
||||
@@ -22,11 +22,14 @@
|
||||
"illuminate/contracts": "^9.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "^1.0",
|
||||
"nunomaduro/collision": "^6.0",
|
||||
"nunomaduro/larastan": "^2.0.1",
|
||||
"orchestra/testbench": "^7.0",
|
||||
"pestphp/pest": "^1.21",
|
||||
"pestphp/pest-plugin-laravel": "^1.1",
|
||||
"pestphp/pest-plugin-livewire": "^1.0",
|
||||
"pestphp/pest-plugin-parallel": "^0.3",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
@@ -45,12 +48,21 @@
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"analyse": "vendor/bin/phpstan analyse",
|
||||
"test": "vendor/bin/pest",
|
||||
"test-coverage": "vendor/bin/pest coverage"
|
||||
"pint": "vendor/bin/pint",
|
||||
"test:pest": "vendor/bin/pest --parallel",
|
||||
"test:phpstan": "vendor/bin/phpstan analyse",
|
||||
"test": [
|
||||
"@test:pest",
|
||||
"@test:phpstan"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"pestphp/pest-plugin": true,
|
||||
"phpstan/extension-installer": true
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
// config for VendorName/Skeleton
|
||||
return [
|
||||
|
||||
|
||||
595
configure.php
595
configure.php
@@ -1,125 +1,6 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
function ask(string $question, string $default = ''): string {
|
||||
$answer = readline($question . ($default ? " ({$default})" : null) . ': ');
|
||||
|
||||
if (! $answer) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $answer;
|
||||
}
|
||||
|
||||
function confirm(string $question, bool $default = false): bool {
|
||||
$answer = ask($question . ' (' . ($default ? 'Y/n' : 'y/N') . ')');
|
||||
|
||||
if (! $answer) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return strtolower($answer) === 'y';
|
||||
}
|
||||
|
||||
function writeln(string $line): void {
|
||||
echo $line . PHP_EOL;
|
||||
}
|
||||
|
||||
function run(string $command): string {
|
||||
return trim(shell_exec($command));
|
||||
}
|
||||
|
||||
function str_after(string $subject, string $search): string {
|
||||
$pos = strrpos($subject, $search);
|
||||
|
||||
if ($pos === false) {
|
||||
return $subject;
|
||||
}
|
||||
|
||||
return substr($subject, $pos + strlen($search));
|
||||
}
|
||||
|
||||
function slugify(string $subject): string {
|
||||
return strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $subject), '-'));
|
||||
}
|
||||
|
||||
function title_case(string $subject): string {
|
||||
return str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $subject)));
|
||||
}
|
||||
|
||||
function replace_in_file(string $file, array $replacements): void {
|
||||
$contents = file_get_contents($file);
|
||||
|
||||
file_put_contents(
|
||||
$file,
|
||||
str_replace(
|
||||
array_keys($replacements),
|
||||
array_values($replacements),
|
||||
$contents
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function remove_prefix(string $prefix, string $content): string {
|
||||
if (str_starts_with($content, $prefix)) {
|
||||
return substr($content, strlen($prefix));
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
function remove_composer_deps(array $names) {
|
||||
$data = json_decode(file_get_contents(__DIR__.'/composer.json'), true);
|
||||
|
||||
foreach($data['require-dev'] as $name => $version) {
|
||||
if (in_array($name, $names, true)) {
|
||||
unset($data['require-dev'][$name]);
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents(__DIR__.'/composer.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
function remove_composer_script($scriptName) {
|
||||
$data = json_decode(file_get_contents(__DIR__.'/composer.json'), true);
|
||||
|
||||
foreach($data['scripts'] as $name => $script) {
|
||||
if ($scriptName === $name) {
|
||||
unset($data['scripts'][$name]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents(__DIR__.'/composer.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
function remove_readme_paragraphs(string $file): void {
|
||||
$contents = file_get_contents($file);
|
||||
|
||||
file_put_contents(
|
||||
$file,
|
||||
preg_replace('/<!--delete-->.*<!--\/delete-->/s', '', $contents) ?: $contents
|
||||
);
|
||||
}
|
||||
|
||||
function safeUnlink(string $filename) {
|
||||
if (file_exists($filename) && is_file($filename)) {
|
||||
unlink($filename);
|
||||
}
|
||||
}
|
||||
|
||||
function determineSeparator(string $path): string {
|
||||
return str_replace('/', DIRECTORY_SEPARATOR, $path);
|
||||
}
|
||||
|
||||
function replaceForWindows(): array {
|
||||
return preg_split('/\\r\\n|\\r|\\n/', run('dir /S /B * | findstr /v /i .git\ | findstr /v /i vendor | findstr /v /i '.basename(__FILE__).' | findstr /r /i /M /F:/ ":author :vendor :package VendorName skeleton vendor_name vendor_slug author@domain.com"'));
|
||||
}
|
||||
|
||||
function replaceForAllOtherOSes(): array {
|
||||
return explode(PHP_EOL, run('grep -E -r -l -i ":author|:vendor|:package|VendorName|skeleton|vendor_name|vendor_slug|author@domain.com" --exclude-dir=vendor ./* ./.github/* | grep -v ' . basename(__FILE__)));
|
||||
}
|
||||
|
||||
$gitName = run('git config user.name');
|
||||
$authorName = ask('Author name', $gitName);
|
||||
|
||||
@@ -148,7 +29,7 @@ $className = ask('Class name', $className);
|
||||
$description = ask('Package description', "This is my package {$packageSlug}");
|
||||
|
||||
$usePhpStan = confirm('Enable PhpStan?', true);
|
||||
$usePhpCsFixer = confirm('Enable PhpCsFixer?', true);
|
||||
$usePint = confirm('Enable Pint?', true);
|
||||
$useUpdateChangelogWorkflow = confirm('Use automatic changelog updater workflow?', true);
|
||||
|
||||
writeln('------');
|
||||
@@ -157,11 +38,12 @@ writeln("Vendor : {$vendorName} ({$vendorSlug})");
|
||||
writeln("Package : {$packageSlug} <{$description}>");
|
||||
writeln("Namespace : {$vendorNamespace}\\{$className}");
|
||||
writeln("Class name : {$className}");
|
||||
writeln("---");
|
||||
writeln("Packages & Utilities");
|
||||
writeln("Use PhpCsFixer : " . ($usePhpCsFixer ? 'yes' : 'no'));
|
||||
writeln("Use Larastan/PhpStan : " . ($usePhpStan ? 'yes' : 'no'));
|
||||
writeln("Use Auto-Changelog : " . ($useUpdateChangelogWorkflow ? 'yes' : 'no'));
|
||||
writeln('---');
|
||||
writeln('Packages & Utilities');
|
||||
writeln('Use PhpCsFixer : ' . ($usePhpCsFixer ? 'yes' : 'no'));
|
||||
writeln('Use Larastan/PhpStan : ' . ($usePhpStan ? 'yes' : 'no'));
|
||||
writeln('Use Pint : ' . ($usePint ? 'yes' : 'no'));
|
||||
writeln('Use Auto-Changelog : ' . ($useUpdateChangelogWorkflow ? 'yes' : 'no'));
|
||||
writeln('------');
|
||||
|
||||
writeln('This script will replace the above values in all relevant files in the project directory.');
|
||||
@@ -200,9 +82,15 @@ foreach ($files as $file) {
|
||||
};
|
||||
}
|
||||
|
||||
if (! $usePhpCsFixer) {
|
||||
safeUnlink(__DIR__ . '/.php_cs.dist.php');
|
||||
safeUnlink(__DIR__ . '/.github/workflows/php-cs-fixer.yml');
|
||||
if (! $usePint) {
|
||||
safeUnlink(__DIR__ . '/pint.json');
|
||||
safeUnlink(__DIR__ . '/.github/workflows/pint.yml');
|
||||
|
||||
remove_composer_deps([
|
||||
'laravel/pint',
|
||||
]);
|
||||
|
||||
remove_composer_script(['pint']);
|
||||
}
|
||||
|
||||
if (! $usePhpStan) {
|
||||
@@ -217,7 +105,10 @@ if (! $usePhpStan) {
|
||||
'nunomaduro/larastan',
|
||||
]);
|
||||
|
||||
remove_composer_script('phpstan');
|
||||
remove_composer_script([
|
||||
'test:phpstan',
|
||||
'@test:phpstan',
|
||||
]);
|
||||
}
|
||||
|
||||
if (! $useUpdateChangelogWorkflow) {
|
||||
@@ -227,3 +118,449 @@ if (! $useUpdateChangelogWorkflow) {
|
||||
confirm('Execute `composer install` and run tests?') && run('composer install && composer test');
|
||||
|
||||
confirm('Let this script delete itself?', true) && unlink(__FILE__);
|
||||
|
||||
function ask(string $question, string $default = ''): string
|
||||
{
|
||||
$consoleColor = new ConsoleColor();
|
||||
$def = $default ? $consoleColor->apply('yellow', " ({$default})") : null;
|
||||
$answer = readline($consoleColor->apply('green', $question . $def . ': '));
|
||||
|
||||
if (! $answer) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $answer;
|
||||
}
|
||||
|
||||
function confirm(string $question, bool $default = false): bool
|
||||
{
|
||||
$consoleColor = new ConsoleColor();
|
||||
|
||||
$answer = ask($question, ($default ? 'Y/n' : 'y/N'));
|
||||
|
||||
if (! $answer) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return strtolower($answer) === 'y';
|
||||
}
|
||||
|
||||
function writeln(string $line): void
|
||||
{
|
||||
echo $line . PHP_EOL;
|
||||
}
|
||||
|
||||
function run(string $command): string
|
||||
{
|
||||
return trim(shell_exec($command));
|
||||
}
|
||||
|
||||
function str_after(string $subject, string $search): string
|
||||
{
|
||||
$pos = strrpos($subject, $search);
|
||||
|
||||
if ($pos === false) {
|
||||
return $subject;
|
||||
}
|
||||
|
||||
return substr($subject, $pos + strlen($search));
|
||||
}
|
||||
|
||||
function slugify(string $subject): string
|
||||
{
|
||||
return strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $subject), '-'));
|
||||
}
|
||||
|
||||
function title_case(string $subject): string
|
||||
{
|
||||
return str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $subject)));
|
||||
}
|
||||
|
||||
function replace_in_file(string $file, array $replacements): void
|
||||
{
|
||||
$contents = file_get_contents($file);
|
||||
|
||||
file_put_contents(
|
||||
$file,
|
||||
str_replace(
|
||||
array_keys($replacements),
|
||||
array_values($replacements),
|
||||
$contents
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function remove_prefix(string $prefix, string $content): string
|
||||
{
|
||||
if (str_starts_with($content, $prefix)) {
|
||||
return substr($content, strlen($prefix));
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
function remove_composer_deps(array $names)
|
||||
{
|
||||
$data = json_decode(file_get_contents(__DIR__ . '/composer.json'), true);
|
||||
|
||||
foreach ($data['require-dev'] as $name => $version) {
|
||||
if (in_array($name, $names, true)) {
|
||||
unset($data['require-dev'][$name]);
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents(__DIR__ . '/composer.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
function remove_composer_script(array $scriptNames)
|
||||
{
|
||||
$data = json_decode(file_get_contents(__DIR__ . '/composer.json'), true);
|
||||
|
||||
foreach ($data['scripts'] as $name => $script) {
|
||||
if (is_array($script)) {
|
||||
foreach ($script as $k => $s) {
|
||||
if (in_array($s, $scriptNames)) {
|
||||
unset($data['scripts'][$name][$k]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} elseif (in_array($name, $scriptNames)) {
|
||||
unset($data['scripts'][$name]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents(__DIR__ . '/composer.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
function remove_readme_paragraphs(string $file): void
|
||||
{
|
||||
$contents = file_get_contents($file);
|
||||
|
||||
file_put_contents(
|
||||
$file,
|
||||
preg_replace('/<!--delete-->.*<!--\/delete-->/s', '', $contents) ?: $contents
|
||||
);
|
||||
}
|
||||
|
||||
function safeUnlink(string $filename)
|
||||
{
|
||||
if (file_exists($filename) && is_file($filename)) {
|
||||
unlink($filename);
|
||||
}
|
||||
}
|
||||
|
||||
function determineSeparator(string $path): string
|
||||
{
|
||||
return str_replace('/', DIRECTORY_SEPARATOR, $path);
|
||||
}
|
||||
|
||||
function replaceForWindows(): array
|
||||
{
|
||||
return preg_split('/\\r\\n|\\r|\\n/', run('dir /S /B * | findstr /v /i .git\ | findstr /v /i vendor | findstr /v /i ' . basename(__FILE__) . ' | findstr /r /i /M /F:/ ":author :vendor :package VendorName skeleton vendor_name vendor_slug author@domain.com"'));
|
||||
}
|
||||
|
||||
function replaceForAllOtherOSes(): array
|
||||
{
|
||||
return explode(PHP_EOL, run('grep -E -r -l -i ":author|:vendor|:package|VendorName|skeleton|vendor_name|vendor_slug|author@domain.com" --exclude-dir=vendor ./* ./.github/* | grep -v ' . basename(__FILE__)));
|
||||
}
|
||||
|
||||
class ConsoleColor
|
||||
{
|
||||
const FOREGROUND = 38;
|
||||
|
||||
const BACKGROUND = 48;
|
||||
|
||||
const COLOR256_REGEXP = '~^(bg_)?color_([0-9]{1,3})$~';
|
||||
|
||||
const RESET_STYLE = 0;
|
||||
|
||||
/** @var bool */
|
||||
private $isSupported;
|
||||
|
||||
/** @var bool */
|
||||
private $forceStyle = false;
|
||||
|
||||
/** @var array */
|
||||
private $styles = [
|
||||
'none' => null,
|
||||
'bold' => '1',
|
||||
'dark' => '2',
|
||||
'italic' => '3',
|
||||
'underline' => '4',
|
||||
'blink' => '5',
|
||||
'reverse' => '7',
|
||||
'concealed' => '8',
|
||||
|
||||
'default' => '39',
|
||||
'black' => '30',
|
||||
'red' => '31',
|
||||
'green' => '32',
|
||||
'yellow' => '33',
|
||||
'blue' => '34',
|
||||
'magenta' => '35',
|
||||
'cyan' => '36',
|
||||
'light_gray' => '37',
|
||||
|
||||
'dark_gray' => '90',
|
||||
'light_red' => '91',
|
||||
'light_green' => '92',
|
||||
'light_yellow' => '93',
|
||||
'light_blue' => '94',
|
||||
'light_magenta' => '95',
|
||||
'light_cyan' => '96',
|
||||
'white' => '97',
|
||||
|
||||
'bg_default' => '49',
|
||||
'bg_black' => '40',
|
||||
'bg_red' => '41',
|
||||
'bg_green' => '42',
|
||||
'bg_yellow' => '43',
|
||||
'bg_blue' => '44',
|
||||
'bg_magenta' => '45',
|
||||
'bg_cyan' => '46',
|
||||
'bg_light_gray' => '47',
|
||||
|
||||
'bg_dark_gray' => '100',
|
||||
'bg_light_red' => '101',
|
||||
'bg_light_green' => '102',
|
||||
'bg_light_yellow' => '103',
|
||||
'bg_light_blue' => '104',
|
||||
'bg_light_magenta' => '105',
|
||||
'bg_light_cyan' => '106',
|
||||
'bg_white' => '107',
|
||||
];
|
||||
|
||||
/** @var array */
|
||||
private $themes = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->isSupported = $this->isSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $style
|
||||
* @param string $text
|
||||
* @return string
|
||||
*
|
||||
* @throws InvalidStyleException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function apply($style, $text)
|
||||
{
|
||||
if (! $this->isStyleForced() && ! $this->isSupported()) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
if (is_string($style)) {
|
||||
$style = [$style];
|
||||
}
|
||||
if (! is_array($style)) {
|
||||
throw new \InvalidArgumentException('Style must be string or array.');
|
||||
}
|
||||
|
||||
$sequences = [];
|
||||
|
||||
foreach ($style as $s) {
|
||||
if (isset($this->themes[$s])) {
|
||||
$sequences = array_merge($sequences, $this->themeSequence($s));
|
||||
} elseif ($this->isValidStyle($s)) {
|
||||
$sequences[] = $this->styleSequence($s);
|
||||
} else {
|
||||
throw new InvalidStyleException($s);
|
||||
}
|
||||
}
|
||||
|
||||
$sequences = array_filter($sequences, function ($val) {
|
||||
return $val !== null;
|
||||
});
|
||||
|
||||
if (empty($sequences)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
return $this->escSequence(implode(';', $sequences)) . $text . $this->escSequence(self::RESET_STYLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $forceStyle
|
||||
*/
|
||||
public function setForceStyle($forceStyle)
|
||||
{
|
||||
$this->forceStyle = (bool) $forceStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isStyleForced()
|
||||
{
|
||||
return $this->forceStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $themes
|
||||
*
|
||||
* @throws InvalidStyleException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setThemes(array $themes)
|
||||
{
|
||||
$this->themes = [];
|
||||
foreach ($themes as $name => $styles) {
|
||||
$this->addTheme($name, $styles);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param array|string $styles
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws InvalidStyleException
|
||||
*/
|
||||
public function addTheme($name, $styles)
|
||||
{
|
||||
if (is_string($styles)) {
|
||||
$styles = [$styles];
|
||||
}
|
||||
if (! is_array($styles)) {
|
||||
throw new \InvalidArgumentException('Style must be string or array.');
|
||||
}
|
||||
|
||||
foreach ($styles as $style) {
|
||||
if (! $this->isValidStyle($style)) {
|
||||
throw new InvalidStyleException($style);
|
||||
}
|
||||
}
|
||||
|
||||
$this->themes[$name] = $styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getThemes()
|
||||
{
|
||||
return $this->themes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTheme($name)
|
||||
{
|
||||
return isset($this->themes[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function removeTheme($name)
|
||||
{
|
||||
unset($this->themes[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSupported()
|
||||
{
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
// phpcs:ignore Generic.PHP.NoSilencedErrors,PHPCompatibility.FunctionUse.NewFunctions.sapi_windows_vt100_supportFound
|
||||
if (function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support(STDOUT)) {
|
||||
return true;
|
||||
} elseif (getenv('ANSICON') !== false || getenv('ConEmuANSI') === 'ON') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
// phpcs:ignore Generic.PHP.NoSilencedErrors
|
||||
return function_exists('posix_isatty') && @posix_isatty(STDOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function are256ColorsSupported()
|
||||
{
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
// phpcs:ignore Generic.PHP.NoSilencedErrors,PHPCompatibility.FunctionUse.NewFunctions.sapi_windows_vt100_supportFound
|
||||
return function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support(STDOUT);
|
||||
} else {
|
||||
return strpos(getenv('TERM'), '256color') !== false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getPossibleStyles()
|
||||
{
|
||||
return array_keys($this->styles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return string[]
|
||||
*/
|
||||
private function themeSequence($name)
|
||||
{
|
||||
$sequences = [];
|
||||
foreach ($this->themes[$name] as $style) {
|
||||
$sequences[] = $this->styleSequence($style);
|
||||
}
|
||||
|
||||
return $sequences;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $style
|
||||
* @return string
|
||||
*/
|
||||
private function styleSequence($style)
|
||||
{
|
||||
if (array_key_exists($style, $this->styles)) {
|
||||
return $this->styles[$style];
|
||||
}
|
||||
|
||||
if (! $this->are256ColorsSupported()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
preg_match(self::COLOR256_REGEXP, $style, $matches);
|
||||
|
||||
$type = $matches[1] === 'bg_' ? self::BACKGROUND : self::FOREGROUND;
|
||||
$value = $matches[2];
|
||||
|
||||
return "$type;5;$value";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $style
|
||||
* @return bool
|
||||
*/
|
||||
private function isValidStyle($style)
|
||||
{
|
||||
return array_key_exists($style, $this->styles) || preg_match(self::COLOR256_REGEXP, $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int $value
|
||||
* @return string
|
||||
*/
|
||||
private function escSequence($value)
|
||||
{
|
||||
return "\033[{$value}m";
|
||||
}
|
||||
}
|
||||
|
||||
20
package.json
Normal file
20
package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev:styles": "npx tailwindcss -i resources/css/plugin.css -o resources/dist/skeleton.css --postcss --watch",
|
||||
"dev:scripts": "esbuild resources/js/plugin.js --bundle --sourcemap=inline --outfile=resources/dist/skeleton.js --watch",
|
||||
"build:styles": "npx tailwindcss -i resources/css/plugin.css -o resources/dist/skeleton.css --postcss --minify",
|
||||
"build:scripts": "esbuild resources/js/plugin.js --bundle --minify --outfile=resources/dist/skeleton.js",
|
||||
"build:purge": "filament-purge -i resources/dist/skeleton.css -o resources/dist/skeleton.css",
|
||||
"dev": "npm-run-all --parallel dev:*",
|
||||
"build": "npm-run-all build:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@awcodes/filament-plugin-purge": "^1.0.2",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"esbuild": "^0.8.57",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.4.14",
|
||||
"tailwindcss": "^3.1.6"
|
||||
}
|
||||
}
|
||||
11
pint.json
Normal file
11
pint.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"preset": "laravel",
|
||||
"rules": {
|
||||
"blank_line_before_statement": true,
|
||||
"concat_space": {
|
||||
"spacing": "one"
|
||||
},
|
||||
"method_argument_space": true,
|
||||
"single_trait_insert_per_statement": true
|
||||
}
|
||||
}
|
||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
1
resources/css/plugin.css
Normal file
1
resources/css/plugin.css
Normal file
@@ -0,0 +1 @@
|
||||
@tailwind utilities;
|
||||
0
resources/dist/.gitkeep
vendored
Normal file
0
resources/dist/.gitkeep
vendored
Normal file
0
resources/js/plugin.js
Normal file
0
resources/js/plugin.js
Normal file
0
resources/lang/en/.gitkeep
Normal file
0
resources/lang/en/.gitkeep
Normal file
@@ -3,8 +3,38 @@
|
||||
namespace VendorName\Skeleton;
|
||||
|
||||
use Filament\PluginServiceProvider;
|
||||
use Spatie\LaravelPackageTools\Package;
|
||||
|
||||
class SkeletonServiceProvider extends PluginServiceProvider
|
||||
{
|
||||
public static string $name = 'skeleton';
|
||||
|
||||
protected array $resources = [
|
||||
// CustomResource::class,
|
||||
];
|
||||
|
||||
protected array $pages = [
|
||||
// CustomPage::class,
|
||||
];
|
||||
|
||||
protected array $widgets = [
|
||||
// CustomWidget::class,
|
||||
];
|
||||
|
||||
protected array $styles = [
|
||||
'plugin-skeleton' => __DIR__ . '/../dist/skeleton.css',
|
||||
];
|
||||
|
||||
protected array $scripts = [
|
||||
'plugin-skeleton' => __DIR__ . '/../dist/skeleton.js',
|
||||
];
|
||||
|
||||
// protected array $beforeCoreScripts = [
|
||||
// 'plugin-skeleton' => __DIR__ . '/../dist/skeleton.js',
|
||||
// ];
|
||||
|
||||
public function configurePackage(Package $package): void
|
||||
{
|
||||
$package->name(static::$name);
|
||||
}
|
||||
}
|
||||
|
||||
21
tailwind.config.js
Normal file
21
tailwind.config.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const colors = require("tailwindcss/colors");
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["./resources/views/**/*.blade.php", "./src/**/*.php"],
|
||||
darkMode: "class",
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
danger: colors.rose,
|
||||
primary: colors.yellow,
|
||||
success: colors.green,
|
||||
warning: colors.amber,
|
||||
},
|
||||
},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
@@ -15,7 +15,7 @@ class TestCase extends Orchestra
|
||||
parent::setUp();
|
||||
|
||||
Factory::guessFactoryNamesUsing(
|
||||
fn (string $modelName) => 'VendorName\\Skeleton\\Database\\Factories\\'.class_basename($modelName).'Factory'
|
||||
fn (string $modelName) => 'VendorName\\Skeleton\\Database\\Factories\\' . class_basename($modelName) . 'Factory'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user