import seriesDataPt from "@/public/series.json"; import frameworksDataPt from "@/public/frameworks.json"; import { categoriasGlossario as glossarioPt } from "@/lib/glossarioData"; import { errosCatalogo as errosPt } from "@/lib/diagnosticoData"; import { COMPONENTES_REGISTRY as componentesPt } from "@/lib/componentRegistryData"; import { montarConhecimento as montarConhecimentoPt } from "@/lib/searchTopics"; import seriesDataEn from "@/data/en/series.json"; import frameworksDataEn from "@/data/en/frameworks.json"; import { categoriasGlossario as glossarioEn } from "@/lib/data/en/glossario"; import { errosCatalogo as errosEn } from "@/lib/data/en/diagnostico"; import { COMPONENTES_REGISTRY as componentesEn } from "@/lib/data/en/componentes"; import { montarConhecimento as montarConhecimentoEn } from "@/lib/data/en/topicos"; import seriesDataEs from "@/data/es/series.json"; import frameworksDataEs from "@/data/es/frameworks.json"; import { categoriasGlossario as glossarioEs } from "@/lib/data/es/glossario"; import { errosCatalogo as errosEs } from "@/lib/data/es/diagnostico"; import { COMPONENTES_REGISTRY as componentesEs } from "@/lib/data/es/componentes"; import { montarConhecimento as montarConhecimentoEs } from "@/lib/data/es/topicos"; import { readFileSync, existsSync } from "node:fs"; import path from "node:path"; /** * Índice de busca do site, montado no servidor a partir dos mesmos dados que * alimentam as páginas. Uma série, termo ou erro novo entra sozinho na busca. * * Cada entrada: { id, tipo, titulo, descricao, href, keywords } * `keywords` guarda texto extra pesquisável (não exibido). */ const PAGINAS_PT = [ { titulo: "Início", descricao: "Página inicial do ESPDocs", href: "/", keywords: "home inicio" }, { titulo: "Todas as Séries", descricao: "Pinouts, especificações e restrições de cada série ESP32", href: "/series", keywords: "chips pinout especificações" }, { titulo: "Comparador de Séries", descricao: "Compare até 4 modelos lado a lado", href: "/comparacao", keywords: "comparar comparação versus" }, { titulo: "Catálogo de Placas", descricao: "Placas de desenvolvimento, conectores e compras", href: "/catalogo", keywords: "placas dev boards comprar devkit" }, { titulo: "Seletor Inteligente", descricao: "Descubra o chip ideal para o seu projeto", href: "/seletor", keywords: "quiz escolher recomendar" }, { titulo: "Diagnóstico de Erros", descricao: "Solucione brownout, bootloop, WDT e falhas", href: "/diagnostico", keywords: "erro problema bug falha" }, { titulo: "Frameworks & SDKs", descricao: "ESP-IDF, Arduino, Rust, RainMaker e mais", href: "/frameworks", keywords: "sdk" }, { titulo: "Component Registry", descricao: "Catálogo de drivers e gerador de idf_component.yml", href: "/componentes", keywords: "bibliotecas drivers yml" }, { titulo: "Glossário Técnico", descricao: "Conceitos essenciais de hardware e software", href: "/glossario", keywords: "termos dicionário significado" }, { titulo: "O Livro", descricao: "Microcontroladores ESP32: conectividade, eficiência e desempenho", href: "/livro", keywords: "livro book capa comprar" }, { titulo: "Sobre o Projeto", descricao: "História, autor e Ciência Embarcada", href: "/sobre", keywords: "autor contato" }, ]; const PAGINAS_EN = [ { titulo: "Home", descricao: "ESPDocs homepage", href: "/en", keywords: "home" }, { titulo: "All Series", descricao: "Pinouts, specifications and restrictions for each ESP32 series", href: "/en/series", keywords: "chips pinout specifications" }, { titulo: "Series Comparator", descricao: "Compare up to 4 models side by side", href: "/en/compare", keywords: "compare comparison versus" }, { titulo: "Board Catalog", descricao: "Development boards, pinouts and purchasing", href: "/en/catalog", keywords: "boards dev boards devkit buy" }, { titulo: "Smart Selector", descricao: "Find the ideal chip for your project", href: "/en/selector", keywords: "quiz choose recommend selector" }, { titulo: "Error Diagnostics", descricao: "Troubleshoot brownout, bootloop, WDT and crashes", href: "/en/diagnostics", keywords: "error problem bug crash issue" }, { titulo: "Frameworks & SDKs", descricao: "ESP-IDF, Arduino, Rust, RainMaker and more", href: "/en/frameworks", keywords: "sdk" }, { titulo: "Component Registry", descricao: "Driver catalog and idf_component.yml generator", href: "/en/components", keywords: "libraries drivers yml components" }, { titulo: "Technical Glossary", descricao: "Essential hardware and software concepts", href: "/en/glossary", keywords: "terms dictionary definition meaning" }, { titulo: "About the Project", descricao: "History, author and open source", href: "/en/about", keywords: "author contact" }, ]; const PAGINAS_ES = [ { titulo: "Inicio", descricao: "Página de inicio de ESPDocs", href: "/es", keywords: "home inicio" }, { titulo: "Todas las Series", descricao: "Distribución de pines, especificaciones y restricciones de cada serie ESP32", href: "/es/series", keywords: "chips distribución de pines especificaciones" }, { titulo: "Comparador de Series", descricao: "Compare hasta 4 modelos lado a lado", href: "/es/comparacion", keywords: "comparar comparación versus" }, { titulo: "Catálogo de Placas", descricao: "Placas de desarrollo, conectores y compras", href: "/es/catalogo", keywords: "placas dev boards comprar devkit" }, { titulo: "Selector Inteligente", descricao: "Descubra el chip ideal para su proyecto", href: "/es/selector", keywords: "quiz elegir recomendar selector" }, { titulo: "Diagnóstico de Errores", descricao: "Solucione brownout, bucles de arranque, WDT y fallos", href: "/es/diagnostico", keywords: "error problema fallo crash" }, { titulo: "Frameworks y SDKs", descricao: "ESP-IDF, Arduino, Rust, RainMaker y más", href: "/es/frameworks", keywords: "sdk" }, { titulo: "Component Registry", descricao: "Catálogo de controladores y generador de idf_component.yml", href: "/es/componentes", keywords: "bibliotecas controladores drivers yml" }, { titulo: "Glosario Técnico", descricao: "Conceptos esenciales de hardware y software", href: "/es/glosario", keywords: "términos diccionario significado" }, { titulo: "Acerca del Proyecto", descricao: "Historia, autor y código abierto", href: "/es/acerca", keywords: "autor contacto código abierto" }, ]; const cortar = (texto = "", max = 140) => (texto.length > max ? `${texto.slice(0, max - 1).trimEnd()}…` : texto); export function construirIndiceBusca(locale = "pt") { const isEn = locale === "en"; const isEs = locale === "es"; let paginas = PAGINAS_PT; let seriesData = seriesDataPt; let frameworksData = frameworksDataPt; let categoriasGlossario = glossarioPt; let errosCatalogo = errosPt; let componentes = componentesPt; let montarConhecimento = montarConhecimentoPt; if (isEn) { paginas = PAGINAS_EN; seriesData = seriesDataEn; frameworksData = frameworksDataEn; categoriasGlossario = glossarioEn; errosCatalogo = errosEn; componentes = componentesEn; montarConhecimento = montarConhecimentoEn; } else if (isEs) { paginas = PAGINAS_ES; seriesData = seriesDataEs; frameworksData = frameworksDataEs; categoriasGlossario = glossarioEs; errosCatalogo = errosEs; componentes = componentesEs; montarConhecimento = montarConhecimentoEs; } const prefixo = isEn ? "/en" : isEs ? "/es" : ""; const slugSeries = `${prefixo}/series`; const slugFrameworks = `${prefixo}/frameworks`; const slugGlossario = isEn ? "/en/glossary" : isEs ? "/es/glosario" : "/glossario"; const slugDiagnostico = isEn ? "/en/diagnostics" : isEs ? "/es/diagnostico" : "/diagnostico"; const slugComponentes = isEn ? "/en/components" : isEs ? "/es/componentes" : "/componentes"; const itens = []; for (const p of paginas) { itens.push({ tipo: "pagina", ...p, keywords: p.keywords }); } for (const [chave, s] of Object.entries(seriesData)) { itens.push({ tipo: "serie", titulo: chave, descricao: cortar(`${s.nome_completo ?? ""} — ${s.descricao ?? ""}`), href: `${slugSeries}/${chave}`, keywords: [s.arquitetura, s.wifi, s.bluetooth, s.frequencia, s.nucleos].filter(Boolean).join(" "), }); } for (const [chave, f] of Object.entries(frameworksData)) { itens.push({ tipo: "framework", titulo: f.nome ?? chave, descricao: cortar(`${f.nome_completo ?? ""} — ${f.descricao ?? ""}`), href: `${slugFrameworks}/${encodeURIComponent(chave)}`, keywords: [f.linguagem, f.tipo, f.funcao_principal].filter(Boolean).join(" "), }); } for (const cat of categoriasGlossario) { for (const t of cat.termos) { const slug = t.termo.toLowerCase().replace(/[\s()/²]+/g, "-"); itens.push({ tipo: "glossario", titulo: t.termo, descricao: cortar(t.definicao), href: `${slugGlossario}#${slug}`, keywords: [cat.nome, t.exemplo].filter(Boolean).join(" "), }); } } for (const e of errosCatalogo) { itens.push({ tipo: "erro", titulo: e.titulo, descricao: cortar(e.resumo), href: `${slugDiagnostico}#${e.id}`, keywords: [e.logSerial, ...(e.sintomas ?? [])].filter(Boolean).join(" "), }); } for (const c of componentes) { itens.push({ tipo: "componente", titulo: c.titulo, descricao: cortar(c.descricao), href: slugComponentes, keywords: [c.name, c.namespace, ...(c.tags ?? [])].filter(Boolean).join(" "), }); } const conexoes = {}; for (const chave of Object.keys(seriesData)) { const pastaConexoes = isEn ? path.join(process.cwd(), "data", "en", "conexoes") : isEs ? path.join(process.cwd(), "data", "es", "conexoes") : path.join(process.cwd(), "public", "conexoes"); const arquivo = path.join(pastaConexoes, `${chave}.json`); if (existsSync(arquivo)) { conexoes[chave] = JSON.parse(readFileSync(arquivo, "utf8")); } else { const fallback = path.join(process.cwd(), "public", "conexoes", `${chave}.json`); if (existsSync(fallback)) conexoes[chave] = JSON.parse(readFileSync(fallback, "utf8")); } } return { itens: itens.map((item, i) => ({ id: i, ...item })), series: montarConhecimento(seriesData, conexoes), }; }