feat: added code highlighting

This commit is contained in:
Joshua Seigler 2016-10-25 23:07:44 -04:00
parent 8a850aab22
commit faafc32d03
5 changed files with 79 additions and 26 deletions

View file

@ -3,6 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Tech Talk: Responsive Typography</title> <title>Tech Talk: Responsive Typography</title>
<link rel="stylesheet" href="libs/highlight.js/monokai-sublime.css">
<link rel="stylesheet" href="styles/main.css" charset="utf-8"> <link rel="stylesheet" href="styles/main.css" charset="utf-8">
<script type="text/javascript" src="libs/prefixfree/prefixfree.min.js"></script> <script type="text/javascript" src="libs/prefixfree/prefixfree.min.js"></script>
</head> </head>
@ -44,7 +45,7 @@
</blockquote> </blockquote>
</section> </section>
<section id="demo1" style="--mouse-x: 0.5"> <section id="demo1">
<div class="live-coding col" style="justify-content: center;"> <div class="live-coding col" style="justify-content: center;">
<div class="browser" style="max-width: calc(100vw * var(--mouse-x)); min-width: 2em; margin-bottom: 0.2em;"> <div class="browser" style="max-width: calc(100vw * var(--mouse-x)); min-width: 2em; margin-bottom: 0.2em;">
<iframe src="about:blank" frameborder="0"></iframe> <iframe src="about:blank" frameborder="0"></iframe>
@ -53,7 +54,8 @@
<input type="radio" id="demo1-markup" name="demo1" janus-sync> <input type="radio" id="demo1-markup" name="demo1" janus-sync>
<div class="live-coding__component" style="--theme-color: #E34F26;"> <div class="live-coding__component" style="--theme-color: #E34F26;">
<label for="demo1-markup">HTML</label> <label for="demo1-markup">HTML</label>
<textarea name="html" cols="1" id="demo1-html" spellcheck="false" janus-sync> <div class="live-coding__code">
<textarea name="html" cols="1" id="demo1-html" spellcheck="false" janus-sync>
<nav> <nav>
<a href="#">Home</a> <a href="#">Home</a>
<a href="#">Shop</a> <a href="#">Shop</a>
@ -71,10 +73,13 @@
</div> </div>
<footer>&copy; by us, forever. Neener neener.</footer> <footer>&copy; by us, forever. Neener neener.</footer>
</textarea> </textarea>
<div class="highlight"></div>
</div>
</div> </div>
<input type="radio" id="demo1-styles" name="demo1" checked janus-sync> <input type="radio" id="demo1-styles" name="demo1" checked janus-sync>
<div class="live-coding__component" style="--theme-color: #0070BA;"> <div class="live-coding__component" style="--theme-color: #0070BA;">
<label for="demo1-styles">CSS</label> <label for="demo1-styles">CSS</label>
<div class="live-coding__code">
<textarea name="css" cols="1" id="demo1-css" spellcheck="false" janus-sync>* { margin: 0; padding: 0; box-size: border-box; } <textarea name="css" cols="1" id="demo1-css" spellcheck="false" janus-sync>* { margin: 0; padding: 0; box-size: border-box; }
body { body {
display: flex; display: flex;
@ -122,12 +127,17 @@ section + section {
margin-top: -0.1em; margin-top: -0.1em;
} }
</textarea> </textarea>
<div class="highlight"></div>
</div>
</div> </div>
<input type="radio" id="demo1-script" name="demo1" janus-sync> <input type="radio" id="demo1-script" name="demo1" janus-sync>
<div class="live-coding__component" style="--theme-color: #F7DF1E;"> <div class="live-coding__component" style="--theme-color: #F7DF1E;">
<label for="demo1-script">JS</label> <label for="demo1-script">JS</label>
<div class="live-coding__code">
<textarea name="js" cols="1" id="demo1-js" spellcheck="false" janus-sync>// no JS needed <textarea name="js" cols="1" id="demo1-js" spellcheck="false" janus-sync>// no JS needed
</textarea> </textarea>
<div class="highlight"></div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -140,6 +150,7 @@ section + section {
</main> </main>
<script type="text/javascript" src="libs/openjs-shortcut/shortcut.js"></script> <script type="text/javascript" src="libs/openjs-shortcut/shortcut.js"></script>
<script type="text/javascript" src="libs/behave/behave.js"></script> <script type="text/javascript" src="libs/behave/behave.js"></script>
<script type="text/javascript" src="libs/highlight.js/highlight.min.js"></script>
<script type="text/javascript" src="scripts/app.js"></script> <script type="text/javascript" src="scripts/app.js"></script>
</body> </body>
</html> </html>

3
libs/highlight.js/highlight.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
.hljs{display:block;overflow-x:auto;padding:0.5em;background:#23241f}.hljs,.hljs-tag,.hljs-subst{color:#f8f8f2}.hljs-strong,.hljs-emphasis{color:#a8a8a2}.hljs-bullet,.hljs-quote,.hljs-number,.hljs-regexp,.hljs-literal,.hljs-link{color:#ae81ff}.hljs-code,.hljs-title,.hljs-section,.hljs-selector-class{color:#a6e22e}.hljs-strong{font-weight:bold}.hljs-emphasis{font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-name,.hljs-attr{color:#f92672}.hljs-symbol,.hljs-attribute{color:#66d9ef}.hljs-params,.hljs-class .hljs-title{color:#f8f8f2}.hljs-string,.hljs-type,.hljs-built_in,.hljs-builtin-name,.hljs-selector-id,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-addition,.hljs-variable,.hljs-template-variable{color:#e6db74}.hljs-comment,.hljs-deletion,.hljs-meta{color:#75715e}

View file

@ -1,5 +1,5 @@
/*jslint browser: true*/ /*jslint browser: true*/
/*global shortcut, Behave*/ /*global shortcut, Behave, hljs*/
(function () { (function () {
"use strict"; "use strict";
@ -116,10 +116,17 @@
} }
function editorListenerGenerator(editor) { function editorListenerGenerator(editor) {
var markupEl, styleEl, scriptEl, frameEl, frameWindow, listener; var frameWindow, listener,
markupEl = editor.querySelector("[name=\"html\"]"); textareas = [
styleEl = editor.querySelector("[name=\"css\"]"); editor.querySelector("[name=\"html\"]"),
scriptEl = editor.querySelector("[name=\"js\"]"); editor.querySelector("[name=\"css\"]"),
editor.querySelector("[name=\"js\"]")
],
highlights = [
editor.querySelector("[name=\"html\"] + .highlight"),
editor.querySelector("[name=\"css\"] + .highlight"),
editor.querySelector("[name=\"js\"] + .highlight")
],
frameEl = editor.querySelector("iframe"); frameEl = editor.querySelector("iframe");
if (frameEl.contentWindow) { if (frameEl.contentWindow) {
frameWindow = frameEl.contentWindow; frameWindow = frameEl.contentWindow;
@ -131,12 +138,15 @@
} }
} }
function editorAction() { function editorAction() {
var compiled = "<!DOCTYPE html><html><head><style>" + styleEl.value + "</style></head><body>" + markupEl.value + "<scr" + "ipt>" + scriptEl.value + "</scr" + "ipt></body></html>"; var compiled = "<!DOCTYPE html><html><head><style>" + textareas[1].value + "</style></head><body>" + textareas[0].value + "<scr" + "ipt>" + textareas[2].value + "</scr" + "ipt></body></html>";
frameWindow.document.open(); frameWindow.document.open();
frameWindow.document.write(compiled); frameWindow.document.write(compiled);
frameWindow.document.close(); frameWindow.document.close();
textareas.forEach(function (current, index, array) {
highlights[index].innerHTML = hljs.highlight(["html", "css", "js"][index], current.value + "\n", true).value;
});
} }
[markupEl, styleEl, scriptEl].forEach(function (current, index, array) { textareas.forEach(function (current, index, array) {
var syncFormElementsIndex = syncFormElements.indexOf(current), editor; var syncFormElementsIndex = syncFormElements.indexOf(current), editor;
editor = new Behave({ editor = new Behave({
textarea: current, textarea: current,
@ -151,8 +161,14 @@
}); });
// add a listener to build the source when the fields are changed // add a listener to build the source when the fields are changed
current.addEventListener('input', editorAction); current.addEventListener('input', editorAction);
if (syncFormElementsIndex >= 0) { current.addEventListener('keydown', editorAction);
// add a listener to sync the highlight element and the textarea
current.addEventListener('scroll', function (event) {
highlights[index].scrollTop = current.scrollTop;
highlights[index].scrollLeft = current.scrollLeft;
}, { passive: true });
// add a listener to receive changes from localStorage // add a listener to receive changes from localStorage
if (syncFormElementsIndex >= 0) {
localStorageActions["janus-input-" + syncFormElementsIndex] = function (event) { localStorageActions["janus-input-" + syncFormElementsIndex] = function (event) {
var storedValue = event.newValue, var storedValue = event.newValue,
decodedValue = storedValue.split("/", 2); decodedValue = storedValue.split("/", 2);

View file

@ -9,7 +9,7 @@
:root { :root {
--main-font: sans-serif; --main-font: sans-serif;
--monospace-font: monospace; --monospace-font: monospace;
--mouse-x: 100vw; --mouse-x: 0.5;
box-sizing: border-box; box-sizing: border-box;
font-family: var(--main-font); font-family: var(--main-font);
@ -59,7 +59,6 @@ textarea {
font-family: monospace; font-family: monospace;
font-family: var(--monospace-font, monospace); font-family: var(--monospace-font, monospace);
font-size: 0.5em; font-size: 0.5em;
height: 100%;
} }
h1 { h1 {
@ -253,20 +252,43 @@ section {
flex: 1 1 100%; flex: 1 1 100%;
} }
.live-coding textarea { .live-coding__code {
font-size: 0.5em; position: relative;
resize: none; width: 100%;
flex: 1 1 auto;
color: white;
background: #333;
border: none;
padding: 0.1em;
outline: none;
} }
.live-coding textarea::selection { .live-coding__code textarea, .live-coding__code .highlight {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 0.1em;
font-size: 0.4em;
resize: none;
color: white;
font-family: monospace;
white-space: pre-wrap;
word-wrap: break-word;
overflow: auto;
border: none;
outline: none;
text-align: left;
line-height: 1.1;
}
.live-coding__code textarea {
background: #333;
-webkit-text-stroke: 2px #333;
}
.live-coding__code .highlight {
pointer-events: none;
}
.live-coding__code textarea::selection {
background-color: black; background-color: black;
color: var(--theme-color, white); color: transparent;
} }
.live-coding__component { .live-coding__component {
@ -286,8 +308,8 @@ section {
.hidden, .hidden,
.live-coding input[type="radio"], .live-coding input[type="radio"],
.live-coding input[type="checkbox"], .live-coding input[type="checkbox"],
.live-coding input[type="radio"]:not(:checked) + .live-coding__component > textarea, .live-coding input[type="radio"]:not(:checked) + .live-coding__component > .live-coding__code,
.live-coding input[type="checkbox"]:not(:checked) + .live-coding__component > textarea { .live-coding input[type="checkbox"]:not(:checked) + .live-coding__component > .live-coding__code {
position: fixed; position: fixed;
visibility: hidden; visibility: hidden;
right: 110vw; right: 110vw;