DenReg/registry/src/views/_browse.tsx

114 lines
2.8 KiB
TypeScript

/// <reference path="../types/jsx.d.ts" />
import { React, Marked } from "../deps.ts";
import type { IPackage } from "../db.ts";
import { sortVersions } from "../utils.ts";
import Prism from "../vendor/prism.ts";
interface IEntryParams {
name: string;
size?: number;
directory?: true;
}
export function Entry({ name, size, directory }: IEntryParams) {
return (
<a class="browse-list-item" href={"./" + name + (directory ? "/" : "")}>
<img src={directory ? "/public/folder.svg" : "/public/file.svg"} />
<span>{name}</span>
{size && <span class="browse-list-item-size">{size}</span>}
</a>
);
}
interface IEntryListParams {
files: { name: string; size: number }[];
directories: { name: string }[];
}
export function EntryList({ directories, files }: IEntryListParams) {
return (
<div class="card" style="padding: 1rem;">
<div>
{directories.map((e) => (
<Entry name={e.name} directory />
))}
{files.map((e) => (
<Entry name={e.name} size={e.size} />
))}
</div>
</div>
);
}
interface IRenderFileInterface {
content: string;
ext: string;
}
const languages: { [key: string]: string } = {
js: "javascript",
cjs: "javascript",
mjs: "javascript",
ts: "typescript",
c: "clike",
svelte: "html",
cs: "csharp",
hb: "handlebars",
ps: "powershell",
sh: "bash",
bat: "batch",
yml: "yaml",
};
export function RenderFile({ content, ext }: IRenderFileInterface) {
if (ext === ".md") {
content = Marked.parse(content).content;
return (
<div
class="card browse-code-block"
style="margin-top: 1rem; padding: 1rem;"
innerHTML={content}
/>
);
} else {
let lang = languages[ext.replace(".", "")] || ext.replace(".", "");
if (Prism.languages[lang]) {
content = Prism.highlight(content, Prism.languages[lang], lang);
}
return <pre innerHTML={content} />;
}
}
interface IBrowseHeaderParams {
pkg: IPackage;
version?: string;
path: string;
}
export function BrowseHeader({ pkg, version, path }: IBrowseHeaderParams) {
return (
<>
<div style="display: flex;">
<div>
<h2 style="margin-bottom: 0">Browse: {pkg.name}</h2>
<h4 class="text-muted" style="margin-top: 0; margin-left: .5rem">
By {pkg.owner}
</h4>
</div>
<div>
Version:
<select>
{pkg.versions.sort(sortVersions).map((v) => (
<option selected={version === v}>{v}</option>
))}
</select>
</div>
</div>
<div class="browse-path">{path}</div>
</>
);
}