JSFiddle - React, Tailwind, and code Playground
HTML
<div ng-app="factbook" ng-controller="loadfact">
<select ng-model="country" ng-change="update()"
ng-options="item.id as item.name for item in countries">
</select>
<div ng-repeat="(heading, section) in data"
ng-init="depth = 1"
ng-include="'recurse.template'"></div>
<!-- A template for nested sections with heading and body parts -->
<script type="text/ng-template" id="recurse.template">
<div ng-if="section.text"
class="level{{depth}} section fact ng-class:safe(heading);">
<div class="level{{depth}} heading factname">{{heading}}</div>
<div class="level{{depth}} body factvalue">{{trunc(section.text)}}</div>
</div>
<div ng-if="!section.text"
class="level{{depth}} section ng-class:safe(heading);">
<div class="level{{depth}} heading">{{heading}}</div>
<div ng-repeat="(heading, body) in section"
ng-init="depth = depth+1; section = body;"
ng-include="'recurse.template'"
class="level{{depth-1}} body"></div>
</div>
</script>
</div>
CSS
/* This app needs some good CSS. */
/* Sections are nested, each with a level number. */
.level1.section { }
.level2.section { }
.level3.section { }
/* Each section starts with a .heading */
.level1.heading { }
.level2.heading { }
.level3.heading { }
/* Each section has .body that can nest sections */
.level1.body { }
.level2.body { }
.level3.body { }
/* Leaf sections also have the class .fact */
.fact { }
.factname { } /* A leaf-level heading */
.factvalue { } /* A leaf-level body */
/* CSS operators can combine and filter: */
.level3.factname::after { content: ':' }
.level2.heading:not(.factname) { }
/* Each specific section has its own class. */
.introduction { }
.geography { }
.people_and_society { }
.government { }
.economy { }
.energy { }
.communications { }
.transportation { }
.military_and_security { }
.transational_issues { }
/* Nth-level sections also have classes. Examples: */
.background .body { }
.geographic_coordinates .heading { }
.area .factname { }
.area .factvalue { }
JavaScript
/* An angular app to display CIA World Factbook data */
var app = angular.module('factbook', []);
app.controller('loadfact', function($scope, $http) {
$scope.country = 'europe/uk';
$scope.safe = function safe(name) { // Makes a safe CSS class name
return name.replace(/[_\W]+/g, '_').toLowerCase();
};
$scope.trunc = function trunc(text) { // Truncates text to 500 chars
return (text.length < 500) ? text : text.substr(0, 500) + "...";
};
$scope.update = function() { // Handles country selection
// $scope.data = {}; // forces rerendering - an angular bug
$http.get('https://rawgit.com/opendatajson/factbook.json/master/' +
$scope.country + '.json').then(function(response) {
$scope.data = response.data;
});
};
// Some countries - for more see https://github.com/opendatajson/factbook.json
$scope.countries = [
{id: 'europe/uk', name: 'UK'},
{id: 'africa/eg', name: 'Egypt'},
{id: 'south-asia/in', name: 'India'},
{id: 'europe/sp', name: 'Spain'},
{id: 'central-asia/rs', name: 'Russia'},
{id: 'south-america/br', name: 'Brazil'},
{id: 'east-n-southeast-asia/ch', name: 'China'}
];
$scope.update();
});