feat(workspace): slash commands ranked by name, taller link cards with a link marker
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m22s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m22s
- /li lists /link first: name prefix, aliases, name, then description - link cards about twice as tall; the bare address below becomes an accent link marker; the link chip bar under bullets is gone, bare web addresses in text are links themselves chore(release): v0.14.3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
08ae91fcdb
commit
6a855fc32c
10 files changed
+109
-72
No files matched your search
@@ -21,3 +21,11 @@ describe('link preview helpers', () => {
|
||||
expect(linkCardUrl(hidePreviewContent('https://koch.de/x', 'https://koch.de/x', 'T'))).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('linkHost', () => {
|
||||
it('shows host and path without scheme and www', async () => {
|
||||
const { linkHost } = await import('../linkPreview');
|
||||
expect(linkHost('https://www.example.com/')).toBe('example.com');
|
||||
expect(linkHost('https://example.com/blog/post')).toBe('example.com/blog/post');
|
||||
});
|
||||
});
|
||||
@@ -17,6 +17,19 @@ describe('renderInlineMarkdown', () => {
|
||||
expect(container.textContent).toBe('Der Block services startet');
|
||||
});
|
||||
|
||||
it('links bare web addresses without the trailing punctuation and keeps markdown links intact', () => {
|
||||
const { container } = render(
|
||||
<div>{renderInlineMarkdown('Siehe https://example.com/a_b_c. und [Doku](https://example.org/x) oder https://x.de/#frag')}</div>
|
||||
);
|
||||
const links = [...container.querySelectorAll('a')].map((a) => [a.textContent, a.getAttribute('href')]);
|
||||
expect(links).toEqual([
|
||||
['https://example.com/a_b_c', 'https://example.com/a_b_c'],
|
||||
['Doku', 'https://example.org/x'],
|
||||
['https://x.de/#frag', 'https://x.de/#frag'],
|
||||
]);
|
||||
expect(container.textContent).toBe('Siehe https://example.com/a_b_c. und Doku oder https://x.de/#frag');
|
||||
});
|
||||
|
||||
it('renders italic text with <em> tag', () => {
|
||||
const { container } = render(<div>{renderInlineMarkdown('Text mit *kursivem* Wort')}</div>);
|
||||
const em = container.querySelector('em');
|
||||
|
||||
@@ -25,6 +25,17 @@ export function linkCardUrl(content: string): string | null {
|
||||
}
|
||||
|
||||
/** Replaces the address by a named link, which shows no preview. */
|
||||
/** "example.com/pfad" for a short link marker (no scheme, no www.) */
|
||||
export function linkHost(url: string): string {
|
||||
try {
|
||||
const u = new URL(url);
|
||||
const path = u.pathname === '/' ? '' : u.pathname;
|
||||
return u.host.replace(/^www\./, '') + path;
|
||||
} catch {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
export function hidePreviewContent(content: string, url: string, title: string): string {
|
||||
const label = (title || new URL(url).hostname).replace(/[[\]]/g, '').trim() || url;
|
||||
return content.replace(url, `[${label}](${url})`);
|
||||
|
||||
@@ -22,7 +22,7 @@ function renderInlineTokens(text: string, options?: InlineMarkdownOptions): Reac
|
||||
|
||||
const tagAlt = options?.onTagClick ? '|#[a-zA-Z0-9äöüÄÖÜß_-]+' : '';
|
||||
const regex = new RegExp(
|
||||
'(\\[\\[[^\\]]+\\]\\]|`[^`]+`|\\*\\*[^*]+\\*\\*|__[^_]+__|~~[^~]+~~|\\*[^*]+\\*|_[^_]+_|\\[([^\\]]+)\\]\\(([^)]+)\\)' + tagAlt + ')',
|
||||
'(\\[\\[[^\\]]+\\]\\]|https?:\\/\\/[^\\s<>()\\[\\]]+[^\\s<>()\\[\\].,;:!?"\']|`[^`]+`|\\*\\*[^*]+\\*\\*|__[^_]+__|~~[^~]+~~|\\*[^*]+\\*|_[^_]+_|\\[([^\\]]+)\\]\\(([^)]+)\\)' + tagAlt + ')',
|
||||
'g'
|
||||
);
|
||||
|
||||
@@ -37,7 +37,25 @@ function renderInlineTokens(text: string, options?: InlineMarkdownOptions): Reac
|
||||
const token = match[0];
|
||||
const key = `${match.index}-${token}`;
|
||||
|
||||
if (token.startsWith('[[') && token.endsWith(']]')) {
|
||||
if (/^https?:\/\//.test(token)) {
|
||||
const href = safeHref(token);
|
||||
elements.push(
|
||||
href ? (
|
||||
<a
|
||||
key={key}
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-accent underline underline-offset-2 decoration-accent/40 hover:decoration-accent break-all"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{token}
|
||||
</a>
|
||||
) : (
|
||||
token
|
||||
)
|
||||
);
|
||||
} else if (token.startsWith('[[') && token.endsWith(']]')) {
|
||||
const link = parseWikiLink(token.slice(2, -2));
|
||||
const onClick = options?.onWikiLinkClick;
|
||||
elements.push(
|
||||
|
||||
Reference in new issue
Block a user