Compare commits
33 Commits
2194bf199e
...
1.0.1
Author | SHA1 | Date | |
---|---|---|---|
675a73e551 | |||
310c8e12fa | |||
a14a5b9462 | |||
a0fef1ef76 | |||
3cda4ee8c8 | |||
e5829d9a4f | |||
3efe4fc34e | |||
22a447604b | |||
9dfb8d65d3 | |||
6bc090e51b | |||
965ca33d33 | |||
0202946813 | |||
53a11eccf6 | |||
325c1a4d7d | |||
c718e8898d | |||
6fe3ddbd37 | |||
79bcef0698 | |||
2af5d4f823 | |||
7c1166bf87 | |||
639287663d | |||
fbbb66d5af | |||
df1f4965ad | |||
10930db13d | |||
6b88be1b18 | |||
c9bd5c7d18 | |||
d1244ac0a7 | |||
e56d8b4548 | |||
ed1ce0cc0f | |||
252bf4aac3 | |||
a3a7370be0 | |||
10a7c26642 | |||
7e821f9771 | |||
1b7c4847dc |
@ -12,7 +12,7 @@ steps:
|
|||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
auto_tag: true
|
auto_tag: true
|
||||||
context: registry
|
context: registry
|
||||||
repo: hibas123.azurecr.io/denreg
|
repo: docker.hibas123.de/denreg
|
||||||
registry: hibas123.azurecr.io
|
registry: docker.hibas123.de
|
||||||
dockerfile: registry/Dockerfile
|
dockerfile: registry/Dockerfile
|
||||||
debug: false
|
debug: false
|
||||||
|
36
.github/workflows/ci.yml
vendored
Normal file
36
.github/workflows/ci.yml
vendored
Normal 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
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -4,5 +4,9 @@
|
|||||||
"debug.javascript.usePreview": false,
|
"debug.javascript.usePreview": false,
|
||||||
"deno.import_intellisense_origins": {
|
"deno.import_intellisense_origins": {
|
||||||
"https://deno.land": true
|
"https://deno.land": true
|
||||||
|
},
|
||||||
|
"deno.suggest.imports.hosts": {
|
||||||
|
"https://deno.land": true,
|
||||||
|
"https://deno.hibas123.de": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Colors, Cliffy } from "../deps.ts";
|
import { Colors, CliffyPrompt } from "../deps.ts";
|
||||||
|
|
||||||
import { getMeta, setMeta, log } from "../global.ts";
|
import { getMeta, setMeta, log } from "../global.ts";
|
||||||
|
|
||||||
export default async function deprecate(options: any) {
|
export default async function deprecate(options: any) {
|
||||||
const meta = await getMeta();
|
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?"
|
"Are you sure you want to deprecat this package?"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Cliffy, Path, FS } from "../deps.ts";
|
import { CliffyPrompt, Path, FS } from "../deps.ts";
|
||||||
import {
|
import {
|
||||||
getMeta,
|
getMeta,
|
||||||
setMeta,
|
setMeta,
|
||||||
@ -11,7 +11,7 @@ export default async function init() {
|
|||||||
let existing = {};
|
let existing = {};
|
||||||
try {
|
try {
|
||||||
existing = await getMeta();
|
existing = await getMeta();
|
||||||
} catch (err) {}
|
} catch (err) { }
|
||||||
let meta: IMeta = {
|
let meta: IMeta = {
|
||||||
name: Path.basename(Deno.cwd()).toLowerCase().replace(/\s+/g, "-"),
|
name: Path.basename(Deno.cwd()).toLowerCase().replace(/\s+/g, "-"),
|
||||||
version: "0.0.1",
|
version: "0.0.1",
|
||||||
@ -23,21 +23,21 @@ export default async function init() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isInteractive()) {
|
if (isInteractive()) {
|
||||||
meta.name = await Cliffy.Input.prompt({
|
meta.name = await CliffyPrompt.Input.prompt({
|
||||||
message: "What's the name of your package?",
|
message: "What's the name of your package?",
|
||||||
default: meta.name,
|
default: meta.name,
|
||||||
});
|
});
|
||||||
meta.description = await Cliffy.Input.prompt({
|
meta.description = await CliffyPrompt.Input.prompt({
|
||||||
message: "What's the description of your package?",
|
message: "What's the description of your package?",
|
||||||
default: meta.description,
|
default: meta.description,
|
||||||
});
|
});
|
||||||
meta.author = await Cliffy.Input.prompt({
|
meta.author = await CliffyPrompt.Input.prompt({
|
||||||
message: "Who's the author of your package?",
|
message: "Who's the author of your package?",
|
||||||
default: meta.author,
|
default: meta.author,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!(await FS.exists("README.md"))) {
|
if (!(await FS.exists("README.md"))) {
|
||||||
const res = await Cliffy.Confirm.prompt({
|
const res = await CliffyPrompt.Confirm.prompt({
|
||||||
message: "Autogenerate README?",
|
message: "Autogenerate README?",
|
||||||
default: true,
|
default: true,
|
||||||
});
|
});
|
||||||
|
@ -1,45 +1,8 @@
|
|||||||
import { Colors, Path, FS, Compress, Base64 } from "../deps.ts";
|
import { Colors, Path, FS, Compress, Base64 } from "../deps.ts";
|
||||||
import { getMeta, IMeta, log, getConfig } from "../global.ts";
|
import { getMeta, IMeta, log, getConfig } from "../global.ts";
|
||||||
|
import { runHooks } from "../helper/run_script.ts";
|
||||||
import { ServerError } from "../helper/server_error.ts";
|
import { ServerError } from "../helper/server_error.ts";
|
||||||
|
import { checkPermOrExit } from "../helper/permission.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function publish(options: { dry: boolean }) {
|
export default async function publish(options: { dry: boolean }) {
|
||||||
const originalMeta = await getMeta();
|
const originalMeta = await getMeta();
|
||||||
@ -100,6 +63,8 @@ export default async function publish(options: { dry: boolean }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!options.dry) {
|
if (!options.dry) {
|
||||||
|
await checkPermOrExit("net", "Net permission required for publishing");
|
||||||
|
|
||||||
log("Uploading new package version");
|
log("Uploading new package version");
|
||||||
await fetch(url, {
|
await fetch(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
18
cli/commands/run.ts
Normal file
18
cli/commands/run.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +1,23 @@
|
|||||||
import { Cliffy } from "../deps.ts";
|
import { CliffyPrompt } from "../deps.ts";
|
||||||
|
|
||||||
import { getConfig, setConfig } from "../global.ts";
|
import { getConfig, setConfig } from "../global.ts";
|
||||||
|
|
||||||
export default async function setup() {
|
export default async function setup() {
|
||||||
const registry = await Cliffy.Input.prompt({
|
const registry = await CliffyPrompt.Input.prompt({
|
||||||
message: "What's your registry?",
|
message: "What's your registry?",
|
||||||
default: getConfig("registry"),
|
default: getConfig("registry"),
|
||||||
});
|
});
|
||||||
const username = await Cliffy.Input.prompt({
|
const username = await CliffyPrompt.Input.prompt({
|
||||||
message: "What's your username?",
|
message: "What's your username?",
|
||||||
default: getConfig("username"),
|
default: getConfig("username"),
|
||||||
});
|
});
|
||||||
const password = await Cliffy.Secret.prompt({
|
const password = await CliffyPrompt.Secret.prompt({
|
||||||
message: "What's your password?",
|
message: "What's your password?",
|
||||||
hidden: true,
|
hidden: true,
|
||||||
default: getConfig("password"),
|
default: getConfig("password"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const author = await Cliffy.Input.prompt({
|
const author = await CliffyPrompt.Input.prompt({
|
||||||
message: "Who are you? (optional) Name <email@example.com>",
|
message: "Who are you? (optional) Name <email@example.com>",
|
||||||
default: getConfig("author"),
|
default: getConfig("author"),
|
||||||
});
|
});
|
||||||
|
@ -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() {
|
export default async function upgrade() {
|
||||||
const res = await Cliffy.Confirm.prompt({
|
await requestPermOrExit(
|
||||||
message: "Are you sure you want to upgrade the denreg cli?",
|
"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,
|
default: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
const process = Deno.run({
|
const cmd_base = ["deno", "install", "-A", "--unstable", "-f"];
|
||||||
cmd: [
|
|
||||||
"deno",
|
const cmd1 = [
|
||||||
"install",
|
...cmd_base,
|
||||||
"-A",
|
`https://deno.hibas123.de/raw/@denreg-cli@${meta.version}/denreg.ts`,
|
||||||
"--unstable",
|
];
|
||||||
"-f",
|
|
||||||
"https://deno.hibas123.de/raw/@denreg-cli/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();
|
const s1 = await process1.status();
|
||||||
if (!s) {
|
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!"));
|
console.log(Colors.red("Upgrade failed!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 { init } from "./global.ts";
|
||||||
|
|
||||||
import { version } from "./version.ts";
|
import { version } from "./version.ts";
|
||||||
|
|
||||||
import setupCMD from "./commands/setup.ts";
|
import setupCMD from "./commands/setup.ts";
|
||||||
import initCMD from "./commands/init.ts";
|
import initCMD from "./commands/init.ts";
|
||||||
import bumpCMD from "./commands/bump.ts";
|
import bumpCMD from "./commands/bump.ts";
|
||||||
import publishCMD from "./commands/publish.ts";
|
import publishCMD from "./commands/publish.ts";
|
||||||
import deprecateCMD from "./commands/deprecate.ts";
|
import deprecateCMD from "./commands/deprecate.ts";
|
||||||
import upgradeCMD from "./commands/upgrade.ts";
|
import upgradeCMD from "./commands/upgrade.ts";
|
||||||
|
import runCMD from "./commands/run.ts";
|
||||||
|
|
||||||
const HOME_FOLDER = Deno.env.get("HOME") || Deno.env.get("USERPROFILE") || "";
|
const HOME_FOLDER = Deno.env.get("HOME") || Deno.env.get("USERPROFILE") || "";
|
||||||
|
|
||||||
@ -26,7 +32,7 @@ const commandWrapper = (cmd: CommandHandler) => {
|
|||||||
opts = params;
|
opts = params;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const flags = await new Cliffy.Command()
|
const flags = await new CliffyCommand.Command()
|
||||||
.name("denreg")
|
.name("denreg")
|
||||||
.version(version)
|
.version(version)
|
||||||
.description("CLI for the Open Source DenReg package registry")
|
.description("CLI for the Open Source DenReg package registry")
|
||||||
@ -44,13 +50,13 @@ const flags = await new Cliffy.Command()
|
|||||||
})
|
})
|
||||||
.command(
|
.command(
|
||||||
"setup",
|
"setup",
|
||||||
new Cliffy.Command()
|
new CliffyCommand.Command()
|
||||||
.description("Configure cli")
|
.description("Configure cli")
|
||||||
.action(commandWrapper(setupCMD))
|
.action(commandWrapper(setupCMD))
|
||||||
)
|
)
|
||||||
.command(
|
.command(
|
||||||
"publish",
|
"publish",
|
||||||
new Cliffy.Command()
|
new CliffyCommand.Command()
|
||||||
.description("Upload package")
|
.description("Upload package")
|
||||||
.action(commandWrapper(publishCMD))
|
.action(commandWrapper(publishCMD))
|
||||||
.option("-d, --dry [dry:boolean]", "Dry run", {
|
.option("-d, --dry [dry:boolean]", "Dry run", {
|
||||||
@ -59,13 +65,13 @@ const flags = await new Cliffy.Command()
|
|||||||
)
|
)
|
||||||
.command(
|
.command(
|
||||||
"init",
|
"init",
|
||||||
new Cliffy.Command()
|
new CliffyCommand.Command()
|
||||||
.description("Create meta.json")
|
.description("Create meta.json")
|
||||||
.action(commandWrapper(initCMD))
|
.action(commandWrapper(initCMD))
|
||||||
)
|
)
|
||||||
.command(
|
.command(
|
||||||
"bump",
|
"bump",
|
||||||
new Cliffy.Command()
|
new CliffyCommand.Command()
|
||||||
.complete("major|minor|patch", () => ["major", "minor", "patch"])
|
.complete("major|minor|patch", () => ["major", "minor", "patch"])
|
||||||
.arguments("<major|minor|patch>")
|
.arguments("<major|minor|patch>")
|
||||||
.description("Change package version")
|
.description("Change package version")
|
||||||
@ -73,17 +79,26 @@ const flags = await new Cliffy.Command()
|
|||||||
)
|
)
|
||||||
.command(
|
.command(
|
||||||
"deprecate",
|
"deprecate",
|
||||||
new Cliffy.Command()
|
new CliffyCommand.Command()
|
||||||
.description("Deprecate package")
|
.description("Deprecate package")
|
||||||
.action(commandWrapper(deprecateCMD))
|
.action(commandWrapper(deprecateCMD))
|
||||||
)
|
)
|
||||||
.command(
|
.command(
|
||||||
"upgrade",
|
"upgrade",
|
||||||
new Cliffy.Command()
|
new CliffyCommand.Command()
|
||||||
.description("Upgrade to latest version of denreg cli")
|
.description("Upgrade to latest version of denreg cli")
|
||||||
.action(commandWrapper(upgradeCMD))
|
.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);
|
.parse(Deno.args);
|
||||||
|
|
||||||
await init(flags.options);
|
await init(flags.options);
|
||||||
@ -95,5 +110,5 @@ if (command) {
|
|||||||
console.log(Colors.bold(Colors.red("An error occured:")), err.message);
|
console.log(Colors.bold(Colors.red("An error occured:")), err.message);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
flags.cmd.help();
|
flags.cmd.showHelp();
|
||||||
}
|
}
|
||||||
|
14
cli/deps.ts
14
cli/deps.ts
@ -1,7 +1,11 @@
|
|||||||
export * as Compress from "https://deno.hibas123.de/raw/@denreg-tar/mod.ts";
|
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 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 CliffyPrompt from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/mod.ts";
|
||||||
export * as Base64 from "https://deno.land/std@0.65.0/encoding/base64.ts";
|
export * as CliffyCommand from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/mod.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 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
1
cli/dpm.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
import "./denreg.ts";
|
@ -14,6 +14,9 @@ export interface IMeta {
|
|||||||
prepublish?: string | string[];
|
prepublish?: string | string[];
|
||||||
postpublish?: string | string[];
|
postpublish?: string | string[];
|
||||||
};
|
};
|
||||||
|
scripts?: {
|
||||||
|
[key: string]: string | string[];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let verbose = false;
|
let verbose = false;
|
||||||
@ -42,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() {
|
export async function getMeta() {
|
||||||
log("Reading meta.json");
|
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> {
|
export async function setMeta(meta: IMeta): Promise<void> {
|
||||||
log("Saving meta.json");
|
log("Saving meta.json");
|
||||||
return FS.writeJson("meta.json", meta, {
|
return writeJson("meta.json", meta, " ");
|
||||||
spaces: " ",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let interactive = true;
|
let interactive = true;
|
||||||
|
26
cli/helper/permission.ts
Normal file
26
cli/helper/permission.ts
Normal 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
51
cli/helper/run_script.ts
Normal 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!"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@denreg-cli",
|
"name": "@denreg-cli",
|
||||||
"version": "0.2.7",
|
"version": "1.0.0",
|
||||||
"description": "CLI for the DenReg package registry",
|
"description": "CLI for the DenReg package registry",
|
||||||
"author": "Fabian Stamm <dev@fabianstamm.de>",
|
"author": "Fabian Stamm <dev@fabianstamm.de>",
|
||||||
"contributors": [],
|
"contributors": [],
|
||||||
@ -9,6 +9,9 @@
|
|||||||
"**/*.js",
|
"**/*.js",
|
||||||
"README.md"
|
"README.md"
|
||||||
],
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "version.ts"
|
||||||
|
},
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"prepublish": "pre.ts"
|
"prepublish": "pre.ts"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FS } from "./deps.ts";
|
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(
|
await Deno.writeTextFile(
|
||||||
"version.ts",
|
"version.ts",
|
||||||
|
0
cli/test.ts
Normal file
0
cli/test.ts
Normal file
@ -1 +1 @@
|
|||||||
export const version = "0.2.7"
|
export const version = "1.0.0"
|
||||||
|
16
jsx-html/.github/workflows/ci.yml
vendored
16
jsx-html/.github/workflows/ci.yml
vendored
@ -1,16 +0,0 @@
|
|||||||
name: ci
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v1
|
|
||||||
- uses: denolib/setup-deno@master
|
|
||||||
- run: deno --version
|
|
||||||
- run: deno test examples/01.tsx
|
|
||||||
- run: deno test examples/03-async.tsx
|
|
3
jsx-html/.gitignore
vendored
3
jsx-html/.gitignore
vendored
@ -1,3 +0,0 @@
|
|||||||
/dist
|
|
||||||
node_modules
|
|
||||||
tmp
|
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"trailingComma": "all",
|
|
||||||
"tabWidth": 4,
|
|
||||||
"singleQuote": true
|
|
||||||
}
|
|
4
jsx-html/.vscode/settings.json
vendored
4
jsx-html/.vscode/settings.json
vendored
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"deno.enable": true,
|
|
||||||
"deno.unstable": true
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2020 Alexandre Piel
|
|
||||||
|
|
||||||
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.
|
|
@ -1,103 +0,0 @@
|
|||||||
# jsx-html
|
|
||||||
|
|
||||||
`jsx-html` render JSX template to HTML asynchronously. Compatible with Deno, NodeJs and can also run in browser.
|
|
||||||
|
|
||||||
Try with runkit: https://runkit.com/apiel/jsx-html-example
|
|
||||||
|
|
||||||
## NodeJs
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add async-jsx-html
|
|
||||||
# or
|
|
||||||
npm install async-jsx-html
|
|
||||||
```
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { React } from 'async-jsx-html';
|
|
||||||
|
|
||||||
const View = () => <div>Hello</div>;
|
|
||||||
// render return a Promise
|
|
||||||
(<View />).render().then((html: string) => console.log(html));
|
|
||||||
```
|
|
||||||
|
|
||||||
## Deno
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
/// <reference path="https://raw.githubusercontent.com/apiel/jsx-html/master/jsx.d.ts" />
|
|
||||||
|
|
||||||
import { React } from 'https://raw.githubusercontent.com/apiel/jsx-html/master/mod.ts';
|
|
||||||
|
|
||||||
const View = () => <div>Hello</div>;
|
|
||||||
// render return a Promise
|
|
||||||
(<View />).render().then((html: string) => console.log(html));
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
deno run https://raw.githubusercontent.com/apiel/jsx-html/master/examples/00.tsx
|
|
||||||
```
|
|
||||||
|
|
||||||
## TsConfig
|
|
||||||
|
|
||||||
As you would do with React, you need to import `React` from `jsx-html` for the transpiler. If you are not feeling confortable with using `React` as import since it is not React, you can import `jsx` from `jsx-html` but you would have to update your tsconfig file: https://github.com/denoland/deno/issues/3572
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"jsx": "react",
|
|
||||||
"jsxFactory": "jsx"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
/// <reference path="https://raw.githubusercontent.com/apiel/jsx-html/master/jsx.d.ts" />
|
|
||||||
|
|
||||||
import { jsx } from 'https://raw.githubusercontent.com/apiel/jsx-html/master/mod.ts';
|
|
||||||
|
|
||||||
const View = () => <div>Hello</div>;
|
|
||||||
(<View />).render().then(console.log);
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Note:** prefer using sermver tags version instead of master to avoid conflict with caching, e.g:
|
|
||||||
> `import { jsx } from 'https://raw.githubusercontent.com/apiel/jsx-html/1.0.0/mod.ts';`.
|
|
||||||
|
|
||||||
## Async component
|
|
||||||
|
|
||||||
Unlike React, components can be asynchrone, so you can fetch for data without to handle states.
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { React } from 'https://raw.githubusercontent.com/apiel/jsx-html/master/mod.ts';
|
|
||||||
|
|
||||||
const Data = async () => {
|
|
||||||
const res = await fetch('http://example.com/some/api');
|
|
||||||
const content = new Uint8Array(await res.arrayBuffer());
|
|
||||||
return <div>{content}</div>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const View = () => (
|
|
||||||
<div>
|
|
||||||
<Data />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
(<View />).render().then(console.log);
|
|
||||||
```
|
|
||||||
|
|
||||||
# InnerHTML
|
|
||||||
|
|
||||||
The Element property innerHTML sets the HTML or XML markup contained within the property.
|
|
||||||
|
|
||||||
In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack.
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
/// <reference path="https://raw.githubusercontent.com/apiel/jsx-html/master/jsx.d.ts" />
|
|
||||||
|
|
||||||
import { jsx } from 'https://raw.githubusercontent.com/apiel/jsx-html/master/mod.ts';
|
|
||||||
|
|
||||||
const View = () => <div innerHTML="<b>hello</b> world" />;
|
|
||||||
(<View />).render().then(console.log); // will output <div><b>hello</b> world</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Browser
|
|
||||||
|
|
||||||
`jsx-html` can also be used directly in browser. Find an example with webpack [here](https://github.com/apiel/jsx-html/tree/master/examples/browser).
|
|
@ -1,26 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var regExp = /\.(ts|tsx|js|jsx)$/i;
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
return {
|
|
||||||
visitor: {
|
|
||||||
ImportDeclaration: function ImportDeclaration(path) {
|
|
||||||
var source = path.node.source;
|
|
||||||
if (!source.value.match(regExp)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
source.value = source.value.replace(regExp, '');
|
|
||||||
},
|
|
||||||
ExportDeclaration: function ExportDeclaration(path) {
|
|
||||||
var source = path.node.source;
|
|
||||||
if (source) {
|
|
||||||
if (!source.value.match(regExp)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
source.value = source.value.replace(regExp, '');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
export enum NODE_TYPE {
|
|
||||||
ELEMENT = 'element',
|
|
||||||
TEXT = 'text',
|
|
||||||
COMPONENT = 'component',
|
|
||||||
FRAGMENT = 'fragment',
|
|
||||||
};
|
|
3496
jsx-html/deno.d.ts
vendored
3496
jsx-html/deno.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"cmds": {
|
|
||||||
"start": ["den 00", "den 01", "den 02", "den 03", "den 04", "den 05", "den 06"],
|
|
||||||
"test": ["den 01:test", "den 03:test", "den 05:test", "den 06:test"],
|
|
||||||
"00": "deno run examples/00.tsx",
|
|
||||||
"01": "deno run examples/01.tsx",
|
|
||||||
"01:test": "deno test examples/01.tsx",
|
|
||||||
"02": "deno run -c examples/02/tsconfig.json examples/02/02.tsx",
|
|
||||||
"03": "deno run examples/03-async.tsx",
|
|
||||||
"03:test": "deno test examples/03-async.tsx",
|
|
||||||
"04": "deno run examples/04.tsx",
|
|
||||||
"05": "deno run examples/05.tsx",
|
|
||||||
"05:test": "deno test examples/05.tsx",
|
|
||||||
"06": "deno run examples/06.tsx",
|
|
||||||
"06:test": "deno test examples/06.tsx"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
const { parse } = require('@babel/parser');
|
|
||||||
const { default: generator } = require('@babel/generator');
|
|
||||||
const { default: traverse } = require('@babel/traverse');
|
|
||||||
const { resolve, extname, join, dirname } = require('path');
|
|
||||||
const { tmpdir } = require('os');
|
|
||||||
const { readdir } = require('fs').promises;
|
|
||||||
const { cwd } = require('process');
|
|
||||||
|
|
||||||
const exts = ['.ts'];
|
|
||||||
const excludes = [
|
|
||||||
'/node_modules/',
|
|
||||||
'/examples/',
|
|
||||||
'/dist/',
|
|
||||||
'/jsx.d.ts',
|
|
||||||
'/mod.d.ts',
|
|
||||||
'/deno.d.ts',
|
|
||||||
];
|
|
||||||
|
|
||||||
const regExpRemoveExts = /\.(ts|tsx|js|jsx)$/i;
|
|
||||||
|
|
||||||
const tsconfig = {
|
|
||||||
compilerOptions: {
|
|
||||||
types: ['node'],
|
|
||||||
module: 'commonjs',
|
|
||||||
declaration: true,
|
|
||||||
removeComments: true,
|
|
||||||
emitDecoratorMetadata: true,
|
|
||||||
experimentalDecorators: true,
|
|
||||||
allowSyntheticDefaultImports: true,
|
|
||||||
target: 'es6',
|
|
||||||
sourceMap: true,
|
|
||||||
outDir: join(cwd(), 'nodejs'),
|
|
||||||
baseUrl: './',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// const distFolder = join(tmpdir(), `deno2nodejs-${+new Date()}`);
|
|
||||||
const distFolder = join(cwd(), `tmp`);
|
|
||||||
console.log('distFolder:', distFolder);
|
|
||||||
fs.mkdirSync(distFolder);
|
|
||||||
fs.writeFileSync(join(distFolder, 'tsconfig.json'), JSON.stringify(tsconfig));
|
|
||||||
|
|
||||||
async function getFiles(dir) {
|
|
||||||
const dirents = await readdir(dir, { withFileTypes: true });
|
|
||||||
const files = await Promise.all(
|
|
||||||
dirents.map((dirent) => {
|
|
||||||
const res = resolve(dir, dirent.name);
|
|
||||||
return dirent.isDirectory() ? getFiles(res) : res;
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
return Array.prototype.concat(...files);
|
|
||||||
}
|
|
||||||
getFiles('./').then((files) => {
|
|
||||||
const tsFiles = files.filter(
|
|
||||||
(f) =>
|
|
||||||
exts.includes(extname(f)) &&
|
|
||||||
!excludes.some((val) => f.includes(val)),
|
|
||||||
);
|
|
||||||
tsFiles.forEach((file) => {
|
|
||||||
const code = deno2nodejs(file);
|
|
||||||
const dist = join(distFolder, file.substr(cwd().length));
|
|
||||||
const ensureDir = dirname(dist);
|
|
||||||
fs.mkdirSync(ensureDir, { recursive: true });
|
|
||||||
fs.writeFileSync(dist, code);
|
|
||||||
// console.log({ file, dist, ensureDir });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// we might want to execute `tsc -p ./tmp/tsconfig.json` in here
|
|
||||||
|
|
||||||
function deno2nodejs(file) {
|
|
||||||
const source = fs.readFileSync(file).toString();
|
|
||||||
|
|
||||||
const ast = parse(source, {
|
|
||||||
sourceType: 'module',
|
|
||||||
plugins: ['typescript', 'classProperties'],
|
|
||||||
});
|
|
||||||
|
|
||||||
traverse(ast, {
|
|
||||||
ImportDeclaration: function ImportDeclaration(path) {
|
|
||||||
var source = path.node.source;
|
|
||||||
if (!source.value.match(regExpRemoveExts)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
source.value = source.value.replace(regExpRemoveExts, '');
|
|
||||||
},
|
|
||||||
ExportDeclaration: function ExportDeclaration(path) {
|
|
||||||
var source = path.node.source;
|
|
||||||
if (source) {
|
|
||||||
if (!source.value.match(regExpRemoveExts)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
source.value = source.value.replace(regExpRemoveExts, '');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const { code } = generator(ast);
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
/// <reference path="https://raw.githubusercontent.com/apiel/jsx-html/latest/jsx.d.ts" />
|
|
||||||
|
|
||||||
import { React } from 'https://raw.githubusercontent.com/apiel/jsx-html/latest/mod.ts';
|
|
||||||
|
|
||||||
const View = () => <div>Hello</div>;
|
|
||||||
console.log((<View />).render());
|
|
@ -1,62 +0,0 @@
|
|||||||
/// <reference path="../jsx.d.ts" />
|
|
||||||
|
|
||||||
import { assertEquals } from 'https://deno.land/std/testing/asserts.ts';
|
|
||||||
import { React, Fragment } from '../mod.ts';
|
|
||||||
|
|
||||||
const Title = () => <h1>title</h1>;
|
|
||||||
const Value = ({ val }: { val: string }) => <p>value: {val}</p>;
|
|
||||||
const Numeric = ({ num }: { num: number }) => <p>num: {num}</p>;
|
|
||||||
|
|
||||||
const View = () => (
|
|
||||||
<div class="deno">
|
|
||||||
<Title />
|
|
||||||
<p onclick={() => 'lol'} valid checked={true} select="">
|
|
||||||
land
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<hr />
|
|
||||||
<Fragment>
|
|
||||||
<Value val="hello" />
|
|
||||||
<Numeric num={23} />
|
|
||||||
</Fragment>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (import.meta.main) {
|
|
||||||
(<View />).render().then(console.log);
|
|
||||||
} else {
|
|
||||||
// Run test
|
|
||||||
|
|
||||||
Deno.test('render title', async() => {
|
|
||||||
assertEquals(await (<Title />).render(), '<h1>title</h1>');
|
|
||||||
});
|
|
||||||
|
|
||||||
Deno.test('render value', async() => {
|
|
||||||
const val = 'hello';
|
|
||||||
assertEquals(await (<Value val={val} />).render(), `<p>value: ${val}</p>`);
|
|
||||||
});
|
|
||||||
|
|
||||||
Deno.test('render numeric', async() => {
|
|
||||||
const num = 123;
|
|
||||||
assertEquals(await (<Numeric num={num} />).render(), `<p>num: ${num}</p>`);
|
|
||||||
});
|
|
||||||
|
|
||||||
Deno.test('render view', async() => {
|
|
||||||
assertEquals(
|
|
||||||
await (<View />).render(),
|
|
||||||
'<div class="deno"><h1>title</h1><p valid checked select>land</p><br /><hr /><p>value: hello</p><p>num: 23</p></div>',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Deno.test('render empty', async ()=>{
|
|
||||||
assertEquals(
|
|
||||||
await (<div/>).render(),
|
|
||||||
`<div></div>`
|
|
||||||
)
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
await (<img/>).render(),
|
|
||||||
`<img />`
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
/// <reference path="../../jsx.d.ts" />
|
|
||||||
|
|
||||||
import { jsx } from '../../mod.ts';
|
|
||||||
|
|
||||||
const View = () => <div>Hello</div>;
|
|
||||||
(<View />).render().then(console.log);
|
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"jsx": "react",
|
|
||||||
"jsxFactory": "jsx"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
/// <reference path="../jsx.d.ts" />
|
|
||||||
|
|
||||||
import { assertEquals } from 'https://deno.land/std/testing/asserts.ts';
|
|
||||||
import { delay } from 'https://deno.land/std/async/delay.ts';
|
|
||||||
import { React } from '../mod.ts';
|
|
||||||
|
|
||||||
const Title = async () => {
|
|
||||||
await delay(100);
|
|
||||||
return <h1>title{ await delay(100) }</h1>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const View = () => (
|
|
||||||
<div>
|
|
||||||
<Title />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (import.meta.main) {
|
|
||||||
(<View />).render().then(console.log);
|
|
||||||
} else {
|
|
||||||
// Run test
|
|
||||||
|
|
||||||
Deno.test('render title', async () => {
|
|
||||||
assertEquals(await (<Title />).render(), '<h1>title</h1>');
|
|
||||||
});
|
|
||||||
|
|
||||||
Deno.test('render view', async () => {
|
|
||||||
assertEquals(await (<View />).render(), '<div><h1>title</h1></div>');
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
/// <reference path="../jsx.d.ts" />
|
|
||||||
|
|
||||||
import { React } from '../mod.ts';
|
|
||||||
|
|
||||||
const View = () => <div>Hello</div>;
|
|
||||||
|
|
||||||
if (import.meta.main) {
|
|
||||||
(<View />).render().then(console.log);
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
/// <reference path="../jsx.d.ts" />
|
|
||||||
import { assertEquals } from 'https://deno.land/std/testing/asserts.ts';
|
|
||||||
|
|
||||||
import { React } from '../mod.ts';
|
|
||||||
|
|
||||||
const View = () => {
|
|
||||||
const techs = ['NodeJS', 'React Native', 'Next'];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ul>
|
|
||||||
{techs.map((tech: any) => (
|
|
||||||
<li>{tech}</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (import.meta.main) {
|
|
||||||
(<View />).render().then(console.log);
|
|
||||||
} else {
|
|
||||||
Deno.test('render with array', async () => {
|
|
||||||
assertEquals(
|
|
||||||
await (<View />).render(),
|
|
||||||
'<ul><li>NodeJS</li><li>React Native</li><li>Next</li></ul>',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/// <reference path="../jsx.d.ts" />
|
|
||||||
import { assertEquals } from 'https://deno.land/std/testing/asserts.ts';
|
|
||||||
|
|
||||||
import { React } from '../mod.ts';
|
|
||||||
|
|
||||||
const View = () => {
|
|
||||||
return <div innerHTML="<b>hello</b> world" />;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (import.meta.main) {
|
|
||||||
(<View />).render().then(console.log);
|
|
||||||
} else {
|
|
||||||
Deno.test('render with array', async () => {
|
|
||||||
assertEquals(
|
|
||||||
await (<View />).render(),
|
|
||||||
'<div><b>hello</b> world</div>',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
19
jsx-html/examples/browser/dist/index.html
vendored
19
jsx-html/examples/browser/dist/index.html
vendored
@ -1,19 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Page Title</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<script src="index.js"></script>
|
|
||||||
|
|
||||||
<div id="div-container" />
|
|
||||||
|
|
||||||
<script>
|
|
||||||
demo.Test().render('#div-container').then((html) => {
|
|
||||||
document.getElementById('div-container').innerHTML = html;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
502
jsx-html/examples/browser/dist/index.js
vendored
502
jsx-html/examples/browser/dist/index.js
vendored
File diff suppressed because one or more lines are too long
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "jsx-to-html-testing",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "jsx-to-html-testing",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"watch": "webpack --watch",
|
|
||||||
"start": "webpack-dev-server --open",
|
|
||||||
"build": "webpack"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "Alex",
|
|
||||||
"license": "ISC",
|
|
||||||
"devDependencies": {
|
|
||||||
"ts-loader": "^8.0.1",
|
|
||||||
"typescript": "^3.9.7",
|
|
||||||
"webpack": "^4.44.1",
|
|
||||||
"webpack-cli": "^3.3.12",
|
|
||||||
"webpack-dev-server": "^3.11.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"async-jsx-html": "^1.2.1"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
import { jsx, ElementNode } from 'async-jsx-html';
|
|
||||||
|
|
||||||
export function Test(): ElementNode {
|
|
||||||
return <div>Hello World</div>;
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "./dist/",
|
|
||||||
"module": "commonjs",
|
|
||||||
"jsx": "react",
|
|
||||||
"jsxFactory": "jsx",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"allowJs": true,
|
|
||||||
"lib": [
|
|
||||||
"es6",
|
|
||||||
"dom"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
const MODULE_NAME = 'demo';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
mode: 'development',
|
|
||||||
entry: {
|
|
||||||
index: './src/index.tsx'
|
|
||||||
},
|
|
||||||
devtool: 'inline-source-map',
|
|
||||||
devServer: {
|
|
||||||
contentBase: './dist'
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.tsx?$/,
|
|
||||||
use: 'ts-loader',
|
|
||||||
exclude: /node_modules/,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
extensions: [ '.tsx', '.ts', '.js' ],
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
filename: '[name].js',
|
|
||||||
path: path.resolve(__dirname, 'dist'),
|
|
||||||
libraryTarget: 'umd',
|
|
||||||
globalObject: 'this',
|
|
||||||
// libraryExport: 'default',
|
|
||||||
library: MODULE_NAME
|
|
||||||
},
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load Diff
@ -1,30 +0,0 @@
|
|||||||
let {
|
|
||||||
React,
|
|
||||||
Fragment
|
|
||||||
} = require('../nodejs/mod');
|
|
||||||
|
|
||||||
const Title = () => /*#__PURE__*/React.createElement("h1", null, "title");
|
|
||||||
|
|
||||||
const Value = ({
|
|
||||||
val
|
|
||||||
}) => /*#__PURE__*/React.createElement("p", null, "value: ", val);
|
|
||||||
|
|
||||||
const Numeric = ({
|
|
||||||
num
|
|
||||||
}) => /*#__PURE__*/React.createElement("p", null, "num: ", num);
|
|
||||||
|
|
||||||
const View = () => /*#__PURE__*/React.createElement("div", {
|
|
||||||
class: "deno"
|
|
||||||
}, /*#__PURE__*/React.createElement(Title, null), /*#__PURE__*/React.createElement("p", {
|
|
||||||
onclick: () => 'lol',
|
|
||||||
valid: true,
|
|
||||||
checked: true,
|
|
||||||
select: ""
|
|
||||||
}, "land"), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("hr", null), /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(Value, {
|
|
||||||
val: "hello"
|
|
||||||
}), /*#__PURE__*/React.createElement(Numeric, {
|
|
||||||
num: 23
|
|
||||||
})));
|
|
||||||
|
|
||||||
/*#__PURE__*/
|
|
||||||
React.createElement(View, null).render().then(console.log);
|
|
@ -1,22 +0,0 @@
|
|||||||
let { React, Fragment } = require('../nodejs/mod');
|
|
||||||
|
|
||||||
const Title = () => <h1>title</h1>;
|
|
||||||
const Value = ({ val }) => <p>value: {val}</p>;
|
|
||||||
const Numeric = ({ num }) => <p>num: {num}</p>;
|
|
||||||
|
|
||||||
const View = () => (
|
|
||||||
<div class="deno">
|
|
||||||
<Title />
|
|
||||||
<p onclick={() => 'lol'} valid checked={true} select="">
|
|
||||||
land
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<hr />
|
|
||||||
<Fragment>
|
|
||||||
<Value val="hello" />
|
|
||||||
<Numeric num={23} />
|
|
||||||
</Fragment>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
(<View />).render().then(console.log);
|
|
5
jsx-html/jsx.d.ts
vendored
5
jsx-html/jsx.d.ts
vendored
@ -1,5 +0,0 @@
|
|||||||
declare namespace JSX {
|
|
||||||
interface IntrinsicElements {
|
|
||||||
[elemName: string]: any;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
import type {
|
|
||||||
NodePropsType,
|
|
||||||
ComponentFunctionType,
|
|
||||||
NullableChildType,
|
|
||||||
ChildType,
|
|
||||||
} from './types.ts';
|
|
||||||
|
|
||||||
import { ElementNode } from './node/ElementNode.ts';
|
|
||||||
import { ComponentNode } from './node/ComponentNode.ts';
|
|
||||||
|
|
||||||
export const jsx = <P extends NodePropsType = NodePropsType>(
|
|
||||||
element: string | ComponentFunctionType,
|
|
||||||
props: P | null,
|
|
||||||
...children: NullableChildType[]
|
|
||||||
) => {
|
|
||||||
const nodeProps = props || {};
|
|
||||||
|
|
||||||
if (typeof element === 'string') {
|
|
||||||
return new ElementNode(element, nodeProps, children);
|
|
||||||
}
|
|
||||||
if (typeof element === 'function') {
|
|
||||||
return new ComponentNode(element, nodeProps, children);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new TypeError(`Expected jsx element to be a string or a function`);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Fragment = (
|
|
||||||
props: NodePropsType,
|
|
||||||
children: ChildType,
|
|
||||||
): NullableChildType => {
|
|
||||||
return children;
|
|
||||||
};
|
|
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "jsx-html",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"description": "",
|
|
||||||
"author": "Fabian Stamm <dev@fabianstamm.de>",
|
|
||||||
"contributors": [],
|
|
||||||
"files": [
|
|
||||||
"**/*.ts",
|
|
||||||
"**/*.js",
|
|
||||||
"README.md"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
import { jsx, Fragment } from './jsx.ts';
|
|
||||||
import type {
|
|
||||||
ComponentFunctionType,
|
|
||||||
NodePropsType,
|
|
||||||
NullableChildType,
|
|
||||||
} from './types.ts';
|
|
||||||
|
|
||||||
export { ElementNode } from './node/ElementNode.ts';
|
|
||||||
export { ComponentNode } from './node/ComponentNode.ts';
|
|
||||||
export type {
|
|
||||||
jsx,
|
|
||||||
Fragment,
|
|
||||||
ComponentFunctionType,
|
|
||||||
NullableChildType,
|
|
||||||
NodePropsType,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const React = {
|
|
||||||
Fragment,
|
|
||||||
createElement<P extends NodePropsType = NodePropsType>(
|
|
||||||
element: string | ComponentFunctionType,
|
|
||||||
props: P | null,
|
|
||||||
...children: NullableChildType[]
|
|
||||||
) {
|
|
||||||
return jsx(element, props, ...children);
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,37 +0,0 @@
|
|||||||
import type {
|
|
||||||
NodePropsType,
|
|
||||||
ComponentFunctionType,
|
|
||||||
NullableChildType,
|
|
||||||
} from '../types.ts';
|
|
||||||
import { NODE_TYPE } from '../constants.ts';
|
|
||||||
import { FragmentNode } from './FragmentNode.ts';
|
|
||||||
import { Node } from './Node.ts';
|
|
||||||
import { normalizeChildren } from './utils/normalizeChildren.ts';
|
|
||||||
|
|
||||||
export class ComponentNode extends Node {
|
|
||||||
type = NODE_TYPE.COMPONENT;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
public component: ComponentFunctionType,
|
|
||||||
public props: NodePropsType,
|
|
||||||
children: NullableChildType[],
|
|
||||||
) {
|
|
||||||
super(children);
|
|
||||||
}
|
|
||||||
|
|
||||||
async render(): Promise<string | any[]> {
|
|
||||||
return [].concat((await this.renderComponent()) as any).join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
async renderComponent() {
|
|
||||||
const child = await this.component(this.props, this.children);
|
|
||||||
const children = normalizeChildren(
|
|
||||||
Array.isArray(child) ? child : [child],
|
|
||||||
);
|
|
||||||
if (children.length === 1) {
|
|
||||||
return children[0].render();
|
|
||||||
} else if (children.length > 1) {
|
|
||||||
return new FragmentNode(children).render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
import { NODE_TYPE } from '../constants.ts';
|
|
||||||
import type { NodePropsType, NullableChildType } from '../types.ts';
|
|
||||||
import { Node } from './Node.ts';
|
|
||||||
import { doubleQuoteEncode } from './utils/htmlEncode.ts';
|
|
||||||
|
|
||||||
const ELEMENT_PROP = {
|
|
||||||
INNER_HTML: 'innerHTML',
|
|
||||||
};
|
|
||||||
|
|
||||||
// List taken from http://w3c.github.io/html-reference/syntax.html
|
|
||||||
const VOID_ELEMENTS = new Set<string>([
|
|
||||||
'area',
|
|
||||||
'base',
|
|
||||||
'br',
|
|
||||||
'col',
|
|
||||||
'command',
|
|
||||||
'embed',
|
|
||||||
'hr',
|
|
||||||
'img',
|
|
||||||
'input',
|
|
||||||
'keygen',
|
|
||||||
'link',
|
|
||||||
'meta',
|
|
||||||
'param',
|
|
||||||
'source',
|
|
||||||
'track',
|
|
||||||
'wbr',
|
|
||||||
]);
|
|
||||||
|
|
||||||
export class ElementNode extends Node {
|
|
||||||
type = NODE_TYPE.ELEMENT;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
public name: string,
|
|
||||||
public props: NodePropsType,
|
|
||||||
children: NullableChildType[],
|
|
||||||
) {
|
|
||||||
super(children);
|
|
||||||
}
|
|
||||||
|
|
||||||
async render(): Promise<string | any[]> {
|
|
||||||
const renderedProps = this.propsToHTML();
|
|
||||||
|
|
||||||
const renderedChildren =
|
|
||||||
typeof this.props[ELEMENT_PROP.INNER_HTML] === 'string'
|
|
||||||
? this.props[ELEMENT_PROP.INNER_HTML]
|
|
||||||
: (await this.renderChildren()).join('');
|
|
||||||
|
|
||||||
return renderedChildren || !VOID_ELEMENTS.has(this.name)
|
|
||||||
? `<${this.name}${renderedProps}>${renderedChildren || ''}</${
|
|
||||||
this.name
|
|
||||||
}>`
|
|
||||||
: `<${this.name}${renderedProps} />`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getValidProps() {
|
|
||||||
const props = this.props;
|
|
||||||
return Object.keys(this.props).filter((key) => {
|
|
||||||
if (key === ELEMENT_PROP.INNER_HTML) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const val = props[key];
|
|
||||||
return (
|
|
||||||
typeof val === 'string' ||
|
|
||||||
typeof val === 'number' ||
|
|
||||||
val === true
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private propsToHTML(): string {
|
|
||||||
const keys = this.getValidProps();
|
|
||||||
if (!keys.length) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = this.props;
|
|
||||||
const pairs = keys.map((key) => {
|
|
||||||
if (!/^[a-zA-Z0-9-:\._]+$/.test(key)) {
|
|
||||||
throw new Error(`Invalid attribute name format ${key}`);
|
|
||||||
}
|
|
||||||
const val = props[key];
|
|
||||||
// https://html.spec.whatwg.org/multipage/dom.html#attributes
|
|
||||||
return val === true || val === ''
|
|
||||||
? key
|
|
||||||
: `${key}="${doubleQuoteEncode(val.toString())}"`;
|
|
||||||
});
|
|
||||||
|
|
||||||
return ` ${pairs.join(' ')}`;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
import { NODE_TYPE } from '../constants.ts';
|
|
||||||
import type { ChildNodeType } from '../types.ts';
|
|
||||||
import { Node } from './Node.ts';
|
|
||||||
|
|
||||||
export class FragmentNode extends Node {
|
|
||||||
type = NODE_TYPE.FRAGMENT;
|
|
||||||
|
|
||||||
constructor(children: ChildNodeType[]) {
|
|
||||||
super(children);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return this.renderChildren();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
import type { NODE_TYPE } from '../constants.ts';
|
|
||||||
import type { NullableChildType } from '../types.ts';
|
|
||||||
import { normalizeChildren } from './utils/normalizeChildren.ts';
|
|
||||||
|
|
||||||
export abstract class Node {
|
|
||||||
abstract type: NODE_TYPE;
|
|
||||||
|
|
||||||
constructor(public children: NullableChildType[]) {}
|
|
||||||
|
|
||||||
abstract async render(): Promise<string | any[]>;
|
|
||||||
|
|
||||||
async renderChildren() {
|
|
||||||
const result: string[] = [];
|
|
||||||
const children = normalizeChildren(this.children);
|
|
||||||
for (const child of children) {
|
|
||||||
const renderedChild = await child.render();
|
|
||||||
if (renderedChild) {
|
|
||||||
if (Array.isArray(renderedChild)) {
|
|
||||||
renderedChild.forEach(
|
|
||||||
(subchild) => subchild && result.push(subchild),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
result.push(renderedChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import { NODE_TYPE } from '../constants.ts';
|
|
||||||
import { htmlEncode } from './utils/htmlEncode.ts';
|
|
||||||
|
|
||||||
export class TextNode {
|
|
||||||
type = NODE_TYPE.TEXT;
|
|
||||||
|
|
||||||
constructor(public text: string) {}
|
|
||||||
|
|
||||||
async render(): Promise<string | any[]> {
|
|
||||||
return htmlEncode(this.text);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
export function doubleQuoteEncode(text: string): string {
|
|
||||||
return text
|
|
||||||
.replace(/"/g, '"')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function htmlEncode(text: string): string {
|
|
||||||
return doubleQuoteEncode(text
|
|
||||||
.replace(/&/g, '&')
|
|
||||||
.replace(/\//g, '/')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>')
|
|
||||||
.replace(/'/g, '''));
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
import type { NullableChildType, ChildNodeType } from '../../types.ts';
|
|
||||||
import { TextNode } from '../TextNode.ts';
|
|
||||||
import { NODE_TYPE } from '../../constants.ts';
|
|
||||||
|
|
||||||
export function normalizeChildren(
|
|
||||||
children: NullableChildType[],
|
|
||||||
): ChildNodeType[] {
|
|
||||||
const result: any[] = [];
|
|
||||||
|
|
||||||
for (const child of children) {
|
|
||||||
if (child && typeof child !== 'boolean') {
|
|
||||||
if (typeof child === 'string' || typeof child === 'number') {
|
|
||||||
result.push(new TextNode(`${child}`));
|
|
||||||
} else if (Array.isArray(child)) {
|
|
||||||
normalizeChildren(child).forEach((normalized) =>
|
|
||||||
result.push(normalized),
|
|
||||||
);
|
|
||||||
} else if (
|
|
||||||
child.type === NODE_TYPE.ELEMENT ||
|
|
||||||
child.type === NODE_TYPE.TEXT ||
|
|
||||||
child.type === NODE_TYPE.COMPONENT
|
|
||||||
) {
|
|
||||||
result.push(child);
|
|
||||||
} else {
|
|
||||||
throw new TypeError(`Unrecognized node type: ${typeof child}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
6
jsx-html/nodejs/constants.d.ts
vendored
6
jsx-html/nodejs/constants.d.ts
vendored
@ -1,6 +0,0 @@
|
|||||||
export declare enum NODE_TYPE {
|
|
||||||
ELEMENT = "element",
|
|
||||||
TEXT = "text",
|
|
||||||
COMPONENT = "component",
|
|
||||||
FRAGMENT = "fragment"
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.NODE_TYPE = void 0;
|
|
||||||
var NODE_TYPE;
|
|
||||||
(function (NODE_TYPE) {
|
|
||||||
NODE_TYPE["ELEMENT"] = "element";
|
|
||||||
NODE_TYPE["TEXT"] = "text";
|
|
||||||
NODE_TYPE["COMPONENT"] = "component";
|
|
||||||
NODE_TYPE["FRAGMENT"] = "fragment";
|
|
||||||
})(NODE_TYPE = exports.NODE_TYPE || (exports.NODE_TYPE = {}));
|
|
||||||
;
|
|
||||||
//# sourceMappingURL=constants.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../tmp/constants.ts"],"names":[],"mappings":";;;AAAA,IAAY,SAKX;AALD,WAAY,SAAS;IACnB,gCAAmB,CAAA;IACnB,0BAAa,CAAA;IACb,oCAAuB,CAAA;IACvB,kCAAqB,CAAA;AACvB,CAAC,EALW,SAAS,GAAT,iBAAS,KAAT,iBAAS,QAKpB;AACD,CAAC"}
|
|
5
jsx-html/nodejs/jsx.d.ts
vendored
5
jsx-html/nodejs/jsx.d.ts
vendored
@ -1,5 +0,0 @@
|
|||||||
import { NodePropsType, ComponentFunctionType, NullableChildType, ChildType } from "./types";
|
|
||||||
import { ElementNode } from "./node/ElementNode";
|
|
||||||
import { ComponentNode } from "./node/ComponentNode";
|
|
||||||
export declare const jsx: <P extends NodePropsType = NodePropsType>(element: string | ComponentFunctionType, props: P, ...children: NullableChildType[]) => ElementNode | ComponentNode;
|
|
||||||
export declare const Fragment: (props: NodePropsType, children: ChildType) => NullableChildType;
|
|
@ -1,19 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.Fragment = exports.jsx = void 0;
|
|
||||||
const ElementNode_1 = require("./node/ElementNode");
|
|
||||||
const ComponentNode_1 = require("./node/ComponentNode");
|
|
||||||
exports.jsx = (element, props, ...children) => {
|
|
||||||
const nodeProps = props || {};
|
|
||||||
if (typeof element === 'string') {
|
|
||||||
return new ElementNode_1.ElementNode(element, nodeProps, children);
|
|
||||||
}
|
|
||||||
if (typeof element === 'function') {
|
|
||||||
return new ComponentNode_1.ComponentNode(element, nodeProps, children);
|
|
||||||
}
|
|
||||||
throw new TypeError(`Expected jsx element to be a string or a function`);
|
|
||||||
};
|
|
||||||
exports.Fragment = (props, children) => {
|
|
||||||
return children;
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=jsx.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"jsx.js","sourceRoot":"","sources":["../tmp/jsx.ts"],"names":[],"mappings":";;;AACA,oDAAiD;AACjD,wDAAqD;AACxC,QAAA,GAAG,GAAG,CAA0C,OAAuC,EAAE,KAAe,EAAE,GAAG,QAA6B,EAAE,EAAE;IACzJ,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE,CAAC;IAE9B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;QAC/B,OAAO,IAAI,yBAAW,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;KACtD;IAED,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE;QACjC,OAAO,IAAI,6BAAa,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;KACxD;IAED,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;AAC3E,CAAC,CAAC;AACW,QAAA,QAAQ,GAAG,CAAC,KAAoB,EAAE,QAAmB,EAAqB,EAAE;IACvF,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
|
|
9
jsx-html/nodejs/mod.d.ts
vendored
9
jsx-html/nodejs/mod.d.ts
vendored
@ -1,9 +0,0 @@
|
|||||||
import { jsx, Fragment } from "./jsx";
|
|
||||||
import { ComponentFunctionType, NodePropsType, NullableChildType } from "./types";
|
|
||||||
export { ElementNode } from "./node/ElementNode";
|
|
||||||
export { ComponentNode } from "./node/ComponentNode";
|
|
||||||
export { jsx, Fragment, ComponentFunctionType, NullableChildType, NodePropsType };
|
|
||||||
export declare const React: {
|
|
||||||
Fragment: (props: NodePropsType, children: import("./types").ChildType) => NullableChildType;
|
|
||||||
createElement<P extends NodePropsType = NodePropsType>(element: string | ComponentFunctionType, props: P, ...children: NullableChildType[]): import("./node/ElementNode").ElementNode | import("./node/ComponentNode").ComponentNode;
|
|
||||||
};
|
|
@ -1,17 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.React = exports.Fragment = exports.jsx = void 0;
|
|
||||||
const jsx_1 = require("./jsx");
|
|
||||||
Object.defineProperty(exports, "jsx", { enumerable: true, get: function () { return jsx_1.jsx; } });
|
|
||||||
Object.defineProperty(exports, "Fragment", { enumerable: true, get: function () { return jsx_1.Fragment; } });
|
|
||||||
var ElementNode_1 = require("./node/ElementNode");
|
|
||||||
Object.defineProperty(exports, "ElementNode", { enumerable: true, get: function () { return ElementNode_1.ElementNode; } });
|
|
||||||
var ComponentNode_1 = require("./node/ComponentNode");
|
|
||||||
Object.defineProperty(exports, "ComponentNode", { enumerable: true, get: function () { return ComponentNode_1.ComponentNode; } });
|
|
||||||
exports.React = {
|
|
||||||
Fragment: jsx_1.Fragment,
|
|
||||||
createElement(element, props, ...children) {
|
|
||||||
return jsx_1.jsx(element, props, ...children);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=mod.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"mod.js","sourceRoot":"","sources":["../tmp/mod.ts"],"names":[],"mappings":";;;AAAA,+BAAsC;AAI7B,oFAJA,SAAG,OAIA;AAAE,yFAJA,cAAQ,OAIA;AAFtB,kDAAiD;AAAxC,0GAAA,WAAW,OAAA;AACpB,sDAAqD;AAA5C,8GAAA,aAAa,OAAA;AAET,QAAA,KAAK,GAAG;IACnB,QAAQ,EAAR,cAAQ;IAER,aAAa,CAA0C,OAAuC,EAAE,KAAe,EAAE,GAAG,QAA6B;QAC/I,OAAO,SAAG,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,CAAC;IAC1C,CAAC;CAEF,CAAC"}
|
|
11
jsx-html/nodejs/node/ComponentNode.d.ts
vendored
11
jsx-html/nodejs/node/ComponentNode.d.ts
vendored
@ -1,11 +0,0 @@
|
|||||||
import { NodePropsType, ComponentFunctionType, NullableChildType } from "../types";
|
|
||||||
import { NODE_TYPE } from "../constants";
|
|
||||||
import { Node } from "./Node";
|
|
||||||
export declare class ComponentNode extends Node {
|
|
||||||
component: ComponentFunctionType;
|
|
||||||
props: NodePropsType;
|
|
||||||
type: NODE_TYPE;
|
|
||||||
constructor(component: ComponentFunctionType, props: NodePropsType, children: NullableChildType[]);
|
|
||||||
render(): Promise<string | any[]>;
|
|
||||||
renderComponent(): Promise<string | any[]>;
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.ComponentNode = void 0;
|
|
||||||
const constants_1 = require("../constants");
|
|
||||||
const FragmentNode_1 = require("./FragmentNode");
|
|
||||||
const Node_1 = require("./Node");
|
|
||||||
const normalizeChildren_1 = require("./utils/normalizeChildren");
|
|
||||||
class ComponentNode extends Node_1.Node {
|
|
||||||
constructor(component, props, children) {
|
|
||||||
super(children);
|
|
||||||
this.component = component;
|
|
||||||
this.props = props;
|
|
||||||
this.type = constants_1.NODE_TYPE.COMPONENT;
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
return [].concat(yield this.renderComponent()).join('');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
renderComponent() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
const child = yield this.component(this.props, this.children);
|
|
||||||
const children = normalizeChildren_1.normalizeChildren(Array.isArray(child) ? child : [child]);
|
|
||||||
if (children.length === 1) {
|
|
||||||
return children[0].render();
|
|
||||||
}
|
|
||||||
else if (children.length > 1) {
|
|
||||||
return new FragmentNode_1.FragmentNode(children).render();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.ComponentNode = ComponentNode;
|
|
||||||
//# sourceMappingURL=ComponentNode.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"ComponentNode.js","sourceRoot":"","sources":["../../tmp/node/ComponentNode.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,4CAAyC;AACzC,iDAA8C;AAC9C,iCAA8B;AAC9B,iEAA8D;AAC9D,MAAa,aAAc,SAAQ,WAAI;IAGrC,YAAmB,SAAgC,EAAS,KAAoB,EAAE,QAA6B;QAC7G,KAAK,CAAC,QAAQ,CAAC,CAAC;QADC,cAAS,GAAT,SAAS,CAAuB;QAAS,UAAK,GAAL,KAAK,CAAe;QAFhF,SAAI,GAAG,qBAAS,CAAC,SAAS,CAAC;IAI3B,CAAC;IAEK,MAAM;;YACV,OAAO,EAAE,CAAC,MAAM,CAAE,MAAM,IAAI,CAAC,eAAe,EAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;KAAA;IAEK,eAAe;;YACnB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,QAAQ,GAAG,qCAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YAE3E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;gBACzB,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aAC7B;iBAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC9B,OAAO,IAAI,2BAAY,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;aAC5C;QACH,CAAC;KAAA;CAEF;AAtBD,sCAsBC"}
|
|
12
jsx-html/nodejs/node/ElementNode.d.ts
vendored
12
jsx-html/nodejs/node/ElementNode.d.ts
vendored
@ -1,12 +0,0 @@
|
|||||||
import { NODE_TYPE } from "../constants";
|
|
||||||
import { NodePropsType, NullableChildType } from "../types";
|
|
||||||
import { Node } from "./Node";
|
|
||||||
export declare class ElementNode extends Node {
|
|
||||||
name: string;
|
|
||||||
props: NodePropsType;
|
|
||||||
type: NODE_TYPE;
|
|
||||||
constructor(name: string, props: NodePropsType, children: NullableChildType[]);
|
|
||||||
render(): Promise<string | any[]>;
|
|
||||||
private getValidProps;
|
|
||||||
private propsToHTML;
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.ElementNode = void 0;
|
|
||||||
const constants_1 = require("../constants");
|
|
||||||
const Node_1 = require("./Node");
|
|
||||||
const htmlEncode_1 = require("./utils/htmlEncode");
|
|
||||||
const ELEMENT_PROP = {
|
|
||||||
INNER_HTML: 'innerHTML'
|
|
||||||
};
|
|
||||||
class ElementNode extends Node_1.Node {
|
|
||||||
constructor(name, props, children) {
|
|
||||||
super(children);
|
|
||||||
this.name = name;
|
|
||||||
this.props = props;
|
|
||||||
this.type = constants_1.NODE_TYPE.ELEMENT;
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
const renderedProps = this.propsToHTML();
|
|
||||||
const renderedChildren = typeof this.props[ELEMENT_PROP.INNER_HTML] === 'string' ? this.props[ELEMENT_PROP.INNER_HTML] : (yield this.renderChildren()).join('');
|
|
||||||
return renderedChildren ? `<${this.name}${renderedProps}>${renderedChildren}</${this.name}>` : `<${this.name}${renderedProps} />`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
getValidProps() {
|
|
||||||
const props = this.props;
|
|
||||||
return Object.keys(this.props).filter(key => {
|
|
||||||
if (key === ELEMENT_PROP.INNER_HTML) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const val = props[key];
|
|
||||||
return typeof val === 'string' || typeof val === 'number' || val === true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
propsToHTML() {
|
|
||||||
const keys = this.getValidProps();
|
|
||||||
if (!keys.length) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
const props = this.props;
|
|
||||||
const pairs = keys.map(key => {
|
|
||||||
if (!/^[a-zA-Z0-9-:\._]+$/.test(key)) {
|
|
||||||
throw new Error(`Invalid attribute name format ${key}`);
|
|
||||||
}
|
|
||||||
const val = props[key];
|
|
||||||
return val === true || val === '' ? key : `${key}="${htmlEncode_1.doubleQuoteEncode(val.toString())}"`;
|
|
||||||
});
|
|
||||||
return ` ${pairs.join(' ')}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.ElementNode = ElementNode;
|
|
||||||
//# sourceMappingURL=ElementNode.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"ElementNode.js","sourceRoot":"","sources":["../../tmp/node/ElementNode.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4CAAyC;AAEzC,iCAA8B;AAC9B,mDAAuD;AACvD,MAAM,YAAY,GAAG;IACnB,UAAU,EAAE,WAAW;CACxB,CAAC;AACF,MAAa,WAAY,SAAQ,WAAI;IAGnC,YAAmB,IAAY,EAAS,KAAoB,EAAE,QAA6B;QACzF,KAAK,CAAC,QAAQ,CAAC,CAAC;QADC,SAAI,GAAJ,IAAI,CAAQ;QAAS,UAAK,GAAL,KAAK,CAAe;QAF5D,SAAI,GAAG,qBAAS,CAAC,OAAO,CAAC;IAIzB,CAAC;IAEK,MAAM;;YACV,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,gBAAgB,GAAG,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChK,OAAO,gBAAgB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,aAAa,IAAI,gBAAgB,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,aAAa,KAAK,CAAC;QACpI,CAAC;KAAA;IAEO,aAAa;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YAC1C,IAAI,GAAG,KAAK,YAAY,CAAC,UAAU,EAAE;gBACnC,OAAO,KAAK,CAAC;aACd;YAED,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC;QAC5E,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,WAAW;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAElC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAChB,OAAO,EAAE,CAAC;SACX;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YAC3B,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;gBACpC,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,EAAE,CAAC,CAAC;aACzD;YAED,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YAEvB,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,8BAAiB,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC;QAC5F,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAC/B,CAAC;CAEF;AA7CD,kCA6CC"}
|
|
8
jsx-html/nodejs/node/FragmentNode.d.ts
vendored
8
jsx-html/nodejs/node/FragmentNode.d.ts
vendored
@ -1,8 +0,0 @@
|
|||||||
import { NODE_TYPE } from "../constants";
|
|
||||||
import { ChildNodeType } from "../types";
|
|
||||||
import { Node } from "./Node";
|
|
||||||
export declare class FragmentNode extends Node {
|
|
||||||
type: NODE_TYPE;
|
|
||||||
constructor(children: ChildNodeType[]);
|
|
||||||
render(): Promise<string[]>;
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.FragmentNode = void 0;
|
|
||||||
const constants_1 = require("../constants");
|
|
||||||
const Node_1 = require("./Node");
|
|
||||||
class FragmentNode extends Node_1.Node {
|
|
||||||
constructor(children) {
|
|
||||||
super(children);
|
|
||||||
this.type = constants_1.NODE_TYPE.FRAGMENT;
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
return this.renderChildren();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.FragmentNode = FragmentNode;
|
|
||||||
//# sourceMappingURL=FragmentNode.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"FragmentNode.js","sourceRoot":"","sources":["../../tmp/node/FragmentNode.ts"],"names":[],"mappings":";;;AAAA,4CAAyC;AAEzC,iCAA8B;AAC9B,MAAa,YAAa,SAAQ,WAAI;IAGpC,YAAY,QAAyB;QACnC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAHlB,SAAI,GAAG,qBAAS,CAAC,QAAQ,CAAC;IAI1B,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;IAC/B,CAAC;CAEF;AAXD,oCAWC"}
|
|
9
jsx-html/nodejs/node/Node.d.ts
vendored
9
jsx-html/nodejs/node/Node.d.ts
vendored
@ -1,9 +0,0 @@
|
|||||||
import { NODE_TYPE } from "../constants";
|
|
||||||
import { NullableChildType } from "../types";
|
|
||||||
export declare abstract class Node {
|
|
||||||
children: NullableChildType[];
|
|
||||||
abstract type: NODE_TYPE;
|
|
||||||
constructor(children: NullableChildType[]);
|
|
||||||
abstract render(): Promise<string | any[]>;
|
|
||||||
renderChildren(): Promise<string[]>;
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.Node = void 0;
|
|
||||||
const normalizeChildren_1 = require("./utils/normalizeChildren");
|
|
||||||
class Node {
|
|
||||||
constructor(children) {
|
|
||||||
this.children = children;
|
|
||||||
}
|
|
||||||
renderChildren() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
const result = [];
|
|
||||||
const children = normalizeChildren_1.normalizeChildren(this.children);
|
|
||||||
for (const child of children) {
|
|
||||||
const renderedChild = yield child.render();
|
|
||||||
if (renderedChild) {
|
|
||||||
if (Array.isArray(renderedChild)) {
|
|
||||||
renderedChild.forEach(subchild => subchild && result.push(subchild));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result.push(renderedChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.Node = Node;
|
|
||||||
//# sourceMappingURL=Node.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"Node.js","sourceRoot":"","sources":["../../tmp/node/Node.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,iEAA8D;AAC9D,MAAsB,IAAI;IAGxB,YAAmB,QAA6B;QAA7B,aAAQ,GAAR,QAAQ,CAAqB;IAAG,CAAC;IAI9C,cAAc;;YAClB,MAAM,MAAM,GAAa,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,qCAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAElD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE;gBAC5B,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC;gBAE3C,IAAI,aAAa,EAAE;oBACjB,IAAI,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE;wBAChC,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;qBACtE;yBAAM;wBACL,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;qBAC5B;iBACF;aACF;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;KAAA;CAEF;AA1BD,oBA0BC"}
|
|
7
jsx-html/nodejs/node/TextNode.d.ts
vendored
7
jsx-html/nodejs/node/TextNode.d.ts
vendored
@ -1,7 +0,0 @@
|
|||||||
import { NODE_TYPE } from "../constants";
|
|
||||||
export declare class TextNode {
|
|
||||||
text: string;
|
|
||||||
type: NODE_TYPE;
|
|
||||||
constructor(text: string);
|
|
||||||
render(): Promise<string | any[]>;
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.TextNode = void 0;
|
|
||||||
const constants_1 = require("../constants");
|
|
||||||
const htmlEncode_1 = require("./utils/htmlEncode");
|
|
||||||
class TextNode {
|
|
||||||
constructor(text) {
|
|
||||||
this.text = text;
|
|
||||||
this.type = constants_1.NODE_TYPE.TEXT;
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
return htmlEncode_1.htmlEncode(this.text);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.TextNode = TextNode;
|
|
||||||
//# sourceMappingURL=TextNode.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"TextNode.js","sourceRoot":"","sources":["../../tmp/node/TextNode.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,4CAAyC;AACzC,mDAAgD;AAChD,MAAa,QAAQ;IAGnB,YAAmB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QAF/B,SAAI,GAAG,qBAAS,CAAC,IAAI,CAAC;IAEY,CAAC;IAE7B,MAAM;;YACV,OAAO,uBAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;KAAA;CAEF;AATD,4BASC"}
|
|
2
jsx-html/nodejs/node/utils/htmlEncode.d.ts
vendored
2
jsx-html/nodejs/node/utils/htmlEncode.d.ts
vendored
@ -1,2 +0,0 @@
|
|||||||
export declare function doubleQuoteEncode(text: string): string;
|
|
||||||
export declare function htmlEncode(text: string): string;
|
|
@ -1,12 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.htmlEncode = exports.doubleQuoteEncode = void 0;
|
|
||||||
function doubleQuoteEncode(text) {
|
|
||||||
return text.replace(/"/g, '"');
|
|
||||||
}
|
|
||||||
exports.doubleQuoteEncode = doubleQuoteEncode;
|
|
||||||
function htmlEncode(text) {
|
|
||||||
return doubleQuoteEncode(text.replace(/&/g, '&').replace(/\//g, '/').replace(/</g, '<').replace(/>/g, '>').replace(/'/g, '''));
|
|
||||||
}
|
|
||||||
exports.htmlEncode = htmlEncode;
|
|
||||||
//# sourceMappingURL=htmlEncode.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"htmlEncode.js","sourceRoot":"","sources":["../../../tmp/node/utils/htmlEncode.ts"],"names":[],"mappings":";;;AAAA,SAAgB,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACtC,CAAC;AAFD,8CAEC;AACD,SAAgB,UAAU,CAAC,IAAY;IACrC,OAAO,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AACpJ,CAAC;AAFD,gCAEC"}
|
|
@ -1,2 +0,0 @@
|
|||||||
import { NullableChildType, ChildNodeType } from "../../types";
|
|
||||||
export declare function normalizeChildren(children: NullableChildType[]): ChildNodeType[];
|
|
@ -1,27 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.normalizeChildren = void 0;
|
|
||||||
const TextNode_1 = require("../TextNode");
|
|
||||||
const constants_1 = require("../../constants");
|
|
||||||
function normalizeChildren(children) {
|
|
||||||
const result = [];
|
|
||||||
for (const child of children) {
|
|
||||||
if (child && typeof child !== 'boolean') {
|
|
||||||
if (typeof child === 'string' || typeof child === 'number') {
|
|
||||||
result.push(new TextNode_1.TextNode(`${child}`));
|
|
||||||
}
|
|
||||||
else if (Array.isArray(child)) {
|
|
||||||
normalizeChildren(child).forEach(result.push);
|
|
||||||
}
|
|
||||||
else if (child.type === constants_1.NODE_TYPE.ELEMENT || child.type === constants_1.NODE_TYPE.TEXT || child.type === constants_1.NODE_TYPE.COMPONENT) {
|
|
||||||
result.push(child);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new TypeError(`Unrecognized node type: ${typeof child}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
exports.normalizeChildren = normalizeChildren;
|
|
||||||
//# sourceMappingURL=normalizeChildren.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"normalizeChildren.js","sourceRoot":"","sources":["../../../tmp/node/utils/normalizeChildren.ts"],"names":[],"mappings":";;;AACA,0CAAuC;AACvC,+CAA4C;AAC5C,SAAgB,iBAAiB,CAAC,QAA6B;IAC7D,MAAM,MAAM,GAAU,EAAE,CAAC;IAEzB,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE;QAC5B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE;YACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBAC1D,MAAM,CAAC,IAAI,CAAC,IAAI,mBAAQ,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;aACvC;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBAC/B,iBAAiB,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;aAC/C;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAS,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAS,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAS,CAAC,SAAS,EAAE;gBAClH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACpB;iBAAM;gBACL,MAAM,IAAI,SAAS,CAAC,2BAA2B,OAAO,KAAK,EAAE,CAAC,CAAC;aAChE;SACF;KACF;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAlBD,8CAkBC"}
|
|
15
jsx-html/nodejs/types.d.ts
vendored
15
jsx-html/nodejs/types.d.ts
vendored
@ -1,15 +0,0 @@
|
|||||||
import { ElementNode } from "./node/ElementNode";
|
|
||||||
import { TextNode } from "./node/TextNode";
|
|
||||||
import { ComponentNode } from "./node/ComponentNode";
|
|
||||||
import { FragmentNode } from "./node/FragmentNode";
|
|
||||||
export declare type NodePropsType = {
|
|
||||||
[key: string]: any;
|
|
||||||
};
|
|
||||||
declare type Primitive = string | boolean | number;
|
|
||||||
declare type NullablePrimitive = Primitive | null | void;
|
|
||||||
export declare type ChildNodeType = ElementNode | TextNode | ComponentNode;
|
|
||||||
export declare type NodeType = ChildNodeType | FragmentNode;
|
|
||||||
export declare type ChildType = ChildNodeType | Primitive;
|
|
||||||
export declare type NullableChildType = ChildType | ChildNodeType | NullablePrimitive;
|
|
||||||
export declare type ComponentFunctionType = (props: NodePropsType, child?: NullableChildType[]) => NullableChildType | Promise<NullableChildType>;
|
|
||||||
export {};
|
|
@ -1,3 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
//# sourceMappingURL=types.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../tmp/types.ts"],"names":[],"mappings":""}
|
|
@ -1,16 +0,0 @@
|
|||||||
deno test examples/01.tsx
|
|
||||||
|
|
||||||
deno run examples/00.tsx
|
|
||||||
deno run examples/01.tsx
|
|
||||||
deno run -c examples/02/tsconfig.json examples/02/02.tsx
|
|
||||||
|
|
||||||
https://deno.land/manual/contributing/style_guide
|
|
||||||
|
|
||||||
|
|
||||||
- would be great to make it as well node compatible:
|
|
||||||
tsc examples/01.tsx --jsx react --outDir dist && node dist/examples/01.js
|
|
||||||
|
|
||||||
git tag --delete latest
|
|
||||||
git push --delete origin latest
|
|
||||||
git tag latest
|
|
||||||
git push --tags
|
|
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "async-jsx-html",
|
|
||||||
"version": "1.2.1",
|
|
||||||
"main": "nodejs/mod.js",
|
|
||||||
"types": "nodejs/mod.d.ts",
|
|
||||||
"repository": "git@github.com:apiel/jsx-html.git",
|
|
||||||
"author": "Alexandre Piel <alexandre.piel@gmail.com>",
|
|
||||||
"license": "MIT",
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rm -rf nodejs/ && rm -rf tmp/",
|
|
||||||
"build": "yarn clean && node deno2nodejs.js && tsc -p ./tmp/tsconfig.json",
|
|
||||||
"transpile": "babel --no-babelrc --plugins @babel/plugin-transform-react-jsx ./examples/node_01.jsx -o ./examples/node_01.js",
|
|
||||||
"start": "yarn transpile && node ./examples/node_01.js"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/cli": "^7.10.3",
|
|
||||||
"@babel/core": "^7.10.3",
|
|
||||||
"@babel/generator": "^7.10.3",
|
|
||||||
"@babel/parser": "^7.10.3",
|
|
||||||
"@babel/plugin-transform-react-jsx": "^7.10.3",
|
|
||||||
"@babel/traverse": "^7.10.3",
|
|
||||||
"@types/node": "^14.0.13",
|
|
||||||
"typescript": "^3.9.5"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
import type { ElementNode } from './node/ElementNode.ts';
|
|
||||||
import type { TextNode } from './node/TextNode.ts';
|
|
||||||
import type { ComponentNode } from './node/ComponentNode.ts';
|
|
||||||
import type { FragmentNode } from './node/FragmentNode.ts';
|
|
||||||
|
|
||||||
export type NodePropsType = {
|
|
||||||
[key: string]: any;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Primitive = string | boolean | number;
|
|
||||||
type NullablePrimitive = Primitive | null | void;
|
|
||||||
|
|
||||||
export type ChildNodeType = ElementNode | TextNode | ComponentNode;
|
|
||||||
|
|
||||||
export type NodeType = ChildNodeType | FragmentNode;
|
|
||||||
|
|
||||||
export type ChildType = ChildNodeType | Primitive;
|
|
||||||
export type NullableChildType = ChildType | ChildNodeType | NullablePrimitive;
|
|
||||||
|
|
||||||
export type ComponentFunctionType = (
|
|
||||||
props: NodePropsType,
|
|
||||||
child?: NullableChildType[],
|
|
||||||
) => NullableChildType | Promise<NullableChildType>;
|
|
1267
jsx-html/yarn.lock
1267
jsx-html/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
|||||||
Denreg JSX renderer
|
|
||||||
|
|
||||||
**deprecated**
|
|
||||||
|
|
||||||
**DO NOT USE**
|
|
@ -1,13 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "@denreg-jsx",
|
"name": "@denreg-jsx",
|
||||||
"version": "0.0.3",
|
"version": "0.1.4",
|
||||||
"description": "Denreg JSX renderer",
|
"description": "Denreg JSX renderer",
|
||||||
"author": "Fabian Stamm <dev@fabianstamm.de>",
|
"author": "Fabian Stamm <dev@fabianstamm.de>",
|
||||||
"contributors": [],
|
"contributors": [],
|
||||||
"deprecated": true,
|
"deprecated": false,
|
||||||
"files": [
|
"files": [
|
||||||
"**/*.ts",
|
"**/*.ts",
|
||||||
"**/*.js",
|
"**/*.js",
|
||||||
|
"tsconfig.json",
|
||||||
"README.md"
|
"README.md"
|
||||||
]
|
]
|
||||||
}
|
}
|
145
jsx/mod.ts
Normal file
145
jsx/mod.ts
Normal 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
7
jsx/tsconfig.json
Normal 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
11
jsx/types.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
declare namespace JSX {
|
||||||
|
interface IntrinsicElements {
|
||||||
|
[elemName: string]: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare namespace JSX {
|
||||||
|
interface ElementClass {
|
||||||
|
render: any;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user