JSFiddle - React, Tailwind, and code Playground
by tidy
HTML
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/[email protected]/lodash.min.js"></script>
<!-- item template -->
<script type="text/x-template" id="page-template">
<div>
<div v-if="!isOpen" @click="setOpen(true)" class="click">
<span> + </span>
{...},
</div>
<div v-if="isOpen">
<span @click="setOpen(false)" class="click"> - </span>
{
<ul>
<li v-for="(prop, key) in model">
<span class="key" v-text="key"></span>
<span v-if="!isObject(prop) && !isArray(prop) && prop" class="value" v-text="prop"></span>
<span v-if="isObject(prop)">{</span>
<span v-if="comment(key)"
class="comment"
v-text="'// ' + comment(key)"
></span>
<div v-if="isObject(prop)" class="object">
<ul>
<li v-for="(subValue, subKey) in prop">
<span class="key sub" v-text="subKey"></span>
<span v-if="!isObject(subValue) && !isArray(subValue) && subValue" class="value sub" v-text="subValue"></span>
<span v-if="comment(subKey)" class="comment" v-text="'// ' + comment(subKey)"></span>
</li>
</ul>
</div>
<span v-if="isObject(prop)">},</span>
<div v-if="isArray(prop)" class="array">
<span class="bracket">[</span>
<page class="item" v-for="child in prop" :model="child" :open="false"></page>
<span class="bracket">]</span>
</div>
</li>
</ul>
}
</div>
</div>
</script>
<p>RenderObject</p>
<ul id="demo">
<page class="item" :model="renderObject" :open="true"></page>
</ul>
CSS
body {
font-family: Menlo, Consolas, monospace;
color: #444;
}
.item {}
.comment {
color: #c4c4c4;
}
.key {
font-weight: bold;
}
.key:after {
content: ": ";
}
.key.sub {
font-weight: normal;
}
.value {
color: #28BB40;
}
.value:before {
content: "'";
}
.value:after {
content: "'";
}
.click {
cursor: pointer;
}
.bold {
font-weight: bold;
}
ul {
padding-left: 1em;
line-height: 1.5em;
list-style-type: none;
}
Babel + JSX
'use strict'
let comments = {
'id': 'page-unique-id (string, uuid-v4)',
'current': 'is this current page (boolean)',
'parent': 'parent page (object)',
'page': 'Page specific content (json, editable)',
'site': 'Sitewide content (json, editable)',
'meta': 'Page specific metadata (json, editable)',
'info': 'Page information (json, not editable)',
'children': 'Child pages of this page',
'tree': 'Whole site structure with all pages',
'name': 'Page name in navigation',
'pathname': 'Page url path',
'visible': 'Is the page visible in navigation',
'sequence': 'Current position compared to siblings',
'slug': 'Page name in url'
}
let frontpage = {
id: 'page-unique-id',
current: 'true',
parent: 'null',
page: {
heading: 'Welcome to my homepage',
content: '<p>Front html content</p>',
},
site: {
company: 'Company Ltd',
address: 'Tidy road 1, New York',
},
meta: {
title: 'My amazing frontpage',
og: {
image: './_assets/media/fb-share-image.jpg'
},
},
info: {
name: 'Frontpage',
pathname: '/',
visible: 'true',
sequence: 1,
slug: 'null',
},
children: [],
}
let article1 = {
id: 'page-unique-id',
current: 'false',
parent: 'null',
page: {
heading: 'News article 1',
content: '<p>Lorem ipsum....</p>',
},
site: {
company: 'Company Ltd',
address: 'Tidy road 1, New York',
},
meta: {
title: 'News article 1',
og: {
image: './_assets/media/fb-share-image.jpg'
},
},
info: {
name: 'News article 1',
pathname: '/news/article1',
visible: 'true',
sequence: 1,
slug: 'article1',
},
children: [],
}
let article2 = {
id: 'page-unique-id',
current: 'false',
parent: 'null',
page: {
heading: 'News article 2',
content: '<p>Lorem ipsum....</p>',
},
site: {
company: 'Company Ltd',
address: 'Tidy road 1, New York',
},
meta: {
title: 'News article 2',
og: {
image: './_assets/media/fb-share-image.jpg'
},
...