mirror of
https://github.com/seigler/janus
synced 2025-07-26 01:06:11 +00:00
feat: added code highlighting
This commit is contained in:
parent
8a850aab22
commit
faafc32d03
5 changed files with 79 additions and 26 deletions
15
index.html
15
index.html
|
@ -3,6 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<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">
|
||||
<script type="text/javascript" src="libs/prefixfree/prefixfree.min.js"></script>
|
||||
</head>
|
||||
|
@ -44,7 +45,7 @@
|
|||
</blockquote>
|
||||
</section>
|
||||
|
||||
<section id="demo1" style="--mouse-x: 0.5">
|
||||
<section id="demo1">
|
||||
<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;">
|
||||
<iframe src="about:blank" frameborder="0"></iframe>
|
||||
|
@ -53,7 +54,8 @@
|
|||
<input type="radio" id="demo1-markup" name="demo1" janus-sync>
|
||||
<div class="live-coding__component" style="--theme-color: #E34F26;">
|
||||
<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>
|
||||
<a href="#">Home</a>
|
||||
<a href="#">Shop</a>
|
||||
|
@ -71,10 +73,13 @@
|
|||
</div>
|
||||
<footer>© by us, forever. Neener neener.</footer>
|
||||
</textarea>
|
||||
<div class="highlight"></div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="radio" id="demo1-styles" name="demo1" checked janus-sync>
|
||||
<div class="live-coding__component" style="--theme-color: #0070BA;">
|
||||
<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; }
|
||||
body {
|
||||
display: flex;
|
||||
|
@ -122,12 +127,17 @@ section + section {
|
|||
margin-top: -0.1em;
|
||||
}
|
||||
</textarea>
|
||||
<div class="highlight"></div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="radio" id="demo1-script" name="demo1" janus-sync>
|
||||
<div class="live-coding__component" style="--theme-color: #F7DF1E;">
|
||||
<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>
|
||||
<div class="highlight"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -140,6 +150,7 @@ section + section {
|
|||
</main>
|
||||
<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/highlight.js/highlight.min.js"></script>
|
||||
<script type="text/javascript" src="scripts/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
3
libs/highlight.js/highlight.min.js
vendored
Normal file
3
libs/highlight.js/highlight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
libs/highlight.js/monokai-sublime.css
Normal file
1
libs/highlight.js/monokai-sublime.css
Normal 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}
|
|
@ -1,5 +1,5 @@
|
|||
/*jslint browser: true*/
|
||||
/*global shortcut, Behave*/
|
||||
/*global shortcut, Behave, hljs*/
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
@ -116,11 +116,18 @@
|
|||
}
|
||||
|
||||
function editorListenerGenerator(editor) {
|
||||
var markupEl, styleEl, scriptEl, frameEl, frameWindow, listener;
|
||||
markupEl = editor.querySelector("[name=\"html\"]");
|
||||
styleEl = editor.querySelector("[name=\"css\"]");
|
||||
scriptEl = editor.querySelector("[name=\"js\"]");
|
||||
frameEl = editor.querySelector("iframe");
|
||||
var frameWindow, listener,
|
||||
textareas = [
|
||||
editor.querySelector("[name=\"html\"]"),
|
||||
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");
|
||||
if (frameEl.contentWindow) {
|
||||
frameWindow = frameEl.contentWindow;
|
||||
} else {
|
||||
|
@ -131,12 +138,15 @@
|
|||
}
|
||||
}
|
||||
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.write(compiled);
|
||||
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;
|
||||
editor = new Behave({
|
||||
textarea: current,
|
||||
|
@ -151,8 +161,14 @@
|
|||
});
|
||||
// add a listener to build the source when the fields are changed
|
||||
current.addEventListener('input', editorAction);
|
||||
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
|
||||
if (syncFormElementsIndex >= 0) {
|
||||
// add a listener to receive changes from localStorage
|
||||
localStorageActions["janus-input-" + syncFormElementsIndex] = function (event) {
|
||||
var storedValue = event.newValue,
|
||||
decodedValue = storedValue.split("/", 2);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
:root {
|
||||
--main-font: sans-serif;
|
||||
--monospace-font: monospace;
|
||||
--mouse-x: 100vw;
|
||||
--mouse-x: 0.5;
|
||||
|
||||
box-sizing: border-box;
|
||||
font-family: var(--main-font);
|
||||
|
@ -59,7 +59,6 @@ textarea {
|
|||
font-family: monospace;
|
||||
font-family: var(--monospace-font, monospace);
|
||||
font-size: 0.5em;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
@ -253,20 +252,43 @@ section {
|
|||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
.live-coding textarea {
|
||||
font-size: 0.5em;
|
||||
resize: none;
|
||||
flex: 1 1 auto;
|
||||
color: white;
|
||||
background: #333;
|
||||
border: none;
|
||||
padding: 0.1em;
|
||||
outline: none;
|
||||
.live-coding__code {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.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;
|
||||
color: var(--theme-color, white);
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.live-coding__component {
|
||||
|
@ -286,8 +308,8 @@ section {
|
|||
.hidden,
|
||||
.live-coding input[type="radio"],
|
||||
.live-coding input[type="checkbox"],
|
||||
.live-coding input[type="radio"]:not(:checked) + .live-coding__component > textarea,
|
||||
.live-coding input[type="checkbox"]: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 > .live-coding__code {
|
||||
position: fixed;
|
||||
visibility: hidden;
|
||||
right: 110vw;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue