CI / Lint e auditorias (push) Successful in 1m10s
CI / Trivy (dependências e segredos) (push) Successful in 12s
CI / Imagem Docker (linux/arm64) (push) Successful in 2m39s
Release / Plano (reaproveitar a imagem?) (push) Successful in 6s
Release / ci (push) Skipped
Release / Publica a imagem (linux/arm64) (push) Successful in 18s
Release / Cria a release no Gitea (push) Successful in 5s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
294 lines
18 KiB
JavaScript
294 lines
18 KiB
JavaScript
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 seriesDataFr from "@/data/fr/series.json";
|
|
import frameworksDataFr from "@/data/fr/frameworks.json";
|
|
import { categoriasGlossario as glossarioFr } from "@/lib/data/fr/glossario";
|
|
import { errosCatalogo as errosFr } from "@/lib/data/fr/diagnostico";
|
|
import { COMPONENTES_REGISTRY as componentesFr } from "@/lib/data/fr/componentes";
|
|
import { montarConhecimento as montarConhecimentoFr } from "@/lib/data/fr/topicos";
|
|
|
|
import seriesDataDe from "@/data/de/series.json";
|
|
import frameworksDataDe from "@/data/de/frameworks.json";
|
|
import { categoriasGlossario as glossarioDe } from "@/lib/data/de/glossario";
|
|
import { errosCatalogo as errosDe } from "@/lib/data/de/diagnostico";
|
|
import { COMPONENTES_REGISTRY as componentesDe } from "@/lib/data/de/componentes";
|
|
import { montarConhecimento as montarConhecimentoDe } from "@/lib/data/de/topicos";
|
|
|
|
import seriesDataZh from "@/data/zh-CN/series.json";
|
|
import frameworksDataZh from "@/data/zh-CN/frameworks.json";
|
|
import { categoriasGlossario as glossarioZh } from "@/lib/data/zh-CN/glossario";
|
|
import { errosCatalogo as errosZh } from "@/lib/data/zh-CN/diagnostico";
|
|
import { COMPONENTES_REGISTRY as componentesZh } from "@/lib/data/zh-CN/componentes";
|
|
import { montarConhecimento as montarConhecimentoZh } from "@/lib/data/zh-CN/topicos";
|
|
|
|
// Nomes, rótulos e sinônimos dos assuntos no idioma da página (o motor só traz os em português).
|
|
import { TOPICOS as TOPICOS_EN } from "@/lib/data/en/topicos";
|
|
import { TOPICOS as TOPICOS_ES } from "@/lib/data/es/topicos";
|
|
import { TOPICOS as TOPICOS_FR } from "@/lib/data/fr/topicos";
|
|
import { TOPICOS as TOPICOS_DE } from "@/lib/data/de/topicos";
|
|
import { TOPICOS as TOPICOS_ZH } from "@/lib/data/zh-CN/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 e 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 PAGINAS_FR = [
|
|
{ titulo: "Accueil", descricao: "Page d'accueil d'ESPDocs", href: "/fr", keywords: "accueil home" },
|
|
{ titulo: "Toutes les Séries", descricao: "Brochages, spécifications et restrictions pour chaque série ESP32", href: "/fr/series", keywords: "puces brochage specifications pinout" },
|
|
{ titulo: "Comparateur de Séries", descricao: "Comparez jusqu'à 4 modèles côte à côte", href: "/fr/comparaison", keywords: "comparer comparaison versus" },
|
|
{ titulo: "Catalogue de Cartes", descricao: "Cartes de développement, brochages et achat", href: "/fr/catalogue", keywords: "cartes dev boards devkit acheter" },
|
|
{ titulo: "Sélecteur Intelligent", descricao: "Trouvez la puce idéale pour votre projet", href: "/fr/selecteur", keywords: "quiz choisir recommander selecteur" },
|
|
{ titulo: "Diagnostic d'Erreurs", descricao: "Résolvez brownout, boucles de démarrage, WDT et crashs", href: "/fr/diagnostic", keywords: "erreur probleme panne crash bug" },
|
|
{ titulo: "Frameworks et SDKs", descricao: "ESP-IDF, Arduino, Rust, RainMaker et plus", href: "/fr/frameworks", keywords: "sdk" },
|
|
{ titulo: "Component Registry", descricao: "Catalogue de pilotes et générateur idf_component.yml", href: "/fr/composants", keywords: "bibliotheques pilotes drivers yml composants" },
|
|
{ titulo: "Glossaire Technique", descricao: "Concepts essentiels de matériel et de logiciel", href: "/fr/glossaire", keywords: "termes dictionnaire definition signification" },
|
|
{ titulo: "À Propos du Projet", descricao: "Histoire, auteur et open source", href: "/fr/a-propos", keywords: "auteur contact open source" },
|
|
];
|
|
|
|
const PAGINAS_ZH = [
|
|
{ titulo: "首页", descricao: "ESPDocs 首页", href: "/zh-CN", keywords: "首页 主页 home" },
|
|
{ titulo: "全部系列", descricao: "每个 ESP32 系列的引脚、规格与限制", href: "/zh-CN/series", keywords: "芯片 引脚 规格 pinout" },
|
|
{ titulo: "系列对比", descricao: "最多并排对比 4 个型号", href: "/zh-CN/compare", keywords: "对比 比较 差异" },
|
|
{ titulo: "开发板目录", descricao: "开发板、引脚与购买渠道", href: "/zh-CN/catalog", keywords: "开发板 devkit 购买" },
|
|
{ titulo: "智能选型", descricao: "为你的项目找到合适的芯片", href: "/zh-CN/selector", keywords: "选型 推荐 测验" },
|
|
{ titulo: "故障诊断", descricao: "排查 Brownout、启动循环、看门狗和崩溃", href: "/zh-CN/diagnostics", keywords: "故障 错误 崩溃 问题 bug" },
|
|
{ titulo: "框架与 SDK", descricao: "ESP-IDF、Arduino、Rust、RainMaker 等", href: "/zh-CN/frameworks", keywords: "sdk 开发框架" },
|
|
{ titulo: "Component Registry", descricao: "驱动目录与 idf_component.yml 生成器", href: "/zh-CN/components", keywords: "库 驱动 组件 yml" },
|
|
{ titulo: "技术术语表", descricao: "关键的硬件与软件概念", href: "/zh-CN/glossary", keywords: "术语 词典 定义 含义" },
|
|
{ titulo: "关于本项目", descricao: "历史、作者与开源", href: "/zh-CN/about", keywords: "作者 联系 开源" },
|
|
];
|
|
|
|
const PAGINAS_DE = [
|
|
{ titulo: "Startseite", descricao: "ESPDocs Startseite", href: "/de", keywords: "startseite home" },
|
|
{ titulo: "Alle Serien", descricao: "Pinbelegungen, Spezifikationen und Einschränkungen für jede ESP32-Serie", href: "/de/serien", keywords: "chips pinbelegung spezifikationen pinout" },
|
|
{ titulo: "Serienvergleich", descricao: "Vergleichen Sie bis zu 4 Modelle nebeneinander", href: "/de/vergleich", keywords: "vergleichen vergleich versus" },
|
|
{ titulo: "Board-Katalog", descricao: "Entwicklungsboards, Pinbelegungen und Kauf", href: "/de/katalog", keywords: "boards dev boards devkit kaufen" },
|
|
{ titulo: "Intelligente Auswahl", descricao: "Finden Sie den idealen Chip für Ihr Projekt", href: "/de/auswahl", keywords: "quiz waehlen empfehlen auswahl" },
|
|
{ titulo: "Fehlerdiagnose", descricao: "Beheben Sie Brownout, Bootloops, WDT und Abstürze", href: "/de/diagnose", keywords: "fehler problem absturz crash bug" },
|
|
{ titulo: "Frameworks & SDKs", descricao: "ESP-IDF, Arduino, Rust, RainMaker und mehr", href: "/de/frameworks", keywords: "sdk" },
|
|
{ titulo: "Component Registry", descricao: "Treiberkatalog und idf_component.yml-Generator", href: "/de/komponenten", keywords: "bibliotheken treiber drivers yml komponenten" },
|
|
{ titulo: "Technisches Glossar", descricao: "Wesentliche Hardware- und Softwarekonzepte", href: "/de/glossar", keywords: "begriffe woerterbuch definition bedeutung" },
|
|
{ titulo: "Über das Projekt", descricao: "Geschichte, Autor und Open Source", href: "/de/ueber-uns", keywords: "autor kontakt open source" },
|
|
];
|
|
|
|
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";
|
|
const isFr = locale === "fr";
|
|
const isDe = locale === "de";
|
|
const isZh = locale === "zh-CN";
|
|
|
|
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;
|
|
} else if (isFr) {
|
|
paginas = PAGINAS_FR;
|
|
seriesData = seriesDataFr;
|
|
frameworksData = frameworksDataFr;
|
|
categoriasGlossario = glossarioFr;
|
|
errosCatalogo = errosFr;
|
|
componentes = componentesFr;
|
|
montarConhecimento = montarConhecimentoFr;
|
|
} else if (isDe) {
|
|
paginas = PAGINAS_DE;
|
|
seriesData = seriesDataDe;
|
|
frameworksData = frameworksDataDe;
|
|
categoriasGlossario = glossarioDe;
|
|
errosCatalogo = errosDe;
|
|
componentes = componentesDe;
|
|
montarConhecimento = montarConhecimentoDe;
|
|
} else if (isZh) {
|
|
paginas = PAGINAS_ZH;
|
|
seriesData = seriesDataZh;
|
|
frameworksData = frameworksDataZh;
|
|
categoriasGlossario = glossarioZh;
|
|
errosCatalogo = errosZh;
|
|
componentes = componentesZh;
|
|
montarConhecimento = montarConhecimentoZh;
|
|
}
|
|
|
|
const slugSeries = isZh ? "/zh-CN/series" : isDe ? "/de/serien" : isFr ? "/fr/series" : isEn ? "/en/series" : isEs ? "/es/series" : "/series";
|
|
const slugFrameworks = isZh ? "/zh-CN/frameworks" : isDe ? "/de/frameworks" : isFr ? "/fr/frameworks" : isEn ? "/en/frameworks" : isEs ? "/es/frameworks" : "/frameworks";
|
|
const slugGlossario = isZh ? "/zh-CN/glossary" : isDe ? "/de/glossar" : isFr ? "/fr/glossaire" : isEn ? "/en/glossary" : isEs ? "/es/glosario" : "/glossario";
|
|
const slugDiagnostico = isZh ? "/zh-CN/diagnostics" : isDe ? "/de/diagnose" : isFr ? "/fr/diagnostic" : isEn ? "/en/diagnostics" : isEs ? "/es/diagnostico" : "/diagnostico";
|
|
const slugComponentes = isZh ? "/zh-CN/components" : isDe ? "/de/komponenten" : isFr ? "/fr/composants" : 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")
|
|
: isFr
|
|
? path.join(process.cwd(), "data", "fr", "conexoes")
|
|
: isZh ? path.join(process.cwd(), "data", "zh-CN", "conexoes") : isDe
|
|
? path.join(process.cwd(), "data", "de", "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"));
|
|
}
|
|
}
|
|
|
|
const topicosLoc = { en: TOPICOS_EN, es: TOPICOS_ES, fr: TOPICOS_FR, de: TOPICOS_DE, "zh-CN": TOPICOS_ZH }[locale];
|
|
return {
|
|
locale,
|
|
topicos: topicosLoc
|
|
? Object.fromEntries(topicosLoc.map((tp) => [tp.id, { nome: tp.nome, pinoRotulo: tp.pinoRotulo, termos: tp.termos }]))
|
|
: null,
|
|
itens: itens.map((item, i) => ({ id: i, ...item })),
|
|
series: montarConhecimento(seriesData, conexoes),
|
|
};
|
|
}
|