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' 
    },
 ...