🚧 wip icons for context providers

This commit is contained in:
Nate Sesti 2024-06-11 13:31:39 -07:00
parent 894e1a3ffb
commit ecd7a81a6c
6 changed files with 127 additions and 21 deletions

View File

@ -1,3 +1,4 @@
import fetch from "node-fetch";
import {
ContextItem,
ContextProviderDescription,
@ -19,6 +20,22 @@ class DocsContextProvider extends BaseContextProvider {
type: "submenu",
};
private async _getIconDataUrl(url: string): Promise<string | undefined> {
try {
const response = await fetch(url);
if (!response.headers.get("content-type")?.startsWith("image/")) {
console.log("Not an image: ", await response.text());
return undefined;
}
const buffer = await response.buffer();
const base64data = buffer.toString("base64");
return `data:${response.headers.get("content-type")};base64,${base64data}`;
} catch (e) {
console.log("E: ", e);
return undefined;
}
}
async getContextItems(
query: string,
extras: ContextProviderExtras,
@ -90,7 +107,7 @@ class DocsContextProvider extends BaseContextProvider {
): Promise<ContextSubmenuItem[]> {
const { listDocs } = await import("../../indexing/docs/db.js");
const docs = await listDocs();
const submenuItems = docs.map((doc) => ({
const submenuItems: ContextSubmenuItem[] = docs.map((doc) => ({
title: doc.title,
description: new URL(doc.baseUrl).hostname,
id: doc.baseUrl,
@ -106,6 +123,7 @@ class DocsContextProvider extends BaseContextProvider {
title: config.title,
description: new URL(config.startUrl).hostname,
id: config.startUrl,
// iconUrl: config.faviconUrl,
})),
);
@ -129,6 +147,15 @@ class DocsContextProvider extends BaseContextProvider {
}
});
// const icons = await Promise.all(
// submenuItems.map(async (item) =>
// item.iconUrl ? this._getIconDataUrl(item.iconUrl) : undefined,
// ),
// );
// icons.forEach((icon, i) => {
// submenuItems[i].iconUrl = icon;
// });
return submenuItems;
}
}

View File

@ -1,246 +1,294 @@
import {SiteIndexingConfig} from "../../index.js";
import { SiteIndexingConfig } from "../../index.js";
const configs: SiteIndexingConfig[] = [
{
title: "Jinja",
startUrl: "https://jinja.palletsprojects.com/en/3.1.x/",
rootUrl: "https://jinja.palletsprojects.com/en/3.1.x/",
faviconUrl: "https://jinja.palletsprojects.com/favicon.ico",
},
{
title: "React",
startUrl: "https://react.dev/reference/",
rootUrl: "https://react.dev/reference/",
faviconUrl: "https://react.dev/favicon.ico",
},
{
title: "PostHog",
startUrl: "https://posthog.com/docs",
rootUrl: "https://posthog.com/docs",
faviconUrl: "https://posthog.com/favicon.ico",
},
{
title: "Express",
startUrl: "https://expressjs.com/en/5x/api.html",
rootUrl: "https://expressjs.com/en/5x/",
faviconUrl: "https://expressjs.com/favicon.ico",
},
{
title: "OpenAI",
startUrl: "https://platform.openai.com/docs/",
rootUrl: "https://platform.openai.com/docs/",
faviconUrl: "https://platform.openai.com/favicon.ico",
},
{
title: "Prisma",
startUrl: "https://www.prisma.io/docs",
rootUrl: "https://www.prisma.io/docs",
faviconUrl: "https://www.prisma.io/favicon.ico",
},
{
title: "Boto3",
startUrl:
"https://boto3.amazonaws.com/v1/documentation/api/latest/index.html",
rootUrl: "https://boto3.amazonaws.com/v1/documentation/api/latest/",
faviconUrl: "https://boto3.amazonaws.com/favicon.ico",
},
{
title: "Pytorch",
startUrl: "https://pytorch.org/docs/stable/",
rootUrl: "https://pytorch.org/docs/stable/",
faviconUrl: "https://pytorch.org/favicon.ico",
},
{
title: "Redis",
startUrl: "https://redis.io/docs/",
rootUrl: "https://redis.io/docs/",
faviconUrl: "https://redis.io/favicon.ico",
},
{
title: "Axios",
startUrl: "https://axios-http.com/docs/intro",
rootUrl: "https://axios-http.com/docs",
faviconUrl: "https://axios-http.com/favicon.ico",
},
{
title: "Redwood JS",
startUrl: "https://redwoodjs.com/docs/introduction",
rootUrl: "https://redwoodjs.com/docs",
faviconUrl: "https://redwoodjs.com/favicon.ico",
},
{
title: "GraphQL",
startUrl: "https://graphql.org/learn/",
rootUrl: "https://graphql.org/learn/",
faviconUrl: "https://graphql.org/favicon.ico",
},
{
title: "Typescript",
startUrl: "https://www.typescriptlang.org/docs/",
rootUrl: "https://www.typescriptlang.org/docs/",
faviconUrl: "https://www.typescriptlang.org/favicon.ico",
},
{
title: "Jest",
startUrl: "https://jestjs.io/docs/getting-started",
rootUrl: "https://jestjs.io/docs",
faviconUrl: "https://jestjs.io/favicon.ico",
},
{
title: "Tailwind CSS",
startUrl: "https://tailwindcss.com/docs/installation",
rootUrl: "https://tailwindcss.com/docs",
faviconUrl: "https://tailwindcss.com/favicon.ico",
},
{
title: "Vue.js",
startUrl: "https://vuejs.org/guide/introduction.html",
rootUrl: "https://vuejs.org",
faviconUrl: "https://vuejs.org/favicon.ico",
},
{
title: "Svelte",
startUrl: "https://svelte.dev/docs/introduction",
rootUrl: "https://svelte.dev/docs",
faviconUrl: "https://svelte.dev/favicon.ico",
},
{
title: "GitHub Actions",
startUrl: "https://docs.github.com/en/actions",
rootUrl: "https://docs.github.com/en/actions",
faviconUrl: "https://docs.github.com/favicon.ico",
},
{
title: "NodeJS",
startUrl: "https://nodejs.org/docs/latest/api/",
rootUrl: "https://nodejs.org/docs/latest/api/",
faviconUrl: "https://nodejs.org/favicon.ico",
},
{
title: "Socket.io",
startUrl: "https://socket.io/docs/v4/",
rootUrl: "https://socket.io/docs/v4/",
faviconUrl: "https://socket.io/favicon.ico",
},
{
title: "Gradle",
startUrl: "https://docs.gradle.org/current/userguide/userguide.html",
rootUrl: "https://docs.gradle.org/current",
faviconUrl: "https://docs.gradle.org/favicon.ico",
},
{
title: "Redux Toolkit",
startUrl: "https://redux-toolkit.js.org/introduction/getting-started",
rootUrl: "https://redux-toolkit.js.org",
faviconUrl: "https://redux-toolkit.js.org/favicon.ico",
},
{
title: "Chroma",
startUrl: "https://docs.trychroma.com/",
rootUrl: "https://docs.trychroma.com/",
faviconUrl: "https://docs.trychroma.com/favicon.ico",
},
{
title: "SQLite",
startUrl: "https://www.sqlite.org/docs.html",
rootUrl: "https://www.sqlite.org",
faviconUrl: "https://www.sqlite.org/favicon.ico",
},
{
title: "Redux",
startUrl: "https://redux.js.org/introduction/getting-started",
rootUrl: "https://redux.js.org",
faviconUrl: "https://redux.js.org/favicon.ico",
},
{
title: "Prettier",
startUrl: "https://prettier.io/docs/en/",
rootUrl: "https://prettier.io/docs/en/",
faviconUrl: "https://prettier.io/favicon.ico",
},
{
title: "VS Code Extension API",
startUrl: "https://code.visualstudio.com/api",
rootUrl: "https://code.visualstudio.com/api",
faviconUrl: "https://code.visualstudio.com/favicon.ico",
},
{
title: "Continue",
startUrl: "https://docs.continue.dev/intro",
rootUrl: "https://docs.continue.dev",
faviconUrl: "https://docs.continue.dev/favicon.ico",
},
{
title: "jQuery",
startUrl: "https://api.jquery.com/",
rootUrl: "https://api.jquery.com/",
faviconUrl: "https://api.jquery.com/favicon.ico",
},
{
title: "Python",
startUrl: "https://docs.python.org/3/",
rootUrl: "https://docs.python.org/3/",
faviconUrl: "https://docs.python.org/favicon.ico",
},
{
title: "Rust",
startUrl: "https://doc.rust-lang.org/book/",
rootUrl: "https://doc.rust-lang.org/book/",
faviconUrl: "https://doc.rust-lang.org/favicon.ico",
},
{
title: "IntelliJ Platform SDK",
startUrl: "https://plugins.jetbrains.com/docs/intellij/welcome.html",
rootUrl: "https://plugins.jetbrains.com/docs/intellij",
faviconUrl: "https://plugins.jetbrains.com/favicon.ico",
},
{
title: "Docker",
startUrl: "https://docs.docker.com/",
rootUrl: "https://docs.docker.com/",
faviconUrl: "https://docs.docker.com/favicon.ico",
},
{
title: "NPM",
startUrl: "https://docs.npmjs.com/",
rootUrl: "https://docs.npmjs.com/",
faviconUrl: "https://docs.npmjs.com/favicon.ico",
},
{
title: "TipTap",
startUrl: "https://tiptap.dev/docs/editor/introduction",
rootUrl: "https://tiptap.dev/docs",
faviconUrl: "https://tiptap.dev/favicon.ico",
},
{
title: "esbuild",
startUrl: "https://esbuild.github.io/",
rootUrl: "https://esbuild.github.io/",
faviconUrl: "https://esbuild.github.io/favicon.ico",
},
{
title: "Tree Sitter",
startUrl: "https://tree-sitter.github.io/tree-sitter/",
rootUrl: "https://tree-sitter.github.io/tree-sitter/",
faviconUrl: "https://tree-sitter.github.io/favicon.ico",
},
{
title: "Netlify",
startUrl: "https://docs.netlify.com/",
rootUrl: "https://docs.netlify.com/",
faviconUrl: "https://docs.netlify.com/favicon.ico",
},
{
title: "Replicate",
startUrl: "https://replicate.com/docs",
rootUrl: "https://replicate.com/docs",
faviconUrl: "https://replicate.com/favicon.ico",
},
{
title: "HTML",
startUrl: "https://www.w3schools.com/html/default.asp",
rootUrl: "https://www.w3schools.com/html",
faviconUrl: "https://www.w3schools.com/favicon.ico",
},
{
title: "CSS",
startUrl: "https://www.w3schools.com/css/default.asp",
rootUrl: "https://www.w3schools.com/css",
faviconUrl: "https://www.w3schools.com/favicon.ico",
},
{
title: "Langchain",
startUrl: "https://python.langchain.com/docs/get_started/introduction",
rootUrl: "https://python.langchain.com/docs",
faviconUrl: "https://python.langchain.com/favicon.ico",
},
{
title: "WooCommerce",
startUrl: "https://developer.woocommerce.com/docs/",
rootUrl: "https://developer.woocommerce.com/docs/",
faviconUrl: "https://developer.woocommerce.com/favicon.ico",
},
{
title: "WordPress",
startUrl: "https://developer.wordpress.org/reference/",
rootUrl: "https://developer.wordpress.org/reference/",
faviconUrl: "https://developer.wordpress.org/favicon.ico",
},
{
title: "PySide6",
startUrl: "https://doc.qt.io/qtforpython-6/quickstart.html",
rootUrl: "https://doc.qt.io/qtforpython-6/api.html",
faviconUrl: "https://doc.qt.io/favicon.ico",
},
{
title: "Bootstrap",
startUrl: "https://getbootstrap.com/docs/5.3/getting-started/introduction/",
rootUrl: "https://getbootstrap.com/docs/5.3/",
faviconUrl: "https://getbootstrap.com/favicon.ico",
},
{
title: "Alpine.js",
startUrl: "https://alpinejs.dev/start-here",
rootUrl: "https://alpinejs.dev/",
faviconUrl: "https://alpinejs.dev/favicon.ico",
},
{
title: "C# Language Reference",
startUrl: "https://learn.microsoft.com/en-us/dotnet/csharp/",
rootUrl: "https://learn.microsoft.com/en-us/dotnet/csharp/",
faviconUrl: "https://learn.microsoft.com/favicon.ico",
},
];

View File

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
interface SafeImg {
src: string;
@ -17,15 +17,40 @@ const SafeImg: React.FC<SafeImg> = ({
}) => {
const [hasError, setHasError] = useState(false);
const [cachedSrc, setCachedSrc] = useState<string | null>(null);
useEffect(() => {
const cachedImage = localStorage.getItem(src);
if (cachedImage) {
console.log("Using cached image");
setCachedSrc(cachedImage);
} else {
fetch(src)
.then((response) => response.blob())
.then((blob) => {
const reader = new FileReader();
reader.onloadend = () => {
localStorage.setItem(src, reader.result as string);
setCachedSrc(reader.result as string);
};
reader.readAsDataURL(blob);
})
.catch((error) => {
// console.error("Error fetching image:", error);
});
}
}, [src]);
const handleError = () => {
setHasError(true);
setCachedSrc(null);
};
return (
<>
{!hasError ? (
<img
src={src}
src={cachedSrc || src}
height={height}
width={width}
className={className}

View File

@ -87,32 +87,35 @@ function DropdownIcon(props: { className?: string; item: ComboBoxItem }) {
: props.item.type;
const iconClass = `${props.className} flex-shrink-0`;
if (false && provider === "docs" && props.item.id !== "docs") {
let fallbackIcon;
const Icon = ICONS_FOR_DROPDOWN[provider];
if (!Icon) {
fallbackIcon =
props.item.type === "contextProvider" ? (
<AtSymbolIcon className={iconClass} height="1.2em" width="1.2em" />
) : (
<CubeIcon className={iconClass} height="1.2em" width="1.2em" />
);
} else {
fallbackIcon = <Icon className={iconClass} height="1.2em" width="1.2em" />;
}
if (false && props.item.iconUrl) {
try {
const faviconUrl = new URL("/favicon.ico", props.item.id);
return (
<SafeImg
className="flex-shrink-0 pr-2"
src={faviconUrl.toString()}
src={props.item.iconUrl}
height="18em"
width="18em"
fallback={
<BookOpenIcon className={iconClass} height="1.2em" width="1.2em" />
}
fallback={fallbackIcon}
/>
);
} catch (e) {}
}
const Icon = ICONS_FOR_DROPDOWN[provider];
if (!Icon) {
return props.item.type === "contextProvider" ? (
<AtSymbolIcon className={iconClass} height="1.2em" width="1.2em" />
) : (
<CubeIcon className={iconClass} height="1.2em" width="1.2em" />
);
}
return <Icon className={iconClass} height="1.2em" width="1.2em" />;
return fallbackIcon;
}
const ItemsDiv = styled.div`

View File

@ -17,5 +17,6 @@ export interface ComboBoxItem {
contextProvider?: ContextProviderDescription;
query?: string;
label?: string;
iconUrl?: string;
action?: () => void;
}

View File

@ -47,7 +47,8 @@ function LinkableCode(props: any) {
// Check if this is a real file
const contextItemFileMatch = contextItems.find(
(item) =>
item.id.providerTitle === "file" && item.description.endsWith(content),
["file", "codebase", "folder"].includes(item.id.providerTitle) &&
item.description.split(" (")[0].endsWith(content),
);
if (contextItemFileMatch) {
setIsLink(true);
@ -68,7 +69,8 @@ function LinkableCode(props: any) {
if (content.length > 6) {
const contextItemContentMatch = contextItems.find(
(item) =>
item.id.providerTitle === "file" && item.content.includes(content),
["file", "codebase", "folder"].includes(item.id.providerTitle) &&
item.content.includes(content),
);
if (contextItemContentMatch) {
setIsLink(true);