{{-- A stored URL, rendered as a link out of the app. Props: url The stored URL, or null. Nothing but the fallback renders when it is empty, so a detail row still reads as a row. fallback What an empty url shows. An em-dash unless told otherwise. label Link text. The url itself unless told otherwise. Two things this component owns so no caller has to remember them: * `target="_blank"` gets `rel="noopener noreferrer"` with it. Without noopener the opened page can reach back through window.opener; without noreferrer it learns which of our screens it was opened from. * The url reaches the href through Blade's own escaping, so a quote in a stored value closes nothing. The scheme is the server's job and is already done: every url column is validated `url:http,https`, which is what keeps `javascript:` out of an href — escaping alone would not. The scheme is checked again below anyway. Nothing the app writes can fail that check, so the branch is unreachable through the forms; it is there for a value that predates the validation rule or was written straight to the database, which the FormRequest cannot speak for. A url that fails it renders as the fallback rather than as a link. --}} @props([ 'url' => null, 'fallback' => '—', 'label' => null, ]) @if (filled($url) && (str_starts_with($url, 'http://') || str_starts_with($url, 'https://'))) merge(['class' => 'text-primary']) }}>{{ $label ?? $url }} @else {{ $fallback }} @endif