mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
feat: serialize JSX for console
This commit is contained in:
parent
5edd102f3f
commit
d1677a1a8f
5 changed files with 531 additions and 1 deletions
|
@ -1,6 +1,11 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
/// <reference path="../../core/internal.d.ts" />
|
/// <reference path="../../core/internal.d.ts" />
|
||||||
|
import {
|
||||||
|
preactAdapter,
|
||||||
|
reactAdapter,
|
||||||
|
serialize,
|
||||||
|
} from "ext:deno_console/02_jsx.js";
|
||||||
|
|
||||||
const core = globalThis.Deno.core;
|
const core = globalThis.Deno.core;
|
||||||
const internals = globalThis.__bootstrap.internals;
|
const internals = globalThis.__bootstrap.internals;
|
||||||
|
@ -169,6 +174,10 @@ const styles = {
|
||||||
regexp: "red",
|
regexp: "red",
|
||||||
module: "underline",
|
module: "underline",
|
||||||
internalError: "red",
|
internalError: "red",
|
||||||
|
jsxElement: "green",
|
||||||
|
jsxComponent: "magenta",
|
||||||
|
jsxAttribute: "yellow",
|
||||||
|
jsxOther: "reset",
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultFG = 39;
|
const defaultFG = 39;
|
||||||
|
@ -919,12 +928,26 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) {
|
||||||
if (noIterator) {
|
if (noIterator) {
|
||||||
keys = getKeys(value, ctx.showHidden);
|
keys = getKeys(value, ctx.showHidden);
|
||||||
braces = ["{", "}"];
|
braces = ["{", "}"];
|
||||||
|
|
||||||
|
// Preact JSX
|
||||||
|
if (
|
||||||
|
constructor === undefined && value !== null && typeof value === "object"
|
||||||
|
) {
|
||||||
|
return serialize(ctx, preactAdapter, value, ctx.indentationLvl, 10);
|
||||||
|
}
|
||||||
|
|
||||||
if (constructor === "Object") {
|
if (constructor === "Object") {
|
||||||
if (isArgumentsObject(value)) {
|
if (isArgumentsObject(value)) {
|
||||||
braces[0] = "[Arguments] {";
|
braces[0] = "[Arguments] {";
|
||||||
} else if (tag !== "") {
|
} else if (tag !== "") {
|
||||||
braces[0] = `${getPrefix(constructor, tag, "Object")}{`;
|
braces[0] = `${getPrefix(constructor, tag, "Object")}{`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// React JSX
|
||||||
|
if ("$$typeof" in value && typeof value.$$typeof === "symbol") {
|
||||||
|
return serialize(ctx, reactAdapter, value, ctx.indentationLvl, 10);
|
||||||
|
}
|
||||||
|
|
||||||
if (keys.length === 0 && protoProps === undefined) {
|
if (keys.length === 0 && protoProps === undefined) {
|
||||||
return `${braces[0]}}`;
|
return `${braces[0]}}`;
|
||||||
}
|
}
|
||||||
|
|
431
ext/console/02_jsx.js
Normal file
431
ext/console/02_jsx.js
Normal file
|
@ -0,0 +1,431 @@
|
||||||
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
/// <reference path="../../core/internal.d.ts" />
|
||||||
|
|
||||||
|
const primordials = globalThis.__bootstrap.primordials;
|
||||||
|
const {
|
||||||
|
Array,
|
||||||
|
ArrayIsArray,
|
||||||
|
ArrayPrototypePush,
|
||||||
|
ArrayPrototypePushApply,
|
||||||
|
ObjectKeys,
|
||||||
|
String,
|
||||||
|
StringPrototypeRepeat,
|
||||||
|
StringPrototypeSlice,
|
||||||
|
SymbolFor,
|
||||||
|
} = primordials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React adapter to serialize JSX to string
|
||||||
|
* @type {import("ext:deno_console/jsx").JSXSerializeAdapter}
|
||||||
|
*/
|
||||||
|
export const reactAdapter = {
|
||||||
|
getName(vnode) {
|
||||||
|
if (typeof vnode.type === "string") return vnode.type;
|
||||||
|
if (typeof vnode.type === "function") {
|
||||||
|
return vnode.type.displayName || vnode.type.name || "Anonymous";
|
||||||
|
}
|
||||||
|
if (vnode.type == SymbolFor("react.fragment")) return "Fragment";
|
||||||
|
if (vnode.type == SymbolFor("react.suspense")) return "Suspense";
|
||||||
|
if (vnode.type == SymbolFor("react.strict_mode")) return "StrictMode";
|
||||||
|
if (vnode.type == SymbolFor("react.profiler")) return "Profiler";
|
||||||
|
|
||||||
|
if (
|
||||||
|
vnode.type !== null &&
|
||||||
|
typeof vnode.type === "object" &&
|
||||||
|
typeof vnode.type.$$typeof === "symbol"
|
||||||
|
) {
|
||||||
|
const $$typeof = vnode.type.$$typeof;
|
||||||
|
if ($$typeof === SymbolFor("react.provider")) {
|
||||||
|
const suffix = vnode.type.displayName
|
||||||
|
? "." + vnode.type.displayName
|
||||||
|
: "";
|
||||||
|
return `Provider${suffix}`;
|
||||||
|
} else if ($$typeof === SymbolFor("react.context")) {
|
||||||
|
const suffix = vnode.type.displayName
|
||||||
|
? "." + vnode.type.displayName
|
||||||
|
: "";
|
||||||
|
return `Consumer${suffix}`;
|
||||||
|
} else if (
|
||||||
|
$$typeof === SymbolFor("react.memo") &&
|
||||||
|
typeof vnode.type.type === "function"
|
||||||
|
) {
|
||||||
|
const fnName = vnode.type.type.displayName || vnode.type.type.name ||
|
||||||
|
"";
|
||||||
|
return `Memo${fnName ? `(${fnName})` : ""}`;
|
||||||
|
} else if ($$typeof === SymbolFor("react.forward_ref")) {
|
||||||
|
const name = vnode.type.render.displayName ||
|
||||||
|
vnode.type.render.name ||
|
||||||
|
"Anonymous";
|
||||||
|
return `ForwardRef(${name})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown";
|
||||||
|
},
|
||||||
|
getTextIfTextNode() {
|
||||||
|
// React doesn't have proper text elements afaik
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
isFragment(vnode) {
|
||||||
|
return vnode.type === SymbolFor("react.fragment");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preact adapter to serialize JSX to string
|
||||||
|
* @type {import("ext:deno_console/jsx").JSXSerializeAdapter}
|
||||||
|
*/
|
||||||
|
export const preactAdapter = {
|
||||||
|
getName(vnode) {
|
||||||
|
if (typeof vnode.type === "string") return vnode.type;
|
||||||
|
if (typeof vnode.type === "function") {
|
||||||
|
const name = vnode.type.displayName || vnode.type.name || "Anonymous";
|
||||||
|
// TODO: Fragments can only be detected by importing them, this is
|
||||||
|
// a hacky workaround
|
||||||
|
if (name === "k") return "Fragment";
|
||||||
|
|
||||||
|
if ("contextType" in vnode.type) {
|
||||||
|
const ct = vnode.type.contextType;
|
||||||
|
const name = vnode.type === ct.Consumer ? "Consumer" : "Provider";
|
||||||
|
const suffix = ct.displayName ? `.${ct.displayName}` : "";
|
||||||
|
return name + suffix;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
},
|
||||||
|
getTextIfTextNode(vnode) {
|
||||||
|
return vnode.type === null ? String(vnode.props.data) : null;
|
||||||
|
},
|
||||||
|
isFragment(vnode) {
|
||||||
|
// TODO: Fragments can only be detected by importing them, this is
|
||||||
|
// a hacky workaround
|
||||||
|
return typeof vnode.type === "function" && vnode.type.name === "k";
|
||||||
|
},
|
||||||
|
isValidElement(value) {
|
||||||
|
return value !== null && typeof value === "object";
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function isVNode(x) {
|
||||||
|
return (
|
||||||
|
x !== null &&
|
||||||
|
typeof x === "object" &&
|
||||||
|
"type" in x &&
|
||||||
|
"props" in x &&
|
||||||
|
"key" in x
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} n
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function indent(n) {
|
||||||
|
if (n === 0) return "";
|
||||||
|
return StringPrototypeRepeat(" ", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
const OTHER = "jsxOther";
|
||||||
|
const ELEMENT = "jsxElement";
|
||||||
|
const COMPONENT = "jsxComponent";
|
||||||
|
const SPECIAL = "special";
|
||||||
|
const ATTR = "jsxAttribute";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize JSX to a pretty formatted string
|
||||||
|
* @param {{ stylize: (str: string, color: string) => string }} ctx
|
||||||
|
* @param {import("ext:deno_console/jsx").JSXSerializeAdapter} adapter
|
||||||
|
* @param {import("ext:deno_console/jsx").SharedVNode} vnode
|
||||||
|
* @param {number} level
|
||||||
|
* @param {number} limit
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function serialize(ctx, adapter, vnode, level, limit) {
|
||||||
|
const space = indent(level);
|
||||||
|
|
||||||
|
const text = adapter.getTextIfTextNode(vnode);
|
||||||
|
if (text !== null) {
|
||||||
|
return space + text;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isKeyed = vnode.key !== null && vnode.key !== undefined;
|
||||||
|
|
||||||
|
const isFragment = adapter.isFragment(vnode);
|
||||||
|
const isDomNode = !isFragment && typeof vnode.type === "string";
|
||||||
|
let namePretty;
|
||||||
|
|
||||||
|
let TAGS = ELEMENT;
|
||||||
|
// Fragments are a special case since they have special nameless
|
||||||
|
// syntax `<>`. They can only have a `key` prop in React, but Preact
|
||||||
|
// doesn't have that restriction
|
||||||
|
if (isFragment) {
|
||||||
|
TAGS = isKeyed ? COMPONENT : ELEMENT;
|
||||||
|
namePretty = isKeyed ? ctx.stylize("Fragment", COMPONENT) : "";
|
||||||
|
} else {
|
||||||
|
const name = adapter.getName(vnode);
|
||||||
|
// Preact text node
|
||||||
|
if (name === null) {
|
||||||
|
return space + vnode.props.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDomNode) {
|
||||||
|
TAGS = ELEMENT;
|
||||||
|
namePretty = ctx.stylize(name, ELEMENT);
|
||||||
|
} else {
|
||||||
|
TAGS = COMPONENT;
|
||||||
|
namePretty = ctx.stylize(name, COMPONENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let out = space + ctx.stylize("<", TAGS) + namePretty;
|
||||||
|
|
||||||
|
if (isKeyed) {
|
||||||
|
const value = ctx.stylize(`"${String(vnode.key)}"`, "string");
|
||||||
|
out += ` ${ctx.stylize("key", ATTR)}${ctx.stylize("=", OTHER)}${value}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
out += serializeProps(
|
||||||
|
ctx,
|
||||||
|
adapter,
|
||||||
|
vnode.props,
|
||||||
|
isDomNode,
|
||||||
|
level + 1 > limit,
|
||||||
|
);
|
||||||
|
|
||||||
|
/** @type {import("ext:deno_console/jsx").NormalizedChild} */
|
||||||
|
const children = [];
|
||||||
|
/** @type {import("ext:deno_console/jsx").VElement} */
|
||||||
|
const rawChildren = vnode.props.children;
|
||||||
|
normalizeChildren(children, rawChildren, 0);
|
||||||
|
|
||||||
|
if (children.length > 0) {
|
||||||
|
const singleChild = !ArrayIsArray(vnode.props.children);
|
||||||
|
|
||||||
|
out += ctx.stylize(">", TAGS);
|
||||||
|
|
||||||
|
// Single text child may be formatted in same line
|
||||||
|
if (level + 1 > limit) {
|
||||||
|
if (children.length > 0) {
|
||||||
|
out += "...";
|
||||||
|
}
|
||||||
|
} else if (children.length === 1 && typeof children[0] === "string") {
|
||||||
|
const str = children[0];
|
||||||
|
const fitsSameLine = str.length < 40;
|
||||||
|
out += fitsSameLine ? str : indent(level + 1) + str + "\n";
|
||||||
|
} else if (children.length === 1 && typeof children[0] === "function") {
|
||||||
|
const fn = children[0];
|
||||||
|
out += ctx.stylize("{", OTHER) +
|
||||||
|
ctx.stylize(`[Function: ${fn.name || "Anonymous"}]`, SPECIAL) +
|
||||||
|
ctx.stylize("}", OTHER);
|
||||||
|
} else {
|
||||||
|
out += "\n";
|
||||||
|
|
||||||
|
const unwrapped = singleChild ? children[0] : children;
|
||||||
|
|
||||||
|
if (ArrayIsArray(unwrapped)) {
|
||||||
|
for (let i = 0; i < unwrapped.length; i++) {
|
||||||
|
out += serializeChildren(ctx, adapter, unwrapped[i], level, limit);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out += serializeChildren(ctx, adapter, unwrapped, level, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
out += indent(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
out += ctx.stylize("</", TAGS) + namePretty +
|
||||||
|
ctx.stylize(">", TAGS);
|
||||||
|
} else if (isFragment && !isKeyed) {
|
||||||
|
out += ctx.stylize("></>", TAGS);
|
||||||
|
} else {
|
||||||
|
out += ctx.stylize(" />", TAGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level > 0 && level + 1 < limit) {
|
||||||
|
out += "\n";
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {{ stylize: (str: string, color: string) => string }} ctx
|
||||||
|
* @param {import("ext:deno_console/jsx").JSXSerializeAdapter} adapter
|
||||||
|
* @param {import("ext:deno_console/jsx".NormalizedChild)} child
|
||||||
|
* @param {number} level
|
||||||
|
* @param {number} limit
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function serializeChildren(
|
||||||
|
ctx,
|
||||||
|
adapter,
|
||||||
|
child,
|
||||||
|
level,
|
||||||
|
limit,
|
||||||
|
) {
|
||||||
|
let out = "";
|
||||||
|
if (typeof child === "string") {
|
||||||
|
return indent(level + 1) + child + "\n";
|
||||||
|
} else if (typeof child === "function") {
|
||||||
|
return (
|
||||||
|
indent(level + 1) +
|
||||||
|
ctx.stylize("{", OTHER) +
|
||||||
|
ctx.stylize(`[Function: ${child.name || "Anonymous"}]`, SPECIAL) +
|
||||||
|
ctx.stylize("}", OTHER) +
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
} else if (Array.isArray(child)) {
|
||||||
|
out += indent(level + 1) + "[\n";
|
||||||
|
|
||||||
|
for (let i = 0; i < child.length; i++) {
|
||||||
|
const actual = child[i];
|
||||||
|
out += serializeChildren(ctx, adapter, actual, level + 1, limit);
|
||||||
|
out = StringPrototypeSlice(out, 0, -1) + ctx.stylize(",\n", OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
out += indent(level + 1) + "]\n";
|
||||||
|
} else {
|
||||||
|
out += serialize(ctx, adapter, child, level + 1, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flatten children into an array. Nested arrays are flattened and some
|
||||||
|
* values like null + undefined or booleans are filtered out.
|
||||||
|
* @param {import("ext:deno_console/jsx").NormalizedChild[]} out
|
||||||
|
* @param {import("ext:deno_console/jsx").VElement} child
|
||||||
|
* @param {number} level
|
||||||
|
*/
|
||||||
|
function normalizeChildren(
|
||||||
|
out,
|
||||||
|
child,
|
||||||
|
level,
|
||||||
|
) {
|
||||||
|
// These are ignored as children
|
||||||
|
if (child === null || child === undefined || typeof child === "boolean") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preserve nested arrays. Frameworks typically replace that with an
|
||||||
|
// implicit Fragment, but showing that would be more confusing than
|
||||||
|
// showing the array
|
||||||
|
if (ArrayIsArray(child)) {
|
||||||
|
/** @type {import("ext:deno_console/jsx").NormalizedChild[]} */
|
||||||
|
const out2 = [];
|
||||||
|
for (let i = 0; i < child.length; i++) {
|
||||||
|
normalizeChildren(out2, child[i], level + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out2.length > 0) {
|
||||||
|
if (out2.length === 1 && typeof out2[0] === "string") {
|
||||||
|
if (out.length > 0) {
|
||||||
|
const last = out[out.length - 1];
|
||||||
|
if (typeof last === "string") {
|
||||||
|
out[out.length - 1] += out2[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayPrototypePushApply(out, out2);
|
||||||
|
} else if (level === 0) {
|
||||||
|
ArrayPrototypePushApply(out, out2);
|
||||||
|
} else {
|
||||||
|
ArrayPrototypePush(out, out2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (typeof child === "function") {
|
||||||
|
ArrayPrototypePush(out, child);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if child can be merged into previous child
|
||||||
|
if (out.length > 0 && !isVNode(child)) {
|
||||||
|
const last = out[out.length - 1];
|
||||||
|
if (typeof last === "string") {
|
||||||
|
out[out.length - 1] += String(child);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayPrototypePush(out, isVNode(child) ? child : String(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize JSX props
|
||||||
|
* @param {{ stylize: (str: string, color: string) => string }} ctx
|
||||||
|
* @param {import("ext:deno_console/jsx").JSXSerializeAdapter} adapter
|
||||||
|
* @param {Record<string, unknown>} props
|
||||||
|
* @param {boolean} isDomNode
|
||||||
|
* @param {boolean} skipVNodeSerialisation
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function serializeProps(
|
||||||
|
ctx,
|
||||||
|
adapter,
|
||||||
|
props,
|
||||||
|
isDomNode,
|
||||||
|
skipVNodeSerialisation,
|
||||||
|
) {
|
||||||
|
// TODO: Primodals
|
||||||
|
const sorted = ObjectKeys(props).sort((a, b) => a.localeCompare(b));
|
||||||
|
let out = "";
|
||||||
|
|
||||||
|
for (let i = 0; i < sorted.length; i++) {
|
||||||
|
const name = sorted[i];
|
||||||
|
const value = props[name];
|
||||||
|
|
||||||
|
// Empty values for DOM nodes
|
||||||
|
if (
|
||||||
|
name === "children" ||
|
||||||
|
name === "key" ||
|
||||||
|
name === "ref" ||
|
||||||
|
value === undefined ||
|
||||||
|
(isDomNode && value === null)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
} else if (typeof value === "string") {
|
||||||
|
out += ` ${ctx.stylize(name, ATTR)}${
|
||||||
|
ctx.stylize("=", OTHER)
|
||||||
|
}${ctx.stylize(`"${value}"`), "green"}`;
|
||||||
|
} else {
|
||||||
|
// Complex types
|
||||||
|
out += ` ${ctx.stylize(name, ATTR)}`;
|
||||||
|
|
||||||
|
// Truthy boolean values are usually displayed without value
|
||||||
|
if (value === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out += ctx.stylize("={", OTHER);
|
||||||
|
|
||||||
|
if (ArrayIsArray(value)) {
|
||||||
|
out += ctx.stylize(`Array(${value.length})`, SPECIAL);
|
||||||
|
} else if (value instanceof Map) {
|
||||||
|
out += ctx.stylize(`Map(${value.size})`, SPECIAL);
|
||||||
|
} else if (value instanceof Set) {
|
||||||
|
out += ctx.stylize(`Set(${value.size})`, SPECIAL);
|
||||||
|
} else if (typeof value === "function") {
|
||||||
|
out += ctx.stylize(
|
||||||
|
`[Function: ${value.name || "Anonymous"}]`,
|
||||||
|
SPECIAL,
|
||||||
|
);
|
||||||
|
} else if (isVNode(value)) {
|
||||||
|
if (skipVNodeSerialisation) {
|
||||||
|
out += ctx.stylize("...", OTHER);
|
||||||
|
} else {
|
||||||
|
out += serialize(ctx, adapter, value, 0, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out += ctx.stylize(String(value), SPECIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
out += ctx.stylize("}", OTHER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
75
ext/console/internal.d.ts
vendored
75
ext/console/internal.d.ts
vendored
|
@ -10,3 +10,78 @@ declare module "ext:deno_console/01_console.js" {
|
||||||
evaluate: boolean;
|
evaluate: boolean;
|
||||||
}): Record<string, unknown>;
|
}): Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module "ext:deno_console/02_jsx.js" {
|
||||||
|
import { JSXSerializeAdapter, SharedVNode } from "ext:deno_console/jsx";
|
||||||
|
|
||||||
|
export const reactAdapter: JSXSerializeAdapter;
|
||||||
|
export const preactAdapter: JSXSerializeAdapter;
|
||||||
|
|
||||||
|
export function serialize(
|
||||||
|
adapter: JSXSerializeAdapter,
|
||||||
|
vnode: SharedVNode,
|
||||||
|
level: number,
|
||||||
|
limit: number
|
||||||
|
): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "ext:deno_console/jsx" {
|
||||||
|
export interface ComponentFunction<T = unknown> {
|
||||||
|
(props: T): VElement;
|
||||||
|
displayName?: string;
|
||||||
|
contenxtType?: {
|
||||||
|
displayName?: string;
|
||||||
|
Provider?: (props: unknown) => VElement;
|
||||||
|
Consumer?: (props: unknown) => VElement;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VChild =
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| null
|
||||||
|
| undefined
|
||||||
|
// deno-lint-ignore ban-types
|
||||||
|
| Function
|
||||||
|
| SharedVNode;
|
||||||
|
export type VElement = VChild | VElement[] | Iterable<VElement>;
|
||||||
|
export type NormalizedChild =
|
||||||
|
| string
|
||||||
|
// deno-lint-ignore ban-types
|
||||||
|
| Function
|
||||||
|
| SharedVNode
|
||||||
|
| NormalizedChild[];
|
||||||
|
|
||||||
|
export interface PreactComponentInstance {
|
||||||
|
sub?: unknown;
|
||||||
|
displayName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SharedVNode {
|
||||||
|
$$typeof?: symbol;
|
||||||
|
// In Preact "null" means text and "props.data" is the text.
|
||||||
|
// In React symbols are for special nodes like Fragments
|
||||||
|
type:
|
||||||
|
| string
|
||||||
|
| ComponentFunction
|
||||||
|
| null
|
||||||
|
| number
|
||||||
|
| symbol
|
||||||
|
// React
|
||||||
|
| {
|
||||||
|
$$typeof: symbol;
|
||||||
|
displayName?: string;
|
||||||
|
type: ComponentFunction;
|
||||||
|
render?: ComponentFunction;
|
||||||
|
};
|
||||||
|
props: Record<string, unknown>;
|
||||||
|
key: null | undefined | number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JSXSerializeAdapter {
|
||||||
|
getTextIfTextNode(x: SharedVNode): string | null;
|
||||||
|
isFragment(x: SharedVNode): boolean;
|
||||||
|
getName(x: SharedVNode): string;
|
||||||
|
isValidElement(x: unknown): x is SharedVNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
deno_core::extension!(deno_console, esm = ["01_console.js"],);
|
deno_core::extension!(deno_console, esm = ["01_console.js", "02_jsx.js"],);
|
||||||
|
|
||||||
pub fn get_declaration() -> PathBuf {
|
pub fn get_declaration() -> PathBuf {
|
||||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_console.d.ts")
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_console.d.ts")
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"ext:deno_broadcast_channel/01_broadcast_channel.js": "../ext/broadcast_channel/01_broadcast_channel.js",
|
"ext:deno_broadcast_channel/01_broadcast_channel.js": "../ext/broadcast_channel/01_broadcast_channel.js",
|
||||||
"ext:deno_cache/01_cache.js": "../ext/cache/01_cache.js",
|
"ext:deno_cache/01_cache.js": "../ext/cache/01_cache.js",
|
||||||
"ext:deno_console/01_console.js": "../ext/console/01_console.js",
|
"ext:deno_console/01_console.js": "../ext/console/01_console.js",
|
||||||
|
"ext:deno_console/02_jsx.js": "../ext/console/02_jsx.js",
|
||||||
"ext:deno_crypto/00_crypto.js": "../ext/crypto/00_crypto.js",
|
"ext:deno_crypto/00_crypto.js": "../ext/crypto/00_crypto.js",
|
||||||
"ext:deno_fetch/20_headers.js": "../ext/fetch/20_headers.js",
|
"ext:deno_fetch/20_headers.js": "../ext/fetch/20_headers.js",
|
||||||
"ext:deno_fetch/21_formdata.js": "../ext/fetch/21_formdata.js",
|
"ext:deno_fetch/21_formdata.js": "../ext/fetch/21_formdata.js",
|
||||||
|
|
Loading…
Reference in a new issue