Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Markdown Tui Laravel Package

datomatic/nova-markdown-tui

A Laravel Nova field that integrates the Toast UI Markdown editor, giving your admin panel a clean WYSIWYG Markdown editing experience with live preview, toolbar controls, and straightforward configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is installed like any other Laravel library and is wired into the framework through a service provider and a single, well-defined entry point: the resolveCallback argument accepted by its resolver. That callback is where almost all of your day-to-day customization will happen, so it is the first thing to locate in the source (grep -rn "resolveCallback" vendor/) before writing any integration code.

Minimal setup:

composer require <vendor>/<package>   # v1.3.2
php artisan vendor:publish --provider="<Vendor>\<Package>\<Package>ServiceProvider"

Then confirm the provider is auto-discovered (php artisan about or php artisan package:discover) and that any published config file appears under config/. If the package ships a facade or helper, resolve it once in tinker to verify the container binding before building on top of it:

app(\<Vendor>\<Package>\<Package>::class);

First use case: register your resolver in AppServiceProvider::boot() rather than in a controller. The callback is invoked by the package internals, so keeping registration in a provider guarantees it is in place for HTTP requests, queued jobs, and console commands alike:

public function boot(): void
{
    $this->app->make(<Package>::class)->resolveUsing(
        fn ($value, $context) => YourModel::findOrFail($value)
    );
}

v1.3.2 itself is a drop-in patch — nothing to configure, just bump the constraint.

Implementation Patterns

Default-first, callback-second. The package resolves values on its own in the common case. Only supply a resolveCallback when your resolution differs from the default (tenant scoping, soft-deleted records, cached lookups, non-Eloquent sources). Overriding the default globally is the most common cause of "why is this slower/looser than before" surprises.

One resolver per concern, registered centrally. If you need different resolution behaviour per route, per model, or per context, prefer passing context through the callback rather than registering multiple resolvers:

->resolveUsing(function ($value, $context) {
    return match ($context['type'] ?? null) {
        'post' => Post::where('tenant_id', tenant()->id)->findOrFail($value),
        default => null, // fall through to package default
    };
});

Returning null (where the contract allows it) is the cleanest way to delegate back to the package's built-in behaviour.

Keep the callback pure and cheap. The resolver runs inside the request lifecycle and may be invoked more than once for the same value. Memoize expensive lookups:

resolveUsing(function ($value) {
    static $cache = [];
    return $cache[$value] ??= ExpensiveLookup::for($value);
});

Testing. Bind a fake resolver in the test case rather than hitting the database, and assert on what the callback received:

$this->app->make(<Package>::class)->resolveUsing(fn ($v) => new FakeResource($v));

For feature tests, RefreshDatabase plus a deterministic resolver keeps things fast; for unit tests, instantiate the resolver class directly — the callback signature is the only integration surface you need to stub.

Queues and serialization. If resolved objects end up inside jobs, resolve inside handle(), not in the constructor — otherwise you serialize models (and their relations) into the payload and hit stale-state bugs on retry.

Caching. Once your resolver is stable, verify it behaves under php artisan config:cache and route:cache; resolvers registered in boot() are fine, but anything registered conditionally on app()->environment() or on request data will be frozen.

Gotchas and Tips

PHP 8.4 implicit-nullable deprecation (the v1.3.2 fix). The release changes a signature from callable $resolveCallback = null to ?callable $resolveCallback = null. This is backward compatible for callers — but not for extenders. If you subclass the resolver, implement its interface, or override the method in your own code, replicate the nullable syntax exactly, or PHP 8.4 will emit Deprecated: Implicitly marking parameter $resolveCallback as nullable is deprecated from your file, not the package's. Grep your app/ for the method name after upgrading.

Static analysis noise. PHPStan/Psalm baselines that recorded the old signature will need regenerating after the bump. Likewise, any @param callable|null docblocks you copied from the vendor source should be updated to match.

Callback arity. The resolver passes arguments positionally. Adding a parameter to your closure is safe; changing the type of the first parameter (e.g. from int to string) is not — the package may cast before calling you. Dump the received value with dd(func_get_args()) once during integration to confirm the shape rather than assuming.

Exceptions inside the callback propagate. A ModelNotFoundException from findOrFail() inside your resolver surfaces wherever the package invokes it — often middleware, before your exception handler's rendering assumptions. Catch and rethrow a domain exception, or return null and let the package produce its own 404.

Config caching masks registration bugs. If resolution works in php artisan serve but fails in a cached production build, you have almost certainly registered the resolver conditionally. Move it to unconditional boot() code.

Extension points beyond the callback. Before writing a custom resolver, check whether the package exposes a contract binding ($this->app->bind(Resolver::class, MyResolver::class)) — replacing the implementation is usually cleaner than a closure, keeps the logic testable in isolation, and survives refactors of where the callback is registered.

Debugging. The callback is a natural breakpoint but an awkward log target. Wrap it temporarily:

resolveUsing(function (...$args) {
    logger()->debug('resolve', $args);
    return $original(...$args);
});

Upgrade hygiene. v1.3.2 is a patch release with no config or API changes; pin ^1.3 and bump freely. Watch for the broader PHP 8.4 nullable-signature sweep across your dependency tree in the same upgrade window — it is common for several packages to ship this fix in the same week, and it is easy to attribute a notice to the wrong package.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons