Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions apps/desktop/src/app/artifacts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ import { RowButton } from '@/components/ui/row-button'
import { Tip } from '@/components/ui/tooltip'
import { getSessionMessages, listAllProfileSessions } from '@/hermes'
import { type Translations, useI18n } from '@/i18n'
import { ExternalLink, ExternalLinkIcon, hostPathLabel, urlSlugTitleLabel, useLinkTitle } from '@/lib/external-link'
import { resolveBrandIcon } from '@/lib/brand-icon'
import {
ExternalLink,
ExternalLinkIcon,
hostPathLabel,
shortHostLabel,
urlSlugTitleLabel,
useLinkTitle
} from '@/lib/external-link'
import { FileImage, FileText, FolderOpen, Link2, Loader2, RefreshCw } from '@/lib/icons'
import { downloadGatewayMediaFile, isRemoteGateway } from '@/lib/media'
import { normalize } from '@/lib/text'
Expand Down Expand Up @@ -543,7 +551,8 @@ function ArtifactCellAction({

function PrimaryCell({ artifact, ctx }: { artifact: ArtifactRecord; ctx: CellCtx }) {
const isLink = artifact.kind === 'link'
const Icon = isLink ? Link2 : FileText
const brand = isLink ? resolveBrandIcon(shortHostLabel(artifact.href)) : null
const Icon = brand ?? (isLink ? Link2 : FileText)
const fetchedTitle = useLinkTitle(isLink ? artifact.href : null)
const label = isLink ? fetchedTitle || urlSlugTitleLabel(artifact.href) : artifact.label

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ export const SessionRefLink: FC<{

return (
<a
className="link-chip font-semibold wrap-anywhere"
className="link-chip wrap-anywhere"
href="#"
onClick={event => {
event.preventDefault()
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/components/assistant-ui/markdown-text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ function MediaAttachment({ path }: { path: string }) {
return (
<span className="wrap-anywhere">
<a
className="link-chip font-semibold wrap-anywhere"
className="link-chip wrap-anywhere"
href="#"
onClick={event => {
event.preventDefault()
Expand Down Expand Up @@ -283,7 +283,7 @@ function MarkdownLink({ children, className, href, ...props }: ComponentProps<'a
if (!target || !/^https?:\/\//i.test(target)) {
return (
<a
className={cn('link-chip font-semibold wrap-anywhere', className)}
className={cn('link-chip wrap-anywhere', className)}
href={href}
rel="noopener noreferrer"
target="_blank"
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/components/chat/compact-markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function tagged<T extends keyof typeof TAG_CLASSES>(Tag: T) {
function MarkdownAnchor({ children, className, href, ...rest }: ComponentProps<'a'>) {
if (!href || !/^https?:\/\//i.test(href)) {
return (
<a className={cn('link-chip font-medium', className)} href={href} {...rest}>
<a className={cn('link-chip', className)} href={href} {...rest}>
{children}
</a>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export const GeneratedImage: FC<{ aspectRatio?: string; result?: unknown }> = ({
if (failed && image) {
return (
<a
className="mt-2 link-chip inline-block font-semibold wrap-anywhere"
className="mt-2 link-chip inline-block wrap-anywhere"
href="#"
onClick={event => {
event.preventDefault()
Expand Down
43 changes: 43 additions & 0 deletions apps/desktop/src/lib/brand-icon.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { describe, expect, it } from 'vitest'

import { resolveBrandIcon } from './brand-icon'

describe('resolveBrandIcon', () => {
it('resolves a registrable domain to a brand glyph', () => {
expect(resolveBrandIcon('github.com')).toBeTruthy()
expect(resolveBrandIcon('gitlab.com')).toBeTruthy()
})

it('ignores case and a leading www.', () => {
const github = resolveBrandIcon('github.com')

expect(resolveBrandIcon('WWW.GitHub.com')).toBe(github)
})

it('inherits the parent brand on subdomains', () => {
const github = resolveBrandIcon('github.com')

expect(resolveBrandIcon('gist.github.com')).toBe(github)
expect(resolveBrandIcon('api.github.com')).toBe(github)
})

it('prefers the longest matching suffix over its parent', () => {
const google = resolveBrandIcon('google.com')
const docs = resolveBrandIcon('docs.google.com')

expect(docs).toBeTruthy()
expect(docs).not.toBe(google)
})

it('returns null for unknown hosts and bare labels', () => {
expect(resolveBrandIcon('example.com')).toBeNull()
expect(resolveBrandIcon('localhost')).toBeNull()
expect(resolveBrandIcon('')).toBeNull()
})

it('never matches on a bare public suffix', () => {
// `github.io` is a real entry; a lone `io` must not inherit it.
expect(resolveBrandIcon('io')).toBeNull()
expect(resolveBrandIcon('com')).toBeNull()
})
})
Loading
Loading