repos / neovimcraft

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

commit
1b60167
parent
be3645d
author
Eric Bower
date
2022-06-25 15:03:48 +0000 UTC
Remove plugin page (#86)

7 files changed,  +10, -308
M package.json
+2, -3
 1@@ -14,15 +14,14 @@
 2     "scrape": "node --no-warnings --es-module-specifier-resolution=node --loader ts-node/esm scripts/scrape.ts",
 3     "patch": "node --no-warnings --es-module-specifier-resolution=node --loader ts-node/esm scripts/patch.ts",
 4     "process": "node --no-warnings --es-module-specifier-resolution=node --loader ts-node/esm scripts/process.ts",
 5-    "html": "node --no-warnings --es-module-specifier-resolution=node --loader ts-node/esm scripts/html.ts",
 6     "resource": "node --no-warnings --es-module-specifier-resolution=node --loader ts-node/esm scripts/resource.ts",
 7     "resource:clean": "node --no-warnings --es-module-specifier-resolution=node --loader ts-node/esm scripts/resource-clean.ts",
 8     "upload:clean": "gsutil -m rm -r gs://neovimcraft.com/*",
 9     "upload": "gsutil -m -h 'Cache-Control:private, max-age=0, no-transform' rsync -r ./build gs://neovimcraft.com",
10     "upload:db": "gsutil -m -h 'Cache-Control:private, max-age=0, no-transform' cp ./src/lib/db.json gs://neovimcraft.com/db.json",
11-    "build:all": "yarn scrape && yarn patch && yarn process && yarn html && yarn build:clean && yarn build",
12+    "build:all": "yarn scrape && yarn patch && yarn process && yarn build:clean && yarn build",
13     "deploy": "yarn build:clean && yarn build && yarn upload:clean && yarn upload && yarn upload:db",
14-    "deploy:all": "yarn scrape && yarn patch && yarn process && yarn html && yarn deploy"
15+    "deploy:all": "yarn scrape && yarn patch && yarn process && yarn deploy"
16   },
17   "devDependencies": {
18     "@sveltejs/adapter-static": "^1.0.0-next.13",
D scripts/html.ts
+0, -54
 1@@ -1,54 +0,0 @@
 2-import fs from 'fs';
 3-import util from 'util';
 4-import marked from 'marked';
 5-import prettier from 'prettier';
 6-
 7-import type { Plugin } from '../src/lib/types';
 8-
 9-const writeFile = util.promisify(fs.writeFile);
10-const readFile = util.promisify(fs.readFile);
11-
12-clean().catch(console.error);
13-
14-async function clean() {
15-  const file = await readFile('./src/lib/db.json', 'utf-8');
16-  const db = JSON.parse(file.toString());
17-  const markdownFile = await readFile('./src/lib/markdown.json', 'utf-8');
18-  const markdownDb = JSON.parse(markdownFile.toString());
19-
20-  const plugins = Object.values(db.plugins);
21-  const nextDb = {};
22-  plugins.forEach((plugin: Plugin) => {
23-    console.log(`processing ${plugin.id}`);
24-    marked.use({
25-      walkTokens: (token) => {
26-        const domain = 'https://github.com';
27-        const pre = `${domain}/${plugin.username}/${plugin.repo}/blob/${plugin.branch}`;
28-
29-        if (token.type === 'link' || token.type === 'image') {
30-          if (token.href && !token.href.startsWith('http') && !token.href.startsWith('#')) {
31-            token.href = `${pre}/${token.href.replace('./', ``)}`;
32-          }
33-        } else if (token.type === 'html') {
34-          token.text = '';
35-          // token.text = token.text.replace(/\.\//g, `${pre}/`);
36-        }
37-      },
38-    });
39-
40-    const markdown = markdownDb.markdown[plugin.id];
41-    if (!markdown) return;
42-    const html = marked(markdown);
43-    nextDb[plugin.id] = html;
44-  });
45-
46-  try {
47-    const json = prettier.format(JSON.stringify({ html: nextDb }), {
48-      parser: 'json',
49-      printWidth: 100,
50-    });
51-    await writeFile('./src/lib/html.json', json);
52-  } catch (err) {
53-    console.error(err);
54-  }
55-}
M scripts/process.ts
+7, -50
  1@@ -43,11 +43,8 @@ async function processMissingResources() {
  2   console.log(`Missing ${missing.length} resources`);
  3 
  4   const results = await processResources(missing);
  5-  const markdownFile = await readFile('./src/lib/markdown.json');
  6-  const markdownJson = JSON.parse(markdownFile.toString());
  7   const plugins = { ...db.plugins, ...results.plugins };
  8-  const markdown = { ...markdownJson.markdown, ...results.markdown };
  9-  return { plugins, markdown };
 10+  return plugins;
 11 }
 12 
 13 async function delay(ms: number): Promise<void> {
 14@@ -81,9 +78,9 @@ async function githubApi(endpoint: string): Promise<Resp<{ [key: string]: any }>
 15       ok: false,
 16       data: {
 17         status: res.status,
 18-        error: new Error(`JSON parsing error [${url}]`)
 19-      }
 20-    }
 21+        error: new Error(`JSON parsing error [${url}]`),
 22+      },
 23+    };
 24   }
 25 
 26   if (res.ok) {
 27@@ -102,25 +99,6 @@ async function githubApi(endpoint: string): Promise<Resp<{ [key: string]: any }>
 28   };
 29 }
 30 
 31-async function fetchReadme({ username, repo }: Props): Promise<Resp<string>> {
 32-  const result = await githubApi(`/repos/${username}/${repo}/readme`);
 33-  if (!result.ok) {
 34-    return {
 35-      ok: false,
 36-      data: result.data as any,
 37-    };
 38-  }
 39-
 40-  const url = result.data.download_url;
 41-  console.log(`Fetching ${url}`);
 42-  const readme = await fetch(url);
 43-  const data = await readme.text();
 44-  return {
 45-    ok: true,
 46-    data,
 47-  };
 48-}
 49-
 50 async function fetchRepo({ username, repo }: Props): Promise<Resp<{ [key: string]: any }>> {
 51   const result = await githubApi(`/repos/${username}/${repo}`);
 52   return result;
 53@@ -159,18 +137,10 @@ async function fetchGithubData(props: Props): Promise<Resp<any>> {
 54     console.log(`${branch.data.status}: ${branch.data.error.message}`);
 55   }
 56 
 57-  const readme = await fetchReadme({
 58-    username: props.username,
 59-    repo: props.repo,
 60-  });
 61-  if (readme.ok === false) {
 62-    console.log(`${readme.data.status}: ${readme.data.error.message}`);
 63-  }
 64-
 65   return {
 66     ok: true,
 67     data: {
 68-      readme: readme.ok ? readme.data : '',
 69+      readme: '',
 70       repo: repo.data,
 71       branch: branch.data,
 72     },
 73@@ -179,7 +149,6 @@ async function fetchGithubData(props: Props): Promise<Resp<any>> {
 74 
 75 async function processResources(resources: Resource[]) {
 76   const plugins: { [key: string]: Plugin } = {};
 77-  const markdown: { [key: string]: string } = {};
 78 
 79   console.log(`Fetching ${resources.length} resources`);
 80 
 81@@ -192,7 +161,6 @@ async function processResources(resources: Resource[]) {
 82         const resp = result.data;
 83         const id = `${d.username}/${d.repo}`;
 84 
 85-        markdown[id] = resp.readme;
 86         plugins[id] = createPlugin({
 87           id,
 88           username: d.username,
 89@@ -216,24 +184,13 @@ async function processResources(resources: Resource[]) {
 90     }
 91   }
 92 
 93-  return { plugins, markdown };
 94+  return plugins;
 95 }
 96 
 97-async function saveData({
 98-  plugins,
 99-  markdown,
100-}: {
101-  plugins: { [key: string]: Plugin };
102-  markdown: { [key: string]: string };
103-}) {
104+async function saveData(plugins: { [key: string]: Plugin }) {
105   const pluginJson = prettier.format(JSON.stringify({ plugins }), {
106     parser: 'json',
107     printWidth: 100,
108   });
109-  const markdownJson = prettier.format(JSON.stringify({ markdown }), {
110-    parser: 'json',
111-    printWidth: 100,
112-  });
113   await writeFile('./src/lib/db.json', pluginJson);
114-  await writeFile('./src/lib/markdown.json', markdownJson);
115 }
D src/lib/plugin-view.svelte
+0, -97
 1@@ -1,97 +0,0 @@
 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-  import { format, relativeTimeFromDates } from '$lib/date';
11-
12-  export let plugin: Plugin;
13-  export let tags: Tag[];
14-  export let html: string = '<div>readme not found</div>';
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-  <div class="timestamps">
45-    <div>
46-      <h5 class="ts-header">CREATED</h5>
47-      <h2>{format(new Date(plugin.createdAt))}</h2>
48-    </div>
49-    <div>
50-      <h5 class="ts-header">UPDATED</h5>
51-      <h2>{relativeTimeFromDates(new Date(plugin.updatedAt))}</h2>
52-    </div>
53-  </div>
54-  <hr />
55-</div>
56-{@html html}
57-
58-<style>
59-  :global(img) {
60-    max-width: 100%;
61-    height: auto;
62-  }
63-
64-  .timestamps {
65-    display: flex;
66-    justify-content: space-between;
67-    background-color: var(--primary-color);
68-    padding: 15px;
69-    margin: 15px 0;
70-  }
71-
72-  .ts-header {
73-    margin-bottom: 10px;
74-  }
75-
76-  .meta {
77-    margin-bottom: 20px;
78-  }
79-
80-  .metrics {
81-    display: flex;
82-    justify-content: space-between;
83-  }
84-
85-  .metric {
86-    display: flex;
87-    align-items: center;
88-    cursor: pointer;
89-  }
90-
91-  .tags_view {
92-    margin-bottom: 10px;
93-  }
94-
95-  .install {
96-    margin-top: 10px;
97-  }
98-</style>
M src/lib/plugin.svelte
+1, -4
 1@@ -12,12 +12,9 @@
 2 <div class="container">
 3   <div class="header">
 4     <h2 class="item_header">
 5-      <a href="/plugin/{plugin.username}/{plugin.repo}">{plugin.repo}</a>
 6+      <a href="{plugin.link}">{plugin.repo}</a>
 7     </h2>
 8     <div class="metrics">
 9-      <Tooltip tip="github repo" bottom>
10-        <a href={plugin.link}><Icon icon="github" /></a>
11-      </Tooltip>
12       <Tooltip tip="stars" bottom>
13         <div class="metric-item"><Icon icon="star" /> <span>{plugin.stars}</span></div>
14       </Tooltip>
D src/routes/plugin/[username]/[repo].json.ts
+0, -15
 1@@ -1,15 +0,0 @@
 2-import type { Plugin } from '$lib/types';
 3-import * as db from '$lib/db.json';
 4-import * as pluginHtml from '$lib/html.json';
 5-import { derivePluginData } from '$lib/plugin-data';
 6-
 7-export async function get({ params }) {
 8-  const { username, repo } = params;
 9-  const id = `${username}/${repo}`;
10-  const plugin = db.plugins[id] as Plugin;
11-  const { tagDb } = derivePluginData(db.plugins);
12-  const html = pluginHtml.html[id];
13-  const tags = plugin.tags.map((t) => tagDb[t]).filter(Boolean);
14-
15-  return { body: { plugin, html, tags } };
16-}
D src/routes/plugin/[username]/[repo].svelte
+0, -85
 1@@ -1,85 +0,0 @@
 2-<script context="module" lang="ts">
 3-  export const prerender = true;
 4-
 5-  import type { LoadInput } from '@sveltejs/kit';
 6-
 7-  export async function load({ page, fetch }: LoadInput) {
 8-    const { username, repo } = page.params;
 9-    const url = `/plugin/${username}/${repo}.json`;
10-    const res = await fetch(url);
11-
12-    if (res.ok) {
13-      return {
14-        props: await res.json(),
15-      };
16-    }
17-
18-    return {
19-      status: res.status,
20-      error: new Error(`Could not load ${url}`),
21-    };
22-  }
23-</script>
24-
25-<script lang="ts">
26-  import type { Plugin, Tag } from '$lib/types';
27-  import PluginView from '$lib/plugin-view.svelte';
28-  import Icon from '$lib/icon.svelte';
29-  import Nav from '$lib/nav.svelte';
30-
31-  export let plugin: Plugin;
32-  export let tags: Tag[];
33-  export let html: string;
34-</script>
35-
36-<svelte:head>
37-  <title>
38-    {plugin.id}: {plugin.description}
39-  </title>
40-  <meta property="og:title" content={plugin.id} />
41-  <meta name="twitter:title" content={plugin.id} />
42-  <meta itemprop="name" content={plugin.id} />
43-
44-  <meta name="description" content="{plugin.id}: {plugin.description}" />
45-  <meta itemprop="description" content="{plugin.id}: {plugin.description}" />
46-  <meta property="og:description" content="{plugin.id}: {plugin.description}" />
47-  <meta name="twitter:description" content="{plugin.id}: {plugin.description}" />
48-</svelte:head>
49-
50-<Nav />
51-
52-<div class="container">
53-  <div class="view">
54-    <div class="header">
55-      <h1>{plugin.id}</h1>
56-      {#if plugin.homepage}<a href={plugin.homepage}>website</a>{/if}
57-      <a href={plugin.link}><Icon icon="github" /> <span>github</span></a>
58-    </div>
59-    <PluginView {plugin} {tags} {html} />
60-  </div>
61-</div>
62-
63-<style>
64-  .container {
65-    display: flex;
66-    justify-content: center;
67-    width: 100%;
68-  }
69-
70-  .view {
71-    max-width: 800px;
72-    width: 95%;
73-    padding: 0 10px 30px 10px;
74-  }
75-
76-  .header {
77-    display: flex;
78-    align-items: center;
79-  }
80-
81-  .header > a {
82-    margin-left: 15px;
83-    display: flex;
84-    align-items: center;
85-  }
86-</style>