snapport 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -98
- package/dist/index.d.ts +1 -0
- package/dist/snap-port.js +3 -2
- package/dist/snap-port.umd.cjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,150 +1,126 @@
|
|
|
1
1
|
# Snap-Port 🚀
|
|
2
|
-
O **Snap-Port** é uma biblioteca **
|
|
2
|
+
O **Snap-Port** é uma biblioteca desenvolvida em **TypeScript**, sem dependências externas, projetada para automatizar a exibição de projetos do GitHub em sites pessoais ou portfólios.
|
|
3
3
|
|
|
4
|
-
A proposta é
|
|
5
|
-
|
|
6
|
-
> **Use o GitHub como fonte única de verdade para o seu portfólio.**
|
|
4
|
+
A proposta central é utilizar o GitHub como **fonte única de verdade:** ao marcar seus repositórios com a tag escolhida, a biblioteca se encarrega de buscar, tratar, aplicar cache e renderizar os dados, eliminando a manutenção manual no código do seu site.
|
|
7
5
|
|
|
8
6
|
---
|
|
9
7
|
|
|
10
|
-
## 🛠
|
|
11
|
-
|
|
12
|
-
A biblioteca foi desenhada para ser modular, funcionando tanto como um **motor de dados (headless)** quanto como uma **solução visual pronta para uso.**
|
|
8
|
+
## 🛠 Funcionalidades Técnicas
|
|
13
9
|
|
|
14
|
-
### 1.
|
|
10
|
+
### 1. Seleção de Projetos e Controle de Stacks
|
|
11
|
+
O Snap-Port oferece controle total sobre o que é exibido e como as tecnologias são categorizadas:
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
- **Tag de Descoberta**: Por padrão, a biblioteca busca repositórios com a tag ``port``, mas você pode definir qualquer outra tag no momento da inicialização.
|
|
14
|
+
- **Filtros por Stacks (Topics):** Para que os filtros automáticos e a barra de busca funcionem corretamente, você deve listar as tecnologias (ex: ``react``, ``nodejs``, ``css``) nos topics do seu repositório no GitHub.
|
|
15
|
+
- **Por que não usar a "Language" automática?** A lib ignora o campo ``language`` do GitHub para permitir que você decida quais ferramentas quer destacar. Isso evita que um projeto de React seja classificado apenas como "HTML" ou "JavaScript" devido ao volume de arquivos gerados por ferramentas de build, garantindo que o filtro reflita a stack real do projeto.
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
### 2. Gestão Inteligente de Imagens
|
|
18
|
+
Como a API do GitHub não retorna links diretos de imagens de preview, o Snap-Port utiliza uma lógica de **geração automática** integrada aos componentes de UI.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
- Descrição
|
|
22
|
-
- Tópicos
|
|
23
|
-
- Link do repositório
|
|
24
|
-
- Link de deploy
|
|
25
|
-
- Linguagem principal
|
|
20
|
+
Para que cada projeto tenha sua própria imagem, siga estas regras:
|
|
26
21
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
import { getPortProjects } from 'snap-port';
|
|
22
|
+
- **Arquivo de Preview:** Você deve criar um arquivo chamado ``preview.png`` na raiz do seu repositório.
|
|
23
|
+
- **Importante:** O nome deve ser exatamente preview.png (letras minúsculas), pois o GitHub diferencia maiúsculas de minúsculas (*case-sensitive*).
|
|
30
24
|
|
|
31
|
-
|
|
32
|
-
```
|
|
25
|
+
Caso o arquivo não exista ou ocorra algum erro de carregamento (como *Rate Limits*), a lib executa uma **estratégia de fallback em cascata:**
|
|
33
26
|
|
|
34
|
-
|
|
27
|
+
- **GitHub Open Graph:** Tenta carregar o card dinâmico gerado pelo próprio GitHub.
|
|
28
|
+
- **Placeholder de Segurança:** Se o GitHub bloquear a requisição, gera um card neutro contendo o nome do projeto via placehold.co.
|
|
35
29
|
|
|
36
|
-
###
|
|
30
|
+
### 3. Componentes de UI Integrados
|
|
37
31
|
|
|
38
|
-
|
|
32
|
+
- **Search Bar:** Filtro textual em tempo real (nome, descrição e tópicos).
|
|
33
|
+
- **Filter** Carousel: Carrossel dinâmico baseado nos tópicos definidos nos repositórios.
|
|
34
|
+
- **Project Cards (Layout 16:9):** Cards responsivos com badges de tecnologia e botões de ação (Código e Deploy).
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
Filtro textual instantâneo que atua sobre os dados em cache.
|
|
36
|
+
---
|
|
42
37
|
|
|
43
|
-
|
|
44
|
-
Carrossel horizontal de tecnologias que identifica automaticamente suas stacks a partir dos tópicos do GitHub.
|
|
38
|
+
## 💡 Dicas para um melhor Resultado
|
|
45
39
|
|
|
46
|
-
- **
|
|
47
|
-
|
|
48
|
-
- Social Preview (imagem do repositório)
|
|
49
|
-
- Descrição com limite de linhas
|
|
50
|
-
- Botões de ação para código-fonte e deploy
|
|
40
|
+
- **Proporção de Imagem:** Para que as imagens não fiquem com partes cortadas nos cards, salve seus arquivos ``preview.png`` na proporção **16:9** (ex: 1280x720px).
|
|
41
|
+
- **Link de Acesso (Deploy):** O botão "Acessar" só aparecerá se o campo **"Homepage"** estiver preenchido nas configurações do seu repositório no GitHub.
|
|
51
42
|
|
|
52
43
|
---
|
|
53
44
|
|
|
54
|
-
##
|
|
45
|
+
## 📦 Instalação e Integração
|
|
55
46
|
|
|
56
47
|
### Via NPM
|
|
57
48
|
|
|
58
49
|
```bash
|
|
59
|
-
npm install
|
|
50
|
+
npm install snapport
|
|
60
51
|
```
|
|
61
52
|
|
|
62
53
|
### Via CDN (Direto no HTML)
|
|
63
|
-
Se preferir não usar gerenciadores de pacotes, você pode importar os arquivos de distribuição diretamente:
|
|
64
54
|
|
|
65
|
-
```
|
|
66
|
-
<!-- Estilos da
|
|
67
|
-
<link rel="stylesheet" href="https://
|
|
55
|
+
```html
|
|
56
|
+
<!-- 1. Estilos da Biblioteca -->
|
|
57
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net">
|
|
68
58
|
|
|
69
|
-
<!-- Lógica
|
|
59
|
+
<!-- 2. Lógica e Inicialização -->
|
|
70
60
|
<script type="module">
|
|
71
|
-
import { initPortfolio } from 'https://
|
|
61
|
+
import { initPortfolio } from 'https://cdn.jsdelivr.net';
|
|
72
62
|
|
|
73
63
|
initPortfolio('seu-usuario', {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
64
|
+
tag: 'port', // Opcional: padrão é 'port'
|
|
65
|
+
searchContainer: 'id-search', // ID do container da busca
|
|
66
|
+
filtersContainer: 'id-filters', // ID do container dos filtros
|
|
67
|
+
projectsContainer: 'id-projects' // ID do container do grid
|
|
77
68
|
});
|
|
78
69
|
</script>
|
|
79
70
|
```
|
|
80
71
|
|
|
81
|
-
## ⚙️ Customização e Comportamento
|
|
82
|
-
|
|
83
|
-
### Gerenciamento de Tags e Imagens
|
|
84
|
-
|
|
85
|
-
A biblioteca utiliza os **topics** do seu repositório para duas funções:
|
|
86
|
-
|
|
87
|
-
- **Filtro de Descoberta**
|
|
88
|
-
Apenas repositórios com a tag **`port`** são processados.
|
|
89
|
-
|
|
90
|
-
- **Identidade Visual**
|
|
91
|
-
Tags como `react`, `nodejs` ou `typescript` são mapeadas para seus respectivos ícones e cores oficiais.
|
|
92
|
-
|
|
93
|
-
- **Imagens**
|
|
94
|
-
O Snap-Port consome o **Open Graph** do repositório para exibir automaticamente a imagem de preview do projeto.
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
### Cache, Performance e Rate Limit
|
|
99
|
-
|
|
100
|
-
Para evitar chamadas excessivas à API do GitHub e reduzir impactos de **rate limit**, o Snap-Port implementa um **sistema de cache inteligente baseado em ``localStorage``**.
|
|
101
|
-
|
|
102
|
-
Esse sistema:
|
|
103
|
-
|
|
104
|
-
- Armazena os dados tratados por usuário de forma isolada, evitando conflitos quando múltiplos portfólios utilizam a biblioteca no mesmo ambiente (ex: recrutadores abrindo vários ports).
|
|
105
|
-
|
|
106
|
-
- Possui ciclo de expiração automática, garantindo que os dados sejam atualizados periodicamente (entre 1 e 2 horas).
|
|
107
|
-
|
|
108
|
-
- Realiza limpeza automática de entradas antigas, funcionando como um garbage collector manual, evitando crescimento indefinido do localStorage.
|
|
109
|
-
|
|
110
|
-
- Trata casos de borda para impedir reutilização indevida de cache entre usuários diferentes.
|
|
111
|
-
|
|
112
|
-
Na prática, isso garante:
|
|
113
|
-
|
|
114
|
-
- Melhor performance,
|
|
115
|
-
|
|
116
|
-
- Menos requisições,
|
|
117
|
-
|
|
118
|
-
- E maior previsibilidade no consumo da API do GitHub.
|
|
119
|
-
|
|
120
72
|
---
|
|
121
73
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
A interface é construída com **variáveis CSS**, permitindo que você adapte as cores ao seu tema sem modificar o código interno:
|
|
74
|
+
## 🎨 Personalização Visual (CSS Variables)
|
|
75
|
+
Se você utiliza o layout padrão da biblioteca, pode adaptar as cores e o estilo ao seu tema sem modificar o código interno. O Snap-Port utiliza **Variáveis CSS** que podem ser facilmente sobrescritas no seu arquivo global:
|
|
125
76
|
|
|
126
77
|
```css
|
|
127
78
|
:root {
|
|
128
|
-
--ghp-accent: #333;
|
|
129
|
-
--ghp-bg: #
|
|
130
|
-
--ghp-
|
|
79
|
+
--ghp-accent: #333; /* Cor de destaque (botões e ícones) */
|
|
80
|
+
--ghp-bg: #ffffff; /* Fundo dos cards */
|
|
81
|
+
--ghp-text: #333; /* Título e textos principais */
|
|
82
|
+
--ghp-text-light: #666; /* Descrições e textos secundários */
|
|
83
|
+
--ghp-border: rgba(226, 226, 228, 0.8); /* Bordas */
|
|
84
|
+
--ghp-shadow: rgba(0, 0, 0, 0.1); /* Sombras dos cards */
|
|
131
85
|
}
|
|
132
86
|
```
|
|
133
87
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
Este projeto está em sua fase **MVP (Minimum Viable Product)**.
|
|
88
|
+
---
|
|
137
89
|
|
|
138
|
-
|
|
90
|
+
## ⚙️ Customização e Performance
|
|
91
|
+
|
|
92
|
+
### Injeção de Template Customizado
|
|
93
|
+
Mantenha a inteligência de busca e cache, mas use seu próprio design:
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
initPortfolio('seu-usuario', {
|
|
97
|
+
searchContainer: 'id-search',
|
|
98
|
+
filtersContainer: 'id-filters',
|
|
99
|
+
projectsContainer: 'id-projects',
|
|
100
|
+
customCardTemplate: (repo) => `
|
|
101
|
+
<div class="meu-card-personalizado">
|
|
102
|
+
<h4>${repo.name}</h4>
|
|
103
|
+
<p>${repo.description}</p>
|
|
104
|
+
<a href="${repo.htmlUrl}">Ver código</a>
|
|
105
|
+
</div>
|
|
106
|
+
`
|
|
107
|
+
});
|
|
108
|
+
```
|
|
139
109
|
|
|
140
|
-
|
|
110
|
+
### Cache e Estabilidade
|
|
111
|
+
A biblioteca utiliza localStorage para garantir performance:
|
|
141
112
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
Para detalhes sobre como contribuir, consulte o [**Guia de Contribuição.**](https://github.com/guilhermegodoydev/snap-port/blob/main/CONTRIBUTING.md)
|
|
113
|
+
- **Persistência:** Dados armazenados por até 2 horas.
|
|
114
|
+
- **Isolamento:** Cache separado por usuário do GitHub.
|
|
145
115
|
|
|
146
116
|
---
|
|
147
117
|
|
|
148
|
-
|
|
118
|
+
⚠️ Status do Projeto
|
|
119
|
+
Este projeto está em fase **v0.1.0 (MVP).** Ele foi desenvolvido para resolver uma necessidade real de automação de portfólios e continuará recebendo melhorias conforme o uso.
|
|
149
120
|
|
|
121
|
+
> **Nota sobre Manutenção:**
|
|
122
|
+
> Este é um projeto de código aberto mantido de forma independente. Sinta-se à vontade para contribuir! Se encontrar um bug ou tiver uma ideia de funcionalidade, abrir uma **Issue** ou um **Pull Request** é a melhor forma de ajudar o projeto a crescer.
|
|
123
|
+
>
|
|
124
|
+
> Para entender como colaborar com o código, consulte o nosso [**Guia de Contribuição**](./CONTRIBUTING.md).
|
|
150
125
|
|
|
126
|
+
**Autor**: Guilherme Godoy (@guilhermegodoydev) • **Licença**: MIT • **Peso**: ~3.12kB (Gzipped)
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export declare function getPortProjects(username: string, tag?: string): Promise
|
|
|
3
3
|
export declare function initPortfolio(username: string, config?: PortfolioConfig): Promise<PortfolioResponse>;
|
|
4
4
|
|
|
5
5
|
export declare interface PortfolioConfig {
|
|
6
|
+
tag?: string;
|
|
6
7
|
searchContainer: string;
|
|
7
8
|
filtersContainer: string;
|
|
8
9
|
projectsContainer: string;
|
package/dist/snap-port.js
CHANGED
|
@@ -172,9 +172,10 @@ async function S(t, e = {
|
|
|
172
172
|
projectsContainer: "projects-cont"
|
|
173
173
|
}) {
|
|
174
174
|
try {
|
|
175
|
+
const o = e.tag || "port";
|
|
175
176
|
$(e.searchContainer), C(e.projectsContainer, 6);
|
|
176
|
-
const
|
|
177
|
-
return w(
|
|
177
|
+
const r = await y(t, o);
|
|
178
|
+
return w(r, e.filtersContainer), m(r, e.projectsContainer, t, e.customCardTemplate), b(e.filtersContainer, r, e.projectsContainer, t, e.customCardTemplate), E(r, e.projectsContainer, t, e.customCardTemplate), { projects: r, status: "success" };
|
|
178
179
|
} catch (o) {
|
|
179
180
|
console.error("Erro ao inicializar portfólio:", o);
|
|
180
181
|
const r = document.getElementById(e.projectsContainer);
|
package/dist/snap-port.umd.cjs
CHANGED
|
@@ -40,4 +40,4 @@
|
|
|
40
40
|
</svg>
|
|
41
41
|
<input type="text" id="gh-port-search" class="ghp-search-input" placeholder="Buscar projeto..." autocomplete="off">
|
|
42
42
|
</div>
|
|
43
|
-
`)}function E(e,t,o,r,n){const c=document.getElementById(e);c&&c.addEventListener("click",i=>{const l=i.target.closest(".ghp-filter-btn");if(!l)return;const p=l.dataset.topic,d=p==="all"?t:t.filter(g=>g.topics.includes(p));u(d,o,r,n),c.querySelectorAll(".ghp-filter-btn").forEach(g=>g.classList.remove("active")),l.classList.add("active")})}function B(e,t,o,r){const n=document.getElementById("gh-port-search");n&&n.addEventListener("input",c=>{const a=c.target.value.toLowerCase(),l=e.filter(p=>p.name.toLowerCase().includes(a)||(p.description||"").toLowerCase().includes(a)||p.topics.some(d=>d.toLowerCase().includes(a)));u(l,t,o,r)})}async function P(e,t={searchContainer:"search-cont",filtersContainer:"filters-cont",projectsContainer:"projects-cont"}){try{j(t.searchContainer),S(t.projectsContainer,6);const
|
|
43
|
+
`)}function E(e,t,o,r,n){const c=document.getElementById(e);c&&c.addEventListener("click",i=>{const l=i.target.closest(".ghp-filter-btn");if(!l)return;const p=l.dataset.topic,d=p==="all"?t:t.filter(g=>g.topics.includes(p));u(d,o,r,n),c.querySelectorAll(".ghp-filter-btn").forEach(g=>g.classList.remove("active")),l.classList.add("active")})}function B(e,t,o,r){const n=document.getElementById("gh-port-search");n&&n.addEventListener("input",c=>{const a=c.target.value.toLowerCase(),l=e.filter(p=>p.name.toLowerCase().includes(a)||(p.description||"").toLowerCase().includes(a)||p.topics.some(d=>d.toLowerCase().includes(a)));u(l,t,o,r)})}async function P(e,t={searchContainer:"search-cont",filtersContainer:"filters-cont",projectsContainer:"projects-cont"}){try{const o=t.tag||"port";j(t.searchContainer),S(t.projectsContainer,6);const r=await f(e,o);return v(r,t.filtersContainer),u(r,t.projectsContainer,e,t.customCardTemplate),E(t.filtersContainer,r,t.projectsContainer,e,t.customCardTemplate),B(r,t.projectsContainer,e,t.customCardTemplate),{projects:r,status:"success"}}catch(o){console.error("Erro ao inicializar portfólio:",o);const r=document.getElementById(t.projectsContainer);return r&&(r.innerHTML='<p class="ghp-empty-msg">Erro ao carregar projetos.</p>'),{status:"error",message:o.message}}}s.getPortProjects=f,s.initPortfolio=P,s.renderFilters=v,s.renderProjects=u,s.renderSearchBar=j,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})}));
|