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

Laravel Rough Notation Laravel Package

amjadiqbal/laravel-rough-notation

A Laravel package that wraps Rough Notation, making it easy to add hand-drawn style annotations such as underlines, boxes, circles, highlights, brackets, and strike-throughs to text using Blade directives and PHP helpers with configurable animation.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. composer require amjadiqbal/laravel-rough-notation — v1.0.0 is the first tag, so pin ^1.0 and treat the public API as stable from here.
  2. Check for publishable assets (php artisan vendor:publish --provider="AmjadIqbal\RoughNotation\...") to see whether views/config can be overridden before you start customising markup by hand.
  3. Add @roughNotationScripts once, near the end of your main layout (before </body>). On 1.0.0 this actually compiles — pre-1.0 it threw a PHP parse error, so any layout workaround you inherited (a hand-written <script src="..."> CDN tag) should be deleted, not kept alongside it.
  4. First use case: wrap a single phrase in a landing-page heading with a highlight or underline annotation and confirm it renders. That exercises the whole chain — attribute emission, JSON options, and the client-side init — in about five minutes.

Start with one annotation on one page. The package is a thin Blade layer over RoughNotation; most of what you'll debug is the underlying JS library, not the PHP.

Implementation Patterns

Annotate inline content in Blade. The natural shape is a component wrapping the text it decorates:

<x-rough-notation type="highlight" color="#fde68a">
    ship faster
</x-rough-notation>

Because options travel as a data-rough-options JSON attribute, you can pass arrays/objects straight through from PHP rather than hand-writing JSON in the template — this is the pattern the 1.0.0 escaping fix exists to support.

Include assets exactly once. Put @roughNotationScripts in the layout, not inside each component. If you're on Vite, the cleaner long-term path is npm i rough-notation and importing it in resources/js/app.js — then you don't need the directive at all, and you get version pinning and bundling for free. Pick one; running both double-registers and produces confusing behaviour.

Centralise your annotation vocabulary. Rather than scattering color="#f59e0b" across views, define a handful of named styles (brand-highlight, brand-underline, callout-circle) — a config array, an enum, or a wrapper Blade component — and reference those. RoughNotation colours are baked into the generated SVG strokes, so consistency is cheap up front and expensive to retrofit.

Re-initialise after DOM swaps. This is the big one for Livewire/Alpine/Turbo apps: annotations are drawn once at page load against elements that exist at that moment. Content morphed in later has no SVG. Hook your framework's "DOM updated" event and re-run the package's init (or call RoughNotation.annotate() yourself on the new nodes).

Defer for long pages. RoughNotation supports an animate option and observers; on marketing pages with a dozen annotations, triggering on scroll-into-view avoids a visible flash of annotation-drawing above the fold and cuts initial work.

Gotchas and Tips

The escaping fix changes bytes on the wire. If any of your own JavaScript reads data-rough-options and worked around the over-escaping — JSON.parse(el.dataset.roughOptions.replace(/&quot;/g, '"')), an html_entity_decode-style helper, a {!! !!} wrapper around the options payload — remove it. After 1.0.0 the attribute contains literal JSON, and your workaround will now corrupt it. Same for any custom Blade partial that re-derived options from the attribute.

Same for the script directive. The @roughNotationScripts parse error (unescaped quote in a single-quoted PHP string) meant any view using the directive failed to compile — not a runtime error, a compile-time one. If a colleague concluded the directive was broken and hardcoded a CDN <script> tag, that's now duplicate script loading. Grep for rough-notation script tags during upgrade.

Test assertions may flip. If your Pest/PHPUnit suite asserts against rendered HTML containing an annotated element, assertSee calls involving quotes or ampersands in options will now match different strings. Run the suite before assuming a regression. Notably, the package's own Pest suite apparently wasn't running until this release — which is a fair signal to keep your own coverage around the rendered output rather than trusting the package's tests.

Dark mode needs a re-render, not a CSS toggle. Annotation colours are set as SVG stroke/fill attributes. Switching theme by swapping CSS variables won't recolour existing annotations; you'll need to clear and re-annotate on theme change. Simplest mitigation: define annotation colours as theme-agnostic accents that read acceptably on both backgrounds.

Accessibility check. RoughNotation draws decorative SVG over the text. Verify the underlying text remains selectable, copyable, and screen-reader-visible (the library sets aria-hidden on the SVG — don't defeat that), and that annotations aren't the sole carrier of meaning. Never annotate text that's only present in the SVG.

Layout edge cases. Annotating an inline element that wraps across lines produces an SVG that doesn't follow the line break cleanly. For long phrases, either shorten to a few words or switch to box/bracket, which degrade more gracefully. Similarly, position: relative on a parent and overflow clipping can hide annotations that extend past the text bounds.

Semver is now real. Pre-1.0 had no tag but was "already shipping as 1.0." That means the API you're using is frozen — no more silent breaking changes, and a ^1.0 constraint is meaningful. If you were tracking dev-main or a branch alias, switch to the tag now; you'll stop absorbing unreviewed changes.

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.
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
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route