- 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
+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",
+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-}
+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 }
+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>
+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>
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-}
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>