Compare commits

...

5 Commits

Author SHA1 Message Date
177d8ca3a4 fix bug and error report 2022-12-01 23:13:07 +09:00
b393f16432 add search 2022-12-01 19:40:03 +09:00
ae4895fff3 add progrossbar 2022-11-29 19:14:48 +09:00
1f3eab6593 fix bug: string escape 2022-11-29 19:14:36 +09:00
5ab8ec04a6 add MyDoc parser 2022-11-29 17:55:06 +09:00
21 changed files with 1021 additions and 58 deletions

2
.gitignore vendored
View File

@ -0,0 +1,2 @@
.env
http_ca.crt

View File

@ -1,3 +1,15 @@
import { Client as ElasticsearchClient, SearchHit } from "https://deno.land/x/elasticsearch@v8.3.3/mod.ts";
import { config } from "https://deno.land/std@0.166.0/dotenv/mod.ts";
import { Doc } from "../doc_load/load.ts";
const env = await config({ export: true });
const client = new ElasticsearchClient({
node: "https://localhost:9200",
auth: {
username: env["ELASTIC_USERNAME"],
password: env["ELASTIC_PASSWORD"],
}
});
export interface RepoData {
name: string;
@ -10,6 +22,19 @@ export interface RepoData {
readme: string;
}
function docToRepoData(doc: Doc): RepoData {
return {
name: doc.name,
author: doc.author,
description: doc.desc,
url: doc.url,
stars: doc.star,
forks: doc.fork,
tags: doc.tags,
readme: doc.readme,
};
}
export const SAMPLE_DATA: RepoData[] = [
{
name: "deno",
@ -50,8 +75,18 @@ export const SAMPLE_DATA: RepoData[] = [
]
export const getRepos = async (): Promise<RepoData[]> => {
// return mock data for now
return SAMPLE_DATA;
const res = await client.search<Doc>({
target: "github-awesome",
body: {
query: {
match_all: {},
},
sort: [
{ "star": "desc" },
]
},
})
return res.hits.hits.map((hit: SearchHit<Doc>) => docToRepoData(hit._source));
}
export interface SearchOptions {
@ -70,6 +105,23 @@ export interface SearchOptions {
}
export async function searchRepos(query: string, options?: SearchOptions): Promise<RepoData[]> {
// return mock data for now
return SAMPLE_DATA;
const res = await client.search<Doc>({
target: "github-awesome",
body: {
query: {
multi_match: {
query,
fields: ["name", "desc", "readme", "tags", "author"],
},
},
sort: [
"_score",
{ "star": "desc" },
],
from: options?.offset,
size: options?.limit,
},
});
//console.log(res);
return res.hits.hits.map((hit: SearchHit<Doc>) => docToRepoData(hit._source));
}

214
cli.ts Normal file
View File

@ -0,0 +1,214 @@
import { expandGlob } from 'std/fs/mod.ts';
import { config } from "std/dotenv/mod.ts";
import { chunk } from "https://deno.land/std/collections/chunk.ts"
import { Client as ElasticsearchClient, DocumentsBulkRequest } from "https://deno.land/x/elasticsearch@v8.3.3/mod.ts";
import { Doc, DocParser, readDoc } from './doc_load/load.ts';
import ProgressBar from 'https://deno.land/x/progress@v1.3.0/mod.ts';
import { Command } from "cliffy";
const env = await config({ export: true });
const client = new ElasticsearchClient({
node: 'https://localhost:9200',
auth: {
username: env['ELASTIC_USERNAME'],
password: env['ELASTIC_PASSWORD'],
}
});
async function createIndex() {
const res = await client.indices.create({
index: 'github-awesome',
body: {
mappings: {
properties: {
"name": {
type: "text",
},
"desc": {
type: "text",
},
"url": {
type: "keyword",
},
"star": {
type: "integer",
},
"fork": {
type: "integer",
},
"author": {
type: "keyword",
},
"tags": {
type: "keyword",
"ignore_above": 256,
},
"readme": {
type: "text",
},
},
},
},
});
console.log(res);
console.log(res.acknowledged ? 'Index created' : 'Index creation failed');
}
async function deleteIndex() {
const res = await client.indices.delete({
index: 'github-awesome',
});
console.log(res);
console.log(res.acknowledged ? 'Index deleted' : 'Index deletion failed');
}
async function bulkIndex(path: string[],{
chunkSize = 1000,
progressBar = false,
}) {
const ch = chunk(path, chunkSize);
const bar = new ProgressBar({
total: ch.length,
title: 'Indexing',
width: 50,
});
let i = 0;
for (const pathes of ch) {
const docs = await Promise.all(pathes.map(async (path) => {
const doc = await readDoc(path);
if (doc.from_url){
delete doc.from_url;
}
return [
{
index: {
_id: doc.author+"/"+doc.name,
}
},
doc
] as [{ index: { _id: string } }, Doc];
}
));
const res = await client.documents.bulk({
target: 'github-awesome',
body: docs.flat(),
} as DocumentsBulkRequest<Doc>) as {
errors: boolean,
took: number,
items: unknown[]
};
if (res.errors){
if (progressBar){
bar.console("error occurs!")
}
else {
console.log("error occurs!")
}
}
if (progressBar) {
bar.render(++i);
}
}
if (progressBar) {
bar.end();
}
}
async function test_search(query: string, {
size = 10,
from = 0,
}) {
const res = await client.search<Doc>({
target: 'github-awesome',
body: {
query: {
multi_match: {
query,
fields: ['name', 'desc', 'tags', 'author', 'readme'],
}
},
from,
size,
},
});
return res.hits.hits;
}
async function main() {
const cmd = new Command();
cmd
.name('github-awesome')
.version('0.1.0')
.description('github-awesome search engine cli');
cmd
.command('index [path...]')
.description('index github-awesome. glob pattern is supported.')
.option('-c, --chunk-size <chunkSize:number>', 'chunk size', {
default: 200,
})
.option('-p, --progress-bar', 'show progress bar')
.action(async ({chunkSize, progressBar}, ...path: string[]) => {
const pathes = [];
for (const p of path) {
for await (const iterator of expandGlob(p)) {
pathes.push(iterator.path);
}
}
if (pathes.length === 0) {
console.log('no path found');
return;
}
await bulkIndex(pathes, {
chunkSize,
progressBar
});
});
cmd
.command('search <query>')
.description('search github-awesome')
.option('-s, --size <size:number>', 'size', {
default: 10,
})
.option('-f, --from <from:number>', 'from', {
default: 0,
})
.option('-j, --json', 'output json')
.action(async ({size, from, json}, query: string) => {
const s = await test_search(query, {
size,
from,
});
if (s.length === 0) {
console.log('no result found');
return;
}
if (json) {
console.log(JSON.stringify(s, null, 2));
}
else {
for (const doc of s) {
console.log("id :",doc._id);
console.log("score :",doc._score);
console.log();
}
}
});
cmd
.command('create-index')
.description('create index')
.action(async () => {
await createIndex();
});
cmd
.command('delete-index')
.description('delete index')
.action(async () => {
await deleteIndex();
});
await cmd.parse(Deno.args);
}
if (import.meta.main) {
await main();
}

View File

@ -3,25 +3,29 @@ import { useState } from "preact/hooks";
export interface SearchBarProps {
value: string;
onChange: (value: string) => void;
onSubmit: () => void;
}
export function SearchBar(props: SearchBarProps) {
const { value, onChange } = props;
const [inputValue, setInputValue] = useState(value);
const { value, onChange, onSubmit } = props;
return (
<div class="flex items-center justify-center w-full p-4">
<input class="w-full flex-auto p-2 border border-gray-200 rounded
focus:outline-none focus:border-gray-600"
type="text" placeholder="Search..." value={inputValue}
type="text" placeholder="Search..." value={value}
onInput={e=>{
if(e.currentTarget){
setInputValue(e.currentTarget.value);
onChange(e.currentTarget.value);
}
}}/>
}}
onKeyUp={e=>{
if(e.key === "Enter"){
onSubmit();
}
}}/>
<button class="flex-grow-0 p-2 ml-2 text-white bg-blue-500 rounded hover:bg-blue-600"
type="submit">Submit</button>
type="submit" onClick={onSubmit}>Submit</button>
</div>
);
}

View File

@ -1,6 +1,8 @@
{
"tasks": {
"start": "deno run -A --watch=static/,routes/ dev.ts"
"start": "deno run -A --cert http_ca.crt --watch=static/,routes/ dev.ts",
"cli": "deno run -A --unstable --cert http_ca.crt cli.ts",
"validate": "deno run -A validator.ts"
},
"importMap": "./import_map.json",
"compilerOptions": {

264
deno.lock
View File

@ -1,6 +1,12 @@
{
"version": "2",
"remote": {
"https://deno.land/std@0.138.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74",
"https://deno.land/std@0.138.0/flags/mod.ts": "019df8a63ed24df2d10be22e8983aa9253623e871228a2f8f328ff2d0404f7ef",
"https://deno.land/std@0.138.0/fmt/colors.ts": "30455035d6d728394781c10755351742dd731e3db6771b1843f9b9e490104d37",
"https://deno.land/std@0.138.0/testing/_diff.ts": "029a00560b0d534bc0046f1bce4bd36b3b41ada3f2a3178c85686eb2ff5f1413",
"https://deno.land/std@0.138.0/testing/_format.ts": "0d8dc79eab15b67cdc532826213bbe05bccfd276ca473a50a3fc7bbfb7260642",
"https://deno.land/std@0.138.0/testing/asserts.ts": "dc7ab67b635063989b4aec8620dbcc6fa7c2465f2d9c856bddf8c0e7b45b4481",
"https://deno.land/std@0.140.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74",
"https://deno.land/std@0.140.0/_util/os.ts": "3b4c6e27febd119d36a416d7a97bd3b0251b77c88942c8f16ee5953ea13e2e49",
"https://deno.land/std@0.140.0/fs/_util.ts": "0fb24eb4bfebc2c194fb1afdb42b9c3dda12e368f43e8f2321f84fc77d42cb0f",
@ -54,12 +60,260 @@
"https://deno.land/std@0.152.0/async/mux_async_iterator.ts": "5b4aca6781ad0f2e19ccdf1d1a1c092ccd3e00d52050d9c27c772658c8367256",
"https://deno.land/std@0.152.0/async/pool.ts": "ef9eb97b388543acbf0ac32647121e4dbe629236899586c4d4311a8770fbb239",
"https://deno.land/std@0.152.0/async/tee.ts": "bcfae0017ebb718cf4eef9e2420e8675d91cb1bcc0ed9b668681af6e6caad846",
"https://deno.land/std@0.152.0/encoding/base64.ts": "c57868ca7fa2fbe919f57f88a623ad34e3d970d675bdc1ff3a9d02bba7409db2",
"https://deno.land/std@0.152.0/http/server.ts": "0b0a9f3abfcfecead944b31ee9098a0c11a59b0495bf873ee200eb80e7441483",
"https://deno.land/std@0.161.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74",
"https://deno.land/std@0.161.0/_util/os.ts": "8a33345f74990e627b9dfe2de9b040004b08ea5146c7c9e8fe9a29070d193934",
"https://deno.land/std@0.161.0/encoding/base64.ts": "c57868ca7fa2fbe919f57f88a623ad34e3d970d675bdc1ff3a9d02bba7409db2",
"https://deno.land/std@0.161.0/fmt/colors.ts": "9e36a716611dcd2e4865adea9c4bec916b5c60caad4cdcdc630d4974e6bb8bd4",
"https://deno.land/std@0.161.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3",
"https://deno.land/std@0.161.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09",
"https://deno.land/std@0.161.0/path/_util.ts": "d16be2a16e1204b65f9d0dfc54a9bc472cafe5f4a190b3c8471ec2016ccd1677",
"https://deno.land/std@0.161.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633",
"https://deno.land/std@0.161.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee",
"https://deno.land/std@0.161.0/path/mod.ts": "56fec03ad0ebd61b6ab39ddb9b0ddb4c4a5c9f2f4f632e09dd37ec9ebfd722ac",
"https://deno.land/std@0.161.0/path/posix.ts": "6b63de7097e68c8663c84ccedc0fd977656eb134432d818ecd3a4e122638ac24",
"https://deno.land/std@0.161.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9",
"https://deno.land/std@0.161.0/path/win32.ts": "ee8826dce087d31c5c81cd414714e677eb68febc40308de87a2ce4b40e10fb8d",
"https://deno.land/std@0.162.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74",
"https://deno.land/std@0.162.0/bytes/bytes_list.ts": "aba5e2369e77d426b10af1de0dcc4531acecec27f9b9056f4f7bfbf8ac147ab4",
"https://deno.land/std@0.162.0/bytes/equals.ts": "3c3558c3ae85526f84510aa2b48ab2ad7bdd899e2e0f5b7a8ffc85acb3a6043a",
"https://deno.land/std@0.162.0/bytes/mod.ts": "b2e342fd3669176a27a4e15061e9d588b89c1aaf5008ab71766e23669565d179",
"https://deno.land/std@0.162.0/fmt/colors.ts": "9e36a716611dcd2e4865adea9c4bec916b5c60caad4cdcdc630d4974e6bb8bd4",
"https://deno.land/std@0.162.0/io/buffer.ts": "fae02290f52301c4e0188670e730cd902f9307fb732d79c4aa14ebdc82497289",
"https://deno.land/std@0.162.0/io/types.d.ts": "107e1e64834c5ba917c783f446b407d33432c5d612c4b3430df64fc2b4ecf091",
"https://deno.land/std@0.162.0/streams/conversion.ts": "555c6c249f3acf85655f2d0af52d1cb3168e40b1c1fa26beefea501b333abe28",
"https://deno.land/std@0.166.0/_util/asserts.ts": "d0844e9b62510f89ce1f9878b046f6a57bf88f208a10304aab50efcb48365272",
"https://deno.land/std@0.166.0/_util/os.ts": "8a33345f74990e627b9dfe2de9b040004b08ea5146c7c9e8fe9a29070d193934",
"https://deno.land/std@0.166.0/bytes/bytes_list.ts": "aba5e2369e77d426b10af1de0dcc4531acecec27f9b9056f4f7bfbf8ac147ab4",
"https://deno.land/std@0.166.0/bytes/equals.ts": "3c3558c3ae85526f84510aa2b48ab2ad7bdd899e2e0f5b7a8ffc85acb3a6043a",
"https://deno.land/std@0.166.0/bytes/mod.ts": "b2e342fd3669176a27a4e15061e9d588b89c1aaf5008ab71766e23669565d179",
"https://deno.land/std@0.166.0/collections/_comparators.ts": "b9edf2170aaccbe11407d37e8948b6867cf68fbe5225f4cd4cdb02f174227157",
"https://deno.land/std@0.166.0/collections/_utils.ts": "fd759867be7a0047a1fa89ec89f7b58ebe3f2f7f089a8f4e416eb30c5d764868",
"https://deno.land/std@0.166.0/collections/aggregate_groups.ts": "c2932492fce4a117b0a271082cecea193b1c3fd7db2422484e67a3c2b8872868",
"https://deno.land/std@0.166.0/collections/associate_by.ts": "272dc97bd296dbf53ba19acc95fda2a8fa8883ed7929ad0b597cfc7efd87c106",
"https://deno.land/std@0.166.0/collections/associate_with.ts": "2206bbc2f497768a0d73e3de08fa8a7a3d2b12e2d731ffa2b2fb7727a5d86909",
"https://deno.land/std@0.166.0/collections/binary_heap.ts": "1879bec8df29e85615789e40b4991dbc944c3d25b5df6f416df1406c6bbffbe0",
"https://deno.land/std@0.166.0/collections/chunk.ts": "6713208d07b9fa3535e46f6aa2c06a57fe0e7497cf7703b0808d85e56ce1c487",
"https://deno.land/std@0.166.0/collections/deep_merge.ts": "a4252c99f82fe4051c6dfbe0c8ba839888c4233ab99c556ba519c5290011c281",
"https://deno.land/std@0.166.0/collections/distinct.ts": "6440d486163278e5b81d55299d83d6706f690b1c929165cc2c673ecd245df851",
"https://deno.land/std@0.166.0/collections/distinct_by.ts": "52ab6146482825932f53f7da2bdd7ae3ac566d38bf1d028edbaf109a4013329e",
"https://deno.land/std@0.166.0/collections/drop_last_while.ts": "36f01ebc2c73d1eb5bba60e76c41101a19f379ffb80b21a313a47b57e99a97d9",
"https://deno.land/std@0.166.0/collections/drop_while.ts": "9ab60aee3956028efedb72bad6c821765bd615aebc49fe874c9f8ab82844f5ad",
"https://deno.land/std@0.166.0/collections/filter_entries.ts": "e3995d73926835a244af192aaa9b7bb3c11641d0efb801807808e4919d281a28",
"https://deno.land/std@0.166.0/collections/filter_keys.ts": "fd0099e0dbf2cad8e52b441a4dac3f7f46adabea3279caf89eb4ed3408cb0f96",
"https://deno.land/std@0.166.0/collections/filter_values.ts": "faf87e3c28a8042f4e4d83c0c65cea71de2d9311644114e93b7f5c93b10cda1a",
"https://deno.land/std@0.166.0/collections/find_single.ts": "36bd5bb4c5b5b77310dbb4795ad7a88d66efb7fbf5f839c219dc766325ba56ba",
"https://deno.land/std@0.166.0/collections/first_not_nullish_of.ts": "7e41ff961587c00132ee2c580b4a0a2b15e0f3eb57f281738997a69c0628281b",
"https://deno.land/std@0.166.0/collections/group_by.ts": "3cf14e55c99320fca7ce6c1521d44170ab4a62c87738937a506357b234145f11",
"https://deno.land/std@0.166.0/collections/includes_value.ts": "cceda098877f99912c152cec9e0a495f44063f009c9fdb2d00b97d3c307218dd",
"https://deno.land/std@0.166.0/collections/intersect.ts": "d9fbee487b6c5690ad72d1555d10892367028754bae6c57b9471e6b23377e0c6",
"https://deno.land/std@0.166.0/collections/join_to_string.ts": "24e35e1a7898047aa7277fdde4526e01102d25b1c47bc5a8c6b7d37a8a83d4a0",
"https://deno.land/std@0.166.0/collections/map_entries.ts": "f0978e222dec4e4fb9d177115f19c0f09f229f952ff897433067e95fbf3c1fb7",
"https://deno.land/std@0.166.0/collections/map_keys.ts": "2139fe25f35a6ef2b91bb00c9cd8b5e9ff2def5a2f714c57bc31c3a45d5aa041",
"https://deno.land/std@0.166.0/collections/map_not_nullish.ts": "3585509bb9fe9cdc6843a51ece02be972a6630922dcda0bbe24e387ec85e21dc",
"https://deno.land/std@0.166.0/collections/map_values.ts": "7e73685397409f2a1bc5356d89a58ce0249faf9e38db29434a8733144c877a2f",
"https://deno.land/std@0.166.0/collections/max_by.ts": "bdc89ab14345aa3e332d87caf5e0f5b9b9f7840bd41addbfa59ba3f00ec158ec",
"https://deno.land/std@0.166.0/collections/max_of.ts": "61808e8b030ba64fc703a89959d50f607554f7739e0ccfe96c4c46646d651a30",
"https://deno.land/std@0.166.0/collections/max_with.ts": "5adbde35bf0f4636d544d4e54ebcf5af48374ccd3a64ad26affb003621801adc",
"https://deno.land/std@0.166.0/collections/min_by.ts": "4fb3ca15babdc354cfb194374db3bb2ef58dccb83eba81ea2fee40dffd32c58f",
"https://deno.land/std@0.166.0/collections/min_of.ts": "8435f5f6add95bf2fc91ba229cb8e44a1fdac9d1974bd25527b83e5276fb56d3",
"https://deno.land/std@0.166.0/collections/min_with.ts": "c3e81382f8eabd81d8bb728bd9ba843c159eef8130561a3a8e595fd26d84d7cf",
"https://deno.land/std@0.166.0/collections/mod.ts": "35b55ac18219107ffcf74051e7989611536d3fb96173f5053df935fdc32cefed",
"https://deno.land/std@0.166.0/collections/partition.ts": "dab859fc9d359a54e4f3ae491dbe51b7299ff0d32a53460fd0b48d03ed10de80",
"https://deno.land/std@0.166.0/collections/permutations.ts": "86475866d36016d15aae7b9c560be163b43879b6aa0b6ef412f6091783c68d51",
"https://deno.land/std@0.166.0/collections/reduce_groups.ts": "29417b912316e06bda8f2ae57d262e4ba18af076c33fedf3290c7bb5d1507f14",
"https://deno.land/std@0.166.0/collections/running_reduce.ts": "e2f21013ea13f04d2faab4258f2b6004153f420c8680cb03b56637b56e6eda1d",
"https://deno.land/std@0.166.0/collections/sample.ts": "f3cb000285da721952bf1c79c5baaa613d742b19bf1a738767a41312be6ddb25",
"https://deno.land/std@0.166.0/collections/sliding_windows.ts": "b386957c2ee81111c316f90585f71faee893952cd5f9426db60f15934ddf6659",
"https://deno.land/std@0.166.0/collections/sort_by.ts": "224fb6bc59f940c6521f06cd81b5f5a5eb887e86e9078070d14299a0847614f4",
"https://deno.land/std@0.166.0/collections/sum_of.ts": "106a416e4169a78f0e8e6dc5c71f25b3b96cafb3f8713f36737cba6c4008580d",
"https://deno.land/std@0.166.0/collections/take_last_while.ts": "17c57d73397819458f0e6c969a2044d16cd89cb7ecc2c7bb1015ab465f74f1fd",
"https://deno.land/std@0.166.0/collections/take_while.ts": "b66dfb3d9e9c16f3973c5824ee7f04107eb3251f4ec7a5f6b0e26d672ee592bd",
"https://deno.land/std@0.166.0/collections/union.ts": "436587bd092d9675bcf9fc8c6c4b82e10920b2127e2107b9b810dc594e2d9164",
"https://deno.land/std@0.166.0/collections/unzip.ts": "bfc58ee369b48e14c3de74c35f32be2ae255c0ef26dba10da1ec192f93428ee4",
"https://deno.land/std@0.166.0/collections/without_all.ts": "f18b9a5e3fe3bbb4f65e92ca41ca0ade6975f44c0afbe6cf0e66d56fbe193249",
"https://deno.land/std@0.166.0/collections/zip.ts": "a04a97f62ae7020329d2f56794ecc333930c6834b4bb1f0e7dfbf75777210e3e",
"https://deno.land/std@0.166.0/dotenv/mod.ts": "b149416f0daa0361873097495d16adbb321b8bcb594dcc5cdb6bf9639fd173fd",
"https://deno.land/std@0.166.0/dotenv/util.ts": "6cc392f087577a26a27f0463f77cc0c31a390aa055917099935b36eb2454592d",
"https://deno.land/std@0.166.0/encoding/_yaml/dumper/dumper.ts": "5bd334372608a1aec7a2343705930889d4048f57a2c4d398f1d6d75996ecd0d3",
"https://deno.land/std@0.166.0/encoding/_yaml/dumper/dumper_state.ts": "3c1bc8519c1832f0f136856881b97f0b42f64b7968767dbc36b8b0b6cae963dc",
"https://deno.land/std@0.166.0/encoding/_yaml/error.ts": "6ca899f6d86c6979bce6d7c3a6a8e2a360b09d8b0f55d2e649bd1233604fb7c9",
"https://deno.land/std@0.166.0/encoding/_yaml/loader/loader.ts": "db200890459e9490b21d8ce657d9566327e1d1d20ed493393a1f04a51516436c",
"https://deno.land/std@0.166.0/encoding/_yaml/loader/loader_state.ts": "59124e56d864274ce4043dca8bf63e937c6e960e4ad120465e424b38f3469b2d",
"https://deno.land/std@0.166.0/encoding/_yaml/mark.ts": "7f67f43755b2602fefe52012eb3ab627880da97edd0f6c00f916ceb2ddb1b5d1",
"https://deno.land/std@0.166.0/encoding/_yaml/parse.ts": "8f362dc01401099263d73a4bfa00bc90ea456d202507d62a11dfcfeac74484f5",
"https://deno.land/std@0.166.0/encoding/_yaml/schema.ts": "db295ea6079fce9c38f4ee2ff1233c65db598b35b379551e445b558534b2e1fd",
"https://deno.land/std@0.166.0/encoding/_yaml/schema/core.ts": "bcb47a389d596369fbfccf73a6b221ac3ca5440149b4f6df1e707f2efc6854ef",
"https://deno.land/std@0.166.0/encoding/_yaml/schema/default.ts": "8b6bd9cb1cab07a3397e1cc3843edba6ad40d1bd15687c1f56cd977da834d984",
"https://deno.land/std@0.166.0/encoding/_yaml/schema/extended.ts": "5e0bfd9a28c7a82ba40fc7ff7890df7469ec85390320349974acbc627ae1be88",
"https://deno.land/std@0.166.0/encoding/_yaml/schema/failsafe.ts": "7254a9ca0dff8f30377098622812e55c4535aaf352fecb4ec51939e596bd74e7",
"https://deno.land/std@0.166.0/encoding/_yaml/schema/json.ts": "2205d0d3d3377de56f92ac0f4a82bf561ea0d7b86eb195c9f0c32c7c7871d78f",
"https://deno.land/std@0.166.0/encoding/_yaml/schema/mod.ts": "6769df6082aceee9849f71168f4353ba4f92e4a2a5a429a422debac13a593d4e",
"https://deno.land/std@0.166.0/encoding/_yaml/state.ts": "374b8dc170417beccb364e543b25eef73576196f4a526836bb3a621b87a204a3",
"https://deno.land/std@0.166.0/encoding/_yaml/stringify.ts": "ec15035c1928f96f4e42c0a0e9f3082512e294fd6b8ff6a0403a3ee9282f69aa",
"https://deno.land/std@0.166.0/encoding/_yaml/type.ts": "95ad0cdbab49343b1527ebc7762c477726c34702438375be6781b44e03e9fcfc",
"https://deno.land/std@0.166.0/encoding/_yaml/type/binary.ts": "8ae1bdeebe090133b1d1e1ef8427d5ea03f8b6f8944bd2eca578c81330700b0a",
"https://deno.land/std@0.166.0/encoding/_yaml/type/bool.ts": "95c030531adc3d66a59979dc25c2fcdeb1f58ae40a91d6f9e9a537af0fd2b5a4",
"https://deno.land/std@0.166.0/encoding/_yaml/type/float.ts": "60e26783fd0e4472bd222e028323ff68e0c5ff37a9871298c676335d8574cf87",
"https://deno.land/std@0.166.0/encoding/_yaml/type/function.ts": "b5642dda5ef8d47c0325a2b89a022cbce3be45ba21f8c4f9202364d967c6b3e5",
"https://deno.land/std@0.166.0/encoding/_yaml/type/int.ts": "166cdd73d9473373e0e65e9f65d5fd8e96cbd303b58535e2ff2e049bb73dbefb",
"https://deno.land/std@0.166.0/encoding/_yaml/type/map.ts": "78bf5447d2e3f79d59bf7cb63a76ca7797854a0d8e2154c6fd35775c4e5c8c61",
"https://deno.land/std@0.166.0/encoding/_yaml/type/merge.ts": "094b272e6087c6aef39cd9617fa6603ec934e507faad6c276d293e2734f9b083",
"https://deno.land/std@0.166.0/encoding/_yaml/type/mod.ts": "b2f267dc0b0296cf8f6109aa129e2cf6d1e1f8c59f8903f0330c18749eca2d3c",
"https://deno.land/std@0.166.0/encoding/_yaml/type/nil.ts": "1988843acab56e99e883cd047c40cc7fb799b6d335f541f022ae3b914abcbe35",
"https://deno.land/std@0.166.0/encoding/_yaml/type/omap.ts": "fd3f2f9a8ae634996da84d021353ac8bf4b41e714f2711159d756d0e2f3aabd1",
"https://deno.land/std@0.166.0/encoding/_yaml/type/pairs.ts": "90736f87b6e39a144205a235d8851f7bebf6bb3835fd03742c30253d5ecd7ec5",
"https://deno.land/std@0.166.0/encoding/_yaml/type/regexp.ts": "a9e70491fa7ede8689b933d81142aa7635a253733a4df626bd479c55cb64222e",
"https://deno.land/std@0.166.0/encoding/_yaml/type/seq.ts": "135f37a1b6dcb3688bc0dad0c9dc3a04370b1fc94267960586ea23877ffd3088",
"https://deno.land/std@0.166.0/encoding/_yaml/type/set.ts": "2937ac0e1ce8c121a4009e74568e341e2a380fdb5f41f16050ce2ca7537b2bd8",
"https://deno.land/std@0.166.0/encoding/_yaml/type/str.ts": "6420d3a0099d9fbc35861241b7dad65b800ff3909efe71ab71c895326187ab8d",
"https://deno.land/std@0.166.0/encoding/_yaml/type/timestamp.ts": "3db0667dd9bdc3b3f0e8596fff023e87bc9fca230a545bb67d0bf3b732c1c656",
"https://deno.land/std@0.166.0/encoding/_yaml/type/undefined.ts": "5b595082d064cf50a3345f5fdda8c02beb0768e9d97d4bd4c53ac81a9f94e185",
"https://deno.land/std@0.166.0/encoding/_yaml/utils.ts": "c7e6bf055b08fffe700c7cbdfa2939cab7b9676ff75b6dc98d72d41b3b173d37",
"https://deno.land/std@0.166.0/encoding/yaml.ts": "4c02197eb797e40dfe0720fbe32a9990c935f02cf75b6091b36c0710c3218cf6",
"https://deno.land/std@0.166.0/fmt/colors.ts": "9e36a716611dcd2e4865adea9c4bec916b5c60caad4cdcdc630d4974e6bb8bd4",
"https://deno.land/std@0.166.0/fs/_util.ts": "fdc156f897197f261a1c096dcf8ff9267ed0ff42bd5b31f55053a4763a4bae3b",
"https://deno.land/std@0.166.0/fs/copy.ts": "37ad2d3390a672a34baf7d16a8623238906a1ee9b2c5fffc8efaa97810f4e6a9",
"https://deno.land/std@0.166.0/fs/empty_dir.ts": "c15a0aaaf40f8c21cca902aa1e01a789ad0c2fd1b7e2eecf4957053c5dbf707f",
"https://deno.land/std@0.166.0/fs/ensure_dir.ts": "76395fc1c989ca8d2de3aedfa8240eb8f5225cde20f926de957995b063135b80",
"https://deno.land/std@0.166.0/fs/ensure_file.ts": "b8e32ea63aa21221d0219760ba3f741f682d7f7d68d0d24a3ec067c338568152",
"https://deno.land/std@0.166.0/fs/ensure_link.ts": "5cc1c04f18487d7d1edf4c5469705f30b61390ffd24ad7db6df85e7209b32bb2",
"https://deno.land/std@0.166.0/fs/ensure_symlink.ts": "5273557b8c50be69477aa9cb003b54ff2240a336db52a40851c97abce76b96ab",
"https://deno.land/std@0.166.0/fs/eol.ts": "65b1e27320c3eec6fb653b27e20056ee3d015d3e91db388cfefa41616ebc7cb3",
"https://deno.land/std@0.166.0/fs/exists.ts": "6a447912e49eb79cc640adacfbf4b0baf8e17ede6d5bed057062ce33c4fa0d68",
"https://deno.land/std@0.166.0/fs/expand_glob.ts": "d08678afa768881b055bdfb5cebe4f089f8db4513a4d2b0bbe748f5870d77ce3",
"https://deno.land/std@0.166.0/fs/mod.ts": "354a6f972ef4e00c4dd1f1339a8828ef0764c1c23d3c0010af3fcc025d8655b0",
"https://deno.land/std@0.166.0/fs/move.ts": "6d7fa9da60dbc7a32dd7fdbc2ff812b745861213c8e92ba96dace0669b0c378c",
"https://deno.land/std@0.166.0/fs/walk.ts": "0a754cc4696a15bdb175380a4b7deff3eb65be9768cb11d91a4138beee35c2d7",
"https://deno.land/std@0.166.0/io/buffer.ts": "245f1762a949082ddc0a6e9b15589d0be2d29c150266decd04320b8a8318f9f6",
"https://deno.land/std@0.166.0/io/types.d.ts": "107e1e64834c5ba917c783f446b407d33432c5d612c4b3430df64fc2b4ecf091",
"https://deno.land/std@0.166.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3",
"https://deno.land/std@0.166.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09",
"https://deno.land/std@0.166.0/path/_util.ts": "d16be2a16e1204b65f9d0dfc54a9bc472cafe5f4a190b3c8471ec2016ccd1677",
"https://deno.land/std@0.166.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633",
"https://deno.land/std@0.166.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee",
"https://deno.land/std@0.166.0/path/mod.ts": "56fec03ad0ebd61b6ab39ddb9b0ddb4c4a5c9f2f4f632e09dd37ec9ebfd722ac",
"https://deno.land/std@0.166.0/path/posix.ts": "6b63de7097e68c8663c84ccedc0fd977656eb134432d818ecd3a4e122638ac24",
"https://deno.land/std@0.166.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9",
"https://deno.land/std@0.166.0/path/win32.ts": "7cebd2bda6657371adc00061a1d23fdd87bcdf64b4843bb148b0b24c11b40f69",
"https://deno.land/std@0.166.0/testing/_diff.ts": "a23e7fc2b4d8daa3e158fa06856bedf5334ce2a2831e8bf9e509717f455adb2c",
"https://deno.land/std@0.166.0/testing/_format.ts": "cd11136e1797791045e639e9f0f4640d5b4166148796cad37e6ef75f7d7f3832",
"https://deno.land/std@0.166.0/testing/asserts.ts": "1e340c589853e82e0807629ba31a43c84ebdcdeca910c4a9705715dfdb0f5ce8",
"https://deno.land/x/cliffy@v0.25.4/_utils/distance.ts": "02af166952c7c358ac83beae397aa2fbca4ad630aecfcd38d92edb1ea429f004",
"https://deno.land/x/cliffy@v0.25.4/ansi/ansi.ts": "7f43d07d31dd7c24b721bb434c39cbb5132029fa4be3dd8938873065f65e5810",
"https://deno.land/x/cliffy@v0.25.4/ansi/ansi_escapes.ts": "885f61f343223f27b8ec69cc138a54bea30542924eacd0f290cd84edcf691387",
"https://deno.land/x/cliffy@v0.25.4/ansi/chain.ts": "31fb9fcbf72fed9f3eb9b9487270d2042ccd46a612d07dd5271b1a80ae2140a0",
"https://deno.land/x/cliffy@v0.25.4/ansi/colors.ts": "df8c48c5a6b6fa50ceea9e6dfd031bef7257a02fd564e4c18ed9890a206c42ee",
"https://deno.land/x/cliffy@v0.25.4/ansi/cursor_position.ts": "d537491e31d9c254b208277448eff92ff7f55978c4928dea363df92c0df0813f",
"https://deno.land/x/cliffy@v0.25.4/ansi/deps.ts": "73ade5630e81216ede16a2908937cf55134290bb1822220df20ce4ba2d1ad337",
"https://deno.land/x/cliffy@v0.25.4/ansi/mod.ts": "bb4e6588e6704949766205709463c8c33b30fec66c0b1846bc84a3db04a4e075",
"https://deno.land/x/cliffy@v0.25.4/ansi/tty.ts": "8fb064c17ead6cdf00c2d3bc87a9fd17b1167f2daa575c42b516f38bdb604673",
"https://deno.land/x/cliffy@v0.25.4/command/_errors.ts": "4fa6e1fa7d363a6ba20c401970da4634bca5a5352ece7005accc706a57407ae3",
"https://deno.land/x/cliffy@v0.25.4/command/_utils.ts": "833aa9152bd36a610860261a6c4a2a3be4c31dbc10c24d076e75d09a9fa50d39",
"https://deno.land/x/cliffy@v0.25.4/command/command.ts": "d51522506acad3a2424a7ba6d9dc98ccb622a68babcf152e116c0e104ad242bc",
"https://deno.land/x/cliffy@v0.25.4/command/completions/_bash_completions_generator.ts": "43b4abb543d4dc60233620d51e69d82d3b7c44e274e723681e0dce2a124f69f9",
"https://deno.land/x/cliffy@v0.25.4/command/completions/_fish_completions_generator.ts": "900b83033093b74814631717b56a3888da14436799a70366e10834230a0288d9",
"https://deno.land/x/cliffy@v0.25.4/command/completions/_zsh_completions_generator.ts": "adf33fd53b69bcb966dfc0a0c7141f542b18f1af56ec61038c80e7cd9614ec17",
"https://deno.land/x/cliffy@v0.25.4/command/completions/bash.ts": "053aa2006ec327ccecacb00ba28e5eb836300e5c1bec1b3cfaee9ddcf8189756",
"https://deno.land/x/cliffy@v0.25.4/command/completions/complete.ts": "58df61caa5e6220ff2768636a69337923ad9d4b8c1932aeb27165081c4d07d8b",
"https://deno.land/x/cliffy@v0.25.4/command/completions/fish.ts": "9938beaa6458c6cf9e2eeda46a09e8cd362d4f8c6c9efe87d3cd8ca7477402a5",
"https://deno.land/x/cliffy@v0.25.4/command/completions/mod.ts": "aeef7ec8e319bb157c39a4bab8030c9fe8fa327b4c1e94c9c1025077b45b40c0",
"https://deno.land/x/cliffy@v0.25.4/command/completions/zsh.ts": "8b04ab244a0b582f7927d405e17b38602428eeb347a9968a657e7ea9f40e721a",
"https://deno.land/x/cliffy@v0.25.4/command/deprecated.ts": "bbe6670f1d645b773d04b725b8b8e7814c862c9f1afba460c4d599ffe9d4983c",
"https://deno.land/x/cliffy@v0.25.4/command/deps.ts": "e57c24e1d4b44b2905cf168050a2a13dbb0642217e99098e49d9cb5ad28a4749",
"https://deno.land/x/cliffy@v0.25.4/command/help/_help_generator.ts": "10d0192727b97354e5fedca28418df94d9bee09253f3afe5196e1285c5e987cc",
"https://deno.land/x/cliffy@v0.25.4/command/help/mod.ts": "09d74d3eb42d21285407cda688074c29595d9c927b69aedf9d05ff3f215820d3",
"https://deno.land/x/cliffy@v0.25.4/command/mod.ts": "91a0487e7eafa2a292137cb3362ecdec4936358cd762182cddfe02be48ef16f0",
"https://deno.land/x/cliffy@v0.25.4/command/type.ts": "24e88e3085e1574662b856ccce70d589959648817135d4469fab67b9cce1b364",
"https://deno.land/x/cliffy@v0.25.4/command/types.ts": "e2a76044de0cbbb46f8beaf8dac50eae41c427ee4acbfd0248d887fb40e226d2",
"https://deno.land/x/cliffy@v0.25.4/command/types/action_list.ts": "33c98d449617c7a563a535c9ceb3741bde9f6363353fd492f90a74570c611c27",
"https://deno.land/x/cliffy@v0.25.4/command/types/boolean.ts": "3879ec16092b4b5b1a0acb8675f8c9250c0b8a972e1e4c7adfba8335bd2263ed",
"https://deno.land/x/cliffy@v0.25.4/command/types/child_command.ts": "f1fca390c7fbfa7a713ca15ef55c2c7656bcbb394d50e8ef54085bdf6dc22559",
"https://deno.land/x/cliffy@v0.25.4/command/types/command.ts": "325d0382e383b725fd8d0ef34ebaeae082c5b76a1f6f2e843fee5dbb1a4fe3ac",
"https://deno.land/x/cliffy@v0.25.4/command/types/enum.ts": "2178345972adf7129a47e5f02856ca3e6852a91442a1c78307dffb8a6a3c6c9f",
"https://deno.land/x/cliffy@v0.25.4/command/types/file.ts": "8618f16ac9015c8589cbd946b3de1988cc4899b90ea251f3325c93c46745140e",
"https://deno.land/x/cliffy@v0.25.4/command/types/integer.ts": "29864725fd48738579d18123d7ee78fed37515e6dc62146c7544c98a82f1778d",
"https://deno.land/x/cliffy@v0.25.4/command/types/number.ts": "aeba96e6f470309317a16b308c82e0e4138a830ec79c9877e4622c682012bc1f",
"https://deno.land/x/cliffy@v0.25.4/command/types/string.ts": "e4dadb08a11795474871c7967beab954593813bb53d9f69ea5f9b734e43dc0e0",
"https://deno.land/x/cliffy@v0.25.4/flags/_errors.ts": "f1fbb6bfa009e7950508c9d491cfb4a5551027d9f453389606adb3f2327d048f",
"https://deno.land/x/cliffy@v0.25.4/flags/_utils.ts": "340d3ecab43cde9489187e1f176504d2c58485df6652d1cdd907c0e9c3ce4cc2",
"https://deno.land/x/cliffy@v0.25.4/flags/_validate_flags.ts": "16eb5837986c6f6f7620817820161a78d66ce92d690e3697068726bbef067452",
"https://deno.land/x/cliffy@v0.25.4/flags/deprecated.ts": "a72a35de3cc7314e5ebea605ca23d08385b218ef171c32a3f135fb4318b08126",
"https://deno.land/x/cliffy@v0.25.4/flags/flags.ts": "68a9dfcacc4983a84c07ba19b66e5e9fccd04389fad215210c60fb414cc62576",
"https://deno.land/x/cliffy@v0.25.4/flags/mod.ts": "b21c2c135cd2437cc16245c5f168a626091631d6d4907ad10db61c96c93bdb25",
"https://deno.land/x/cliffy@v0.25.4/flags/types.ts": "7452ea5296758fb7af89930349ce40d8eb9a43b24b3f5759283e1cb5113075fd",
"https://deno.land/x/cliffy@v0.25.4/flags/types/boolean.ts": "b21be165b49b8517372361642cffaeaa4f4bb69637994a9762ceba642fe39676",
"https://deno.land/x/cliffy@v0.25.4/flags/types/integer.ts": "b60d4d590f309ddddf066782d43e4dc3799f0e7d08e5ede7dc62a5ee94b9a6d9",
"https://deno.land/x/cliffy@v0.25.4/flags/types/number.ts": "610936e2d29de7c8c304b65489a75ebae17b005c6122c24e791fbed12444d51e",
"https://deno.land/x/cliffy@v0.25.4/flags/types/string.ts": "e89b6a5ce322f65a894edecdc48b44956ec246a1d881f03e97bbda90dd8638c5",
"https://deno.land/x/cliffy@v0.25.4/keycode/key_code.ts": "b768c9227b8142cff3beb0a0bbe5d9119ba085c7f520f71799916f17d93a8daf",
"https://deno.land/x/cliffy@v0.25.4/keycode/key_codes.ts": "917f0a2da0dbace08cf29bcfdaaa2257da9fe7e705fff8867d86ed69dfb08cfe",
"https://deno.land/x/cliffy@v0.25.4/keycode/mod.ts": "292d2f295316c6e0da6955042a7b31ab2968ff09f2300541d00f05ed6c2aa2d4",
"https://deno.land/x/cliffy@v0.25.4/mod.ts": "e3515ccf6bd4e4ac89322034e07e2332ed71901e4467ee5bc9d72851893e167b",
"https://deno.land/x/cliffy@v0.25.4/prompt/_generic_input.ts": "65ed92d1f7ee616cc2926ae4d9b94445ac785fa6a6f584793e572dfcda8700eb",
"https://deno.land/x/cliffy@v0.25.4/prompt/_generic_list.ts": "85ab9aeb5b2288d9d4ef47ead6ea591bd1954ada113e3ff0d355b0670b576bad",
"https://deno.land/x/cliffy@v0.25.4/prompt/_generic_prompt.ts": "8b4a7d8c23a42cbdaa919fdb9b33b9eac33e5214a41202f5a8110ec988ee8e3c",
"https://deno.land/x/cliffy@v0.25.4/prompt/_generic_suggestions.ts": "42b9a8f6d447d0dde1b904c2fc9f47bb04da2cfa2670ade4f459b1ec306aa194",
"https://deno.land/x/cliffy@v0.25.4/prompt/_utils.ts": "676cca30762656ed1a9bcb21a7254244278a23ffc591750e98a501644b6d2df3",
"https://deno.land/x/cliffy@v0.25.4/prompt/checkbox.ts": "4e00e94efcd7a9917101f719564b3bf98a7aee0986bb004a4a75125081538b9d",
"https://deno.land/x/cliffy@v0.25.4/prompt/confirm.ts": "9de9fd0e51f939bac0c6a5758bf6c9aa438d5916de196761091d689c6f950cf0",
"https://deno.land/x/cliffy@v0.25.4/prompt/deps.ts": "12d5b88381ba80a3d6c173dea82e715b106087825602731d01322ea6499ba0d2",
"https://deno.land/x/cliffy@v0.25.4/prompt/figures.ts": "26af0fbfe21497220e4b887bb550fab997498cde14703b98e78faf370fbb4b94",
"https://deno.land/x/cliffy@v0.25.4/prompt/input.ts": "5c579a21150228528e81d219dab23503b5d497bb511ccad72c34db3d323c580f",
"https://deno.land/x/cliffy@v0.25.4/prompt/list.ts": "b13e05359ea98f058f950062814219d32d4cde131dd1cdc6e239814f6d321d98",
"https://deno.land/x/cliffy@v0.25.4/prompt/mod.ts": "195aed14d10d279914eaa28c696dec404d576ca424c097a5bc2b4a7a13b66c89",
"https://deno.land/x/cliffy@v0.25.4/prompt/number.ts": "65766e272f4fb96d35b3e6f54673987f81119315b2e843ae60516b064eb5ac04",
"https://deno.land/x/cliffy@v0.25.4/prompt/prompt.ts": "7752e9d37dc10e793b260971415e65bcb7d2b3b7b5a8e3279c6785e6bf24fa61",
"https://deno.land/x/cliffy@v0.25.4/prompt/secret.ts": "799986d32f0a7386f8502d42ccabfd1b9dc57d2189ac9457867d8ac64b5dcc19",
"https://deno.land/x/cliffy@v0.25.4/prompt/select.ts": "daf9db5a1c07e51c32a94313c9d29faf3b58ab4f547b5331cdcfa6b655e42be5",
"https://deno.land/x/cliffy@v0.25.4/prompt/toggle.ts": "16a8aa3f4f22db7d4705cd263569d547b6540c53b057e64a4c4028b610dd1920",
"https://deno.land/x/cliffy@v0.25.4/table/border.ts": "2514abae4e4f51eda60a5f8c927ba24efd464a590027e900926b38f68e01253c",
"https://deno.land/x/cliffy@v0.25.4/table/cell.ts": "1d787d8006ac8302020d18ec39f8d7f1113612c20801b973e3839de9c3f8b7b3",
"https://deno.land/x/cliffy@v0.25.4/table/deps.ts": "e61aab0abd205058aba0e6a74ee9f25dd2f4127d41c8cc41146c7a81b5bc6a81",
"https://deno.land/x/cliffy@v0.25.4/table/layout.ts": "46bf10ae5430cf4fbb92f23d588230e9c6336edbdb154e5c9581290562b169f4",
"https://deno.land/x/cliffy@v0.25.4/table/mod.ts": "e74f69f38810ee6139a71132783765feb94436a6619c07474ada45b465189834",
"https://deno.land/x/cliffy@v0.25.4/table/row.ts": "5f519ba7488d2ef76cbbf50527f10f7957bfd668ce5b9169abbc44ec88302645",
"https://deno.land/x/cliffy@v0.25.4/table/table.ts": "ec204c9d08bb3ff1939c5ac7412a4c9ed7d00925d4fc92aff9bfe07bd269258d",
"https://deno.land/x/cliffy@v0.25.4/table/utils.ts": "187bb7dcbcfb16199a5d906113f584740901dfca1007400cba0df7dcd341bc29",
"https://deno.land/x/code_block_writer@11.0.3/mod.ts": "2c3448060e47c9d08604c8f40dee34343f553f33edcdfebbf648442be33205e5",
"https://deno.land/x/code_block_writer@11.0.3/utils/string_utils.ts": "60cb4ec8bd335bf241ef785ccec51e809d576ff8e8d29da43d2273b69ce2a6ff",
"https://deno.land/x/denoflate@1.2.1/mod.ts": "f5628e44b80b3d80ed525afa2ba0f12408e3849db817d47a883b801f9ce69dd6",
"https://deno.land/x/denoflate@1.2.1/pkg/denoflate.js": "b9f9ad9457d3f12f28b1fb35c555f57443427f74decb403113d67364e4f2caf4",
"https://deno.land/x/denoflate@1.2.1/pkg/denoflate_bg.wasm.js": "d581956245407a2115a3d7e8d85a9641c032940a8e810acbd59ca86afd34d44d",
"https://deno.land/x/denomander@0.9.3/deps.ts": "ee3eaf845a9837e38bfd660fd3521c85b3decc5f264b7c6e474627a46f87e9bf",
"https://deno.land/x/denomander@0.9.3/mod.ts": "eb4b69cb286079982ac85c30591a2311047441f2bc2c9ad137f738843933965a",
"https://deno.land/x/denomander@0.9.3/src/Arguments.ts": "597037e58244baa1d9acb216da77913d3a4e9885fafadc76929155a4f0a74298",
"https://deno.land/x/denomander@0.9.3/src/Command.ts": "f27085b553809674dec027ffd5b8f4470730af8186856850ee9689c48cd0c095",
"https://deno.land/x/denomander@0.9.3/src/CustomOption.ts": "22316399f71ce584d36e242643113456cf7d93b195b4667a3cf4c1e20c8847ae",
"https://deno.land/x/denomander@0.9.3/src/Denomander.ts": "597491b5bfbb653ae5e05d0307cfb0c733615e7dbc3322b7da36523dd306ebd6",
"https://deno.land/x/denomander@0.9.3/src/Executor.ts": "fa3a1132981369a97636af17139a316885e05810806498daf15a8197b0f032eb",
"https://deno.land/x/denomander@0.9.3/src/Kernel.ts": "7800e95588c341ee46019991453f60e54e850a2d6293dbd81dfca3b212d2db47",
"https://deno.land/x/denomander@0.9.3/src/Option.ts": "a272450bb3e814ee2ef1776f75c595e50230c3f56fd16c85809c122979dbf492",
"https://deno.land/x/denomander@0.9.3/src/Validator.ts": "b7f56a2bd773ab52394bf0d7d8b47379331eead2dcd1282062c045bec215a020",
"https://deno.land/x/denomander@0.9.3/src/printer/Printer.ts": "ff4b25a2c734322ea60ce43a7c66f39e28bb0b32ca105bcdf78e5741d0ecab60",
"https://deno.land/x/denomander@0.9.3/src/printer/colors.ts": "ba785bf6a5975200e29fd120e34a78cf192b43fd25deed3b2516c05f833fc941",
"https://deno.land/x/denomander@0.9.3/src/types/interfaces.ts": "1a64640a774f6a6a0c4f23aa3886b5e19acd07da7b72fa5365e3cd208457c704",
"https://deno.land/x/denomander@0.9.3/src/types/types.ts": "8c575c785e522269e454f6130aea764d829d581566b06fc1fc87e3fce3779856",
"https://deno.land/x/denomander@0.9.3/src/utils/detect.ts": "e20b93554e8d87126a0a813c247a53b8781c6a65bbd1ca0cd6526567e84f878a",
"https://deno.land/x/denomander@0.9.3/src/utils/find.ts": "0a74d7a081a0c97ded180e5ce728bd1b156e7aaf67116713ddc4abe545e44ded",
"https://deno.land/x/denomander@0.9.3/src/utils/print.ts": "6d6a6d86f14ced800bb1c49eed2d2ea20f5f33a922aba60659e221b4a7e942ff",
"https://deno.land/x/denomander@0.9.3/src/utils/remove.ts": "e80f1d257f76cbcafafc855debe7274c59db319639b51aca63a63003e8cf1118",
"https://deno.land/x/denomander@0.9.3/src/utils/set.ts": "a89fe0f27575cecd5f5fdaa6907f13a387a03c83b3ef66fd317d114f4dc0fe3e",
"https://deno.land/x/denomander@0.9.3/src/utils/utils.ts": "fc29c3b267065685c45d24b3e597e67bee94b2b9d68b5739625051358fef541e",
"https://deno.land/x/elasticsearch@v8.3.3/deps.ts": "18920291f3b1d48f1a10d462b5b4ab79e20aa630c43814c25cff028935018fa2",
"https://deno.land/x/elasticsearch@v8.3.3/mod.ts": "c012c590c515ed56078bb1583e4488b5dffa7b7efe41900b4f9407787de18807",
"https://deno.land/x/elasticsearch@v8.3.3/src/client.ts": "9396ca210678ce39f8a3a10a1667bfd82948fd00cad937906907f74a21a46f42",
"https://deno.land/x/elasticsearch@v8.3.3/src/helpers/mod.ts": "520d8cca6906cdd34f795b57b1975a5bb729c8937a0cf1e7be142686075c2bb6",
"https://deno.land/x/elasticsearch@v8.3.3/src/helpers/request.ts": "6ba039199f9958ca1b972f08517fd963987cdbb94bddf0fe8bd6125feb0b9b75",
"https://deno.land/x/elasticsearch@v8.3.3/src/helpers/serializer.ts": "d1a402ca489335c439fe9d5b58d3c0879cb993b02ef86416a0c398a1cad38bda",
"https://deno.land/x/elasticsearch@v8.3.3/src/rest/cat.ts": "d3f31d96951ac8ebf538a9d60b71c4d133c38c273d3ab56e1e3da882b8d86590",
"https://deno.land/x/elasticsearch@v8.3.3/src/rest/cluster.ts": "afbde8f1b49f95d18e785978bf105a9f2e53e0d3834a1e9d589bbb77bb37f1c8",
"https://deno.land/x/elasticsearch@v8.3.3/src/rest/documents.ts": "069704e06db6736c6b29a51dc25ec05bca71bd7f3d4bb0f52390eb92714ca3f9",
"https://deno.land/x/elasticsearch@v8.3.3/src/rest/indices.ts": "8678c1cbffbb54c336f266fd6ff5a1a9b078cfd43938fa2a1fda003af2f0c372",
"https://deno.land/x/elasticsearch@v8.3.3/src/rest/rest.ts": "983a0b0f8456d1e751d4bd27284d9a85060beccc4e8300f100a08f30d72530b8",
"https://deno.land/x/elasticsearch@v8.3.3/src/rest/sql.ts": "218e3f6a7780ff773dbcb9c1cc67ae02a52eea5b1bf1e2a6a06b41feb68974ca",
"https://deno.land/x/elasticsearch@v8.3.3/src/types.d.ts": "2e79495e7097d9da14ae284b7ca5d61c5e977c3304309330d6662b4efc51d6ce",
"https://deno.land/x/esbuild@v0.14.51/mod.d.ts": "c142324d0383c39de0d7660cd207a7f7f52c7198a13d7d3281c0d636a070f441",
"https://deno.land/x/esbuild@v0.14.51/mod.js": "7432566c71fac77637822dc230319c7392a2d2fef51204c9d12c956d7093c279",
"https://deno.land/x/esbuild@v0.14.51/wasm.d.ts": "c142324d0383c39de0d7660cd207a7f7f52c7198a13d7d3281c0d636a070f441",
@ -92,6 +346,16 @@
"https://deno.land/x/fresh@1.1.2/src/server/types.ts": "dde992ab4ee635df71a7fc96fe4cd85943c1a9286ea8eb586563d5f5ca154955",
"https://deno.land/x/importmap@0.2.1/_util.ts": "ada9a9618b537e6c0316c048a898352396c882b9f2de38aba18fd3f2950ede89",
"https://deno.land/x/importmap@0.2.1/mod.ts": "ae3d1cd7eabd18c01a4960d57db471126b020f23b37ef14e1359bbb949227ade",
"https://deno.land/x/progress@v1.3.0/deps.ts": "83050e627263931d853ba28b7c15c80bf4be912bea7e0d3d13da2bc0aaf7889d",
"https://deno.land/x/progress@v1.3.0/mod.ts": "de6a75f14964a870facb51b902d39d7fa391e2b4281af062c5c4525af0fa6796",
"https://deno.land/x/progress@v1.3.0/multi.ts": "8cd7c2df6b00148fa0cd60554693b337d85e95a823f40b7c1ec2ba0d301263db",
"https://deno.land/x/progress@v1.3.4/deps.ts": "83050e627263931d853ba28b7c15c80bf4be912bea7e0d3d13da2bc0aaf7889d",
"https://deno.land/x/progress@v1.3.4/mod.ts": "ca65cf56c63d48ac4806f62a6ee5e5889dc19b8bd9a3be2bfeee6c8c4a483786",
"https://deno.land/x/progress@v1.3.4/multi.ts": "755f05ce3d1f859142c6a1e67972f8765ee29eac7bfdec8126008c312addbeef",
"https://deno.land/x/progress@v1.3.4/time.ts": "e7ab1975dadf519c8881a333cbc661d6048da2b1c2f4a7d3e995065d53340144",
"https://deno.land/x/progressbar@v0.2.0/progressbar.ts": "d571c5505c2afd792d729f2467a017dd3a108c82ecb4421280fa86eec6d25a05",
"https://deno.land/x/progressbar@v0.2.0/styles.ts": "2ba8cfb41688c0ca497ed740bda342f55e629043397eef43180665aa34ef2f01",
"https://deno.land/x/progressbar@v0.2.0/widgets.ts": "73aa6d06b6a89a4dfd8d15e97ca634bc1e82c7993cd95ba56459f900d2e02838",
"https://deno.land/x/rutt@0.0.13/mod.ts": "af981cfb95131152bf50fc9140fc00cb3efb6563df2eded1d408361d8577df20",
"https://deno.land/x/ts_morph@16.0.0/common/DenoRuntime.ts": "537800e840d0994f9055164e11bf33eadf96419246af0d3c453793c3ae67bdb3",
"https://deno.land/x/ts_morph@16.0.0/common/mod.ts": "01985d2ee7da8d1caee318a9d07664774fbee4e31602bc2bb6bb62c3489555ed",

1
dev.ts
View File

@ -1,5 +1,6 @@
#!/usr/bin/env -S deno run -A --watch=static/,routes/
import dev from "$fresh/dev.ts";
//import "https://deno.land/std@0.162.0/dotenv/load.ts";
await dev(import.meta.url, "./main.ts");

15
doc_load/load.test.ts Normal file
View File

@ -0,0 +1,15 @@
import { assertEquals } from "std/testing/asserts.ts";
import { fromFileUrl, join } from "std/path/mod.ts";
import { readDoc } from "./load.ts";
Deno.test("readDoc", async () => {
let path = fromFileUrl(import.meta.url)
path = join(path,"../mysample.md");
const doc = await readDoc(path, true);
assertEquals(doc.name, "aws-cdk");
assertEquals(doc.star, 9537);
assertEquals(doc.fork, 2905);
assertEquals(doc.desc, "The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code");
assertEquals(doc.url, "https://github.com/aws/aws-cdk");
assertEquals(doc.tags, ['aws', 'typescript', 'cloud-infrastructure', 'infrastructure-as-code']);
});

135
doc_load/load.ts Normal file
View File

@ -0,0 +1,135 @@
import {parse as parseYaml, stringify} from "https://deno.land/std@0.166.0/encoding/yaml.ts";
function trimSubstring(str: string, start: number, end: number) {
while (str[start] === ' ' || str[start] === '\t' || str[start] === '\r' || str[start] === '\n') {
start++;
}
return str.substring(start, end);
}
function splitTwo(str: string, separator: string): [string, string] {
const index = str.indexOf(separator);
if (index === -1) {
return [str, ''];
}
return [str.substring(0, index), str.substring(index + separator.length)];
}
export interface Doc {
from_url?: string;
name: string;
author: string;
star: number;
fork: number;
desc: string;
url: string;
tags: string[];
readme: string;
}
export class DocParser {
constructor() {
}
parse(content: string) {
if(!content.startsWith('---')){
throw new Error('Invalid doc format');
}
const index = content.indexOf('\n---', 3);
const meta = content.substring(3, index);
const readme = trimSubstring(content, index + 4, content.length);
const doc = parseYaml(meta) as Doc;
doc.readme = readme;
return doc;
}
parseAlternative(content: string): Doc {
if(!content.startsWith('---')){
throw new Error('Invalid doc format');
}
const index = content.indexOf('\n---', 3);
const meta = content.substring(3, index);
const readme = trimSubstring(content, index + 4, content.length);
const doc = {} as Doc;
const lines = meta.split('\n').map(line => line.trim());
for(const line of lines){
if(line.length === 0) continue;
let [key, value] = splitTwo(line, ':');
value = value.trimStart();
if (value.startsWith('"') && value.endsWith('"')) {
value = JSON.parse( value );
}
key = key.trimEnd();
switch(key){
case 'name':
doc.name = value;
break;
case 'author':
doc.author = value;
break;
case 'star':
doc.star = parseInt(value);
break;
case 'fork':
doc.fork = parseInt(value);
break;
case 'desc':
doc.desc = value;
break;
case 'url':
doc.url = value;
break;
case 'tags':
doc.tags = JSON.parse(value.replaceAll("'",'"'));
break;
case 'from_url':
doc.from_url = value;
break;
default:
throw new Error(`Invalid key: ${key}`);
}
}
doc.readme = readme;
return doc;
}
}
export async function readDoc(path: string, alternative: boolean = false): Promise<Doc> {
const doc = await Deno.readTextFile(path);
const parser = new DocParser();
if(alternative){
return parser.parseAlternative(doc);
}
return parser.parse(doc);
}
function genDocContent(doc: Doc): string {
return `---
${doc.from_url ? `from_url: ${doc.from_url}\n` : ''}name: "${doc.name}"
author: "${doc.author}"
star: ${doc.star}
fork: ${doc.fork}
desc: ${JSON.stringify(doc.desc)}
url: ${doc.url}
tags: ${JSON.stringify(doc.tags)}
---
${doc.readme}
`;
}
export async function writeDoc(path: string, doc: Doc, options?: Omit<Deno.WriteFileOptions, "append">) {
const content = genDocContent(doc);
await Deno.writeTextFile(path, content, options);
}
async function main() {
const doc = await readDoc('./mysample.md');
console.log(stringify(doc as any));
const doc2 = await readDoc('./mysample.md', true);
console.log(stringify(doc2 as any));
console.log(genDocContent(doc2));
}
if (import.meta.main) {
await main();
}

11
doc_load/mysample.md Normal file
View File

@ -0,0 +1,11 @@
---
from_url: https://github.com/donnemartin/awesome-aws
name: aws-cdk
author: "0x0d"
star: 9537
fork: 2905
desc: "The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code"
tags: ['aws', 'typescript', 'cloud-infrastructure', 'infrastructure-as-code']
url: https://github.com/aws/aws-cdk
---
read

View File

@ -5,19 +5,25 @@
import config from "./deno.json" assert { type: "json" };
import * as $0 from "./routes/api/_list.ts";
import * as $1 from "./routes/api/_query.ts";
import * as $2 from "./routes/index.tsx";
import * as $2 from "./routes/dynamic.tsx";
import * as $3 from "./routes/index.tsx";
import * as $$0 from "./islands/Counter.tsx";
import * as $$1 from "./islands/RepoViewer.tsx";
import * as $$1 from "./islands/MySearchBar.tsx";
import * as $$2 from "./islands/RepoViewer.tsx";
import * as $$3 from "./islands/Search.tsx";
const manifest = {
routes: {
"./routes/api/_list.ts": $0,
"./routes/api/_query.ts": $1,
"./routes/index.tsx": $2,
"./routes/dynamic.tsx": $2,
"./routes/index.tsx": $3,
},
islands: {
"./islands/Counter.tsx": $$0,
"./islands/RepoViewer.tsx": $$1,
"./islands/MySearchBar.tsx": $$1,
"./islands/RepoViewer.tsx": $$2,
"./islands/Search.tsx": $$3,
},
baseUrl: import.meta.url,
config,

View File

@ -7,6 +7,9 @@
"@preact/signals": "https://esm.sh/*@preact/signals@1.0.3",
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.0.1",
"twind": "https://esm.sh/twind@0.16.17",
"twind/": "https://esm.sh/twind@0.16.17/"
"twind/": "https://esm.sh/twind@0.16.17/",
"cliffy": "https://deno.land/x/cliffy@v0.25.4/mod.ts",
"std/": "https://deno.land/std@0.166.0/"
}
}

12
islands/MySearchBar.tsx Normal file
View File

@ -0,0 +1,12 @@
import { useState } from "preact/hooks";
import { SearchBar } from "../components/SearchBar.tsx";
export default function MySearch({query}: {query?: string}) {
const [searchValue, setSearchValue] = useState(query ?? "");
return (
<SearchBar value={searchValue} onChange={(v) => {setSearchValue(v)}} onSubmit={()=>{
window.location.href = `/?q=${searchValue}`;
}} />);
}

View File

@ -18,7 +18,7 @@ function RepoItem(props: RepoData) {
const opacity = useRelativeTopOppacity({elem: ref});
const { name, description, url, author, stars, tags, forks } = props;
return (
<div ref={ref} class="flex flex-col bg-white rounded transition-opacity"
<div ref={ref} class="flex flex-col bg-white rounded"
style={`opacity: ${opacity}`}>
<div class="flex flex-col flex-grow p-4">
<a class="text-xl font-bold text-gray-900 hover:text-gray-700 flex-auto"

67
islands/Search.tsx Normal file
View File

@ -0,0 +1,67 @@
import { useEffect, useState } from "preact/hooks";
import { RepoData } from "../api/repo.ts";
import { SearchBar } from "../components/SearchBar.tsx";
import RepoViewer from "./RepoViewer.tsx";
export default function Search(props:{query?: string}) {
const [searchValue, setSearchValue] = useState(props.query ?? "");
const [searchResults, setSearchResults] = useState<RepoData[] | null>(null);
useEffect(() => {
// on mount
search(searchValue);
}, [])
useEffect(() => {
const callback = (ev: PopStateEvent)=>{
// pop state
if(ev.state && ev.state.q){
const q = ev.state.q;
setSearchValue(q);
search(q);
}
else{
setSearchValue("");
search("");
}
}
addEventListener("popstate", callback);
return ()=>{
removeEventListener("popstate", callback);
}
}, []);
useEffect(() => {
if (searchValue) {
document.title = `Search: ${searchValue}`;
} else {
document.title = "Search";
}
},[searchValue]);
return (<>
<SearchBar value={searchValue} onChange={(v) => {setSearchValue(v)}} onSubmit={()=>{
//window.location.href = `/?q=${searchValue}`;
history.pushState({q:searchValue}, "", `/?q=${searchValue}`);
search(searchValue);
}} />
<RepoViewer repos={searchResults ?? []} />
</>);
function search(searchValue: string) {
if (searchValue) {
console.log("searching", searchValue);
fetch(`/api/_query?q=${searchValue}`)
.then((res) => res.json())
.then((data) => {
setSearchResults(data);
}
);
} else {
fetch(`/api/_list`)
.then((res) => res.json())
.then((data) => {
setSearchResults(data);
}
);
}
}
}

View File

@ -1,10 +1,13 @@
import { HandlerContext } from "$fresh/server.ts";
import { SAMPLE_DATA, RepoData } from "../../api/repo.ts";
import { HandlerContext, Handlers } from "$fresh/server.ts";
import { SAMPLE_DATA, RepoData, searchRepos, getRepos } from "../../api/repo.ts";
export const handler = (_req: Request, _ctx: HandlerContext): Response => {
return new Response(JSON.stringify(SAMPLE_DATA), {
headers: {
"content-type": "application/json",
},
});
export const handler: Handlers = {
async GET(_req, _ctx) {
const repos = await getRepos();
return new Response(JSON.stringify(repos), {
headers: {
"content-type": "application/json",
},
});
},
};

View File

@ -1,10 +1,18 @@
import { HandlerContext } from "$fresh/server.ts";
import { SAMPLE_DATA, RepoData } from "../../api/repo.ts";
import { Handlers } from "$fresh/server.ts";
import { searchRepos, getRepos } from "../../api/repo.ts";
export const handler = (_req: Request, _ctx: HandlerContext): Response => {
return new Response(JSON.stringify(SAMPLE_DATA), {
headers: {
"content-type": "application/json",
},
});
};
export const handler: Handlers = {
async GET(req, _ctx) {
const url = new URL(req.url);
const q = url.searchParams.get("q");
const repos = q != null ? await searchRepos(q, {
limit: 10,
offset: 0
}) : await getRepos();
return new Response(JSON.stringify(repos), {
headers: {
"content-type": "application/json",
},
});
}
}

30
routes/dynamic.tsx Normal file
View File

@ -0,0 +1,30 @@
import { Head } from "$fresh/runtime.ts";
import { Handlers, PageProps } from "$fresh/server.ts";
import { RepoData, getRepos, searchRepos } from "../api/repo.ts";
import { useState } from "preact/hooks";
import { SearchBar } from "../components/SearchBar.tsx";
import RepoViewer from "../islands/RepoViewer.tsx";
import Search from "../islands/Search.tsx";
export const handler: Handlers = {
GET: (req, ctx) => {
const url = new URL(req.url);
const searchParams = url.searchParams;
const query = searchParams.get("q");
return ctx.render({query})
},
};
export default function Home({ data }: PageProps<{query?: string}>) {
return (
<>
<Head>
<title>Search Github Awesome App</title>
</Head>
<div class="p-4 mx-auto max-w-screen-md">
<h1 class="text-4xl font-bold">Search Github Awesome App</h1>
<Search query={data.query}></Search>
</div>
</>
);
}

View File

@ -4,29 +4,27 @@ import { RepoData, getRepos, searchRepos } from "../api/repo.ts";
import { useState } from "preact/hooks";
import { SearchBar } from "../components/SearchBar.tsx";
import RepoViewer from "../islands/RepoViewer.tsx";
import Search from "../islands/Search.tsx";
import MySearch from "../islands/MySearchBar.tsx";
export const handler: Handlers<RepoData[] | null> = {
async GET(req, ctx) {
try {
const url = new URL(req.url);
const query = url.searchParams.get("q");
if (query) {
const repos = await searchRepos(query);
return ctx.render(repos);
}
else {
const repos = await getRepos();
return ctx.render(repos);
}
} catch (error) {
console.error(error);
return ctx.render(null);
export const handler: Handlers = {
GET: async(req, ctx) => {
const url = new URL(req.url);
const searchParams = url.searchParams;
const query = searchParams.get("q");
if(query){
const data = await searchRepos(query);
return ctx.render({repos:data, query})
}
}
}
else{
const data = await getRepos();
return ctx.render({repos:data, query: ""})
}
},
};
export default function Home({ data }: PageProps<{repos: RepoData[], query: string}>) {
export default function Home({ data }: PageProps<RepoData[] | null>) {
const [searchValue, setSearchValue] = useState("");
return (
<>
<Head>
@ -34,8 +32,8 @@ export default function Home({ data }: PageProps<RepoData[] | null>) {
</Head>
<div class="p-4 mx-auto max-w-screen-md">
<h1 class="text-4xl font-bold">Search Github Awesome App</h1>
<SearchBar value={searchValue} onChange={() => { }} />
<RepoViewer repos={data || []} />
<MySearch query={data.query}></MySearch>
<RepoViewer repos={data.repos ?? []} />
</div>
</>
);

View File

@ -60,7 +60,7 @@ export function useRelativeTopOppacity({elem}:{elem: RefObject<Element>}) {
if (intersect >= 0) {
let v = Math.min(Math.max(intersect, 0), 1);
v *= 4/3;
//v *= 4/3;
v = Math.min(Math.max(v, 0), 1);
setOpacity(v);
}

136
validator.ts Normal file
View File

@ -0,0 +1,136 @@
import { Command } from "cliffy";
import { DocParser, readDoc, writeDoc, Doc } from "./doc_load/load.ts";
import { expandGlob } from "https://deno.land/std@0.166.0/fs/mod.ts";
import ProgressBar from "https://deno.land/x/progress@v1.3.4/mod.ts";
function checkAndPrint(doc: Doc, another: Doc): [boolean, string[]] {
const diffs = [];
if (doc.name !== another.name) {
diffs.push(`name: ${doc.name} => ${another.name}`);
}
if (doc.author !== another.author) {
diffs.push(`author: ${doc.author} => ${another.author}`);
}
if (doc.star !== another.star) {
diffs.push(`star: ${doc.star} => ${another.star}`);
}
if (doc.fork !== another.fork) {
diffs.push(`fork: ${doc.fork} => ${another.fork}`);
}
if (doc.desc !== another.desc) {
diffs.push(`desc: "${doc.desc}" => ${another.desc}`);
}
if (doc.url !== another.url) {
diffs.push(`url: ${doc.url} => ${another.url}`);
}
if (doc.tags.length !== another.tags.length) {
diffs.push(`tags: ${doc.tags} => ${another.tags}`);
}
else {
doc.tags = doc.tags.sort();
another.tags = another.tags.sort();
for (let i = 0; i < doc.tags.length; i++) {
if (doc.tags[i] !== another.tags[i]) {
diffs.push(`tags: ${doc.tags} => ${another.tags}`);
break;
}
}
}
if (doc.readme !== another.readme) {
diffs.push(`readme: ${doc.readme} => ${another.readme}`);
}
if (doc.from_url !== another.from_url) {
diffs.push(`from_url: ${doc.from_url} => ${another.from_url}`);
}
return [diffs.length === 0, diffs];
}
async function validateDoc(path: string, parser: DocParser, fix?: boolean, log = console.log): Promise<void> {
try {
const content = await Deno.readTextFile(path);
const doc = parser.parseAlternative(content);
if (fix) {
await writeDoc(path, doc);
}
else {
try {
parser.parse(content);
const another = parser.parse(content);
const [isSame, errors] = checkAndPrint(doc, another);
if (!isSame) {
log(`File ${path} is not valid.`);
for (const error of errors) {
log("\t",error);
}
}
}
catch (e) {
if ( e instanceof Error) {
log(`File ${path} is not valid. error: ${e.name}`);
}
else {
throw e;
}
}
}
} catch (error) {
log(`File ${path} is not valid. error: ${error.name}`);
throw error;
}
}
if(import.meta.main){
const app = new Command()
.name("validator")
.version("0.1.0")
.description("Validate and fix the doc files in the sample directory. glob is supported.")
.option("-v, --verbose", "Enable verbose mode.")
.option("-f, --fix", "Fix the doc files.")
.option("-p, --progress", "Show progress.")
.arguments("[pathes...:string]")
.action(async (options, ...pathes) => {
const { verbose, fix, progress } = options;
const parser = new DocParser();
if(pathes.length === 0){
console.log("No pathes specified. Use --help to see the usage.");
Deno.exit(1);
}
if (verbose) {
console.log("Verbose mode enabled.");
}
if (progress) {
console.log("Progress mode enabled.");
const targets = (await Promise.all(pathes.map(async (path) => {
const paths = [];
for await (const entry of expandGlob(path)) {
paths.push(entry.path);
}
return paths;
}))).flat();
const bar = new ProgressBar({
total: targets.length,
title: "Validating",
});
let count = 0;
for (const path of targets) {
await validateDoc(path, parser, fix, verbose ? (...args)=>{
bar.console(args.join(" "));
} : () => { });
bar.render(++count);
}
bar.end();
}
else {
for (const path of pathes) {
for await (const dir of expandGlob(path)) {
if (verbose) {
console.log(`Processing ${dir.path}`);
}
validateDoc(dir.path, parser, fix);
}
}
}
});
await app.parse(Deno.args);
}