feat: fix Debug component (#1633)
This commit is contained in:
parent
b5226e68dd
commit
4647c998ea
2 changed files with 27 additions and 279 deletions
|
@ -1,144 +1,6 @@
|
||||||
---
|
---
|
||||||
const key = Object.keys(Astro.props)[0];
|
const key = Object.keys(Astro.props)[0];
|
||||||
const value = Astro.props[key];
|
const value = Astro.props[key];
|
||||||
|
|
||||||
const getType = (node: unknown) => {
|
|
||||||
if (Array.isArray(node)) return 'array';
|
|
||||||
if (node === null) return 'null';
|
|
||||||
if (typeof node === 'object') {
|
|
||||||
if ((node as any).then) return 'promise';
|
|
||||||
}
|
|
||||||
return typeof node;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSummary = (node: any, key: string, className: string) => {
|
|
||||||
const type = getType(node);
|
|
||||||
let value;
|
|
||||||
let open;
|
|
||||||
let close;
|
|
||||||
|
|
||||||
if (type === 'function') {
|
|
||||||
return <>
|
|
||||||
{(key || !key && key === 0) && <><span class={`${className} key`}>{key}</span><span class={`${className} sep`}>:</span></>}
|
|
||||||
<span class={`${className} value value-function`}>{node.name}<span class={`${className} punc`}>()</span></span>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'promise') {
|
|
||||||
return <>
|
|
||||||
{(key || !key && key === 0) && <><span class={`${className} key`}>{key}</span><span class={`${className} sep`}>:</span></>}
|
|
||||||
<span class={`${className} value value-promise`}>Promise</span>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'array') {
|
|
||||||
value = node.length;
|
|
||||||
open = <><span class={`${className} none`}>Array</span>{'['}</>;
|
|
||||||
close = ']';
|
|
||||||
} else if (type === 'object') {
|
|
||||||
const keys = Object.keys(node);
|
|
||||||
if (keys.length === 0) {
|
|
||||||
value = 'Empty';
|
|
||||||
} else if (keys.length > 3) {
|
|
||||||
value = '…';
|
|
||||||
} else {
|
|
||||||
value = keys.slice(0, 3).join(',');
|
|
||||||
}
|
|
||||||
open = '{';
|
|
||||||
close = '}';
|
|
||||||
};
|
|
||||||
|
|
||||||
return <>
|
|
||||||
{key && <><span class={`${className} key`}>{key}</span>: </>}
|
|
||||||
{open && <span class={`${className} punc`}>{open}</span>}
|
|
||||||
<span class={`${className} hide`}>
|
|
||||||
<span class={`${className} len`}>{value}</span>
|
|
||||||
{close && <span class={`${className} punc`}>{close}</span>}
|
|
||||||
</span>
|
|
||||||
</>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Details = ({ node, key, children, class: className }) => {
|
|
||||||
const type = getType(node);
|
|
||||||
const props = {};
|
|
||||||
|
|
||||||
if (type === 'array' || type === 'object') {
|
|
||||||
props['data-char'] = type === 'array' ? ']' : '}'
|
|
||||||
props.open = !key && type === 'object' ? '' : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<details {...props} class={className}>
|
|
||||||
<Summary node={node} key={key} class={className} />
|
|
||||||
{children}
|
|
||||||
</details>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Summary = ({ node, key, class: className }) => {
|
|
||||||
return (
|
|
||||||
<summary class={className}>{getSummary(node, key, className)}</summary>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Empty = Symbol('Empty');
|
|
||||||
|
|
||||||
const KeyValue = ({ key, value, dim, class: className }) => {
|
|
||||||
let type = key === '__proto__' ? 'prototype' : getType(value);
|
|
||||||
if (type === 'null') {
|
|
||||||
value = 'null';
|
|
||||||
} else if (type === 'undefined') {
|
|
||||||
value = 'undefined';
|
|
||||||
} else if (value === Empty) {
|
|
||||||
type = 'empty';
|
|
||||||
value = 'Empty';
|
|
||||||
} else {
|
|
||||||
value = JSON.stringify(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class={`${className} line`}>
|
|
||||||
{(key || !key && key === 0) && <><span class={`${className} key ${dim ? 'key-dim' : ''}`.trim()}>{key}</span><span class={`${className} sep`}>:</span></>}
|
|
||||||
<span class={`${className} value value-${type}`}>
|
|
||||||
{value}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const Node = ({ node, key, class: className, ...props }) => {
|
|
||||||
const type = getType(node);
|
|
||||||
className = className.replace(/debug-value/g, '');
|
|
||||||
|
|
||||||
if (type === 'array' || type === 'object') {
|
|
||||||
let children = [];
|
|
||||||
if (type === 'array' && node.length > 0 && Object.entries(node).length === 0) {
|
|
||||||
children = Array.from({ length: node.length }, (_, key) => <Node node={Empty} key={key} class={className} />);
|
|
||||||
} else {
|
|
||||||
children = Object.entries(node).map(([key, value]) => <Node node={value} key={key} class={className} />);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Details node={node} key={key} children={children} class={className} />
|
|
||||||
);
|
|
||||||
} else if (type === 'function') {
|
|
||||||
return (
|
|
||||||
<Details node={node} key={key} class={className} children={
|
|
||||||
<>
|
|
||||||
<KeyValue key="name" value={node.name} dim={true} class={className} />
|
|
||||||
<KeyValue key="__proto__" value="Function" dim={true} class={className} />
|
|
||||||
</>
|
|
||||||
}/>
|
|
||||||
);
|
|
||||||
} else if (type === 'promise') {
|
|
||||||
return (
|
|
||||||
<Details node={node} key={key} class={className} children={
|
|
||||||
<KeyValue key="__proto__" value="Promise" dim={true} />
|
|
||||||
} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <KeyValue key={key} value={node} class={className} />;
|
|
||||||
}
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="debug">
|
<div class="debug">
|
||||||
|
@ -146,21 +8,32 @@ const Node = ({ node, key, class: className, ...props }) => {
|
||||||
<h2 class="debug-title"><span class="debug-label">Debug</span> <span class="debug-name">"{key}"</span></h2>
|
<h2 class="debug-title"><span class="debug-label">Debug</span> <span class="debug-name">"{key}"</span></h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main>
|
<pre>{JSON.stringify(value, null, 2)}</pre>
|
||||||
<Node node={value} class="debug-value" />
|
|
||||||
</main>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style>
|
||||||
.debug-header {
|
.debug {
|
||||||
background: #FF1639;
|
font-size: 14px;
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
background: white;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.debug-header, pre {
|
||||||
margin: -1rem -1.5rem 1rem;
|
margin: -1rem -1.5rem 1rem;
|
||||||
padding: 0.25rem 0.75rem;
|
padding: 0.25rem 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.debug-header {
|
||||||
|
background: #FF1639;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.debug-title {
|
.debug-title {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
color: #fff;
|
color: white;
|
||||||
margin: 0.5em 0;
|
margin: 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,137 +43,12 @@ const Node = ({ node, key, class: className, ...props }) => {
|
||||||
margin-right: 0.75em;
|
margin-right: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug {
|
pre {
|
||||||
all: initial;
|
border: 1px solid #eee;
|
||||||
display: flex;
|
padding: 1rem 0.75rem;
|
||||||
flex-direction: column;
|
border-radius: 4px;
|
||||||
padding: 1rem 1.5rem;
|
border-top-left-radius: 0;
|
||||||
overflow-y: hidden;
|
border-top-right-radius: 0;
|
||||||
overflow-x: auto;
|
font-size: 14px;
|
||||||
border: 1px solid #FFCFD6;
|
|
||||||
|
|
||||||
background: #FFF;
|
|
||||||
font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
line-height: 1.44;
|
|
||||||
color: #6b7280;
|
|
||||||
white-space: pre;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
details[open] > summary span.hide {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
details[open] > summary span.none {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
details > details {
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line {
|
|
||||||
padding-left: 1.125em;
|
|
||||||
}
|
|
||||||
|
|
||||||
details[open]::after {
|
|
||||||
content: attr(data-char);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sep {
|
|
||||||
margin-right: 0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
details > summary {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
details:hover > summary::before,
|
|
||||||
details:focus > summary::before {
|
|
||||||
transform: translate(0.25em, -0.25em);
|
|
||||||
}
|
|
||||||
|
|
||||||
details > summary::before {
|
|
||||||
content: '';
|
|
||||||
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M13 8L2.60769 14L2.6077 2L13 8Z' fill='%236B7280' /%3E%3C/svg%3E%0A");
|
|
||||||
background-size: 1em;
|
|
||||||
|
|
||||||
display: inline-flex;
|
|
||||||
font-size: 0.5em;
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
margin-right: 1.25em;
|
|
||||||
margin-left: -2em;
|
|
||||||
transform: translate(0, -0.25em);
|
|
||||||
line-height: 1em;
|
|
||||||
transition: transform 120ms ease-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
details[open] > summary::before {
|
|
||||||
transform: translate(0.25em, -0.25em) rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.debug :global(::marker) {
|
|
||||||
content: '';
|
|
||||||
width: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key {
|
|
||||||
color: #882de7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-dim {
|
|
||||||
color: #B881F1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.len {
|
|
||||||
color: #B881F1;
|
|
||||||
}
|
|
||||||
|
|
||||||
details:hover > summary,
|
|
||||||
details:focus > summary,
|
|
||||||
details:hover > summary .punc,
|
|
||||||
details:focus > summary .punc,
|
|
||||||
details:hover[open]::after,
|
|
||||||
details:focus[open]::after {
|
|
||||||
color: #000012;
|
|
||||||
}
|
|
||||||
|
|
||||||
details:hover > summary .len,
|
|
||||||
details:focus > summary .len {
|
|
||||||
color: #882DE7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.punc {
|
|
||||||
color: #6b7280;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value-string {
|
|
||||||
color: #17c083;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value-function::before {
|
|
||||||
content: 'ƒ ';
|
|
||||||
color: #3894ff;
|
|
||||||
}
|
|
||||||
.value-function {
|
|
||||||
color: #5076f9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value-number {
|
|
||||||
color: #ff5d01;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value-null,
|
|
||||||
.value-undefined {
|
|
||||||
color: #9ca3af;
|
|
||||||
}
|
|
||||||
|
|
||||||
main > .line {
|
|
||||||
margin-left: -0.75em;
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//export { default as Code } from './Code.astro';
|
//export { default as Code } from './Code.astro';
|
||||||
//export { default as Debug } from './Debug.astro';
|
export { default as Debug } from './Debug.astro';
|
||||||
export { default as Markdown } from './Markdown.astro';
|
export { default as Markdown } from './Markdown.astro';
|
||||||
export { default as Prism } from './Prism.astro';
|
export { default as Prism } from './Prism.astro';
|
||||||
|
|
Loading…
Add table
Reference in a new issue