Skip to content

Instantly share code, notes, and snippets.

@maxjustus
Created November 5, 2020 23:37
Show Gist options
  • Save maxjustus/6dc3657370d615bcc70190c43161ec65 to your computer and use it in GitHub Desktop.
Save maxjustus/6dc3657370d615bcc70190c43161ec65 to your computer and use it in GitHub Desktop.
A stencil functional component for rendering the children element's markup in a <code> element along side the rendered jsx
import { h, ChildNode, FunctionalComponent, FunctionalUtilities } from "@stencil/core";
function vnodeToSource(elem: ChildNode, utils: FunctionalUtilities, output = "", level = 0): string {
if (elem.vchildren) {
let childOutput: string[] = [];
utils.forEach(elem.vchildren, (child) => {
childOutput.push(vnodeToSource(child, utils, output, level + 1));
});
output += childOutput.join("\n");
}
let indent = "";
for (let i = 0; i < level; i++) {
indent += " ";
}
if (elem.vtag) {
let attrs: string[] = [];
if (elem.vattrs) {
const vattrs = elem.vattrs;
attrs = Object.keys(vattrs)
.reduce(
(previousValue, key): string[] => {
const attrVal = vattrs[key];
let attrString: string;
switch (typeof attrVal) {
case ("boolean"):
attrString = key;
break;
case ("number"):
case ("string"):
attrString = `${ key }="${ attrVal }"`;
break;
default:
attrString = `${ key }={ ${ attrVal.toString() } }`;
}
return [...previousValue, attrString];
}, attrs);
}
const attrsString = attrs.length > 0 ? ` ${ attrs.join(" ") }` : "";
if (elem.vchildren) {
output = `${ indent }<${ elem.vtag }${ attrsString }>\n${ output }\n${ indent }</${ elem.vtag }>`;
} else {
output = `${ indent }<${ elem.vtag }${ attrsString } />`
}
} else if (elem.vtext) {
output = `${ indent }${ elem.vtext }`;
}
return output;
}
const AsSource: FunctionalComponent = (_, children, utils) => {
var codeOut = "";
utils.forEach(children, (child) => {
codeOut += vnodeToSource(child, utils);
});
return <div>
{ children }
<code class="html">{ codeOut }</code>
</div>
};
export default AsSource;
@bitflower
Copy link

bitflower commented Dec 5, 2020

Hey, awesome component ;-) Is it supposed to break lines? I'm getting this:

image

with this code:

image

@maxjustus
Copy link
Author

Hmm, yes it should! It's recursing through the vdom hierarchy and inserting line breaks / indentation as needed https://gist.github.com/maxjustus/6dc3657370d615bcc70190c43161ec65#file-as-source-tsx-L11

If you view the source for that rendered output do you see linebreaks/indentation by chance?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment