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

Css Color Validator Bundle Laravel Package

jbafford/css-color-validator-bundle

A Symfony bundle that validates CSS color values, checking strings against supported color formats and specifications. Useful for form constraints and sanitizing user-supplied color input before it reaches your stylesheets.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before you type a single line: this repository is a Symfony bundle, not a Laravel package. It ships a Constraint + ConstraintValidator pair wired through Symfony's DI extension and Kernel::registerBundles(). Laravel does not consume bundles. There is no ServiceProvider, no config/css_color_validator.php, no facade, and no auto-discovery. Running composer require jbafford/css-color-validator-bundle in a Laravel app will at best pull in symfony/validator as dead weight and at worst fail resolution outright against PHP 8.x / Symfony 6–7 constraints.

So what do you actually do?

  1. Read the source first — not the docs. The value of this package is the grammar knowledge encoded in the validator class (typically something like vendor/jbafford/css-color-validator-bundle/Validator/Constraints/CssColorValidator.php). Open that file. That is what you are effectively adopting.
  2. Decide the real requirement. Two very different asks:
    • "Is this syntactically valid CSS color?" → grammar validation. This bundle (or its logic) is relevant.
    • "Is this safe to interpolate into a stylesheet?" → allowlist problem. A regex or in_array() against a known set is the correct, cheaper, safer answer. Do not use a grammar parser for this.
  3. Install attempt (timeboxed to ~30 minutes). In a throwaway container, try composer require jbafford/css-color-validator-bundle. The resolution failure is the proof you need that the bundle path is dead. Record the result.
  4. Vendor, don't depend. Copy the constraint validator class into app/Rules/Support/CssColorValidator.php, retain the MIT header, and wrap it in an Illuminate\Contracts\Validation\Rule. This is the realistic first use case: a white-label branding settings form where users type a hex or rgb() value and you must reject garbage before it reaches your CSS generator.

First use case to build: a theming endpoint (PUT /settings/theme) with a color field on the request. Rule: new ValidCssColor(). This is a two-hour task and gives you a working integration to test the grammar against real user input.

Implementation Patterns

Pattern 1 — Laravel ValidationRule wrapper (the primary pattern).

// app/Rules/ValidCssColor.php
namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;

class ValidCssColor implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (!is_string($value) || !$this->isValidColor($value)) {
            $fail('validation.css_color')->translate();
        }
    }

    private function isValidColor(string $value): bool
    {
        // Delegate to vendored logic or spatie/color + explicit allowlist
        return CssColorGrammar::matches(trim($value));
    }
}

Pattern 2 — Form request integration. Define a ThemeSettingsRequest with rules(): array returning 'color' => ['required', 'string', new ValidCssColor()]. This is where the rule lives in most Laravel apps; you rarely call Validator::make() manually for this.

Pattern 3 — Legacy string-rule call sites. If you have existing 'color' => 'regex:...' rules scattered around, use Validator::extend('css_color', fn ($attr, $value) => ...) to register a string alias, then migrate call sites to the Rule object over time. Do not add new string-rule call sites.

Pattern 4 — Import / bulk validation. For CSV/JSON imports carrying color config, run the rule per row before persistence. Batch a validation pass over the input array and collect all failures, rather than failing on the first bad color — a half-imported theme config is worse than a rejected one.

Pattern 5 — Pair with a normalization layer. The bundle (and any grammar validator) answers yes/no only. In a theming pipeline you almost always follow with normalization: #FFF → #ffffff, rgb(255,0,0) → hex. Do this in a separate service (ColorNormalizer) backed by spatie/color. Keeping "is valid" and "is canonical" separate means you can swap either independently.

Pattern 6 — Testing. Maintain a fixture array of [input, expected] pairs covering: 3- and 6-digit hex, 8-digit hex with alpha, legacy rgb() comma syntax, modern space/slash rgb(), hsl(), hwb(), transparent, currentColor, named colors, and — critically — modern CSS Color 4/5 (lab(), lch(), oklch(), color(display-p3 …)). Assert accept/reject on each. Every false-rejection bug your users report gets added as a fixture.

Gotchas and Tips

The false-negative trap (highest pain). A 2010s-era validator will reject oklch(70% 0.15 250) or color(display-p3 1 0 0) even though browsers handle them fine. Rejecting valid input is the worst failure mode for a validation rule — it surfaces as a bug report against your product, and it is nearly impossible to distinguish from a user typing genuine garbage. Test your actual expected input syntaxes against the vendored validator before shipping. If your users only ever get colors from a picker emitting #rrggbb, use an allowlist regex instead and skip the grammar entirely.

Don't confuse validation with safety. If user-supplied color strings are interpolated into a <style> block or a generated .css file, a grammar-valid string is not automatically injection-safe (var(--x), url(...) inside certain functions, attr() in modern specs). If that is your real threat model, use a strict allowlist (# + hex, plus an enumerated set of function forms) and reject everything else. Grammar validation answers a correctness question, not a security one.

Configuration quirks. If you attempt the bundle path, expect Composer to fight you on Symfony version constraints. The *Bundle naming and single-maintainer history strongly suggest Symfony 3/4-era code. Even if resolution succeeds, you have adopted an unmaintained transitive dependency (symfony/validator) for one string check. Note this in the pull request so reviewers understand the trade.

Empty and null input. Confirm the vendored validator fails closed on "", " ", and null. Some grammar validators happily return true for an empty string because "zero tokens = vacuously valid." Your Rule wrapper should short-circuit these to false before delegating.

Maintenance posture — assume you are the fork. 1 star, 0 dependents, single maintainer, no issue triage, no release cadence. Plan for zero upstream fixes. Keep a NOTICE file crediting the original MIT license if you vendor the code, and pin the commit hash in a comment so future maintainers can find the origin.

Extension point is the wrapper, not the package. Do not patch the vendored class. Add behavior — allowlist overrides, normalization, logging of rejections — in your ValidCssColor rule or a small CssColorGrammar service that the rule calls. That keeps the vendored code frozen and diffable against upstream if you ever need to diff it.

Instrument rejections for the first two weeks. Log every color value your rule rejects (with a correlation ID, not the raw string if PII concerns apply) and review the log weekly. This is the only practical way to catch false negatives on real input before users escalate them as bugs. Roll the rule out behind a feature flag if the theming feature is customer-facing.

Migration guidance. There is no incremental migration path — 0 dependents, no evidence of prior internal use. Treat this as greenfield: write the rule, add fixtures, ship. If you later find the vendored behavior insufficient, swapping in spatie/color + an allowlist is a single-class change because the wrapper isolates the dependency.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings