repos / neovimcraft

website that makes it easy to find neovim plugins
git clone https://github.com/neurosnap/neovimcraft.git

commit
21d48bd
parent
68b23ca
author
Eric Bower
date
2021-07-19 14:53:37 +0000 UTC
show tags under each plugin in plugin list
5 files changed,  +187, -150
A src/lib/plugin-view.svelte
+89, -0
 1@@ -0,0 +1,89 @@
 2+<script lang="ts">
 3+  import qs from 'query-string';
 4+  import { goto } from '$app/navigation';
 5+
 6+  import type { Plugin, Tag } from './types';
 7+  import TagItem from './tag.svelte';
 8+  import Icon from './icon.svelte';
 9+  import Tooltip from '$lib/tooltip.svelte';
10+
11+  export let plugin: Plugin;
12+  export let tags: Tag[];
13+  export let html: string = '<div>readme not found</div>';
14+  const isPlugin = tags.find((t) => t.id === 'plugin');
15+
16+  function onSearch(curSearch: string) {
17+    const query = qs.parseUrl(window.location.search);
18+    const s = encodeURIComponent(curSearch);
19+    query.query.search = s;
20+    goto(`/${qs.stringifyUrl(query)}`);
21+  }
22+</script>
23+
24+<div class="meta">
25+  <div class="tags_view">
26+    {#each tags as tag}
27+      <TagItem {tag} {onSearch} showCount={false} />
28+    {/each}
29+  </div>
30+  <div class="metrics">
31+    <Tooltip tip="stars" bottom>
32+      <div class="metric"><Icon icon="star" /> <span>{plugin.stars}</span></div>
33+    </Tooltip>
34+    <Tooltip tip="open issues" bottom>
35+      <div class="metric"><Icon icon="alert-circle" /> <span>{plugin.openIssues}</span></div>
36+    </Tooltip>
37+    <Tooltip tip="subscribers" bottom>
38+      <div class="metric"><Icon icon="users" /> <span>{plugin.subscribers}</span></div>
39+    </Tooltip>
40+    <Tooltip tip="forks" bottom>
41+      <div class="metric"><Icon icon="git-branch" /> <span>{plugin.forks}</span></div>
42+    </Tooltip>
43+  </div>
44+  {#if isPlugin}
45+  <div class="install">
46+    <h3>packer</h3>
47+    <pre><code>require('packer').startup(function()
48+  use '{plugin.id}'
49+end)</code></pre>
50+  </div>
51+  <div class="install">
52+    <h3>paq</h3>
53+    <pre><code>require "paq" &lcub; 
54+  '{plugin.id}'
55+&rcub;</code></pre>
56+  </div>
57+  {/if}
58+  <hr />
59+</div>
60+{@html html}
61+
62+<style>
63+  :global(img) {
64+    max-width: 100%;
65+    height: auto;
66+  }
67+
68+  .meta {
69+    margin-bottom: 20px;
70+  }
71+
72+  .metrics {
73+    display: flex;
74+    justify-content: space-between;
75+  }
76+
77+  .metric {
78+    display: flex;
79+    align-items: center;
80+    cursor: pointer;
81+  }
82+
83+  .tags_view {
84+    margin-bottom: 10px;
85+  }
86+
87+  .install {
88+    margin-top: 10px;
89+  }
90+</style>
M src/lib/plugin.svelte
+65, -74
  1@@ -1,89 +1,80 @@
  2 <script lang="ts">
  3-  import qs from 'query-string';
  4-  import { goto } from '$app/navigation';
  5-
  6-  import type { Plugin, Tag } from './types';
  7-  import TagView from './tag.svelte';
  8-  import Icon from './icon.svelte';
  9-  import Tooltip from '$lib/tooltip.svelte';
 10-
 11-  export let plugin: Plugin;
 12-  export let tags: Tag[];
 13-  export let html: string = '<div>readme not found</div>';
 14-  const isPlugin = tags.find((t) => t.id === 'plugin');
 15-
 16-  function onSearch(curSearch: string) {
 17-    const query = qs.parseUrl(window.location.search);
 18-    const s = encodeURIComponent(curSearch);
 19-    query.query.search = s;
 20-    goto(`/${qs.stringifyUrl(query)}`);
 21-  }
 22+import type { Plugin, Tag } from './types';
 23+import Tooltip from './tooltip.svelte';
 24+import Icon from './icon.svelte';
 25+import TagItem from './tag.svelte';
 26+export let plugin: Plugin;
 27+export let tags: Tag[];
 28+export let onSearch: (t: string) => any = (_: string) => {};
 29 </script>
 30 
 31-<div class="meta">
 32-  <div class="tags_view">
 33-    {#each tags as tag}
 34-      <TagView {tag} {onSearch} />
 35-    {/each}
 36-  </div>
 37-  <div class="metrics">
 38-    <Tooltip tip="stars" bottom>
 39-      <div class="metric"><Icon icon="star" /> <span>{plugin.stars}</span></div>
 40-    </Tooltip>
 41-    <Tooltip tip="open issues" bottom>
 42-      <div class="metric"><Icon icon="alert-circle" /> <span>{plugin.openIssues}</span></div>
 43-    </Tooltip>
 44-    <Tooltip tip="subscribers" bottom>
 45-      <div class="metric"><Icon icon="users" /> <span>{plugin.subscribers}</span></div>
 46-    </Tooltip>
 47-    <Tooltip tip="forks" bottom>
 48-      <div class="metric"><Icon icon="git-branch" /> <span>{plugin.forks}</span></div>
 49-    </Tooltip>
 50+
 51+<div class="container">
 52+  <div class="header">
 53+    <h2 class="item_header">
 54+      <a href="/plugin/{plugin.username}/{plugin.repo}">{plugin.repo}</a>
 55+    </h2>
 56+    <div class="metrics">
 57+      <Tooltip tip="stars" bottom>
 58+        <div class="metric-item"><Icon icon="star" /> <span>{plugin.stars}</span></div>
 59+      </Tooltip>
 60+      <Tooltip tip="open issues" bottom>
 61+        <div class="metric-item">
 62+          <Icon icon="alert-circle" /> <span>{plugin.openIssues}</span>
 63+        </div>
 64+      </Tooltip>
 65+    </div>
 66   </div>
 67-  {#if isPlugin}
 68-  <div class="install">
 69-    <h3>packer</h3>
 70-    <pre><code>require('packer').startup(function()
 71-  use '{plugin.id}'
 72-end)</code></pre>
 73+  <div class="desc">
 74+    {plugin.description}
 75   </div>
 76-  <div class="install">
 77-    <h3>paq</h3>
 78-    <pre><code>require "paq" &lcub; 
 79-  '{plugin.id}'
 80-&rcub;</code></pre>
 81+  <div class="tags">
 82+  {#each tags as tag}
 83+    <TagItem {tag} showCount={false} {onSearch} />
 84+  {/each}
 85   </div>
 86-  {/if}
 87-  <hr />
 88 </div>
 89-{@html html}
 90 
 91 <style>
 92-  :global(img) {
 93-    max-width: 100%;
 94-    height: auto;
 95-  }
 96+.container {
 97+  display: flex;
 98+  flex-direction: column;
 99+  padding: 15px 5px;
100+  height: 140px;
101+  border-bottom: 1px solid var(--primary-color);
102+}
103+
104+.header {
105+  display: flex;
106+  align-items: center;
107+  margin-bottom: 5px;
108+}
109 
110-  .meta {
111-    margin-bottom: 20px;
112-  }
113+.desc {
114+  margin-top: 5px;
115+}
116 
117-  .metrics {
118-    display: flex;
119-    justify-content: space-between;
120-  }
121+.item_header {
122+  flex: 1;
123+  display: flex;
124+  align-items: center;
125+}
126 
127-  .metric {
128-    display: flex;
129-    align-items: center;
130-    cursor: pointer;
131-  }
132+.metrics {
133+  width: 150px;
134+  min-width: 150px;
135+  display: flex;
136+  justify-content: space-between;
137+}
138 
139-  .tags_view {
140-    margin-bottom: 10px;
141-  }
142+.metric-item {
143+  display: flex;
144+  justify-content: center;
145+  align-items: center;
146+  cursor: pointer;
147+}
148 
149-  .install {
150-    margin-top: 10px;
151-  }
152+.tags {
153+  margin-top: 5px;
154+}
155 </style>
M src/lib/tag.svelte
+2, -1
 1@@ -11,10 +11,11 @@
 2 
 3   export let tag: Tag;
 4   export let onSearch: (t: string) => any = (_: string) => {};
 5+  export let showCount: boolean = true;
 6 </script>
 7 
 8 <span class="tag {findColor(tag)}" on:click={() => onSearch(`tag:${tag.id}`)}>
 9-  {tag.id} x {tag.count}
10+  {tag.id}{#if showCount} x {tag.count}{/if}
11 </span>
12 
13 <style>
M src/routes/index.svelte
+30, -74
  1@@ -6,12 +6,13 @@
  2 
  3   export async function load() {
  4     const pluginDb = db.plugins as any;
  5-    const { plugins, tags } = derivePluginData(pluginDb);
  6+    const { plugins, tags, tagDb } = derivePluginData(pluginDb);
  7 
  8     return {
  9       props: {
 10         plugins,
 11         tags,
 12+        tagDb
 13       },
 14     };
 15   }
 16@@ -21,10 +22,10 @@
 17   import qs from 'query-string';
 18   import { goto } from '$app/navigation';
 19   import { page } from '$app/stores';
 20-  import type { Plugin, Tag } from '$lib/types';
 21-  import TagView from '$lib/tag.svelte';
 22+  import type { Plugin, Tag, TagMap } from '$lib/types';
 23+  import TagItem from '$lib/tag.svelte';
 24   import Icon from '$lib/icon.svelte';
 25-  import Tooltip from '$lib/tooltip.svelte';
 26+  import PluginItem from '$lib/plugin.svelte';
 27 
 28   let timer: NodeJS.Timeout;
 29   const debounce = (fn: (v: string) => any) => {
 30@@ -76,6 +77,11 @@
 31     return plugins.filter(onFilter);
 32   }
 33 
 34+  export let tagDb: TagMap = {};
 35+  function getTags(tags: string[]): Tag[] {
 36+    return tags.map((t) => tagDb[t]).filter(Boolean);
 37+  }
 38+
 39   let search = '';
 40   page.subscribe(({ query }) => {
 41     search = decodeURIComponent(query.get('search') || '');
 42@@ -89,7 +95,7 @@
 43 <div class="container">
 44   <div class="intro">
 45     <h1 id="logo">
 46-      Neovim Awesome
 47+      neovim awesome
 48       <a href="https://github.com/neurosnap/neovim-awesome" target="_blank">
 49         <Icon icon="github" />
 50       </a>
 51@@ -111,34 +117,17 @@
 52     {/if}
 53   </div>
 54 
 55-  <div class="tags_view">
 56+  <div class="sidebar">
 57+    <div class="desc">Search through our curated list of neovim plugins</div>
 58     {#each tags as tag}
 59-      <TagView {tag} {onSearch} />
 60+      <TagItem {tag} {onSearch} />
 61     {/each}
 62   </div>
 63-  <div class="plugins_view">
 64+  <div class="plugins">
 65+    <div class="search_results">{results.length} results</div>
 66     <div class="plugins_list">
 67       {#each results as plugin}
 68-        <div class="plugin">
 69-          <div class="plugin_top">
 70-            <h2 class="plugin_item_header">
 71-              <a href="/plugin/{plugin.username}/{plugin.repo}">{plugin.repo}</a>
 72-            </h2>
 73-            <div class="plugin_metrics">
 74-              <Tooltip tip="stars" bottom>
 75-                <div class="metric"><Icon icon="star" /> <span>{plugin.stars}</span></div>
 76-              </Tooltip>
 77-              <Tooltip tip="open issues" bottom>
 78-                <div class="metric">
 79-                  <Icon icon="alert-circle" /> <span>{plugin.openIssues}</span>
 80-                </div>
 81-              </Tooltip>
 82-            </div>
 83-          </div>
 84-          <div class="plugin_desc">
 85-            {plugin.description}
 86-          </div>
 87-        </div>
 88+        <PluginItem {plugin} tags={getTags(plugin.tags)} onSearch={onSearch} />
 89       {/each}
 90     </div>
 91   </div>
 92@@ -149,6 +138,10 @@
 93 </svelte:head>
 94 
 95 <style>
 96+  .desc {
 97+    margin-bottom: 5px;
 98+  }
 99+
100   .search_view {
101     grid-column: 2;
102     grid-row: 1;
103@@ -175,6 +168,10 @@
104     padding-right: 30px;
105   }
106 
107+  .search_results {
108+    margin: 5px 0;
109+  }
110+
111   .container {
112     height: 100vh;
113     display: grid;
114@@ -198,7 +195,7 @@
115     margin-left: 15px;
116   }
117 
118-  .tags_view {
119+  .sidebar {
120     grid-column: 1;
121     grid-row: 2;
122     padding: 0 10px;
123@@ -206,54 +203,13 @@
124     overflow-y: scroll;
125   }
126 
127-  .plugin {
128-    display: flex;
129-    flex-direction: column;
130-    padding: 15px;
131-    height: 110px;
132-    border-bottom: 1px solid var(--primary-color);
133-  }
134-
135-  .plugin_top {
136-    display: flex;
137-    align-items: center;
138-    margin-bottom: 5px;
139-  }
140-
141-  .plugin_desc {
142-    margin-top: 5px;
143-  }
144-
145-  .plugin_item_header {
146-    flex: 1;
147-    display: flex;
148-    align-items: center;
149-  }
150-
151-  .plugin_metrics {
152-    width: 150px;
153-    min-width: 150px;
154-    display: flex;
155-    justify-content: space-between;
156-  }
157-
158-  .metric {
159-    display: flex;
160-    justify-content: center;
161-    align-items: center;
162-    cursor: pointer;
163-  }
164-
165-  .plugins_view {
166-    display: flex;
167-    align-items: center;
168-    flex-direction: column;
169+  .plugins {
170     grid-column: 2;
171     grid-row: 2;
172-    height: calc(100vh - 50px);
173   }
174 
175   .plugins_list {
176+    height: calc(100vh - 50px);
177     width: 100%;
178     overflow-y: auto;
179     overflow-x: hidden;
180@@ -265,7 +221,7 @@
181     }
182 
183     #logo,
184-    .tags_view {
185+    .sidebar {
186       display: none;
187     }
188 
189@@ -274,7 +230,7 @@
190       padding: 0 10px;
191     }
192 
193-    .plugins_view {
194+    .plugins {
195       grid-column: 1;
196     }
197   }
M src/routes/plugin/[username]/[repo].svelte
+1, -1
1@@ -23,7 +23,7 @@
2 
3 <script lang="ts">
4   import type { Plugin, Tag } from '$lib/types';
5-  import PluginView from '$lib/plugin.svelte';
6+  import PluginView from '$lib/plugin-view.svelte';
7   import Icon from '$lib/icon.svelte';
8 
9   export let plugin: Plugin;