Add Laravel guidelines, Spanish translations, and configuration updates

- Added Laravel Boost Guidelines for structured development practices.
- Introduced Spanish translations for `auth`, `passwords`, and additional JSON keys.
- Configured markdown highlighting with Shiki in `config/markdown.php`.
- Updated sidebar layout for improved interactivity and styling.
- Enhanced user feedback with a copy-to-clipboard directive and toast notifications in Flux.
This commit is contained in:
HolgerHatGarKeineNode
2025-11-21 09:48:30 +01:00
parent c2193233f7
commit 1ef9b62762
22 changed files with 2262 additions and 19 deletions

View File

@@ -54,3 +54,579 @@ Components use the format: `<flux:name />`
- Icon components accept variant options (outline, solid, mini, micro)
- Size props typically offer xs, sm, base, lg, xl, 2xl options
- Variant props provide visual style alternatives
===
<laravel-boost-guidelines>
=== foundation rules ===
# Laravel Boost Guidelines
The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications.
## Foundational Context
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
- php - 8.4.14
- laravel/framework (LARAVEL) - v12
- laravel/prompts (PROMPTS) - v0
- livewire/flux (FLUXUI_FREE) - v2
- livewire/flux-pro (FLUXUI_PRO) - v2
- livewire/livewire (LIVEWIRE) - v3
- livewire/volt (VOLT) - v1
- laravel/mcp (MCP) - v0
- laravel/pint (PINT) - v1
- laravel/sail (SAIL) - v1
- pestphp/pest (PEST) - v3
- phpunit/phpunit (PHPUNIT) - v11
- tailwindcss (TAILWINDCSS) - v4
## Conventions
- You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, naming.
- Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`.
- Check for existing components to reuse before writing a new one.
## Verification Scripts
- Do not create verification scripts or tinker when tests cover that functionality and prove it works. Unit and feature tests are more important.
## Application Structure & Architecture
- Stick to existing directory structure - don't create new base folders without approval.
- Do not change the application's dependencies without approval.
## Frontend Bundling
- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `vendor/bin/sail yarn run build`, `vendor/bin/sail yarn run dev`, or `vendor/bin/sail composer run dev`. Ask them.
## Replies
- Be concise in your explanations - focus on what's important rather than explaining obvious details.
## Documentation Files
- You must only create documentation files if explicitly requested by the user.
=== boost rules ===
## Laravel Boost
- Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them.
## Artisan
- Use the `list-artisan-commands` tool when you need to call an Artisan command to double check the available parameters.
## URLs
- Whenever you share a project URL with the user you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain / IP, and port.
## Tinker / Debugging
- You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly.
- Use the `database-query` tool when you only need to read from the database.
## Reading Browser Logs With the `browser-logs` Tool
- You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost.
- Only recent browser logs will be useful - ignore old logs.
## Searching Documentation (Critically Important)
- Boost comes with a powerful `search-docs` tool you should use before any other approaches. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation specific for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages.
- The 'search-docs' tool is perfect for all Laravel related packages, including Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc.
- You must use this tool to search for Laravel-ecosystem documentation before falling back to other approaches.
- Search the documentation before making code changes to ensure we are taking the correct approach.
- Use multiple, broad, simple, topic based queries to start. For example: `['rate limiting', 'routing rate limiting', 'routing']`.
- Do not add package names to queries - package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`.
### Available Search Syntax
- You can and should pass multiple queries at once. The most relevant results will be returned first.
1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'
2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit"
3. Quoted Phrases (Exact Position) - query="infinite scroll" - Words must be adjacent and in that order
4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit"
5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms
=== php rules ===
## PHP
- Always use curly braces for control structures, even if it has one line.
### Constructors
- Use PHP 8 constructor property promotion in `__construct()`.
- <code-snippet>public function __construct(public GitHub $github) { }</code-snippet>
- Do not allow empty `__construct()` methods with zero parameters.
### Type Declarations
- Always use explicit return type declarations for methods and functions.
- Use appropriate PHP type hints for method parameters.
<code-snippet name="Explicit Return Types and Method Params" lang="php">
protected function isAccessible(User $user, ?string $path = null): bool
{
...
}
</code-snippet>
## Comments
- Prefer PHPDoc blocks over comments. Never use comments within the code itself unless there is something _very_ complex going on.
## PHPDoc Blocks
- Add useful array shape type definitions for arrays when appropriate.
## Enums
- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`.
=== sail rules ===
## Laravel Sail
- This project runs inside Laravel Sail's Docker containers. You MUST execute all commands through Sail.
- Start services using `vendor/bin/sail up -d` and stop them with `vendor/bin/sail stop`.
- Open the application in the browser by running `vendor/bin/sail open`.
- Always prefix PHP, Artisan, Composer, and Node commands** with `vendor/bin/sail`. Examples:
- Run Artisan Commands: `vendor/bin/sail artisan migrate`
- Install Composer packages: `vendor/bin/sail composer install`
- Execute node commands: `vendor/bin/sail yarn run dev`
- Execute PHP scripts: `vendor/bin/sail php [script]`
- View all available Sail commands by running `vendor/bin/sail` without arguments.
=== tests rules ===
## Test Enforcement
- Every change must be programmatically tested. Write a new test or update an existing test, then run the affected tests to make sure they pass.
- Run the minimum number of tests needed to ensure code quality and speed. Use `vendor/bin/sail artisan test` with a specific filename or filter.
=== laravel/core rules ===
## Do Things the Laravel Way
- Use `vendor/bin/sail artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using the `list-artisan-commands` tool.
- If you're creating a generic PHP class, use `vendor/bin/sail artisan make:class`.
- Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior.
### Database
- Always use proper Eloquent relationship methods with return type hints. Prefer relationship methods over raw queries or manual joins.
- Use Eloquent models and relationships before suggesting raw database queries
- Avoid `DB::`; prefer `Model::query()`. Generate code that leverages Laravel's ORM capabilities rather than bypassing them.
- Generate code that prevents N+1 query problems by using eager loading.
- Use Laravel's query builder for very complex database operations.
### Model Creation
- When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `list-artisan-commands` to check the available options to `vendor/bin/sail artisan make:model`.
### APIs & Eloquent Resources
- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.
### Controllers & Validation
- Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages.
- Check sibling Form Requests to see if the application uses array or string based validation rules.
### Queues
- Use queued jobs for time-consuming operations with the `ShouldQueue` interface.
### Authentication & Authorization
- Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.).
### URL Generation
- When generating links to other pages, prefer named routes and the `route()` function.
### Configuration
- Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`.
### Testing
- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
- When creating tests, make use of `vendor/bin/sail artisan make:test [options] {name}` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests.
### Vite Error
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `vendor/bin/sail yarn run build` or ask the user to run `vendor/bin/sail yarn run dev` or `vendor/bin/sail composer run dev`.
=== laravel/v12 rules ===
## Laravel 12
- Use the `search-docs` tool to get version specific documentation.
- Since Laravel 11, Laravel has a new streamlined file structure which this project uses.
### Laravel 12 Structure
- No middleware files in `app/Http/Middleware/`.
- `bootstrap/app.php` is the file to register middleware, exceptions, and routing files.
- `bootstrap/providers.php` contains application specific service providers.
- **No app\Console\Kernel.php** - use `bootstrap/app.php` or `routes/console.php` for console configuration.
- **Commands auto-register** - files in `app/Console/Commands/` are automatically available and do not require manual registration.
### Database
- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost.
- Laravel 11 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`.
### Models
- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
=== fluxui-pro/core rules ===
## Flux UI Pro
- This project is using the Pro version of Flux UI. It has full access to the free components and variants, as well as full access to the Pro components and variants.
- Flux UI is a component library for Livewire. Flux is a robust, hand-crafted, UI component library for your Livewire applications. It's built using Tailwind CSS and provides a set of components that are easy to use and customize.
- You should use Flux UI components when available.
- Fallback to standard Blade components if Flux is unavailable.
- If available, use Laravel Boost's `search-docs` tool to get the exact documentation and code snippets available for this project.
- Flux UI components look like this:
<code-snippet name="Flux UI component usage example" lang="blade">
<flux:button variant="primary"/>
</code-snippet>
### Available Components
This is correct as of Boost installation, but there may be additional components within the codebase.
<available-flux-components>
accordion, autocomplete, avatar, badge, brand, breadcrumbs, button, calendar, callout, card, chart, checkbox, command, context, date-picker, dropdown, editor, field, heading, file upload, icon, input, modal, navbar, pagination, pillbox, popover, profile, radio, select, separator, switch, table, tabs, text, textarea, toast, tooltip
</available-flux-components>
=== livewire/core rules ===
## Livewire Core
- Use the `search-docs` tool to find exact version specific documentation for how to write Livewire & Livewire tests.
- Use the `vendor/bin/sail artisan make:livewire [Posts\CreatePost]` artisan command to create new components
- State should live on the server, with the UI reflecting it.
- All Livewire requests hit the Laravel backend, they're like regular HTTP requests. Always validate form data, and run authorization checks in Livewire actions.
## Livewire Best Practices
- Livewire components require a single root element.
- Use `wire:loading` and `wire:dirty` for delightful loading states.
- Add `wire:key` in loops:
```blade
@foreach ($items as $item)
<div wire:key="item-{{ $item->id }}">
{{ $item->name }}
</div>
@endforeach
```
- Prefer lifecycle hooks like `mount()`, `updatedFoo()` for initialization and reactive side effects:
<code-snippet name="Lifecycle hook examples" lang="php">
public function mount(User $user) { $this->user = $user; }
public function updatedSearch() { $this->resetPage(); }
</code-snippet>
## Testing Livewire
<code-snippet name="Example Livewire component test" lang="php">
Livewire::test(Counter::class)
->assertSet('count', 0)
->call('increment')
->assertSet('count', 1)
->assertSee(1)
->assertStatus(200);
</code-snippet>
<code-snippet name="Testing a Livewire component exists within a page" lang="php">
$this->get('/posts/create')
->assertSeeLivewire(CreatePost::class);
</code-snippet>
=== livewire/v3 rules ===
## Livewire 3
### Key Changes From Livewire 2
- These things changed in Livewire 2, but may not have been updated in this application. Verify this application's setup to ensure you conform with application conventions.
- Use `wire:model.live` for real-time updates, `wire:model` is now deferred by default.
- Components now use the `App\Livewire` namespace (not `App\Http\Livewire`).
- Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`).
- Use the `components.layouts.app` view as the typical layout path (not `layouts.app`).
### New Directives
- `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target` are available for use. Use the documentation to find usage examples.
### Alpine
- Alpine is now included with Livewire, don't manually include Alpine.js.
- Plugins included with Alpine: persist, intersect, collapse, and focus.
### Lifecycle Hooks
- You can listen for `livewire:init` to hook into Livewire initialization, and `fail.status === 419` for the page expiring:
<code-snippet name="livewire:load example" lang="js">
document.addEventListener('livewire:init', function () {
Livewire.hook('request', ({ fail }) => {
if (fail && fail.status === 419) {
alert('Your session expired');
}
});
Livewire.hook('message.failed', (message, component) => {
console.error(message);
});
});
</code-snippet>
=== volt/core rules ===
## Livewire Volt
- This project uses Livewire Volt for interactivity within its pages. New pages requiring interactivity must also use Livewire Volt. There is documentation available for it.
- Make new Volt components using `vendor/bin/sail artisan make:volt [name] [--test] [--pest]`
- Volt is a **class-based** and **functional** API for Livewire that supports single-file components, allowing a component's PHP logic and Blade templates to co-exist in the same file
- Livewire Volt allows PHP logic and Blade templates in one file. Components use the `@volt` directive.
- You must check existing Volt components to determine if they're functional or class based. If you can't detect that, ask the user which they prefer before writing a Volt component.
### Volt Functional Component Example
<code-snippet name="Volt Functional Component Example" lang="php">
@volt
<?php
use function Livewire\Volt\{state, computed};
state(['count' => 0]);
$increment = fn () => $this->count++;
$decrement = fn () => $this->count--;
$double = computed(fn () => $this->count * 2);
?>
<div>
<h1>Count: {{ $count }}</h1>
<h2>Double: {{ $this->double }}</h2>
<button wire:click="increment">+</button>
<button wire:click="decrement">-</button>
</div>
@endvolt
</code-snippet>
### Volt Class Based Component Example
To get started, define an anonymous class that extends Livewire\Volt\Component. Within the class, you may utilize all of the features of Livewire using traditional Livewire syntax:
<code-snippet name="Volt Class-based Volt Component Example" lang="php">
use Livewire\Volt\Component;
new class extends Component {
public $count = 0;
public function increment()
{
$this->count++;
}
} ?>
<div>
<h1>{{ $count }}</h1>
<button wire:click="increment">+</button>
</div>
</code-snippet>
### Testing Volt & Volt Components
- Use the existing directory for tests if it already exists. Otherwise, fallback to `tests/Feature/Volt`.
<code-snippet name="Livewire Test Example" lang="php">
use Livewire\Volt\Volt;
test('counter increments', function () {
Volt::test('counter')
->assertSee('Count: 0')
->call('increment')
->assertSee('Count: 1');
});
</code-snippet>
<code-snippet name="Volt Component Test Using Pest" lang="php">
declare(strict_types=1);
use App\Models\{User, Product};
use Livewire\Volt\Volt;
test('product form creates product', function () {
$user = User::factory()->create();
Volt::test('pages.products.create')
->actingAs($user)
->set('form.name', 'Test Product')
->set('form.description', 'Test Description')
->set('form.price', 99.99)
->call('create')
->assertHasNoErrors();
expect(Product::where('name', 'Test Product')->exists())->toBeTrue();
});
</code-snippet>
### Common Patterns
<code-snippet name="CRUD With Volt" lang="php">
<?php
use App\Models\Product;
use function Livewire\Volt\{state, computed};
state(['editing' => null, 'search' => '']);
$products = computed(fn() => Product::when($this->search,
fn($q) => $q->where('name', 'like', "%{$this->search}%")
)->get());
$edit = fn(Product $product) => $this->editing = $product->id;
$delete = fn(Product $product) => $product->delete();
?>
<!-- HTML / UI Here -->
</code-snippet>
<code-snippet name="Real-Time Search With Volt" lang="php">
<flux:input
wire:model.live.debounce.300ms="search"
placeholder="Search..."
/>
</code-snippet>
<code-snippet name="Loading States With Volt" lang="php">
<flux:button wire:click="save" wire:loading.attr="disabled">
<span wire:loading.remove>Save</span>
<span wire:loading>Saving...</span>
</flux:button>
</code-snippet>
=== pint/core rules ===
## Laravel Pint Code Formatter
- You must run `vendor/bin/sail bin pint --dirty` before finalizing changes to ensure your code matches the project's expected style.
- Do not run `vendor/bin/sail bin pint --test`, simply run `vendor/bin/sail bin pint` to fix any formatting issues.
=== pest/core rules ===
## Pest
### Testing
- If you need to verify a feature is working, write or update a Unit / Feature test.
### Pest Tests
- All tests must be written using Pest. Use `vendor/bin/sail artisan make:test --pest {name}`.
- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files - these are core to the application.
- Tests should test all of the happy paths, failure paths, and weird paths.
- Tests live in the `tests/Feature` and `tests/Unit` directories.
- Pest tests look and behave like this:
<code-snippet name="Basic Pest Test Example" lang="php">
it('is true', function () {
expect(true)->toBeTrue();
});
</code-snippet>
### Running Tests
- Run the minimal number of tests using an appropriate filter before finalizing code edits.
- To run all tests: `vendor/bin/sail artisan test`.
- To run all tests in a file: `vendor/bin/sail artisan test tests/Feature/ExampleTest.php`.
- To filter on a particular test name: `vendor/bin/sail artisan test --filter=testName` (recommended after making a change to a related file).
- When the tests relating to your changes are passing, ask the user if they would like to run the entire test suite to ensure everything is still passing.
### Pest Assertions
- When asserting status codes on a response, use the specific method like `assertForbidden` and `assertNotFound` instead of using `assertStatus(403)` or similar, e.g.:
<code-snippet name="Pest Example Asserting postJson Response" lang="php">
it('returns all', function () {
$response = $this->postJson('/api/docs', []);
$response->assertSuccessful();
});
</code-snippet>
### Mocking
- Mocking can be very helpful when appropriate.
- When mocking, you can use the `Pest\Laravel\mock` Pest function, but always import it via `use function Pest\Laravel\mock;` before using it. Alternatively, you can use `$this->mock()` if existing tests do.
- You can also create partial mocks using the same import or self method.
### Datasets
- Use datasets in Pest to simplify tests which have a lot of duplicated data. This is often the case when testing validation rules, so consider going with this solution when writing tests for validation rules.
<code-snippet name="Pest Dataset Example" lang="php">
it('has emails', function (string $email) {
expect($email)->not->toBeEmpty();
})->with([
'james' => 'james@laravel.com',
'taylor' => 'taylor@laravel.com',
]);
</code-snippet>
=== tailwindcss/core rules ===
## Tailwind Core
- Use Tailwind CSS classes to style HTML, check and use existing tailwind conventions within the project before writing your own.
- Offer to extract repeated patterns into components that match the project's conventions (i.e. Blade, JSX, Vue, etc..)
- Think through class placement, order, priority, and defaults - remove redundant classes, add classes to parent or child carefully to limit repetition, group elements logically
- You can use the `search-docs` tool to get exact examples from the official documentation when needed.
### Spacing
- When listing items, use gap utilities for spacing, don't use margins.
<code-snippet name="Valid Flex Gap Spacing Example" lang="html">
<div class="flex gap-8">
<div>Superior</div>
<div>Michigan</div>
<div>Erie</div>
</div>
</code-snippet>
### Dark Mode
- If existing pages and components support dark mode, new pages and components must support dark mode in a similar way, typically using `dark:`.
=== tailwindcss/v4 rules ===
## Tailwind 4
- Always use Tailwind CSS v4 - do not use the deprecated utilities.
- `corePlugins` is not supported in Tailwind v4.
- In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed.
<code-snippet name="Extending Theme in CSS" lang="css">
@theme {
--color-brand: oklch(0.72 0.11 178);
}
</code-snippet>
- In Tailwind v4, you import Tailwind using a regular CSS `@import` statement, not using the `@tailwind` directives used in v3:
<code-snippet name="Tailwind v4 Import Tailwind Diff" lang="diff">
- @tailwind base;
- @tailwind components;
- @tailwind utilities;
+ @import "tailwindcss";
</code-snippet>
### Replaced Utilities
- Tailwind v4 removed deprecated utilities. Do not use the deprecated option - use the replacement.
- Opacity values are still numeric.
| Deprecated | Replacement |
|------------+--------------|
| bg-opacity-* | bg-black/* |
| text-opacity-* | text-black/* |
| border-opacity-* | border-black/* |
| divide-opacity-* | divide-black/* |
| ring-opacity-* | ring-black/* |
| placeholder-opacity-* | placeholder-black/* |
| flex-shrink-* | shrink-* |
| flex-grow-* | grow-* |
| overflow-ellipsis | text-ellipsis |
| decoration-slice | box-decoration-slice |
| decoration-clone | box-decoration-clone |
</laravel-boost-guidelines>

11
.junie/mcp/mcp.json Normal file
View File

@@ -0,0 +1,11 @@
{
"mcpServers": {
"laravel-boost": {
"command": "vendor/bin/sail",
"args": [
"artisan",
"boost:mcp"
]
}
}
}

10
boost.json Normal file
View File

@@ -0,0 +1,10 @@
{
"agents": [
"phpstorm"
],
"editors": [
"phpstorm"
],
"guidelines": [],
"sail": true
}

View File

@@ -18,6 +18,7 @@
"livewire/volt": "^1.7.0",
"outhebox/blade-flags": "^1.5",
"spatie/laravel-ciphersweet": "^1.7",
"spatie/laravel-markdown": "^2.7",
"spatie/laravel-medialibrary": "^11.13",
"spatie/laravel-permission": "^6.20",
"spatie/laravel-sluggable": "^3.7",
@@ -28,6 +29,7 @@
"fakerphp/faker": "^1.23",
"laravel-lang/lang": "^15.22",
"laravel-lang/starter-kits": "^1.3",
"laravel/boost": "^1.8",
"laravel/pail": "^1.2.2",
"laravel/pint": "^1.18",
"laravel/sail": "^1.43",

403
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "72455cf4c50537280d36f9cda0228f1b",
"content-hash": "2b5ac6d2d0ecd2bc146681ccff0ad722",
"packages": [
{
"name": "akuechler/laravel-geoly",
@@ -4201,6 +4201,66 @@
},
"time": "2025-09-04T20:59:21+00:00"
},
{
"name": "spatie/commonmark-shiki-highlighter",
"version": "2.5.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/commonmark-shiki-highlighter.git",
"reference": "595c7e0b45d4a63b17dfc1ccbd13532d431ec351"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/commonmark-shiki-highlighter/zipball/595c7e0b45d4a63b17dfc1ccbd13532d431ec351",
"reference": "595c7e0b45d4a63b17dfc1ccbd13532d431ec351",
"shasum": ""
},
"require": {
"league/commonmark": "^2.4.2",
"php": "^8.0",
"spatie/shiki-php": "^2.2.2",
"symfony/process": "^5.4|^6.4|^7.1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.19|^v3.49.0",
"phpunit/phpunit": "^9.5",
"spatie/phpunit-snapshot-assertions": "^4.2.7",
"spatie/ray": "^1.28"
},
"type": "commonmark-extension",
"autoload": {
"psr-4": {
"Spatie\\CommonMarkShikiHighlighter\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"role": "Developer"
}
],
"description": "Highlight code blocks with league/commonmark and Shiki",
"homepage": "https://github.com/spatie/commonmark-shiki-highlighter",
"keywords": [
"commonmark-shiki-highlighter",
"spatie"
],
"support": {
"source": "https://github.com/spatie/commonmark-shiki-highlighter/tree/2.5.1"
},
"funding": [
{
"url": "https://github.com/spatie",
"type": "github"
}
],
"time": "2025-01-13T11:25:47+00:00"
},
{
"name": "spatie/eloquent-sortable",
"version": "4.5.2",
@@ -4474,6 +4534,82 @@
},
"time": "2025-09-18T10:35:25+00:00"
},
{
"name": "spatie/laravel-markdown",
"version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-markdown.git",
"reference": "353e7f9fae62826e26cbadef58a12ecf39685280"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-markdown/zipball/353e7f9fae62826e26cbadef58a12ecf39685280",
"reference": "353e7f9fae62826e26cbadef58a12ecf39685280",
"shasum": ""
},
"require": {
"illuminate/cache": "^9.0|^10.0|^11.0|^12.0",
"illuminate/contracts": "^9.0|^10.0|^11.0|^12.0",
"illuminate/support": "^9.0|^10.0|^11.0|^12.0",
"illuminate/view": "^9.0|^10.0|^11.0|^12.0",
"league/commonmark": "^2.6.0",
"php": "^8.1",
"spatie/commonmark-shiki-highlighter": "^2.5",
"spatie/laravel-package-tools": "^1.4.3"
},
"require-dev": {
"brianium/paratest": "^6.2|^7.8",
"nunomaduro/collision": "^5.3|^6.0|^7.0|^8.0",
"orchestra/testbench": "^6.15|^7.0|^8.0|^10.0",
"pestphp/pest": "^1.22|^2.0|^3.7",
"phpunit/phpunit": "^9.3|^11.5.3",
"spatie/laravel-ray": "^1.23",
"spatie/pest-plugin-snapshots": "^1.1|^2.2|^3.0",
"vimeo/psalm": "^4.8|^6.7"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Spatie\\LaravelMarkdown\\MarkdownServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Spatie\\LaravelMarkdown\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"role": "Developer"
}
],
"description": "A highly configurable markdown renderer and Blade component for Laravel",
"homepage": "https://github.com/spatie/laravel-markdown",
"keywords": [
"Laravel-Markdown",
"laravel",
"spatie"
],
"support": {
"source": "https://github.com/spatie/laravel-markdown/tree/2.7.1"
},
"funding": [
{
"url": "https://github.com/spatie",
"type": "github"
}
],
"time": "2025-02-21T13:43:18+00:00"
},
{
"name": "spatie/laravel-medialibrary",
"version": "11.17.5",
@@ -4940,6 +5076,71 @@
],
"time": "2025-02-20T15:51:22+00:00"
},
{
"name": "spatie/shiki-php",
"version": "2.3.2",
"source": {
"type": "git",
"url": "https://github.com/spatie/shiki-php.git",
"reference": "a2e78a9ff8a1290b25d550be8fbf8285c13175c5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/shiki-php/zipball/a2e78a9ff8a1290b25d550be8fbf8285c13175c5",
"reference": "a2e78a9ff8a1290b25d550be8fbf8285c13175c5",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^8.0",
"symfony/process": "^5.4|^6.4|^7.1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^v3.0",
"pestphp/pest": "^1.8",
"phpunit/phpunit": "^9.5",
"spatie/pest-plugin-snapshots": "^1.1",
"spatie/ray": "^1.10"
},
"type": "library",
"autoload": {
"psr-4": {
"Spatie\\ShikiPhp\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rias Van der Veken",
"email": "rias@spatie.be",
"role": "Developer"
},
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"role": "Developer"
}
],
"description": "Highlight code using Shiki in PHP",
"homepage": "https://github.com/spatie/shiki-php",
"keywords": [
"shiki",
"spatie"
],
"support": {
"source": "https://github.com/spatie/shiki-php/tree/2.3.2"
},
"funding": [
{
"url": "https://github.com/spatie",
"type": "github"
}
],
"time": "2025-02-21T14:16:57+00:00"
},
{
"name": "spatie/temporary-directory",
"version": "2.3.0",
@@ -9128,6 +9329,145 @@
},
"time": "2025-11-17T02:59:45+00:00"
},
{
"name": "laravel/boost",
"version": "v1.8.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/boost.git",
"reference": "cf57ba510df44e0d4ed2c1c91360477e92d7d644"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/boost/zipball/cf57ba510df44e0d4ed2c1c91360477e92d7d644",
"reference": "cf57ba510df44e0d4ed2c1c91360477e92d7d644",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^7.9",
"illuminate/console": "^10.49.0|^11.45.3|^12.28.1",
"illuminate/contracts": "^10.49.0|^11.45.3|^12.28.1",
"illuminate/routing": "^10.49.0|^11.45.3|^12.28.1",
"illuminate/support": "^10.49.0|^11.45.3|^12.28.1",
"laravel/mcp": "^0.3.4",
"laravel/prompts": "0.1.25|^0.3.6",
"laravel/roster": "^0.2.9",
"php": "^8.1"
},
"require-dev": {
"laravel/pint": "1.20",
"mockery/mockery": "^1.6.12",
"orchestra/testbench": "^8.36.0|^9.15.0|^10.6",
"pestphp/pest": "^2.36.0|^3.8.4",
"phpstan/phpstan": "^2.1.27",
"rector/rector": "^2.1"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Boost\\BoostServiceProvider"
]
},
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Laravel\\Boost\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Laravel Boost accelerates AI-assisted development by providing the essential context and structure that AI needs to generate high-quality, Laravel-specific code.",
"homepage": "https://github.com/laravel/boost",
"keywords": [
"ai",
"dev",
"laravel"
],
"support": {
"issues": "https://github.com/laravel/boost/issues",
"source": "https://github.com/laravel/boost"
},
"time": "2025-11-20T18:13:17+00:00"
},
{
"name": "laravel/mcp",
"version": "v0.3.4",
"source": {
"type": "git",
"url": "https://github.com/laravel/mcp.git",
"reference": "0b86fb613a0df971cec89271c674a677c2cb4f77"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/mcp/zipball/0b86fb613a0df971cec89271c674a677c2cb4f77",
"reference": "0b86fb613a0df971cec89271c674a677c2cb4f77",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-mbstring": "*",
"illuminate/console": "^10.49.0|^11.45.3|^12.28.1",
"illuminate/container": "^10.49.0|^11.45.3|^12.28.1",
"illuminate/contracts": "^10.49.0|^11.45.3|^12.28.1",
"illuminate/http": "^10.49.0|^11.45.3|^12.28.1",
"illuminate/json-schema": "^12.28.1",
"illuminate/routing": "^10.49.0|^11.45.3|^12.28.1",
"illuminate/support": "^10.49.0|^11.45.3|^12.28.1",
"illuminate/validation": "^10.49.0|^11.45.3|^12.28.1",
"php": "^8.1"
},
"require-dev": {
"laravel/pint": "1.20.0",
"orchestra/testbench": "^8.36.0|^9.15.0|^10.6.0",
"pestphp/pest": "^2.36.0|^3.8.4|^4.1.0",
"phpstan/phpstan": "^2.1.27",
"rector/rector": "^2.2.4"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Mcp": "Laravel\\Mcp\\Server\\Facades\\Mcp"
},
"providers": [
"Laravel\\Mcp\\Server\\McpServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Mcp\\": "src/",
"Laravel\\Mcp\\Server\\": "src/Server/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Rapidly build MCP servers for your Laravel applications.",
"homepage": "https://github.com/laravel/mcp",
"keywords": [
"laravel",
"mcp"
],
"support": {
"issues": "https://github.com/laravel/mcp/issues",
"source": "https://github.com/laravel/mcp"
},
"time": "2025-11-18T14:41:05+00:00"
},
{
"name": "laravel/pail",
"version": "v1.2.3",
@@ -9273,6 +9613,67 @@
},
"time": "2025-09-19T02:57:12+00:00"
},
{
"name": "laravel/roster",
"version": "v0.2.9",
"source": {
"type": "git",
"url": "https://github.com/laravel/roster.git",
"reference": "82bbd0e2de614906811aebdf16b4305956816fa6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/roster/zipball/82bbd0e2de614906811aebdf16b4305956816fa6",
"reference": "82bbd0e2de614906811aebdf16b4305956816fa6",
"shasum": ""
},
"require": {
"illuminate/console": "^10.0|^11.0|^12.0",
"illuminate/contracts": "^10.0|^11.0|^12.0",
"illuminate/routing": "^10.0|^11.0|^12.0",
"illuminate/support": "^10.0|^11.0|^12.0",
"php": "^8.1|^8.2",
"symfony/yaml": "^6.4|^7.2"
},
"require-dev": {
"laravel/pint": "^1.14",
"mockery/mockery": "^1.6",
"orchestra/testbench": "^8.22.0|^9.0|^10.0",
"pestphp/pest": "^2.0|^3.0",
"phpstan/phpstan": "^2.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Roster\\RosterServiceProvider"
]
},
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Laravel\\Roster\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Detect packages & approaches in use within a Laravel project",
"homepage": "https://github.com/laravel/roster",
"keywords": [
"dev",
"laravel"
],
"support": {
"issues": "https://github.com/laravel/roster/issues",
"source": "https://github.com/laravel/roster"
},
"time": "2025-10-20T09:56:46+00:00"
},
{
"name": "laravel/sail",
"version": "v1.48.1",

View File

@@ -78,7 +78,7 @@ return [
|
*/
'locale' => env('APP_LOCALE', 'en'),
'locale' => env('APP_LOCALE', 'de'),
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),

106
config/markdown.php Normal file
View File

@@ -0,0 +1,106 @@
<?php
return [
'code_highlighting' => [
/*
* To highlight code, we'll use Shiki under the hood. Make sure it's installed.
*
* More info: https://spatie.be/docs/laravel-markdown/v1/installation-setup
*/
'enabled' => true,
/*
* The name of or path to a Shiki theme
*
* More info: https://github.com/shikijs/shiki/blob/main/docs/themes.md
*/
'theme' => 'github-light',
],
/*
* When enabled, anchor links will be added to all titles
*/
'add_anchors_to_headings' => true,
/**
* When enabled, anchors will be rendered as links.
*/
'render_anchors_as_links' => false,
/*
* These options will be passed to the league/commonmark package which is
* used under the hood to render markdown.
*
* More info: https://spatie.be/docs/laravel-markdown/v1/using-the-blade-component/passing-options-to-commonmark
*/
'commonmark_options' => [],
/*
* Rendering markdown to HTML can be resource intensive. By default
* we'll cache the results.
*
* You can specify the name of a cache store here. When set to `null`
* the default cache store will be used. If you do not want to use
* caching set this value to `false`.
*/
'cache_store' => null,
/*
* When cache_store is enabled, this value will be used to determine
* how long the cache will be valid. If you set this to `null` the
* cache will never expire.
*
*/
'cache_duration' => null,
/*
* This class will convert markdown to HTML
*
* You can change this to a class of your own to greatly
* customize the rendering process
*
* More info: https://spatie.be/docs/laravel-markdown/v1/advanced-usage/customizing-the-rendering-process
*/
'renderer_class' => Spatie\LaravelMarkdown\MarkdownRenderer::class,
/*
* These extensions should be added to the markdown environment. A valid
* extension implements League\CommonMark\Extension\ExtensionInterface
*
* More info: https://commonmark.thephpleague.com/2.4/extensions/overview/
*/
'extensions' => [
//
],
/*
* These block renderers should be added to the markdown environment. A valid
* renderer implements League\CommonMark\Renderer\NodeRendererInterface;
*
* More info: https://commonmark.thephpleague.com/2.4/customization/rendering/
*/
'block_renderers' => [
// ['class' => FencedCode::class, 'renderer' => MyCustomCodeRenderer::class, 'priority' => 0]
],
/*
* These inline renderers should be added to the markdown environment. A valid
* renderer implements League\CommonMark\Renderer\NodeRendererInterface;
*
* More info: https://commonmark.thephpleague.com/2.4/customization/rendering/
*/
'inline_renderers' => [
// ['class' => FencedCode::class, 'renderer' => MyCustomCodeRenderer::class, 'priority' => 0]
],
/*
* These inline parsers should be added to the markdown environment. A valid
* parser implements League\CommonMark\Renderer\InlineParserInterface;
*
* More info: https://commonmark.thephpleague.com/2.4/customization/inline-parsing/
*/
'inline_parsers' => [
// ['parser' => MyCustomInlineParser::class, 'priority' => 0]
],
];

144
lang/es.json Normal file
View File

@@ -0,0 +1,144 @@
{
"(and :count more error)": "(y :count error más)",
"(and :count more errors)": "(y :count error más)|(y :count errores más)|(y :count errores más)",
"2FA Recovery Codes": "Códigos de recuperación de 2FA",
"A decryption key is required.": "Se requiere una clave de descifrado.",
"A new verification link has been sent to the email address you provided during registration.": "Se ha enviado un nuevo enlace de verificación a la dirección de correo electrónico que proporcionó durante el registro.",
"A new verification link has been sent to your email address.": "Se ha enviado un nuevo enlace de verificación a su dirección de correo electrónico.",
"A reset link will be sent if the account exists.": "Se enviará un enlace de restablecimiento si la cuenta existe.",
"All rights reserved.": "Todos los derechos reservados.",
"Already have an account?": "¿Ya tiene una cuenta?",
"Appearance": "Apariencia",
"Are you sure you want to delete your account?": "¿Está seguro que desea eliminar su cuenta?",
"Authentication Code": "Código de autenticación",
"Back": "Atrás",
"Cancel": "Cancelar",
"Click here to re-send the verification email.": "Haga clic aquí para reenviar el correo de verificación.",
"Close": "Cerrar",
"Confirm": "Confirmar",
"Confirm Password": "Confirmar contraseña",
"Confirm password": "Confirmar contraseña",
"Continue": "Continuar",
"Create account": "Crear cuenta",
"Create an account": "Crear una cuenta",
"Current password": "Contraseña actual",
"Dark": "Oscuro",
"Dashboard": "Panel",
"Delete account": "Eliminar cuenta",
"Delete your account and all of its resources": "Elimine su cuenta y todos sus recursos",
"Disable 2FA": "Desactivar 2FA",
"Disabled": "Desactivado",
"Documentation": "Documentación",
"Don't have an account?": "¿No tiene una cuenta?",
"Each recovery code can be used once to access your account and will be removed after use. If you need more, click Regenerate Codes above.": "Cada código de recuperación se puede usar una vez para acceder a su cuenta y se eliminará después de usarlo. Si necesita más, haga clic arriba en \"Regenerar códigos\".",
"Email": "Correo electrónico",
"Email Address": "Correo electrónico",
"Email address": "Correo electrónico",
"Email password reset link": "Enviar enlace de restablecimiento de contraseña",
"Enable 2FA": "Habilitar 2FA",
"Enable Two-Factor Authentication": "Habilitar autenticación de dos factores",
"Enabled": "Habilitado",
"Encrypted environment file already exists.": "El archivo de entorno cifrado ya existe.",
"Encrypted environment file not found.": "No se encontró el archivo de entorno cifrado.",
"Ensure your account is using a long, random password to stay secure": "Asegúrese de que su cuenta esté usando una contraseña larga y aleatoria para mantenerla segura",
"Enter the 6-digit code from your authenticator app.": "Ingrese el código de 6 dígitos de su aplicación de autenticación.",
"Enter the authentication code provided by your authenticator application.": "Ingrese el código de autenticación proporcionado por su aplicación de autenticación.",
"Enter your details below to create your account": "Ingrese sus datos a continuación para crear su cuenta",
"Enter your email and password below to log in": "Ingrese su correo electrónico y contraseña a continuación para iniciar sesión",
"Enter your email to receive a password reset link": "Ingrese su correo electrónico para recibir un enlace de restablecimiento de contraseña",
"Environment file already exists.": "El archivo de entorno ya existe.",
"Environment file not found.": "Archivo de entorno no encontrado.",
"errors": "errores",
"Forbidden": "Prohibido",
"Forgot password": "Olvido de contraseña",
"Forgot your password?": "¿Olvidó su contraseña?",
"Full name": "Nombre completo",
"Go to page :page": "Ir a la página :page",
"Hello!": "¡Hola!",
"Hide Recovery Codes": "Ocultar códigos de recuperación",
"If you did not create an account, no further action is required.": "Si no ha creado una cuenta, no se requiere ninguna acción adicional.",
"If you did not request a password reset, no further action is required.": "Si no ha solicitado el restablecimiento de contraseña, omita este mensaje de correo electrónico.",
"If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Si está teniendo problemas al hacer clic en el botón \":actionText\", copie y pegue la URL de abajo\nen su navegador web:",
"Invalid filename.": "Nombre de archivo no válido.",
"Invalid JSON was returned from the route.": "Se devolvió un JSON no válido desde la ruta.",
"Light": "Claro",
"Location": "Ubicación",
"Log in": "Iniciar sesión",
"log in": "iniciar sesión",
"Log in to your account": "Inicie sesión en su cuenta",
"Log Out": "Finalizar sesión",
"Log out": "Cerrar sesión",
"Login": "Iniciar sesión",
"login using a recovery code": "iniciar sesión usando un código de recuperación",
"login using an authentication code": "iniciar sesión usando un código de autenticación",
"Logout": "Finalizar sesión",
"Manage your profile and account settings": "Administre su perfil y la configuración de su cuenta",
"Manage your two-factor authentication settings": "Administre su configuración de autenticación de dos factores",
"Name": "Nombre",
"New password": "Nueva contraseña",
"Not Found": "No encontrado",
"of": "de",
"Once your account is deleted, all of its resources and data will also be permanently deleted. Please confirm you would like to permanently delete your account.": "Una vez que se elimine su cuenta, todos sus recursos y datos también se eliminarán de forma permanente. Confirme que desea eliminar su cuenta de forma permanente.",
"Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.": "Una vez que se elimine su cuenta, todos sus recursos y datos se eliminarán de forma permanente. Ingrese su contraseña para confirmar que desea eliminar su cuenta de forma permanente.",
"or you can": "o usted puede",
"or, enter the code manually": "o, ingrese el código manualmente",
"Or, return to": "O, regrese a",
"Page Expired": "Página expirada",
"Pagination Navigation": "Navegación por los enlaces de paginación",
"Password": "Contraseña",
"Payment Required": "Pago requerido",
"Platform": "Plataforma",
"Please click the button below to verify your email address.": "Por favor, haga clic en el botón de abajo para verificar su dirección de correo electrónico.",
"Please confirm access to your account by entering one of your emergency recovery codes.": "Confirme el acceso a su cuenta ingresando uno de sus códigos de recuperación de emergencia.",
"Please enter your new password below": "Por favor, introduzca su nueva contraseña a continuación",
"Please verify your email address by clicking on the link we just emailed to you.": "Por favor, verifique su dirección de correo electrónico haciendo clic en el enlace que acabamos de enviarle.",
"Profile": "Perfil",
"Recovery Code": "Código de recuperación",
"Recovery codes let you regain access if you lose your 2FA device. Store them in a secure password manager.": "Los códigos de recuperación le permiten recuperar el acceso si pierde su dispositivo con autenticación de dos factores. Guárdelos en un gestor de contraseñas seguro.",
"Regards,": "Saludos,",
"Regenerate Codes": "Regenerar códigos",
"Register": "Registrarse",
"Remember me": "Mantener sesión activa",
"Repository": "Repositorio",
"Resend verification email": "Reenviar correo de verificación",
"Reset Password": "Restablecer contraseña",
"Reset password": "Restablecer contraseña",
"Reset Password Notification": "Notificación de restablecimiento de contraseña",
"results": "resultados",
"Save": "Guardar",
"Saved.": "Guardado.",
"Search": "Buscar",
"Server Error": "Error del servidor",
"Service Unavailable": "Servicio no disponible",
"Settings": "Configuración",
"Showing": "Mostrando",
"Sign up": "Regístrese",
"System": "Sistema",
"The given data was invalid.": "Los datos proporcionados no son válidos.",
"The response is not a streamed response.": "La respuesta no es una respuesta transmitida.",
"The response is not a view.": "La respuesta no es una vista.",
"This action is unauthorized.": "Esta acción no está autorizada.",
"This is a secure area of the application. Please confirm your password before continuing.": "Esta es una zona segura de la aplicación. Confirme su contraseña antes de continuar.",
"This password reset link will expire in :count minutes.": "Este enlace de restablecimiento de contraseña expirará en :count minutos.",
"to": "al",
"To finish enabling two-factor authentication, scan the QR code or enter the setup key in your authenticator app.": "Para terminar de habilitar la autenticación de dos factores, escanee el código QR o ingrese la clave de configuración en su aplicación de autenticación.",
"Toggle navigation": "Alternar navegación",
"Too Many Requests": "Demasiadas peticiones",
"Two Factor Authentication": "Autenticación de Dos Factores",
"Two-Factor Auth": "Autenticación de Dos Factores",
"Two-Factor Authentication Enabled": "Autenticación de dos factores habilitada",
"Two-factor authentication is now enabled. Scan the QR code or enter the setup key in your authenticator app.": "La autenticación de dos factores ya está habilitada. Escanea el código QR o introduce la clave de configuración en tu app de autenticación.",
"Unauthorized": "No autorizado",
"Update password": "Actualizar contraseña",
"Update the appearance settings for your account": "Actualice la configuración de apariencia de su cuenta",
"Update your account's appearance settings": "Actualice la configuración de apariencia de su cuenta",
"Update your name and email address": "Actualice su nombre y dirección de correo electrónico",
"Verify Authentication Code": "Verificar código de autenticación",
"Verify Email Address": "Confirme su correo electrónico",
"View Recovery Codes": "Ver códigos de recuperación",
"When you enable two-factor authentication, you will be prompted for a secure pin during login. This pin can be retrieved from a TOTP-supported application on your phone.": "Al activar la autenticación de dos factores, se le solicitará un PIN seguro al iniciar sesión. Puede obtenerlo desde una aplicación compatible con TOTP en su teléfono.",
"Whoops!": "¡Ups!",
"With two-factor authentication enabled, you will be prompted for a secure, random pin during login, which you can retrieve from the TOTP-supported application on your phone.": "Con la autenticación de dos factores habilitada, se le solicitará un PIN aleatorio seguro durante el inicio de sesión, que puede recuperar de la aplicación compatible con TOTP en su teléfono.",
"You are receiving this email because we received a password reset request for your account.": "Ha recibido este mensaje porque se solicitó un restablecimiento de contraseña para su cuenta.",
"Your email address is unverified.": "Su dirección de correo electrónico no está verificada."
}

9
lang/es/auth.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
return [
'failed' => 'Estas credenciales no coinciden con nuestros registros.',
'password' => 'La contraseña es incorrecta.',
'throttle' => 'Demasiados intentos de acceso. Por favor intente nuevamente en :seconds segundos.',
];

251
lang/es/countries.php Normal file
View File

@@ -0,0 +1,251 @@
<?php return array (
'AF' => 'Afganistán',
'AL' => 'Albania',
'DE' => 'Alemania',
'AD' => 'Andorra',
'AO' => 'Angola',
'AI' => 'Anguila',
'AQ' => 'Antártida',
'AG' => 'Antigua y Barbuda',
'SA' => 'Arabia Saudí',
'DZ' => 'Argelia',
'AR' => 'Argentina',
'AM' => 'Armenia',
'AW' => 'Aruba',
'AU' => 'Australia',
'AT' => 'Austria',
'AZ' => 'Azerbaiyán',
'BS' => 'Bahamas',
'BD' => 'Bangladés',
'BB' => 'Barbados',
'BH' => 'Baréin',
'BE' => 'Bélgica',
'BZ' => 'Belice',
'BJ' => 'Benín',
'BM' => 'Bermudas',
'BY' => 'Bielorrusia',
'BO' => 'Bolivia',
'BA' => 'Bosnia y Herzegovina',
'BW' => 'Botsuana',
'BR' => 'Brasil',
'BN' => 'Brunéi',
'BG' => 'Bulgaria',
'BF' => 'Burkina Faso',
'BI' => 'Burundi',
'BT' => 'Bután',
'CV' => 'Cabo Verde',
'KH' => 'Camboya',
'CM' => 'Camerún',
'CA' => 'Canadá',
'BQ' => 'Caribe neerlandés',
'QA' => 'Catar',
'TD' => 'Chad',
'CZ' => 'Chequia',
'CL' => 'Chile',
'CN' => 'China',
'CY' => 'Chipre',
'VA' => 'Ciudad del Vaticano',
'CO' => 'Colombia',
'KM' => 'Comoras',
'CG' => 'Congo',
'KP' => 'Corea del Norte',
'KR' => 'Corea del Sur',
'CR' => 'Costa Rica',
'CI' => 'Côte dIvoire',
'HR' => 'Croacia',
'CU' => 'Cuba',
'CW' => 'Curazao',
'DK' => 'Dinamarca',
'DM' => 'Dominica',
'EC' => 'Ecuador',
'EG' => 'Egipto',
'SV' => 'El Salvador',
'AE' => 'Emiratos Árabes Unidos',
'ER' => 'Eritrea',
'SK' => 'Eslovaquia',
'SI' => 'Eslovenia',
'ES' => 'España',
'US' => 'Estados Unidos',
'EE' => 'Estonia',
'SZ' => 'Esuatini',
'ET' => 'Etiopía',
'PH' => 'Filipinas',
'FI' => 'Finlandia',
'FJ' => 'Fiyi',
'FR' => 'Francia',
'GA' => 'Gabón',
'GM' => 'Gambia',
'GE' => 'Georgia',
'GH' => 'Ghana',
'GI' => 'Gibraltar',
'GD' => 'Granada',
'GR' => 'Grecia',
'GL' => 'Groenlandia',
'GP' => 'Guadalupe',
'GU' => 'Guam',
'GT' => 'Guatemala',
'GF' => 'Guayana Francesa',
'GG' => 'Guernsey',
'GN' => 'Guinea',
'GQ' => 'Guinea Ecuatorial',
'GW' => 'Guinea-Bisáu',
'GY' => 'Guyana',
'HT' => 'Haití',
'HN' => 'Honduras',
'HU' => 'Hungría',
'IN' => 'India',
'ID' => 'Indonesia',
'IQ' => 'Irak',
'IR' => 'Irán',
'IE' => 'Irlanda',
'BV' => 'Isla Bouvet',
'IM' => 'Isla de Man',
'CX' => 'Isla de Navidad',
'NF' => 'Isla Norfolk',
'IS' => 'Islandia',
'AX' => 'Islas Åland',
'KY' => 'Islas Caimán',
'CC' => 'Islas Cocos',
'CK' => 'Islas Cook',
'FO' => 'Islas Feroe',
'GS' => 'Islas Georgia del Sur y Sandwich del Sur',
'HM' => 'Islas Heard y McDonald',
'FK' => 'Islas Malvinas',
'MP' => 'Islas Marianas del Norte',
'MH' => 'Islas Marshall',
'UM' => 'Islas menores alejadas de EE. UU.',
'PN' => 'Islas Pitcairn',
'SB' => 'Islas Salomón',
'TC' => 'Islas Turcas y Caicos',
'VG' => 'Islas Vírgenes Británicas',
'VI' => 'Islas Vírgenes de EE. UU.',
'IL' => 'Israel',
'IT' => 'Italia',
'JM' => 'Jamaica',
'JP' => 'Japón',
'JE' => 'Jersey',
'JO' => 'Jordania',
'KZ' => 'Kazajistán',
'KE' => 'Kenia',
'KG' => 'Kirguistán',
'KI' => 'Kiribati',
'KW' => 'Kuwait',
'LA' => 'Laos',
'LS' => 'Lesoto',
'LV' => 'Letonia',
'LB' => 'Líbano',
'LR' => 'Liberia',
'LY' => 'Libia',
'LI' => 'Liechtenstein',
'LT' => 'Lituania',
'LU' => 'Luxemburgo',
'MK' => 'Macedonia del Norte',
'MG' => 'Madagascar',
'MY' => 'Malasia',
'MW' => 'Malaui',
'MV' => 'Maldivas',
'ML' => 'Mali',
'MT' => 'Malta',
'MA' => 'Marruecos',
'MQ' => 'Martinica',
'MU' => 'Mauricio',
'MR' => 'Mauritania',
'YT' => 'Mayotte',
'MX' => 'México',
'FM' => 'Micronesia',
'MD' => 'Moldavia',
'MC' => 'Mónaco',
'MN' => 'Mongolia',
'ME' => 'Montenegro',
'MS' => 'Montserrat',
'MZ' => 'Mozambique',
'MM' => 'Myanmar (Birmania)',
'NA' => 'Namibia',
'NR' => 'Nauru',
'NP' => 'Nepal',
'NI' => 'Nicaragua',
'NE' => 'Níger',
'NG' => 'Nigeria',
'NU' => 'Niue',
'NO' => 'Noruega',
'NC' => 'Nueva Caledonia',
'NZ' => 'Nueva Zelanda',
'OM' => 'Omán',
'NL' => 'Países Bajos',
'PK' => 'Pakistán',
'PW' => 'Palaos',
'PA' => 'Panamá',
'PG' => 'Papúa Nueva Guinea',
'PY' => 'Paraguay',
'PE' => 'Perú',
'PF' => 'Polinesia Francesa',
'PL' => 'Polonia',
'PT' => 'Portugal',
'PR' => 'Puerto Rico',
'HK' => 'RAE de Hong Kong (China)',
'MO' => 'RAE de Macao (China)',
'GB' => 'Reino Unido',
'CF' => 'República Centroafricana',
'CD' => 'República Democrática del Congo',
'DO' => 'República Dominicana',
'RE' => 'Reunión',
'RW' => 'Ruanda',
'RO' => 'Rumanía',
'RU' => 'Rusia',
'EH' => 'Sáhara Occidental',
'WS' => 'Samoa',
'AS' => 'Samoa Americana',
'BL' => 'San Bartolomé',
'KN' => 'San Cristóbal y Nieves',
'SM' => 'San Marino',
'MF' => 'San Martín',
'PM' => 'San Pedro y Miquelón',
'VC' => 'San Vicente y las Granadinas',
'SH' => 'Santa Elena',
'LC' => 'Santa Lucía',
'ST' => 'Santo Tomé y Príncipe',
'SN' => 'Senegal',
'RS' => 'Serbia',
'SC' => 'Seychelles',
'SL' => 'Sierra Leona',
'SG' => 'Singapur',
'SX' => 'Sint Maarten',
'SY' => 'Siria',
'SO' => 'Somalia',
'LK' => 'Sri Lanka',
'ZA' => 'Sudáfrica',
'SD' => 'Sudán',
'SS' => 'Sudán del Sur',
'SE' => 'Suecia',
'CH' => 'Suiza',
'SR' => 'Surinam',
'SJ' => 'Svalbard y Jan Mayen',
'TH' => 'Tailandia',
'TW' => 'Taiwán',
'TZ' => 'Tanzania',
'TJ' => 'Tayikistán',
'IO' => 'Territorio Británico del Océano Índico',
'TF' => 'Territorios Australes Franceses',
'PS' => 'Territorios Palestinos',
'TL' => 'Timor-Leste',
'TG' => 'Togo',
'TK' => 'Tokelau',
'TO' => 'Tonga',
'TT' => 'Trinidad y Tobago',
'TN' => 'Túnez',
'TM' => 'Turkmenistán',
'TR' => 'Turquía',
'TV' => 'Tuvalu',
'UA' => 'Ucrania',
'UG' => 'Uganda',
'UY' => 'Uruguay',
'UZ' => 'Uzbekistán',
'VU' => 'Vanuatu',
'VE' => 'Venezuela',
'VN' => 'Vietnam',
'WF' => 'Wallis y Futuna',
'YE' => 'Yemen',
'DJ' => 'Yibuti',
'ZM' => 'Zambia',
'ZW' => 'Zimbabue',
);

8
lang/es/pagination.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
return [
'next' => 'Siguiente &raquo;',
'previous' => '&laquo; Anterior',
];

11
lang/es/passwords.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
return [
'reset' => 'Su contraseña ha sido restablecida.',
'sent' => 'Le hemos enviado por correo electrónico el enlace para restablecer su contraseña.',
'throttled' => 'Por favor espere antes de intentar de nuevo.',
'token' => 'El token de restablecimiento de contraseña es inválido.',
'user' => 'No encontramos ningún usuario con ese correo electrónico.',
];

158
lang/es/validation.php Normal file
View File

@@ -0,0 +1,158 @@
<?php
declare(strict_types=1);
return [
'accepted' => 'El campo :attribute debe ser aceptado.',
'accepted_if' => 'El campo :attribute debe ser aceptado cuando :other sea :value.',
'active_url' => 'El campo :attribute debe ser una URL válida.',
'after' => 'El campo :attribute debe ser una fecha posterior a :date.',
'after_or_equal' => 'El campo :attribute debe ser una fecha posterior o igual a :date.',
'alpha' => 'El campo :attribute sólo debe contener letras.',
'alpha_dash' => 'El campo :attribute sólo debe contener letras, números, guiones y guiones bajos.',
'alpha_num' => 'El campo :attribute sólo debe contener letras y números.',
'any_of' => 'El campo :attribute no es válido.',
'array' => 'El campo :attribute debe ser un conjunto.',
'ascii' => 'El campo :attribute solo debe contener caracteres alfanuméricos y símbolos de un solo byte.',
'before' => 'El campo :attribute debe ser una fecha anterior a :date.',
'before_or_equal' => 'El campo :attribute debe ser una fecha anterior o igual a :date.',
'between' => [
'array' => 'El campo :attribute tiene que tener entre :min - :max elementos.',
'file' => 'El campo :attribute debe pesar entre :min - :max kilobytes.',
'numeric' => 'El campo :attribute tiene que estar entre :min - :max.',
'string' => 'El campo :attribute tiene que tener entre :min - :max caracteres.',
],
'boolean' => 'El campo :attribute debe tener un valor verdadero o falso.',
'can' => 'El campo :attribute contiene un valor no autorizado.',
'confirmed' => 'La confirmación de :attribute no coincide.',
'contains' => 'Al campo :attribute le falta un valor obligatorio.',
'current_password' => 'La contraseña es incorrecta.',
'date' => 'El campo :attribute debe ser una fecha válida.',
'date_equals' => 'El campo :attribute debe ser una fecha igual a :date.',
'date_format' => 'El campo :attribute debe coincidir con el formato :format.',
'decimal' => 'El campo :attribute debe tener :decimal cifras decimales.',
'declined' => 'El campo :attribute debe ser rechazado.',
'declined_if' => 'El campo :attribute debe ser rechazado cuando :other sea :value.',
'different' => 'El campo :attribute y :other deben ser diferentes.',
'digits' => 'El campo :attribute debe tener :digits dígitos.',
'digits_between' => 'El campo :attribute debe tener entre :min y :max dígitos.',
'dimensions' => 'El campo :attribute tiene dimensiones de imagen no válidas.',
'distinct' => 'El campo :attribute contiene un valor duplicado.',
'doesnt_contain' => 'El campo :attribute no debe contener ninguno de los siguientes valores: :values.',
'doesnt_end_with' => 'El campo :attribute no debe finalizar con uno de los siguientes: :values.',
'doesnt_start_with' => 'El campo :attribute no debe comenzar con uno de los siguientes: :values.',
'email' => 'El campo :attribute no es un correo válido.',
'ends_with' => 'El campo :attribute debe finalizar con uno de los siguientes valores: :values',
'enum' => 'El campo :attribute no está en la lista de valores permitidos.',
'exists' => 'El campo :attribute no existe.',
'extensions' => 'El campo :attribute debe tener una de las siguientes extensiones: :values.',
'file' => 'El campo :attribute debe ser un archivo.',
'filled' => 'El campo :attribute es obligatorio.',
'gt' => [
'array' => 'El campo :attribute debe tener más de :value elementos.',
'file' => 'El campo :attribute debe tener más de :value kilobytes.',
'numeric' => 'El campo :attribute debe ser mayor que :value.',
'string' => 'El campo :attribute debe tener más de :value caracteres.',
],
'gte' => [
'array' => 'El campo :attribute debe tener como mínimo :value elementos.',
'file' => 'El campo :attribute debe tener como mínimo :value kilobytes.',
'numeric' => 'El campo :attribute debe ser como mínimo :value.',
'string' => 'El campo :attribute debe tener como mínimo :value caracteres.',
],
'hex_color' => 'El campo :attribute debe tener un color hexadecimal válido.',
'image' => 'El campo :attribute debe ser una imagen.',
'in' => 'El campo :attribute no está en la lista de valores permitidos.',
'in_array' => 'El campo :attribute debe existir en :other.',
'in_array_keys' => 'El campo :attribute debe contener al menos una de las siguientes claves: :values.',
'integer' => 'El campo :attribute debe ser un número entero.',
'ip' => 'El campo :attribute debe ser una dirección IP válida.',
'ipv4' => 'El campo :attribute debe ser una dirección IPv4 válida.',
'ipv6' => 'El campo :attribute debe ser una dirección IPv6 válida.',
'json' => 'El campo :attribute debe ser una cadena JSON válida.',
'list' => 'El campo :attribute debe ser una lista.',
'lowercase' => 'El campo :attribute debe estar en minúscula.',
'lt' => [
'array' => 'El campo :attribute debe tener menos de :value elementos.',
'file' => 'El campo :attribute debe tener menos de :value kilobytes.',
'numeric' => 'El campo :attribute debe ser menor que :value.',
'string' => 'El campo :attribute debe tener menos de :value caracteres.',
],
'lte' => [
'array' => 'El campo :attribute debe tener como máximo :value elementos.',
'file' => 'El campo :attribute debe tener como máximo :value kilobytes.',
'numeric' => 'El campo :attribute debe ser como máximo :value.',
'string' => 'El campo :attribute debe tener como máximo :value caracteres.',
],
'mac_address' => 'El campo :attribute debe ser una dirección MAC válida.',
'max' => [
'array' => 'El campo :attribute no debe tener más de :max elementos.',
'file' => 'El campo :attribute no debe ser mayor que :max kilobytes.',
'numeric' => 'El campo :attribute no debe ser mayor que :max.',
'string' => 'El campo :attribute no debe ser mayor que :max caracteres.',
],
'max_digits' => 'El campo :attribute no debe tener más de :max dígitos.',
'mimes' => 'El campo :attribute debe ser un archivo con formato: :values.',
'mimetypes' => 'El campo :attribute debe ser un archivo con formato: :values.',
'min' => [
'array' => 'El campo :attribute debe tener al menos :min elementos.',
'file' => 'El tamaño de :attribute debe ser de al menos :min kilobytes.',
'numeric' => 'El tamaño de :attribute debe ser de al menos :min.',
'string' => 'El campo :attribute debe contener al menos :min caracteres.',
],
'min_digits' => 'El campo :attribute debe tener al menos :min dígitos.',
'missing' => 'El campo :attribute no debe estar presente.',
'missing_if' => 'El campo :attribute no debe estar presente cuando :other sea :value.',
'missing_unless' => 'El campo :attribute no debe estar presente a menos que :other sea :value.',
'missing_with' => 'El campo :attribute no debe estar presente si alguno de los campos :values está presente.',
'missing_with_all' => 'El campo :attribute no debe estar presente cuando los campos :values estén presentes.',
'multiple_of' => 'El campo :attribute debe ser múltiplo de :value',
'not_in' => 'El campo :attribute no debe estar en la lista.',
'not_regex' => 'El formato del campo :attribute no es válido.',
'numeric' => 'El campo :attribute debe ser numérico.',
'password' => [
'letters' => 'La :attribute debe contener al menos una letra.',
'mixed' => 'La :attribute debe contener al menos una letra mayúscula y una minúscula.',
'numbers' => 'La :attribute debe contener al menos un número.',
'symbols' => 'La :attribute debe contener al menos un símbolo.',
'uncompromised' => 'La :attribute proporcionada se ha visto comprometida en una filtración de datos (data leak). Elija una :attribute diferente.',
],
'present' => 'El campo :attribute debe estar presente.',
'present_if' => 'El campo :attribute debe estar presente cuando :other es :value.',
'present_unless' => 'El campo :attribute debe estar presente a menos que :other sea :value.',
'present_with' => 'El campo :attribute debe estar presente cuando :values esté presente.',
'present_with_all' => 'El campo :attribute debe estar presente cuando :values estén presentes.',
'prohibited' => 'El campo :attribute está prohibido.',
'prohibited_if' => 'El campo :attribute está prohibido cuando :other es :value.',
'prohibited_if_accepted' => 'El campo :attribute está prohibido cuando se acepta :other.',
'prohibited_if_declined' => 'El campo :attribute está prohibido cuando se rechaza :other.',
'prohibited_unless' => 'El campo :attribute está prohibido a menos que :other sea :values.',
'prohibits' => 'El campo :attribute prohibe que :other esté presente.',
'regex' => 'El formato del campo :attribute no es válido.',
'required' => 'El campo :attribute es obligatorio.',
'required_array_keys' => 'El campo :attribute debe contener entradas para: :values.',
'required_if' => 'El campo :attribute es obligatorio cuando :other es :value.',
'required_if_accepted' => 'El campo :attribute es obligatorio si :other es aceptado.',
'required_if_declined' => 'El campo :attribute es obligatorio si :other es rechazado.',
'required_unless' => 'El campo :attribute es obligatorio a menos que :other esté en :values.',
'required_with' => 'El campo :attribute es obligatorio cuando :values está presente.',
'required_with_all' => 'El campo :attribute es obligatorio cuando :values están presentes.',
'required_without' => 'El campo :attribute es obligatorio cuando :values no está presente.',
'required_without_all' => 'El campo :attribute es obligatorio cuando ninguno de :values está presente.',
'same' => 'Los campos :attribute y :other deben coincidir.',
'size' => [
'array' => 'El campo :attribute debe contener :size elementos.',
'file' => 'El tamaño de :attribute debe ser :size kilobytes.',
'numeric' => 'El tamaño de :attribute debe ser :size.',
'string' => 'El campo :attribute debe contener :size caracteres.',
],
'starts_with' => 'El campo :attribute debe comenzar con uno de los siguientes valores: :values',
'string' => 'El campo :attribute debe ser una cadena de caracteres.',
'timezone' => 'El campo :attribute debe ser una zona horaria válida.',
'ulid' => 'El campo :attribute debe ser un ULID válido.',
'unique' => 'El campo :attribute ya ha sido registrado.',
'uploaded' => 'Subir :attribute ha fallado.',
'uppercase' => 'El campo :attribute debe estar en mayúscula.',
'url' => 'El campo :attribute debe ser una URL válida.',
'uuid' => 'El campo :attribute debe ser un UUID válido.',
];

View File

@@ -11,6 +11,7 @@
"axios": "^1.7.4",
"concurrently": "^9.0.1",
"laravel-vite-plugin": "^1.0",
"shiki": "^3.15.0",
"tailwindcss": "^4.0.7",
"vite": "^6.0"
},

View File

@@ -4,6 +4,9 @@
@include('partials.head')
</head>
<body class="min-h-screen bg-white dark:bg-zinc-800">
<flux:toast.group>
<flux:toast/>
</flux:toast.group>
<flux:header container class="border-b border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
<flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left"/>
@@ -29,7 +32,7 @@
<flux:navbar.item
class="h-10 max-lg:hidden [&>div>svg]:size-5"
icon="folder-git-2"
href="https://github.com/laravel/livewire-starter-kit"
href="https://gitworkshop.dev/holgerhatgarkeinenode@einundzwanzig.space/einundzwanzig-app"
target="_blank"
:label="__('Repository')"
/>
@@ -113,7 +116,9 @@
<flux:spacer/>
<flux:navlist variant="outline">
<flux:navlist.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit" target="_blank">
<flux:navlist.item icon="folder-git-2"
href="https://gitworkshop.dev/holgerhatgarkeinenode@einundzwanzig.space/einundzwanzig-app"
target="_blank">
{{ __('Repository') }}
</flux:navlist.item>
@@ -131,6 +136,23 @@
if (!localStorage.getItem('flux.appearance')) {
localStorage.setItem('flux.appearance', 'dark');
}
document.addEventListener('alpine:init', () => {
Alpine.directive('copy-to-clipboard', (el, {expression}, {evaluate}) => {
el.addEventListener('click', () => {
const text = evaluate(expression);
console.log(text);
navigator.clipboard.writeText(text).then(() => {
Flux.toast({
heading: '{{ __('Success!') }}',
text: '{{ __('Copied into clipboard') }}',
variant: 'success',
duration: 3000
});
}).catch(err => console.error(err));
});
});
});
</script>
</body>

View File

@@ -4,6 +4,9 @@
@include('partials.head')
</head>
<body class="min-h-screen bg-white dark:bg-zinc-800">
<flux:toast.group>
<flux:toast/>
</flux:toast.group>
<flux:sidebar sticky stashable class="border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
<flux:sidebar.toggle class="lg:hidden" icon="x-mark"/>
@@ -34,7 +37,7 @@
<flux:spacer/>
<flux:navlist variant="outline">
<flux:navlist.item icon="folder-git-2" href="https://git.affekt.de/einundzwanzig/einundzwanzig-app"
<flux:navlist.item icon="folder-git-2" href="https://gitworkshop.dev/holgerhatgarkeinenode@einundzwanzig.space/einundzwanzig-app"
target="_blank">
{{ __('Repository') }}
</flux:navlist.item>
@@ -176,6 +179,23 @@
if (!localStorage.getItem('flux.appearance')) {
localStorage.setItem('flux.appearance', 'dark');
}
document.addEventListener('alpine:init', () => {
Alpine.directive('copy-to-clipboard', (el, {expression}, {evaluate}) => {
el.addEventListener('click', () => {
const text = evaluate(expression);
console.log(text);
navigator.clipboard.writeText(text).then(() => {
Flux.toast({
heading: '{{ __('Success!') }}',
text: '{{ __('Copied into clipboard') }}',
variant: 'success',
duration: 3000
});
}).catch(err => console.error(err));
});
});
});
</script>
</body>

View File

@@ -13,6 +13,23 @@
if (!localStorage.getItem('flux.appearance')) {
localStorage.setItem('flux.appearance', 'dark');
}
document.addEventListener('alpine:init', () => {
Alpine.directive('copy-to-clipboard', (el, {expression}, {evaluate}) => {
el.addEventListener('click', () => {
const text = evaluate(expression);
console.log(text);
navigator.clipboard.writeText(text).then(() => {
Flux.toast({
heading: '{{ __('Success!') }}',
text: '{{ __('Copied into clipboard') }}',
variant: 'success',
duration: 3000
});
}).catch(err => console.error(err));
});
});
});
</script>
</body>
</html>

View File

@@ -7,10 +7,16 @@ use Livewire\WithPagination;
new class extends Component {
use WithPagination;
public $country = 'de';
public $sortBy = 'name';
public $sortDirection = 'asc';
public $search = '';
public function mount(): void
{
$this->country = request()->route('country');
}
public function sort($column)
{
if ($this->sortBy === $column) {
@@ -25,7 +31,7 @@ new class extends Component {
{
return [
'meetups' => Meetup::with(['city.country', 'createdBy'])
->whereHas('city.country', fn($query) => $query->where('countries.code', request()->route('country')))
->whereHas('city.country', fn($query) => $query->where('countries.code', $this->country))
->when($this->search, fn($query)
=> $query->where('name', 'ilike', '%'.$this->search.'%'),
)
@@ -63,9 +69,12 @@ new class extends Component {
<flux:table.rows>
@foreach ($meetups as $meetup)
<flux:table.row :key="$meetup->id">
<flux:table.cell variant="strong">
{{ $meetup->name }}
<flux:table.cell variant="strong" class="flex items-center gap-3">
<flux:avatar :href="route('meetups.landingpage', ['meetup' => $meetup, 'country' => $country])" src="{{ $meetup->getFirstMediaUrl('logo', 'thumb') }}"/>
<div>
@if($meetup->city)
<a href="{{ route('meetups.landingpage', ['meetup' => $meetup, 'country' => $country]) }}">
<span>{{ $meetup->name }}</span>
<div class="text-xs text-zinc-500 flex items-center space-x-2">
<div>{{ $meetup->city->name }}</div>
@if($meetup->city->country)
@@ -73,7 +82,9 @@ new class extends Component {
<div>{{ $meetup->city->country->name }}</div>
@endif
</div>
</a>
@endif
</div>
</flux:table.cell>
<flux:table.cell>
@@ -100,7 +111,8 @@ new class extends Component {
</flux:link>
@endif
@if($meetup->nostr)
<flux:link :href="'https://njump.me/'.$meetup->nostr" external variant="subtle" title="Nostr">
<flux:link :href="'https://njump.me/'.$meetup->nostr" external variant="subtle"
title="Nostr">
<flux:icon.bolt variant="mini"/>
</flux:link>
@endif

View File

@@ -0,0 +1,168 @@
<?php
use App\Models\Meetup;
use Livewire\Volt\Component;
new class extends Component {
public Meetup $meetup;
public function with(): array
{
return [
'meetup' => $this->meetup,
];
}
}; ?>
<div class="container mx-auto px-4 py-8">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- Left Column: Meetup Details -->
<div class="space-y-6">
<div class="flex items-center space-x-2">
<flux:avatar class="[:where(&)]:size-32 [:where(&)]:text-base" size="xl" src="{{ $meetup->getFirstMediaUrl('logo') }}" />
<div>
<flux:heading size="xl" class="mb-4">{{ $meetup->name }}</flux:heading>
<flux:subheading class="text-gray-600 dark:text-gray-400">
{{ $meetup->city->name }}, {{ $meetup->city->country->name }}
</flux:subheading>
</div>
</div>
@if($meetup->intro)
<div>
<flux:heading size="lg" class="mb-2">{{ __('Über uns') }}</flux:heading>
<x-markdown class="prose whitespace-pre-wrap">{!! $meetup->intro !!}</x-markdown>
</div>
@endif
<div class="space-y-4">
<flux:heading size="lg">{{ __('Kontakt & Links') }}</flux:heading>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
@if($meetup->webpage)
<flux:button href="{{ $meetup->webpage }}" target="_blank" variant="ghost" class="justify-start">
<flux:icon.globe-alt class="w-5 h-5 mr-2" />
Webseite
</flux:button>
@endif
@if($meetup->telegram_link)
<flux:button href="{{ $meetup->telegram_link }}" target="_blank" variant="ghost" class="justify-start">
<flux:icon.chat-bubble-left-right class="w-5 h-5 mr-2" />
Telegram
</flux:button>
@endif
@if($meetup->twitter_username)
<flux:button href="https://twitter.com/{{ $meetup->twitter_username }}" target="_blank" variant="ghost" class="justify-start">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 24 24">
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
</svg>
Twitter/X
</flux:button>
@endif
@if($meetup->matrix_group)
<flux:button href="{{ $meetup->matrix_group }}" target="_blank" variant="ghost" class="justify-start">
<flux:icon.hashtag class="w-5 h-5 mr-2" />
Matrix
</flux:button>
@endif
@if($meetup->signal)
<flux:button href="{{ $meetup->signal }}" target="_blank" variant="ghost" class="justify-start">
<flux:icon.phone class="w-5 h-5 mr-2" />
Signal
</flux:button>
@endif
@if($meetup->simplex)
<flux:button href="{{ $meetup->simplex }}" target="_blank" variant="ghost" class="justify-start">
<flux:icon.chat-bubble-oval-left-ellipsis class="w-5 h-5 mr-2" />
SimpleX
</flux:button>
@endif
@if($meetup->nostr)
<div class="col-span-full">
<flux:heading size="sm" class="mb-2">Nostr</flux:heading>
<code x-copy-to-clipboard="'{{ $meetup->nostr }}'" class="cursor-pointer block p-2 bg-gray-100 dark:bg-gray-800 rounded text-xs break-all">{{ $meetup->nostr }}</code>
</div>
@endif
</div>
@if($meetup->community)
<div>
<flux:heading size="sm" class="mb-2">Community</flux:heading>
<p class="text-gray-700 dark:text-gray-300">{{ $meetup->community }}</p>
</div>
@endif
</div>
</div>
<!-- Right Column: Map -->
<div>
<style>
#meetup-map {
height: 70vh;
min-height: 500px;
z-index: 0!important;
}
#meetup-map:focus {
outline: none;
}
</style>
@php
$attribution = '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
@endphp
<div>
<flux:heading size="lg" class="mb-4">{{ __('Standort') }}</flux:heading>
</div>
<div x-data="{
meetup: @js($meetup),
initializeMap() {
const map = L.map($refs.map, {
scrollWheelZoom: false
}).setView([this.meetup.city.latitude, this.meetup.city.longitude], 8);
L.tileLayer('https://tile.openstreetmap.de/{z}/{x}/{y}.png', {
minZoom: 0,
maxZoom: 18,
attribution: '{{ $attribution }}'
}).addTo(map);
// Custom BTC icon
const btcIcon = L.icon({
iconUrl: '/img/btc_marker.png',
iconSize: [32, 32],
iconAnchor: [16, 32],
popupAnchor: [0, -32],
shadowUrl: null
});
L.marker([this.meetup.city.latitude, this.meetup.city.longitude], {
icon: btcIcon
})
.bindPopup(this.meetup.name)
.addTo(map);
// CTRL + scroll wheel zoom
const container = map.getContainer();
container.addEventListener('wheel', function (e) {
e.preventDefault();
if (e.ctrlKey) {
const delta = e.deltaY > 0 ? -1 : 1;
map.setZoom(map.getZoom() + delta, { animate: true });
}
}, { passive: false });
}
}"
x-init="initializeMap()"
>
<div id="meetup-map" x-ref="map"></div>
<p class="text-sm text-gray-500 mt-2">{{ __('Zoom = STRG+Scroll') }}</p>
</div>
</div>
</div>
</div>

View File

@@ -33,7 +33,7 @@ new class extends Component {
$attribution = '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
@endphp
<div>
<flux:heading>Zoom = STRG+Scroll</flux:heading>
<flux:heading>{{ __('Zoom = STRG+Scroll') }}</flux:heading>
</div>
<div x-data="{
markers: @js($meetups),

View File

@@ -16,6 +16,7 @@ Route::middleware([])
Volt::route('meetups', 'meetups.index')->name('meetups.index');
Volt::route('map', 'meetups.map')->name('meetups.map');
Volt::route('meetup/{meetup:slug}', 'meetups.landingpage')->name('meetups.landingpage');
});
Route::middleware(['auth'])

315
yarn.lock
View File

@@ -312,6 +312,60 @@
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz#38ae84f4c04226c1d56a3b17296ef1e0460ecdfe"
integrity sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==
"@shikijs/core@3.15.0":
version "3.15.0"
resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-3.15.0.tgz#eee251070b4e39b59e108266cbcd50c85d738d54"
integrity sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg==
dependencies:
"@shikijs/types" "3.15.0"
"@shikijs/vscode-textmate" "^10.0.2"
"@types/hast" "^3.0.4"
hast-util-to-html "^9.0.5"
"@shikijs/engine-javascript@3.15.0":
version "3.15.0"
resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-3.15.0.tgz#478dd4feb3b4b7e91f148cc9e7ebc0b7de5fbb18"
integrity sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg==
dependencies:
"@shikijs/types" "3.15.0"
"@shikijs/vscode-textmate" "^10.0.2"
oniguruma-to-es "^4.3.3"
"@shikijs/engine-oniguruma@3.15.0":
version "3.15.0"
resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-3.15.0.tgz#bc5fe6484d64b2daacdfbb248f06732fbc78c8e2"
integrity sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA==
dependencies:
"@shikijs/types" "3.15.0"
"@shikijs/vscode-textmate" "^10.0.2"
"@shikijs/langs@3.15.0":
version "3.15.0"
resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-3.15.0.tgz#d8385a9ca66ce9923149c650336444b1d25fc248"
integrity sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A==
dependencies:
"@shikijs/types" "3.15.0"
"@shikijs/themes@3.15.0":
version "3.15.0"
resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-3.15.0.tgz#6093a90191b89654045c72636ddd35c04273658f"
integrity sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ==
dependencies:
"@shikijs/types" "3.15.0"
"@shikijs/types@3.15.0":
version "3.15.0"
resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-3.15.0.tgz#4e025b4dea98e1603243b1f00677854e07e5eda1"
integrity sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw==
dependencies:
"@shikijs/vscode-textmate" "^10.0.2"
"@types/hast" "^3.0.4"
"@shikijs/vscode-textmate@^10.0.2":
version "10.0.2"
resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz#a90ab31d0cc1dfb54c66a69e515bf624fa7b2224"
integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==
"@tailwindcss/node@4.1.17":
version "4.1.17"
resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.1.17.tgz#ec40a37293246f4eeab2dac00e4425af9272f600"
@@ -431,6 +485,30 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e"
integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==
"@types/hast@^3.0.0", "@types/hast@^3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa"
integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==
dependencies:
"@types/unist" "*"
"@types/mdast@^4.0.0":
version "4.0.4"
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6"
integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==
dependencies:
"@types/unist" "*"
"@types/unist@*", "@types/unist@^3.0.0":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c"
integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==
"@ungap/structured-clone@^1.0.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8"
integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
@@ -498,6 +576,11 @@ caniuse-lite@^1.0.30001754:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz#fe80104631102f88e58cad8aa203a2c3e5ec9ebd"
integrity sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==
ccount@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5"
integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==
chalk@4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@@ -506,6 +589,16 @@ chalk@4.1.2:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
character-entities-html4@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b"
integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==
character-entities-legacy@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b"
integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==
cliui@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
@@ -534,6 +627,11 @@ combined-stream@^1.0.8:
dependencies:
delayed-stream "~1.0.0"
comma-separated-tokens@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee"
integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==
concurrently@^9.0.1:
version "9.2.1"
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-9.2.1.tgz#248ea21b95754947be2dad9c3e4b60f18ca4e44f"
@@ -551,11 +649,23 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
dequal@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
detect-libc@^2.0.3:
version "2.1.2"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad"
integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==
devlop@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018"
integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==
dependencies:
dequal "^2.0.0"
dunder-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
@@ -746,6 +856,35 @@ hasown@^2.0.2:
dependencies:
function-bind "^1.1.2"
hast-util-to-html@^9.0.5:
version "9.0.5"
resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz#ccc673a55bb8e85775b08ac28380f72d47167005"
integrity sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==
dependencies:
"@types/hast" "^3.0.0"
"@types/unist" "^3.0.0"
ccount "^2.0.0"
comma-separated-tokens "^2.0.0"
hast-util-whitespace "^3.0.0"
html-void-elements "^3.0.0"
mdast-util-to-hast "^13.0.0"
property-information "^7.0.0"
space-separated-tokens "^2.0.0"
stringify-entities "^4.0.0"
zwitch "^2.0.4"
hast-util-whitespace@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621"
integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==
dependencies:
"@types/hast" "^3.0.0"
html-void-elements@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7"
integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
@@ -850,6 +989,53 @@ math-intrinsics@^1.1.0:
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
mdast-util-to-hast@^13.0.0:
version "13.2.0"
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4"
integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==
dependencies:
"@types/hast" "^3.0.0"
"@types/mdast" "^4.0.0"
"@ungap/structured-clone" "^1.0.0"
devlop "^1.0.0"
micromark-util-sanitize-uri "^2.0.0"
trim-lines "^3.0.0"
unist-util-position "^5.0.0"
unist-util-visit "^5.0.0"
vfile "^6.0.0"
micromark-util-character@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.1.tgz#2f987831a40d4c510ac261e89852c4e9703ccda6"
integrity sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==
dependencies:
micromark-util-symbol "^2.0.0"
micromark-util-types "^2.0.0"
micromark-util-encode@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz#0d51d1c095551cfaac368326963cf55f15f540b8"
integrity sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==
micromark-util-sanitize-uri@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz#ab89789b818a58752b73d6b55238621b7faa8fd7"
integrity sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==
dependencies:
micromark-util-character "^2.0.0"
micromark-util-encode "^2.0.0"
micromark-util-symbol "^2.0.0"
micromark-util-symbol@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz#e5da494e8eb2b071a0d08fb34f6cefec6c0a19b8"
integrity sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==
micromark-util-types@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.2.tgz#f00225f5f5a0ebc3254f96c36b6605c4b393908e"
integrity sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
@@ -877,6 +1063,20 @@ normalize-range@^0.1.2:
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
oniguruma-parser@^0.12.1:
version "0.12.1"
resolved "https://registry.yarnpkg.com/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz#82ba2208d7a2b69ee344b7efe0ae930c627dcc4a"
integrity sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==
oniguruma-to-es@^4.3.3:
version "4.3.3"
resolved "https://registry.yarnpkg.com/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz#50db2c1e28ec365e102c1863dfd3d1d1ad18613e"
integrity sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==
dependencies:
oniguruma-parser "^0.12.1"
regex "^6.0.1"
regex-recursion "^6.0.2"
picocolors@^1.0.0, picocolors@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
@@ -906,11 +1106,35 @@ postcss@^8.5.3:
picocolors "^1.1.1"
source-map-js "^1.2.1"
property-information@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/property-information/-/property-information-7.1.0.tgz#b622e8646e02b580205415586b40804d3e8bfd5d"
integrity sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
regex-recursion@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/regex-recursion/-/regex-recursion-6.0.2.tgz#a0b1977a74c87f073377b938dbedfab2ea582b33"
integrity sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==
dependencies:
regex-utilities "^2.3.0"
regex-utilities@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/regex-utilities/-/regex-utilities-2.3.0.tgz#87163512a15dce2908cf079c8960d5158ff43280"
integrity sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==
regex@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/regex/-/regex-6.0.1.tgz#282fa4435d0c700b09c0eb0982b602e05ab6a34f"
integrity sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==
dependencies:
regex-utilities "^2.3.0"
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -959,11 +1183,30 @@ shell-quote@1.8.3:
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.3.tgz#55e40ef33cf5c689902353a3d8cd1a6725f08b4b"
integrity sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==
shiki@^3.15.0:
version "3.15.0"
resolved "https://registry.yarnpkg.com/shiki/-/shiki-3.15.0.tgz#27cb37a080f987a4ec3a0402137b72f7400b8ea4"
integrity sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw==
dependencies:
"@shikijs/core" "3.15.0"
"@shikijs/engine-javascript" "3.15.0"
"@shikijs/engine-oniguruma" "3.15.0"
"@shikijs/langs" "3.15.0"
"@shikijs/themes" "3.15.0"
"@shikijs/types" "3.15.0"
"@shikijs/vscode-textmate" "^10.0.2"
"@types/hast" "^3.0.4"
source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
space-separated-tokens@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f"
integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@@ -973,6 +1216,14 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
stringify-entities@^4.0.0:
version "4.0.4"
resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3"
integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==
dependencies:
character-entities-html4 "^2.0.0"
character-entities-legacy "^3.0.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
@@ -1017,11 +1268,54 @@ tree-kill@1.2.2:
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
trim-lines@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338"
integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==
tslib@^2.1.0, tslib@^2.4.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
unist-util-is@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.1.tgz#d0a3f86f2dd0db7acd7d8c2478080b5c67f9c6a9"
integrity sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==
dependencies:
"@types/unist" "^3.0.0"
unist-util-position@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4"
integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==
dependencies:
"@types/unist" "^3.0.0"
unist-util-stringify-position@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2"
integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==
dependencies:
"@types/unist" "^3.0.0"
unist-util-visit-parents@^6.0.0:
version "6.0.2"
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz#777df7fb98652ce16b4b7cd999d0a1a40efa3a02"
integrity sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==
dependencies:
"@types/unist" "^3.0.0"
unist-util-is "^6.0.0"
unist-util-visit@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6"
integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==
dependencies:
"@types/unist" "^3.0.0"
unist-util-is "^6.0.0"
unist-util-visit-parents "^6.0.0"
update-browserslist-db@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz#7802aa2ae91477f255b86e0e46dbc787a206ad4a"
@@ -1030,6 +1324,22 @@ update-browserslist-db@^1.1.4:
escalade "^3.2.0"
picocolors "^1.1.1"
vfile-message@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.3.tgz#87b44dddd7b70f0641c2e3ed0864ba73e2ea8df4"
integrity sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==
dependencies:
"@types/unist" "^3.0.0"
unist-util-stringify-position "^4.0.0"
vfile@^6.0.0:
version "6.0.3"
resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.3.tgz#3652ab1c496531852bf55a6bac57af981ebc38ab"
integrity sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==
dependencies:
"@types/unist" "^3.0.0"
vfile-message "^4.0.0"
vite-plugin-full-reload@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/vite-plugin-full-reload/-/vite-plugin-full-reload-1.2.0.tgz#bc4bfdc842abb4d24309ca802be8b955fce1c0c6"
@@ -1083,3 +1393,8 @@ yargs@17.7.2:
string-width "^4.2.3"
y18n "^5.0.5"
yargs-parser "^21.1.1"
zwitch@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"
integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==