snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-23 16:12:52 +05:00
commit a774ac673a
4541 changed files with 770499 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
import { Hit } from 'instantsearch.js'
import { getHighlightedParts, getPropertyByPath, unescape } from 'instantsearch.js/es/lib/utils'
import { memo } from 'react'
import { SearchEntry } from '@/utils/algolia'
export const ContentHighlight = memo(function ContentHighlight({ hit }: { hit: Hit<SearchEntry> }) {
const descriptionHighlight = getHighlights(hit, 'description', 40)
const contentHighlight = getHighlights(hit, 'content', 40)
let firstItem = null
let secondItem = null
if (descriptionHighlight.didMatch === contentHighlight.didMatch) {
// if both either matched or didn't, show whatever has actual content:
if (descriptionHighlight.parts.length && contentHighlight.parts.length) {
firstItem = descriptionHighlight
secondItem = contentHighlight
} else if (descriptionHighlight.parts.length) {
firstItem = descriptionHighlight
} else if (contentHighlight.parts.length) {
firstItem = contentHighlight
}
} else if (descriptionHighlight.didMatch && !contentHighlight.didMatch) {
// if only the description matched, show both because the description is short:
firstItem = descriptionHighlight
secondItem = contentHighlight
} else {
// otherwise, only the content matched. show just the content:
firstItem = contentHighlight
}
if (firstItem && !secondItem) {
// if we only have the first item, show it over two lines:
return (
<HighlightContent
didTruncateStart={firstItem.didTruncateStart}
parts={firstItem.parts}
className="line-clamp-2 text-sm"
/>
)
} else {
// otherwise, show both items on one line each:
return (
<>
{firstItem && (
<HighlightContent
didTruncateStart={firstItem.didTruncateStart}
parts={firstItem.parts}
className="line-clamp-1 text-sm"
/>
)}
{secondItem && (
<HighlightContent
didTruncateStart={secondItem.didTruncateStart}
parts={secondItem.parts}
className="line-clamp-1 text-sm"
/>
)}
</>
)
}
})
function HighlightContent({
parts,
didTruncateStart,
className,
}: {
parts: { value: string; isHighlighted: boolean }[]
didTruncateStart: boolean
className: string
}) {
return (
<div className={className}>
{didTruncateStart && '…'}
{parts.map((part, index) =>
part.isHighlighted ? <mark key={index}>{part.value}</mark> : part.value
)}
</div>
)
}
function getHighlights(
hit: Hit<SearchEntry>,
attribute: 'description' | 'content',
maxUnhighlightedPrefix: number
): {
didTruncateStart: boolean
didMatch: boolean
parts: { value: string; isHighlighted: boolean }[]
} {
const originalProperty = hit[attribute]?.trim()
const highlightedProperty = getPropertyByPath(hit._highlightResult, attribute as string)
if (!highlightedProperty) {
return {
didMatch: false,
didTruncateStart: false,
parts: originalProperty ? [{ value: originalProperty, isHighlighted: false }] : [],
}
}
const parts = getHighlightedParts(unescape(highlightedProperty.value || ''))
let didTruncateStart = false
const didMatch = parts.some((part) => part.isHighlighted)
const initialPart = parts[0]
// if the first part is unhighlighted and too long, we should cut it short
if (initialPart && !initialPart.isHighlighted && didMatch) {
const words = initialPart.value.split(' ').reverse()
let lengthSoFar = 0
const wordsToInclude: string[] = []
for (const word of words) {
lengthSoFar += word.length
if (lengthSoFar > maxUnhighlightedPrefix) {
break
}
wordsToInclude.push(word)
}
if (wordsToInclude.length < words.length) {
didTruncateStart = true
parts[0].value = `${wordsToInclude.reverse().join(' ')}`
}
}
return { didTruncateStart, didMatch, parts }
}