JsFiddle-API

by denvdmj

HTML

<output></output>
<ul JsFiddle-API></ul>
<template JsFiddle-API>
  <li>
    <a href="{{url}}">{{title}}</a> 
    <span>(<a href="{{url}}{{version}}">v-{{version}}</a>)</span>
    <span><a href="{{url}}embedded/result,html,css,js/">Demo</a></span>
    <div>
      <span>({{framework}})</span>
      <span>rev-{{version}}</span>
      <span>{{created}}</span>
    </div>      
    <p>{{description}}</p>
  </li>
</template>

SCSS

@import url(https://be5invis.github.io/Iosevka/fonts.css);
:root {
  font: 400 14px/1.5 'Condensed-Coding', 'IosevkaWEB', monospace;
  margin: 1rem 4rem;
}
:root > body {
  max-width: 40rem;
  min-width: 14rem;
  margin: auto;
  padding: 1rem 1rem;
  background: #12161D;
  color: #fff;
}
a {
  color: #92b1d8;
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}
ul[JsFiddle-API] {
  margin: 1rem 0;
  padding: 1rem 0;
  > li {
    margin: 1rem 0;
    padding: 1rem 0;
    border: solid 1px #313842;
    border-width: 0 0 1px 0;
  }
  > li:first-child {  
    border-width: 1px 0 1px 0;
  }    
  > li span {
    color: #5E6C7E;
  }
  > li p {
    font-size: .9rem;
    color: #A0ACBE;
  }    
}

@font-face {
  font-family: 'Condensed-Coding';
  font-style: normal;
  font-weight: 400;
  src: 
    url(https://cdn.rawgit.com/frantisek-sodomka-gomorrka/fonts/3063e30b/condensed-coding.r-webfont.woff2?raw=true) format('woff2'),
    url(https://cdn.rawgit.com/frantisek-sodomka-gomorrka/fonts/3063e30b/condensed-coding.r-webfont.woff?raw=true) format('woff'),
    url(https://cdn.rawgit.com/frantisek-sodomka-gomorrka/fonts/3063e30b/condensed-coding.r-webfont.ttf?raw=true) format('truetype');
}

@media only screen and (min-width: 15rem) { :root { margin: 1rem 1rem } }
@media only screen and (min-width: 20rem) { :root { margin: 1rem 2rem } }
@media only screen and (min-width: 25rem) { :root { margin: 1rem 2rem } }
@media only screen and (min-width: 30rem) { :root { margin: 1rem 4rem } }

JavaScript

//
// https://learn.javascript.ru/ajax-getJSONP
// https://learn.javascript.ru/onload-onerror
//

function getJSONP (url, onSuccess, onError) {
  var body = document.body,
    cbOk = false,
    cbName = '_cb_' + (getJSONP.counter++).toString(36),
    amp = ~url.indexOf('?') ? '&' : '?',
    src = url.replace(/(\w+=)?$/, function (_, param) {
      return (param || (amp + 'jsonp=')) + 'getJSONP.' + cbName;
    }),
    script = document.createElement('script');

  var checker = function () {
    if (cbOk) return;
    checker = null;
    cleaner();
    try {
      onError && onError(url);
    } catch (e) {}
  };

  getJSONP[cbName] = function (data) {
    cbOk = true;
    cleaner();
    try {
      onSuccess && onSuccess(data, url);
    } catch (e) {}
  };

  function cleaner () {
    delete getJSONP[cbName];
    body.removeChild(script);
  }

  // For outdated MSIE versions
  script.onreadystatechange = function() {
    if (/^(complete|loaded)$/.test(this.readyState)) {
      this.onreadystatechange = null;
      setTimeout(checker, 0);
    }
  };

  script.onload = script.onerror = checker;
  script.async = true;
  script.src = src;

  body.appendChild(script);

}

getJSONP.counter = 0;

function domTextProcess (root, processor) {
  function traverse (node) {
    if (!node) return;
    var nodeType = node.nodeType, attrs, attr, i, el;
    if (nodeType === 3) {
      node.nodeValue = processor(node.nodeValue);
    }
    if (nodeType === 1) {
      for (attrs = node.attributes, i = attrs.length; i--;) {
        attr = attrs[i];
        attr.value = processor(attr.value);
      }
    }
    for (el = node.firstChild; el !== null; el = el.nextSibling) {
      traverse(el);
    }
  }
  traverse(root);
}

function fillTemplate (templateNode, data) {
  var clone = document.importNode(templateNode.content, true);
  domTextProcess(clone, text => text.replace(/\{\{(\w+)\}\}/g, (_, name) => data[name]));
  return clone;
}

// About JsFiddle API:...