Skip to content

Instantly share code, notes, and snippets.

@sjorsrijsdam
Last active November 28, 2023 19:14
Show Gist options
  • Save sjorsrijsdam/6bbfe5f3a32cb4f4dce52d0c0cc058d8 to your computer and use it in GitHub Desktop.
Save sjorsrijsdam/6bbfe5f3a32cb4f4dce52d0c0cc058d8 to your computer and use it in GitHub Desktop.
Custom Enhance element to be able to debug view state
// Custom Enhance element to debug/inspect the `state` property
// that is passed to Enhance views.
//
// Optional `key` attribute can be used to inspect from
// a desired depth.
//
// Default styling is Monokai Midnight, but can be overridden
// by changing the various custom properties.
//
// Usage:
// `<d-bug></d-bug>`
// or:
// `<d-bug key="some.depth.withIndex[4]"></d-bug>
export default function dBug ({ html, state }) {
const TYPES = Object.freeze({
'string': 'string',
'number': 'number',
'undefined': 'undefined',
'null': 'null',
'array': 'array',
'object': 'object',
'boolean': 'boolean',
});
function getType (value) {
if (value === null) {
return TYPES.null;
}
if (value === undefined) {
return TYPES.undefined;
}
if (typeof value === 'string') {
return TYPES.string;
}
if (typeof value === 'number') {
return TYPES.number;
}
if (typeof value === 'boolean') {
return TYPES.boolean;
}
if (Array.isArray(value)) {
return TYPES.array;
}
return TYPES.object;
}
function renderPrimitive (value) {
return `<span class="type-${getType(value)}">${value}</span>`;
}
function renderNonPrimitive (key, value) {
const label = key ? `${renderPrimitive(key)}: ` : '';
return [
`<details class="type-${getType(value)}">`,
`<summary><span>${label && label}</span></summary>`,
render(value),
'</details>',
].join('');
}
function render (value) {
const entries = [];
if (getType(value) === TYPES.object) {
Object.keys(value).forEach(key => {
const item = value[key];
const itemType = getType(item);
if (itemType === TYPES.array || itemType === TYPES.object) {
entries.push(
`<div>${renderNonPrimitive(key, item)}</div>`
);
} else {
entries.push(`<div>${renderPrimitive(key)}: ${renderPrimitive(item)}</div>`);
}
});
} else if (getType(value) === TYPES.array) {
value.forEach(item => {
const itemType = getType(item);
if (itemType === TYPES.array || itemType === TYPES.object) {
entries.push(`<div>${renderNonPrimitive('', item)}</div>`);
} else {
entries.push(`<div>${renderPrimitive(item)}</div>`);
}
});
} else {
entries.push(renderPrimitive(value));
}
return entries.join('');
}
let debug = state;
if (state.attrs.key) {
state.attrs.key.split('.').forEach(key => {
const keyParts = key.split('[');
keyParts.forEach(keyPart => {
debug = debug[keyPart.replace(']', '')];
});
});
}
return html`
<style scope="module">
:host {
--string-color: #E6DB74;
--number-color: #AE81FF;
--boolean-color: #AE81FF;
--null-color: #AE81FF;
--undefined-color: #AE81FF;
--text-color: #FFF;
--background-color: #000;
display: block;
width: fit-content;
background-color: var(--background-color);
color: var(--text-color);
padding: 1ch;
}
span.type-string {
color: var(--string-color);
}
span.type-string::before,
span.type-string::after {
content: '"';
}
span.type-number {
color: var(--number-color);
}
span.type-undefined {
color: var(--undefined-color);
}
span.type-null {
color: var(--null-color);
}
span.type-boolean {
color: var(--boolean-color);
}
details > div {
padding-left: 4ch;
}
details summary {
display: flex;
cursor: pointer;
}
details summary::before {
content: ' ▶';
order: 2;
}
details[open] > summary::before {
content: ' ▼';
order: 2;
}
details.type-array > summary > span::after {
content: '[...]';
}
details.type-array[open] > summary > span::after {
content: '[';
}
details.type-array[open]::after {
content: ']';
display: block;
}
details.type-object > summary > span::after {
content: '{...}';
}
details.type-object[open] > summary > span::after {
content: '{';
}
details.type-object[open]::after {
content: '}';
display: block;
}
</style>
<pre><code>${render(debug)}</code></pre>
`;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment