Compare commits

40 Commits

Author SHA1 Message Date
ae69bcd48e The official image does not support arm and building it yourself is garbage, so some random image from docker hub is used. Great Work
All checks were successful
CI / build (push) Successful in 52s
2023-11-28 16:47:09 +01:00
675a73e551 Add CI
All checks were successful
CI / build (push) Successful in 51s
2023-11-28 16:14:45 +01:00
310c8e12fa Merge branch 'master' of https://git.stamm.me/Deno/DenReg 2023-11-28 16:12:49 +01:00
a14a5b9462 Make it modern 2023-11-28 16:10:33 +01:00
a0fef1ef76 Improve upgrade script
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-28 12:20:30 +02:00
3cda4ee8c8 Improve upgrade script
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-28 12:16:50 +02:00
e5829d9a4f Add script running abilities
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-28 11:47:52 +02:00
3efe4fc34e Add dpm alias 2021-04-28 11:19:29 +02:00
22a447604b Update to work with newer deno versions
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-15 17:20:09 +02:00
9dfb8d65d3 Add support for intellisense imports for the vscode extension
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-15 02:32:51 +01:00
6bc090e51b Fix dockerfile
Some checks failed
continuous-integration/drone/push Build is failing
2021-01-11 15:38:44 +01:00
965ca33d33 Improve startup speed
Some checks failed
continuous-integration/drone/push Build is failing
2021-01-11 15:37:06 +01:00
0202946813 Implement fragment support
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-11 15:32:47 +01:00
53a11eccf6 Fix tsconfig wrong path
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-11 15:24:00 +01:00
325c1a4d7d Add tsconfig to docker
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-11 15:20:37 +01:00
c718e8898d Change import
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-11 15:10:43 +01:00
6fe3ddbd37 Many improvements
Some checks failed
continuous-integration/drone/push Build is failing
2021-01-11 15:06:02 +01:00
79bcef0698 Remove unused console output 2021-01-11 15:05:03 +01:00
2af5d4f823 Move to own JSX implementation
Some checks failed
continuous-integration/drone/push Build is failing
2021-01-11 14:55:54 +01:00
7c1166bf87 Update dependencies
Some checks failed
continuous-integration/drone/push Build is failing
2021-01-04 22:57:14 +01:00
639287663d Remove useless log output
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-27 03:23:49 +01:00
fbbb66d5af Add option to add tracking to denreg
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-27 03:16:57 +01:00
df1f4965ad Switch src image to new registry
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-19 19:06:29 +01:00
10930db13d Change registry
Some checks failed
continuous-integration/drone/push Build is failing
2020-12-19 19:02:24 +01:00
6b88be1b18 Add content type to registry using filenames
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-21 02:40:55 +02:00
c9bd5c7d18 Adding support for readme field in meta.json to registry
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-19 21:10:53 +02:00
d1244ac0a7 A few SEO
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 22:34:57 +02:00
e56d8b4548 Add prism.css to public folder instead of unpkg
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 22:20:50 +02:00
ed1ce0cc0f Improving update support
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 22:04:18 +02:00
252bf4aac3 Remove logging output
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 21:47:09 +02:00
a3a7370be0 Add log
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 17:51:49 +02:00
10a7c26642 Configurable region
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 17:44:36 +02:00
7e821f9771 Updating dependencies
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 17:07:51 +02:00
1b7c4847dc Add s3 error output
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 16:48:27 +02:00
2194bf199e Add debug output
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 16:34:26 +02:00
f3f6f0d7bc Add ability to add root folder to meta.json (only affects upload) 2020-10-14 16:34:18 +02:00
13bc1b07cd Fixing dockerfile
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 02:58:00 +02:00
1b2d85eeef Adding hotfixes for packages
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-14 02:56:11 +02:00
46d8f8b289 Adding basic file browsing support
Some checks failed
continuous-integration/drone/push Build is failing
2020-10-14 02:52:02 +02:00
78c40e4819 [CLI] Add help message when no subcommand is specified
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-15 11:40:25 +02:00
101 changed files with 4276 additions and 276 deletions

View File

@ -12,7 +12,7 @@ steps:
from_secret: docker_password
auto_tag: true
context: registry
repo: hibas123.azurecr.io/denreg
registry: hibas123.azurecr.io
repo: docker.hibas123.de/denreg
registry: docker.hibas123.de
dockerfile: registry/Dockerfile
debug: false

36
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,36 @@
# .github/workflows/ci.yml
name: CI
on:
push:
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
env:
MY_DOCKER_USERNAME: ${{ secrets.MY_DOCKER_USERNAME }}
MY_DOCKER_PASSWORD: ${{ secrets.MY_DOCKER_PASSWORD }}
FORCE_COLOR: 1
steps:
- uses: https://github.com/earthly/actions-setup@v1
with:
version: v0.7.0
- uses: actions/checkout@v2
- name: Put back the git branch into git (Earthly uses it for tagging)
run: |
branch=""
if [ -n "$GITHUB_HEAD_REF" ]; then
branch="$GITHUB_HEAD_REF"
else
branch="${GITHUB_REF##*/}"
fi
git checkout -b "$branch" || true
- name: Docker Login
run: docker login git.hibas.dev --username "$MY_DOCKER_USERNAME" --password "$MY_DOCKER_PASSWORD"
- name: Earthly version
run: earthly --version
- name: Run build
run: cd registry && earthly --push +docker-multi

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
test.ini

View File

@ -1,5 +1,12 @@
{
"deno.enable": true,
"deno.unstable": true,
"debug.javascript.usePreview": false
"debug.javascript.usePreview": false,
"deno.import_intellisense_origins": {
"https://deno.land": true
},
"deno.suggest.imports.hosts": {
"https://deno.land": true,
"https://deno.hibas123.de": false
}
}

View File

@ -1,11 +1,11 @@
import { Colors, Cliffy } from "../deps.ts";
import { Colors, CliffyPrompt } from "../deps.ts";
import { getMeta, setMeta, log } from "../global.ts";
export default async function deprecate(options: any) {
const meta = await getMeta();
const res = await Cliffy.Confirm.prompt(
const res = await CliffyPrompt.Confirm.prompt(
"Are you sure you want to deprecat this package?"
);

View File

@ -1,4 +1,4 @@
import { Cliffy, Path, FS } from "../deps.ts";
import { CliffyPrompt, Path, FS } from "../deps.ts";
import {
getMeta,
setMeta,
@ -11,7 +11,7 @@ export default async function init() {
let existing = {};
try {
existing = await getMeta();
} catch (err) {}
} catch (err) { }
let meta: IMeta = {
name: Path.basename(Deno.cwd()).toLowerCase().replace(/\s+/g, "-"),
version: "0.0.1",
@ -23,21 +23,21 @@ export default async function init() {
};
if (isInteractive()) {
meta.name = await Cliffy.Input.prompt({
meta.name = await CliffyPrompt.Input.prompt({
message: "What's the name of your package?",
default: meta.name,
});
meta.description = await Cliffy.Input.prompt({
meta.description = await CliffyPrompt.Input.prompt({
message: "What's the description of your package?",
default: meta.description,
});
meta.author = await Cliffy.Input.prompt({
meta.author = await CliffyPrompt.Input.prompt({
message: "Who's the author of your package?",
default: meta.author,
});
if (!(await FS.exists("README.md"))) {
const res = await Cliffy.Confirm.prompt({
const res = await CliffyPrompt.Confirm.prompt({
message: "Autogenerate README?",
default: true,
});

View File

@ -1,64 +1,31 @@
import { Colors, Path, FS, Compress, Base64 } from "../deps.ts";
import { getMeta, IMeta, log, getConfig } from "../global.ts";
import { runHooks } from "../helper/run_script.ts";
import { ServerError } from "../helper/server_error.ts";
async function runScript(script: string) {
console.log(Colors.bold(Colors.blue("Running script:")), script);
const runPerm = await Deno.permissions.query({
name: "run",
});
if (runPerm.state !== "granted") {
console.log(
Colors.red("Missing --allow-run permission. Cannot run hooks!")
);
throw new Error("Missing --allow-run permission. Cannot run hooks!");
}
const process = Deno.run({
cmd: ["deno", "run", "-A", "--unstable", script],
});
const status = await process.status();
console.log(Colors.bold(Colors.blue("Finished script:")), script);
if (!status.success) {
throw new Error(
"A hook did not complete sucessfully. This is not a issue of denreg!"
);
}
}
async function runHooks(hooks: undefined | string | string[]) {
if (!hooks) return;
if (typeof hooks === "string") {
hooks = [hooks];
}
for (const hook of hooks) {
await runScript(hook);
}
}
import { checkPermOrExit } from "../helper/permission.ts";
export default async function publish(options: { dry: boolean }) {
const meta: IMeta = await getMeta();
const originalMeta = await getMeta();
if (originalMeta.hooks) {
log("Running prepublish hooks");
await runHooks(originalMeta.hooks.prepublish);
}
const meta = await getMeta();
//TODO: Output Diff between original and result meta
if (!meta.name) throw new Error("name is not set in meta.json");
if (!meta.version) throw new Error("version is not set in meta.json");
if (!meta.files || !Array.isArray(meta.files) || meta.files.length <= 0)
throw new Error("files is not set or empty in meta.json");
if (meta.hooks) {
log("Running prepublish hooks");
await runHooks(meta.hooks.prepublish);
}
const tmpDir = await Deno.makeTempDir();
const packedFile = (await Deno.makeTempFile()) + ".tar";
try {
const walker = FS.walk(".", {
const walker = FS.walk(meta.root || ".", {
includeDirs: false,
includeFiles: true,
match: meta.files.map((file) => Path.globToRegExp(file)),
@ -66,17 +33,18 @@ export default async function publish(options: { dry: boolean }) {
log("Copying files to package to", tmpDir);
const copy = async (path: string) => {
const dest = Path.join(tmpDir, path);
const copy = async (path: string, abs?: boolean) => {
const relative = abs ? path : Path.relative(meta.root || ".", path);
log("Adding file:", path, "as", relative);
const dest = Path.join(tmpDir, relative);
await FS.ensureDir(Path.dirname(dest));
await FS.copy(path, dest);
};
await copy("meta.json");
await copy("meta.json", true);
for await (const file of walker) {
await copy(file.path);
log("Adding file:", file.path);
}
log("Compressing files into", packedFile);
@ -88,9 +56,16 @@ export default async function publish(options: { dry: boolean }) {
const url = new URL(getConfig("registry"));
url.pathname = "/api/package/" + meta.name;
if (!options.dry) {
log("Uploading new package version");
console.log(
"Pushing version",
Colors.blue(meta.version),
"to repository"
);
if (!options.dry) {
await checkPermOrExit("net", "Net permission required for publishing");
log("Uploading new package version");
await fetch(url, {
method: "POST",
body: await Deno.readFile(packedFile),

18
cli/commands/run.ts Normal file
View File

@ -0,0 +1,18 @@
import { Colors, Path, FS, Compress, Base64 } from "../deps.ts";
import { getMeta, IMeta, log, getConfig } from "../global.ts";
import { ServerError } from "../helper/server_error.ts";
import { runScript } from "../helper/run_script.ts";
export default async function run(options: {}, name: string) {
const { scripts } = await getMeta();
if (!scripts || !scripts[name]) {
console.log(Colors.bold(Colors.red("Script not found:")), name);
} else {
let script = scripts[name];
if (!Array.isArray(script)) script = [script];
for (const s of script) {
await runScript(s);
}
}
}

View File

@ -1,23 +1,23 @@
import { Cliffy } from "../deps.ts";
import { CliffyPrompt } from "../deps.ts";
import { getConfig, setConfig } from "../global.ts";
export default async function setup() {
const registry = await Cliffy.Input.prompt({
const registry = await CliffyPrompt.Input.prompt({
message: "What's your registry?",
default: getConfig("registry"),
});
const username = await Cliffy.Input.prompt({
const username = await CliffyPrompt.Input.prompt({
message: "What's your username?",
default: getConfig("username"),
});
const password = await Cliffy.Secret.prompt({
const password = await CliffyPrompt.Secret.prompt({
message: "What's your password?",
hidden: true,
default: getConfig("password"),
});
const author = await Cliffy.Input.prompt({
const author = await CliffyPrompt.Input.prompt({
message: "Who are you? (optional) Name <email@example.com>",
default: getConfig("author"),
});

View File

@ -1,25 +1,63 @@
import { Cliffy, Colors } from "../deps.ts";
import { CliffyPrompt, Colors } from "../deps.ts";
import { version } from "../version.ts";
import { requestPermOrExit } from "../helper/permission.ts";
export default async function upgrade() {
const res = await Cliffy.Confirm.prompt({
message: "Are you sure you want to upgrade the denreg cli?",
await requestPermOrExit(
"net",
"Net permission required to fetch new version"
);
const meta = await fetch(
"https://deno.hibas123.de/raw/@denreg-cli/meta.json"
).then((e) => e.json());
if (meta.version === version) {
const res = await CliffyPrompt.Confirm.prompt({
message: Colors.yellow("No update available!") + " Continue?",
default: false,
});
if (!res) return;
}
const res = await CliffyPrompt.Confirm.prompt({
message: "Are you sure you want to upgrade?",
default: true,
});
if (res) {
const process = Deno.run({
cmd: [
"deno",
"install",
"-A",
"--unstable",
"-f",
"https://deno.hibas123.de/raw/@denreg-cli/denreg.ts",
],
const cmd_base = ["deno", "install", "-A", "--unstable", "-f"];
const cmd1 = [
...cmd_base,
`https://deno.hibas123.de/raw/@denreg-cli@${meta.version}/denreg.ts`,
];
const cmd2 = [
...cmd_base,
`https://deno.hibas123.de/raw/@denreg-cli@${meta.version}/dpm.ts`,
];
await requestPermOrExit(
"run",
"Run permission required to install new version. Or run it manually: " +
cmd1.join(" ")
);
const process1 = Deno.run({
cmd: cmd1,
});
const s = await process.status();
if (!s) {
const s1 = await process1.status();
if (!s1) {
console.log(Colors.red("Upgrade failed!"));
}
const process2 = Deno.run({
cmd: cmd2,
});
const s2 = await process2.status();
if (!s2) {
console.log(Colors.red("Upgrade failed!"));
}
}

View File

@ -1,14 +1,20 @@
import { Cliffy, Path, Colors } from "./deps.ts";
import { CliffyCommand, Path, Colors } from "./deps.ts";
import { checkPermOrExit } from "./helper/permission.ts";
await checkPermOrExit("env", "Requires --allow-env");
await checkPermOrExit("read", "Requires --allow-read");
await checkPermOrExit("write", "Requires --allow-write");
import { init } from "./global.ts";
import { version } from "./version.ts";
import setupCMD from "./commands/setup.ts";
import initCMD from "./commands/init.ts";
import bumpCMD from "./commands/bump.ts";
import publishCMD from "./commands/publish.ts";
import deprecateCMD from "./commands/deprecate.ts";
import upgradeCMD from "./commands/upgrade.ts";
import runCMD from "./commands/run.ts";
const HOME_FOLDER = Deno.env.get("HOME") || Deno.env.get("USERPROFILE") || "";
@ -26,7 +32,7 @@ const commandWrapper = (cmd: CommandHandler) => {
opts = params;
};
};
const flags = await new Cliffy.Command()
const flags = await new CliffyCommand.Command()
.name("denreg")
.version(version)
.description("CLI for the Open Source DenReg package registry")
@ -44,13 +50,13 @@ const flags = await new Cliffy.Command()
})
.command(
"setup",
new Cliffy.Command()
new CliffyCommand.Command()
.description("Configure cli")
.action(commandWrapper(setupCMD))
)
.command(
"publish",
new Cliffy.Command()
new CliffyCommand.Command()
.description("Upload package")
.action(commandWrapper(publishCMD))
.option("-d, --dry [dry:boolean]", "Dry run", {
@ -59,13 +65,13 @@ const flags = await new Cliffy.Command()
)
.command(
"init",
new Cliffy.Command()
new CliffyCommand.Command()
.description("Create meta.json")
.action(commandWrapper(initCMD))
)
.command(
"bump",
new Cliffy.Command()
new CliffyCommand.Command()
.complete("major|minor|patch", () => ["major", "minor", "patch"])
.arguments("<major|minor|patch>")
.description("Change package version")
@ -73,17 +79,26 @@ const flags = await new Cliffy.Command()
)
.command(
"deprecate",
new Cliffy.Command()
new CliffyCommand.Command()
.description("Deprecate package")
.action(commandWrapper(deprecateCMD))
)
.command(
"upgrade",
new Cliffy.Command()
new CliffyCommand.Command()
.description("Upgrade to latest version of denreg cli")
.action(commandWrapper(upgradeCMD))
)
.command("completions", new Cliffy.CompletionsCommand())
.command(
"run",
new CliffyCommand.Command()
.arguments("<name>")
// .complete("name", ()=>) //TODO: add autocomplete?
.description("Run script from meta.json")
.action(commandWrapper(runCMD))
)
.command("completions", new CliffyCommand.CompletionsCommand())
.command("help", new CliffyCommand.HelpCommand().global())
.parse(Deno.args);
await init(flags.options);
@ -94,4 +109,6 @@ if (command) {
} catch (err) {
console.log(Colors.bold(Colors.red("An error occured:")), err.message);
}
} else {
flags.cmd.showHelp();
}

View File

@ -1,7 +1,11 @@
export * as Compress from "https://deno.hibas123.de/raw/@denreg-tar/mod.ts";
export * as Ini from "https://deno.land/x/ini@v2.1.0/mod.ts";
export * as Cliffy from "https://deno.land/x/cliffy@v0.14.1/mod.ts";
export * as Base64 from "https://deno.land/std@0.65.0/encoding/base64.ts";
export * as FS from "https://deno.land/std@0.65.0/fs/mod.ts";
export * as Colors from "https://deno.land/std@0.65.0/fmt/colors.ts";
export * as Path from "https://deno.land/std@0.65.0/path/mod.ts";
export * as CliffyPrompt from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/mod.ts";
export * as CliffyCommand from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/mod.ts";
export * as Cliffy from "https://deno.land/x/cliffy@v0.18.2/mod.ts";
export * as Base64 from "https://deno.land/std@0.95.0/encoding/base64.ts";
export * as FS from "https://deno.land/std@0.95.0/fs/mod.ts";
export * as Colors from "https://deno.land/std@0.95.0/fmt/colors.ts";
export * as Path from "https://deno.land/std@0.95.0/path/mod.ts";

1
cli/dpm.ts Normal file
View File

@ -0,0 +1 @@
import "./denreg.ts";

View File

@ -9,10 +9,14 @@ export interface IMeta {
contributors?: string[];
deprecated?: boolean;
files: string[];
root?: string;
hooks?: {
prepublish?: string | string[];
postpublish?: string | string[];
};
scripts?: {
[key: string]: string | string[];
};
}
let verbose = false;
@ -41,16 +45,18 @@ export async function setConfig(name: string, value: string) {
});
}
const readJson = (name: string) => Deno.readTextFile(name).then(JSON.parse);
const writeJson = (name: string, value: any, spaces?: string) =>
Deno.writeTextFile(name, JSON.stringify(value, null, spaces));
export async function getMeta() {
log("Reading meta.json");
return (await FS.readJson("meta.json")) as IMeta;
return (await readJson("meta.json")) as IMeta;
}
export async function setMeta(meta: IMeta): Promise<void> {
log("Saving meta.json");
return FS.writeJson("meta.json", meta, {
spaces: " ",
});
return writeJson("meta.json", meta, " ");
}
let interactive = true;

26
cli/helper/permission.ts Normal file
View File

@ -0,0 +1,26 @@
import { Colors } from "../deps.ts";
export const checkPermOrExit = (name: string, err: string) =>
Deno.permissions.query({ name: name as any }).then((res) => {
if (res.state !== "granted") {
console.log(Colors.bold(Colors.red(err)));
Deno.exit(1);
}
});
export const requestPermOrExit = (name: string, err: string) => {
Deno.permissions
.query({ name: name as any })
.then((res) => {
if (res.state === "prompt") {
return Deno.permissions.request({ name: name as any });
}
return res;
})
.then((res) => {
if (res.state !== "granted") {
console.log(Colors.bold(Colors.red(err)));
Deno.exit(1);
}
});
};

51
cli/helper/run_script.ts Normal file
View File

@ -0,0 +1,51 @@
import { Colors } from "../deps.ts";
import { checkPermOrExit } from "../helper/permission.ts";
export async function runScript(script: string) {
await checkPermOrExit(
"run",
"Requires --allow-run to run scripts and hooks"
);
console.log(Colors.bold(Colors.blue("Running script:")), script);
const runPerm = await Deno.permissions.query({
name: "run",
});
if (runPerm.state !== "granted") {
console.log(
Colors.red("Missing --allow-run permission. Cannot run hooks!")
);
throw new Error("Missing --allow-run permission. Cannot run hooks!");
}
const process = Deno.run({
cmd: ["deno", "run", "-A", "--unstable", script],
});
const status = await process.status();
console.log(Colors.bold(Colors.blue("Finished script:")), script);
if (!status.success) {
throw new Error(
"A script did not complete sucessfully. This is not a issue of denreg!"
);
}
}
export async function runHooks(hooks: undefined | string | string[]) {
if (!hooks) return;
if (typeof hooks === "string") {
hooks = [hooks];
}
for (const hook of hooks) {
try {
await runScript(hook);
} catch (err) {
throw new Error(
"A hook did not complete sucessfully. This is not a issue of denreg!"
);
}
}
}

View File

@ -1,11 +1,18 @@
{
"name": "@denreg-cli",
"version": "0.2.5",
"version": "1.0.0",
"description": "CLI for the DenReg package registry",
"author": "Fabian Stamm <dev@fabianstamm.de>",
"contributors": [],
"files": ["**/*.ts", "**/*.js", "README.md"],
"files": [
"**/*.ts",
"**/*.js",
"README.md"
],
"scripts": {
"test": "version.ts"
},
"hooks": {
"prepublish": "pre.ts"
}
}
}

View File

@ -1,6 +1,6 @@
import { FS } from "./deps.ts";
const meta = (await FS.readJson("./meta.json")) as any;
const meta = (await Deno.readTextFile("./meta.json").then(JSON.parse)) as any;
await Deno.writeTextFile(
"version.ts",

0
cli/test.ts Normal file
View File

View File

@ -1 +1 @@
export const version = "0.2.5"
export const version = "1.0.0"

View File

@ -1,5 +0,0 @@
Denreg JSX renderer
**deprecated**
**DO NOT USE**

View File

@ -1,13 +1,14 @@
{
"name": "@denreg-jsx",
"version": "0.0.3",
"version": "0.1.4",
"description": "Denreg JSX renderer",
"author": "Fabian Stamm <dev@fabianstamm.de>",
"contributors": [],
"deprecated": true,
"deprecated": false,
"files": [
"**/*.ts",
"**/*.js",
"tsconfig.json",
"README.md"
]
}

145
jsx/mod.ts Normal file
View File

@ -0,0 +1,145 @@
import "./types.ts";
const Fragment = Symbol("fragment");
declare namespace JSX {
interface Element {}
interface IntrinsicElements {
div: any;
}
}
export type Element = {
component: Component | string | typeof Fragment;
props: any;
children: any[];
};
export type ComponentRetElm = Element | Element[];
export type Component = (
props: any,
children: any
) => ComponentRetElm | Promise<ComponentRetElm>;
export function h(
component: string | Component,
props: any,
...children: Element[]
): Element {
return {
component,
props,
children,
};
}
const createElement = h;
export { Fragment, createElement };
export async function renderSSR(element: Element | string): Promise<string> {
if (typeof element === "string") return element;
else if (typeof element.component === "string")
return await renderHTML(element as Element);
else if (
typeof element.component === "function" ||
element.component === Fragment
)
return await renderCustom(element as Element);
console.warn("renderSSR: invalid element", element);
return "";
}
const selfClosing = new Set([
"area",
"base",
"br",
"col",
"embed",
"hr",
"img",
"input",
"link",
"meta",
"param",
"source",
"track",
"wbr",
]);
function flatDeep(arr: any, d = Infinity): any[] {
if (Array.isArray(arr) && d >= 0) {
let res = [];
for (const val of arr) {
const v = flatDeep(val, d - 1);
res.push(...v);
}
return res;
}
return [arr];
}
function cleanChildren(children: any) {
return flatDeep(children).filter((e) => !!e);
}
async function renderHTML(element: Element) {
if (typeof element.component !== "string")
throw new Error("Internal consistency error");
let props = "";
for (const key in element.props) {
if (key == "innerHTML") continue;
props += `${key}="${element.props[key] || ""}" `;
}
const tag = element.component;
if (selfClosing.has(element.component)) {
return `<${tag} ${props}/>`;
} else {
let inner = "";
if (element.props && element.props["innerHTML"]) {
inner = element.props["innerHTML"];
} else {
const children = cleanChildren(element.children);
inner = (
await Promise.all(children.map((child) => renderSSR(child)))
).join("");
}
return `<${tag} ${props}>${inner || ""}</${tag}>`;
}
}
async function renderCustom(element: Element) {
if (typeof element.component === "string")
throw new Error("Internal consistency error");
if (element.component === Fragment) {
const ch = (
await Promise.all(
cleanChildren(element.children).map((child) => renderSSR(child))
)
).join("");
return ch;
} else {
const res = await Promise.resolve(
element.component(
{
...element.props,
children: element.children,
},
element.children
)
);
const ch = (
await Promise.all(cleanChildren(res).map((child) => renderSSR(child)))
).join("");
return ch;
}
}

7
jsx/tsconfig.json Normal file
View File

@ -0,0 +1,7 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext", "deno.ns", "deno.unstable"],
"jsxFactory": "h",
"strictPropertyInitialization": false
}
}

11
jsx/types.ts Normal file
View File

@ -0,0 +1,11 @@
declare namespace JSX {
interface IntrinsicElements {
[elemName: string]: any;
}
}
declare namespace JSX {
interface ElementClass {
render: any;
}
}

14
markdown/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,14 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Deno",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "deno",
"runtimeArgs": ["run", "--inspect", "-A", "app.ts"],
"port": 9229
}
]
}

9
markdown/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"deno.enable": true,
"[typescript]": {
"editor.defaultFormatter": "axetroy.vscode-deno"
},
"[typescriptreact]": {
"editor.defaultFormatter": "axetroy.vscode-deno"
}
}

21
markdown/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Eivind Furuberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

62
markdown/README.md Normal file
View File

@ -0,0 +1,62 @@
# markdown
Deno Markdown module forked from https://github.com/ts-stack/markdown/tree/bb47aa8e625e89e6aa84f49a98536a3089dee831
### Example usage
Simple md2html.ts script:
```typescript
import { Marked } from "./mod.ts";
const decoder = new TextDecoder("utf-8");
const filename = Deno.args[0];
const markdown = decoder.decode(await Deno.readFile(filename));
const markup = Marked.parse(markdown);
console.log(markup.content);
console.log(JSON.stringify(markup.meta))
```
Now running:
```bash
deno run --allow-read md2html.ts example.md > example.html
```
Will output:
```html
<h1 id="hello-world">Hello World</h1>
<h2 id="this-an-example-for-md2html-ts-">
This an example for <code>md2html.ts</code>
</h2>
<p>A small paragraph that will become a <code>&lt;p&gt;</code> tag</p>
<hr />
<p>Code Block (md2html.ts)</p>
<pre><code class="lang-typescript">import { Marked } from &quot;./mod.ts&quot;;
const decoder = new TextDecoder("utf-8");
const filename = Deno.args[0];
const markdown = decoder.decode(await Deno.readFile(filename));
const markup = Marked.parse(markdown);
console.log(markup.content);
console.log(JSON.stringify(markup.meta))
</code></pre>
<p>
This module is forked from
<a
href="https://github.com/ts-stack/markdown/tree/bb47aa8e625e89e6aa84f49a98536a3089dee831"
>ts-stack/markdown</a
>
</p>
<p>Made for Deno <img src="https://deno.land/logo.svg" alt="deno-logo" /></p>
{"title":"Hello world!","subtitle":"Front-matter is supported!","boolean":true,"list-example":["this","is",{"a":"list"}]}
```
---
### Notes
I had to do some changes to the source code to make the compiler happy, mostly fixes for things that were uninitialized and possibly null or undefined

BIN
markdown/example.html Normal file

Binary file not shown.

34
markdown/example.md Normal file
View File

@ -0,0 +1,34 @@
---
title : Hello world!
subtitle : Front-matter is supported!
boolean: true
list-example:
- this
- is
- a: list
---
# Hello World
## This an example for `md2html.ts`
A small paragraph that will become a `<p>` tag
---
Code Block (md2html.ts)
```typescript
import { Marked } from "./mod.ts";
const decoder = new TextDecoder("utf-8");
const filename = Deno.args[0];
const markdown = decoder.decode(await Deno.readFile(filename));
const markup = Marked.parse(markdown);
console.log(markup.content);
console.log(JSON.stringify(markup.meta));
```
This module is forked from [ts-stack/markdown](https://github.com/ts-stack/markdown/tree/bb47aa8e625e89e6aa84f49a98536a3089dee831)
Made for Deno
![deno-logo](https://deno.land/logo.svg)

8
markdown/md2html.ts Normal file
View File

@ -0,0 +1,8 @@
import { Marked } from "./mod.ts";
const decoder = new TextDecoder("utf-8");
const filename = Deno.args[0];
const markdown = decoder.decode(await Deno.readFile(filename));
const markup = Marked.parse(markdown);
console.log(markup.content);
console.log(JSON.stringify(markup.meta))

12
markdown/meta.json Normal file
View File

@ -0,0 +1,12 @@
{
"name": "markdown",
"version": "0.1.0",
"description": "",
"author": "Fabian Stamm <dev@fabianstamm.de>",
"contributors": [],
"files": [
"**/*.ts",
"**/*.js",
"README.md"
]
}

8
markdown/mod.ts Normal file
View File

@ -0,0 +1,8 @@
export * from "./src/block-lexer.ts";
export * from "./src/helpers.ts";
export * from "./src/inline-lexer.ts";
export * from "./src/interfaces.ts";
export * from "./src/marked.ts";
export * from "./src/parser.ts";
export * from "./src/renderer.ts";
export * from "./src/extend-regexp.ts";

522
markdown/src/block-lexer.ts Normal file
View File

@ -0,0 +1,522 @@
/**
* @license
*
* Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
* https://github.com/chjj/marked
*
* Copyright (c) 2018, Костя Третяк. (MIT Licensed)
* https://github.com/ts-stack/markdown
*/
import { ExtendRegexp } from "./extend-regexp.ts";
import {
Align,
LexerReturns,
Links,
MarkedOptions,
RulesBlockBase,
RulesBlockGfm,
RulesBlockTables,
Token,
TokenType,
Obj
} from "./interfaces.ts";
import { Marked } from "./marked.ts";
import { parse } from "https://deno.land/std@0.208.0/yaml/mod.ts";
export class BlockLexer<T extends typeof BlockLexer> {
static simpleRules: RegExp[] = [];
protected static rulesBase: RulesBlockBase;
/**
* GFM Block Grammar.
*/
protected static rulesGfm: RulesBlockGfm;
/**
* GFM + Tables Block Grammar.
*/
protected static rulesTables: RulesBlockTables;
protected rules!: RulesBlockBase | RulesBlockGfm | RulesBlockTables;
protected options: MarkedOptions;
protected links: Links = {};
protected tokens: Token[] = [];
protected frontmatter: Obj = {};
protected hasRulesGfm!: boolean;
protected hasRulesTables!: boolean;
constructor(protected staticThis: typeof BlockLexer, options?: object) {
this.options = options || Marked.options;
this.setRules();
}
/**
* Accepts Markdown text and returns object with tokens and links.
*
* @param src String of markdown source to be compiled.
* @param options Hash of options.
*/
static lex(
src: string,
options?: MarkedOptions,
top?: boolean,
isBlockQuote?: boolean,
): LexerReturns {
const lexer = new this(this, options);
return lexer.getTokens(src, top, isBlockQuote);
}
protected static getRulesBase(): RulesBlockBase {
if (this.rulesBase) {
return this.rulesBase;
}
const base: RulesBlockBase = {
newline: /^\n+/,
code: /^( {4}[^\n]+\n*)+/,
hr: /^( *[-*_]){3,} *(?:\n+|$)/,
heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
html:
/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
paragraph:
/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
text: /^[^\n]+/,
bullet: /(?:[*+-]|\d+\.)/,
item: /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,
};
base.item = new ExtendRegexp(base.item, "gm").setGroup(/bull/g, base.bullet)
.getRegexp();
base.list = new ExtendRegexp(base.list)
.setGroup(/bull/g, base.bullet)
.setGroup("hr", "\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")
.setGroup("def", "\\n+(?=" + base.def.source + ")")
.getRegexp();
const tag = "(?!(?:" +
"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code" +
"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo" +
"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";
base.html = new ExtendRegexp(base.html)
.setGroup("comment", /<!--[\s\S]*?-->/)
.setGroup("closed", /<(tag)[\s\S]+?<\/\1>/)
.setGroup("closing", /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
.setGroup(/tag/g, tag)
.getRegexp();
base.paragraph = new ExtendRegexp(base.paragraph)
.setGroup("hr", base.hr)
.setGroup("heading", base.heading)
.setGroup("lheading", base.lheading)
.setGroup("blockquote", base.blockquote)
.setGroup("tag", "<" + tag)
.setGroup("def", base.def)
.getRegexp();
return (this.rulesBase = base);
}
protected static getRulesGfm(): RulesBlockGfm {
if (this.rulesGfm) {
return this.rulesGfm;
}
const base = this.getRulesBase();
const gfm: RulesBlockGfm = {
...base,
...{
fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
paragraph: /^/,
heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/,
},
};
const group1 = gfm.fences.source.replace("\\1", "\\2");
const group2 = base.list.source.replace("\\1", "\\3");
gfm.paragraph = new ExtendRegexp(base.paragraph).setGroup(
"(?!",
`(?!${group1}|${group2}|`,
).getRegexp();
return (this.rulesGfm = gfm);
}
protected static getRulesTable(): RulesBlockTables {
if (this.rulesTables) {
return this.rulesTables;
}
return (this.rulesTables = {
...this.getRulesGfm(),
...{
nptable:
/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/,
},
});
}
protected setRules() {
if (this.options.gfm) {
if (this.options.tables) {
this.rules = this.staticThis.getRulesTable();
} else {
this.rules = this.staticThis.getRulesGfm();
}
} else {
this.rules = this.staticThis.getRulesBase();
}
this.hasRulesGfm = (this.rules as RulesBlockGfm).fences !== undefined;
this.hasRulesTables = (this.rules as RulesBlockTables).table !== undefined;
}
/**
* Lexing.
*/
protected getTokens(
src: string,
top?: boolean,
isBlockQuote?: boolean,
): LexerReturns {
let nextPart = src;
let execArr, fmArr: RegExpExecArray | null;
mainLoop:
while (nextPart) {
// newline
if ((execArr = this.rules.newline.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
if (execArr[0].length > 1) {
this.tokens.push({ type: TokenType.space });
}
}
// code
if ((execArr = this.rules.code.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
const code = execArr[0].replace(/^ {4}/gm, "");
this.tokens.push({
type: TokenType.code,
text: !this.options.pedantic ? code.replace(/\n+$/, "") : code,
});
continue;
}
// fences code (gfm)
if (
this.hasRulesGfm &&
(execArr = (this.rules as RulesBlockGfm).fences.exec(nextPart))
) {
nextPart = nextPart.substring(execArr[0].length);
this.tokens.push({
type: TokenType.code,
lang: execArr[2],
text: execArr[3] || "",
});
continue;
}
// heading
if ((execArr = this.rules.heading.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
this.tokens.push({
type: TokenType.heading,
depth: execArr[1].length,
text: execArr[2],
});
continue;
}
// table no leading pipe (gfm)
if (
top && this.hasRulesTables &&
(execArr = (this.rules as RulesBlockTables).nptable.exec(nextPart))
) {
nextPart = nextPart.substring(execArr[0].length);
const item: Token = {
type: TokenType.table,
header: execArr[1].replace(/^ *| *\| *$/g, "").split(/ *\| */),
align: execArr[2].replace(/^ *|\| *$/g, "").split(
/ *\| */,
) as Align[],
cells: [],
};
if (!item.align) throw ReferenceError;
for (let i = 0; i < item.align.length; i++) {
if (/^ *-+: *$/.test(item.align[i])) {
item.align[i] = "right";
} else if (/^ *:-+: *$/.test(item.align[i])) {
item.align[i] = "center";
} else if (/^ *:-+ *$/.test(item.align[i])) {
item.align[i] = "left";
} else {
item.align[i] = "";
}
}
const td: string[] = execArr[3].replace(/\n$/, "").split("\n");
if (!item.cells) throw ReferenceError;
for (let i = 0; i < td.length; i++) {
item.cells[i] = td[i].split(/ *\| */);
}
this.tokens.push(item);
continue;
}
// lheading
if ((execArr = this.rules.lheading.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
this.tokens.push({
type: TokenType.heading,
depth: execArr[2] === "=" ? 1 : 2,
text: execArr[1],
});
continue;
}
// hr
if ((execArr = this.rules.hr.exec(nextPart))) {
// Checks if the previous string contains a content.
if ((this.tokens.length == 0) || (this.tokens.every(object => object.type == TokenType.space))) {
// Grabs front-matter data and parse it into Javascript object.
if (fmArr = /^(?:\-\-\-)(.*?)(?:\-\-\-|\.\.\.)/s.exec(nextPart)) {
nextPart = nextPart.substring(fmArr[0].length);
this.frontmatter = <Obj>parse(fmArr[1]);
}
continue;
} else {
nextPart = nextPart.substring(execArr[0].length);
this.tokens.push({ type: TokenType.hr });
continue;
}
}
// blockquote
if ((execArr = this.rules.blockquote.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
this.tokens.push({ type: TokenType.blockquoteStart });
const str = execArr[0].replace(/^ *> ?/gm, "");
// Pass `top` to keep the current
// "toplevel" state. This is exactly
// how markdown.pl works.
this.getTokens(str);
this.tokens.push({ type: TokenType.blockquoteEnd });
continue;
}
// list
if ((execArr = this.rules.list.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
const bull: string = execArr[2];
this.tokens.push(
{ type: TokenType.listStart, ordered: bull.length > 1 },
);
// Get each top-level item.
const str = execArr[0].match(this.rules.item) || "";
const length = str.length;
let next = false;
let space: number;
let blockBullet: string;
let loose: boolean;
for (let i = 0; i < length; i++) {
let item = str[i];
// Remove the list item's bullet so it is seen as the next token.
space = item.length;
item = item.replace(/^ *([*+-]|\d+\.) +/, "");
// Outdent whatever the list item contains. Hacky.
if (item.indexOf("\n ") !== -1) {
space -= item.length;
item = !this.options.pedantic
? item.replace(new RegExp("^ {1," + space + "}", "gm"), "")
: item.replace(/^ {1,4}/gm, "");
}
// Determine whether the next list item belongs here.
// Backpedal if it does not belong in this list.
if (this.options.smartLists && i !== length - 1) {
const bb = this.staticThis.getRulesBase().bullet.exec(str[i + 1]);
blockBullet = bb ? bb[0] : "";
if (
bull !== blockBullet &&
!(bull.length > 1 && blockBullet.length > 1)
) {
nextPart = (str.slice(i + 1) as string[]).join("\n") + nextPart;
i = length - 1;
}
}
// Determine whether item is loose or not.
// Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
// for discount behavior.
loose = next || /\n\n(?!\s*$)/.test(item);
if (i !== length - 1) {
next = item.charAt(item.length - 1) === "\n";
if (!loose) {
loose = next;
}
}
this.tokens.push(
{
type: loose ? TokenType.looseItemStart : TokenType.listItemStart,
},
);
// Recurse.
this.getTokens(item, false, isBlockQuote);
this.tokens.push({ type: TokenType.listItemEnd });
}
this.tokens.push({ type: TokenType.listEnd });
continue;
}
// html
if ((execArr = this.rules.html.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
const attr = execArr[1];
const isPre = attr === "pre" || attr === "script" || attr === "style";
this.tokens.push({
type: this.options.sanitize ? TokenType.paragraph : TokenType.html,
pre: !this.options.sanitizer && isPre,
text: execArr[0],
});
continue;
}
// def
if (top && (execArr = this.rules.def.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
this.links[execArr[1].toLowerCase()] = {
href: execArr[2],
title: execArr[3],
};
continue;
}
// table (gfm)
if (
top && this.hasRulesTables &&
(execArr = (this.rules as RulesBlockTables).table.exec(nextPart))
) {
nextPart = nextPart.substring(execArr[0].length);
const item: Token = {
type: TokenType.table,
header: execArr[1].replace(/^ *| *\| *$/g, "").split(/ *\| */),
align: execArr[2].replace(/^ *|\| *$/g, "").split(
/ *\| */,
) as Align[],
cells: [],
};
if (!item.align) throw ReferenceError;
for (let i = 0; i < item.align.length; i++) {
if (/^ *-+: *$/.test(item.align[i])) {
item.align[i] = "right";
} else if (/^ *:-+: *$/.test(item.align[i])) {
item.align[i] = "center";
} else if (/^ *:-+ *$/.test(item.align[i])) {
item.align[i] = "left";
} else {
item.align[i] = "";
}
}
const td = execArr[3].replace(/(?: *\| *)?\n$/, "").split("\n");
if (!item.cells) throw ReferenceError;
for (let i = 0; i < td.length; i++) {
item.cells[i] = td[i].replace(/^ *\| *| *\| *$/g, "").split(/ *\| */);
}
this.tokens.push(item);
continue;
}
// simple rules
if (this.staticThis.simpleRules.length) {
const simpleRules = this.staticThis.simpleRules;
for (let i = 0; i < simpleRules.length; i++) {
if ((execArr = simpleRules[i].exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
const type = "simpleRule" + (i + 1);
this.tokens.push({ type, execArr });
continue mainLoop;
}
}
}
// top-level paragraph
if (top && (execArr = this.rules.paragraph.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
if (execArr[1].slice(-1) === "\n") {
this.tokens.push({
type: TokenType.paragraph,
text: execArr[1].slice(0, -1),
});
} else {
this.tokens.push({
type: this.tokens.length > 0 ? TokenType.paragraph : TokenType.text,
text: execArr[1],
});
}
continue;
}
// text
// Top-level should never reach here.
if ((execArr = this.rules.text.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
this.tokens.push({ type: TokenType.text, text: execArr[0] });
continue;
}
if (nextPart) {
throw new Error(
"Infinite loop on byte: " + nextPart.charCodeAt(0) +
`, near text '${nextPart.slice(0, 30)}...'`,
);
}
}
return { tokens: this.tokens, links: this.links, meta: this.frontmatter };
}
}

View File

@ -0,0 +1,43 @@
/*
* @license
*
* Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
* https://github.com/chjj/marked
*
* Copyright (c) 2018, Костя Третяк. (MIT Licensed)
* https://github.com/ts-stack/markdown
*/
export class ExtendRegexp {
private source: string;
private flags: string;
constructor(regex: RegExp, flags: string = "") {
this.source = regex.source;
this.flags = flags;
}
/**
* Extend regular expression.
*
* @param groupName Regular expression for search a group name.
* @param groupRegexp Regular expression of named group.
*/
setGroup(groupName: RegExp | string, groupRegexp: RegExp | string): this {
let newRegexp: string = typeof groupRegexp == "string"
? groupRegexp
: groupRegexp.source;
newRegexp = newRegexp.replace(/(^|[^\[])\^/g, "$1");
// Extend regexp.
this.source = this.source.replace(groupName, newRegexp);
return this;
}
/**
* Returns a result of extending a regular expression.
*/
getRegexp(): RegExp {
return new RegExp(this.source, this.flags);
}
}

64
markdown/src/helpers.ts Normal file
View File

@ -0,0 +1,64 @@
/**
* @license
*
* Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
* https://github.com/chjj/marked
*
* Copyright (c) 2018, Костя Третяк. (MIT Licensed)
* https://github.com/ts-stack/markdown
*/
import type { Replacements } from "./interfaces.ts";
const escapeTest = /[&<>"']/;
const escapeReplace = /[&<>"']/g;
const replacements: Replacements = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
// tslint:disable-next-line:quotemark
"'": "&#39;",
};
const escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
const escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
export function escape(html: string, encode?: boolean) {
if (encode) {
if (escapeTest.test(html)) {
return html.replace(escapeReplace, (ch: string) => replacements[ch]);
}
} else {
if (escapeTestNoEncode.test(html)) {
return html.replace(
escapeReplaceNoEncode,
(ch: string) => replacements[ch]
);
}
}
return html;
}
export function unescape(html: string) {
// Explicitly match decimal, hex, and named HTML entities
return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi, function (
_,
n
) {
n = n.toLowerCase();
if (n === "colon") {
return ":";
}
if (n.charAt(0) === "#") {
return n.charAt(1) === "x"
? String.fromCharCode(parseInt(n.substring(2), 16))
: String.fromCharCode(+n.substring(1));
}
return "";
});
}

View File

@ -0,0 +1,419 @@
/**
* @license
*
* Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
* https://github.com/chjj/marked
*
* Copyright (c) 2018, Костя Третяк. (MIT Licensed)
* https://github.com/ts-stack/markdown
*/
import { ExtendRegexp } from "./extend-regexp.ts";
import type {
Link,
Links,
MarkedOptions,
RulesInlineBase,
RulesInlineBreaks,
RulesInlineCallback,
RulesInlineGfm,
RulesInlinePedantic,
} from "./interfaces.ts";
import { Marked } from "./marked.ts";
import { Renderer } from "./renderer.ts";
/**
* Inline Lexer & Compiler.
*/
export class InlineLexer {
protected static rulesBase: RulesInlineBase;
/**
* Pedantic Inline Grammar.
*/
protected static rulesPedantic: RulesInlinePedantic;
/**
* GFM Inline Grammar
*/
protected static rulesGfm: RulesInlineGfm;
/**
* GFM + Line Breaks Inline Grammar.
*/
protected static rulesBreaks: RulesInlineBreaks;
protected rules!:
| RulesInlineBase
| RulesInlinePedantic
| RulesInlineGfm
| RulesInlineBreaks;
protected renderer: Renderer;
protected inLink!: boolean;
protected hasRulesGfm!: boolean;
protected ruleCallbacks!: RulesInlineCallback[];
constructor(
protected staticThis: typeof InlineLexer,
protected links: Links,
protected options: MarkedOptions = Marked.options,
renderer?: Renderer
) {
this.renderer =
renderer || this.options.renderer || new Renderer(this.options);
if (!this.links) {
throw new Error(`InlineLexer requires 'links' parameter.`);
}
this.setRules();
}
/**
* Static Lexing/Compiling Method.
*/
static output(src: string, links: Links, options: MarkedOptions): string {
const inlineLexer = new this(this, links, options);
return inlineLexer.output(src);
}
protected static getRulesBase(): RulesInlineBase {
if (this.rulesBase) {
return this.rulesBase;
}
/**
* Inline-Level Grammar.
*/
const base: RulesInlineBase = {
escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
autolink: /^<([^ <>]+(@|:\/)[^ <>]+)>/,
tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^<'">])*?>/,
link: /^!?\[(inside)\]\(href\)/,
reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
code: /^(`+)([\s\S]*?[^`])\1(?!`)/,
br: /^ {2,}\n(?!\s*$)/,
text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/,
_inside: /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/,
_href: /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/,
};
base.link = new ExtendRegexp(base.link)
.setGroup("inside", base._inside)
.setGroup("href", base._href)
.getRegexp();
base.reflink = new ExtendRegexp(base.reflink)
.setGroup("inside", base._inside)
.getRegexp();
return (this.rulesBase = base);
}
protected static getRulesPedantic(): RulesInlinePedantic {
if (this.rulesPedantic) {
return this.rulesPedantic;
}
return (this.rulesPedantic = {
...this.getRulesBase(),
...{
strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
},
});
}
protected static getRulesGfm(): RulesInlineGfm {
if (this.rulesGfm) {
return this.rulesGfm;
}
const base = this.getRulesBase();
const escape = new ExtendRegexp(base.escape)
.setGroup("])", "~|])")
.getRegexp();
const text = new ExtendRegexp(base.text)
.setGroup("]|", "~]|")
.setGroup("|", "|https?://|")
.getRegexp();
return (this.rulesGfm = {
...base,
...{
escape,
url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
del: /^~~(?=\S)([\s\S]*?\S)~~/,
text,
},
});
}
protected static getRulesBreaks(): RulesInlineBreaks {
if (this.rulesBreaks) {
return this.rulesBreaks;
}
const inline = this.getRulesGfm();
const gfm = this.getRulesGfm();
return (this.rulesBreaks = {
...gfm,
...{
br: new ExtendRegexp(inline.br).setGroup("{2,}", "*").getRegexp(),
text: new ExtendRegexp(gfm.text).setGroup("{2,}", "*").getRegexp(),
},
});
}
protected setRules() {
if (this.options.gfm) {
if (this.options.breaks) {
this.rules = this.staticThis.getRulesBreaks();
} else {
this.rules = this.staticThis.getRulesGfm();
}
} else if (this.options.pedantic) {
this.rules = this.staticThis.getRulesPedantic();
} else {
this.rules = this.staticThis.getRulesBase();
}
this.hasRulesGfm = (this.rules as RulesInlineGfm).url !== undefined;
}
/**
* Lexing/Compiling.
*/
output(nextPart: string): string {
nextPart = nextPart;
let execArr: RegExpExecArray | null;
let out = "";
while (nextPart) {
// escape
if ((execArr = this.rules.escape.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
out += execArr[1];
continue;
}
// autolink
if ((execArr = this.rules.autolink.exec(nextPart))) {
let text: string;
let href: string;
nextPart = nextPart.substring(execArr[0].length);
if (!this.options.escape) throw ReferenceError;
if (execArr[2] === "@") {
text = this.options.escape(
execArr[1].charAt(6) === ":"
? this.mangle(execArr[1].substring(7))
: this.mangle(execArr[1])
);
href = this.mangle("mailto:") + text;
} else {
text = this.options.escape(execArr[1]);
href = text;
}
out += this.renderer.link(href, "", text);
continue;
}
// url (gfm)
if (
!this.inLink &&
this.hasRulesGfm &&
(execArr = (this.rules as RulesInlineGfm).url.exec(nextPart))
) {
if (!this.options.escape) throw ReferenceError;
let text: string;
let href: string;
nextPart = nextPart.substring(execArr[0].length);
text = this.options.escape(execArr[1]);
href = text;
out += this.renderer.link(href, "", text);
continue;
}
// tag
if ((execArr = this.rules.tag.exec(nextPart))) {
if (!this.inLink && /^<a /i.test(execArr[0])) {
this.inLink = true;
} else if (this.inLink && /^<\/a>/i.test(execArr[0])) {
this.inLink = false;
}
nextPart = nextPart.substring(execArr[0].length);
if (!this.options.escape) throw ReferenceError;
out += this.options.sanitize
? this.options.sanitizer
? this.options.sanitizer(execArr[0])
: this.options.escape(execArr[0])
: execArr[0];
continue;
}
// link
if ((execArr = this.rules.link.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
this.inLink = true;
out += this.outputLink(execArr, {
href: execArr[2],
title: execArr[3],
});
this.inLink = false;
continue;
}
// reflink, nolink
if (
(execArr = this.rules.reflink.exec(nextPart)) ||
(execArr = this.rules.nolink.exec(nextPart))
) {
nextPart = nextPart.substring(execArr[0].length);
const keyLink = (execArr[2] || execArr[1]).replace(/\s+/g, " ");
const link = this.links[keyLink.toLowerCase()];
if (!link || !link.href) {
out += execArr[0].charAt(0);
nextPart = execArr[0].substring(1) + nextPart;
continue;
}
this.inLink = true;
out += this.outputLink(execArr, link);
this.inLink = false;
continue;
}
// strong
if ((execArr = this.rules.strong.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
out += this.renderer.strong(this.output(execArr[2] || execArr[1]));
continue;
}
// em
if ((execArr = this.rules.em.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
out += this.renderer.em(this.output(execArr[2] || execArr[1]));
continue;
}
// code
if ((execArr = this.rules.code.exec(nextPart))) {
if (!this.options.escape) throw ReferenceError;
nextPart = nextPart.substring(execArr[0].length);
out += this.renderer.codespan(
this.options.escape(execArr[2].trim(), true)
);
continue;
}
// br
if ((execArr = this.rules.br.exec(nextPart))) {
nextPart = nextPart.substring(execArr[0].length);
out += this.renderer.br();
continue;
}
// del (gfm)
if (
this.hasRulesGfm &&
(execArr = (this.rules as RulesInlineGfm).del.exec(nextPart))
) {
nextPart = nextPart.substring(execArr[0].length);
out += this.renderer.del(this.output(execArr[1]));
continue;
}
// text
if ((execArr = this.rules.text.exec(nextPart))) {
if (!this.options.escape) throw ReferenceError;
nextPart = nextPart.substring(execArr[0].length);
out += this.renderer.text(
this.options.escape(this.smartypants(execArr[0]))
);
continue;
}
if (nextPart) {
throw new Error("Infinite loop on byte: " + nextPart.charCodeAt(0));
}
}
return out;
}
/**
* Compile Link.
*/
protected outputLink(execArr: RegExpExecArray, link: Link) {
if (!this.options.escape) throw ReferenceError;
const href = this.options.escape(link.href);
const title = link.title ? this.options.escape(link.title) : null;
return execArr[0].charAt(0) !== "!"
? this.renderer.link(href, title || "", this.output(execArr[1]))
: this.renderer.image(href, title || "", this.options.escape(execArr[1]));
}
/**
* Smartypants Transformations.
*/
protected smartypants(text: string) {
if (!this.options.smartypants) {
return text;
}
return (
text
// em-dashes
.replace(/---/g, "\u2014")
// en-dashes
.replace(/--/g, "\u2013")
// opening singles
.replace(/(^|[-\u2014/(\[{"\s])'/g, "$1\u2018")
// closing singles & apostrophes
.replace(/'/g, "\u2019")
// opening doubles
.replace(/(^|[-\u2014/(\[{\u2018\s])"/g, "$1\u201c")
// closing doubles
.replace(/"/g, "\u201d")
// ellipses
.replace(/\.{3}/g, "\u2026")
);
}
/**
* Mangle Links.
*/
protected mangle(text: string) {
if (!this.options.mangle) {
return text;
}
let out = "";
const length = text.length;
for (let i = 0; i < length; i++) {
let str: string = "";
if (Math.random() > 0.5) {
str = "x" + text.charCodeAt(i).toString(16);
}
out += "&#" + str + ";";
}
return out;
}
}

196
markdown/src/interfaces.ts Normal file
View File

@ -0,0 +1,196 @@
/**
* @license
*
* Copyright (c) 2018, Костя Третяк. (MIT Licensed)
* https://github.com/ts-stack/markdown
*/
import { escape, unescape } from "./helpers.ts";
import type { Renderer } from "./renderer.ts";
export interface Obj {
[key: string]: any;
}
export interface RulesBlockBase {
newline: RegExp;
code: RegExp;
hr: RegExp;
heading: RegExp;
lheading: RegExp;
blockquote: RegExp;
list: RegExp;
html: RegExp;
def: RegExp;
paragraph: RegExp;
text: RegExp;
bullet: RegExp;
/**
* List item (<li>).
*/
item: RegExp;
}
export interface RulesBlockGfm extends RulesBlockBase {
fences: RegExp;
}
export interface RulesBlockTables extends RulesBlockGfm {
nptable: RegExp;
table: RegExp;
}
export interface Link {
href: string;
title: string;
}
export interface Links {
[key: string]: Link;
}
export enum TokenType {
space = 1,
text,
paragraph,
heading,
listStart,
listEnd,
looseItemStart,
looseItemEnd,
listItemStart,
listItemEnd,
blockquoteStart,
blockquoteEnd,
code,
table,
html,
hr,
}
export type Align = "center" | "left" | "right" | "";
export interface Token {
type: number | string;
text?: string;
lang?: string;
depth?: number;
header?: string[];
align?: Align[];
cells?: string[][];
ordered?: boolean;
pre?: boolean;
escaped?: boolean;
execArr?: RegExpExecArray;
/**
* Used for debugging. Identifies the line number in the resulting HTML file.
*/
line?: number;
}
export interface RulesInlineBase {
escape: RegExp;
autolink: RegExp;
tag: RegExp;
link: RegExp;
reflink: RegExp;
nolink: RegExp;
strong: RegExp;
em: RegExp;
code: RegExp;
br: RegExp;
text: RegExp;
_inside: RegExp;
_href: RegExp;
}
export interface RulesInlinePedantic extends RulesInlineBase {}
/**
* GFM Inline Grammar
*/
export interface RulesInlineGfm extends RulesInlineBase {
url: RegExp;
del: RegExp;
}
export interface RulesInlineBreaks extends RulesInlineGfm {}
export class MarkedOptions {
gfm?: boolean = true;
tables?: boolean = true;
breaks?: boolean = false;
pedantic?: boolean = false;
sanitize?: boolean = false;
sanitizer?: (text: string) => string;
mangle?: boolean = false;
smartLists?: boolean = false;
silent?: boolean = false;
/**
* @param code The section of code to pass to the highlighter.
* @param lang The programming language specified in the code block.
*/
highlight?: (code: string, lang?: string) => string;
langPrefix?: string = "lang-";
smartypants?: boolean = false;
headerPrefix?: string = "";
/**
* An object containing functions to render tokens to HTML. Default: `new Renderer()`
*/
renderer?: Renderer;
/**
* Self-close the tags for void elements (&lt;br/&gt;, &lt;img/&gt;, etc.)
* with a "/" as required by XHTML.
*/
xhtml?: boolean = false;
/**
* The function that will be using to escape HTML entities.
* By default using inner helper.
*/
escape?: (html: string, encode?: boolean) => string = escape;
/**
* The function that will be using to unescape HTML entities.
* By default using inner helper.
*/
unescape?: (html: string) => string = unescape;
/**
* If set to `true`, an inline text will not be taken in paragraph.
*
* ```ts
* // isNoP == false
* Marked.parse('some text'); // returns '<p>some text</p>'
*
* Marked.setOptions({isNoP: true});
*
* Marked.parse('some text'); // returns 'some text'
* ```
*/
isNoP?: boolean;
}
export interface LexerReturns {
tokens: Token[];
links: Links;
meta: Obj;
}
export interface Parsed {
content: string;
meta: Obj;
}
export interface DebugReturns extends LexerReturns {
result: string;
}
export interface Replacements {
[key: string]: string;
}
export interface RulesInlineCallback {
regexp?: RegExp;
condition(): RegExp;
tokenize(execArr: RegExpExecArray): void;
}
export type SimpleRenderer = (execArr?: RegExpExecArray) => string;

154
markdown/src/marked.ts Normal file
View File

@ -0,0 +1,154 @@
/**
* @license
*
* Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
* https://github.com/chjj/marked
*
* Copyright (c) 2018, Костя Третяк. (MIT Licensed)
* https://github.com/ts-stack/markdown
*/
import { BlockLexer } from "./block-lexer.ts";
import {
DebugReturns,
LexerReturns,
Links,
MarkedOptions,
SimpleRenderer,
Token,
TokenType,
Parsed
} from "./interfaces.ts";
import { Parser } from "./parser.ts";
export class Marked {
static options = new MarkedOptions();
protected static simpleRenderers: SimpleRenderer[] = [];
protected static parsed: Parsed = {
content: "",
meta: {},
};
/**
* Merges the default options with options that will be set.
*
* @param options Hash of options.
*/
static setOptions(options: MarkedOptions) {
Object.assign(this.options, options);
return this;
}
/**
* Setting simple block rule.
*/
static setBlockRule(regexp: RegExp, renderer: SimpleRenderer = () => "") {
BlockLexer.simpleRules.push(regexp);
this.simpleRenderers.push(renderer);
return this;
}
/**
* Accepts Markdown text and returns an object containing HTML and metadata.
*
* @param src String of markdown source to be compiled.
* @param options Hash of options. They replace, but do not merge with the default options.
* If you want the merging, you can to do this via `Marked.setOptions()`.
*/
static parse(src: string, options: MarkedOptions = this.options): Parsed {
try {
const { tokens, links, meta } = this.callBlockLexer(src, options);
this.parsed.content = this.callParser(tokens, links, options);
this.parsed.meta = meta;
return this.parsed;
} catch (e) {
this.parsed.content = this.callMe(e);
return this.parsed;
}
}
/**
* Accepts Markdown text and returns object with text in HTML format,
* tokens and links from `BlockLexer.parser()`.
*
* @param src String of markdown source to be compiled.
* @param options Hash of options. They replace, but do not merge with the default options.
* If you want the merging, you can to do this via `Marked.setOptions()`.
*/
static debug(
src: string,
options: MarkedOptions = this.options,
): DebugReturns {
const { tokens, links, meta } = this.callBlockLexer(src, options);
let origin = tokens.slice();
const parser = new Parser(options);
parser.simpleRenderers = this.simpleRenderers;
const result = parser.debug(links, tokens);
/**
* Translates a token type into a readable form,
* and moves `line` field to a first place in a token object.
*/
origin = origin.map((token) => {
token.type = (TokenType as any)[token.type] || token.type;
const line = token.line;
delete token.line;
if (line) {
return { ...{ line }, ...token };
} else {
return token;
}
});
return { tokens: origin, links, meta, result};
}
protected static callBlockLexer(
src: string = "",
options?: MarkedOptions,
): LexerReturns {
if (typeof src != "string") {
throw new Error(
`Expected that the 'src' parameter would have a 'string' type, got '${typeof src}'`,
);
}
// Preprocessing.
src = src
.replace(/\r\n|\r/g, "\n")
.replace(/\t/g, " ")
.replace(/\u00a0/g, " ")
.replace(/\u2424/g, "\n")
.replace(/^ +$/gm, "");
return BlockLexer.lex(src, options, true);
}
protected static callParser(
tokens: Token[],
links: Links,
options?: MarkedOptions,
): string {
if (this.simpleRenderers.length) {
const parser = new Parser(options);
parser.simpleRenderers = this.simpleRenderers;
return parser.parse(links, tokens);
} else {
return Parser.parse(tokens, links, options);
}
}
protected static callMe(err: Error) {
err.message +=
"\nPlease report this to https://github.com/ts-stack/markdown";
if (this.options.silent && this.options.escape) {
return "<p>An error occured:</p><pre>" +
this.options.escape(err.message + "", true) + "</pre>";
}
throw err;
}
}

247
markdown/src/parser.ts Normal file
View File

@ -0,0 +1,247 @@
/**
* @license
*
* Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
* https://github.com/chjj/marked
*
* Copyright (c) 2018, Костя Третяк. (MIT Licensed)
* https://github.com/ts-stack/markdown
*/
import { InlineLexer } from "./inline-lexer.ts";
import {
Links,
MarkedOptions,
SimpleRenderer,
Token,
TokenType,
} from "./interfaces.ts";
import { Marked } from "./marked.ts";
import { Renderer } from "./renderer.ts";
/**
* Parsing & Compiling.
*/
export class Parser {
simpleRenderers: SimpleRenderer[] = [];
protected tokens: Token[];
protected token: Token | undefined;
protected inlineLexer!: InlineLexer;
protected options: MarkedOptions;
protected renderer: Renderer;
protected line: number = 0;
constructor(options?: MarkedOptions) {
this.tokens = [];
this.token = undefined;
this.options = options || Marked.options;
this.renderer = this.options.renderer || new Renderer(this.options);
}
static parse(tokens: Token[], links: Links, options?: MarkedOptions): string {
const parser = new this(options);
return parser.parse(links, tokens);
}
parse(links: Links, tokens: Token[]) {
this.inlineLexer = new InlineLexer(
InlineLexer,
links,
this.options,
this.renderer,
);
this.tokens = tokens.reverse();
let out = "";
while (this.next()) {
out += this.tok();
}
return out;
}
debug(links: Links, tokens: Token[]) {
this.inlineLexer = new InlineLexer(
InlineLexer,
links,
this.options,
this.renderer,
);
this.tokens = tokens.reverse();
let out = "";
while (this.next()) {
const outToken: string = this.tok() || "";
if (!this.token) throw ReferenceError;
this.token.line = this.line += outToken.split("\n").length - 1;
out += outToken;
}
return out;
}
protected next() {
return (this.token = this.tokens.pop());
}
protected getNextElement() {
return this.tokens[this.tokens.length - 1];
}
protected parseText() {
if (!this.token) throw ReferenceError;
let body = this.token.text;
let nextElement: Token;
while (
(nextElement = this.getNextElement()) &&
nextElement.type == TokenType.text
) {
body += "\n" + this.next()?.text;
}
return this.inlineLexer.output(body || "");
}
protected tok() {
if (!this.token) throw ReferenceError;
switch (this.token.type) {
case TokenType.space: {
return "";
}
case TokenType.paragraph: {
return this.renderer.paragraph(
this.inlineLexer.output(this.token.text || ""),
);
}
case TokenType.text: {
if (this.options.isNoP) {
return this.parseText();
} else {
return this.renderer.paragraph(this.parseText());
}
}
case TokenType.heading: {
return this.renderer.heading(
this.inlineLexer.output(this.token.text || ""),
this.token.depth || 0,
this.token.text || "",
);
}
case TokenType.listStart: {
let body = "";
const ordered = this.token.ordered;
while (this.next()?.type != TokenType.listEnd) {
body += this.tok();
}
return this.renderer.list(body, ordered);
}
case TokenType.listItemStart: {
let body = "";
while (this.next()?.type != TokenType.listItemEnd) {
body += this.token.type == (TokenType.text as any)
? this.parseText()
: this.tok();
}
return this.renderer.listitem(body);
}
case TokenType.looseItemStart: {
let body = "";
while (this.next()?.type != TokenType.listItemEnd) {
body += this.tok();
}
return this.renderer.listitem(body);
}
case TokenType.code: {
return this.renderer.code(
this.token.text || "",
this.token.lang,
this.token.escaped,
);
}
case TokenType.table: {
let header = "";
let body = "";
let cell;
if (
!this.token || !this.token.header || !this.token.align ||
!this.token.cells
) {
throw ReferenceError;
}
// header
cell = "";
for (let i = 0; i < this.token.header.length; i++) {
const flags = { header: true, align: this.token.align[i] };
const out = this.inlineLexer.output(this.token.header[i]);
cell += this.renderer.tablecell(out, flags);
}
header += this.renderer.tablerow(cell);
for (const row of this.token.cells) {
cell = "";
for (let j = 0; j < row.length; j++) {
cell += this.renderer.tablecell(this.inlineLexer.output(row[j]), {
header: false,
align: this.token.align[j],
});
}
body += this.renderer.tablerow(cell);
}
return this.renderer.table(header, body);
}
case TokenType.blockquoteStart: {
let body = "";
while (this.next()?.type != TokenType.blockquoteEnd) {
body += this.tok();
}
return this.renderer.blockquote(body);
}
case TokenType.hr: {
return this.renderer.hr();
}
case TokenType.html: {
const html = !this.token.pre && !this.options.pedantic
? this.inlineLexer.output(this.token.text || "")
: this.token.text;
return this.renderer.html(html || "");
}
default: {
if (this.simpleRenderers.length) {
for (let i = 0; i < this.simpleRenderers.length; i++) {
if (this.token.type == "simpleRule" + (i + 1)) {
return this.simpleRenderers[i].call(
this.renderer,
this.token.execArr,
);
}
}
}
const errMsg = `Token with "${this.token.type}" type was not found.`;
if (this.options.silent) {
console.log(errMsg);
} else {
throw new Error(errMsg);
}
}
}
}
}

179
markdown/src/renderer.ts Normal file
View File

@ -0,0 +1,179 @@
/**
* @license
*
* Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
* https://github.com/chjj/marked
*
* Copyright (c) 2018, Костя Третяк. (MIT Licensed)
* https://github.com/ts-stack/markdown
*/
import type { Align, MarkedOptions } from "./interfaces.ts";
import { Marked } from "./marked.ts";
export class Renderer {
protected options: MarkedOptions;
constructor(options?: MarkedOptions) {
this.options = options || Marked.options;
}
code(code: string, lang?: string, escaped?: boolean): string {
if (this.options.highlight) {
const out = this.options.highlight(code, lang);
if (out != null && out !== code) {
escaped = true;
code = out;
}
}
if (!this.options.escape) throw ReferenceError;
if (!lang) {
return (
"\n<pre><code>" +
(escaped ? code : this.options.escape(code, true)) +
"\n</code></pre>\n"
);
}
return (
'\n<pre><code class="' +
this.options.langPrefix +
this.options.escape(lang, true) +
'">' +
(escaped ? code : this.options.escape(code, true)) +
"\n</code></pre>\n"
);
}
blockquote(quote: string): string {
return "<blockquote>\n" + quote + "</blockquote>\n";
}
html(html: string): string {
return html;
}
heading(text: string, level: number, raw: string): string {
const id: string =
this.options.headerPrefix + raw.toLowerCase().replace(/[^\w]+/g, "-");
return `<h${level} id="${id}">${text}</h${level}>\n`;
}
hr(): string {
return this.options.xhtml ? "<hr/>\n" : "<hr>\n";
}
list(body: string, ordered?: boolean): string {
const type = ordered ? "ol" : "ul";
return `\n<${type}>\n${body}</${type}>\n`;
}
listitem(text: string): string {
return "<li>" + text + "</li>\n";
}
paragraph(text: string): string {
return "<p>" + text + "</p>\n";
}
table(header: string, body: string): string {
return `
<table>
<thead>
${header}</thead>
<tbody>
${body}</tbody>
</table>
`;
}
tablerow(content: string): string {
return "<tr>\n" + content + "</tr>\n";
}
tablecell(
content: string,
flags: { header?: boolean; align?: Align }
): string {
const type = flags.header ? "th" : "td";
const tag = flags.align
? "<" + type + ' style="text-align:' + flags.align + '">'
: "<" + type + ">";
return tag + content + "</" + type + ">\n";
}
// *** Inline level renderer methods. ***
strong(text: string): string {
return "<strong>" + text + "</strong>";
}
em(text: string): string {
return "<em>" + text + "</em>";
}
codespan(text: string): string {
return "<code>" + text + "</code>";
}
br(): string {
return this.options.xhtml ? "<br/>" : "<br>";
}
del(text: string): string {
return "<del>" + text + "</del>";
}
link(href: string, title: string, text: string): string {
if (this.options.sanitize) {
let prot: string;
if (!this.options.unescape) throw ReferenceError;
try {
prot = decodeURIComponent(this.options.unescape(href))
.replace(/[^\w:]/g, "")
.toLowerCase();
} catch (e) {
return text;
}
if (
prot.indexOf("javascript:") === 0 ||
prot.indexOf("vbscript:") === 0 ||
prot.indexOf("data:") === 0
) {
return text;
}
}
let out = '<a href="' + href + '"';
if (title) {
out += ' title="' + title + '"';
}
out += ">" + text + "</a>";
return out;
}
image(href: string, title: string, text: string): string {
let out = '<img src="' + href + '" alt="' + text + '"';
if (title) {
out += ' title="' + title + '"';
}
out += this.options.xhtml ? "/>" : ">";
return out;
}
text(text: string): string {
return text;
}
}

View File

@ -1,10 +1,11 @@
FROM hibas123.azurecr.io/deno
FROM docker.io/denoland/deno:alpine-1.38.3
WORKDIR /app
ADD src /app/src
RUN /usr/bin/deno cache --unstable src/registry.ts
ADD public /app/public
ADD deno.json /app/
RUN deno cache --unstable src/registry.ts
VOLUME [ "/app/data" ]
ENTRYPOINT [ "/usr/bin/deno", "run", "-A", "--unstable", "/app/src/registry.ts" ]
CMD [ "run", "-A", "--unstable", "/app/src/registry.ts" ]

19
registry/Earthfile Normal file
View File

@ -0,0 +1,19 @@
VERSION 0.7
FROM docker.io/runcitadel/deno:v1.29.3
WORKDIR /app
docker-multi:
BUILD --platform linux/amd64 --platform linux/arm64 +docker
docker:
COPY src /app/src
COPY public /app/public
COPY deno.json /app/
RUN deno cache --unstable src/registry.ts
CMD [ "run", "-A", "--unstable", "/app/src/registry.ts" ]
ARG EARTHLY_TARGET_TAG
ARG TAG=$EARTHLY_TARGET_TAG
SAVE IMAGE --push git.hibas.dev/deno/denreg:$TAG

19
registry/deno.json Normal file
View File

@ -0,0 +1,19 @@
{
"tasks": {
"start": "deno run --allow-net --allow-read index.tsx"
},
"imports": {
"nano-jsx": "https://deno.land/x/nano_jsx@v0.0.34/mod.ts",
"oak": "https://deno.land/x/oak@v10.6.0/mod.ts"
},
"compilerOptions": {
"lib": [
"dom",
"dom.iterable",
"dom.asynciterable",
"deno.ns"
],
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment"
}
}

388
registry/deno.lock generated Normal file
View File

@ -0,0 +1,388 @@
{
"version": "3",
"redirects": {
"https://deno.land/std/fs/mod.ts": "https://deno.land/std@0.208.0/fs/mod.ts",
"https://deno.land/std/path/mod.ts": "https://deno.land/std@0.208.0/path/mod.ts",
"https://deno.land/std/uuid/mod.ts": "https://deno.land/std@0.208.0/uuid/mod.ts",
"https://deno.land/x/base64/base64url.ts": "https://deno.land/x/base64@v0.2.1/base64url.ts",
"https://deno.land/x/nano_jsx/mod.ts": "https://deno.land/x/nano_jsx@v0.1.0/mod.ts",
"https://git.stamm.me/Deno/DenReg/raw/branch/master/tar/mod.ts": "https://git.hibas.dev/Deno/DenReg/raw/branch/master/tar/mod.ts"
},
"remote": {
"https://cdn.skypack.dev/-/@jsreport/mingo@v2.4.1-ZVYVnAnRedyuAPBNb9NZ/dist=es2019,mode=imports/optimized/@jsreport/mingo.js": "75213f47970810db2eaed8a551167ba85d301eeec879b21b8fce9faf61a68b33",
"https://cdn.skypack.dev/-/prismjs@v1.29.0-tsFxawAKDjgdZ80OeL0T/dist=es2019,mode=imports/optimized/prismjs.js": "4aa116c4194f957b8500bd5fbcec3b2cf9c9132dad3d1fcebebe634b9ef8603e",
"https://cdn.skypack.dev/@jsreport/mingo": "a2acca816e6078b3080e80b717fa09a9e0c7a805017d514536b0655b7dad79a7",
"https://cdn.skypack.dev/prismjs": "2f31eecf3dea3232b302fbc57b7d0383d8f27d4ce1b14c72b77989d33de16bd5",
"https://deno.hibas123.de/raw/ini@0.0.3/ini.ts": "436fba4744160024f02844ea255778c5009e65ececdccee65ff846e0edf5f829",
"https://deno.hibas123.de/raw/ini@0.0.3/mod.ts": "c04a10c3a9e7849149caaf7a9101dce60919345149797ac463f5a6778f3e062f",
"https://deno.hibas123.de/raw/markdown@0.1.0/mod.ts": "495ee5abb28bff8e6e4027819ece57f61342ef7715419675c1b1be24c47fc624",
"https://deno.hibas123.de/raw/markdown@0.1.0/src/block-lexer.ts": "8bb407abb7dc0cdf99eef9610c67812057749a36f7ffddc87aa6ce30ece3df71",
"https://deno.hibas123.de/raw/markdown@0.1.0/src/extend-regexp.ts": "187bbc8527a00add37f05790af39e0a242dd2064270ab52a536f104d76634ab7",
"https://deno.hibas123.de/raw/markdown@0.1.0/src/helpers.ts": "5cfea4e14aed4dc1964c006bab11f83444f51db5cfdeeb9d94e0463f5fa3f369",
"https://deno.hibas123.de/raw/markdown@0.1.0/src/inline-lexer.ts": "8e665c6540dd2dac5a71e4b0e67546b32315e7e2593ed076d4b5aecc03715df0",
"https://deno.hibas123.de/raw/markdown@0.1.0/src/interfaces.ts": "fe985b08281f5e00e658aed72b16d1c890f465683f27e357b4aa34b26ff4e748",
"https://deno.hibas123.de/raw/markdown@0.1.0/src/marked.ts": "36cacb1b13527429bf48935d0fed1f715e71238375ba5163054d57cb6ebbe732",
"https://deno.hibas123.de/raw/markdown@0.1.0/src/parser.ts": "3b200dc5ca451f7309d794da517c8b80cfe333c3636e5beb168b29b952f10f9a",
"https://deno.hibas123.de/raw/markdown@0.1.0/src/renderer.ts": "5437d447a90e6bdff628dde6c5e56d2210bc979661c47850576dc9ed9372334b",
"https://deno.land/std@0.208.0/assert/assert.ts": "9a97dad6d98c238938e7540736b826440ad8c1c1e54430ca4c4e623e585607ee",
"https://deno.land/std@0.208.0/assert/assertion_error.ts": "4d0bde9b374dfbcbe8ac23f54f567b77024fb67dbb1906a852d67fe050d42f56",
"https://deno.land/std@0.208.0/bytes/concat.ts": "d3d420badeb4f26a0f2f3ce343725f937326aff1b4634b25341b12b27353aac4",
"https://deno.land/std@0.208.0/bytes/copy.ts": "939d89e302a9761dcf1d9c937c7711174ed74c59eef40a1e4569a05c9de88219",
"https://deno.land/std@0.208.0/crypto/_fnv/fnv32.ts": "e4649dfdefc5c987ed53c3c25db62db771a06d9d1b9c36d2b5cf0853b8e82153",
"https://deno.land/std@0.208.0/crypto/_fnv/fnv64.ts": "bfa0e4702061fdb490a14e6bf5f9168a22fb022b307c5723499469bfefca555e",
"https://deno.land/std@0.208.0/crypto/_fnv/mod.ts": "f956a95f58910f223e420340b7404702ecd429603acd4491fa77af84f746040c",
"https://deno.land/std@0.208.0/crypto/_fnv/util.ts": "accba12bfd80a352e32a872f87df2a195e75561f1b1304a4cb4f5a4648d288f9",
"https://deno.land/std@0.208.0/crypto/_wasm/lib/deno_std_wasm_crypto.generated.mjs": "c41c4676a3ea2a92e8fdff55434533474131e4dfac2262a6a6c81631069808d8",
"https://deno.land/std@0.208.0/crypto/_wasm/mod.ts": "d7b7dc54bbd6b02c16cd08e8e3d30fa9aa9692efb112a7ab5d8595827b9a0234",
"https://deno.land/std@0.208.0/crypto/crypto.ts": "91c67764abb640b3e2a0b46867704d02077c0b1f978f5c711e4408e5d856717d",
"https://deno.land/std@0.208.0/encoding/_util.ts": "f368920189c4fe6592ab2e93bd7ded8f3065b84f95cd3e036a4a10a75649dcba",
"https://deno.land/std@0.208.0/encoding/base64.ts": "81c0ecff5ccb402def58ca03d8bd245bd01da15a077d3362b568e991aa10f4d9",
"https://deno.land/std@0.208.0/fs/_util.ts": "fbf57dcdc9f7bc8128d60301eece608246971a7836a3bb1e78da75314f08b978",
"https://deno.land/std@0.208.0/fs/copy.ts": "ca19e4837965914471df38fbd61e16f9e8adfe89f9cffb0c83615c83ea3fc2bf",
"https://deno.land/std@0.208.0/fs/empty_dir.ts": "7fba29ef2d03f3503cd512616efc0535984cf1bbe7ca9d098e8b4d0d88910120",
"https://deno.land/std@0.208.0/fs/ensure_dir.ts": "dc64c4c75c64721d4e3fb681f1382f803ff3d2868f08563ff923fdd20d071c40",
"https://deno.land/std@0.208.0/fs/ensure_file.ts": "39ac83cc283a20ec2735e956adf5de3e8a3334e0b6820547b5772f71c49ae083",
"https://deno.land/std@0.208.0/fs/ensure_link.ts": "c15e69c48556d78aae31b83e0c0ece04b7b8bc0951412f5b759aceb6fde7f0ac",
"https://deno.land/std@0.208.0/fs/ensure_symlink.ts": "b389c8568f0656d145ac7ece472afe710815cccbb2ebfd19da7978379ae143fe",
"https://deno.land/std@0.208.0/fs/eol.ts": "8565e1e076c5baced170236617150a7833668658e000205d896fc54084309ce1",
"https://deno.land/std@0.208.0/fs/exists.ts": "cb59a853d84871d87acab0e7936a4dac11282957f8e195102c5a7acb42546bb8",
"https://deno.land/std@0.208.0/fs/expand_glob.ts": "4f98c508fc9e40d6311d2f7fd88aaad05235cc506388c22dda315e095305811d",
"https://deno.land/std@0.208.0/fs/mod.ts": "bc3d0acd488cc7b42627044caf47d72019846d459279544e1934418955ba4898",
"https://deno.land/std@0.208.0/fs/move.ts": "b4f8f46730b40c32ea3c0bc8eb0fd0e8139249a698883c7b3756424cf19785c9",
"https://deno.land/std@0.208.0/fs/walk.ts": "c1e6b43f72a46e89b630140308bd51a4795d416a416b4cfb7cd4bd1e25946723",
"https://deno.land/std@0.208.0/io/buffer.ts": "11acaeae3dc0e491a335d82915e09e9f8afd53ecb82562515e5951e78f69b076",
"https://deno.land/std@0.208.0/path/_common/assert_path.ts": "061e4d093d4ba5aebceb2c4da3318bfe3289e868570e9d3a8e327d91c2958946",
"https://deno.land/std@0.208.0/path/_common/basename.ts": "0d978ff818f339cd3b1d09dc914881f4d15617432ae519c1b8fdc09ff8d3789a",
"https://deno.land/std@0.208.0/path/_common/common.ts": "9e4233b2eeb50f8b2ae10ecc2108f58583aea6fd3e8907827020282dc2b76143",
"https://deno.land/std@0.208.0/path/_common/constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0",
"https://deno.land/std@0.208.0/path/_common/dirname.ts": "2ba7fb4cc9fafb0f38028f434179579ce61d4d9e51296fad22b701c3d3cd7397",
"https://deno.land/std@0.208.0/path/_common/format.ts": "11aa62e316dfbf22c126917f5e03ea5fe2ee707386555a8f513d27ad5756cf96",
"https://deno.land/std@0.208.0/path/_common/from_file_url.ts": "ef1bf3197d2efbf0297a2bdbf3a61d804b18f2bcce45548ae112313ec5be3c22",
"https://deno.land/std@0.208.0/path/_common/glob_to_reg_exp.ts": "5c3c2b79fc2294ec803d102bd9855c451c150021f452046312819fbb6d4dc156",
"https://deno.land/std@0.208.0/path/_common/normalize.ts": "2ba7fb4cc9fafb0f38028f434179579ce61d4d9e51296fad22b701c3d3cd7397",
"https://deno.land/std@0.208.0/path/_common/normalize_string.ts": "88c472f28ae49525f9fe82de8c8816d93442d46a30d6bb5063b07ff8a89ff589",
"https://deno.land/std@0.208.0/path/_common/relative.ts": "1af19d787a2a84b8c534cc487424fe101f614982ae4851382c978ab2216186b4",
"https://deno.land/std@0.208.0/path/_common/strip_trailing_separators.ts": "7ffc7c287e97bdeeee31b155828686967f222cd73f9e5780bfe7dfb1b58c6c65",
"https://deno.land/std@0.208.0/path/_common/to_file_url.ts": "a8cdd1633bc9175b7eebd3613266d7c0b6ae0fb0cff24120b6092ac31662f9ae",
"https://deno.land/std@0.208.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b",
"https://deno.land/std@0.208.0/path/_os.ts": "30b0c2875f360c9296dbe6b7f2d528f0f9c741cecad2e97f803f5219e91b40a2",
"https://deno.land/std@0.208.0/path/basename.ts": "04bb5ef3e86bba8a35603b8f3b69537112cdd19ce64b77f2522006da2977a5f3",
"https://deno.land/std@0.208.0/path/common.ts": "f4d061c7d0b95a65c2a1a52439edec393e906b40f1caf4604c389fae7caa80f5",
"https://deno.land/std@0.208.0/path/dirname.ts": "88a0a71c21debafc4da7a4cd44fd32e899462df458fbca152390887d41c40361",
"https://deno.land/std@0.208.0/path/extname.ts": "2da4e2490f3b48b7121d19fb4c91681a5e11bd6bd99df4f6f47d7a71bb6ecdf2",
"https://deno.land/std@0.208.0/path/format.ts": "3457530cc85d1b4bab175f9ae73998b34fd456c830d01883169af0681b8894fb",
"https://deno.land/std@0.208.0/path/from_file_url.ts": "e7fa233ea1dff9641e8d566153a24d95010110185a6f418dd2e32320926043f8",
"https://deno.land/std@0.208.0/path/glob.ts": "a00a81a55c02bbe074ab21a50b6495c6f7795f54cd718c824adaa92c6c9b7419",
"https://deno.land/std@0.208.0/path/glob_to_regexp.ts": "74d7448c471e293d03f05ccb968df4365fed6aaa508506b6325a8efdc01d8271",
"https://deno.land/std@0.208.0/path/is_absolute.ts": "67232b41b860571c5b7537f4954c88d86ae2ba45e883ee37d3dec27b74909d13",
"https://deno.land/std@0.208.0/path/is_glob.ts": "567dce5c6656bdedfc6b3ee6c0833e1e4db2b8dff6e62148e94a917f289c06ad",
"https://deno.land/std@0.208.0/path/join.ts": "98d3d76c819af4a11a81d5ba2dbb319f1ce9d63fc2b615597d4bcfddd4a89a09",
"https://deno.land/std@0.208.0/path/join_globs.ts": "9b84d5103b63d3dbed4b2cf8b12477b2ad415c7d343f1488505162dc0e5f4db8",
"https://deno.land/std@0.208.0/path/mod.ts": "3defabebc98279e62b392fee7a6937adc932a8f4dcd2471441e36c15b97b00e0",
"https://deno.land/std@0.208.0/path/normalize.ts": "aa95be9a92c7bd4f9dc0ba51e942a1973e2b93d266cd74f5ca751c136d520b66",
"https://deno.land/std@0.208.0/path/normalize_glob.ts": "674baa82e1c00b6cb153bbca36e06f8e0337cb8062db6d905ab5de16076ca46b",
"https://deno.land/std@0.208.0/path/parse.ts": "d87ff0deef3fb495bc0d862278ff96da5a06acf0625ca27769fc52ac0d3d6ece",
"https://deno.land/std@0.208.0/path/posix/_util.ts": "ecf49560fedd7dd376c6156cc5565cad97c1abe9824f4417adebc7acc36c93e5",
"https://deno.land/std@0.208.0/path/posix/basename.ts": "a630aeb8fd8e27356b1823b9dedd505e30085015407caa3396332752f6b8406a",
"https://deno.land/std@0.208.0/path/posix/common.ts": "e781d395dc76f6282e3f7dd8de13194abb8b04a82d109593141abc6e95755c8b",
"https://deno.land/std@0.208.0/path/posix/dirname.ts": "f48c9c42cc670803b505478b7ef162c7cfa9d8e751b59d278b2ec59470531472",
"https://deno.land/std@0.208.0/path/posix/extname.ts": "ee7f6571a9c0a37f9218fbf510c440d1685a7c13082c348d701396cc795e0be0",
"https://deno.land/std@0.208.0/path/posix/format.ts": "b94876f77e61bfe1f147d5ccb46a920636cd3cef8be43df330f0052b03875968",
"https://deno.land/std@0.208.0/path/posix/from_file_url.ts": "b97287a83e6407ac27bdf3ab621db3fccbf1c27df0a1b1f20e1e1b5acf38a379",
"https://deno.land/std@0.208.0/path/posix/glob_to_regexp.ts": "6ed00c71fbfe0ccc35977c35444f94e82200b721905a60bd1278b1b768d68b1a",
"https://deno.land/std@0.208.0/path/posix/is_absolute.ts": "159900a3422d11069d48395568217eb7fc105ceda2683d03d9b7c0f0769e01b8",
"https://deno.land/std@0.208.0/path/posix/is_glob.ts": "ec4fbc604b9db8487f7b56ab0e759b24a971ab6a45f7b0b698bc39b8b9f9680f",
"https://deno.land/std@0.208.0/path/posix/join.ts": "0c0d84bdc344876930126640011ec1b888e6facf74153ffad9ef26813aa2a076",
"https://deno.land/std@0.208.0/path/posix/join_globs.ts": "f4838d54b1f60a34a40625a3293f6e583135348be1b2974341ac04743cb26121",
"https://deno.land/std@0.208.0/path/posix/mod.ts": "f1b08a7f64294b7de87fc37190d63b6ce5b02889af9290c9703afe01951360ae",
"https://deno.land/std@0.208.0/path/posix/normalize.ts": "11de90a94ab7148cc46e5a288f7d732aade1d616bc8c862f5560fa18ff987b4b",
"https://deno.land/std@0.208.0/path/posix/normalize_glob.ts": "10a1840c628ebbab679254d5fa1c20e59106102354fb648a1765aed72eb9f3f9",
"https://deno.land/std@0.208.0/path/posix/parse.ts": "199208f373dd93a792e9c585352bfc73a6293411bed6da6d3bc4f4ef90b04c8e",
"https://deno.land/std@0.208.0/path/posix/relative.ts": "e2f230608b0f083e6deaa06e063943e5accb3320c28aef8d87528fbb7fe6504c",
"https://deno.land/std@0.208.0/path/posix/resolve.ts": "51579d83159d5c719518c9ae50812a63959bbcb7561d79acbdb2c3682236e285",
"https://deno.land/std@0.208.0/path/posix/separator.ts": "0b6573b5f3269a3164d8edc9cefc33a02dd51003731c561008c8bb60220ebac1",
"https://deno.land/std@0.208.0/path/posix/to_file_url.ts": "08d43ea839ee75e9b8b1538376cfe95911070a655cd312bc9a00f88ef14967b6",
"https://deno.land/std@0.208.0/path/posix/to_namespaced_path.ts": "c9228a0e74fd37e76622cd7b142b8416663a9b87db643302fa0926b5a5c83bdc",
"https://deno.land/std@0.208.0/path/relative.ts": "23d45ede8b7ac464a8299663a43488aad6b561414e7cbbe4790775590db6349c",
"https://deno.land/std@0.208.0/path/resolve.ts": "5b184efc87155a0af9fa305ff68a109e28de9aee81fc3e77cd01380f19daf867",
"https://deno.land/std@0.208.0/path/separator.ts": "40a3e9a4ad10bef23bc2cd6c610291b6c502a06237c2c4cd034a15ca78dedc1f",
"https://deno.land/std@0.208.0/path/to_file_url.ts": "edaafa089e0bce386e1b2d47afe7c72e379ff93b28a5829a5885e4b6c626d864",
"https://deno.land/std@0.208.0/path/to_namespaced_path.ts": "cf8734848aac3c7527d1689d2adf82132b1618eff3cc523a775068847416b22a",
"https://deno.land/std@0.208.0/path/windows/_util.ts": "f32b9444554c8863b9b4814025c700492a2b57ff2369d015360970a1b1099d54",
"https://deno.land/std@0.208.0/path/windows/basename.ts": "8a9dbf7353d50afbc5b221af36c02a72c2d1b2b5b9f7c65bf6a5a2a0baf88ad3",
"https://deno.land/std@0.208.0/path/windows/common.ts": "e781d395dc76f6282e3f7dd8de13194abb8b04a82d109593141abc6e95755c8b",
"https://deno.land/std@0.208.0/path/windows/dirname.ts": "5c2aa541384bf0bd9aca821275d2a8690e8238fa846198ef5c7515ce31a01a94",
"https://deno.land/std@0.208.0/path/windows/extname.ts": "07f4fa1b40d06a827446b3e3bcc8d619c5546b079b8ed0c77040bbef716c7614",
"https://deno.land/std@0.208.0/path/windows/format.ts": "343019130d78f172a5c49fdc7e64686a7faf41553268961e7b6c92a6d6548edf",
"https://deno.land/std@0.208.0/path/windows/from_file_url.ts": "d53335c12b0725893d768be3ac6bf0112cc5b639d2deb0171b35988493b46199",
"https://deno.land/std@0.208.0/path/windows/glob_to_regexp.ts": "290755e18ec6c1a4f4d711c3390537358e8e3179581e66261a0cf348b1a13395",
"https://deno.land/std@0.208.0/path/windows/is_absolute.ts": "245b56b5f355ede8664bd7f080c910a97e2169972d23075554ae14d73722c53c",
"https://deno.land/std@0.208.0/path/windows/is_glob.ts": "ec4fbc604b9db8487f7b56ab0e759b24a971ab6a45f7b0b698bc39b8b9f9680f",
"https://deno.land/std@0.208.0/path/windows/join.ts": "e6600bf88edeeef4e2276e155b8de1d5dec0435fd526ba2dc4d37986b2882f16",
"https://deno.land/std@0.208.0/path/windows/join_globs.ts": "f4838d54b1f60a34a40625a3293f6e583135348be1b2974341ac04743cb26121",
"https://deno.land/std@0.208.0/path/windows/mod.ts": "d7040f461465c2c21c1c68fc988ef0bdddd499912138cde3abf6ad60c7fb3814",
"https://deno.land/std@0.208.0/path/windows/normalize.ts": "9deebbf40c81ef540b7b945d4ccd7a6a2c5a5992f791e6d3377043031e164e69",
"https://deno.land/std@0.208.0/path/windows/normalize_glob.ts": "344ff5ed45430495b9a3d695567291e50e00b1b3b04ea56712a2acf07ab5c128",
"https://deno.land/std@0.208.0/path/windows/parse.ts": "120faf778fe1f22056f33ded069b68e12447668fcfa19540c0129561428d3ae5",
"https://deno.land/std@0.208.0/path/windows/relative.ts": "026855cd2c36c8f28f1df3c6fbd8f2449a2aa21f48797a74700c5d872b86d649",
"https://deno.land/std@0.208.0/path/windows/resolve.ts": "5ff441ab18a2346abadf778121128ee71bda4d0898513d4639a6ca04edca366b",
"https://deno.land/std@0.208.0/path/windows/separator.ts": "ae21f27015f10510ed1ac4a0ba9c4c9c967cbdd9d9e776a3e4967553c397bd5d",
"https://deno.land/std@0.208.0/path/windows/to_file_url.ts": "8e9ea9e1ff364aa06fa72999204229952d0a279dbb876b7b838b2b2fea55cce3",
"https://deno.land/std@0.208.0/path/windows/to_namespaced_path.ts": "e0f4d4a5e77f28a5708c1a33ff24360f35637ba6d8f103d19661255ef7bfd50d",
"https://deno.land/std@0.208.0/streams/_common.ts": "3b2c1f0287ce2ad51fff4091a7d0f48375c85b0ec341468e76d5ac13bb0014dd",
"https://deno.land/std@0.208.0/streams/buffer.ts": "6cd773d22cf21bb988a98cc551b5abfc4c3b03516f93eaa3fb6f2f6e16032deb",
"https://deno.land/std@0.208.0/streams/byte_slice_stream.ts": "c46d7c74836fc8c1a9acd9fe211cbe1bbaaee1b36087c834fb03af4991135c3a",
"https://deno.land/std@0.208.0/streams/copy.ts": "faa201291ce9116fb1fae9d16b4f033e259fdea437b77404ff5cf742507844e6",
"https://deno.land/std@0.208.0/streams/delimiter_stream.ts": "af7aab15d830636265c998ca330576edb6a50959fec1949d2fa57ef8dda299d2",
"https://deno.land/std@0.208.0/streams/early_zip_readable_streams.ts": "4005fa74162b943f79899e5d7cb96adcbc0a6b867f9144974ed12d30e0a556e1",
"https://deno.land/std@0.208.0/streams/iterate_reader.ts": "d6b2770f8ee27fb1c1e2c5a3c66451647f6fb5371534c78bef2ce614d60568d8",
"https://deno.land/std@0.208.0/streams/limited_bytes_transform_stream.ts": "05dc592ffaab83257494d22dd53917e56243c26e5e3129b3f13ddbbbc4785048",
"https://deno.land/std@0.208.0/streams/limited_transform_stream.ts": "d69ab790232c1b86f53621ad41ef03c235f2abb4b7a1cd51960ad6e12ee55e38",
"https://deno.land/std@0.208.0/streams/merge_readable_streams.ts": "22963b9bbec8d000d9613db859002768e013fd731cafd55942dc0120d03e7b5d",
"https://deno.land/std@0.208.0/streams/mod.ts": "e133c271474f1e9dc19f5c4959406f5c2101540c56a3e7d7abc6bdb7bcef807e",
"https://deno.land/std@0.208.0/streams/read_all.ts": "64bfb842f4047f81d977dead27b6e5a9faaba17c8f1c30066284553dcfc13171",
"https://deno.land/std@0.208.0/streams/readable_stream_from_reader.ts": "c28abb70a35c683f522b6bd43d39c272db33d86d874c59e728e26f270956b773",
"https://deno.land/std@0.208.0/streams/reader_from_iterable.ts": "4fd184770b3756987b97c7718df3f5c4a2828b50e1cdc33111827d640dca6366",
"https://deno.land/std@0.208.0/streams/reader_from_stream_reader.ts": "6fb8852fdd9775ce940a4facf6e265f1f233cc3b90f6d064b1556f6b0ef3d18b",
"https://deno.land/std@0.208.0/streams/text_delimiter_stream.ts": "f0dc8ff953a8a77f0d1fa8db1fee62de817f36e20d79b00b1362847e30fbdd90",
"https://deno.land/std@0.208.0/streams/text_line_stream.ts": "4958525688593d20c1c439a006dabd64881736bff642744ca060b2c34b40c240",
"https://deno.land/std@0.208.0/streams/to_array_buffer.ts": "31b0729f6527054760a3758e84d6d646eac0f7f586204a81824c3eb7728ce836",
"https://deno.land/std@0.208.0/streams/to_blob.ts": "4cf929b3ffe5d4dbe445d572246159ee2eebf69e998a0ba867b9048fb6e92797",
"https://deno.land/std@0.208.0/streams/to_json.ts": "10635fac9826392bb8e70bc8354d3beb1058fa1676aa9b6f98257a0d5575f520",
"https://deno.land/std@0.208.0/streams/to_text.ts": "4018b5f7a0e7ab28d6957c239e401f8b534ef326b7ebd282ca76b3cd55380aab",
"https://deno.land/std@0.208.0/streams/to_transform_stream.ts": "50af06140c414090df8c3879f46bed4043a5d73caa60352c0c9682a88ec7a8c9",
"https://deno.land/std@0.208.0/streams/writable_stream_from_writer.ts": "057bdfc6c08e34a8a86e2d61efe7354a8a0976260cd1437de8b7e64bcefaa9b9",
"https://deno.land/std@0.208.0/streams/write_all.ts": "8fc9525c16eb60eb851274d4693ecd35c2177620239fbdfa8f5aacb32702f2cb",
"https://deno.land/std@0.208.0/streams/writer_from_stream_writer.ts": "71d7a26f2a2b955794a7318856ad64d9eade36467d930b40698d3d5bfb0ce3b4",
"https://deno.land/std@0.208.0/streams/zip_readable_streams.ts": "721c5bce8862c8225e60995b2d61c7b1b1d5b5178b60d303a01f453d5c26bb62",
"https://deno.land/std@0.208.0/uuid/_common.ts": "cb1441f4df460571fc0919e1c5c217f3e7006189b703caf946604b3f791ae34d",
"https://deno.land/std@0.208.0/uuid/constants.ts": "0d0e95561343da44adb4a4edbc1f04cef48b0d75288c4d1704f58743f4a50d88",
"https://deno.land/std@0.208.0/uuid/mod.ts": "5c7ca252dddba1ddf0bca2dc1124328245272650c98251d71996bb9cd8f5a386",
"https://deno.land/std@0.208.0/uuid/v1.ts": "fe36009afce7ced96e1b5928565e12c5a8eb0df1a2b5063c0a72bda6b75c0de5",
"https://deno.land/std@0.208.0/uuid/v3.ts": "397ad58daec8b5ef6ba7e94fe86c9bc56b194adcbe2f70ec40a1fb005203c870",
"https://deno.land/std@0.208.0/uuid/v4.ts": "0f081880c156fd59b9e44e2f84ea0f94a3627e89c224eaf6cc982b53d849f37e",
"https://deno.land/std@0.208.0/uuid/v5.ts": "9daaf769e487b512d25adf8e137e05ff2e3392d27f66d5b273ee28030ff7cd58",
"https://deno.land/std@0.208.0/yaml/_dumper/dumper.ts": "717403d0e700de783f2ef5c906b3d7245383e1509fc050e7ff5d4a53a03dbf40",
"https://deno.land/std@0.208.0/yaml/_dumper/dumper_state.ts": "f0d0673ceea288334061ca34b63954c2bb5feb5bf6de5e4cfe9a942cdf6e5efe",
"https://deno.land/std@0.208.0/yaml/_error.ts": "b59e2c76ce5a47b1b9fa0ff9f96c1dd92ea1e1b17ce4347ece5944a95c3c1a84",
"https://deno.land/std@0.208.0/yaml/_loader/loader.ts": "63ec7f0a265dbbabc54b25a4beefff7650e205160a2d75c7d8f8363b5f84851a",
"https://deno.land/std@0.208.0/yaml/_loader/loader_state.ts": "0841870b467169269d7c2dfa75cd288c319bc06f65edd9e42c29e5fced91c7a4",
"https://deno.land/std@0.208.0/yaml/_mark.ts": "dcd8585dee585e024475e9f3fe27d29740670fb64ebb970388094cad0fc11d5d",
"https://deno.land/std@0.208.0/yaml/_state.ts": "ef03d55ec235d48dcfbecc0ab3ade90bfae69a61094846e08003421c2cf5cfc6",
"https://deno.land/std@0.208.0/yaml/_type/binary.ts": "24d49614463a7339a8a16d894919c2ec18a10588ae360ec352093b60e2cc8b0d",
"https://deno.land/std@0.208.0/yaml/_type/bool.ts": "5bfa75da84343d45347b521ba4e5aeace9fe6f53447405290d53315a3fc20e66",
"https://deno.land/std@0.208.0/yaml/_type/float.ts": "056bd3cb9c5586238b20517511014fb24b0e36f98f9f6073e12da308b6b9808a",
"https://deno.land/std@0.208.0/yaml/_type/function.ts": "ff574fe84a750695302864e1c31b93f12d14ada4bde79a5f93197fc33ad17471",
"https://deno.land/std@0.208.0/yaml/_type/int.ts": "563ad074f0fa7aecf6b6c3d84135bcc95a8269dcc15de878de20ce868fd773fa",
"https://deno.land/std@0.208.0/yaml/_type/map.ts": "7b105e4ab03a361c61e7e335a0baf4d40f06460b13920e5af3fb2783a1464000",
"https://deno.land/std@0.208.0/yaml/_type/merge.ts": "8192bf3e4d637f32567917f48bb276043da9cf729cf594e5ec191f7cd229337e",
"https://deno.land/std@0.208.0/yaml/_type/mod.ts": "060e2b3d38725094b77ea3a3f05fc7e671fced8e67ca18e525be98c4aa8f4bbb",
"https://deno.land/std@0.208.0/yaml/_type/nil.ts": "606e8f0c44d73117c81abec822f89ef81e40f712258c74f186baa1af659b8887",
"https://deno.land/std@0.208.0/yaml/_type/omap.ts": "cfe59a294726f5cea705c39a61fd2b08199cf48f4ccd6b040cb550ec0f38d0a1",
"https://deno.land/std@0.208.0/yaml/_type/pairs.ts": "0032fdfe57558d21696a4f8cf5b5cfd1f698743177080affc18629685c905666",
"https://deno.land/std@0.208.0/yaml/_type/regexp.ts": "1ce118de15b2da43b4bd8e4395f42d448b731acf3bdaf7c888f40789f9a95f8b",
"https://deno.land/std@0.208.0/yaml/_type/seq.ts": "95333abeec8a7e4d967b8c8328b269e342a4bbdd2585395549b9c4f58c8533a2",
"https://deno.land/std@0.208.0/yaml/_type/set.ts": "f28ba44e632ef2a6eb580486fd47a460445eeddbdf1dbc739c3e62486f566092",
"https://deno.land/std@0.208.0/yaml/_type/str.ts": "a67a3c6e429d95041399e964015511779b1130ea5889fa257c48457bd3446e31",
"https://deno.land/std@0.208.0/yaml/_type/timestamp.ts": "706ea80a76a73e48efaeb400ace087da1f927647b53ad6f754f4e06d51af087f",
"https://deno.land/std@0.208.0/yaml/_type/undefined.ts": "94a316ca450597ccbc6750cbd79097ad0d5f3a019797eed3c841a040c29540ba",
"https://deno.land/std@0.208.0/yaml/_utils.ts": "26b311f0d42a7ce025060bd6320a68b50e52fd24a839581eb31734cd48e20393",
"https://deno.land/std@0.208.0/yaml/mod.ts": "28ecda6652f3e7a7735ee29c247bfbd32a2e2fc5724068e9fd173ec4e59f66f7",
"https://deno.land/std@0.208.0/yaml/parse.ts": "1fbbda572bf3fff578b6482c0d8b85097a38de3176bf3ab2ca70c25fb0c960ef",
"https://deno.land/std@0.208.0/yaml/schema.ts": "96908b78dc50c340074b93fc1598d5e7e2fe59103f89ff81e5a49b2dedf77a67",
"https://deno.land/std@0.208.0/yaml/schema/core.ts": "fa406f18ceedc87a50e28bb90ec7a4c09eebb337f94ef17468349794fa828639",
"https://deno.land/std@0.208.0/yaml/schema/default.ts": "0047e80ae8a4a93293bc4c557ae8a546aabd46bb7165b9d9b940d57b4d88bde9",
"https://deno.land/std@0.208.0/yaml/schema/extended.ts": "0784416bf062d20a1626b53c03380e265b3e39b9409afb9f4cb7d659fd71e60d",
"https://deno.land/std@0.208.0/yaml/schema/failsafe.ts": "d219ab5febc43f770917d8ec37735a4b1ad671149846cbdcade767832b42b92b",
"https://deno.land/std@0.208.0/yaml/schema/json.ts": "5f41dd7c2f1ad545ef6238633ce9ee3d444dfc5a18101e1768bd5504bf90e5e5",
"https://deno.land/std@0.208.0/yaml/schema/mod.ts": "4472e827bab5025e92bc2eb2eeefa70ecbefc64b2799b765c69af84822efef32",
"https://deno.land/std@0.208.0/yaml/stringify.ts": "fffc09c65c68d3d63f8159e8cbaa3f489bc20a8e55b4fbb61a8c2e9f914d1d02",
"https://deno.land/std@0.208.0/yaml/type.ts": "65553da3da3c029b6589c6e4903f0afbea6768be8fca61580711457151f2b30f",
"https://deno.land/std@0.63.0/_util/assert.ts": "e1f76e77c5ccb5a8e0dbbbe6cce3a56d2556c8cb5a9a8802fc9565af72462149",
"https://deno.land/std@0.63.0/archive/tar.ts": "5a0a7465d57fec2684239b07da0f5ec884c6c71a768297f73c348f22e04acd92",
"https://deno.land/std@0.63.0/bytes/mod.ts": "b1a149ac741728db00bda9ce1a2d044f248edd5ac95e708a6cc501bfd3adb4a7",
"https://deno.land/std@0.63.0/encoding/utf8.ts": "8654fa820aa69a37ec5eb11908e20b39d056c9bf1c23ab294303ff467f3d50a1",
"https://deno.land/std@0.63.0/fs/_util.ts": "68508c05d5a02678179a02beabf2b3eac5b16c5a9cbd1c272686d8101bb2679d",
"https://deno.land/std@0.63.0/fs/copy.ts": "b562e8f482cb8459bb011cbd769769bbdb4f6bc966effd277c06edbdbe41b72e",
"https://deno.land/std@0.63.0/fs/empty_dir.ts": "4d706eb01e5d08d862c673200d1978526e485368559fc7fb0f297add68f9cc43",
"https://deno.land/std@0.63.0/fs/ensure_dir.ts": "54cf0cfb16160857116d1bdff98214ad0189275fe2f089607fdc06c52ac79cc4",
"https://deno.land/std@0.63.0/fs/ensure_file.ts": "b70eccaee6f41ae226d399ad9c8ebc29beb5dd86fe179d30ab7e681976352baf",
"https://deno.land/std@0.63.0/fs/ensure_link.ts": "f647cea5c3b65f4a6618444546e9ca891d38f54f7fd4c718fb1fd575b4232213",
"https://deno.land/std@0.63.0/fs/ensure_symlink.ts": "d472af1507fb920db214f6816522ddc89eefd5800735243873053b2523882ec1",
"https://deno.land/std@0.63.0/fs/eol.ts": "4a0b2a612e0639b76d9c5fab0392e7bf1a158a7dab191ff7b7564870a1173812",
"https://deno.land/std@0.63.0/fs/exists.ts": "5429dce6587bfcdde06a7a2a1fd5ad932c17d74ca082e67934fa646cff1d2e57",
"https://deno.land/std@0.63.0/fs/expand_glob.ts": "415a109faaf50f8bf3e116bac534928a72373d0a981784e6130d91d11ce543a6",
"https://deno.land/std@0.63.0/fs/mod.ts": "88bb982130bb86df1cb350619fed4118c4cc439eeced6484330b7255e3a16568",
"https://deno.land/std@0.63.0/fs/move.ts": "020f56063c66288facbebc7d3c8dd3f309b0949fcaea49e463ccd5217fc82e2c",
"https://deno.land/std@0.63.0/fs/read_json.ts": "6922a9adc50cd2a7233298fd7b7ad9062d8602a55d4abb2b72d23ef0268b1306",
"https://deno.land/std@0.63.0/fs/walk.ts": "1715028b1646648b1239b9f93ff42beaf38f8e77424f8f9c2ffab9ee1594a54f",
"https://deno.land/std@0.63.0/fs/write_json.ts": "89a6231f51a6759dfff8f1f5534d030c2239c22fc9f3c0b3305d424f4f1d5604",
"https://deno.land/std@0.63.0/io/bufio.ts": "e76c5b7bf978a638aae6f62b87efde3ab7203b85902ce9b84ac8388c8c2bb104",
"https://deno.land/std@0.63.0/io/readers.ts": "4c2e98abf2a2a1d5e2adaf460479a1c69f742951c1bc141b26654d2f5248b663",
"https://deno.land/std@0.63.0/path/_constants.ts": "e11f32a36644e04dce243f3c1f30c02cc5d149827f48a755628176f0707cfc70",
"https://deno.land/std@0.63.0/path/_globrex.ts": "cfd1af99fb5ed2eff9b49aef994cdf7a14a5d26cd32b14c60b27bfff49839c82",
"https://deno.land/std@0.63.0/path/_interface.ts": "5876f91d35fd42624893a4aaddaee352144e1f46e719f1dde6511bab7c3c1029",
"https://deno.land/std@0.63.0/path/_util.ts": "f0fa012d40ae9b6acbef03908e534eb11e694de6470fb4d78ea4f38829e735ab",
"https://deno.land/std@0.63.0/path/common.ts": "e4ec66a7416d56f60331b66e27a8a4f08c7b1cf48e350271cb69754a01cf5c04",
"https://deno.land/std@0.63.0/path/glob.ts": "dbcda011329b5ba0f955823e578af19a8bf8d01586a07925b42affe885544e62",
"https://deno.land/std@0.63.0/path/mod.ts": "6de8885c2534757097818e302becd1cefcbc4c28ac022cc279e612ee04e8cfd1",
"https://deno.land/std@0.63.0/path/posix.ts": "1a6e53e1c90dde43750f38134ace0f6300f7330f5456b60d4979a4564fcf5f7a",
"https://deno.land/std@0.63.0/path/separator.ts": "9dd15d46ff84a16e13554f56af7fee1f85f8d0f379efbbe60ac066a60561f036",
"https://deno.land/std@0.63.0/path/win32.ts": "b530878b0f3f281c7f06fa73dc8e89a15106ab06e88ca1dea27394d09a1b0514",
"https://deno.land/std@0.79.0/async/pool.ts": "a499691231d8c249f044f69d204b479ad3af7f115e0b37342829eff076bc2450",
"https://deno.land/std@0.79.0/encoding/base64.ts": "b1d8f99b778981548457ec74bc6273ad785ffd6f61b2233bd5b30925345b565d",
"https://deno.land/std@0.79.0/encoding/hex.ts": "07a03ba41c96060a4ed4ba272e50b9e23f3c5b3839f4b069cdebc24d57434386",
"https://deno.land/std@0.79.0/hash/_wasm/hash.ts": "005f64c4d9343ecbc91e0da9ae5e800f146c20930ad829bbb872c5c06bd89c5f",
"https://deno.land/std@0.79.0/hash/_wasm/wasm.js": "fa27095b91e6268682100997577f1d3478beab5b045777e27ff7b2b5d19c8fdc",
"https://deno.land/std@0.79.0/hash/mod.ts": "e764a6a9ab2f5519a97f928e17cc13d984e3dd5c7f742ff9c1c8fb3114790f0c",
"https://deno.land/std@0.80.0/fs/eol.ts": "e133163510b683fc26a8285c4fa81e259a398ca592ab49edc3fdc9b2cc71e99a",
"https://deno.land/std@0.81.0/_util/assert.ts": "e1f76e77c5ccb5a8e0dbbbe6cce3a56d2556c8cb5a9a8802fc9565af72462149",
"https://deno.land/std@0.81.0/_util/has_own_property.ts": "91a2ef2fae5d941643a6472b97cac7ed8060a96deb66f4fafb4a2750c8af18e5",
"https://deno.land/std@0.81.0/_util/os.ts": "e2be3e25f96e4b5a233a08fd03aba80819bcaee66ac53c11c9b5aaa64799b475",
"https://deno.land/std@0.81.0/async/deferred.ts": "ecdb71319e164ec4ace5a44e3ee991b52c21bfc19e498acdf8eccdc0b1184f70",
"https://deno.land/std@0.81.0/async/delay.ts": "35957d585a6e3dd87706858fb1d6b551cb278271b03f52c5a2cb70e65e00c26a",
"https://deno.land/std@0.81.0/async/mod.ts": "39f2602a005805dd1e6b9da4ee5391b14d15e8fec4fa5494a6165c599911d746",
"https://deno.land/std@0.81.0/async/mux_async_iterator.ts": "2532c6f448fda34db7ab9504746db671c32425dd4ffa96eeb9df744c3038c106",
"https://deno.land/std@0.81.0/async/pool.ts": "a499691231d8c249f044f69d204b479ad3af7f115e0b37342829eff076bc2450",
"https://deno.land/std@0.81.0/bytes/mod.ts": "e4f91c6473fe13e3cf1a23649137f87f49135c10bc08fc0f83382a0fb0b03744",
"https://deno.land/std@0.81.0/datetime/formatter.ts": "0db8ca0d476bd80151b3557eb8f1bb2b6d5ba0713c8fc98f3526c2ce8c01649e",
"https://deno.land/std@0.81.0/datetime/mod.ts": "38ecaf7da9f81da63a18c7e6d4602ba70f563e99ab786c179393c7984fbf6006",
"https://deno.land/std@0.81.0/datetime/tokenizer.ts": "ae21a459f2f017ac81b1b49caa81174b6b8ab8a4d8d82195dcf25bb67b565c71",
"https://deno.land/std@0.81.0/encoding/utf8.ts": "1b7e77db9a12363c67872f8a208886ca1329f160c1ca9133b13d2ed399688b99",
"https://deno.land/std@0.81.0/fmt/colors.ts": "c5665c66f1a67228f21c5989bbb04b36d369b98dd7ceac06f5e26856c81c2531",
"https://deno.land/std@0.81.0/http/_io.ts": "8e1ed7effe99446535a98ac0cdcfd544265c78c46e4cef5a8c5f8e31037711d9",
"https://deno.land/std@0.81.0/http/cookie.ts": "8b54d578e1b72df92b30ec65c0e0d89142fec8700bff18a8cfe3ce87e60edeb6",
"https://deno.land/std@0.81.0/http/http_status.ts": "0ecc0799a208f49452023b1b927106ba5a2c13cc6cf6666345db028239d554ab",
"https://deno.land/std@0.81.0/http/server.ts": "282bb3b13da077a760083b465843fc2b8bf8936c3e22c514f6ae695db0721866",
"https://deno.land/std@0.81.0/io/bufio.ts": "3cbbe1f761c1c636d1e7128ed4e7fdca6bf21d9199aa3cae71e69972a6ae8f93",
"https://deno.land/std@0.81.0/io/ioutil.ts": "b781afd113a7d29c88c3d88efec391a0446c3e6537b74f795dd8579339ae8a5f",
"https://deno.land/std@0.81.0/io/readers.ts": "4c2e98abf2a2a1d5e2adaf460479a1c69f742951c1bc141b26654d2f5248b663",
"https://deno.land/std@0.81.0/mime/multipart.ts": "fa3c5ea5374ecae99e02543506a6ef4dc43ed5f3e26f406e8f4fea20f184cca6",
"https://deno.land/std@0.81.0/path/_constants.ts": "3a19d04e5d6de4620df22ab40c2e8c9d87002b56702d2b4669c14dfa2765e368",
"https://deno.land/std@0.81.0/path/_interface.ts": "67b276380d297a7cedc3c17f7a0bf122edcfc96a3e1f69de06f379d85ba0e2c0",
"https://deno.land/std@0.81.0/path/_util.ts": "7820a788b35c26dfc27ff329df12507fc0553ae92727009597046f6cf856b4fa",
"https://deno.land/std@0.81.0/path/common.ts": "e4ec66a7416d56f60331b66e27a8a4f08c7b1cf48e350271cb69754a01cf5c04",
"https://deno.land/std@0.81.0/path/glob.ts": "c36be777b82346a3fac02ef0ffef7d6c9bfe4da50f4599c798d7ded072f88d22",
"https://deno.land/std@0.81.0/path/mod.ts": "ef6a91aed4bc417eb56f8d5947f117f35ed3ca76c24d19dc482d3d6514218d5f",
"https://deno.land/std@0.81.0/path/posix.ts": "0f635537634111caa17a944b7405cf0a50ed6d6dd1a847c65323bebeccec5718",
"https://deno.land/std@0.81.0/path/separator.ts": "696812939d47fbe095002e92d595e3a1cdf03157222029a39c68dce9995f38c4",
"https://deno.land/std@0.81.0/path/win32.ts": "c5efe2a88d2351adddb53c22439ef32dc1081bc0d4205ae54a2ce388bcc600fb",
"https://deno.land/std@0.81.0/textproto/mod.ts": "4c378eda3cb6216608bb4c3a34201761c65f6980c4669455ca224c330cd5b790",
"https://deno.land/std@0.83.0/_util/assert.ts": "e1f76e77c5ccb5a8e0dbbbe6cce3a56d2556c8cb5a9a8802fc9565af72462149",
"https://deno.land/std@0.83.0/_util/os.ts": "e2be3e25f96e4b5a233a08fd03aba80819bcaee66ac53c11c9b5aaa64799b475",
"https://deno.land/std@0.83.0/encoding/base64.ts": "b1d8f99b778981548457ec74bc6273ad785ffd6f61b2233bd5b30925345b565d",
"https://deno.land/std@0.83.0/encoding/hex.ts": "fa01b16414c8e04caa0055f2d8c4610a3ec714a04315d0afe6956e07d501e11d",
"https://deno.land/std@0.83.0/fmt/colors.ts": "c5665c66f1a67228f21c5989bbb04b36d369b98dd7ceac06f5e26856c81c2531",
"https://deno.land/std@0.83.0/fs/_util.ts": "9318f5253cb09177280bdce64b6af97012707cdb458c02864811c2bae1dd1dbd",
"https://deno.land/std@0.83.0/fs/copy.ts": "94a9035388fb197e5d61db360bbf77497dbddd66bce56a42b7b6e0c39d5f7a2e",
"https://deno.land/std@0.83.0/fs/empty_dir.ts": "4d706eb01e5d08d862c673200d1978526e485368559fc7fb0f297add68f9cc43",
"https://deno.land/std@0.83.0/fs/ensure_dir.ts": "54cf0cfb16160857116d1bdff98214ad0189275fe2f089607fdc06c52ac79cc4",
"https://deno.land/std@0.83.0/fs/ensure_file.ts": "b70eccaee6f41ae226d399ad9c8ebc29beb5dd86fe179d30ab7e681976352baf",
"https://deno.land/std@0.83.0/fs/ensure_link.ts": "f647cea5c3b65f4a6618444546e9ca891d38f54f7fd4c718fb1fd575b4232213",
"https://deno.land/std@0.83.0/fs/ensure_symlink.ts": "88e14896b2cf069ac6342cf929c1ca57a681eb90f48e5af658c05fbb100c6097",
"https://deno.land/std@0.83.0/fs/eol.ts": "e133163510b683fc26a8285c4fa81e259a398ca592ab49edc3fdc9b2cc71e99a",
"https://deno.land/std@0.83.0/fs/exists.ts": "5429dce6587bfcdde06a7a2a1fd5ad932c17d74ca082e67934fa646cff1d2e57",
"https://deno.land/std@0.83.0/fs/expand_glob.ts": "1b43b860bd0834f2d79db4b88bb3ae97b4aed6c91e377bb843cc9d2f024bb117",
"https://deno.land/std@0.83.0/fs/mod.ts": "54ba0d1dac6de21ac32e3b60b83930e7febb4a2148ed735013b8d911c889d172",
"https://deno.land/std@0.83.0/fs/move.ts": "63803372793b85edfb8da586145fa5d33f4836caf4cea919f5b172b06bcab08a",
"https://deno.land/std@0.83.0/fs/walk.ts": "8d37f2164a7397668842a7cb5d53b9e7bcd216462623b1b96abe519f76d7f8b9",
"https://deno.land/std@0.83.0/hash/_wasm/hash.ts": "005f64c4d9343ecbc91e0da9ae5e800f146c20930ad829bbb872c5c06bd89c5f",
"https://deno.land/std@0.83.0/hash/_wasm/wasm.js": "fa27095b91e6268682100997577f1d3478beab5b045777e27ff7b2b5d19c8fdc",
"https://deno.land/std@0.83.0/hash/mod.ts": "e764a6a9ab2f5519a97f928e17cc13d984e3dd5c7f742ff9c1c8fb3114790f0c",
"https://deno.land/std@0.83.0/path/_constants.ts": "3a19d04e5d6de4620df22ab40c2e8c9d87002b56702d2b4669c14dfa2765e368",
"https://deno.land/std@0.83.0/path/_interface.ts": "67b276380d297a7cedc3c17f7a0bf122edcfc96a3e1f69de06f379d85ba0e2c0",
"https://deno.land/std@0.83.0/path/_util.ts": "7820a788b35c26dfc27ff329df12507fc0553ae92727009597046f6cf856b4fa",
"https://deno.land/std@0.83.0/path/common.ts": "e4ec66a7416d56f60331b66e27a8a4f08c7b1cf48e350271cb69754a01cf5c04",
"https://deno.land/std@0.83.0/path/glob.ts": "c36be777b82346a3fac02ef0ffef7d6c9bfe4da50f4599c798d7ded072f88d22",
"https://deno.land/std@0.83.0/path/mod.ts": "ef6a91aed4bc417eb56f8d5947f117f35ed3ca76c24d19dc482d3d6514218d5f",
"https://deno.land/std@0.83.0/path/posix.ts": "0f635537634111caa17a944b7405cf0a50ed6d6dd1a847c65323bebeccec5718",
"https://deno.land/std@0.83.0/path/separator.ts": "696812939d47fbe095002e92d595e3a1cdf03157222029a39c68dce9995f38c4",
"https://deno.land/std@0.83.0/path/win32.ts": "c5efe2a88d2351adddb53c22439ef32dc1081bc0d4205ae54a2ce388bcc600fb",
"https://deno.land/x/abc@v1.2.4/_header.ts": "111617a83e956c74f2bb2c3ccbb0cc39801b13365c11c050e74d0b74d31546ac",
"https://deno.land/x/abc@v1.2.4/_http_method.ts": "407c04d24eaee5ce9a1b00a9f1ef0d5b0b0cacfec080a98ece15ed8471ee9ef8",
"https://deno.land/x/abc@v1.2.4/_mime.ts": "32d91f49a4477ec4901830b12c22ce77c5ade18bc22f83ce6e3f803c47cbfdd3",
"https://deno.land/x/abc@v1.2.4/app.ts": "88c0ff086e82cabf7a72276a263cc4d51de6db2e9d8f947dff3f8370a9488b7c",
"https://deno.land/x/abc@v1.2.4/constants.ts": "1c04ea5873f9540a1c227c70ebbf97f3f3c2751a88b98f035f7eccf6b3ae4201",
"https://deno.land/x/abc@v1.2.4/context.ts": "e919516d5b9b21bbb70cd59409174b98a72f05f8fbb1f41ed30ca7a75170b806",
"https://deno.land/x/abc@v1.2.4/group.ts": "cadbb1476b06b828494bf1fc049c1184cd5fc8bf519c1eb9e59e5b4409c8eba6",
"https://deno.land/x/abc@v1.2.4/http_exception.ts": "45cd2e85f3f63f011af35064459d5180257766ebc4af981aef6c3a7fc9955ca3",
"https://deno.land/x/abc@v1.2.4/middleware/cors.ts": "c274cfb67d71a97e3648a299aad5a7eed428a20ee02914bb3428c044d66edd3c",
"https://deno.land/x/abc@v1.2.4/middleware/logger.ts": "18aaf687a365050c8cffa133019bf2af13c4fdf755ea75ab6f8c194059f40a5c",
"https://deno.land/x/abc@v1.2.4/middleware/skipper.ts": "a8f299c116b6f68e6c3f387cb871b2e7d6f4418ecee927f0fc0ca1794be53662",
"https://deno.land/x/abc@v1.2.4/mod.ts": "861cbdf90446f40afc7ddcaacbcb69e432e0970e6c6ea830ea80fd988de3a2e8",
"https://deno.land/x/abc@v1.2.4/router.ts": "45be01701031eda4c95f9a68c6248014a4e939c2e9e0679d920867fe327a7da0",
"https://deno.land/x/abc@v1.2.4/types.ts": "2e8a6ebbacf3c814b3b1f40d9b38a8833d8e41b55b67a23e5bbedf4edb51212a",
"https://deno.land/x/abc@v1.2.4/util.ts": "8eb6a894461a1875132b4d380cf6e52396a5fbcc7e1cde4aa7d523183cadf51b",
"https://deno.land/x/abc@v1.2.4/vendor/https/deno.land/std/encoding/utf8.ts": "7e1736536d5c8c9c5a541eff0515ab1fbb068c7d3ee2064264c87adcb540c7b7",
"https://deno.land/x/abc@v1.2.4/vendor/https/deno.land/std/fmt/colors.ts": "4ccb3297215fff946df10a6e8f844cf582534562f1c36d8a66addc3681be907f",
"https://deno.land/x/abc@v1.2.4/vendor/https/deno.land/std/http/cookie.ts": "8a62a5a7a9f7231e4045f176e45ace7a54b39f90019771a6308c383591ca04d2",
"https://deno.land/x/abc@v1.2.4/vendor/https/deno.land/std/http/http_status.ts": "f517061c2ff552bf04414a00b77b57aff6c1f8493fb9ecc06c966e082e7c0e45",
"https://deno.land/x/abc@v1.2.4/vendor/https/deno.land/std/http/server.ts": "7c1511c064a883e2f34aaa19a6f4a7403364447c6f95f7cdb238f7aa50e9e49c",
"https://deno.land/x/abc@v1.2.4/vendor/https/deno.land/std/mime/multipart.ts": "f5e978a047df388190a59d9ddb5905ae75048e129b14c9b8ca567f1322699672",
"https://deno.land/x/abc@v1.2.4/vendor/https/deno.land/std/path/mod.ts": "a095ff43f5219bbe6ebee2e4038106b0cb6509499cee5d650e63749c802ffb6a",
"https://deno.land/x/abc@v1.2.4/vendor/https/deno.land/x/router/mod.ts": "a12a329c0b5d04e409fc7ad9f202fd3f78ed494e0236c04eba98a02e69731707",
"https://deno.land/x/aws_sign_v4@0.1.5/deps.ts": "83822a3274e4e2fa51d62f099fde58500a842c1ebd220d407cc2c9428296b7f3",
"https://deno.land/x/aws_sign_v4@0.1.5/mod.ts": "133d10a9073f1550795bdea025a398a5b2e64bb0276af6c4e76d963fec0eac84",
"https://deno.land/x/aws_sign_v4@0.1.5/src/date.ts": "96d156206dceadbede0e8cd709dd2b0f8c8aef858359dbe187b78c50bdc73353",
"https://deno.land/x/aws_sign_v4@0.1.5/src/signing.ts": "20188270e96390320b776d6b00596a02140106fabb5cb61e0a3263252fd0c8ba",
"https://deno.land/x/base64@v0.2.1/base.ts": "47dc8d68f07dc91524bdd6db36eccbe59cf4d935b5fc09f27357a3944bb3ff7b",
"https://deno.land/x/base64@v0.2.1/base64url.ts": "18bbf879b31f1f32cca8adaa2b6885ae325c2cec6a66c5817b684ca12c46ad5e",
"https://deno.land/x/html_entities@v1.0/lib/xml-entities.js": "cbbc40f7b6fd1f925508ff7d43a52d2383a57a64d0aaa3a7a1eca9d4155e4bde",
"https://deno.land/x/nano_jsx@v0.1.0/component.ts": "6bd3dab67754e91308df863e11e2b7945bbe0bf575b4bc529e8a9e02087eb732",
"https://deno.land/x/nano_jsx@v0.1.0/components/helmet.ts": "59e598dc79c7b18620de175c61eb26f4aeb6905a6654cd63359208a26471541e",
"https://deno.land/x/nano_jsx@v0.1.0/components/img.ts": "82a9f830394a7d6cd9b789b48fe1e70bc64eb151c4b410a3da74347c06acdae0",
"https://deno.land/x/nano_jsx@v0.1.0/components/index.ts": "8855ee8302a9a19f38202d4a7ff5b17e22942600da02356bdfbc80c99c5c55f5",
"https://deno.land/x/nano_jsx@v0.1.0/components/link.ts": "0f0b1c57dc8c466203105062335e0d9ded89a34e75d08b1bbeece198d42021cb",
"https://deno.land/x/nano_jsx@v0.1.0/components/router.ts": "186e77064a96c31cb66ff1935c93d91904347647fcb13b56b5875ea64905397d",
"https://deno.land/x/nano_jsx@v0.1.0/components/suspense.ts": "0711b7cdcd42b0b085972eca796d3ba7c436a736e1d2ce17db7e0cd1d3b928f5",
"https://deno.land/x/nano_jsx@v0.1.0/components/visible.ts": "f19487f7faff0bad38a5549f1efac1df351e83ee4a77ca5886412b439f4b6b53",
"https://deno.land/x/nano_jsx@v0.1.0/context.ts": "a65018beedf3e1863b96f9d99cf2d471c231a6ae0c77877a77754a398105f9fc",
"https://deno.land/x/nano_jsx@v0.1.0/core.ts": "9346346ba7ddc52057131953a333c3ffa12e2a93aaceb25dabbab4bf8f1a171c",
"https://deno.land/x/nano_jsx@v0.1.0/customElementsMode.ts": "61b9688ae89bfcc6109b72eaab4d82a69a8482d89770f3e2c1359b79bf57bb91",
"https://deno.land/x/nano_jsx@v0.1.0/fragment.ts": "9cfb0dcdcb02d5cc53f027b4b55609e4f9d6d9322b665292e572856f4b688569",
"https://deno.land/x/nano_jsx@v0.1.0/helpers.ts": "d904aa646534f1c0cf7c05a6c8e02231f906d962acb725c964aedbcf50216d85",
"https://deno.land/x/nano_jsx@v0.1.0/htm.ts": "d8d9cd4fb4ad4645bff3698c7eb96e7798022c5519d04e709ebde236edde156b",
"https://deno.land/x/nano_jsx@v0.1.0/htm/build.ts": "9d6b6eb407c0db2d1213a3f9c82efc66a2bec34c89976132ff13e3e095dcaaaf",
"https://deno.land/x/nano_jsx@v0.1.0/htm/constants.ts": "3f296f87f03bd0ba8d7673884a1f6c4c927a2774648eaa4fd3ca9e3c46c3f7b8",
"https://deno.land/x/nano_jsx@v0.1.0/htm/index.ts": "29912b9f7a760884fce79caca82649b9772cfa3c3272e0426a4ce377b67d70d5",
"https://deno.land/x/nano_jsx@v0.1.0/index.ts": "0f39c911a39c61cb39f9bd8a2481500126dcb1b2a826d5b4523dd47a08b6938d",
"https://deno.land/x/nano_jsx@v0.1.0/jsx.ts": "7d5b4d4a249fba1a42f2016f54f71ca049d96ff490e098db4a19b2a9b197b952",
"https://deno.land/x/nano_jsx@v0.1.0/lazy.ts": "f8b8a2b915daff1fb70704ffad5171c805f1e28778b5cd0f8c827780762776c4",
"https://deno.land/x/nano_jsx@v0.1.0/mod.ts": "3dda2bc0dbee9abd01c03acf43ab55a7854952afe0450245fc2ad12eb9bd9598",
"https://deno.land/x/nano_jsx@v0.1.0/regexDom.ts": "de82fd3110c5a367e3d4ba9b774cfef3baf995deff455edc7363551d79089c90",
"https://deno.land/x/nano_jsx@v0.1.0/ssr.ts": "1ab6c17f41f612fe409d29d81ce1f17692ff02e5abea6ef4080cabecafc246dd",
"https://deno.land/x/nano_jsx@v0.1.0/state.ts": "cfc6ca6eb5e65f4cd60717a0a96ce604053bacf6e0b8835afbe22327e9979a1b",
"https://deno.land/x/nano_jsx@v0.1.0/store.ts": "bf075833a656fc87b2a24c486bb3f77e13f19d6d9efcc42e31ffb6f24ec8eb93",
"https://deno.land/x/nano_jsx@v0.1.0/types.ts": "fb338d7fa4422a92c442d14e073a2deb01d42b017fcd36013a1f6554e17c5449",
"https://deno.land/x/nano_jsx@v0.1.0/version.ts": "d7f3813a3b1c490f16e77047483b0dc52cc0cec6cb1b73d6926cf9ad96129a59",
"https://deno.land/x/nano_jsx@v0.1.0/withStyles.ts": "8aae4c8e79319fe991d49dd8ccc927c221786dfe58de640dba9d9885ce0dd4b7",
"https://deno.land/x/router@v2.0.0/mod.ts": "8792d3c390e0446d89eb94ee8030dd20de18f2aba649e263d2832f3f150ea2ce",
"https://deno.land/x/s3@0.3.0/deps.ts": "590be3be45b218c91979d4d70db22cc25d16aa2f0ea6d4c414508f87bb3525e7",
"https://deno.land/x/s3@0.3.0/mod.ts": "2f2bee45abe1c1197bba5d251ea49b3a342ed474c829119f315202011195f649",
"https://deno.land/x/s3@0.3.0/src/bucket.ts": "85fd6d3a4f633ef70509d60397aa4dbf4cc7b6cfb155dedc70a22794a49984ff",
"https://deno.land/x/s3@0.3.0/src/error.ts": "a7857ca64eedbaf5c4daad5e83fdef5c4acd61534bffdab784b4e17e008e6aae",
"https://denopkg.com/chiefbiiko/hmac@v1.0.2/deps.ts": "fb061e6fa0fd96f455ef647c57e9e6309a86fb0bf484447fc6cb38e57262192f",
"https://denopkg.com/chiefbiiko/hmac@v1.0.2/mod.ts": "83590b95de468d0cf5398b7631b4fb62a64226786247fe265482045d799e8f97",
"https://denopkg.com/chiefbiiko/sha1@v1.0.3/deps.ts": "2e1af51a48c8507017fdb057b950366601b177fb7e73d5de54c1b3e0e115d72e",
"https://denopkg.com/chiefbiiko/sha1@v1.0.3/mod.ts": "146a101c9776cc9c807053c93f23e4b321ade5251f65745df418f4a75d5fd27b",
"https://denopkg.com/chiefbiiko/sha256@v1.0.2/deps.ts": "2e1af51a48c8507017fdb057b950366601b177fb7e73d5de54c1b3e0e115d72e",
"https://denopkg.com/chiefbiiko/sha256@v1.0.2/mod.ts": "f109aa5eeb201a0cbfaf44950b70a429838b187e8a84c5b810c1ac84953427cc",
"https://denopkg.com/chiefbiiko/sha512@v1.0.3/deps.ts": "2e1af51a48c8507017fdb057b950366601b177fb7e73d5de54c1b3e0e115d72e",
"https://denopkg.com/chiefbiiko/sha512@v1.0.3/mod.ts": "33190babd4c0e748bb2568fd003444487c8798c8c3a618f6593098c12805fe15",
"https://denopkg.com/chiefbiiko/std-encoding@v1.0.0/mod.ts": "4a927e5cd1d9b080d72881eb285b3b94edb6dadc1828aeb194117645f4481ac0",
"https://git.hibas.dev/Deno/DenReg/raw/branch/master/tar/mod.ts": "472497c6ef7ed0f45e11c6ad9a3d7ff9caf3ea9da377e53b73a9466d089f1beb",
"https://git.hibas.dev/Deno/DenReg/raw/branch/master/tar/src/deps.ts": "d8066e3bcd0a1885ce6b352f71845ec639e9392f7b84f517d1ff6d70e39498ec",
"https://git.hibas.dev/Deno/DenReg/raw/branch/master/tar/src/mod.ts": "438a487ea4a8ef4f2767cd2399a569fd0ef59524b4863b68568775a2bca76416",
"https://raw.githubusercontent.com/hibas123/dndb/master/deps.ts": "02b61f3ce1d74cf2f0c723b4e43240a6c6da39166391b1adec5b139c06e8e010",
"https://raw.githubusercontent.com/hibas123/dndb/master/mod.ts": "3890f580d22e97bacf44050661b74a2c4a3dcbf75e4d8e0f56fd2cbce9305f2a",
"https://raw.githubusercontent.com/hibas123/dndb/master/src/methods/find.js": "59b664c58cc986a2639b3a5ca0a158ddbc6cf812345f65c0b2bd3533c058dc41",
"https://raw.githubusercontent.com/hibas123/dndb/master/src/methods/findOne.js": "3230785e45781324b421c47b7e9ef1f5bd058691d75d2eae9ab2242815159792",
"https://raw.githubusercontent.com/hibas123/dndb/master/src/methods/insert.js": "8df8a869bf97c16eb5ee696157b59cf8d2b0238b427b08a92b6e4e63ce2ffadd",
"https://raw.githubusercontent.com/hibas123/dndb/master/src/methods/mod.js": "fe009c4a55bad2ad84a0d3ad7ee0ab0d3166f91f2f706fe0550df92a90171b7e",
"https://raw.githubusercontent.com/hibas123/dndb/master/src/methods/remove.js": "5f623dea009ec34831ba8362175a090b1055f28fe9576e9f929ce7df888a6467",
"https://raw.githubusercontent.com/hibas123/dndb/master/src/methods/update.js": "9e8c9ec9cfebe3c46cfe68ef6fd98e452c24cb93c858f58e03d1d81b87c62da6",
"https://raw.githubusercontent.com/hibas123/dndb/master/src/mod.ts": "476b9d0069b60443b3e9684fa086374bffbc45f02a083b7608c28dfd5733f702",
"https://raw.githubusercontent.com/hibas123/dndb/master/src/storage.js": "fa06befe5609fda4dfc6fc2ddc0cfdc4765ddf0b9cccf106fc14435f83ef975c",
"https://raw.githubusercontent.com/nekobato/deno-xml-parser/0bc4c2bd2f5fad36d274279978ca57eec57c680c/index.ts": "05d093028c005706e37b46bfe2bb7e2488f42fdc74d2196ac818902336927c01"
}
}

BIN
registry/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

11
registry/favicon.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/public/ms-icon-70x70.png"/><square150x150logo src="/public/ms-icon-150x150.png"/><square310x310logo src="/public/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
registry/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

1
registry/public/file.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>

After

Width:  |  Height:  |  Size: 337 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-folder"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>

After

Width:  |  Height:  |  Size: 311 B

View File

@ -0,0 +1,41 @@
{
"name": "Deno package Registry",
"short_name": "DenReg",
"description": "A deno package registry, that can be self hosted easily",
"start_url": "/",
"scope": "/",
"theme_color": "#ffffff",
"display": "standalone",
"icons": [
{
"src": "/public/favicon-32x32.png",
"sizes": "32x32",
"type": "image/png",
"density": "0.75"
},
{
"src": "/public/apple-icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"density": "1.5"
},
{
"src": "/public/favicon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"density": "2.0"
},
{
"src": "/public/apple-icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"density": "3.0"
},
{
"src": "/public/android-icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"density": "4.0"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

2
registry/public/paper.min.css vendored Normal file

File diff suppressed because one or more lines are too long

218
registry/public/prism.css Normal file
View File

@ -0,0 +1,218 @@
/* PrismJS 1.22.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+abap+abnf+actionscript+ada+agda+al+antlr4+apacheconf+apl+applescript+aql+arduino+arff+asciidoc+aspnet+asm6502+autohotkey+autoit+bash+basic+batch+bbcode+birb+bison+bnf+brainfuck+brightscript+bro+bsl+c+csharp+cpp+cil+clojure+cmake+coffeescript+concurnas+csp+crystal+css-extras+cypher+d+dart+dax+dhall+diff+django+dns-zone-file+docker+ebnf+editorconfig+eiffel+ejs+elixir+elm+etlua+erb+erlang+excel-formula+fsharp+factor+firestore-security-rules+flow+fortran+ftl+gml+gcode+gdscript+gedcom+gherkin+git+glsl+go+graphql+groovy+haml+handlebars+haskell+haxe+hcl+hlsl+http+hpkp+hsts+ichigojam+icon+ignore+inform7+ini+io+j+java+javadoc+javadoclike+javastacktrace+jolie+jq+jsdoc+js-extras+json+json5+jsonp+jsstacktrace+js-templates+julia+keyman+kotlin+latex+latte+less+lilypond+liquid+lisp+livescript+llvm+lolcode+lua+makefile+markdown+markup-templating+matlab+mel+mizar+mongodb+monkey+moonscript+n1ql+n4js+nand2tetris-hdl+naniscript+nasm+neon+nginx+nim+nix+nsis+objectivec+ocaml+opencl+oz+parigp+parser+pascal+pascaligo+pcaxis+peoplecode+perl+php+phpdoc+php-extras+plsql+powerquery+powershell+processing+prolog+properties+protobuf+pug+puppet+pure+purebasic+purescript+python+q+qml+qore+r+racket+jsx+tsx+reason+regex+renpy+rest+rip+roboconf+robotframework+ruby+rust+sas+sass+scss+scala+scheme+shell-session+smali+smalltalk+smarty+sml+solidity+solution-file+soy+sparql+splunk-spl+sqf+sql+stan+iecst+stylus+swift+t4-templating+t4-cs+t4-vb+tap+tcl+tt2+textile+toml+turtle+twig+typescript+typoscript+unrealscript+vala+vbnet+velocity+verilog+vhdl+vim+visual-basic+warpscript+wasm+wiki+xeora+xml-doc+xojo+xquery+yaml+yang+zig&plugins=line-numbers+inline-color */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.token.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
/* This background color was intended by the author of this theme. */
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
pre[class*="language-"].line-numbers {
position: relative;
padding-left: 3.8em;
counter-reset: linenumber;
}
pre[class*="language-"].line-numbers > code {
position: relative;
white-space: inherit;
}
.line-numbers .line-numbers-rows {
position: absolute;
pointer-events: none;
top: 0;
font-size: 100%;
left: -3.8em;
width: 3em; /* works for line-numbers below 1000 lines */
letter-spacing: -1px;
border-right: 1px solid #999;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.line-numbers-rows > span {
display: block;
counter-increment: linenumber;
}
.line-numbers-rows > span:before {
content: counter(linenumber);
color: #999;
display: block;
padding-right: 0.8em;
text-align: right;
}
span.inline-color-wrapper {
/*
* The background image is the following SVG inline in base 64:
*
* <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2">
* <path fill="gray" d="M0 0h2v2H0z"/>
* <path fill="white" d="M0 0h1v1H0zM1 1h1v1H1z"/>
* </svg>
*
* SVG-inlining explained:
* https://stackoverflow.com/a/21626701/7595472
*/
background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyIDIiPjxwYXRoIGZpbGw9ImdyYXkiIGQ9Ik0wIDBoMnYySDB6Ii8+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0wIDBoMXYxSDB6TTEgMWgxdjFIMXoiLz48L3N2Zz4=");
/* This is to prevent visual glitches where one pixel from the repeating pattern could be seen. */
background-position: center;
background-size: 110%;
display: inline-block;
height: 1.333ch;
width: 1.333ch;
margin: 0 .333ch;
box-sizing: border-box;
border: 1px solid white;
outline: 1px solid rgba(0,0,0,.5);
overflow: hidden;
}
span.inline-color {
display: block;
/* To prevent visual glitches again */
height: 120%;
width: 120%;
}

View File

@ -0,0 +1,6 @@
await fetch("https://unpkg.com/papercss/dist/paper.min.css")
.then((res) => res.arrayBuffer())
.then((data) =>
Deno.writeFile("./public/paper.min.css", new Uint8Array(data))
)
.catch(console.error);

View File

@ -14,6 +14,8 @@ const config =
) || {};
if (!config.user) config.user = {};
if (!config.web) config.web = {};
if (!config.general) config.general = {};
const env = Deno.env.toObject();
@ -40,11 +42,30 @@ for (const key in env) {
case "S3_SECRET":
config.s3 = { ...(config.s3 || {}), secretKey: env[key] };
break;
case "S3_REGION":
config.s3 = { ...(config.s3 || {}), region: env[key] };
break;
case "WEB_URL":
config.web.url = env[key];
break;
case "WEB_TRACKING":
config.web.tracking = env[key];
break;
case "GENERAL_DEV":
config.general.dev = env[key] === "true";
}
}
}
}
if (config.general.dev) {
console.warn("Dev mode active!!!");
}
if (!config.web.url) {
console.error("The web.url configuration has to be set!");
}
console.log("Known users:", Object.keys(config.user));
export default config;

View File

@ -8,6 +8,7 @@ export interface IPackage {
description: string;
versions: string[];
deprecated: boolean;
readme: string;
}
export interface IApiKey {

View File

@ -1,29 +1,26 @@
// export { MongoClient, ObjectId } from "https://deno.land/x/mongo@v0.9.1/mod.ts";
// @deno-types="./types/hotfix.d.ts"
export * as Ini from "https://deno.hibas123.de/raw/ini@0.0.3/mod.ts";
export * as S3 from "https://deno.land/x/s3/mod.ts";
export * as ABC from "https://deno.land/x/abc@v1.2.4/mod.ts";
export * as CorsMW from "https://deno.land/x/abc@v1.2.4/middleware/cors.ts";
export * as LoggerMW from "https://deno.land/x/abc@v1.2.4/middleware/logger.ts";
export * as Ini from "https://deno.land/x/ini/mod.ts";
export * as Path from "https://deno.land/std@0.83.0/path/mod.ts";
export * as FS from "https://deno.land/std@0.83.0/fs/mod.ts";
export * as Base64 from "https://deno.land/std@0.208.0/encoding/base64.ts";
export * as Hash from "https://deno.land/std@0.83.0/hash/mod.ts";
export * as Colors from "https://deno.land/std@0.83.0/fmt/colors.ts";
export * as Streams from "https://deno.land/std@0.208.0/streams/mod.ts";
export * as ABC from "https://deno.land/x/abc@v1/mod.ts";
export * as CorsMW from "https://deno.land/x/abc@v1/middleware/cors.ts";
export * as LoggerMW from "https://deno.land/x/abc@v1/middleware/logger.ts";
export * as Path from "https://deno.land/std@0.63.0/path/mod.ts";
export * as FS from "https://deno.land/std@0.63.0/fs/mod.ts";
export * as Base64 from "https://deno.land/std@0.63.0/encoding/base64.ts";
export * as Hash from "https://deno.land/std@0.63.0/hash/mod.ts";
export * as Compress from "https://git.hibas.dev/Deno/DenReg/raw/branch/master/tar/mod.ts";
export * as Compress from "https://git.stamm.me/Deno/DenReg/raw/branch/master/tar/mod.ts";
export { default as Prism } from "https://cdn.skypack.dev/prismjs";
export { Marked } from "https://deno.land/x/markdown/mod.ts";
export { Marked } from "https://deno.hibas123.de/raw/markdown@0.1.0/mod.ts";
import DS from "https://raw.githubusercontent.com/hibas123/dndb/master/mod.ts";
/// <reference path="./types/jsx.d.ts" />
export {
React,
jsx,
Fragment,
} from "https://raw.githubusercontent.com/apiel/jsx-html/master/mod.ts";
export * as Nano from "https://deno.land/x/nano_jsx@v0.1.0/mod.ts";
export const Datastore = DS;

View File

@ -1,5 +1,5 @@
/// <reference path="./types/jsx.d.ts" />
import { ABC, CorsMW, LoggerMW } from "./deps.ts";
// /// <reference path="./types/jsx.d.ts" />
import { ABC, CorsMW, LoggerMW, Path } from "./deps.ts";
import config from "./config.ts";
const port = config?.api?.port || 8000;
@ -8,16 +8,50 @@ const app = new ABC.Application();
app.use(LoggerMW.logger({}));
app.use(CorsMW.cors({}));
// app.static("/public", "./public");
const MIMEDB = {
".css": "text/css",
".json": "application/json",
".js": "application/javascript",
".gz": "applcation/gzip",
".ico": "image/x-icon",
".png": "image/png",
".svg": "image/svg+xml",
".xml": "application/xml",
};
app.get("/public/*path", async (ctx) => {
const filePath = Path.join("./public", ctx.params.path);
console.log(filePath);
ctx.blob(
await Deno.open(filePath, { read: true }),
(MIMEDB as any)[Path.extname(filePath)]
);
});
import api from "./http/api.ts";
api(app.group("/api"));
import raw from "./http/raw.ts";
raw(app.group("/raw"));
import intellisense from "./http/intellisense.ts";
intellisense(app.group("/.well-known"));
import view from "./http/views.ts";
view(app);
// function logNode(router: Node, indent = 0) {
// trees.map((tree) => {
// console.log("Path:", tree.path);
// tree.children?.forEach((node) => logNode(node, indent + 3));
// });
// }
console.log(app.router.trees.GET);
// const trees = Object.values(app.router) as Node[];
// trees.forEach(logNode);
import render from "./renderer.tsx";
app.renderer = {

View File

@ -1,11 +1,16 @@
import { ABC, Path, Compress, FS } from "../deps.ts";
import { ABC, Path, Compress, FS, Colors } from "../deps.ts";
import bucket from "../s3.ts";
import { isValidPackageName, basicauth, isValidFullVersion } from "../utils.ts";
import {
isValidPackageName,
basicauth,
isValidFullVersion,
getAbsolutePackageVersion,
getFilePath,
} from "../utils.ts";
import db, { IPackage } from "../db.ts";
import * as Storage from "../storage.ts";
import { v4 } from "https://deno.land/std/uuid/mod.ts";
import db from "../db.ts";
export default function api(g: ABC.Group) {
const cacheControl = (next: ABC.HandlerFunc) => (ctx: ABC.Context) => {
@ -15,14 +20,65 @@ export default function api(g: ABC.Group) {
g.get(
"/",
(ctx) => {
(_ctx) => {
return { version: "1" };
},
cacheControl
);
g.get("/module", async (_ctx) => {
const res = await db.package.find({});
return res.map((e) => e.name);
});
g.get("/module/:module", async (ctx) => {
const module = await db.package.findOne({ name: ctx.params.module });
if (!module) {
ctx.response.status = 404;
return "// Not found";
} else {
return module.versions;
}
});
g.get("/module/:module/v/:version", async (ctx) => {
const module = await db.package.findOne({ name: ctx.params.module });
if (!module) {
ctx.response.status = 404;
return "// Not found";
} else {
const version = getAbsolutePackageVersion(
module,
ctx.params.version
) as string;
if (!version) {
ctx.response.status = 404;
return "// Not found";
}
const bucketPath = await getFilePath(module.name, version, "/");
const filesItr = Storage.walkFiles(module.name + "/" + version + "/");
const allowedExts = new Set(
(ctx.queryParams.ext || "js|ts").split("|").map((e) => "." + e)
);
const files: string[] = [];
for await (const file of filesItr) {
const relPath = Path.posix.relative(bucketPath, file.path || "");
const ext = Path.extname(relPath);
if (allowedExts.has(ext)) files.push(relPath);
}
return files;
}
});
// g.post("/getapikey", getApiKey, basicauth("api"));
g.post("/package/:name", uploadPackage, cacheControl, basicauth("api"));
g.post("/module/:name", uploadPackage, cacheControl, basicauth("api")); //Switch no module instead of package
}
// async function getApiKey(ctx: ABC.Context) {
@ -42,7 +98,7 @@ export default function api(g: ABC.Group) {
// }
async function uploadPackage(ctx: ABC.Context) {
const reqId = v4.generate();
const reqId = crypto.randomUUID();
const filename = "./tmp/" + reqId + ".tar";
const folder = "./tmp/" + reqId;
@ -61,6 +117,7 @@ async function uploadPackage(ctx: ABC.Context) {
write: true,
create: true,
});
// ctx.request.body.pipeTo(file); //TODO: Do this, once web framework is updated
await Deno.copy(ctx.request.body, file);
file.close();
@ -98,7 +155,6 @@ async function uploadPackage(ctx: ABC.Context) {
success: false,
message: "Invalid version. Version must be in format: 0.0.0",
};
return;
}
console.log("Checking for previous uploads");
@ -113,6 +169,7 @@ async function uploadPackage(ctx: ABC.Context) {
owner: ctx.customContext.user,
description: meta.description,
deprecated: false,
readme: meta.readme,
versions: [],
};
@ -128,7 +185,7 @@ async function uploadPackage(ctx: ABC.Context) {
};
}
const bucketBase = "packages/" + packageName + "/" + packageVersion + "/";
const storageBase = packageName + "/" + packageVersion + "/";
console.log("Uploading files to S3");
@ -138,16 +195,16 @@ async function uploadPackage(ctx: ABC.Context) {
});
for await (const file of walker) {
const relative = Path.relative(folder, file.path);
const relative = Path.relative(folder, file.path).replace("\\", "/");
const bucketPath = (bucketBase + relative).replace(/@/g, "§");
console.log("Normalised path:", relative.replace("\\", "/"));
console.log("Uploading file:", file.path, bucketPath, bucketBase);
await bucket.putObject(
bucketPath,
await Deno.readAll(await Deno.open(file.path)),
{}
);
const bucketPath = (storageBase + relative).replace(/@/g, "§");
const body = await Deno.readAll(await Deno.open(file.path));
console.log("Put Object", bucketPath, body.byteLength);
await Storage.writeFile(bucketPath, body);
}
console.log("Setting new live version");
@ -168,7 +225,9 @@ async function uploadPackage(ctx: ABC.Context) {
success: true,
};
} catch (err) {
console.error("Error while processing newly uploaded package");
console.error(
Colors.red("Error while processing newly uploaded package")
);
console.error(err);
return {
success: false,

View File

@ -0,0 +1,43 @@
import { ABC } from "../deps.ts";
import config from "../config.ts";
export default function raw(g: ABC.Group) {
g.get("/deno-import-intellisense.json", (_ctx) => {
return {
version: 1,
registries: [
{
schema: "/raw/:module([@]*[a-z0-9\\-\\_]*)@:version?/:path*",
variables: [
{
key: "module",
url: `${config.web.url}/api/module`,
},
{
key: "version",
url: `${config.web.url}/api/module/\${module}`,
},
{
key: "path",
url: `${config.web.url}/api/module/\${module}/v/\${{version}}`,
},
],
},
{
schema: "/raw/:module([@]*[a-z0-9\\-\\_]*)/:path*",
variables: [
{
key: "module",
url: `${config.web.url}/api/module`,
},
{
key: "path",
url: `${config.web.url}/api/module/\${module}/v/latest`,
},
],
},
],
};
});
}

View File

@ -1,5 +1,12 @@
import { ABC } from "../deps.ts";
import { extractPackagePath, getFile } from "../utils.ts";
import { Path } from "../deps.ts";
import type { ABC } from "../deps.ts";
import {
extractPackagePath,
getAbsolutePackageVersion,
getFile,
getContentType,
} from "../utils.ts";
import db from "../db.ts";
const MAX_FIXED_CACHE_AGE = 60 * 60 * 24 * 365;
const MAX_FLOATING_CACHE_AGE = 60 * 30;
@ -11,16 +18,27 @@ export default function raw(g: ABC.Group) {
ctx.params.package
);
const pkg = await db.package.findOne({ name: packageName });
packageVersion = getAbsolutePackageVersion(pkg, packageVersion);
const E404 = () => {
ctx.response.status = 404;
ctx.response.body = "// Not found!";
};
const result = await getFile(
packageName,
packageVersion,
ctx.params.path
);
const filepath = ctx.params.path;
const result = await getFile(packageName, packageVersion, filepath);
if (filepath.endsWith(".js")) {
const tsFile = filepath.slice(0, filepath.length - 3) + ".d.ts";
const tsResult = await getFile(packageName, packageVersion, tsFile);
if (tsResult) {
ctx.response.headers.set(
"X-TypeScript-Types",
"./" + Path.posix.basename(tsFile)
);
}
}
if (packageVersion && result) {
ctx.response.headers.set(
@ -37,6 +55,8 @@ export default function raw(g: ABC.Group) {
if (!result) return E404();
ctx.response.headers.set("e-tag", result.etag);
let contentType = getContentType(filepath);
if (contentType) ctx.response.headers.set("Content-Type", contentType);
return result.data;
});
}

View File

@ -1,8 +1,16 @@
import { ABC } from "../deps.ts";
import { basicauth, extractPackagePath, sortVersions } from "../utils.ts";
import type { ABC } from "../deps.ts";
import {
extractPackagePath,
getFilePath,
getFile,
getOneOf,
getAbsolutePackageVersion,
sortVersions,
} from "../utils.ts";
import { Hash } from "../deps.ts";
import { Hash, Path } from "../deps.ts";
import db, { IPackage } from "../db.ts";
import * as Storage from "../storage.ts";
const MAX_CACHE_AGE = 60 * 30; // 30 Minutes
@ -23,6 +31,7 @@ export default function views(g: ABC.Application) {
packages = await db.package.find({});
}
await ctx.render("index", {
packages: packages.reverse(),
search,
@ -44,21 +53,116 @@ export default function views(g: ABC.Application) {
ctx.response.headers.set("cache-control", CACHE_CONTROL);
ctx.response.headers.set("E-Tag", etag);
});
g.get("/package/:package", async (ctx) => {
let [packageName, packageVersion] = extractPackagePath(
const [packageName, packageVersion] = extractPackagePath(
ctx.params.package
);
const pkg = await db.package.findOne({ name: packageName });
if (!pkg) {
ctx.response.status = 404;
ctx.response.body = "// Package not found!";
return;
}
const readmeContentRaw = (await getOneOf(
pkg.name,
packageVersion || pkg.versions.sort(sortVersions).reverse()[0],
[pkg.readme, "README.md", "readme.md", "Readme.md"]
))?.data;
const readmeContent = readmeContentRaw
? new TextDecoder().decode(readmeContentRaw)
: "";
const etag =
"W/" +
Hash.createHash("sha3-256")
.update(`${packageName}:${packageVersion}`)
.toString("base64");
await ctx.render("package", { pkg, version: packageVersion });
await ctx.render("package", { pkg, version: packageVersion, readmeContent });
ctx.response.headers.set("cache-control", CACHE_CONTROL);
ctx.response.headers.set("E-Tag", etag);
});
async function handleBrowse(ctx: ABC.Context) {
const E404 = () => {
ctx.response.status = 404;
ctx.response.body = "// Not found!";
};
let [packageName, packageVersion] = extractPackagePath(
ctx.params.package
);
const pkg = await db.package.findOne({ name: packageName });
packageVersion = getAbsolutePackageVersion(pkg, packageVersion);
if (!packageVersion) return E404();
const path = ctx.params.path || "";
const fileContent = await getFile(packageName, packageVersion, path);
if (fileContent) {
await ctx.render("browse_file", {
pkg,
version: packageVersion,
content: new TextDecoder().decode(fileContent.data),
ext: Path.extname(path),
path: `${packageName}@${packageVersion}/${path}`,
});
} else {
const filesPath = getFilePath(
packageName,
packageVersion,
path
);
if (!filesPath) return E404();
console.log(filesPath);
const filesItr = Storage.walkFiles(filesPath);
const files: { name: string; size: number }[] = [];
const directories: Set<string> = new Set();
let readme: string | null = null;
for await (const file of filesItr) {
const relPath = Path.posix.relative(filesPath, file.path || "");
console.log({ file, relPath, filesPath });
if (relPath.indexOf("/") >= 0) {
directories.add(relPath.split("/")[0]);
} else {
files.push({ name: relPath, size: -1 }); //TODO: Size is not implemented yet
if (relPath.toLowerCase() === "readme.md") {
const readmeCont = await getFile(
packageName,
packageVersion,
Path.posix.join(path, relPath)
);
if (readmeCont) {
readme = new TextDecoder().decode(readmeCont?.data);
}
}
}
}
await ctx.render("browse_folder", {
pkg,
version: packageVersion,
readme,
files,
directories: Array.from(directories.values()).map((e) => ({
name: e,
})),
path: `${packageName}@${packageVersion}/${path}`,
});
}
}
g.get("/browse/:package", handleBrowse);
g.get("/browse/:package/*path", handleBrowse);
}

0
registry/src/react.ts Normal file
View File

View File

@ -1,8 +1,10 @@
/// <reference path="./types/jsx.d.ts" />
import { React, jsx } from "./deps.ts";
import { Nano } from "./deps.ts";
const { h, renderSSR } = Nano;
import config from "./config.ts";
class StringReader implements Deno.Reader {
private data: Uint8Array;
private offset = 0;
@ -25,15 +27,50 @@ class StringReader implements Deno.Reader {
}
}
type ELM = any;
type Component = () => ELM;
const componentCache = new Map<string, Component>();
async function loadComponent(name: string) {
let mod = componentCache.get(name);
if (!mod || config.general.dev) {
mod = (await import(`./views/${name}.tsx`)).default;
if (!mod) throw new Error("Invalid component " + name);
componentCache.set(name, mod);
}
return mod;
}
Promise.resolve().then(async () => {
console.log("[PRECACHE] Start loading pages");
await loadComponent("index");
await loadComponent("package");
await loadComponent("browse_folder");
await loadComponent("browse_file");
console.log("[PRECACHE] Finished loading pages");
});
// import index from "./views/index.tsx";
// componentCache.set("index", index as Component);
// import pkg from "./views/package.tsx";
// componentCache.set("package", pkg as Component);
// import browse_folder from "./views/browse_folder.tsx";
// componentCache.set("browse_folder", browse_folder as Component);
// import browse_file from "./views/browse_file.tsx";
// componentCache.set("browse_file", browse_file as Component);
export default async function render(
name: string,
data: any
): Promise<Deno.Reader> {
const component: {
default: () => JSX.IntrinsicElements | Promise<JSX.IntrinsicElements>;
} = await import(`./views/${name}.tsx`);
const Component = await loadComponent(name);
const res = await (<component.default {...data} />).render();
// // @ts-ignore
// const res = await Pico.renderSSR(<Component {...data} />);
const res = await renderSSR(<Component {...data} />);
return new StringReader(res as string);
return new StringReader("<!DOCTYPE html>\n" + res);
}

View File

@ -1,16 +0,0 @@
import { S3 } from "./deps.ts";
import config from "./config.ts";
if (!config.s3) {
throw new Error("Config is missing [s3] section!");
}
const bucket = new S3.S3Bucket({
bucket: config.s3.bucket || "deno-registry",
endpointURL: config.s3.endpoint,
accessKeyID: config.s3.accessKey,
secretKey: config.s3.secretKey,
region: config?.s3?.region || "us-east-1",
});
export default bucket;

40
registry/src/storage.ts Normal file
View File

@ -0,0 +1,40 @@
import { FS, Path } from "./deps.ts";
const STORAGE_ROOT = Path.resolve("./data/files");
export function walkFiles(path: string) {
const norm = Path.normalize(path);
const p = Path.join(STORAGE_ROOT, norm);
const walker = FS.walk(p, { includeFiles: true, includeDirs: false })
// Make path of entry relative to the root and return an async iterator
return (async function* () {
for await (const entry of walker) {
const rel = Path.relative(STORAGE_ROOT, entry.path);
yield { ...entry, path: rel };
}
})();
}
export async function writeFile(path: string, content: Uint8Array) {
const norm = Path.normalize(path);
const p = Path.join(STORAGE_ROOT, norm);
await FS.ensureFile(p);
await Deno.writeFile(p, content);
}
export async function readFile(path: string) {
const norm = Path.normalize(path);
const p = Path.join(STORAGE_ROOT, norm);
if (!await FS.exists(p)) return undefined;
const s = await Deno.stat(p);
if (!s.isFile) return undefined;
return await Deno.readFile(p);
}

3
registry/src/test.ts Normal file
View File

@ -0,0 +1,3 @@
import * as Prism from "./vendor/prism/prism.js";
console.log((window as any).Prism);

4
registry/src/types/hotfix.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
// fixes an issue in std@0.80.0
interface ReadableStream<R> {
getIterator(): any;
}

View File

@ -1,5 +0,0 @@
declare namespace JSX {
interface IntrinsicElements {
[elemName: string]: any;
}
}

View File

@ -1,15 +1,13 @@
import { ABC, Base64 } from "./deps.ts";
import { ABC, Base64, Path } from "./deps.ts";
import config from "./config.ts";
import * as Storage from "./storage.ts";
const packageNameRegex = /^[@]?[a-zA-Z][\d\w\-\_]*$/g.compile();
const packageVersionRegex = /^\d(\.\d)?(\.\d)?$/g.compile();
const packageFullVersionRegex = /^\d(\.\d)(\.\d)$/g.compile();
export const isValidPackageName = (name: string) => packageNameRegex.test(name);
export const isValidPackageName = (name: string) => /^[@]?[a-zA-Z][\d\w\-\_]*$/g.test(name);
export const isValidVersion = (version: string) =>
packageVersionRegex.test(version);
/^\d+(\.\d+)?(\.\d+)?$/g.test(version);
export const isValidFullVersion = (version: string) =>
packageFullVersionRegex.test(version);
/^\d+(\.\d+)(\.\d+)$/g.test(version);
const ALg = 1;
const ASm = -ALg;
@ -70,16 +68,18 @@ export function extractPackagePath(path: string): [string, string | undefined] {
path = path.slice(1);
}
let parts = path.split("@");
const parts = path.split("@");
if (parts.length > 2) throw new Error("Invalid package name!");
packageName += parts[0];
let packageVersion: string | undefined = parts[1];
const packageVersion: string | undefined = parts[1];
console.log({ path, parts, packageName, packageVersion });
if (!isValidPackageName(packageName))
throw new Error("Invalid package name!");
if (packageVersion !== "") {
if (packageVersion && packageVersion !== "") {
if (!isValidVersion(packageVersion))
throw new Error("Invalid package version!");
}
@ -87,32 +87,37 @@ export function extractPackagePath(path: string): [string, string | undefined] {
return [packageName, packageVersion];
}
import db from "./db.ts";
import type { IPackage } from "./db.ts";
import bucket from "./s3.ts";
export function getAbsolutePackageVersion(
pkg?: IPackage | null,
version?: string
) {
if (!pkg || pkg.versions.length < 1) return undefined;
export async function getFile(
pkgName: string,
version: string | null | undefined,
file: string
): Promise<{ etag: string; data: Uint8Array } | null | undefined> {
console.log("Searching for file: %s/%s@%s", pkgName, file, version);
const meta = await db.package.findOne({ name: pkgName });
const versions = pkg.versions.sort(sortVersions).reverse();
if (!meta || meta.versions.length < 1) return null;
const versions = meta.versions.sort(sortVersions).reverse();
if (!version) {
if (!version || version === "latest") {
version = versions[0];
} else {
const v = versions.filter((e) => e.startsWith(version as string));
if (v.length < 1) return null;
if (v.length < 1) return undefined;
version = v[0];
}
return version;
}
export function getFilePath(
pkgName: string,
version: string,
file: string
) {
if (file.startsWith("/")) {
file = file.substr(1);
}
const bucketPath = (
"packages/" +
pkgName +
"/" +
version +
@ -120,14 +125,36 @@ export async function getFile(
file
).replace(/@/g, "§");
return bucketPath;
}
export async function getOneOf(pkgName: string, version: string, files: (string | undefined)[]) {
for (const file of files) {
if (!file) continue;
const res = await getFile(pkgName, version, file);
if (res) return res;
}
return undefined;
}
export async function getFile(
pkgName: string,
version: string | undefined,
file: string
): Promise<{ etag: string; data: Uint8Array } | null | undefined> {
if (!version) return undefined;
const bucketPath = await getFilePath(pkgName, version, file);
if (!bucketPath) return null;
console.log("Getting file from:", bucketPath);
try {
const res = await bucket.getObject(bucketPath);
const res = await Storage.readFile(bucketPath);
if (!res) return undefined;
return {
etag: res.etag,
data: res.body,
etag: Base64.encodeBase64(await crypto.subtle.digest("sha-1", res)),
data: res,
};
} catch (err) {
const msg = err.message as string;
@ -135,3 +162,18 @@ export async function getFile(
throw err;
}
}
const exts = new Map<string, string>();
exts.set(".js", "text/javascript");
exts.set(".mjs", "text/javascript");
exts.set(".json", "application/json");
exts.set(".jsonld", "application/ld+json");
exts.set(".css", "text/css");
exts.set(".html", "text/html");
exts.set(".htm", "text/html");
export function getContentType(filename: string) {
const ext = Path.extname(filename);
return exts.get(ext);
}

7
registry/src/vendor/prism.ts vendored Normal file
View File

@ -0,0 +1,7 @@
import "./prism/prism.js";
const Prism = (window as any).Prism;
delete (window as any).Prism;
export default Prism;

239
registry/src/vendor/prism/prism.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,24 +1,103 @@
/// <reference path="../types/jsx.d.ts" />
import { React } from "../deps.ts";
import { Nano } from "../deps.ts";
const { h } = Nano;
import config from "../config.ts";
const styles = new TextDecoder().decode(
Deno.readFileSync("src/views/styles.css")
);
export default function Base(p: any, children: any[]) {
// href="https://unpkg.com/papercss@1.6.1/dist/paper.min.css"
export default function Base(p: any) {
const title = p.title || "DenReg";
return (
<html>
<html lang="en">
<head>
<meta charset="UTF-8"></meta>
<style dangerouslySetInnerHTML={{ __html: ".clean {all:revert;}" }} />
{/* <link
rel="stylesheet"
href="https://deno.hibas123.de/raw/@hibas123-theme@2.0.2/out/base.css"
/> */}
<link rel="stylesheet" href="/public/paper.min.css" />
<link
rel="stylesheet"
href="https://unpkg.com/papercss@1.6.1/dist/paper.min.css"
rel="apple-touch-icon"
sizes="57x57"
href="/public/apple-icon-57x57.png"
/>
<style innerHTML={styles}></style>
<link
rel="apple-touch-icon"
sizes="60x60"
href="/public/apple-icon-60x60.png"
/>
<link
rel="apple-touch-icon"
sizes="72x72"
href="/public/apple-icon-72x72.png"
/>
<link
rel="apple-touch-icon"
sizes="76x76"
href="/public/apple-icon-76x76.png"
/>
<link
rel="apple-touch-icon"
sizes="114x114"
href="/public/apple-icon-114x114.png"
/>
<link
rel="apple-touch-icon"
sizes="120x120"
href="/public/apple-icon-120x120.png"
/>
<link
rel="apple-touch-icon"
sizes="144x144"
href="/public/apple-icon-144x144.png"
/>
<link
rel="apple-touch-icon"
sizes="152x152"
href="/public/apple-icon-152x152.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/public/apple-icon-180x180.png"
/>
<link
rel="icon"
type="image/png"
sizes="192x192"
href="/public/android-icon-192x192.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/public/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="96x96"
href="/public/favicon-96x96.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/public/favicon-16x16.png"
/>
<link rel="manifest" href="/public/manifest.json" />
<meta name="msapplication-TileColor" content="#ffffff" />
<meta
name="msapplication-TileImage"
content="/public/ms-icon-144x144.png"
/>
<meta name="theme-color" content="#ffffff"></meta>
<link href="/public/prism.css" rel="stylesheet" />
<style dangerouslySetInnerHTML={{ __html: styles }}></style>
<title>{title}</title>
<meta
name="Description"
@ -29,7 +108,12 @@ export default function Base(p: any, children: any[]) {
content="width=device-width,initial-scale=1"
/>
</head>
<body class="site">{children}</body>
<body class="site">
{config.web.tracking && (
<tracking dangerouslySetInnerHTML={{ __html: config.web.tracking }}></tracking>
)}
{p.children}
</body>
</html>
);
}

View File

@ -0,0 +1,114 @@
import { Marked } from "../deps.ts";
import { Nano } from "../deps.ts";
const { h, Fragment } = Nano;
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;"
dangerouslySetInnerHTML={{ __html: content }}
/>
);
} else {
let lang = languages[ext.replace(".", "")] || ext.replace(".", "");
if (Prism.languages[lang]) {
content = Prism.highlight(content, Prism.languages[lang], lang);
}
return <pre><code dangerouslySetInnerHTML={{ __html: content }}> </code></pre>;
}
}
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>
</>
);
}

View File

@ -1,15 +1,15 @@
/// <reference path="../types/jsx.d.ts" />
import { React, Fragment } from "../deps.ts";
import { Nano } from "../deps.ts";
const { h } = Nano;
export function Main(a: any, children: any) {
export function Main(a: any) {
return (
<div style="grid-area: main">
<div class="paper">{children}</div>
<div class="paper">{a.children}</div>
</div>
);
}
export function Menu({}: any, children: any) {
export function Menu(a: any) {
return (
<div style="grid-area: menu">
<div class="paper">
@ -23,7 +23,7 @@ export function Menu({}: any, children: any) {
</a>
</h3>
{children}
{a.children}
</div>
</div>
);

View File

@ -0,0 +1,22 @@
// /// <reference path="../types/jsx.d.ts" />
import { Nano } from "../deps.ts";
const { h, Fragment } = Nano;
import type { IPackage } from "../db.ts";
export default function index({
pkg,
version,
}: {
pkg: IPackage;
version?: string;
}) {
return (
<>
<h2 style="margin-bottom: 0">Package: {pkg.name}</h2>
<h4 class="text-muted" style="margin-top: 0; margin-left: .5rem">
By {pkg.owner}
</h4>
</>
);
}

View File

@ -0,0 +1,38 @@
import { Nano } from "../deps.ts";
const { h } = Nano;
import Base from "./_base.tsx";
import type { IPackage } from "../db.ts";
import { Main, Menu } from "./_default.tsx";
import { RenderFile, EntryList, BrowseHeader } from "./_browse.tsx";
export default function index({
pkg,
version,
content,
ext,
path,
}: {
pkg: IPackage;
version?: string;
content: string;
ext: string;
path: string;
}) {
if (!pkg)
return (
<Base>
<h1>Not found</h1>
</Base>
);
return (
<Base title={"DenReg - " + pkg.name}>
<Main>
<BrowseHeader pkg={pkg} version={version} path={path} />
<RenderFile content={content} ext={ext} />
</Main>
<Menu></Menu>
</Base>
);
}

View File

@ -0,0 +1,43 @@
import { Nano } from "../deps.ts";
const { h } = Nano;
import Base from "./_base.tsx";
import type { IPackage } from "../db.ts";
import { Main, Menu } from "./_default.tsx";
import { RenderFile, EntryList, BrowseHeader } from "./_browse.tsx";
export default function index({
pkg,
version,
files,
directories,
readme,
path,
}: {
pkg: IPackage;
version?: string;
files: { name: string; size: number }[];
directories: { name: string }[];
readme?: string;
path: string;
}) {
if (!pkg)
return (
<Base>
<h1>Not found</h1>
</Base>
);
return (
<Base title={"DenReg - " + pkg.name}>
<Main>
<BrowseHeader pkg={pkg} version={version} path={path} />
<EntryList directories={directories} files={files} />
{readme && <RenderFile content={readme} ext={".md"} />}
</Main>
<Menu></Menu>
</Base>
);
}

View File

@ -1,7 +1,7 @@
/// <reference path="../types/jsx.d.ts" />
import { React, Fragment } from "../deps.ts";
import { Nano } from "../deps.ts";
const { h } = Nano;
import Base from "./_base.tsx";
import DB, { IPackage } from "../db.ts";
import type { IPackage } from "../db.ts";
import { sortVersions } from "../utils.ts";
function Package({ pkg }: { pkg: IPackage }) {
@ -10,9 +10,11 @@ function Package({ pkg }: { pkg: IPackage }) {
const sorted = versions.sort(sortVersions).reverse();
return (
<div
class="card package-list-margin"
onClick={"window.location.href = '/package/" + name + "'"}
<a
style="text-decoration:none; color: black"
class="clean card package-list-margin"
href={"/package/" + name}
// onClick={"window.location.href = '/package/" + name + "'"}
>
<div class="card-body">
<h4 class="card-title">
@ -27,13 +29,13 @@ function Package({ pkg }: { pkg: IPackage }) {
{description}
</div>
</div>
</div>
</a>
);
}
import { Main, Menu } from "./_default.tsx";
export default async function index({
export default function index({
packages,
search,
}: {

View File

@ -1,9 +1,9 @@
/// <reference path="../types/jsx.d.ts" />
import { React, Fragment, Marked } from "../deps.ts";
import { Nano, Marked } from "../deps.ts";
const { h, Suspense } = Nano;
import Base from "./_base.tsx";
import DB, { IPackage } from "../db.ts";
import { sortVersions, getFile } from "../utils.ts";
import type { IPackage } from "../db.ts";
import { sortVersions, getFile, getAbsolutePackageVersion } from "../utils.ts";
import PkgHeader from "./_pkgheader.tsx";
// function Package({ pkg }: { pkg: IPackage }) {
// const { name, versions, author } = pkg;
@ -30,12 +30,14 @@ import { sortVersions, getFile } from "../utils.ts";
import { Main, Menu } from "./_default.tsx";
export default async function index({
export default function index({
pkg,
version,
readmeContent
}: {
pkg: IPackage;
version?: string;
readmeContent: string | undefined;
}) {
if (!pkg)
return (
@ -44,40 +46,23 @@ export default async function index({
</Base>
);
const readmeContent = await getFile(pkg.name, version, "README.md").then(
(res) => {
if (res)
return Marked.parse(new TextDecoder().decode(res.data))
.content as string;
else return undefined;
}
);
version = getAbsolutePackageVersion(pkg, version);
return (
<Base title={"DenReg - " + pkg.name}>
<Main>
<h2 style="margin-bottom: 0">Package: {pkg.name}</h2>
<h4 class="text-muted" style="margin-top: 0; margin-left: .5rem">
By {pkg.owner}
</h4>
<PkgHeader pkg={pkg} version={version} />
<div class="tabs">
<input id="tab1" type="radio" name="tabs" checked />
<label for="tab1">Readme</label>
<input id="tab2" type="radio" name="tabs" />
<label for="tab2">Versions</label>
{/*
<input id="tab3" type="radio" name="tabs" />
<label for="tab3">Tab 3</label>
<input id="tab4" type="radio" name="tabs" />
<label for="tab4">Tab 4</label> */}
<div class="content" id="content1">
{readmeContent !== undefined ? (
<div
style="overflow-x: hidden"
innerHTML={readmeContent}
dangerouslySetInnerHTML={{ __html: Marked.parse(readmeContent).content }}
/>
) : (
<div class="alert alert-warning">No README.md found!</div>
@ -95,7 +80,11 @@ export default async function index({
</div>
</div>
</Main>
<Menu></Menu>
<Menu>
<a href={`/browse/${pkg.name}${version ? "@" + version : ""}/`}>
Browse Files
</a>
</Menu>
</Base>
);
}
}

Some files were not shown because too many files have changed in this diff Show More